GLSL核心课程---纹理图像

大多数时候我们会将一幅纹理图像应用到模型上,或多或少就像壁纸一样。有时候纹理还可以看成是数据,不是颜色值。纹理坐标提供了在图像和模型之间的映射关系。在我们着色器中处理使用纹理之前我们需要在我们的OpenGL应用程序中做一些设置步骤。在这一节中,我们将覆盖一下经典纹理用法案例。

OpenGL

在我们着色器中使用纹理的第一步就是需要创建一个OpenGL纹理对象。一个通用的用法就是我们同样需要从文件中加载图像数据来添加到纹理中,如果你不确定如何做这一步,那么请看这一页的介绍。

在着色器中需要设置一个一致变量来储存纹理单元。注意,着色器接收的是纹理单元而不是纹理名字。OpenGL提供了多个单元,因此我们在一个着色器中使用多个纹理。纹理单元有效数据是GL_MAX_COMBIEND_TEXTURE_IMAGE_UNITS

让我们假定在着色器中定义一个叫做texUnit的一致变量。同样假定我们仅仅只有一个纹理,因此我们将绑定到纹理单元0.

OpenGL应用程序这一端,在设置的步骤,我们需要得到一致变量texUnit的位置。到目前为止OpenGL是将texUnit定义成整型变量。因此,假定变量p存储GLSL程序的名字,下面的代码得到位置:

GLint texUnitLoc = glGetUniformLocation(p, “texUnit”);

如果提供给着色器的纹理单元总是跟我们在应用程序设置的一样。房子我们不得不经常修改纹理单元。为了设置变量texUnit为纹理单元0我们需要这么写:

glProgramUniformli(p, texUnitLoc, 0);

绘制实现绑定纹理到纹理单元。因此,如果我们假定texture1D是纹理单元(由glGenTextures创建)和纹理是2D,我们可以这么写:

glActiveTexture(GL_TEXTURE0);

glBindTexture(GL_TEXTURE_2D, texture1D);

后面我们将绑定到VAOs和调用glDraw*命令。

GLSL

现在,让我们回到GLSL这一端。首先必须定义一个变量texUnit。这个变量定义成sampler*类型。Samplers是一个不透明类型,比如说,它们不能像常规变量那样处理,它们的用法在函数中有限制,必须适当使用。采样器处理的纹理是在OpenGL应用程序端定义的,输入函数可以从纹理数据中返回值。每个纹理类型都有一个合适的采样类型,实际上,就像一个纹理模板GL_TEXTURE_2D,那么采样类型会sampler2D

为了处理纹理我们需要两个元素:纹理单元,和纹理坐标。在这里有很多函数来处理纹理数据。其中的很多都是用来查询,其他一些提供纹理数据,让我们从一些查询开始。

一个通用的着色器可以处理纹理通过它们的大小。大小信息(宽度和高度)可以通过一致变量来提供给着色器。另外一个选项就是使用textureSize函数。这个函数返回的纹理在x, y, z分量的大小,而w是在纹理数组或者立方体纹理的索引。这个函数同样可以使用mipmap级数,在这种情况下上面所有的信息就是相对于查询mipmap级数信息。

纹理mipmap级数大小可以有textureQueryLevels来查询。这个函数可以返回在纹理中(从OpenGL4.3有效)有效的mipmap计算数目。

Mipmap级数,或者结合mipmap等级,可以在特定片段使用textureQueryLod获取。这个函数返回一个vec2其中的x分量表示将会被使用的等级和相应的比例。实际上x=3.25然后等级3将会贡献75%和等级425%

我们可以这个动作,参考下面的代码:

#version 420

uniform sampler2D texUnit;

out vec4 outputF;

void main()

{

vec2 res = textureQueryLod(texUnit, VertexIn.texCoord.xy);

if(res.x == 0)

outputF = vec4(1.0, 0.0, 0.0, 0.0);

else if(res.x < 1)

outputF = vec4(0.0, 1.0, 0.0, 0.0);

else if(res.x < 2)

outputF = vec4(0.0, 0.0, 1.0, 0.0);

else if(res.x < 3)

outputF = vec4(0.0, 1.0, 1.0, 0.0);

else if(res.x < 4)

outputF = vec4(1.0, 0.0, 1.0, 0.0);

else if(res.x < 5)

outputF = vec4(1.0, 1.0, 0.0, 0.0);

else if(res.x < 6)

outputF = vec4(0.5, 1.0, 0.0, 0.0);

else if(res.x < 7)

outputF = vec4(0.0, 1.0, 0.5, 0.0);

}

结果就像下面的图示一样:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值