1 概述
用户程序可以使用纹理状态函数接口为每个纹理单元指定渲染状态。纹理状态函数接口与非纹理状态的接口类似。用户可以使用osg::StateSet::setTextureAttribute()将一个纹理属性关联到StateSet对象。
setTextureAttribute()的第一个参数是纹理单元,第二个参数是继承自 StateAttribute类的一种纹理属性。
合法的纹理属性类共有6种,其中包括5种纹理类型(osg::TextureID、osg::Texture2D、osg::Texture3D、 osg::TextureCubeMap 和 osg::TextureRectangle)和一个用于纹理坐标的生成的类(osg::TexGen)。
下面的代码将根据给定的Texture2D属性对象tex和渲染状态 StateSet将tex关联到渲染状态,并设置使用纹理单元0。
//创建一个Texture2D 属性
Osg:ref_ptr<osg:Texture2D>tex=new osg:Texture2D;
//关联材质属性到材质单元0
state->setTextureAttribute(0,tex.get0));
与上面的程序类似,用户可以调用 osg::StateSet::setTextureModeO)方法来设置材质渲染模式,这个方法与setModeO)方法类似。用户可以使用setTextureMode()来设置 GL_TEXTURE_ID、GL_TEXTURE 2D、GL_TEXTURE_3D、GL_TEXTURE_CUBE_MAP、GL_TEXTURE_RECTANGLE、GL_TEXTURE GEN_Q、GL_TEXTURE_GEN_R、GL_TEXTURE_GEN_S以及GL_TEXTURE_GEN_T模式。
与 setTextureAttribute()相似,setTextureModeO)的第一个参数表示纹理单元。下面的代码段将禁止 纹理单元1的2D纹理映射:
state->setTextureMode( 1,GL_TEXTURE_2D,osg::StateAttribute::OFF);
当然,用户也可以使用 osg::StateSet::setTextureAttributesAndModes()来关联纹理渲染属性到 StateSet,同时允许相应的纹理模式。如果属性是一个TexGen对象,那么 setTextureAttributesAndModes()将设置相应的坐标生成模式GL_TEXTURE_GEN_Q、GL_TEXTURE_GEN_R.GL_TEXTURE_GEN_S 和GL_TEXTURE_GEN_T.对于其他纹理属性来说,这一模式是隐含的。例如,下面的代码中,由于第二个参数传入了一个 Texture2D 对象作为纹理属性,setTextureAttributesAndModes()将允许 GL_TEXTURE_2D模式:
//创建一个Texture2D 属性对象
osg:ref_ptr<osg:Texture2D>tex=new osg:Texture2D;
//在纹理单元0上,关联2D纹理属性并许可GL_TEXTURE_2D模式
state->setTextureAttributeAndModes(0,tex);
setTextureAttributeAndModes()的第三个参数的默认值为ON,即允许纹理渲染模式。与 setAttribute AndModesO类似,读者可以对这个参数使用位或操作包括 OVERRIDE、PROTECTED 和 INHERIT,以修改纹理属性的继承特性。读者还可以通过修改setTextureModeO和 setTextureAttribute()的第三个参数来指定这个继承标志。
2 代码示例
#include <osgViewer/Viewer>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>
#include <osg/Image>
#include <osg/TexGen>
#include <osg/TexEnv>
#include <osg/StateSet>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgUtil/Optimizer>
#include <iostream>
#include "utility.h"
// 创建一个四边形节点
osg::ref_ptr<osg::Node> createNode()
{
osg::ref_ptr<osg::Geode> geode = new osg::Geode();
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry();
// 设置顶点
osg::ref_ptr<osg::Vec3Array> vc = new osg::Vec3Array();
vc->push_back(osg::Vec3(0.0f, 0.0f, 0.0f));
vc->push_back(osg::Vec3(1.0f, 0.0f, 0.0f));
vc->push_back(osg::Vec3(1.0f, 0.0f, 1.0f));
vc->push_back(osg::Vec3(0.0f, 0.0f, 1.0f));
geom->setVertexArray(vc.get());
// 设置纹理坐标
osg::ref_ptr<osg::Vec2Array> vt = new osg::Vec2Array();
vt->push_back(osg::Vec2(0.0f, 0.0f));
vt->push_back(osg::Vec2(1.0f, 0.0f));
vt->push_back(osg::Vec2(1.0f, 1.0f));
vt->push_back(osg::Vec2(0.0f, 1.0f));
geom->setTexCoordArray(0, vt.get());
// 设置法线
osg::ref_ptr<osg::Vec3Array> nc = new osg::Vec3Array();
nc->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));
geom->setNormalArray(nc.get());
geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
// 添加图元
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));
// 绘制
geode->addDrawable(geom.get());
return geode.get();
}
// 创建二维纹理状态对象
osg::ref_ptr<osg::StateSet> createTexture2DState(osg::ref_ptr<osg::Image> image)
{
// 创建状态集对象
osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet();
// 创建二维纹理对象
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D();
texture->setDataVariance(osg::Object::DYNAMIC);
// 设置贴图
texture->setImage(image.get());
stateset->setTextureAttributeAndModes(0, texture.get(), osg::StateAttribute::ON);
return stateset.get();
}
int main()
{
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
osg::ref_ptr<osg::Group> root = new osg::Group();
// 读取贴图文件
osg::ref_ptr<osg::Image> image = osgDB::readImageFile(GetCurrentPath() + "Data\\fengjing1.jpeg");
osg::ref_ptr<osg::Node> node = createNode();
// 创建状态集对象
osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet();
stateset = createTexture2DState(image.get());
// 使用二维纹理
node->setStateSet(stateset.get());
root->addChild(node.get());
// 优化场景数据
osgUtil::Optimizer optimzer;
optimzer.optimize(root.get());
setWindowSize(viewer.get(), 600, 600, "Texture2D");
viewer->setSceneData(root.get());
viewer->realize();
viewer->run();
return 0;
}
原图
效果图
动态效果图