OSG之TextureRectangle纹理映射

395 阅读2分钟

1 概述

TextureRectangle 纹理映射是在OpenGL 后来版本中的一个扩展ARB_texture_rectangle,它也 是一种二维纹理映射,但它与前面介绍的二维映射有很大的区别。如下所示。

Texture2D与TextureRectangle比较

(1) 纹理坐标

Texture2D 坐标必须被单位化,范围被限定在0~1之间,其他范围不在0~1之间的纹理坐标不会被支持 TextureRectangle 纹理坐标不要求单位化

(2) 纹理大小

Texture2D 纹理大小必须是2的n次方,如1024、512等。当然,如果读者的显卡驱动支持ARB_non power of two 或OpenGL2.0,则不会受到此限制

TextureRectangle 纹理尺寸的大小是任意纹理大小的,如513x1025

使用TextureRectangle纹理映射时有以下几点需要注意:

  • 纹理环绕模式。它并不支持所有的纹理包装模式,只能使用CLAMP、CLAMP_TO_EDGE或CLAMP_TO_BORDER,并不支持REPEAT。
  • 纹理滤波。它只支持NEAREST或者LINEAR,不支持Mipmap滤波,使用它时不能实现Mipmap 纹理。 不支持纹理边框。
  • 对于没有图形学基础的开发人员来说,TextureRectangle比较容易理解,也非常容易上手,可以简单理解为一个矩形纹理。

2 TextureRectangle 纹理映射示例

TextureRectangle纹理映射示例的代码如程序清单所示。


#include <osgViewer/Viewer>

#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>
#include <osg/Image>
#include <osg/TexGen>
#include <osg/Texture1D>
#include <osg/TexEnv>
#include <osg/StateSet>
#include <osg/TextureRectangle>
#include <osg/TexMat>

#include <osgDB/ReadFile>
#include <osgDB/WriteFile>

#include <osgUtil/Optimizer>

#include <Windows.h>

#include <iostream>
#include <string>
using namespace std;

//创建一个四边形节点
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::TextureRectangle> texture = new osg::TextureRectangle();
	texture->setDataVariance(osg::Object::DYNAMIC);
	//设置贴图
	texture->setImage(image.get());

	//设置纹理矩阵,并设置为根据矩阵纹理(TextureRectangle)的大小自动缩放
	//从而允许应用一个矩形纹理到一个纹理坐标不在0-1上
	osg::ref_ptr<osg::TexMat> texmat = new osg::TexMat;
	texmat->setScaleByTextureRectangleSize(true);

	//启用纹理及纹理矩阵
	stateset->setTextureAttributeAndModes(0,texmat.get(),osg::StateAttribute::ON);
	stateset->setTextureAttributeAndModes(0,texture.get(),osg::StateAttribute::ON);

	//关闭光照
	stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);

	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(GetExePath() + "/Data/2.jpg");

	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 optimizer ;
	optimizer.optimize(root.get()) ;

	viewer->setSceneData(root.get());

	setWindowSize(viewer, 640, 480);

	viewer->realize();

	viewer->run();

	return 0 ;
}

纹理图片

2.jpg

效果图

2.png

动态效果图

1.gif