【问题标题】:How stencil buffer and masking work?模板缓冲区和掩蔽如何工作?
【发布时间】:2018-03-30 02:02:09
【问题描述】:

我想在特定区域绘制对象。请看这张图片以供参考

2 个三角形(图片 A)仅绘制在四边形(图片 B)内的区域中,因此结果看起来会被剪裁(图片 C)。

首先我在模板缓冲区中绘制四边形。

gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);

gl.stencilFunc(gl.ALWAYS, 1, 0xff);
gl.stencilMask(0xff);
gl.depthMask(false);
gl.colorMask(false, false, false, false);

drawQuads();

据我了解,现在模板缓冲区在四边形区域的值为 1。然后,绘制三角形。

gl.stencilFunc(gl.EQUAL, 1, 0xff);
gl.stencilMask(0x00);
gl.depthMask(true);
gl.colorMask(true, true, true, true);

drawTriagles();

我原以为结果会像图片 (C) 上的那样,但事实并非如此。我做错了什么?

请在此处找到完整代码https://jsfiddle.net/z11zhf01/1

【问题讨论】:

    标签: webgl webgl2 stencil-buffer


    【解决方案1】:

    您的程序绝对可以正常运行,但是您必须在创建上下文时告诉getContext 函数创建模板缓冲区:

    gl = glcanvas.getContext("webgl", {stencil:true});
    

    Khronos WebGL Specification - WebGLContextAttributes:

    stencil
    如果值为true,则绘图缓冲区具有至少 8 位的模板缓冲区。如果值为 false,则没有模板缓冲区可用。

    查看示例:

    (function() {
    var gl;
    
    var gProgram;
    
    var gVertexAttribLocation;
    var gColorAttribLocation;
    
    var gTriangleVertexBuffer;
    var gTriangleColorBuffer;
    var gQuadVertexBuffer;
    var gQuadColorBuffer;
    
    
    function initGL() {
    	var glcanvas = document.getElementById("glcanvas");
    	gl = glcanvas.getContext("webgl", {stencil:true});
    }
    
    function createAndCompileShader(type, source) {
    	var shader = gl.createShader(type);
    
    	gl.shaderSource(shader, source);
    	gl.compileShader(shader);
    
    	if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
    		throw new Error(gl.getShaderInfoLog(shader));
    	}
    
    	return shader;
    }
    
    function createAndLinkProgram(glVertexShader, glFragmentShader) {
    	var glProgram = gl.createProgram();
    
    	gl.attachShader(glProgram, glVertexShader);
    	gl.attachShader(glProgram, glFragmentShader);
    	gl.linkProgram(glProgram);
    
    	if (!gl.getProgramParameter(glProgram, gl.LINK_STATUS)) {
    	    throw new Error("Could not initialise shaders");
    	}
    
    	return glProgram;
    }
    
    function initShaderPrograms() {
    	var gVertexShader = createAndCompileShader(gl.VERTEX_SHADER, [
    		"attribute vec3 a_vertex;",
    		"attribute vec4 a_color;",
    
    		"varying vec4 v_color;",
    
    		"void main(void) {",
    			"v_color = a_color;",
    			"gl_Position = vec4(a_vertex, 1.0);",
    		"}"
    	].join("\n"));
    
    	var gFragmentShader = createAndCompileShader(gl.FRAGMENT_SHADER, [
    		"precision mediump float;",
    
    		"varying vec4 v_color;",
    		"void main(void) {",
    			"gl_FragColor = v_color;",
    		"}"
    	].join("\n"));
    
    	gProgram = createAndLinkProgram(gVertexShader, gFragmentShader);
    }
    
    function initGLAttribLocations() {
    	gVertexAttribLocation = gl.getAttribLocation(gProgram, "a_vertex");
    	gColorAttribLocation = gl.getAttribLocation(gProgram, "a_color");
    }
    
    function initBuffers() {
    	gTriangleVertexBuffer = gl.createBuffer();
    	gTriangleColorBuffer = gl.createBuffer();
    	gQuadVertexBuffer = gl.createBuffer();
    	gQuadColorBuffer = gl.createBuffer();
    
    
    	gl.bindBuffer(gl.ARRAY_BUFFER, gTriangleVertexBuffer);
    	var vertices = new Float32Array([
    	     0.0,  1.0,  0.0,
    	    -1.0, -1.0,  0.0,
    	     1.0, -1.0,  0.0,
    
    	     0.0, -1.0,  0.0,
    	    -1.0, 1.0,  0.0,
    	     1.0, 1.0,  0.0
    	]);
    	gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
    
    	gl.bindBuffer(gl.ARRAY_BUFFER, gTriangleColorBuffer);
    	var colors = new Float32Array([
    	     0.0, 1.0,  0.0, 1.0,
    	     0.0, 1.0,  0.0, 1.0,
    	     0.0, 1.0,  0.0, 1.0,
    
    	     0.0, 0.0,  1.0, 1.0,
    	     0.0, 0.0,  1.0, 1.0,
    	     0.0, 0.0,  1.0, 1.0
    	]);
    	gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
    
    
    	gl.bindBuffer(gl.ARRAY_BUFFER, gQuadVertexBuffer);
    	var vertices = new Float32Array([
    	     -1.0,  1.0,  0.0,
    	    -1.0, -1.0,  0.0,
    	     1.0, 1.0,  0.0,
    	     1.0, -1.0,  0.0
    	]);
    	for(let i = 0, ii = vertices.length; i < ii; ++i) {
    		vertices[i] *= 0.75;
    	}
    	gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
    
    	gl.bindBuffer(gl.ARRAY_BUFFER, gQuadColorBuffer);
    	var colors = new Float32Array([
    	     1.0, 0.0, 0.0, 1.0,
    	     1.0, 0.0, 0.0, 1.0,
    	     1.0, 0.0, 0.0, 1.0,
    	     1.0, 0.0, 0.0, 1.0,
    	]);
    	gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
    
    }
    
    function drawQuads() {
    	gl.bindBuffer(gl.ARRAY_BUFFER, gQuadVertexBuffer);
    	gl.vertexAttribPointer(gVertexAttribLocation, 3, gl.FLOAT, false, 0, 0);
    
    	gl.bindBuffer(gl.ARRAY_BUFFER, gQuadColorBuffer);
    	gl.vertexAttribPointer(gColorAttribLocation, 4, gl.FLOAT, false, 0, 0);
    
    	gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
    }
    
    function drawTriagles() {
    	gl.bindBuffer(gl.ARRAY_BUFFER, gTriangleVertexBuffer);
    	gl.vertexAttribPointer(gVertexAttribLocation, 3, gl.FLOAT, false, 0, 0);
    
    	gl.bindBuffer(gl.ARRAY_BUFFER, gTriangleColorBuffer);
    	gl.vertexAttribPointer(gColorAttribLocation, 4, gl.FLOAT, false, 0, 0);
    
    	gl.drawArrays(gl.TRIANGLES, 0, 6);
    }
    
    
    function renderScene() {
    	gl.enable(gl.STENCIL_TEST);
    	gl.enable(gl.DEPTH_TEST);
    	// gl.enable(gl.CULL_FACE);
    	gl.useProgram(gProgram);
    
    	gl.clearColor(0.5, 0.5, 0.5, 1.0);
    
    	gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
    
    	gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
    
    	gl.enableVertexAttribArray(gVertexAttribLocation);
    	gl.enableVertexAttribArray(gColorAttribLocation);
    
    	gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
    
    	gl.stencilFunc(gl.ALWAYS, 1, 0xff);
    	gl.stencilMask(0xff);
    	gl.depthMask(false);
    	gl.colorMask(false, false, false, false);
    
    	drawQuads();
    
    	gl.stencilFunc(gl.EQUAL, 1, 0xff);
    	gl.stencilMask(0x00);
    	gl.depthMask(true);
    	gl.colorMask(true, true, true, true);
    
    	drawTriagles();
    
    	gl.disableVertexAttribArray(gVertexAttribLocation);
    	gl.disableVertexAttribArray(gColorAttribLocation);
    
    	gl.flush();
    }
    
    
    initGL();
    initShaderPrograms();
    initGLAttribLocations();
    initBuffers();
    renderScene();
    
    
    }());
    <main>
    	<canvas id="glcanvas" width="480" height="360">
    		WebGL not supported!
    	</canvas>
    </main>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-09
      • 1970-01-01
      • 1970-01-01
      • 2016-01-31
      • 1970-01-01
      • 1970-01-01
      • 2011-04-16
      相关资源
      最近更新 更多