多重纹理和纹理组合器

多重纹理和纹理组合器

本文主要介绍OpenGL中两种技术的使用方法:多重纹理技术和纹理组合器技术,最终根据参考【2】中的代码,实现了两个简单的演示DEMO,其中使用到了《八叉树颜色量化、BMP、TGA文件解析》篇章中提供的图像解析类。

下载地址:https://github.com/twinklingstar20/twinklingstar_cn_demo_multitexture_texture_combiner/

一.多重纹理技术(Multitexture)

1.1 多重纹理技术简介

OpenGL在渲染多边形时允许多张纹理同时被应用,这些纹理在操作管线上一个接一个的被处理。一个纹理单元(texture unit)表示单个纹理的操作,一个纹理单元处理完成后,将它的结果传递给下一个纹理单元,直至所有的纹理单元都被处理完。下图显示了片断(fragment)经历的四个纹理操作过程。

2013-12-2 22-39-39

图1.片断经历的四个纹理过程

注意:在反馈模式下,除了第一个纹理单元外多重纹理是处于未定义的状态,即只有第一张纹理单元能用(In feedback mode, multitexturing is undefined beyond the first texture unit)。

1.2 使用多重纹理的几个步骤

(1)   建立每个纹理单元的纹理状态,包括纹理图像数据,过滤器,环境,矩阵,纹理函数生成方式等。可用glActiveTexture()函数以改变当前的纹理状态,然后调用glTexImage*(),glTexParameter*(),glTexEnv*(),glTexGen*(),glBindTexture()方法分配每个纹理单元的纹理信息,纹理状态、纹理坐标和光栅化纹理坐标的查询都应用在当前纹理单上,即glActiveTexture()指定的纹理单元。此外,可以使用glGetIntegerv(GL_MAX_TEXTURE_UNITS,…)显示当前实现中允许的最大纹理单元数,得到的最大纹理单元数至少为2。

注意:glPushAttrib(),glPushClientAttrib(),glPopAttrib(),或者glPopClientAttrib()可以保存或者恢复所有纹理单元的纹理状态,但是纹理矩阵堆栈除外。

(2)   可以用glMultiTexCoord*()函数规定每个顶点上不同纹理单元的纹理坐标。下面的代码片段演示该函数的用法:

1
2
3
4
5
6
7
8
9
10
11
glBegin(GL_TRIANGLES);
glMultiTexCoord2f(GL_TEXTURE0,0.0f,0.0f);
glMultiTexCoord2f(GL_TEXTURE1,1.0f,0.0f);
glVertex2f(0.0f,0.0f);
glMultiTexCoord2f(GL_TEXTURE0,0.5f,1.0f);
glMultiTexCoord2f(GL_TEXTURE1,0.5f,0.0f);
glVertex2f(50.0f,100.0f);
glMultiTexCoord2f(GL_TEXTURE0,1.0f,0.0f);
glMultiTexCoord2f(GL_TEXTURE1,1.0f,1.0f);
glVertex2f(100.0f,0.0f);
glEnd();

注意:如果使用glTexCoord*()相当于采用了第一个纹理单元的纹理坐标,即与glMultiTexCoord*(GL_TEXTURE0,…)等价。

(3)   恢复使用单个纹理。在使用多重纹理时,如果想要恢复使用单个纹理,需要禁用除纹理单位0之外的所有纹理单位。如下面的代码片段所示:

1
2
3
4
5
glActiveTexture(GL_TEXTURE1);
glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE2);
glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);

附加说明:

(1)由于微软的VS平台上,只支持OpenGL 1.1版本,所以无法使用glActiveTexture()等函数,所以需要安装上glew库,这个库的安装方法网上很容易搜索到;

(2)将多重纹理技术与组合器函数glTexEnv*()结合使用,可以产生很绚丽的效果,下面介绍纹理组器函数;

(3)multitexture-demo演示了一个多重纹理的简单例子,使用到纹理组合器。

