osg环境映射

看了几个环境映射的例子,一个是把天空盒挂上,我不同意这种观点。以车身为例,因为环境映射是车身自身反射的内容,而与环境无关。

即:输入只与视点位置有关,反射向量碰到哪个物体了就用哪个物体的像素颜色。


挂代码:

天空盒不变

#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;
    }
    else
        return 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;
    }
    else
        return 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 );
如果周围没天空盒时,即为黑色的,因为反射法线碰不到物体
加上天空盒后,滑翔机显示天空盒



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值