总要有人来改变世界的,为什么不能是你呢

WebGL编程指南案例解析之纹理叠加

复制代码
var vShader = `
    attribute vec4 a_Position;
    attribute vec2 a_TexCoord;
    varying vec2 v_TexCoord;
    void main(){
        gl_Position = a_Position;
        v_TexCoord = a_TexCoord;
    }
`;

var fShader = `
    //设定默认精度
    #ifdef GL_ES
    precision mediump float;
    #endif
    uniform sampler2D u_Sampler;
    uniform sampler2D u_Sampler1;
    varying vec2 v_TexCoord;
    void main(){
        vec4 color  = texture2D(u_Sampler,v_TexCoord);
        vec4 color1 = texture2D(u_Sampler1,v_TexCoord);
         gl_FragColor = color * color1;
    }
`;

function main(){
    //获取canvas元素
    var canvas = document.getElementById('webgl');

    //获取webgl上下文
    var gl = getWebGLContext(canvas);

    if(!gl){
        console.log('Failed to get the rendering context for WebGL!');
        return;
    }
    //初始化着色器
    if(!initShaders(gl,vShader,fShader)){
        console.log('Failed to initialize shaders.');
        return;
    }
    var n = initVertexBuffers(gl);
    if(n < 0){
        console.log('Failed to set the positions of the vertices!');
        return;
    }
    if(!initTextures(gl,n)){
        console.log('Failed to initialize textures.');
        return;
    }


    //用指定颜色填充webgl容器,就是设置背景
    gl.clearColor(0.4, 0.5, 0.0, 1.0);


    function initVertexBuffers(gl){
        var verticesTex =  new Float32Array([
            -0.5, 0.5, 0.0, 1.0,
            -0.5,-0.5, 0.0, 0.0,
             0.5, 0.5, 1.0, 1.0,
             0.5,-0.5, 1.0, 0.0
        ]);
        var n = 4;//点的个数
        //创建缓冲区对象
        var vertexTexBuffer = gl.createBuffer();
        if(!vertexTexBuffer){
            console.log('Failed to create the buffer object!');
            return -1;
        }
        //将数据添加到缓冲区(绑定在缓冲区对象上)
        gl.bindBuffer(gl.ARRAY_BUFFER,vertexTexBuffer);
        gl.bufferData(gl.ARRAY_BUFFER,verticesTex,gl.STATIC_DRAW);
        var fsize = verticesTex.BYTES_PER_ELEMENT;

        //获取shaderProgram中attribute变量‘a_Position’的地址
        var a_Position = gl.getAttribLocation(gl.program,'a_Position');
        if (a_Position < 0) {
            console.log('Failed to get the storage location of a_Position');
            return -1;
        }
        //将缓冲区对象分配给a_Position变量并开启访问
        gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,fsize * 4,0);
        gl.enableVertexAttribArray(a_Position);


        var a_TexCoord = gl.getAttribLocation(gl.program,'a_TexCoord');
        if (a_TexCoord < 0) {
            console.log('Failed to get the storage location of a_TexCoord');
            return -1;
        }
        //将缓冲区对象分配给a_TexCoord变量并开启访问
        gl.vertexAttribPointer(a_TexCoord,2,gl.FLOAT,false,fsize * 4,fsize * 2);
        gl.enableVertexAttribArray(a_TexCoord);

        return n;
    }


    //初始化纹理图片,通过image传入
    function initTextures(){
        //创建纹理对象
        var texture = gl.createTexture();
        var texture1 = gl.createTexture();

        //读取u_Sampler存储位置
        var u_Sampler = gl.getUniformLocation(gl.program,'u_Sampler');
        var u_Sampler1 = gl.getUniformLocation(gl.program,'u_Sampler1');

        var image = new Image(),image1 = new Image;

        image.onload = function(){
            loadTexture(gl,n,texture,u_Sampler,image,0);
        }
        image1.onload = function(){
            loadTexture(gl,n,texture1,u_Sampler1,image1,1);
        }

        image.src = '../image/sky.JPG';
        image1.src = '../image/circle.gif';

        return true;
    }
    var flag = false,flag1= false;
    //加载纹理
    function loadTexture(gl,n,texture,u_Sampler,image,index){
        //对问题图像进行y轴反转
        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1);
        //开启纹理单元
        if(index ==0){
            gl.activeTexture(gl.TEXTURE0);
            flag = true;
        }else{
            gl.activeTexture(gl.TEXTURE1);
            flag1 = true;
        }
        //向target绑定纹理对象
        gl.bindTexture(gl.TEXTURE_2D,texture);
        //配置纹理参数
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
        //处理图片像素非2的幂次方的配置
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);

        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

        //配置纹理图像
        gl.texImage2D(gl.TEXTURE_2D,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE,image);

        //将纹理传递给着色器
        gl.uniform1i(u_Sampler,index);

        if(flag && flag1){
            gl.clear(gl.COLOR_BUFFER_BIT);   // Clear <canvas>
              gl.drawArrays(gl.TRIANGLE_STRIP, 0, n); 
        }

    }
}


main();
复制代码

相对于之前的为正方形添加单个纹理来说,多了一些变化,文中已经用红字标出:

①片元着色器中新增一个取样器,并且main方法输出的颜色是这两个取色器颜色的乘积;

②用两个纹理对象来加载纹理,并且启用不同的纹理单元(gl.TEXTURE0、gl.TEXTURE1);配置好参数后将纹理传递给对应的纹理单元

③在两个纹理都激活之后才开始绘图

效果:

 

posted @   桔子桑  阅读(894)  评论(0)    收藏  举报
编辑推荐:
· 记录一次线上问题排查:JDK序列化问题
· 微服务之间有哪些调用方式?
· 记一次SQL隐式转换导致精度丢失问题的排查
· dotnet 9 通过 AppHostRelativeDotNet 指定自定义的运行时路径
· 如何统计不同电话号码的个数?—位图法
阅读排行:
· EF Core 10 现已支持 LeftJoin 和 RightJoin 运算符查询了!
· C#/.NET/.NET Core技术前沿周刊 | 第 36 期(2025年4.21-4.27)
· 为什么多智能体不会成功?
· Python 3.14 t-string 要来了,它与 f-string 有何不同?
· 上周热点回顾(4.21-4.27)
历史上的今天:
2018-04-10 Yii2表单提交(带文件上传)
点击右上角即可分享
微信分享提示