这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战 玩过LOL或者王者的人应该都知道,很多游戏在运行时,屏幕上不仅显示主视角游戏场景,还会显示小地图这类的次视角游戏场景。想要满足这样的需求仅采用前面介绍的技术几乎是不可能的,因此,本章将向读者介绍一些能满足特殊需求的裁剪与测试方面的知识,主要内容包括裁剪测试,模板测试。
裁剪测试
裁剪测试主要在渲染场景时限制绘制区域,用它可以方便地实现同时在屏幕上绘制主视角与次视角场景的功能。
前面已经提过,裁剪测试可以在渲染时限制绘制区域,通过此技术可以在屏幕(帧缓冲)上指定一个矩形区域。启用裁剪测试后,绘制将不会像前面介绍过的案例一样在整个屏幕(帧缓冲)中进行,而是仅在指定的区域中进行。 不在此矩形区域内的片元将被丢弃,只有在此矩形区域内的片元才有机会最终进入帧缓冲。因此,实际的效果就是在屏幕上开辟一个小窗口,在其中进行特定内容的绘制。
使用裁剪测试所需要的核心代码如下所示。
//启用剪裁测试
gl.enable(gl.SCISSOR_TEST);
//设置剪裁区域
gl.scissor(0,100, 350, 300);
//禁用剪裁测试
gl.disable(gl.SCISSOR_TEST);
gl.scissor函数前两个参数是矩形视口的左下角坐标,三四参数是长宽
下面我们通过一个demo看看裁剪测试的实际效果
//设置屏幕背景色RGBA
gl.clearColor(0.0, 0.0, 0.0, 1.0);
//清除着色缓冲与深度缓冲
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
//设置投影参数
ms.setProjectOrtho(-1.5, 1.5, -1, 1, 1, 300);
//设置摄像机
ms.setCamera(0, 0, 0, 0, 0, -1, 0, 1, 0);
//保护现场
ms.pushMatrix();
//执行平移
ms.translate(0, -0.4, -25);
ms.scale(0.025, 0.025, 0.025);
//执行绕Y轴旋转
ms.rotate(currentYAngle, 0, 1, 0);
//执行绕X轴旋转
ms.rotate(currentXAngle, 1, 0, 0);
//绘制物体
ooTri.drawSelf(ms, texMap["ghxp"]);
//绘制副视角场景=============================================begin=========================
//启用剪裁测试
gl.enable(gl.SCISSOR_TEST);
//设置剪裁区域
gl.scissor(0, 1080 - 300, 350, 300);
//设置屏幕背景色RGBA
gl.clearColor(0.7, 0.7, 0.7, 1.0);
//清除颜色缓存于深度缓存
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
//调用此方法计算产生透视投影矩阵setProjectOrtho
ms.setProjectOrtho(-0.17 * 1.5, 1.83 * 1.5, -1.7, 0.30, 2, 100); //-0.62f*ratio, 1.38f*ratio, -1.55f, 0.45f,
//调用此方法产生摄像机9参数位置矩阵
ms.setCamera(0, 60, -25, 0, -0.4, -25, 0, 0.0, -1.0);
ms.scale(0.25, 0.25, 0.25);
//绘制物体
ooTri.drawSelf(ms, texMap["ghxp"]);
//禁用剪裁测试
gl.disable(gl.SCISSOR_TEST);
//绘制副视角场景=============================================end=========================
//恢复现场
ms.popMatrix();
效果如下:
模板测试
通过上面的裁剪测试可以将绘制限制在一个矩形中,但如果想将绘制限定在任意形状区域内,裁剪测试就无能为力了,此时就需要模板测试了。
使用模板测试所需要的核心代码如下所示。
//清除着色缓冲与深度缓冲
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
//允许模板测试
gl.enable(gl.STENCIL_TEST);
//设置模板测试参数
gl.stencilFunc(gl.ALWAYS, 1, 1);
//设置模板测试后的操作
gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
//禁用模板测试
gl.disable(gl.STENCIL_TEST);
stencilFunc的gl.ALWAYS代表总是通过模板测试,第二个参数是参考值,第三个是掩码。
gl.stencilOp的gl.KEEP 模板测试不通过的时候要保持不变,第二个参数代表模板测试沟通但深度测试未通过时,片源的效果,第三个是都通过的效果,使用测试条件设置的值来显示。
下面我们通过一个demo看看裁剪测试的实际效果
//清除着色缓冲与深度缓冲
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
//清除模板缓存
gl.clear(gl.STENCIL_BUFFER_BIT);
//关闭深度检测
gl.disable(gl.DEPTH_TEST);
//允许模板测试
gl.enable(gl.STENCIL_TEST);
/**
* 首先打开模板测试 绘制反射地板 用于初始化模板缓冲的模板值
* 利用产生的模板值 在规定区域中绘制镜像物体
* 关闭模板测试后 绘制正常的地板
* 最后在绘制实际物体*/
//设置模板测试参数
gl.stencilFunc(gl.ALWAYS, 1, 1);
//设置模板测试后的操作
gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
ms.pushMatrix();
ms.scale(0.3, 0.3, 0.3);
//绘制反射面地板
rectdb.drawSelf(ms, texMap["db"]);
ms.popMatrix();
//设置模板测试参数
gl.stencilFunc(gl.EQUAL, 1, 1);
//设置模板测试后的操作
gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
//绘制镜像体
drawmirror();
//禁用模板测试
gl.disable(gl.STENCIL_TEST);
//开启混合
gl.enable(gl.BLEND);
//设置混合因子
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
ms.pushMatrix();
ms.scale(0.3, 0.3, 0.3);
//绘制半透明反射面地板
rectdb.drawSelf(ms, texMap["tm"]);
ms.popMatrix();
//开启深度检测
gl.enable(gl.DEPTH_TEST);
//关闭混合
gl.disable(gl.BLEND);
//绘制实际物体
drawball();
效果如下:
本章小结 通过上面两个功能,我们可以用来实现鹰眼地图效果和水面倒影的效果,可是场景更加的真实些。