osg+pbr-直接光

このアルゴリズムは、opengl pbr の学習の関連部分から取得されており、
osg に移植する方法のみを考慮しています。

1. ローカル座標系からワールド座標系への法線の変化(逆転置行列)
2. ロボットが視点を取得する
3. 視点統一ポインタがロボットに渡され、ロボット内で変更される

正確さを示すために、まず視点を原点に設定し、右矢印キーを押すと正常になります。

ここに画像の説明を挿入
半分が原点を向いているのが正しいことがわかります。

修正後、
ここに画像の説明を挿入

代償如下:
travel.h
#pragma Once
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osgGA/GUIEventAdapter>
#include <osgViewer/ViewerEventHandlers>
#include <osg/AnimationPath>
#include
#include <osg /PositionAttitudeTransform>
#include <osg/MatrixTransform>
#include <osgGA/CameraManipulator>
#include <osg/matrixd>
class TravelManipulator : public osgGA::CameraManipulator
{ public: TravelManipulator();

public:
//現在のビューポートを設定します
virtual void setByMatrix(const osg::Matrixd& matrix);
virtual void setByInverseMatrix(const osg::Matrixd& matrix);
//現在の行列と逆行列を取得します
virtual osg::Matrixd getMatrix() const;
virtual osg::Matrixd getInverseMatrix() const;

virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us);
void ChangePosition(osg::Vec3d& delta);

private:
//視点
osg::Vec3 m_vPosition;
//
osg::Vec3 に向かって m_vRotation;
//移動ステップ
int m_vStep;
//回転ステップ
float m_vRotateSpeed;

//暂停
bool _bPause;

public:
//目の位置をシェーダに設定
void setEyePosUniform(osg::ref_ptrosg::Uniform camaraPosUniform);
//
osg::ref_ptrosg::Uniform _eyePosUniform;
};
travel.cpp
#include “Travel.h”

TravelManipulator::TravelManipulator()
{ m_vPosition = osg::Vec3(0, 0, 50); m_vRotation = osg::Vec3(osg::PI_2, 0, 0); m_vステップ = 1.0; m_vRotateSpeed = 1.0; _b一時停止 = false; _eyePosUniform = NULL; }






void TravelManipulator::setByMatrix(const osg::Matrixd & 行列)
{ }

void TravelManipulator::setByInverseMatrix(const osg::Matrixd & 行列)
{ }

osg::Matrixd TravelManipulator::getMatrix() const
{ osg::Matrixd matTrans; matTrans.makeTranslate(m_vPosition); osg::Matrixd matRotate; matRotate.makeRotate(m_vRotation[0], osg::X_AXIS, m_vRotation[1], osg::Y_AXIS, m_vRotation[2], osg::Z_AXIS); matRotate * matTrans を返します。}





osg::Matrixd TravelManipulator::getInverseMatrix() const
{ osg::Matrixd mat = getMatrix(); 戻り osg::Matrixd::inverse(mat); }


