OSG之二维纹理状态

451 阅读3分钟

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;
}

原图

3.PNG

效果图

2.PNG

动态效果图

1.gif