二.纹理组合器(Texture combiner

2.1 纹理组合器函数简介

OpenGL除了多重纹理外,还提供了一些灵活的纹理组合器函数,允许程序员对片断与纹理值或者其它颜色的混合,对纹理提供了更加精细的控制。这就使得OpenGL的重心从原先的顶点处理(变换、裁剪)过渡到光栅化和片断操作,片断的处理能力越来越强。纹理组合器函数glTexEnv*()的参数比较多,下面会逐步进行介绍。

2.2 glTexEnv*()函数介绍

void glTexEnv{if}(GLenum target,GLenum pname,TYPE param);

void glTexEnv{if}v(GLenum target,GLenum pname,TYPE* param);

target规定纹理环境(texture environment),必需是GL_TEXTURE_ENV,GL_TEXTURE_FILTER_CONTROL,GL_POINT_SPRITE中的任意一个值。对target和pname对应参数进行总结,如表1所示;对pname和param对应参数进行总结,如表2所示。

2013-12-2 22-40-43

表1. 参数target和参数pname的对应取值

2013-12-02-table2

表2. 参数pname和参数param的对应取值

2.2.1 target的值是GL_TEXTURE_FILTER_CONTROL

如果target是GL_TEXTURE_FILTER_CONTROL时,pname必须是GL_TEXTURE_LOD_BIAS,则param规定了纹理细节层的偏移量,它的用途可以参见文章《基本的二维纹理对象的使用方法介绍》中3.1小节的介绍。

2.2.2 target的值是GL_POINT_SPRITE

如果target是GL_POINT_SPRITE 时,pname必须是GL_COORD_REPLACE,boolean值用于规定是否开启点精灵纹理坐标替换(point sprite texture coordinate replacement)。

2.2.3 target的值是GL_TEXTURE_ENV

如果target是GL_TEXTURE_ENV,pname必须是(1)GL_TEXTURE_ENV_MODE,  GL_TEXTURE_ENV_COLOR,(3)GL_COMBINE_RGB,GL_COMBINE_ALPHA,(4)GL_RGB_SCALE,(5)GL_ALPHA_SCALE,(6)GL_SRC0_RGB, GL_SRC1_RGB,(7)GL_SRC2_RGB,(8)GL_SRC0_ALPHA,(9)GL_SRC1_ALPHA,(10)GL_SRC2_ALPHA。

在不同的纹理存储格式下,用于纹理计算的R、G、B、A4个颜色分量的取值。

2013-12-2 22-44-27

表3.进行组合操作的源纹理(不同的内部存储格式下)的Cs、As

C代表一个三元的颜色值(RGB),A是相关的alpha值,从纹理图像中提取的RGBA的值都在范围[0,1]内,下标是p的代表由上一个阶段计算得到的纹理颜色(处理阶段为0的纹理颜色就是起始的原片断颜色),下标是s的代表原纹理颜色(Texture Source Color),下标是c的代表纹理环境的颜色(Texture Environment Color),下标是v的代表通过纹理函数计算后得到的纹理颜色。

2013-12-02-table4

表4. 当pname是GL_TEXTURE_ENV_MODE时,几种纹理处理函数的计算公式

如果pname是GL_TEXTURE_ENV_MODE,params是GL_COMBINE,则纹理函数的计算依赖GL_COMBINE_RGB和GL_COMBINE_ALPHA。

接下来描述的是由GL_SRC0_RGB、GL_SRC1_RGB、GL_SRC2_RGB、GL_SRC0_ALPHA、GL_SRC1_ALPHA、GL_SRC2_ALPHA规定的源纹理,通过组合,生成最后的纹理颜色的方法,在下面的表中GL_SRC0_c表示Arg0,GL_SRC1_c表示Arg1,GL_SRC2_c表示Arg2。

当pname是GL_COMBINE_RGB时,param可以接受的几个参数是GL_REPLACE、GL_MODULATE、GL_ADD、GL_ADD_SIGNED、GL_INTERPOLATE、GL_SUBTRACT、GL_DOT3_RGB、GL_DOT3_RGBA。

2013-12-02-table5

表5. 规定几种源纹理,通过对这几种纹理的RGB颜色计算,得到最终的纹理颜色

    类似的,当pname是GL_COMBINE_ALPHA时,param可以接受的几个参数是GL_REPLACE、GL_MODULATE、GL_ADD、GL_ADD_SIGNED、GL_INTERPOLATE、GL_SUBTRACT。

2013-12-02-table6

表6.规定几种源纹理,通过对这几种纹理的alpha颜色计算,得到最终的纹理颜色

下面的表格中Cs表示当前绑定的纹理采样的颜色,Cc表示环境纹理颜色常量(Constant Texture-Environment Color),Cf表示传入片断的主颜色,Cp表示以前的纹理阶段计算出的颜色(如果当前正处理的纹理阶段是0,则它的值为Cf),类似的,As,Ac,Af,Ap表示对应纹理的alpha值。下表是基于源纹理的RGB值和操作,计算得到的Arg0,Arg1,Arg2。

2013-12-02-table7

表7. 基于源纹理的RGB值和操作,计算得到的Arg0,Arg1,Arg2 

    类似的,下表是基于源纹理的Alpha值和操作,计算得到的Arg0,Arg1,Arg2。

2013-12-02-table8

表8. 基于源纹理的Alpha值和操作,计算得到的Arg0,Arg1,Arg2

2.3 glTexEnv*()函数使用例子

选择激活纹理组合方法:

1
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);

选择纹理组合的运算法则:

1
glTexEnvf(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_SUBTRACT);

设置纹理组合函数中纹理的来源:

1
2
glTexEnvf(GL_TEXTURE_ENV,GL_SRC0_RGB,GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV,GL_SRC1_RGB,GL_PREVIOUS);

设置如何使用纹理组合函数中纹理的来源来计算Arg0和Arg1,如表7所示:

1
2
glTexEnvf(GL_TEXTURE_ENV,GL_OPERAND0_RGB,GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV,GL_OPERAND1_RGB,GL_SRC_COLOR);

实现了multitexture-combine-demo这个demo,用组合器生成多重纹理的代码片段如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
void initTexture()
{
    unsigned int textureId[2];
    //创建2个纹理
    //生成一个2*2,颜色为(0,0,255)的纹理图片
    textureId[0] = genTexture(0,0,255);
    //读取一个BMP图片,生成纹理
    textureId[1] = genTextureFile("text.bmp");
    //激活第1个纹理
    glActiveTexture(GL_TEXTURE0);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D,textureId[0]);
    //用纹理textureId[0]替换环境纹理
    glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
    glActiveTexture(GL_TEXTURE1);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D,textureId[1]);
    //设置组合器,运算法则是“减法”,
    //textureId[1]是纹理GL_SRC0_RGB,前一个阶段计算的纹理是GL_SRC1_RGB,
    //根据运算法则GL_SRC0_RGB-GL_SRC1_RGB,字体中间是白色的(255,255,255),减去(0,0,255),会显示出黄色;
    //字体周围是黑色的,减去(0,0,255)还是黑色的。
    glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);
    glTexEnvf(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_SUBTRACT);
    glTexEnvf(GL_TEXTURE_ENV,GL_SRC0_RGB,GL_TEXTURE);
    glTexEnvf(GL_TEXTURE_ENV,GL_OPERAND0_RGB,GL_SRC_COLOR);
    glTexEnvf(GL_TEXTURE_ENV,GL_SRC1_RGB,GL_PREVIOUS);
    glTexEnvf(GL_TEXTURE_ENV,GL_OPERAND1_RGB,GL_SRC_COLOR);
}
void drawScene()
{
    glBegin(GL_QUADS);
        //分别指定三个纹理的纹理坐标
        glMultiTexCoord2f(GL_TEXTURE0,0.0f, 0.0f);glMultiTexCoord2f(GL_TEXTURE1,0.0f, 0.0f);
        glVertex3f(-1.0f, -1.0f,  1.0f);
        glMultiTexCoord2f(GL_TEXTURE0,1.0f, 0.0f);glMultiTexCoord2f(GL_TEXTURE1,1.0f, 0.0f);
        glVertex3f( 1.0f, -1.0f,  1.0f);
        glMultiTexCoord2f(GL_TEXTURE0,1.0f, 1.0f);glMultiTexCoord2f(GL_TEXTURE1,1.0f, 1.0f);
        glVertex3f( 1.0f,  1.0f,  1.0f);
        glMultiTexCoord2f(GL_TEXTURE0,0.0f, 1.0f);glMultiTexCoord2f(GL_TEXTURE1,0.0f, 1.0f);
        glVertex3f(-1.0f,  1.0f,  1.0f);
    glEnd();
}