bool TravelManipulator::handle(const osgGA::GUIEventAdapter & ea, osgGA::GUIActionAdapter & us)
{ switch (ea.getEventType()) { case osgGA::GUIEventAdapter::KEYDOWN: { //if (ea.getKey() =='p') //{ // _bPause = !_bPause; //} //if (_bPause) { if ((ea.getKey() == 'w') || (ea.getKey() == 'W') ) { ChangePosition(osg::Vec3d(m_vStep * cosf) (osg::PI_2 + m_vRotation._v[2]), m_vStep * sinf(osg::PI_2 + m_vRotation._v[2]), 0)); true を返します。else if ((ea.getKey() == 's') || (ea.getKey() == 'S')) {

















ChangePosition(osg::Vec3d(-m_vStep * cosf(osg::PI_2 + m_vRotation._v[2]), -m_vStep * sinf(osg::PI_2 + m_vRotation._v[2]), 0));
true を返します。
}
else if ((ea.getKey() == 'a') || (ea.getKey() == 'A') )
{ ChangePosition(osg::Vec3d(m_vStep * sinf(osg::PI_2 + m_vRotation. _v[2]), -m_vStep * cosf(osg::PI_2 + m_vRotation._v[2]), 0)); true を返します。} else if ((ea.getKey() == 'd') || (ea.getKey() == 'D') ) { ChangePosition(osg::Vec3d(-m_vStep * sinf(osg::PI_2 + m_vRotation) ._v[2]), m_vStep * cosf(osg::PI_2 + m_vRotation._v[2]), 0)); true を返します。} else if ((ea.getKey() == 'Q') || (ea.getKey() == 'q')) { ChangePosition(osg::Vec3d(0, 0, 0.2));











true を返します。
else
if ((ea.getKey() == 'E') || (ea.getKey() == 'e'))
{

			ChangePosition(osg::Vec3d(0, 0, -0.2));
			return true;
		}
		else if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Up)
		{
			m_vRotation[0] += 0.2;
			if (_eyePosUniform)
			{
				//_eyePosUniform->set(m_vPosition);
			}
			return true;
		}
		else if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Down)
		{

			m_vRotation[0] -= 0.2;
			if (_eyePosUniform)
			{
				//_eyePosUniform->set(m_vPosition);
			}
			return true;
		}
		else if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Left)
		{
			m_vRotation[2] += 0.2;
			if (_eyePosUniform)
			{
				//_eyePosUniform->set(m_vPosition);
			}
			return true;
		}
		else if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Right)
		{

			m_vRotation[2] -= 0.2;
			if (_eyePosUniform)
			{
				_eyePosUniform->set(m_vPosition);
			}
			return true;
		}
	}
}
break;
case osgGA::GUIEventAdapter::FRAME:
{
	//if (!_bPause)
	//{
	//	//m_vPosition[2] += 1;
	//}
}
	break;
default:
	break;
}
return false;

}

void TravelManipulator::ChangePosition(osg::Vec3d & delta)
{ m_vPosition += delta; } void TravelManipulator::setEyePosUniform(osg::ref_ptrosg::Uniform CameraPosUniform) { _eyePosUniform = camaraPosUniform; } main.cpp //Liblas を介して読み取ります。 las ファイルを作成し、osg で表示し、シェーダーを使用します。最初にフラグメント シェーダーで緑の使用を指定します#include <liblas/liblas.hpp> #include #include










#include <osgDB/読み取りファイル>
#include <osgDB/書き込みファイル>
#include <osgUtil/オプティマイザー>
#include <osg/座標システムノード>

#include <osg/スイッチ>
#include <osg/タイプ>
#include <osgText/テキスト>

#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>

#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator
> #include <osgGA/DriveManipulator
> #include <osgGA/KeySwitchMatrixManipulator> #include
<osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TerrainManipulator>
# <osgGA/SphericalManipulator> を含める

#include <osgGA/デバイス>

#include
#include <osg/Shader>
#include <osg/BlendFunc>
#include <osg/blendColor>
#include <osg/Point>
#include <osg/Shapedrawable>
#include <osgUtil/SmoothingVisitor>
#include “Travel.h” 」

static const char * vertexShader_PBR =
{ "in vec3 aPos; \n" "vec3 aNormal; \n" "さまざまな vec3 WorldPos; \n" "さまざまな vec3 通常。\n" "uniform mat4 NormalMatrix; \n" "void main() \n" " { \n" " WorldPos = aPos; \n" " Normal = vec3(normalMatrix * vec4(aNormal,1.0)); \n" " gl_Position = ftransform(); \ n" "}\n" };











static const char psShader_PBR =
{ “#バージョン 330 コア \n” “out vec4 FragColor; \n" "さまざまな vec3 WorldPos; \n" "さまざまな vec3 通常。\n" "均一な vec3 アルベド; \n" "均一なフロート メタリック; \n" "均一なフロート粗さ; \n" "均一なフロート青; \n" "uniform vec3 lightPositions[4]; \n" "uniform vec3 lightColors[4]; \n" "均一な vec3 camPos; \n" "const float PI = 3.14159265359; \n" "float DistributionGGX(vec3 N, vec3 H, float 粗さ) \n" " { \n" " float a = 粗さ














粗さ; \n"
" float a2 = a a; \n"
" float NdotH = max(ドット(N, H), 0.0); \n"
0);
\n" " float NdotL = max(dot(N, L), 0.0); \n"

















