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>

  

原文地址:https://www.cnblogs.com/honghong87/p/9758929.html

时间: 2024-10-24 01:59:52

webgl 模板缓冲的相关文章

模板缓冲与阴影体 【转】

一.模板缓冲 与模板缓冲相关的操作有两种——比较操作和更新操作. 1. 比较操作 Stencil Test 比较的是Reference和Stencil Buffer中的值,公式如下: (Stencil Ref \ &mask ) op (Stencil Buffer \ &mask )      // 左右顺序不可颠倒 相应的DX和OpenGL中的命令为: glStencil(cmp_fun, ref, mask) 和 device->SetRenderState(D3DRS_STE

OpenGL ES 学习教程(十三) Stencil_TEST(模板缓冲测试)

模板缓冲测试,是指 将模版缓冲区中的值 与 一个参考值 进行比较,根据比较的结果,来对缓冲区中的值进行修改.进而决定该片段是否有效. 在应用中的体现就比如:Unity中的Mask . 大致的工作流程: 1.第一次Draw的时候,将所有的片段都设置为不通过模版测试.然后修改模版缓冲区的值,比如+1. 2.第二次Draw的时候,给定一个值 与 模版缓冲区中的值进行比较,比如用 1 与模版缓冲区中的值进行比较 . 因为第一步中,已经+1,所以模版缓冲区中值已经是1,然后用相等 作为条件判定 模版测试通

webgl 深度缓冲

深度缓冲很强大,用起来很简单 开启深度缓冲 gl.enable(gl.DEPTH_TEST); 清除深度缓存 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 为什么要用它呢? 因为画一些三维图形时,很难困难层级,深度缓冲就是帮你干这事的. 原文地址:https://www.cnblogs.com/honghong87/p/9760174.html

OpenGL ES 中的模板测试

模板测试的主要功能是丢弃一部分片元,相对于深度检测来说,模板测试提出的片元数量相对较少.模板测试发生在剪裁测试之后,深度测试之前. 使用模板测试时很重要的代码提示: 1 1.glClear( GL_STENCIL_BUFFER_BIT); 2 //启用模板测试 3 2.glEnable(GL_STENCIL_TEST); 大多数情况你的模板遮罩(stencil mask)写为0x00或0xFF就行. 1 // 0xFF == 0b11111111,此时,模板值与它进行按位与运算结果是模板值,模板

WebGL自学教程——WebGL演示样本:开始

最终开始WebGL样品演示,...... 开始 使用WebGL步骤,非常easy: 1. 获得WebGL的渲染环境(也叫渲染上下文). 2. 发挥你的想象力,利用<WebGL參考手冊>中的函数,參考<OpenGL ES 2.0编程指南>和各种已有的WebGL演示,针对获得的WebGL渲染环境进行操作,表达出你的意境. 为了获得WebGL的渲染环境.或者说,为了给WebGL一个渲染环境.我们须要在Web页面中定义一个名称为"canvas "的HTML5元素. 每一

OpenGL-----深度测试,剪裁测试、Alpha测试和模板测试

片断测试其实就是测试每一个像素,只有通过测试的像素才会被绘制,没有通过测试的像素则不进行绘制.OpenGL提供了多种测试操作,利用这些操作可以实现一些特殊的效果.我们在前面的课程中,曾经提到了“深度测试”的概念,它在绘制三维场景的时候特别有用.在不使用深度测试的时候,如果我们先绘制一个距离较近的物体,再绘制距离较远的物体,则距离远的物体因为后绘制,会把距离近的物体覆盖掉,这样的效果并不是我们所希望的.如果使用了深度测试,则情况就会有所不同:每当一个像素被绘制,OpenGL就记录这个像素的“深度”

模板测试

一: 模板测试 当片段着色器处理完一个片段之后,模板测试(Stencil Test)会开始执行,和深度测试一样,它也可能会丢弃片段.接下来,被保留的片段会进入深度测试,它可能会丢弃更多的片段.模板测试是根据又一个缓冲来进行的,它叫做模板缓冲(Stencil Buffer). 一个模板缓冲中,(通常)每个模板值(Stencil Value)是8位的.所以每个像素/片段一共能有256种不同的模板值.我们可以将这些模板值设置为我们想要的值,然后当某一个片段有某一个模板值的时候,我们就可以选择丢弃或是保

Ogre Composition解析

Composition脚本与类型 上面是一个Composition资源.在解析时,主要是使用CompositionPass,CompositionTargetPass,CompositionTechnique,Compositor,而在渲染时,使用RenderSystemOperation,TargetOperation,CompositorInstance,CompositionChain.管理Composition用CompositionManage. Composition主要类型说明.

layaAir引擎制作游戏的图集动画、时间轴动画、和骨骼动画总结二

一.角色序列帧.ani动画的制作 1.在项目管理器中创建动画文件 2.创建动画模板,编辑动效名称 3.编辑序列帧动画 .ani格式动画的代码控制 1.动画加载loadAnmition() 2.播放与停止.动效模板切换 3.动画帧位置控制 4.动画播放完成事件 uui截图: Laya.init(1334, 750); Laya.loader.load(["res/comp.atlas","res/role.atlas"],Laya.Handler.create(thi