在本章之前说过,WebGL可以同时处理多幅纹理,纹理单元就是为了这个目的而设 计的。之前的示例程序都只用到了一幅纹理,也只用到了一个纹理单元。这一节的示例 程序MultiTexture来在矩形上重叠粘贴两幅纹理图像。通过本例,你可以进一- 步了解纹 理单元的机制。图5.34显示了MultiTexture的运行效果,两张纹理图像在矩形.上的混合 效果如下。
加载的相关代码
const FSHADER_SOURCE = `
// 指定精度,书上的例子会编译报错, 参考 https://stackoverflow.com/a/27067272
precision mediump float;
varying vec4 v_Color;
uniform sampler2D u_Sampler0;
uniform sampler2D u_Sampler1;
varying vec2 v_TexCoord;
void main() {
vec4 color0 = texture2D(u_Sampler0, v_TexCoord);
vec4 color1 = texture2D(u_Sampler1, v_TexCoord);
// 两个vec4颜色变量相乘
gl_FragColor = color0 * color1;
}
`;
// 标记纹理单元是不是就绪
let g_texUnit0 = false;
let g_texUnit1 = false;
const flags = { g_texUnit0, g_texUnit1 };
export function initTextures_Ch5_4(gl: WebGLRenderingContext, n: number) {
// 创建纹理对象
const texture0 = gl.createTexture()!;
const texture1 = gl.createTexture()!;
const image0 = new Image();
image0.onload = () => {
// 图像加载完成处理纹理
// 获取uniform存储位置
const u_Sampler0 = gl.getUniformLocation(gl.program, 'u_Sampler0')!;
loadTexture_Ch5_4(gl, n, u_Sampler0, texture0, image0, 0);
};
image0.src = '/images/sky.jpg';
const image1 = new Image();
image1.onload = () => {
// 图像加载完成处理纹理
const u_Sampler1 = gl.getUniformLocation(gl.program, 'u_Sampler1')!;
loadTexture_Ch5_4(gl, n, u_Sampler1, texture1, image1, 1);
};
image1.src = '/images/circle.gif';
}
function loadTexture_Ch5_4(
gl: WebGLRenderingContext, n: number, u_Sampler: WebGLUniformLocation,
texture: WebGLTexture, image: HTMLImageElement, texUnit: number,
) {
//对纹理图像y轴反转
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
// 激活纹理
if (texUnit === 0) {
// 开启0号纹理单元
gl.activeTexture(gl.TEXTURE0);
flags.g_texUnit0 = true;
} else {
// 开启1号纹理单元
gl.activeTexture(gl.TEXTURE1);
flags.g_texUnit1 = true;
}
// 向target绑定纹理对象
gl.bindTexture(gl.TEXTURE_2D, texture);
// 配置纹理参数
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
// 配置纹理图像
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
// 将0号纹理传给着色器
gl.uniform1i(u_Sampler, texUnit);
console.log('loadtexture', texture);
if (flags.g_texUnit0 && flags.g_texUnit1) {
// 清空canvas
gl.clear(gl.COLOR_BUFFER_BIT);
//绘制点
gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);
}
console.log('loadTexture_Ch5_4',flags);
}