多幅纹理映射

返回首页

使用多幅纹理

在本章之前说过,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);
}