文章目录
- 一、说明
- 二、贴图的初始化处理
- 2.1 贴图中的几种纹理
- 2.2 原始数据处理 - 贴图的规格化
- 三、纹理对象生成和绑定(选中)
- 3.1 生成纹理矩阵
- 3.2 glGenTextures 函数明细
- 3.2 glBindTexture函数明细
- 四、glTexParameteri函数
- 4.1 贴放放法参数确定
- 4.2 放大缩小插值方法参数确定
- 五、一段参考代码
- 5.1 顶点着色器
- 5.2 片段着色器
- 5.3 OpenGL代码
- 六、glTexImage2D函数
- 6.1 函数描述
- 6.2 参数解释
- 6.3 其它限制
- 6.4 补充描述
- 七、纹理对象调用过程总结
- 7.1 顶点着色器作用
- 7.2 片元着色器作用
- 7.3 OpenGL的作用
- 八、后记
一、说明
关于贴图问题,是OpenGL最复杂的系统了,本系列文挡将在整个流程上叙述纹理贴图的过程。在本文中,将涉及最一般朴素的若干操作,基本覆盖从读入图片,到生成纹理图像的过程。在整个过程的若干操作函数都给出一般常识性解释。
常见函数:
glActiveTexture,
glCopyTexImage1D,
glCopyTexImage2D,
glCopyTexSubImage1D,
glCopyTexSubImage2D,
glCopyTexSubImage3D,
glPixelStore,
glTexImage1D,
glTexImage3D,
glTexSubImage1D,
glTexSubImage2D,
glTexSubImage3D,
glTexParameter
二、贴图的初始化处理
2.1 贴图中的几种纹理
纹理有两种:
- GL_TEXTURE_1D_ARRAY 表明是一维纹理
- GL_TEXTURE_2D_ARRAY 表明是二维纹理
2.2 原始数据处理 - 贴图的规格化
1)将三通道图像转化成4通道图像
- 读入Image图像,此为RGB格式的数据结构,要追加 α \alpha α通道形成四通道图像:
from PIL import Image
image = Image.open("textures/cat.png")
image = image.transpose(Image.FLIP_TOP_BOTTOM)
img_data = image.convert("RGBA").tobytes()
2)PIL.image.convert有九种不同模式:
convert参数 | 意义 |
---|---|
1: | 1位像素,黑白,每字节一个像素存储 |
L: | 8位像素,黑白 |
P: | 8位像素,使用调色板映射到任何其他模式 |
RGB: | 3x8位像素,真彩色 |
RGBA: | 4x8位像素,带透明度掩模的真彩色 |
CMYK: | 4x8位像素,分色 |
YCbCr: | 3x8位像素,彩色视频格式 |
I: | 32位有符号整数像素 |
F: | 32位浮点像素 |
示例:将彩色转成黑白:
image_1 = image.convert('1')
image_1.show()
三、纹理对象生成和绑定(选中)
3.1 生成纹理矩阵
通过纹理数组,可以将几个2D图像加载到一个单独的纹理对象中,然后在着色器中对它们进行检索,这样就大大增加了着色器可用的纹理数据数量;
对于2D纹理数组来说,和其正常创建和绑定纹理相似只是改变了target参数;
GLuint Texture;
glGenTextures(1,&Texture);
glBindTexture(GL_TEXTURE_2D_ARRAY,Texture);
3.2 glGenTextures 函数明细
glGenTextures 返回纹理中的 n 个纹理名称。不能保证名称形成一组连续的整数;但是,可以保证在调用 glGenTextures 之前没有立即使用返回的名称。
- 生成的纹理没有维度;它们假定它们首先绑定到的纹理目标的维度(参见 glBindTexture)。
- 后续调用不会返回调用 glGenTextures 返回的纹理名称,除非首先使用 glDeleteTextures 删除它们。
GLuint Texture;
glGenTextures(10,&Texture);
Signature
- c++ 程序:void glGenTextures( GLsizei ( n ) , GLuint * ( textures ) )
- python程序:textures=glGenTextures( n )
参数描述
n : 要生成纹理对象的个数.
textures : 生成的纹理句柄
3.2 glBindTexture函数明细
- 该函数选中纹理之一,作为当前使用纹理
glBindTexture 允许您创建或使用命名纹理。调用 glBindTexture 并将目标设置为 GL_TEXTURE_1D 、 GL_TEXTURE_2D 、 GL_TEXTURE_3D 、 GL_TEXTURE_1D_ARRAY 、 GL_TEXTURE_2D_ARRAY 、 GL_TEXTURE_RECTANGLE 、 GL_TEXTURE_CUBE_MAP 、 GL_TEXTURE_CUBE_MAP_ARRAY 、 GL_TEXTURE_BUFFER 、 TEXTURE_2D_MULTISAMPLE 或 GL_TEXTURE_2D_MULTISAMPLE_ARRAY 和设置为新纹理名称的纹理会将纹理名称绑定到目标。当纹理绑定到目标时,该目标的先前绑定将自动中断。
纹理名称是无符号整数。保留值零来表示每个纹理目标的默认纹理。纹理名称和对应的纹理内容是当前GL渲染上下文的共享对象空间本地的;仅当两个渲染上下文通过适当的 GL windows 接口函数显式启用上下文之间的共享时,它们才共享纹理名称。 - 您必须使用 glGenTextures 生成一组新的纹理名称。
当纹理第一次绑定时,它假定指定的目标:首先绑定到 GL_TEXTURE_1D 的纹理成为一维纹理,首先绑定到 GL_TEXTURE_2D 的纹理成为二维纹理,首先绑定到 GL_TEXTURE_3D 的纹理成为三维纹理,首先绑定到 GL_TEXTURE_1D_ARRAY 的纹理成为一维数组纹理,首先绑定到 GL_TEXTURE_2D_ARRAY 的纹理成为二维数组纹理,首先绑定到 GL_TEXTURE_RECTANGLE 的纹理成为矩形纹理,首先绑定到 GL_TEXTURE_CUBE_MAP 的纹理成为立方体映射纹理,首先绑定到 GL_TEXTURE_CUBE_MAP_ARRAY 的纹理将成为立方体映射数组纹理,首先绑定到GL_TEXTURE_BUFFER 的纹理将成为缓冲区纹理,首先绑定到 GL_TEXTURE_2D_MULTISAMPLE 的纹理将成为二维多重采样纹理,并且首先绑定到 GL_TEXTURE_2D_MULTISAMPLE_ARRAY 的纹理将成为二维多重采样纹理数组纹理。一维纹理在第一次绑定后的状态相当于 GL 初始化时默认 GL_TEXTURE_1D 的状态,对于其他纹理类型也是如此。
函数规格:
C++函数格式: - glBindTexture( GLenum ( target ) , GLuint ( texture ) )-> void
python函数格式: - glBindTexture( target , texture )
- glBindTextures( first , count , textures )
当纹理被绑定时,对其绑定的目标的 GL 操作会影响绑定的纹理,并且对其绑定的目标的查询会从绑定的纹理返回状态。实际上,纹理目标成为当前绑定到它们的纹理的别名,纹理名称零指的是在初始化时绑定到它们的默认纹理。
使用 glBindTexture 创建的纹理绑定保持活动状态,直到将不同的纹理绑定到同一目标,或者直到使用 glDeleteTextures 删除绑定的纹理。
创建后,命名纹理可以根据需要经常重新绑定到其相同的原始目标。使用 glBindTexture 将现有命名纹理绑定到纹理目标之一通常比使用 glTexImage1D 、 glTexImage2D 、 glTexImage3D 或其他类似函数重新加载纹理图像要快得多。
四、glTexParameteri函数
设置纹理包裹参数,什么意思?
部分参数功能说明如下:
4.1 贴放放法参数确定
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
GL_TEXTURE_2D: 操作2D纹理.
GL_TEXTURE_WRAP_S: S方向上的贴图模式.
GL_CLAMP: 将纹理坐标限制在0.0,1.0的范围之内.如果超出了会如何呢.不会错误,只是会边缘拉伸填充.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
这里同上,只是它是T方向
4.2 放大缩小插值方法参数确定
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 这是纹理过滤
GL_TEXTURE_MAG_FILTER: 放大过滤
GL_LINEAR: 线性过滤, 使用距离当前渲染像素中心最近的4个纹素加权平均值.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
GL_TEXTURE_MIN_FILTER: 缩小过滤
GL_LINEAR_MIPMAP_NEAREST: 使用GL_NEAREST对最接近当前多边形的解析度的两个层级贴图进行采样,然后用这两个值进行线性插值.
void glTexParameterfv(GLenum target, GLenum pname, const GLfloat * params);
void glTexParameteriv(GLenum target, GLenum pname, const GLint * params);
void glTexParameterIiv(GLenum target, GLenum pname, const GLint * params);
void glTexParameterIuiv(GLenum target, GLenum pname, const GLuint * params);
- target
- 规定纹理格式,必须是下列之一:
GL_TEXTURE_1D,
GL_TEXTURE_2D,
GL_TEXTURE_3D,
GL_TEXTURE_1D_ARRAY,
GL_TEXTURE_2D_ARRAY,
GL_TEXTURE_RECTANGLE,
GL_TEXTURE_CUBE_MAP. - pname
- 指定纹理参数的符号名称。 pname可以是以下之一。
GL_DEPTH_STENCIL_TEXTURE_MODE,
GL_TEXTURE_BASE_LEVEL,
GL_TEXTURE_BORDER_COLOR,
GL_TEXTURE_COMPARE_FUNC,
GL_TEXTURE_COMPARE_MODE,
GL_TEXTURE_LOD_BIAS,
GL_TEXTURE_MIN_FILTER,
GL_TEXTURE_MAG_FILTER,
GL_TEXTURE_MIN_LOD,
GL_TEXTURE_MAX_LOD,
GL_TEXTURE_MAX_LEVEL,
GL_TEXTURE_SWIZZLE_R,
GL_TEXTURE_SWIZZLE_G,
GL_TEXTURE_SWIZZLE_B,
GL_TEXTURE_SWIZZLE_A,
GL_TEXTURE_SWIZZLE_RGBA,
GL_TEXTURE_WRAP_S,
GL_TEXTURE_WRAP_T,
GL_TEXTURE_WRAP_R.
params
Specifies a pointer to an array where the value or values of pname are stored.
params 提供了一个用于缩小纹理的函数,如下所示:
参数 | 意义 |
---|---|
GL_NEAREST | 返回最接近(以曼哈顿距离)正在纹理化的像素中心的纹理元素的值。 |
GL_LINEAR | 返回最接近纹理像素中心的四个纹理元素的加权平均值。这些可以包括边框纹理元素,具体取决于 GL_TEXTURE_WRAP_S 和 GL_TEXTURE_WRAP_T 的值以及确切的映射。 |
GL_NEAREST_MIPMAP_NEAREST | 选择与纹理像素大小最匹配的 mipmap,并使用 GL_NEAREST 标准(最接近像素中心的纹理元素)来生成纹理值。 |
GL_LINEAR_MIPMAP_NEAREST | 选择与纹理像素大小最匹配的 mipmap,并使用 GL_LINEAR 标准(最接近像素中心的四个纹理元素的加权平均值)来生成纹理值。 |
GL_NEAREST_MIPMAP_LINEAR | 选择与纹理像素大小最匹配的两个 mipmap,并使用 GL_NEAREST 标准(最接近像素中心的纹理元素)从每个 mipmap 生成纹理值。最终纹理值是这两个值的加权平均值。 |
GL_LINEAR_MIPMAP_LINEAR | 选择与纹理像素大小最匹配的两个 mipmap,并使用 GL_LINEAR 标准(最接近像素中心的四个纹理元素的加权平均值)从每个 mipmap 生成纹理值。最终纹理值是这两个值的加权平均值。 |
五、一段参考代码
下面代码演示生成一个2d纹理贴图的过程:
5.1 顶点着色器
#version 330 core
layout (location=0) in vec3 vertexPos;
layout (location=1) in vec3 vertexColor;
layout (location=2) in vec2 vertexTexCoord;
out vec3 fragmentColor;
out vec2 fragmentTexCoord;
void main()
{
gl_Position = vec4(vertexPos, 1.0);
fragmentColor = vertexColor;
fragmentTexCoord = vertexTexCoord;
}
5.2 片段着色器
#version 330 core
in vec3 fragmentColor;
in vec2 fragmentTexCoord;
out vec4 color;
uniform sampler2D imageTexture;
void main()
{
color = 0.4*vec4(fragmentColor, 1.0) + 0.6*texture(imageTexture, fragmentTexCoord);
}
5.3 OpenGL代码
GLuint Texture;
texture = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texture)
# Set the texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
# Set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
# load image
image = Image.open("textures/cat.png")
image = image.transpose(Image.FLIP_TOP_BOTTOM)
img_data = image.convert("RGBA").tobytes()
# img_data = np.array(image.getdata(), np.uint8) # second way of getting the raw image data
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width, image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img_data)
glUseProgram(shader)
glClearColor(0, 0.1, 0.1, 1)
glEnable(GL_DEPTH_TEST)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
六、glTexImage2D函数
void glTexImage2D( GLenum target,
GLint level,
GLint internalformat,
GLsizei width,
GLsizei height,
GLint border,
GLenum format,
GLenum type,
const void * data);
此函数按照图像格式,以及给出的种种条件,生成纹理图像。此纹理允许着色器读取图像数组的元素。
要定义纹理图像,请调用 glTexImage2D。这些参数描述了纹理图像的参数,例如高度、宽度、边框宽度、细节级别编号(请参阅 glTexParameter)以及提供的颜色分量的数量。最后三个参数描述了图像在内存中的表示方式。
纹理允许着色器读取图像数组的元素。也就是片段着色器的像素坐标与图片的重叠部分。
6.1 函数描述
要定义纹理图像,请调用 glTexImage2D。这些参数描述了纹理图像的参数,例如高度、宽度、边框宽度、细节级别编号(请参阅 glTexParameter)以及提供的颜色分量的数量。最后三个参数描述了图像在内存中的表示方式。
void glTexImage2D( GLenum target,
GLint level,
GLint internalformat,
GLsizei width,
GLsizei height,
GLint border,
GLenum format,
GLenum type,
const void * data);
6.2 参数解释
参数描述
-
target
指定目标纹理。必须是: GL_TEXTURE_2D, GL_PROXY_TEXTURE_2D, GL_TEXTURE_1D_ARRAY, GL_PROXY_TEXTURE_1D_ARRAY, GL_TEXTURE_RECTANGLE, GL_PROXY_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, or GL_PROXY_TEXTURE_CUBE_MAP. -
level
指定详细级别编号。级别 0 是基础图像级别。 n 级是第 n 个 mipmap 缩小图像。如果目标纹理是 GL_TEXTURE_RECTANGLE
GL_PROXY_TEXTURE_RECTANGLE,
level 必须是 0.
- internalformat
指定纹理中颜色分量的数量。必须是表 1 中给出的基本内部格式之一、表 2 中给出的大小内部格式之一或下表 3 中给出的压缩内部格式之一。
internalformat参数 | 意义 |
---|---|
GL_RED | 每个元素都是一个红色组件。 GL 将其转换为浮点,并通过为绿色和蓝色附加 0、为 Alpha 附加 1 将其组装成 RGBA 元素。每个分量都被限制在 [0,1] 范围内。 |
GL_RG | 每个元素都是红/绿双色。 GL 将其转换为浮点型,并通过附加 0(表示蓝色)和 1(表示 alpha)将其组装成 RGBA 元素。每个分量都被限制在 [0,1] 范围内。 |
GL_RGB, GL_BGR | 每个元素都是一个 RGB 三元组。 GL 将其转换为浮点,并通过为 alpha 附加 1 将其组装成 RGBA 元素。每个分量都被限制在 [0,1] 范围内。 |
GL_RGBA, GL_BGRA | 每个元素包含所有四个组件。每个分量都被限制在 [0,1] 范围内。 |
GL_DEPTH_COMPONENT | 每个元素都是一个深度值。 GL 将其转换为浮点数并限制在 [0,1] 范围内。 |
GL_DEPTH_STENCIL | 每个元素都是一对深度和模板值。该对的深度分量被解释为 GL_DEPTH_COMPONENT。模板组件根据指定的深度+模板内部格式进行解释。 |
-
width
指定纹理图像的宽度。所有实现都支持至少 1024 纹理像素宽的纹理图像。 -
height
在 GL_TEXTURE_1D_ARRAY 和 GL_PROXY_TEXTURE_1D_ARRAY 目标的情况下,指定纹理图像的高度或纹理数组中的层数。所有实现都支持至少 1024 纹理像素高的 2D 纹理图像以及至少 256 层深的纹理数组。 -
border
必须是 0. -
format
指定像素数据的格式。接受以下符号值: GL_RED, GL_RG, GL_RGB, GL_BGR, GL_RGBA, GL_BGRA, GL_RED_INTEGER, GL_RG_INTEGER, GL_RGB_INTEGER, GL_BGR_INTEGER, GL_RGBA_INTEGER, GL_BGRA_INTEGER, GL_STENCIL_INDEX, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL. -
type
指定像素数据的数据类型。接受以下符号值:GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, GL_UNSIGNED_INT, GL_INT, GL_HALF_FLOAT, GL_FLOAT, GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, and GL_UNSIGNED_INT_2_10_10_10_REV. -
data
内存中图像的指针.
6.3 其它限制
-
如果目标是 GL_PROXY_TEXTURE_2D、GL_PROXY_TEXTURE_1D_ARRAY、GL_PROXY_TEXTURE_CUBE_MAP 或 GL_PROXY_TEXTURE_RECTANGLE,则不会从数据中读取任何数据,但会重新计算所有纹理图像状态,检查一致性,并根据实现的功能进行检查。如果实现无法处理所请求纹理大小的纹理,则会将所有图像状态设置为 0,但不会生成错误(请参阅 glGetError)。要查询整个 mipmap 数组,请使用大于或等于 1 的图像数组级别。
-
如果目标是 GL_TEXTURE_2D、GL_TEXTURE_RECTANGLE 或 GL_TEXTURE_CUBE_MAP 目标之一,则从 data 中读取数据作为有符号或无符号字节、短整型或长整型或单精度浮点值的序列,具体取决于类型。根据格式,这些值被分组为一个、两个、三个或四个值的集合,以形成元素。每个数据字节被视为八个 1 位元素,位顺序由 GL_UNPACK_LSB_FIRST 确定(请参阅 glPixelStore)。
-
如果目标是GL_TEXTURE_1D_ARRAY,则数据被解释为一维图像的数组。
-
如果在指定纹理图像时将非零命名缓冲区对象绑定到 GL_PIXEL_UNPACK_BUFFER 目标(请参阅 glBindBuffer),则数据将被视为缓冲区对象数据存储中的字节偏移量。
-
第一个元素对应于纹理图像的左下角。后续元素从左到右穿过纹理图像最低行中的剩余纹理像素,然后依次进入纹理图像的较高行中。最后一个元素对应于纹理图像的右上角。
6.4 补充描述
-
1 如果目标是 GL_PROXY_TEXTURE_2D、GL_PROXY_TEXTURE_1D_ARRAY、GL_PROXY_TEXTURE_CUBE_MAP 或 GL_PROXY_TEXTURE_RECTANGLE,则不会从数据中读取任何数据,但会重新计算所有纹理图像状态,检查一致性,并根据实现的功能进行检查。如果实现无法处理所请求纹理大小的纹理,则会将所有图像状态设置为 0,但不会生成错误(请参阅 glGetError)。要查询整个 mipmap 数组,请使用大于或等于 1 的图像数组级别。
-
2 如果目标是 GL_TEXTURE_2D、GL_TEXTURE_RECTANGLE 或 GL_TEXTURE_CUBE_MAP 目标之一,则从 data 中读取数据作为有符号或无符号字节、短整型或长整型或单精度浮点值的序列,具体取决于类型。根据格式,这些值被分组为一个、两个、三个或四个值的集合,以形成元素。每个数据字节被视为八个 1 位元素,位顺序由 GL_UNPACK_LSB_FIRST 确定(请参阅 glPixelStore)。
-
3 如果目标是GL_TEXTURE_1D_ARRAY,则数据被解释为一维图像的数组。
-
4 如果在指定纹理图像时将非零命名缓冲区对象绑定到 GL_PIXEL_UNPACK_BUFFER 目标(请参阅 glBindBuffer),则数据将被视为缓冲区对象数据存储中的字节偏移量。
-
5 纹理图像的第一个元素,对应于纹理图像的左下角。后续元素从左到右穿过纹理图像最低行中的剩余纹理像素,然后依次进入纹理图像的较高行中。最后一个元素对应于纹理图像的右上角。
format:格式决定了数据中每个元素的组成。它可以采用以下符号值之一:
GL_RED
Each element is a single red component. The GL converts it to floating point and assembles it into an RGBA element by attaching 0 for green and blue, and 1 for alpha. Each component is clamped to the range [0,1].
GL_RG
Each element is a red/green double. The GL converts it to floating point and assembles it into an RGBA element by attaching 0 for blue, and 1 for alpha. Each component is clamped to the range [0,1].
GL_RGB, GL_BGR
Each element is an RGB triple. The GL converts it to floating point and assembles it into an RGBA element by attaching 1 for alpha. Each component is clamped to the range [0,1].
GL_RGBA, GL_BGRA
Each element contains all four components. Each component is clamped to the range [0,1].
GL_DEPTH_COMPONENT
Each element is a single depth value. The GL converts it to floating point and clamps to the range [0,1].
GL_DEPTH_STENCIL
Each element is a pair of depth and stencil values. The depth component of the pair is interpreted as in GL_DEPTH_COMPONENT. The stencil component is interpreted based on specified the depth + stencil internal format.
internalformat:
Base Internal Format | RGBA, Depth and Stencil Values | Internal Components |
---|---|---|
GL_DEPTH_COMPONENT | Depth | D |
GL_DEPTH_STENCIL | Depth, Stencil | D, S |
GL_RED | Red | R |
GL_RG | Red, Green | R, G |
GL_RGB | Red, Green, Blue | R, G, B |
GL_RGBA | Red, Green, Blue, Alpha | R, G, B, A |
至此,纹理图像生成了。
七、纹理对象调用过程总结
总之,贴图的步骤共有三个:
1)OpenGL准备外部图片,并转化成GPU纹理对象。
2)顶点着色器引进纹理坐标,并传递给片元着色器。
3)片元着色器将上述元数据解构成像素颜色。
下面用代码实际解释。
7.1 顶点着色器作用
顶点着色器明确地规定,该顶点对应贴图的哪个位置,下面以三角形图元为例:
- 顶点着色器提供ST坐标,纹理坐标
7.2 片元着色器作用
片元着色器是一个像素生成环节,它是一个加工厂,原料:
- 顶点着色器提供ST坐标,纹理坐标。
- 来自客户端的纹理对象。
上图表示,假如一个图元是个三角形,片段着色器将取出与这个两个区域的交集:
区域1:三角形图元区域
区域2: glTexImage2D生成的区域。
7.3 OpenGL的作用
用于生成片元可调用的纹理图:
1)通过 glTexImage2D生成的区域,提供给片元着色器的uniform sampler2D变量
2)uniform sampler2D的调用可以默认,因此无显式调用过程。
3)如果有放大缩小纹理,可调用glGenerateMipmap(GL_TEXTURE_2D)
4)如果纹理很多,可用 glActiveTexture(GL_TEXTURE0)切换。
八、后记
本文前半部分来自手册理解,后半部分解释一个调用实例,试图解释OpenGL的纹理使用过程,只是一个粗略理解,如果有新的知识,本文将系列地给出解释。