该DEMO的组合效果如下图所示:

2013-12-02-demo2

图2. 通过设置组合器,得到最终的结果

    至此,演示了组合器的基本用法,可以通过概念组合器不同的参数,得到不同的结果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/509859.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ClouderaManager agent 报错,无法连接到结群 Error, CM server guid updated, expected xxx , received xxx

场景 集群版本:CDH 6.0.1 服务器版本:Centos 7.3 JAVA版本:1.8 异常出现原因 搭建集群中遇到异常,删除agent节点,重新部署CM后发现异常,CDH处于无法使用状态 异常 查看agent日志会出现,说无法连接到…

1192 约瑟夫问题(1)

1192 约瑟夫问题(1) Time Limit : 2000/1000 MS(Java/Others) | Memory Limit :65536/32768 KB(Java/Others) Submits : 1235 | Solved : 716 Description 模拟这个游戏。有n个人围成一圈,从第一个人开始沿顺时针方向报数(从1到3…

CDH Kerberos 认证下Kafka 消费方式

集群Kerberos认证安装参考:https://datamining.blog.csdn.net/article/details/98480008 目录 环境: 配置 Java Producer 代码 文件内容: kafka_client_jaas.conf krb5.conf ( kerberos 配置文件复制过来即可) kafka.keytab Java Co…

glsl基础

目录[-] 变量 基本类型 结构体 数组 修饰符 内置变量 表达式 操作符 数组访问 构造函数 成分选择 控制流 循环 if/else discard 函数 变量 GLSL的变量命名方式与C语言类似。变量的名称可以使用字母,数字以及下划线,但变量名不能以数字开头,还…

1260 不一样的A+B

1260 不一样的AB Time Limit : 2000/1000 MS(Java/Others) | Memory Limit :65536/32768 KB(Java/Others) Submits : 641 | Solved : 357 Description 读入两个小于100的正整数A和B,计算AB的值并输出。需要注意的是:整数A和B的每一位数字由对应的英文单…

IntelliJ IDEA Maven jar包冲突解决,快速发现jar包冲突

IntelliJ IDEA 自带的Diagrams 去查看jar包冲突相当费劲 ~ ,安装个插件即可快速解决该问题 打开Settings,搜索maven helper,并安装 安装完成后,直接打开pom文件,点击Dependency Analyzer 删除冲突jar包,在…

GLSL学习教程博客

http://blog.csdn.net/racehorse/article/details/6593719

1185 城市名排序

1185 城市名排序 Time Limit : 2000/1000 MS(Java/Others) | Memory Limit :65536/32768 KB(Java/Others) Submits : 3989 | Solved : 2049 Description 从键盘输入n个城市名,进行升序排序并输出。 Input 第一行输入一个整数n,表示有n个城市&#xff0…

osg基本图元

OSG绘制几何体学习总结(超全)在osg中,场景图形采用一种自顶向下的,分层的树状数据结构来组织空间数据集,以提高渲染的效率 场景图形树结构的顶部是一个根节点,从根节点向下延伸,各个组节点中均包…

kafka如何彻底删除topic及数据

前言: 删除kafka topic及其数据,严格来说并不是很难的操作。但是,往往给kafka 使用者带来诸多问题。项目组之前接触过多个开发者,发现都会偶然出现无法彻底删除kafka的情况。本文总结多个删除kafka topic的应用场景,总…

如何用css设计出商品购物图片

代码: 常见问题:背景填充时候图片大小不一致、重复等等问题,建议在插入图片的时候最好不用img标签直接在div中添加背景图片,有利于对背景图片的更改。 插入图片:background-image: url(../img/product-auto/benz-amg-s…

OLTP、OLAP与HTAP 区别

OLTP On-Line Transaction Processing联机事务处理过程(OLTP) 也称为面向交易的处理过程,其基本特征是前台接收的用户数据可以立即传送到计算中心进行处理,并在很短的时间内给出处理结果,是对用户操作快速响应的方式之一。 这样做的最大优点…

osg布告板技术(Billboard)

公告牌技术,即billboard技术,在3D游戏中有着广泛的应用.它的本质就是用预先做好的几幅 位图来代替3D物体,极大地节省资源和提高速度.仔细观察<<魔法门>>系列游戏,它的精灵,树木,物 品都是二维图象,但由于它始终朝向观察者,你根本看不到它"扁"的一面,所以…

1224 哥德巴赫猜想(2)

1224 哥德巴赫猜想&#xff08;2&#xff09; Time Limit : 2000/1000 MS(Java/Others) | Memory Limit :65536/32768 KB(Java/Others) Submits : 1564 | Solved : 629 Description 所谓哥德巴赫猜想&#xff0c;就是指任何一个大于2的偶数&#xff0c;都可以写成两个素数的和…

Hbase 查看 rowkey在哪个region中

首先我们先了解下 hbase:meta 表&#xff0c;hbase是指的namespace&#xff0c;meta是表名&#xff0c;这张表存储的是整个集群的Region信息。 hbase:meta表的一个rowkey对应一个region&#xff0c;rowkey设计如下: 表名,region的startRowkey,region创建时的时间戳,EcodedName …

osg坐标系转换

osg中将局部坐标系下的点坐标换算成全局坐标系下点的坐标 标签&#xff1a; matrixlist2012-05-17 16:27 2940人阅读 评论(1) 收藏 举报分类&#xff1a;osg&#xff08;7&#xff09; 坐标变换版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 今天…

1295 爱翻译

1295 爱翻译 Time Limit : 2000/1000 MS(Java/Others) | Memory Limit :65536/32768 KB(Java/Others) Submits : 390 | Solved : 80 Description 英语是现在世界第一大语言&#xff0c;所以学好英语是very important&#xff0c; 但是宁波大学的某个大牛说&#xff1a;“我不怕…

C#/WPF 播放音频文件

C#播放音频文件的方式&#xff1a; 播放系统事件声音使用System.Media.SoundPlayer播放wav使用MCI Command String多媒体设备程序接口播放mp3&#xff0c;wav&#xff0c;avi等使用WindowsMediaPlayer的COM组件来播放(可视化)使用DirectX播放音频文件使用Speech播放(朗读器&am…

Hbase 二级索引 Solr int字段排序问题 can not sort on multivalued field

Hbase Solr 同步二级索引后&#xff0c;进行int字段排序时报错 报错如下 {"responseHeader":{"zkConnected":true,"status":400,"QTime":75,"params":{"q":"*:*","sort":"hbase_index…

OpenGL渲染管线,着色器,光栅化等概念理解

卧槽&#xff0c;前些日子看这几个概念就十分想吐槽&#xff0c;这么难理解的概念窃以为纯属翻译的不够接地气。————首先&#xff0c;光栅化&#xff08;Rasterize/rasteriztion&#xff09;。这个词儿Adobe官方翻译成栅格化或者像素化。没错&#xff0c;就是把矢量图形转化…