[Solved] Stencil buffer in WebGL - Local Coder
文章推薦指數: 80 %
To use the stencil buffer you have to first request it when you create the webgl context const gl = someCanvasElement.getContext('webgl', {stencil: true});
StencilbufferinWebGL
Javascript
Canvas
Webgl
StencilBuffer
Solution1:
[1]
Tousethestencilbufferyouhavetofirstrequestitwhenyoucreatethewebglcontext
constgl=someCanvasElement.getContext('webgl',{stencil:true});
Thenyouturnonthestenciltest
gl.enable(gl.STENCIL_TEST);
Setupthetestsoitalwayspassesandsetthereferencevalueto1
gl.stencilFunc(
gl.ALWAYS,//thetest
1,//referencevalue
0xFF,//mask
);
Andsettheoperationsowe'llsetthestenciltothereferencevaluewhenboththestencilanddepthtestspass
gl.stencilOp(
gl.KEEP,//whattodoifthestenciltestfails
gl.KEEP,//whattodoifthedepthtestfails
gl.REPLACE,//whattodoifbothtestspass
);
Wethendrawthefirstinnertriangle
...lotsofsetupforasingletriangle...
gl.drawArrays(...)orgl.drawElements(...)
Thenwechangethetestsoitonlypassesifthestenciliszero
gl.stencilFunc(
gl.EQUAL,//thetest
0,//referencevalue
0xFF,//mask
);
gl.stencilOp(
gl.KEEP,//whattodoifthestenciltestfails
gl.KEEP,//whattodoifthedepthtestfails
gl.KEEP,//whattodoifbothtestspass
);
andnowwecandrawsomethingelse(thelargertriangle)anditwillonlydrawwherethereis0inthestencilbufferwhichiseverywhereexceptwherethefirsttrianglewasdrawn.
Example:
constm4=twgl.m4;
constgl=document.querySelector('canvas').getContext('webgl',{stencil:true});
constvs=`
attributevec4position;
uniformmat4matrix;
voidmain(){
gl_Position=matrix*position;
}
`;
constfs=`
precisionmediumpfloat;
uniformvec4color;
voidmain(){
gl_FragColor=color;
}
`;
constprogram=twgl.createProgram(gl,[vs,fs]);
constposLoc=gl.getAttribLocation(program,'position');
constmatLoc=gl.getUniformLocation(program,'matrix');
constcolorLoc=gl.getUniformLocation(program,'color');
constbuf=gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,buf);
gl.bufferData(gl.ARRAY_BUFFER,newFloat32Array([
0,-1,
1,1,
-1,1,
]),gl.STATIC_DRAW);
gl.enableVertexAttribArray(posLoc);
gl.vertexAttribPointer(
posLoc,//attributelocation
2,//2valuepervertex
gl.FLOAT,//32bitfloatingpointvalues
false,//don'tnormalize
0,//stride(0=baseontypeandsize)
0,//offsetintobuffer
);
//clearthestencilto0(thedefault)
gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT|gl.STENCIL_BUFFER_BIT);
gl.useProgram(program);
//turnonthestencil
gl.enable(gl.STENCIL_TEST);
//Setthestenciltestsoitalwayspasses
//andthereferenceto1
gl.stencilFunc(
gl.ALWAYS,//thetest
1,//referencevalue
0xFF,//mask
);
//Setitsowereplacewiththereferencevalue(1)
gl.stencilOp(
gl.KEEP,//whattodoifthestenciltestfails
gl.KEEP,//whattodoifthedepthtestfails
gl.REPLACE,//whattodoifbothtestspass
);
//drawawhitesmalltriangle
gl.uniform4fv(colorLoc,[1,1,1,1]);//white
gl.uniformMatrix4fv(matLoc,false,m4.scaling([0.2,0.2,1]));
gl.drawArrays(gl.TRIANGLES,0,3);
//Setthetestthatthestencilmust=0
gl.stencilFunc(
gl.EQUAL,//thetest
0,//referencevalue
0xFF,//mask
);
//don'tchangethestencilbufferondraw
gl.stencilOp(
gl.KEEP,//whattodoifthestenciltestfails
gl.KEEP,//whattodoifthedepthtestfails
gl.KEEP,//whattodoifbothtestspass
);
//drawalargegreentriangle
gl.uniform4fv(colorLoc,[0,1,0,1]);//green
gl.uniformMatrix4fv(matLoc,false,m4.scaling([0.9,-0.9,1]));
gl.drawArrays(gl.TRIANGLES,0,3);
canvas{border:1pxsolidblack;}
延伸文章資訊
- 1WebGLRenderer#stencil – three.js docs
The WebGL renderer displays your beautifully crafted scenes using WebGL. ... stencil - whether th...
- 2Stencil buffer doesn't work on WebGL2 - Unity Answers
If you want to use stencil buffer in WebGL use it via render feature and specify masks and events...
- 3WebGL绘制详解之五:Stencil Buffer | JZ's Blog
WebGL中的stencil buffer(模板缓冲区)的作用也是类似的,可以在Buffer中指定一个形状作为模板,接着通过stencil test(模板测试)过程让位于形状 ...
- 4How stencil buffer and masking work? - webgl - Stack Overflow
Your program works absolute correctly, but you have to tell the getContext function to create a s...
- 5WebGLRenderingContext.stencilFunc() - Web APIs | MDN
The WebGLRenderingContext.stencilFunc() method of the WebGL API sets the front and back function ...