当前位置: 首页 > news >正文

【OpenGL】模板测试(StencilTest)

目录

一、模板测试(StencilTest)的引入

二、相关API

1、模板测试的开启/关闭

2、模板测试通过/失败后

3.效果实现

三、模板测试的封装


前言:总结于b站赵新政老师的OpenGL课程,含个人理解,如有错误,很高兴大家可以指出,我会尽快修改的OwO(赵新政的个人空间-赵新政个人主页-哔哩哔哩视频)

一、模板测试(StencilTest)的引入

现在,我们想要为一个物体进行“勾边”,让他更为突出。

该效果实际上是由两个盒体进行实现,首先先渲染box本体,然后边框特效则是将原本的盒体扩大一点,替换成白色材质进行渲染。

可是呢,当我们进行渲染的时候,很显然后渲染的边框效果会遮盖住前面渲染的本体。而为了解决这个问题,就要确保边框效果不会覆盖掉本体内容。因而,就出现了模板测试(StencilTest)

首先了解模板缓冲(StencilBuffer):与深度缓冲相似(一张画布),记录了当前绘制的物体覆盖了哪些像素区域(8bit,一般而言8bit就足够使用了)。

借助模板缓冲,可以知道那些像素被绘制过,从而指定规则,只有通过本规则测试的像素才能绘制出来。

在上一物体进行渲染的时候,我们将会根据颜色缓冲更新模板缓冲,在进行下一个物体的渲染的时候,会将当前的颜色缓冲模板缓冲进行比较,根据设置的模板测试类型来决定是否需要对当前颜色进行渲染。

二、相关API

1、模板测试的开启/关闭

void glEnable(GL_STENCIL_TEST);//开启模板测试

void glDisable(GL_STENCIL_TEST);//关闭模板测试

模板测试条件:设置当前渲染Mesh通过模板测试的条件

void glStencilFunc(GLenum func,GLint ref,GLuint mask);

        func:使用模板缓存中的数值与ref如何对比才算通过测试;

        ref:参考数值

        mask:缓存数值与参考值进行比较前,都要先与mask做AND(&)操作

func:

GL_NEVER:总是不允许通过测试

GL_ALWAYS:总是通过测试

GL_EQUAL:相等才通过测试

GL_NOTEQUAL:不等才通过测试

GL_LESS:小于才通过测试

GL_GREATER:大于才通过测试

假如我们使用GL_EQUAL

那么假如当前的模板缓冲中的值为value=3,mask=1。

此时如果我们的模板数值ref=1

那么value&mask=1  , ref&mask=1

两个结果相同,那么当前通过了模板测试,可以进行渲染。

2、模板测试通过/失败后

void glStencilOp(GLenum sfail,GLenum zfail,GLenum zpass);

  1. sfail:模板测试失败的时候执行什么操作
  2. zfail:模板测试通过但深度测试失败时执行的操作
  3. zpass:模板测试和深度测试都通过时执行的操作

GL_KEEP:保持当前的模板值

GL_ZERO:将模板值设置为0

GL_REPLACE:将模板值设置为glStencilFunc中指定的参考值

GL_INCR:如果当前模板值小于最大值,则将模板值+1

GL_INCR_WRAP:类似于GL_INCR,但是如果增加后超过了最大值则会绕回0。

GL_DECR:如果当前模板值大于0,则将模板值减1

GL_DECR_WRAP:类似于GL_DECR,但是如果减小后小于0则会绕回最大值。

GL_INVERT:按位翻转当前的模板值

类似于深度缓冲写入,我们也可以决定是否对模板缓冲进行写入。

·开启模板测试情况下,禁止模板缓冲写入

void glStencilMask(GLuint mask)

mask:掩码的每一位对应于模板缓冲区中的每一位,,每当一个位是1时,模板缓冲区的相应位可以被写入;当一个位是0时,相应位不能被写入。

0x00:任何bit位都不允许写入

0xFF:任何bit位都允许写入

举例来讲,如果当前模板缓冲的参考值ref=3,且已经通过了模板测试,若mask=2,则其进行模板缓冲写入的时候,当前新的模板缓冲值=ref&mask=2,所以,如果mask=0x00,那么模板缓冲写入始终为0,而当mask=0xFF的时候,就会直接写入ref。

3.效果实现