0); \n" " for (int i = 0; i < 4; ++i) \n" " { \n" " vec3 L = Normalize(lightPositions[i] - WorldPos); \n" " vec3 H = 正規化(V + L); \n"


















0 - メタリック。\n" " float NdotL = max(dot(N, L), 0.0); \n"












" Lo += (kD * アルベド / PI + スペキュラー) * 放射輝度 * NdotL; \n" " } \
n"
" vec3 アンビエント = vec3(0.03) * アルベド * ao; \n" "
vec3 カラー = アンビエント + Lo; \n"
" color = color / (color + vec3(1.0)); \n" "
color = pow(color, vec3(1.0 / 2.2)); \n" "
FragColor = vec4(color, 1.0); \n "
//" FragColor = vec4(1.0,0.0,0.0, 1.0); \n"
"} \n"
};

osg::ref_ptrosg::Geode CreateSphereGeode()
{ osg::ref_ptrosg::Geode geode = new osg::Geode; osg::ref_ptrosg::Vec3Array 頂点 = 新しい osg::Vec3Array(6); (*頂点)[0].set(0.0f, 0.0f, 1.0f); (*頂点)[1].set(-0.5f, -0.5f, 0.0f); (*頂点)[2].set(0.5f, -0.5f, 0.0f); (*頂点)[3].set(0.5f, 0.5f, 0.0f); (*頂点)[4].set(-0.5f, 0.5f, 0.0f); (*頂点)[5].set(0.0f, 0.0f, -1.0f); osg::ref_ptrosg::DrawElementsUInt インデックス = 新しい osg::DrawElementsUInt(GL_TRIANGLES, 24); (*インデックス)[0] = 0; (*インデックス)[1] = 1; (*インデックス)[2] = 2; (*インデックス)[3] = 0; (*インデックス)[4] = 2; (*インデックス)[5] = 3; (*インデックス)[6] = 0; (*インデックス)[7] = 3; (*インデックス)[8] = 4;












(*インデックス)[9] = 0; (*インデックス)[10] = 4; (*インデックス)[11] = 1;
(*インデックス)[12] = 5; (*インデックス)[13] = 2; (*インデックス)[14] = 1;
(*インデックス)[15] = 5; (*インデックス)[16] = 3; (*インデックス)[17] = 2;
(*インデックス)[18] = 5; (*インデックス)[19] = 4; (*インデックス)[20] = 3;
(*インデックス)[21] = 5; (*インデックス)[22] = 1; (*インデックス)[23] = 4;
osg::ref_ptrosg::ジオメトリ geom = 新しい osg::ジオメトリ;
geom->setVertexArray(vertices.get());
geom->addPrimitiveSet(indices.get());
osgUtil::SmoothingVisitor::smooth(*geom);
geode->addDrawable(geom);
ジオードを返します。

}

