attribute vec4 gl_MultiTexCoord0; attribute vec4 gl_MultiTexCoord1; attribute vec4 gl_MultiTexCoord2; attribute vec4 gl_MultiTexCoord3; attribute vec4 gl_MultiTexCoord4; attribute vec4 gl_MultiTexCoord5; attribute vec4 gl_MultiTexCoord6; attribute vec4 gl_MultiTexCoord7;GLSL还为访问每个纹理的纹理矩阵提供了一个一致变量数组:
uniform mat4 gl_TextureMatrix[gl_MaxTextureCoords];顶点shader可以通过上面所示的内容访问OpenGL程序中指定的纹理坐标。然后必须为每个顶点计算纹理坐标,并保存在预先定义的易变变量gl_TexCoord[i]中,i表示纹理单元号。
gl_TexCoord[0] = gl_MultiTexCoord0;下面是个简单的例子,在顶点shader中设置纹理单元0的纹理坐标。
void main() { gl_TexCoord[0] = gl_MultiTexCoord0; gl_Position = ftransform(); }如果你想使用纹理矩阵,可以这样操作:
void main() { gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; gl_Position = ftransform(); }前面说过,gl_TexCoord是一个易变变量,所以在片断shder中可以访问经过插值的纹理坐标。
uniform sampler2D tex;如果是1D或者3D的纹理,可以改成sampler1D和sampler3D。
vec4 texture2D(sampler2D, vec2);函数的返回值已经考虑了所有在OpenGL程序中定义的纹理设置,比如过滤、mipmap、clamp等。
uniform sampler2D tex; void main() { vec4 color = texture2D(tex,gl_TexCoord[0].st); gl_FragColor = color; }注意访问gl_TexCoord时选择子st的使用。在本教程前面关于数据类型和变量的讨论中说过,访问纹理坐标时可以使用如下选择子:s、t、p、q。(r因为和rgb选择子冲突而没有使用)
OpenGL允许我们通过多种方式将纹理颜色和片断颜色联合到一起。下表显示了RGBA模式时可用的联合方式:
GL_REPLACE | C = Ct | A = At |
GL_MODULATE | C = Ct*Cf | A = At*Af |
GL_DECAL | C = Cf * (1 – At) + Ct * At | A = Af |
varying vec3 lightDir,normal; void main() { normal = normalize(gl_NormalMatrix * gl_Normal); lightDir = normalize(vec3(gl_LightSource[0].position)); gl_TexCoord[0] = gl_MultiTexCoord0; gl_Position = ftransform(); }在片断shader中,光照得到的片断的颜色和alpha值在cf和af中分别计算。shader中剩余代码按照GL_MODULATE的公式计算:
varying vec3 lightDir,normal; uniform sampler2D tex; void main() { vec3 ct,cf; vec4 texel; float intensity,at,af; intensity = max(dot(lightDir,normalize(normal)),0.0); cf = intensity * (gl_FrontMaterial.diffuse).rgb + gl_FrontMaterial.ambient.rgb; af = gl_FrontMaterial.diffuse.a; texel = texture2D(tex,gl_TexCoord[0].st); ct = texel.rgb; at = texel.a; gl_FragColor = vec4(ct * cf, at * af); }Shader Designer的工程下载地址:
varying vec3 lightDir,normal; uniform sampler2D tex; void main() { vec3 ct,cf; vec4 texel; float intensity,at,af; intensity = max(dot(lightDir,normalize(normal)),0.0); cf = intensity * (gl_FrontMaterial.diffuse).rgb + gl_FrontMaterial.ambient.rgb; af = gl_FrontMaterial.diffuse.a; texel = texture2D(tex,gl_TexCoord[0].st) + texture2D(l3d,gl_TexCoord[0].st); ct = texel.rgb; at = texel.a; gl_FragColor = vec4(ct * cf, at * af); }效果如下:
genType smoothStep(genType edge0, genType edge1, genType x);如果x <= edge0结果是0,如果x >= edge1结果为1,如果edge0 < x < edge1结果在0和1之间进行Hermite插值。在本例中我们按如下方式调用:
varying vec3 lightDir,normal; uniform sampler2D tex,l3d; void main() { vec3 ct,cf,c; vec4 texel; float intensity,at,af,a; intensity = max(dot(lightDir,normalize(normal)),0.0); cf = intensity * (gl_FrontMaterial.diffuse).rgb + gl_FrontMaterial.ambient.rgb; af = gl_FrontMaterial.diffuse.a; texel = texture2D(tex,gl_TexCoord[0].st); ct = texel.rgb; at = texel.a; c = cf * ct; a = af * at; float coef = smoothstep(1.0,0.2,intensity); c += coef * vec3(texture2D(l3d,gl_TexCoord[0].st)); gl_FragColor = vec4(c, a); }Shader Designer的工程下载地址: