• webgl 模板缓冲


    先思考个问题, 想实现遮罩怎么办?

    <!doctype html>
    <html>
    <head>
    <meta charset="utf-8" />
    <title>Stencil Buffer</title>
    <script id="shader-vs" type="x-shader/x-vertex">
    precision highp float;
    attribute vec3 aPos;
    attribute vec4 aColor;
    varying vec4 vColor;
    void main(void){
        gl_Position = vec4(aPos, 1);
        vColor = aColor;
    }
    </script>
    <script id="shader-fs" type="x-shader/x-fragment">
    precision highp float;
    varying vec4 vColor;
    void main(void) {
        gl_FragColor = vColor;
    }
    </script>
    <script id="shader-vs-2" type="x-shader/x-vertex">
    precision highp float;
    attribute vec3 aPos;
    attribute vec2 aTextureCoords;
    varying vec2 vTextureCoord;
    void main(void){
        gl_Position = vec4(aPos, 1.0);
        vTextureCoord = aTextureCoords;
    }
    </script>
    <script id="shader-fs-2" type="x-shader/x-fragment">
    precision highp float;
    varying vec2 vTextureCoord;
    uniform sampler2D uSampler;
    void main(void) {
        gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
        if (gl_FragColor.a == 0.0) {
            discard;
        }
    }
    </script>
    </head>
    <body>
    <canvas id="canvas" width="400" height="400" ></canvas>
    <script>
    var gl;
    var canvas = document.getElementById('canvas');
    var glProgram = null;
    var glProgram2 = null;
    var samplerUniform = null;
    var maskTexture;
    
    function getGLContext() {
        var glContextNames = ['webgl', 'experimental-webgl'];
        for (var i = 0; i < glContextNames.length; i ++) {
            try {
                gl = canvas.getContext(glContextNames[i], {
                    stencil: true
                });
            } catch (e) {}
            if (gl) {
                gl.clearColor(74 / 255, 115 / 255, 94 / 255, 1.0);
                gl.clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
                gl.viewport(0, 0, canvas.width, canvas.height);
                gl.enable(gl.STENCIL_TEST);
                break;
            }
        }
    }
    
    function initShaders(vsShaderId, fsShaderId) {
        //get shader source
        var vs_source = document.getElementById(vsShaderId).innerHTML;
        var fs_source = document.getElementById(fsShaderId).innerHTML;
    
        //compile shaders
        var vertexShader = makeShader(vs_source, gl.VERTEX_SHADER);
        var fragmentShader = makeShader(fs_source, gl.FRAGMENT_SHADER);
    
        //create program
        var glProgram = gl.createProgram();
    
        //attach and link shaders to the program
        gl.attachShader(glProgram, vertexShader);
        gl.attachShader(glProgram, fragmentShader);
        gl.linkProgram(glProgram);
    
        if (!gl.getProgramParameter(glProgram, gl.LINK_STATUS)) {
            alert("Unable to initialize the shader program.");
        }
    
        //use program
        // gl.useProgram(glProgram);
        return glProgram;
    }
    
    function makeShader(src, type) {
        //compile the vertex shader
        var shader = gl.createShader(type);
        gl.shaderSource(shader, src);
        gl.compileShader(shader);
    
        if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
            alert("Error compiling shader: " + gl.getShaderInfoLog(shader));
        }
        return shader;
    }
    // vertex representing the triangle
    var vertex = [
        -.5, -.2,  0,
        .5,  -.2,  0,
        0,   .6,   0
    ];
    var stencilVertex = [
        -.2, -.5,  0,
        .4,  -.5,  0,
        .3,   .6,   0
    ];
    function setupBufferAndDraw(){
        // draw the mask image as stencil
        gl.useProgram(program2);
        var maskVertex = [
             -1, -1, 0,
             1,  -1, 0,
             1,   1, 0,
             -1, -1, 0,
             1,   1, 0,
             -1,  1, 0
        ];
        var maskTexCoords = [
            0, 0,
            1, 0,
            1, 1,
            0, 0,
            1, 1,
            0, 1
        ];
        var maskBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, maskBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(maskVertex), gl.STATIC_DRAW);
    
        var aMaskVertexPosition = gl.getAttribLocation(program2, 'aPos');
        gl.vertexAttribPointer(aMaskVertexPosition, 3, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(aMaskVertexPosition);
    
        // texture coordinate data
        var maskTexCoordBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, maskTexCoordBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(maskTexCoords), gl.STATIC_DRAW);
    
        var vertexTexCoordAttribute = gl.getAttribLocation(program2, "aTextureCoords");
        gl.enableVertexAttribArray(vertexTexCoordAttribute);
        gl.vertexAttribPointer(vertexTexCoordAttribute, 2, gl.FLOAT, false, 0, 0);
    
        // Always pass test
        gl.stencilFunc(gl.ALWAYS, 1, 0xff);
        gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
        gl.stencilMask(0xff);
        gl.clear(gl.STENCIL_BUFFER_BIT);
        // No need to display the triangle
        gl.colorMask(0, 0, 0, 0);
    
        gl.activeTexture(gl.TEXTURE0);
        gl.bindTexture(gl.TEXTURE_2D, maskTexture);
        gl.uniform1i(samplerUniform, 0);
    
        gl.drawArrays(gl.TRIANGLES, 0, maskVertex.length / 3);
        // return;
        gl.useProgram(program);
        // Pass test if stencil value is 1
        gl.stencilFunc(gl.EQUAL, 1, 0xFF);
        gl.stencilMask(0x00);
        gl.colorMask(1, 1, 1, 1);
        // draw the clipped triangle
        var color = [
            1, 0, 0, 1,
            0, 1, 0, 1,
            0, 0, 1, 1
        ];
        var colorBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(color), gl.STATIC_DRAW);
    
        var aColorPosition = gl.getAttribLocation(program, 'aColor');
        gl.vertexAttribPointer(aColorPosition, 4, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(aColorPosition);
    
        var vertexBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertex), gl.STATIC_DRAW);
    
        var aVertexPosition = gl.getAttribLocation(program, 'aPos');
        gl.vertexAttribPointer(aVertexPosition, 3, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(aVertexPosition);
        gl.clear(gl.COLOR_BUFFER_BIT);
        gl.drawArrays(gl.TRIANGLES, 0, vertex.length / 3);
    }
    
    function createTexture(source) {
        var texture = gl.createTexture();
        gl.bindTexture(gl.TEXTURE_2D, texture);
        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
        gl.bindTexture(gl.TEXTURE_2D, null);
        return texture;
    }
    
    window.onload = function () {
        getGLContext();
        program = initShaders('shader-vs', 'shader-fs');
        program2 = initShaders('shader-vs-2', 'shader-fs-2');
        samplerUniform = gl.getUniformLocation(program2, 'uSampler');
        var img = new Image();
        img.onload = function () {
            maskTexture = createTexture(this);
            setupBufferAndDraw();
        };
        img.src = '../images/mask-png8.png';
    }
    </script>
    </body>
    </html>
    

      

  • 相关阅读:
    C#,调用Process解压文件
    使用Jquery的treeview
    利用VS2010的项目生成事件属性进行生成文件的复制与打包
    简单理解laravel框架中的服务容器,服务提供者以及怎样调用服务
    详解PHP实现定时任务的五种方法
    php 回调函数和匿名函数
    mongodb的连接和开启安全验证
    关于版本号:alpha、beta、rc、stable
    php7 mongodb 扩展windows 安装
    终端提交代码到码云
  • 原文地址:https://www.cnblogs.com/honghong87/p/9758929.html
Copyright © 2020-2023  润新知