osg::ref_ptrosg::Geode renderSphere(osg::Vec3f pos)
{ osg::ref_ptrosg::Geode geode = new osg::Geode; const unsigned int X_SEGMENTS = 64; const unsigned int Y_SEGMENTS = 64; const float PI = 3.14159265359f; osg::ref_ptrosg::Vec3Array 頂点 = 新しい osg::Vec3Array; osg::ref_ptrosg::Vec3ArraynormalArray = 新しい osg::Vec3Array; for (unsigned int x = 0; x <= X_SEGMENTS; ++x) { for (unsigned int y = 0; y <= Y_SEGMENTS; ++y) { float xSegment = (float)x / (float)X_SEGMENTS; float ySegment = (float)y / (float)Y_SEGMENTS; float xPos = std::cos(xSegment * 2.0f * PI) * std::sin(ySegment * PI); float yPos = std::cos(ySegment * PI);














float zPos = std::sin(xSegment * 2.0f * PI) * std::sin(ySegment * PI);

		vertices->push_back(osg::Vec3(xPos, yPos, zPos) + pos);
		normalArray->push_back(osg::Vec3(xPos, yPos, zPos));
	}
}
osg::ref_ptr<osg::DrawElementsUInt> indices = new osg::DrawElementsUInt();
bool oddRow = false;
for (unsigned int y = 0; y < Y_SEGMENTS; ++y)
{
	if (!oddRow) // even rows: y == 0, y == 2; and so on
	{
		for (unsigned int x = 0; x <= X_SEGMENTS; ++x)
		{
			indices->push_back(y       * (X_SEGMENTS + 1) + x);
			indices->push_back((y + 1) * (X_SEGMENTS + 1) + x);
		}
	}
	else
	{
		for (int x = X_SEGMENTS; x >= 0; --x)
		{
			indices->push_back((y + 1) * (X_SEGMENTS + 1) + x);
			indices->push_back(y       * (X_SEGMENTS + 1) + x);
		}
	}
	oddRow = !oddRow;
}
int indexCount = static_cast<unsigned int>(indices->size());
indices->setMode(GL_TRIANGLE_STRIP);

osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
geom->setVertexArray(vertices.get());
geom->addPrimitiveSet(indices.get());
geom->setNormalArray(normalArray, osg::Array::BIND_PER_VERTEX);

geom->setVertexAttribArray(1, vertices, osg::Array::BIND_PER_VERTEX);
geom->setVertexAttribArray(2, normalArray, osg::Array::BIND_PER_VERTEX);

//osgUtil::SmoothingVisitor::smooth(*geom);
geode->addDrawable(geom);
return geode;

}

