OpenGL着色语言对深度学习应用开发的可能性有多大

OpenGL 着色语言 (Shader Language) | 猎数博客
数据挖掘,机器学习
OpenGL 着色语言 (Shader Language)
(阅读 7,140 次)
顶点着色器实例:
模拟重力加速度,对每个点的坐标进行了变换
#version 130
uniform float
attribute vec4
const vec4 g = vec4(0.0,-9.8,0.0) ;
void main()
vec4 position=gl_V
position += t*vel
gl_Position = gl_ModelViewProjectionMatrix *
同一程序的1.40版本
#version 140
uniform float
//time , passed in from the application
uniform mat4 MVP //combined modelview and projection matrices
const vec4 g = vec4(0.0,-9.8,0.0);
void main()
vec4 position =
position += t*vel + t* t*
gl_Position = MVP *
类型限定符: in: 限定输入, out: 限定输出 uniform: 表示一个变量的值将由应用程序在该程序运行之前制定,并且在图元处理过程中不会发生变化。在Shader被绑定后,应用程序可以通过API来修改uniform变量。
Shader中访问纹理: GLSL把一个在OpenGL应用程序中配置的活动纹理单元与Shader中一个变量关联。这个变量使用某种采样器数据类型。以下是几个采样器的数据类型:
sample1/2/3D , isampler1/2/3D , usampler1/2/3D, samplerCube
, sampler1/2DArray , sampler2DRect, sampler1/2DShader , sampler1/2DArrayShadow , sampler2DRectShadow ,
samplerBuffer . 采样器必须声明为uniform变量,并且他的赋值必须来自OpenGL应用程序, 采样器在shader中使用之前必须分配一个纹理单元,并且只能通过glUniformli ,
glUniformliv() 来进行初始化。
GLint texS
texSampler = glGetUniformLocation(program , “tex”);
glUniformli(texSampler,2) ; //set “tex” to use GL_TEXTURE2.
在GLSL中进行纹理采样:
uniform sample2D
void main {
gl_FragColor= gl_Color * texture2D(tex, gl_TexCoord[0].st);
指定输入:
glVertex* () , glNormal*()
uniform 变量,并且在程序绑定后更新uniform. (包含texsampler)
指定输出: 需要写入的输出包括 gl_Position. varying变量。 内置的属性输入变量: gl_Vertex , gl_Color , gl_SecondaryColor , gl_Normal , gl_MultiCoordn , gl_FogCoord (float) , gl_VertexId(int) , gl_InstanceID(int) .
用户定义的属性变量都是全局变量,程序(shader)中定义, varying vec3
可以在opengl中利用glGetAttribLocation(program, *name)来获得该属性的位置,然后利用glVertexAttrib* (index,values) 来更新属性值。
另外可以利用glBindAttribLocation来直接绑定属性变量与索引值,但是这个调用必须在shader链接以前进行。
同样的,可以利用glVertexAttribPointer来指定某属性的数组值。当然为了使用定点数组,必须先启用glEnableVertexAttribArray() 定点数组。
特殊的输出变量: gl_Position (经过变换的定点位置,视觉坐标系中) , gl_PointSize
, gl_ClipVertex
(用户定义的裁剪平面中使用的定点位置,这个值必须与裁剪平面使用一样的坐标系)
varying 输出变量: gl_FrontColor , gl_BackColor, glFrontSecondaryColor , gl_BackSecondaryColor , gl_TexCoordn , glFogFragCoord.
PS细节: 输入:
gl_FragCoord
, gl_FrontFacing , gl_color , gl_SecondColor , gl_TexCoord , gl_FogFragCoord , gl_PointCoord
gl_FragColor , gl_FragDepth , gl_FragData[n] (for MRT)
转载请注明
( 10,214 )( 7,246 )( 7,140 )( 6,177 )( 2,819 )( 2,733 )( 2,641 )( 2,535 )( 2,314 )( 2,197 )OpenGL学习笔记——OpenGL着色语言 - 推酷
OpenGL学习笔记——OpenGL着色语言
OpenGL图形管线和可编程着色器
除了固定功能的管线之外,OpenGL2.0还增加了一种“可编程着色管线”,可以用小型程序控制顶点和片断的处理。这种小型程序是用OpenGL着色语言编写的。在应用程序中,既可以使用固定功能的管线处理数据,也可以使用可编程着色管线处理数据,但是不能同时兼用两者。使用着色器进行数据处理时,对应的固定功能的管线就被禁用。
顶点处理 当OpenGL使用固定功能的管线处理顶点时,它负责提供下面这些值,用于后面的光栅化处理:
视觉空间坐标
主颜色和辅助颜色
根据应用程序启用的特性,顶点管线可能不会对上面所有的值进行更新。这些值都是应用程序根据glVertex*()和其他顶点数据调用所输入的数据进行计算的。 并不是顶点管线中所有的操作都可以由顶点着色器代替。在执行着色器之后,下面的操作依然会出现,就像之前的顶点处理是由固定功能的管线完成的那样。
平截头体(视景体)和用户裁剪
双面光照选择
多边形模式处理
多边形偏移
深度范围截取
片断处理 与顶点着色器类似,片断着色器可以接管部分片断处理功能。片断着色器可以处理的功能包括:
提取纹理单元,用于纹理贴图
主颜色和辅助颜色的混合
无论是否使用片断着色器,OpenGL总会执行下面的操作:
单调或平滑着色(控制片断之间的插值)
像素覆盖计算
像素所有权测试
点画模式应用
对像素进行逻辑操作
颜色值的抖动
颜色掩码操作
使用GLSL着色器
OpenGL/GLSL接口 编写OpenGL程序所使用的着色器类似于使用基于编译器的语言编写程序。我们需要编译器来分析程序,检查它存在的错误,并把它转换为目标代码。接着,在链接阶段,链接器把一组目标文件组合在一起,形成一个可执行程序。在OpenGL程序中使用GLSL着色器是一个类似的过程,只不过编译器和链接器是OpenGL的驱动程序的一部分。 如果想要使用顶点或片断着色器,需要按照下面的步骤执行: 对每个着色器对象:
创建一个着色器对象
把着色器源代码编译为目标代码
验证这个着色器已成功通过编译
然后,为了把多个着色器对象链接到一个着色器程序中,需要:
创建一个着色器程序;
把适当的着色器对象链接到这个着色器程序中;
链接着色器程序;
验证着色器链接阶段已经成功完成;
使用着色器进行顶点或片断处理。
OpenGL着色语言
程序起点 着色器程序就像C程序一样,是从main()函数开始执行的。
声明变量 GLSL是一种强类型语言。
类似IEEE的浮点值
有符号整型值
无符号的整型值
GLSL还提供了额外的类型,称为采样器,作为访问纹理图像的不透明句柄。
变量的作用域 所有的变量都必须进行声明,在所有函数定义之外声明的变量具有全局作用域,它们在着色器程序的所有函数中均可见。
变量的初始化 整型常量可以用八进制、十进制或十六进制来表示。后面有一个“u”或“U”,表示是一个无符号整型值。
构造函数 不同类型的值不存在隐式类型转换。
聚合类型 GLSL的3种基本类型可以进行组合,更好地与OpenGL的数据值相匹配,并且能够简化计算方法。 首先,GLSL支持每种基本类型的二维、三维或四维向量。另外,它还支持2x2、3x3和4x4的浮点矩阵。
mat2, mat3, mat 4, mat2x2, mat2x3...
矩阵类型列出了所有各维,例如mat4x3,第一个值指定了列的数量,第二个值指定了行的数量。
访问向量和矩阵中的元素 可以对向量和矩阵中的单独元素进行访问和赋值。向量提供了两种类型的访问方式,名称成分方法和类似数组的方法。
成分访问名称
(x, y, z, w)
与位置相关的成分
(r, g, b, a)
与颜色相关的成分
(s, t, p, q)
与纹理坐标相关的成分
结构 可以在一个结构中把一组不同的类型从逻辑上组合在一起。结构可以方便地把一组相关的数据传递给函数。
数组 GLSL支持任何类型的一维数组,包括结构。
类型限定符 类型也可以使用限定符,对它们的行为进行限定。GLSL定义了4中限定符。
类型限定符
把变量标记为只读的编译期常量
指定变量为着色器阶段的一个输入
指定变量为着色器阶段的一个输出
指定这个值从应用程序传递给着色器,并在一个特定的图元中保持为常量值
所有的存储类型限定符都适用于全局作用域的变量。另外,const还适用于局部变量和函数的形参。
const类型限定符 表示变量是只读的。
in类型限定符 限定一个着色器阶段的输入。这些输入可能是顶点属性(用于顶点着色器),或者是插值变量(用于片断着色器)。 片断着色器可以进一步限定其输入值,这要使用那些只有和in关键字组合使用才有效的额外关键字。
in关键字限定符
在打开多点采样的时候,强迫一个片断输入变量的采样位于图元像素覆盖的区域
以透视校正的方式插值片断输入变量
不对片断输入插值(例如,对于所有的片断,输入都是相同的,就像在单调着色中一样)
noperspetive
线性插值片断变量
out类型限定符 out限定符用来限定一个着色器阶段的输出,例如,来自一个顶点着色器的齐次坐标变换,或者来自一个片断着色器的最终片断颜色。 顶点着色器可以使用centroid关键字限定其输出值,该关键字在这里的含义与其对片断输入的含义相同。此外,centroid限定的任何顶点着色器输出,都必须有一个匹配的片断着色器输入也被centroid限定。
uniform类型限定符 uniform限定了表示一个变量的值将由应用程序在着色器执行之前指定,并且在图元的处理过程中不会发生变化。uniform变量是由顶点着色器和片断着色器共享的,它们必须声明为全局变量。任何类型的变量,包括结构和数组,都可以声明为uniform变量。 考虑这样一个着色器:它在对一个图元进行着色时使用了一种额外的颜色。可以声明一个uniform变量,把这个信息传递给着色器。在这个着色器中,可以声明下面的变量: uniform vec4 BaseC
在着色器内部,可以通过名字来引用BaseColor,但是为了在应用程序中设置它的值,需要做一些额外的工作。当GLSL编译器链接到着色器程序后,它会创建一个表格,其中包含了所有的uniform变量。为了在应用程序中设置BaseColor的值,需要获取BaseColor在表中的索引值。 uniform变量可以在制定的uniform块中声明,uniform块支持着色器的共享及其它功能。
随着着色器程序变得越来越复杂,它们用到的uniform变量的数目将会增加。经常会出现几个着色器程序中使用同一个uniform值的情况。由于在连接着色器的时候(例如,调用glLinkProgram()的时候)产生uniform位置,索引可能会变化,即便uniform变量的值是相同的。统一缓冲区对象提供了一种方法,既优化了uniform变量的访问,又使得可以跨着色器程序共享uniform值。
可以想象的到,给定的uniform变量在应用程序和着色器中都可以存在,我们既要修改着色器,也要使用OpenGL程序来设置统一缓冲区对象。
在着色器中指定uniform变量 要使用glMapBuffer()这样的程序来访问uniform变量的一个集合,需要在着色器中稍微修改一下它们的声明。在一个uniform块中,我们成组地声明uniform变量,而不是单独地声明每个uniform变量,这就像在结构中的做法一样。用uniform关键字指定一个uniform块。然后,用一对花括号把想要的所有变量都包含到一个块中。 所有的类型,除了采样器,都允许放到一个uniform块中。此外,uniform块必须声明为全局作用域。
uniform块布局控制 有各种限定符可以用来指定一个uniform块中如何布局变量。这些限定符可以针对每一个单个的uniform块使用,或者用来指定所有后续的uniform块如何安排(在指定一个布局声明之后)。
布局限定符
指定uniform块在多个程序之间共享(这是默认的共享设置)
布局uniform块以使其使用的内存最小化;然而,这通常不允许跨程序共享
为uniform块使用OpenGL规范中描述的默认布局
使得uniform块中的矩阵按照行主序的方式存储
column_major
指定矩阵应该按照列主序的方式存储(这是默认的排序)
访问在uniform块中声明的uniform变量 尽管命名了uniform块,在其中声明的uniform变量并没有被该名称所限定。也就是说,uniform块并不能作为一个uniform变量的作用域,因此,在两个uniform块中声明具有相同名称的两个变量将会导致错误。然而,访问一个uniform变量的时候,没必要使用uniform块的名字。
从应用程序中访问uniform块 由于uniform构成了一座桥梁,以便在着色器和应用程序之间共享数据,需要找到指定的uniform块中的各个uniform变量在着色器这种的偏移量。一旦知道了这些变量的位置,可以用数据把它们初始化,就像可以对任何类型的缓冲区对象所做的那样(例如,使用glBufferData()这样的调用)。 首先,假设已经知道了在应用程序的着色器中使用的uniform块的名字。初始化uniform块中uniform变量的第一步,是针对一个给定的程序获取块的索引。调用glGetUniformBlockIndex(),将返回完成把uniform变量映射到应用程序的地址空间所需的一段基本信息。 要初始化与uniform块相关的一个缓冲区对象,需要使用glBindBuffer()函数把缓冲区对象绑定到一个GL_UNIFORM_BUFFER目标。 一旦初始化了一个缓冲区对象,需要确定从着色器留出多大空间来容纳指定的uniform块中的变量。为了做到这一点,我们使用函数glGetActiveUniformBlockiv()来请求GL_UNIFORM_BLOCK_DATA_SIZE,它返回了编译器生成的块的大小(根据选择何种uniform块布局,编译器可能确定删除着色器中不使用的uniform变量)。 在获取了uniform块的索引之后,需要把一个帧缓冲区对象和该块联系起来。这么做的最常见的方法是调用glBindBufferRange(),或者,如果所有的缓冲区存储都用于存储uniform块,调用glBindBufferBase()。 一旦一个具名的uniform块和一个缓冲区对象建立了关联,可以使用会影响到缓冲区值的任何命令来初始化或修改该块中的值。 与允许连接器分配一个块绑定然后查询分配的值这一过程相比较,你可能也想指定把一个特定名称的uniform块绑定到一个缓冲区对象。如果有多个着色器程序要共享一个uniform块,可能要采用这个方法。它避免了为每个程序分配一个不同的块索引。要显式地控制一个uniform块的绑定,在调用glLinkProgram()之前调用glUniformBlockBinding()。 uniform变量在一个具名的uniform块中的布局,由指定的布局限定符来控制,而这在编译和链接uniform块的时候进行。如果使用默认的布局指定,需要确定uniform块中的每个变量的offset和数据存储size。为了做到这一点,我们将使用一对调用:调用glGetUniformIndices()获取一个特定的具名uniform变量的索引,调用glGetActiveUniformBlockiv()获取这个特定索引的offset和size。
计算不变性 GLSL并不保证不同的着色器中的两个相同的计算将产生完全相同的结果。这种情况与在CPU上执行的计算性应用程序并无不同。在计算性应用程序中,由于指令顺序的累积差别,编译后的指令顺序可能会产生微小的差别。有些多道渲染算法要求在每道着色器渲染时计算的位置完全相同,此时这些微小的错误就可能会造成问题。GLSL提供了一种方法,使用invariant关键字,强制在着色器之间实行这种类型的不变性。
invariant类型限定符
invariant限定符可以应用于顶点着色器的任何输出varying变量。这种变量可以是内置的变量,也可以是用户定义的变量。 varying变量用于把顶点着色器的数据传递给片断着色器。不变性变量必须在顶点和片断着色器中都声明为invariant。可以在着色器中使用变量之前的任何时候都能对它应用invariant关键字,并可以用它修改以前声明的变量。 为了便于调试,可以对着色器中的所有varying变量施加不变性限制。这可以通过使用顶点着色器预处理pragma指令来实现。 #pragma STDGL invariant(all)
按照这种方式使用的全局不变性就可以用于调试。但是,它可能会对着色器的性能产生影响。保证不变性通常会禁用GLSL编译器所执行的那些优化。
语句 着色器的真正工作是通过对值进行计算以及做出来的决策来完成的。和C++一样,GLSL提供了一组丰富的操作符,可以用于创建各种算数操作来计算各种值。另外,GLSL还包括了一组标准的逻辑结构,用于控制着色器的执行。
操作符与C++的操作符用法相同,实现了部分常用的操作符。
操作符重载
GLSL的绝大多数操作符都进行了重载。也就是说,它们可以对各种类型的数据进行操作。尤其是用于向量和矩阵操作的算术操作符(包括前缀和后缀形式的自增和自减操作),在GLSL中都经过了精心的定义。
GLSL仅有的逻辑控制结构就是if-then-else语句。从GLSL1.30开始,switch语句也可以使用了。
GLSL支持我们在C语言中所熟悉的for、while和do...while循环。
流控制语句
在GLSL中,除了条件和循环之外,还存在其他控制语句。
终止循环块的执行,并接着执行循环块之后的代码
终止当前的那次循环,然后继续执行下一次循环
return [result]
从当前的子程序(函数)返回,可以同时返回一个值(假定返回值与调用程序的返回类型匹配)
丢弃当前的片断并终止着色器执行。diacard语句只在片断着色器程序中有效
函数 函数允许使用一个函数调用来代替一段经常出现的代码,从而实现更短小精悍的代码,并减少了出错的机会。GLSL定义了一些内置的函数,此外,GLSL也支持用户定义的函数。用户定义的函数可以在单个着色器对象内部定义,并在多个着色器程序中使用。
声明 函数声明的语法与C语言非常相似,唯一的例外是变量的访问限定符。
参数访问限定符 虽然GLSL的函数可以修改数据并在执行完成后返回数据,但是它并不存在C和C++中指针或引用的概念。反之,函数的参数具有相关的访问限定符,表示这个值是否应该复制到函数中以及在函数完成执行后是否可以提取这个值。
访问限定符
值复制到函数中(如果未指定限定符,此为默认)
只读的值,复制到函数中
值从函数中复制出来(在传递给函数之前未初始化)
值复制到函数中,并从函数中复制出来
in关键字是可选的。如果变量没有包含访问限定符,那么,参数声明中隐式地添加了一个“in”限定符,然而,如果变量的值需要从一个函数中复制出来,它必须或者标记为一个“out”(用于只写的变量),或者一个“inout”(用于可读写的变量)。向不带这些限定符之一的一个变量写入,将会产生一个编译时错误。 此外,要在编译时验证一个函数不会修改一个仅输入的变量,添加一个“const in”修饰词将会引发编译器检查该变量在函数中没有被写入过。
在GLSL程序中使用OpenGL状态值 使用OpenGL API可以设置的所有值几乎都可以在顶点和片断着色器中访问。
在着色器中访问纹理图像
GLSL支持在顶点和片断着色器使用纹理图像。OpenGL实现可以选择是否在顶点着色器中使用纹理图像(只要底层的OpenGL实现支持这个功能),但是它必须在片断着色器中使用纹理图像。为了使用纹理图像,GLSL把一个在OpenGL应用程序中配置的活动纹理单元与着色器中的一个变量相关联。这个变量使用采样器数据类型之一,它允许着色器程序访问纹理图像的数据。相关的纹理图像的维数必须与采样器的类型相匹配。
采样器必须在着色器中声明uniform变量,并且它们的赋值必须来自OpenGL应用程序。采样器也可以作为函数的参数,但必须是类型匹配的采样器。
采样器在着色器中使用之前必须分配一个纹理单位,并且只能通过glUniformli()、glUniformliv()进行初始化(把采样器应该使用的纹理单位的索引作为参数)。
在GLSL中使用纹理 当在GLSL着色器内部对一幅纹理图像进行采样时,需要使用已经声明并与一个纹理单位相关联的采样器变量。可以使用一些与纹理相关的函数来访问OpenGL所支持的所有纹理图像类型。 即使纹理看上去很简单,实际上需要做的事情仍然很多。但是,在许多有趣的应用程序中,纹理图像中的数据并不一定用来表示颜色,应用程序可以把纹理图像的读取结果用于后续的计算中,尤其是当应用程序把一幅纹理图像的值作为索引来访问另一幅纹理图像的时候。同样的结果也可以使用组合器纹理环境来实现,但是用着色器来实现要简单的多。 对纹理进行采样之后所进行的计算是由在着色器中编写的代码控制的,但是纹理图像的采样方法仍然是由应用程序控制的。例如,可以控制一幅纹理图像是否包含mipmap层、这些mipmap层是如何进行采样的,以及用于解析返回纹理单元值(基本上是glTexParameter*()函数所设置的参数)的过滤器。在着色器内部,可以控制mipmap选择的偏移值,并使用投影纹理技巧。
依赖性纹理读取 在一个使用纹理贴图的着色器的执行过程中,需要使用纹理坐标在纹理图像中指定位置,并提取相应的纹理单元的值。纹理坐标是为每个活动纹理单位提供的,可以使用你所希望的任何值(前提是维数要匹配)来表示纹理坐标(包括刚刚从其他纹理图像采集的数据),供采样器使用。把一个纹理读取的结果作为索引值来读取另一个纹理的操作通常称为依赖性纹理读取,即第二个操作的结果依赖于第一个操作。
纹理缓冲区 尽管GLSL使得数组可用,不论是在着色器中用作静态初始化的值,还是作为值的集合呈现为uniform变量中的一个数组,在这两种情况下,我们都可能偶尔需要超出可用的大小限制的数组。在OpenGL3.1之前,我们可能把这样的一个值的表存储在一个纹理图像中,然后,在纹理中操作纹理坐标来访问想要的值,这通常不是太直接了当的方式。对于这一数据存储问题,另一个更加直接的解决方案是纹理缓冲区。纹理缓冲区是缓冲区对象的一种特定类型,类似于一维纹理,可以在着色器中使用一个整数值来索引,但是,它提供了较为昂贵的纹理内存的资源,因此也支持较大的数据集合。我们像创建任何其他的缓冲区对象那样,来创建一个纹理缓冲区。
着色器预处理器
编译GLSL着色器的第一个步骤是由预处理器进行解析。与C语言的预处理器相似,GLSL提供了一些指令,用于创建条件编译代码块以及定义一些值。但是,和C语言的预处理器不同,GLSL并没有提供文件包含指令。
预处理器指令
预处理器指令
#define #undef
控制常量和宏的定义
#if #ifdef #ifndef
条件代码管理,与C语言预处理器相似,包括defined操作符
#else #elif #endif
条件表达式,只对整型表达式和已定义的值(例如由#define指定)进行求值
#error text
使编译器在着色器信息日志中插入text(直到第一个换行符)
#pragma options
控制编译器的特定选项
#extension options
根据指定的GLSL扩展,指定编译器操作
#version number
强制要求支持一个特定版本的GLSL版本
#line options
控制诊断行的编号
宏定义 GLSL预处理器允许使用宏定义,它与C语言的预处理器所采用的方式极为相似,只是它并不提供字符串替换和连接工具。
预处理器条件
编译器控制 #pragma指令向编译器提供了关于希望如何对着色器进行编译的额外信息。
优化编译器选项 optinize选项指示编译器在着色器源文件中这条指令开始的位置开始启用或禁用着色器的优化。下面这两条命令分别用于启用和禁用优化。 #pragma optimize(on)
和 #pragma optimize(off) 这些选择只能在函数定义的外面使用。在默认情况下,所有着色器的优化选项都是启用的。
调试编译器选项 debug选项启用或禁用着色器的额外诊断输出。可以使用下面这两条指令分别启用或禁用调试: #pragma debug(on)
和 #pragma debug(off) 与optimize选项相似,这些选项只能在函数定义的外面使用。在默认请下,所有着色器的调试选项都是禁用的。
全局着色器编译选项 最后一条#pragma指令是STDGL。这个选项当前用于启用varying值输出的不变性。
和OpenGL一样,GLSL可以通过扩展进行增强。由于开发商可能会包含与它们的OpenGL实现特定的扩展,因此根据着色器可能使用的扩展,对着色器的编译施加一个控制是非常有用的。
GLSL预处理器使用#extension指令向着色器编译器提供指令,说明在编译器应该如何处理可用的扩展。对于任何扩展,可以指定编译器在编译时如何对它们进行处理。
顶点着色器的细节
可是使用如下几种机制把数据从应用程序发送到顶点着色器程序:
通过使用标准的OpenGL顶点数据接口(这些函数在glBegin()和glEnd()之间进行调用才是合法的),例如glVertex*()、glNormal*()等。这些值因顶点而已,被认为是内置的属性值;
通过声明uniform变量。这些值在几何图形中保持常量性质;
通过声明attribute变量,除了标准的顶点状态外,它们还可以根据顶点进行更新。
类似地,顶点着色器程序必须输出一些数据(还可以更新这些变量),以便OpenGL管线执行剩下的顶点处理操作。另外,顶点着色器程序常常和片断着色器程序一起执行。
需要写入的输出包括:
gl_position,它必须由顶点着色器程序进行更新,并包括顶点在进行模型视图变换和投影变换之后的齐次坐标;
其他各个声明为varying的内置变量,用于向片断管线传递数据。这些数据包括颜色、纹理坐标和其他基于片断的数据。它们将在稍后的“varying输出变量”中描述;
用户定义的varying变量。
内置的属性输入变量
用户定义的属性变量 用户定义的属性变量都是全局变量,与OpenGL应用程序传递给OpenGL实现内部执行的顶点着色器的值相关联。属性变量可以定义为float、float类型的向量(vec*)或矩阵(mat*)。 为了使用用户定义的属性变量,OpenGL需要知道如何把在着色器程序中指定的变量名与传递给着色器的值进行匹配。类似于OpenGL处理uniform变量的方式,当一个着色器程序被链接时,链接器会生成一个变量名表格,用于表示属性变量。为了确定用户定义的顶点属性的最大数量,可以用GL_MAX_VERTEX_ATTRIBS为参数调用glGetIntegerv()函数。
特殊输出变量
varying输出变量
顶点着色器中的纹理贴图
片断着色器
和顶点着色器一样,OpenGL应用程序也可以直接向片断着色器程序发送数据,并且让OpenGL在程序内部提供这些值。所有这些数据,包括输入到片断着色器的数据,用于产生片断的最终颜色和深度值。在执行片断着色器之后,经过计算所产生的值继续经过OpenGL的片断管线,进入片断测试和混合阶段。
特殊的输出值
渲染到多个输出缓冲区
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致}

我要回帖

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信