因而,想要实现上述的效果,对于box本体而言,其应当开启模板测试之后,设置总是可以通过模板测试(GL_ALWAYS),并设置好ref值,模板测试mask和模板缓冲写入的mask设置为0xFF,其通过模板测试和深度测试的操作应当设置为替换(GL_REPLACE),其余为保持(GL_KEEP)

glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS,1,0xFF);
glStencilMask(0xFF);
glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE);

而对于白色的框体而言,就应该在开启模板测试之后设置只有当模板测试值不等(GL_NOTEQUAL)的时候才进行渲染,ref值取1,模板测试的mask设置为0xFF,模板缓冲写入的mask设置为0x00(不进行写入)

glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_NOTEQUAL,1,0xFF);
glStencilMask(0x00);

三、模板测试的封装

从设置模板测试的变量去看,我们需要为每一个材质material加入如下变量

//Stencil模板测试
bool m_stencil_test{ false };
GLenum m_stencil_func{ GL_ALWAYS };
GLint m_stencil_ref{ 0 };
GLuint m_stencil_func_mask{ 0xFF };GLenum m_fail{ GL_KEEP };
GLenum m_zfail{ GL_KEEP };
GLenum m_zpass{ GL_KEEP };GLuint m_stencil_mask{ 0xFF };

于是,在渲染阶段,就需要根据材质material中的变量,来对模板测试进行设置,包括:

(1)是否要开启模板检测        glEnable/glDisable(GL_STENCIL_TEST)

(2)通过测试的操作设置        gl_StencilOp(fail,zfail,zpass)

(3)模板测试的比较方式        gl_StencilFunc(func,ref,mask)

(4)是否写入模板缓冲            gl_StencilMask(mask)

void Renderer::set_stencil_test(Material* material)
{if (material->m_stencil_test){glEnable(GL_STENCIL_TEST);glStencilOp(material->m_fail, material->m_zfail, material->m_zpass);glStencilFunc(material->m_stencil_func, material->m_stencil_ref, material->m_stencil_func_mask);glStencilMask(material->m_stencil_mask);}else{glDisable(GL_STENCIL_TEST);}
}

我们可以考虑去实现如下场景,对两个粘连在一起的正方体进行勾边:

在这种情况下,我们会发现,其中一个正方体的勾边遮住了另外一个正方体,在正常情况下我们是不希望这样的。

所以,为了解决这个问题,就需要关闭勾边的深度检测,这样,就可以确保勾边不会影响到原来的像素。

http://www.dtcms.com/a/498725.html

相关文章:

  • 文本描述驱动的可视化工具在IDE中的应用与实践
  • C#程序实现将MySQL的存储过程转换成Oracle的存储过程
  • IDEA 中 Tomcat 部署 Java Web 项目
  • 全景网站模版校园微网站建设方案ppt模板
  • 东莞公司网站建设公司哪家好制作网站链接
  • 【Linux】Socket编程UDP
  • “桌面自动化”解救“浏览器自动化”受阻(反爬虫检测)(pywinauto、pyautogui、playwright)
  • 线程安全集合源码速读:Hashtable、Vector、Collections.synchronizedMap
  • 大文件上传与文件下载
  • React Native 项目中 WebSocket 的完整实现方案
  • 电脑建设银行怎样设置网站查询密码手机网站建设价钱是多少
  • Linux内核ida数据结构使用
  • SAP MM委外采购订单执行报表分享
  • Docker中授权普通用户使用docker命令以及解决无权限访问/var/run/docker.sock错误
  • 算法奇妙屋(八)-泰波那契数列模型
  • 荆门哪里做网站女生学建筑工程技术就业前景
  • HarmonyOS中ArkTS与Flutter数据类型对比详解
  • 【11408学习记录】考研数学核心突破:线性变换的深度解析与应用实例
  • PHP8.5 的新 URI 扩展
  • 基于单片机的 220v车载逆变电源的设计与制作(论文+图纸)
  • 网站建设定制设计南京企业网站开发
  • python|运算符
  • 基于精准营养与数字表型的糖尿病生活方式干预新范式
  • 基于开源AI大模型、AI智能名片与S2B2C商城小程序的购物中心精准零售数据架构研究
  • 深度学习进阶(八)——AI 操作系统的雏形:AgentOS、Devin 与多智能体协作
  • 旧物新生,从二手回收小程序开启绿色生活
  • 网站建设模板代理手机购物app排行榜前十名
  • openharmony之分布式购物车开发实战
  • 音乐网站建设的意义全媒体运营技巧和工具
  • 关于最简单的机器学习的梯度下降公式的求导过程