Stencil模板测试是一个类似于深度测试的功能,由WebGL提供,但Laya没有未开发者打通这个环节。
图1是未使用Stencil的效果,因为顶点重叠,阴影效果不理想。图二使用了Stencil,已绘制阴影的地方不再重复绘制。
Laya引擎版本:2.11.0 ts实验版
1、首先在WebGLContext.ts中添加WebG的Stencil相关接口:
/**
* @internal
*/
static setStencilFunc(gl: WebGLRenderingContext, func: number, value: number, mask: number): void {
gl.stencilFunc(func, value, mask);
}
/**
* @internal
*/
static setStencilOp(gl: WebGLRenderingContext, fail: number, zfail: number, zpass: number): void {
gl.stencilOp(fail, zfail, zpass);
}
2、在ShaderInstance.ts的uploadRenderStateBlendDepth方法最后,添加调用上面两个接口的代码:
WebGLContext.setStencilFunc(gl, renderState.stencilFunc, renderState.stencilRef, renderState.stencilMask);
WebGLContext.setStencilOp(gl, renderState.stencilOpFail, renderState.stencilOpZFail, renderState.stencilOpPass);
3、接下来,在RenderState.ts中加入Stencil相关的枚举和需要传递给WebGL的参数
/**stencil测试函数枚举_从不通过。*/
static STENCIL_NEVER: number = 0x0200;
/**stencil测试函数枚举_小于时通过。*/
static STENCIL_LESS: number = 0x0201;
/**stencil测试函数枚举_等于时通过。*/
static STENCIL_EQUAL: number = 0x0202;
/**stencil测试函数枚举_小于等于时通过。*/
static STENCIL_LEQUAL: number = 0x0203;
/**stencil测试函数枚举_大于时通过。*/
static STENCIL_GREATER: number = 0x0204;
/**stencil测试函数枚举_不等于时通过。*/
static STENCIL_NOTEQUAL: number = 0x0205;
/**stencil测试函数枚举_大于等于时通过。*/
static STENCIL_GEQUAL: number = 0x0206;
/**stencil测试函数枚举_总是通过。*/
static STENCIL_ALWAYS: number = 0x0207;
/**stencil测试操作行为 */
static STENCIL_ZERO: number = 0;
/**stencil测试操作值行为 */
static STENCIL_INVERT: number = 0x150a;
/**stencil测试操作行为 */
static STENCIL_KEEP: number = 0x1e00;
/**stencil测试操作行为 */
static STENCIL_REPLACE: number = 0x1e01;
/**stencil测试操作行为 */
static STENCIL_INCR: number = 0x1e02;
/**stencil测试操作行为 */
static STENCIL_DECR: number = 0x1e03;
/**stencil测试操作行为 */
static STENCIL_INCR_WRAP: number = 0x8507;
/**stencil测试操作行为 */
static STENCIL_DECR_WRAP: number = 0x8508;
/**stencil测试函数 */
stencilFunc: number;
/**stencil测试参考值 */
stencilRef: number;
/**stencil测试掩码 */
stencilMask: number;
/**stencil测试未通过时的行为 */
stencilOpFail: number;
/**stencil测试通过但是depth测试未通过时的行为 */
stencilOpZFail: number;
/**stencil测试通过且depth测试也通过时的行为 */
stencilOpPass: number;
4、在RenderState的构造方法最后,给Stencil相关的参数设置默认值
this.stencilFunc = RenderState.STENCIL_ALWAYS;
this.stencilRef = 0;
this.stencilMask = 0;
this.stencilOpFail = RenderState.STENCIL_KEEP;
this.stencilOpZFail = RenderState.STENCIL_KEEP;
this.stencilOpPass = RenderState.STENCIL_KEEP;
5、在Rerder.ts中开始WebGL的Stencil功能
6、最后一步,渲染2D之前,恢复Stencil设置,以免影响2D渲染,在Context.ts里
使用方法,创建shader的pass时,设置stencil相关的参数