[osg-users] Normal Mapping using Dynamic Cubemap

Sebastian Messerschmidt sebastian.messerschmidt at gmx.de
Wed Dec 27 03:50:27 PST 2017


Hi Rômulo,

I already tried to describe the building-blocks for the way:

1. Render to FBO with MRT (see osgmultiplerendertargets example for 
this). The MRT/FBO-attachments should be your color, normal and depth.
You'll need to use a shader that writes the correct information to the 
correct buffers. That's all in the example. Basically that's deferred 
rendering's approach. An example by Michael Kapelko can be found here: [0].

2. Once you understand how to render to one FBO you can use your 
approach to render to the individual faces of your cubemap.

You need to learn the basics. Pasting source code might not attract a 
lot of attention, so please try to follow my hints before asking the 
question over and over.


[0] 
https://bitbucket.org/kornerr/osg-deferred-shading/src/5b8555059707?at=default


Cheers
Sebastian



Am 26.12.2017 um 18:17 schrieb Rômulo Cerqueira:
> Hi Roberto and Sebastian,
> 
> sorry for my duplicated post. I need to render the depth/normal surface to texture of reflected objects by cube maps.
> 
> Until this moment, I got the depth data. Could you help me to get the normal data too (as single channel data). My current code follows below:
> 
> C++ code:
> 
> Code:
> 
> // OSG includes
> #include <osgViewer/Viewer>
> #include <osg/Texture>
> #include <osg/TexGen>
> #include <osg/Geode>
> #include <osg/ShapeDrawable>
> #include <osg/TextureCubeMap>
> #include <osg/TexMat>
> #include <osg/MatrixTransform>
> #include <osg/PositionAttitudeTransform>
> #include <osg/Camera>
> #include <osg/TexGenNode>
> #include <osgDB/FileUtils>
> 
> // C++ includes
> #include <iostream>
> 
> #define SHADER_PATH_FRAG "normal_depth_map/shaders/normalDepthMap.frag"
> #define SHADER_PATH_VERT "normal_depth_map/shaders/normalDepthMap.vert"
> 
> #define BOOST_TEST_MODULE "DynamicCubeMap_test"
> 
> using namespace osg;
> 
> unsigned int numTextures = 6;
> 
> enum TextureUnitTypes {
>      TEXTURE_UNIT_DIFFUSE,
>      TEXTURE_UNIT_NORMAL,
>      TEXTURE_UNIT_CUBEMAP
> };
> 
> osg::ref_ptr<osg::Group> _create_scene() {
>      osg::ref_ptr<osg::Group> scene = new osg::Group;
> 
>      osg::ref_ptr<osg::Geode> geode = new osg::Geode;
>      scene->addChild(geode.get());
> 
>      const float radius = 0.8f;
>      const float height = 1.0f;
>      osg::ref_ptr<osg::ShapeDrawable> shape;
> 
>      // sphere
>      shape = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(-3.0f, 0.0f, 0.0f), radius));
>      shape->setColor(osg::Vec4(0.6f, 0.8f, 0.8f, 1.0f));
>      geode->addDrawable(shape.get());
> 
>      // box
>      shape = new osg::ShapeDrawable(new osg::Box(osg::Vec3(3.0f, 0.0f, 0.0f), 2 * radius));
>      shape->setColor(osg::Vec4(0.4f, 0.9f, 0.3f, 1.0f));
>      geode->addDrawable(shape.get());
> 
>      // cone
>      shape = new osg::ShapeDrawable(new osg::Cylinder(osg::Vec3(0.0f, 0.0f, -3.0f), radius, height));
>      shape->setColor(osg::Vec4(1.0f, 0.3f, 0.3f, 1.0f));
>      geode->addDrawable(shape.get());
> 
>      // cylinder
>      shape = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0f, 0.0f, 3.0f), 2* radius));
>      shape->setColor(osg::Vec4(0.8f, 0.8f, 0.4f, 1.0f));
>      geode->addDrawable(shape.get());
> 
>      return scene;
> }
> 
> osg::NodePath createReflector() {
>      Geode* node = new Geode;
>      const float radius = 0.8f;
>      ref_ptr<TessellationHints> hints = new TessellationHints;
>      hints->setDetailRatio(2.0f);
>      ShapeDrawable* shape = new ShapeDrawable(new Sphere(Vec3(0.0f, 0.0f, 0.0f), radius * 1.5f), hints.get());
>      shape->setColor(Vec4(0.8f, 0.8f, 0.8f, 1.0f));
>      node->addDrawable(shape);
> 
>      osg::NodePath nodeList;
>      nodeList.push_back(node);
> 
>      return nodeList;
> }
> 
> class UpdateCameraAndTexGenCallback : public osg::NodeCallback
> {
>      public:
> 
>          typedef std::vector< osg::ref_ptr<osg::Camera> >  CameraList;
> 
>          UpdateCameraAndTexGenCallback(osg::NodePath& reflectorNodePath, CameraList& Cameras):
>              _reflectorNodePath(reflectorNodePath),
>              _Cameras(Cameras)
>          {
>          }
> 
>          virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
>          {
>              // first update subgraph to make sure objects are all moved into position
>              traverse(node,nv);
> 
>              // compute the position of the center of the reflector subgraph
>              osg::Matrixd worldToLocal = osg::computeWorldToLocal(_reflectorNodePath);
>              osg::BoundingSphere bs = _reflectorNodePath.back()->getBound();
>              osg::Vec3 position = bs.center();
> 
>              typedef std::pair<osg::Vec3, osg::Vec3> ImageData;
>              const ImageData id[] =
>              {
>                  ImageData( osg::Vec3( 1,  0,  0), osg::Vec3( 0, -1,  0) ), // +X
>                  ImageData( osg::Vec3(-1,  0,  0), osg::Vec3( 0, -1,  0) ), // -X
>                  ImageData( osg::Vec3( 0,  1,  0), osg::Vec3( 0,  0,  1) ), // +Y
>                  ImageData( osg::Vec3( 0, -1,  0), osg::Vec3( 0,  0, -1) ), // -Y
>                  ImageData( osg::Vec3( 0,  0,  1), osg::Vec3( 0, -1,  0) ), // +Z
>                  ImageData( osg::Vec3( 0,  0, -1), osg::Vec3( 0, -1,  0) )  // -Z
>              };
> 
>              for(unsigned int i = 0; i < 6 && i < _Cameras.size(); ++i) {
>                  osg::Matrix localOffset;
>                  localOffset.makeLookAt(position,position+id[i].first,id[i].second);
> 
>                  osg::Matrix viewMatrix = worldToLocal*localOffset;
> 
>                  _Cameras[i]->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
>                  _Cameras[i]->setProjectionMatrixAsFrustum(-1.0,1.0,-1.0,1.0,1.0,10000.0);
>                  _Cameras[i]->setViewMatrix(viewMatrix);
>              }
>          }
> 
>      protected:
> 
>          virtual ~UpdateCameraAndTexGenCallback() {}
> 
>          osg::NodePath               _reflectorNodePath;
>          CameraList                  _Cameras;
> };
> 
> class TexMatCullCallback : public osg::NodeCallback
> {
>      public:
> 
>          TexMatCullCallback(osg::TexMat* texmat):
>              _texmat(texmat)
>          {
>          }
> 
>          virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
>          {
>              // first update subgraph to make sure objects are all moved into position
>              traverse(node,nv);
> 
>              osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
>              if (cv)
>              {
> 				osg::Quat q = osg::Matrix::inverse(*cv->getModelViewMatrix()).getRotate();
> 
> 
> 				float yaw2 = asin(-2.0f*(q.x()*q.z() - q.w()*q.y()));
> 				osg::Matrixd mxY;
> 				mxY.makeRotate(yaw2,osg::Vec3(0,0,1));
> 
> 				osg::Matrixd mx = mxY;
>                  _texmat->setMatrix(mx);
>              }
>          }
> 
>      protected:
> 
>          osg::ref_ptr<TexMat>    _texmat;
> };
> 
> class UpdateCameraPosUniformCallback : public osg::Uniform::Callback
> {
> public:
> 	UpdateCameraPosUniformCallback(osg::Camera* camera)
> 		: mCamera(camera)
> 	{
> 	}
> 
> 	virtual void operator () (osg::Uniform* u, osg::NodeVisitor*)
> 	{
> 		osg::Vec3 eye;
> 		osg::Vec3 center;
> 		osg::Vec3 up;
> 		mCamera->getViewMatrixAsLookAt(eye,center,up);
> 
> 		u->set(eye);
> 	}
> protected:
> 	osg::Camera* mCamera;
> };
> 
> osg::Group* createShadowedScene(osg::Node* reflectedSubgraph, osg::NodePath reflectorNodePath, unsigned int unit, const osg::Vec4& clearColor, unsigned tex_width, unsigned tex_height, osg::Camera::RenderTargetImplementation renderImplementation, osg::Camera* camera = 0) {
>      osg::Group* group = new osg::Group;
> 
>      osg::TextureCubeMap* texture = new osg::TextureCubeMap;
>      texture->setTextureSize(tex_width, tex_height);
>      texture->setInternalFormat(GL_DEPTH_COMPONENT);
>      texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
>      texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
>      texture->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE);
>      texture->setFilter(osg::TextureCubeMap::MIN_FILTER,osg::TextureCubeMap::LINEAR);
>      texture->setFilter(osg::TextureCubeMap::MAG_FILTER,osg::TextureCubeMap::LINEAR);
> 
>      // set up the render to texture cameras.
>      UpdateCameraAndTexGenCallback::CameraList Cameras;
>      for(unsigned int i = 0; i < 6; ++i) {
>          // create the camera
>          osg::Camera* camera = new osg::Camera;
> 
>          camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
>          camera->setClearColor(clearColor);
> 
>          // set viewport
>          camera->setViewport(0,0,tex_width,tex_height);
> 
>          // set the camera to render before the main camera.
>          camera->setRenderOrder(osg::Camera::PRE_RENDER);
> 
>          // tell the camera to use OpenGL frame buffer object where supported.
>          camera->setRenderTargetImplementation(renderImplementation);
> 
>          // attach the texture and use it as the color buffer.
>          camera->attach(osg::Camera::DEPTH_BUFFER, texture, 0, i);
> 
>          // add subgraph to render
>          camera->addChild(reflectedSubgraph);
> 
>          group->addChild(camera);
> 
>          Cameras.push_back(camera);
>      }
> 
>      // create the texgen node to project the tex coords onto the subgraph
>      osg::TexGenNode* texgenNode = new osg::TexGenNode;
>      texgenNode->getTexGen()->setMode(osg::TexGen::REFLECTION_MAP);
>      texgenNode->setTextureUnit(unit);
>      group->addChild(texgenNode);
> 
>      // set the reflected subgraph so that it uses the texture and tex gen settings.
> 	osg::Node* reflectorNode = reflectorNodePath.front();
>      {
> 
>          group->addChild(reflectorNode);
> 
>          osg::StateSet* stateset = reflectorNode->getOrCreateStateSet();
> 		stateset->setTextureAttributeAndModes(unit,texture,osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
>          stateset->setTextureMode(unit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
>          stateset->setTextureMode(unit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
>          stateset->setTextureMode(unit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
>          stateset->setTextureMode(unit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
> 
>          osg::TexMat* texmat = new osg::TexMat;
>          stateset->setTextureAttributeAndModes(unit,texmat,osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
> 
>          reflectorNode->setCullCallback(new TexMatCullCallback(texmat));
>      }
> 
> 	osg::StateSet* ss = reflectorNode->getOrCreateStateSet();
> 	ss->setTextureAttributeAndModes(unit,texture,osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
> 
> 	osg::Program* program = new osg::Program;
>      osg::ref_ptr<osg::Shader> shaderVertex = osg::Shader::readShaderFile(osg::Shader::VERTEX, osgDB::findDataFile(SHADER_PATH_VERT));
>      osg::ref_ptr<osg::Shader> shaderFragment = osg::Shader::readShaderFile(osg::Shader::FRAGMENT, osgDB::findDataFile(SHADER_PATH_FRAG));
>      program->addShader(shaderFragment);
>      program->addShader(shaderVertex);
>      ss->setAttributeAndModes( program, osg::StateAttribute::ON );
> 	ss->addUniform( new osg::Uniform("cubeMap", unit) );
> 
> 	osg::Uniform* u = new osg::Uniform("cameraPos",osg::Vec3());
> 	u->setUpdateCallback( new UpdateCameraPosUniformCallback( camera ) );
> 	ss->addUniform( u );
> 
>      // add the reflector scene to draw just as normal
>      group->addChild(reflectedSubgraph);
> 
>      // set an update callback to keep moving the camera and tex gen in the right direction.
>      group->setUpdateCallback(new UpdateCameraAndTexGenCallback(reflectorNodePath, Cameras));
> 
>      return group;
> }
> 
> 
> int main() {
>      // construct the viewer.
>      osgViewer::Viewer viewer;
> 
>      unsigned tex_width = 256;
>      unsigned tex_height = 256;
> 
>      osg::Camera::RenderTargetImplementation renderImplementation = osg::Camera::FRAME_BUFFER_OBJECT;
> 
>      osg::ref_ptr<osg::Group> scene = new osg::Group;
>      osg::ref_ptr<osg::Group> reflectedSubgraph = _create_scene();
>      if (!reflectedSubgraph.valid()) exit(0);
> 
>      osg::ref_ptr<osg::Group> reflectedScene = createShadowedScene(
> 			reflectedSubgraph.get(),
> 			createReflector(),
> 			TEXTURE_UNIT_CUBEMAP,
> 			viewer.getCamera()->getClearColor(),
>              tex_width,
> 			tex_height,
> 			renderImplementation,
> 			viewer.getCamera());
> 
>      scene->addChild(reflectedScene.get());
>      viewer.setSceneData(scene.get());
>      viewer.setUpViewInWindow(0,0,600,600);
>      viewer.run();
>      return 0;
> }
> 
> 
> 
> 
> 
> Vertex Shader:
> 
> Code:
> #version 130
> 
> uniform mat4 osg_ViewMatrixInverse;
> uniform vec3 cameraPos;
> 
> void main() {
>      gl_Position = ftransform();
>      gl_TexCoord[0] = gl_MultiTexCoord0;
>      mat4 ModelWorld4x4 = osg_ViewMatrixInverse * gl_ModelViewMatrix;
>      mat3 ModelWorld3x3 = mat3( ModelWorld4x4 );
>      vec4 WorldPos = ModelWorld4x4 *  gl_Vertex;
>      vec3 N = normalize( ModelWorld3x3 * gl_Normal );
>      vec3 E = normalize( WorldPos.xyz - cameraPos.xyz );
>      gl_TexCoord[1].xyz = reflect( E, N );
> }
> 
> 
> 
> Fragment Shader:
> 
> Code:
> #version 130
> 
> uniform samplerCube cubeMap;
> uniform sampler2D colorMap;
> const float reflect_factor = 0.5;
> 
> void main (void)
> {
>      vec3 base_color = texture2D(colorMap, gl_TexCoord[0].xy).rgb;
>      vec3 cube_color = textureCube(cubeMap, gl_TexCoord[1].xyz).rgb;
>      gl_FragColor = vec4( mix(cube_color, base_color, reflect_factor).rgb, 1.0);
> }
> 
> 
> 
> ...
> 
> Thank you!
> 
> Cheers,
> Rômulo
> 
> ------------------
> Read this topic online here:
> http://forum.openscenegraph.org/viewtopic.php?p=72639#72639
> 
> 
> 
> 
> 
> _______________________________________________
> osg-users mailing list
> osg-users at lists.openscenegraph.org
> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
> 


More information about the osg-users mailing list