看了几个环境映射的例子,一个是把天空盒挂上,我不同意这种观点。以车身为例,因为环境映射是车身自身反射的内容,而与环境无关。
即:输入只与视点位置有关,反射向量碰到哪个物体了就用哪个物体的像素颜色。
挂代码:
天空盒不变
#ifndefSKYBOX_H
#define SKYBOX_H
#include <osg/TextureCubeMap>
#include <osg/Transform>
class SkyBox : public osg::Transform
{
public:
SkyBox();
SkyBox( const SkyBox& copy, osg::CopyOp copyop=osg::CopyOp::SHALLOW_COPY )
: osg::Transform(copy, copyop) {}
META_Node( osg, SkyBox )
void setEnvironmentMap( unsigned int unit, osg::Image* posX, osg::Image* negX,
osg::Image* posY, osg::Image* negY, osg::Image* posZ, osg::Image* negZ );
virtual bool computeLocalToWorldMatrix( osg::Matrix& matrix, osg::NodeVisitor* nv ) const;
virtual bool computeWorldToLocalMatrix( osg::Matrix& matrix, osg::NodeVisitor* nv ) const;
protected:
virtual ~SkyBox() {}
};
#endif // SKYBOX_H
#include <osg/Depth>#include <osgUtil/CullVisitor>#include "skybox.h"#include <QDebug>SkyBox::SkyBox(){
setReferenceFrame( osg::Transform::ABSOLUTE_RF );setCullingActive( false );osg::StateSet* ss = getOrCreateStateSet();ss->setAttributeAndModes( new osg::Depth(osg::Depth::LEQUAL, 1.0f, 1.0f) );ss->setMode( GL_LIGHTING, osg::StateAttribute::OFF );ss->setMode( GL_CULL_FACE, osg::StateAttribute::OFF );ss->setRenderBinDetails( 5, "RenderBin" );}
void SkyBox::setEnvironmentMap( unsigned int unit, osg::Image* posX, osg::Image* negX,osg::Image* posY, osg::Image* negY, osg::Image* posZ, osg::Image* negZ ){
if ( posX && posY && posZ && negX && negY && negZ ){qDebug() << "6imageok!";osg::ref_ptr<osg::TextureCubeMap> cubemap = new osg::TextureCubeMap;cubemap->setImage( osg::TextureCubeMap::POSITIVE_X, posX );cubemap->setImage( osg::TextureCubeMap::NEGATIVE_X, negX );cubemap->setImage( osg::TextureCubeMap::POSITIVE_Y, posY );cubemap->setImage( osg::TextureCubeMap::NEGATIVE_Y, negY );cubemap->setImage( osg::TextureCubeMap::POSITIVE_Z, posZ );cubemap->setImage( osg::TextureCubeMap::NEGATIVE_Z, negZ );cubemap->setWrap( osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE );cubemap->setWrap( osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE );cubemap->setWrap( osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE );cubemap->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR );cubemap->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR );cubemap->setResizeNonPowerOfTwoHint( false );getOrCreateStateSet()->setTextureAttributeAndModes( unit, cubemap.get() );}}
bool SkyBox::computeLocalToWorldMatrix( osg::Matrix& matrix, osg::NodeVisitor* nv ) const{
if ( nv && nv->getVisitorType()==osg::NodeVisitor::CULL_VISITOR ){osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>( nv );matrix.preMult( osg::Matrix::translate(cv->getEyeLocal()) );return true;}elsereturn osg::Transform::computeLocalToWorldMatrix( matrix, nv );}
bool SkyBox::computeWorldToLocalMatrix( osg::Matrix& matrix, osg::NodeVisitor* nv ) const{
if ( nv && nv->getVisitorType()==osg::NodeVisitor::CULL_VISITOR ){osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>( nv );matrix.postMult( osg::Matrix::translate(-cv->getEyeLocal()) );return true;}elsereturn osg::Transform::computeWorldToLocalMatrix( matrix, nv );}
顶点着色器,uniform vec3 eyepos; varying vec3 reflectvec; void main(void) { vec4 pos = normalize(gl_ModelViewMatrix * gl_Vertex); pos = pos / pos.w; vec3 eyevec = normalize(eyepos - pos.xyz); vec3 norm = normalize(gl_NormalMatrix * gl_Normal); reflectvec = reflect(-eyevec, norm); gl_Position = ftransform(); } 片元着色器uniform samplerCube cubemap; varying vec3 reflectvec; void main(void) { vec4 texcolor = textureCube(cubemap, reflectvec); gl_FragColor = texcolor; //gl_FragColor = float4(1.0,0.0,0.0,1.0); }关键在于调用时,
osg::ref_ptr<SkyBox> theSky = new SkyBox;theSky->getOrCreateStateSet()->setTextureAttributeAndModes( 0, new osg::TexGen );theSky->setEnvironmentMap( 0,osgDB::readImageFile("E:/cubemap/pos_x.jpg"),osgDB::readImageFile("E:/cubemap/neg_x.jpg"),osgDB::readImageFile("E:/cubemap/pos_y.jpg"),osgDB::readImageFile("E:/cubemap/neg_y.jpg"),osgDB::readImageFile("E:/cubemap/pos_z.jpg"),osgDB::readImageFile("E:/cubemap/neg_z.jpg") );//theSky->addChild(geode.get());root->addChild(theSky);qDebug() << "天空盒位置:"<<theSky->getBound().center().x()<<","<<theSky->getBound().center().y()<<","<<theSky->getBound().center().z();//环境映射物体_nodeEnvMapping = osgDB::readNodeFile("E:/glider.osg");root->addChild(_nodeEnvMapping);osg::StateSet * stateEnv = _nodeEnvMapping->getOrCreateStateSet();osg::ref_ptr<osg::Program> programEnv = new osg::Program;osg::ref_ptr<osg::Shader> vertexShaderEnv = new osg::Shader( osg::Shader::VERTEX );osg::ref_ptr<osg::Shader> fragShaderEnv = new osg::Shader( osg::Shader::FRAGMENT );vertexShaderEnv->loadShaderSourceFromFile("E:/vertexEnv.txt");fragShaderEnv->loadShaderSourceFromFile("E:/fragEnv.txt");programEnv->addShader( vertexShaderEnv );programEnv->addShader( fragShaderEnv );stateEnv->setAttributeAndModes( programEnv,osg::StateAttribute::ON );//传递视点坐标viewer->setCameraManipulator(NULL);//获取相机参数osg::Vec3f eye, center, up;viewer->getCamera()->getViewMatrixAsLookAt(eye,center,up);eye = osg::Vec3(100,100,100);_uniEyePos = new osg::Uniform("eyepos", eye);stateEnv->addUniform( _uniEyePos );如果周围没天空盒时,即为黑色的,因为反射法线碰不到物体
加上天空盒后,滑翔机显示天空盒