int main()
{

osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
osg::ref_ptr<TravelManipulator> manipulator = new TravelManipulator;
viewer->setCameraManipulator(manipulator);

osg::ref_ptr<osg::Uniform> camPosUniform = new osg::Uniform("camPos", osg::Vec3f(0,0,0));
manipulator->setEyePosUniform(camPosUniform);

osg::ref_ptr<osg::Camera> camera = viewer->getCamera();
osg::Matrix viewMatrix = camera->getViewMatrix();
osg::Matrix projMatrix = camera->getProjectionMatrix();
osg::Vec3f eye, center, up;
camera->getViewMatrixAsLookAt(eye, center, up);

//osg::ref_ptr<osg::Uniform> camPosUniform = new osg::Uniform("camPos", eye);
osg::ref_ptr<osg::Uniform> viewMatrixUniform = new osg::Uniform("view", viewMatrix);
osg::ref_ptr<osg::Uniform> projMatrixUniform = new osg::Uniform("projection", projMatrix);
osg::ref_ptr<osg::Group> grp = new osg::Group;
osg::Vec3f albedo(0.5f, 0.0f, 0.0f);
osg::ref_ptr<osg::Uniform> albedoUniform = new osg::Uniform("albedo", albedo);
float ao = 1.0f;
osg::ref_ptr<osg::Uniform> aoUniform = new osg::Uniform("ao", ao);

int nrRows = 7;
int nrColumns = 7;
float spacing = 2.5;
float ballRadius = 1.0f;

osg::ref_ptr<osg::Vec3Array> lightColors = new osg::Vec3Array;
lightColors->push_back(osg::Vec3(300.0f, 300.0f, 300.0f));
lightColors->push_back(osg::Vec3(300.0f, 300.0f, 300.0f));
lightColors->push_back(osg::Vec3(300.0f, 300.0f, 300.0f));
lightColors->push_back(osg::Vec3(300.0f, 300.0f, 300.0f));

osg::ref_ptr<osg::Uniform> lightColorsUniform = new osg::Uniform(osg::Uniform::FLOAT_VEC3, "lightColors", lightColors->size());
for (int i = 0; i < lightColors->size(); i++)
{
	lightColorsUniform->setElement(i, lightColors->at(i));
}
osg::ref_ptr<osg::Vec3Array> lightPositions = new osg::Vec3Array;
lightPositions->push_back(osg::Vec3(-10.0f, 10.0f, 10.0f));
lightPositions->push_back(osg::Vec3(10.0f, 10.0f, 10.0f));
lightPositions->push_back(osg::Vec3(-10.0f, -10.0f, 10.0f));
lightPositions->push_back(osg::Vec3(10.0f, -10.0f, 10.0f));

osg::ref_ptr<osg::Uniform> lightPositionsUniform = new osg::Uniform(osg::Uniform::FLOAT_VEC3, "lightPositions", lightPositions->size());
for (int i = 0; i < lightPositions->size(); i++)
{
	lightPositionsUniform->setElement(i, lightPositions->at(i));
}
for (int row = 0; row < nrRows; row++)
{
	float metallic = row * 1.0 / nrRows;
	for (int col = 0; col < nrColumns; col++)
	{
		float roughness = col * 1.0 / nrColumns;
		if (roughness <0.05)
		{
			roughness = 0.05;
		}
		if (roughness > 1.0)
		{
			roughness = 1.0;
		}
		osg::Vec3 ballCenter(
			(col - (nrColumns / 2)) * spacing,
			(row - (nrRows / 2)) * spacing,
			0.0f);
		osg::Matrix worldMatrix = osg::Matrix::translate(ballCenter);

		osg::Matrix inverse;
		inverse.invert(worldMatrix);
		osg::Matrix transPose;
		transPose.transpose(inverse);
		osg::ref_ptr<osg::Geode> geode = renderSphere(ballCenter);
		{
			osg::ref_ptr<osg::StateSet> stateset = geode->getOrCreateStateSet();
			osg::ref_ptr<osg::Shader> vs = new osg::Shader(osg::Shader::VERTEX, vertexShader_PBR);
			osg::ref_ptr<osg::Shader> ps = new osg::Shader(osg::Shader::FRAGMENT, psShader_PBR);
			osg::ref_ptr<osg::Program> program = new osg::Program;
			program->addBindAttribLocation("aPos", 1);
			program->addBindAttribLocation("aNormal", 2);
			program->addShader(vs);
			program->addShader(ps);

			osg::ref_ptr<osg::Uniform> metallicUniform = new osg::Uniform("metallic", metallic);
			osg::ref_ptr<osg::Uniform> roughnessUniform = new osg::Uniform("roughness", roughness);
			//osg::ref_ptr<osg::Uniform> transposeInverseMatrixUniform = new osg::Uniform("normalMatrix", transPose);

			osg::Uniform* transposeInverseMatrixUniform = stateset->getOrCreateUniform("normalMatrix", osg::Uniform::FLOAT_MAT4);
			transposeInverseMatrixUniform->set(transPose);
			stateset->addUniform(albedoUniform);
			stateset->addUniform(metallicUniform);
			stateset->addUniform(roughnessUniform);
			stateset->addUniform(aoUniform);
			stateset->addUniform(lightPositionsUniform);
			stateset->addUniform(lightColorsUniform);
			stateset->addUniform(transposeInverseMatrixUniform);
			stateset->addUniform(viewMatrixUniform);
			stateset->addUniform(projMatrixUniform);
			stateset->addUniform(camPosUniform);
			stateset->setAttribute(program, osg::StateAttribute::ON);
		}
		grp->addChild(geode);
	}

}
grp->addChild(renderSphere(osg::Vec3(-10.0f, 10.0f, 10.0f)));
grp->addChild(renderSphere(osg::Vec3(10.0f, 10.0f, 10.0f)));
grp->addChild(renderSphere(osg::Vec3(-10.0f, -10.0f, 10.0f)));
grp->addChild(renderSphere(osg::Vec3(10.0f, -10.0f, 10.0f)));

viewer->getCamera()->setClearColor(osg::Vec4(0.1f, 0.1f, 0.1f, 1.0f));
viewer->setSceneData(grp);
viewer->run();

return 0;

}

おすすめ

転載: blog.csdn.net/directx3d_beginner/article/details/131430221
おすすめ