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 ;
}
纹理图片
效果图
动态效果图