`
sogotobj
  • 浏览: 646583 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

无stencil buffer,绘制半透明planar shadow的一种方法

阅读更多

所谓planar shadow就是用一个投影矩阵(不是opengl流水线所谓之projection matrix,而是根据光源和投影面位置将一个点投射到投影面上的矩阵),将模型的所有顶点投射到投影面(比如地面)上。一般或者直接使用模型经过skin动画计算好的mesh进行投影并绘制,或者使用一个低模独立计算mesh然后投影绘制。无论哪种方法,都有一个问题,由于影子是很多三角形重叠在一起的,如果使用半透明材质绘制,众多的三角形会重叠在一起非常难看,且会有z-fighting现象闪烁不止。。当然如果有stencil buffer,可以使用stencil buffer进行mask,如果没有呢?确实在某些平台上没有stencil buffer,往往只能通过depth buffer做一些有限的模拟,本文所提的方法就是一例。

------------------------------------------

绘制过程:

1)首先绘制场景里所有其他东西

2)用0清除depth buffer:

glClearDepth(0);

glClear(GL_DEPTH_BUFFER_BIT);

3)确保深度测试开启,z write允许,并且设置depth func为always

glEnable(GL_DEPTH_TEST);

glDepthMask(GL_TRUE);

glDepthFunc(GL_ALWAYS);

4)禁止color buffer写入:

glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );

5)绘制影子(solid材质,无纹理,无blend)

经过上面的设置,实际上只会更新depth buffer, 写入z buffer时,默认的depth range是0~1,所以没有影子的地方,z buffer中是0,有影子的地方是一个大于0的值,因为影子一般不可能离near plane很近很近,所以这个值应该>0。

6)将model-view和projection矩阵设为单位阵

glMatrixMode (GL_MODELVIEW);

glLoadIdentity ();

glMatrixMode (GL_PROJECTION);

glLoadIdentity ();

7)重新开启color buffer写入,depth func为LEQUAL, 并关闭depth buffer的写入

8)绘制一个全屏的矩形,开启blend,设置矩形顶点颜色为半透明黑色

矩阵顶点坐标为:

glVertex3i (-1, -1, -0.99);
glVertex3i (1, -1, -0.99);
glVertex3i (1, 1, -0.99);
glVertex3i (-1, 1, -0.99);

绘制这个矩形时进行深度测试LEQUAL,z值-0.99是clip space中的值,通过depth range的映射,最终的z值是>0但很接近0的值,而影子应该是离near plane比这个面更远的(即z值比这个面的z值要大),所以经过LEQUAL的测试,画这个矩形的时候,z buffer上有影子的部分通过深度测试,而z buffer为0的地方不通过所以不绘制。而且由于启用了blend,矩形的像素还要和color buffer上的已有颜色进行混合,达到半透明效果。这样半透明的矩形被影子mask出来了,就得到了半透明的影子。

另外,为啥是-0.99而不是-1呢?因为clip space, -1就是在near clip plane上了,窗口坐标映射后的z值是0,0==0就能通过LEQUAL的测试了就会全部画出来了。。但是如果使用LESS测试,-1也就可以用了。

注:以上代码仅作参考,实际调用的都是引擎的接口

当然这个方法不完美,毛病也很多,比如影子会遮住人的脚,平台边缘无法裁掉影子等

ps:复习一下向z buffer写入z值的整个过程:此Z非x,y,z的z,而是eye space, clip space, NDC, windows space的z。通过modle-view变换,相机被变换到默认位置,即view为-z,此为eye space。我们在世界坐标系下,往往采用z up,所以此z非彼z,无论世界坐标z表示什么,到eye space之后,z值就表示深度了,所谓深度就是指离camera的距离。从eye space经过投影变换,到达clip space, clip space中(x,y,z)都被变换到[-w,w]的范围,再经过透视除法,x,y,z都除以w,使得x,y,z都在[-1,1]之间这就是NDC了(归一化坐标)。然后再经过viewport变换,变换到窗口坐标,此时z值会根据depth range进行映射,默认的是映射为[0,1]。clip,透视除法和视口变换都属于图元装配过程,之后是光栅化阶段,图元被光栅化为片段(fragment),在光栅化阶段,为了降低zfighting现象,可以使用polygon offset, polygon offset是在进行深度测试和写入zbuffer之前,将计算好的z值加上一个偏移量,如果深度测试通过,会将原始深度值(而不是加上offset之后的z值)写入zbuffer。也就是说无论是否使用polygon offset,最终写入zbuffer的z值是视口变换之后通过depth range映射的windows coordinate z值,但polygon offset会对depth test产生影响。

分享到:
评论

相关推荐

    OpenGL3.3_StencilBuffer_Outlines.rar

    OpenGL3.3_StencilBuffer_Outlines.rar 这个压缩包文件主要关注的是OpenGL 3.3版本中的Stencil Buffer技术,用于实现复杂的图形效果,特别是轮廓描边。Stencil Buffer是OpenGL中一个重要的辅助缓冲区,它独立于颜色...

    用Stencil Buffer实现在UGUI上嵌入3D模型

    总的来说,利用Stencil Buffer在UGUI上嵌入3D模型是一种高级的渲染技巧,它结合了2D界面和3D场景的优势,可以创建出更具深度和交互性的用户体验。在Unity开发中,熟练掌握这种技术对于提升游戏和应用的视觉质量至关...

    Optimized Stencil Shadow Volumes

    “Optimized Stencil Shadow Volumes”是一种先进的计算机图形学技术,用于模拟真实世界中的阴影效果。该技术通过利用硬件加速的深度(Z)缓冲器和模板缓冲器来实现高效且高质量的阴影渲染。本文将详细介绍优化的...

    D3D111_StencilBuffer

    在这个特定的知识点"**D3D111_StencilBuffer**"中,我们关注的是D3D11.1如何使用模板缓存(Stencil Buffer)来实现复杂的场景渲染效果。 模板缓存是一种特殊的缓冲区,与颜色缓冲区和深度缓冲区并存,用于存储每个...

    D3D11(StencilBuffer)镜子的实现

    该示例程序用于学习D3D11中模板缓冲区的使用,通过使用它来实现一个平面镜面反射的效果。 操作说明:鼠标左键按下旋转镜头,右键按下调整镜头远近。 文件中包含整个示例程序及框架,以及可执行程序。如果exe不能正常...

    shadowVolume封装类

    `ShadowVolume`是一种用于实现三维场景中动态阴影的技术,尤其在DirectX(DX)高级开发中被广泛应用。本篇文章将详细探讨`ShadowVolume`封装类及其在动态阴影渲染中的应用。 首先,`ShadowVolume`的概念源于将每个...

    Stencil-Mirror-Shadow.rar_Mirror Mirror

    "Stencil-Mirror-Shadow.rar_Mirror Mirror" 提供了一个关于如何利用DirectX 9.0实现镜面反射和墙壁不反射的技术实例。这个压缩包可能包含源代码、教程或演示程序,用于解释如何使用模板缓冲(Stencil Buffer)技术...

    OpenGL Shadow volume

    OpenGL Shadow Volume是一个在3D图形渲染中用于实现阴影效果的技术,尤其在游戏和实时可视化应用中常见。这个演示程序展示了如何使用z-pass方法来创建阴影体积,从而为场景中的对象添加逼真的光照阴影。 首先,我们...

    模板测试StencilTest功能应用演示demo源码

    在OpenGL中,模板测试(Stencil Testing)是一种用于控制像素绘制的方式。它允许开发者根据模板缓冲区(Stencil Buffer)中的值来决定是否绘制某个像素。模板测试通常用于实现一些高级的图形效果,如阴影、反射、...

    VMware Visio stencil 20.11

    VisioStencil是Visio中的一个关键元素,它包含了一系列预定义的形状和图标,使得用户能够便捷地绘制出专业且准确的虚拟化架构图。这个版本20.11表明它可能包含了最新的VMware产品和技术的图形表示。 在描述中提到的...

    Graff Stencil iPhone_WebApp_WireFrame

    总结来说,Graff Stencil iPhone_WebApp_WireFrame 是一款强大且实用的原型设计资源,对于从事iPhone Web应用开发的设计师来说,它是不可或缺的工具之一。借助这款工具,设计师能够高效、专业地创建出符合用户需求的...

    VMware VISIO 專用 Stencil2

    《VMware VISIO 專用 Stencil2:打造专业虚拟化设计》 VMware VISIO 專用 Stencil2 是一套专为VMware环境设计的Visio模板,它极大地提升了IT专业人员在创建虚拟化解决方案的流程图和架构图时的效率与准确性。此工具...

    Stencil:Stencil是Swift的一种简单而强大的模板语言

    Stencil是Swift的一种简单而强大的模板语言。 它提供类似于Django和Mustache的语法。 如果您熟悉这些内容,您将对Stencil感到宾至如归。 例子 There are {{ articles.count }} articles. {% for article in ...

    octin stencil

    "Octin Stencil" 是一款字体相关的资源,很可能是一个包含多种设计风格的字体包。在设计领域,尤其是图形设计和网页设计中,字体的选择对于视觉效果和信息传达至关重要。"Stencil" 在英文中有模板的意思,这暗示了这...

    三维变换的消隐

    例如,在Z缓冲区基础上结合Stencil Buffer,可以处理透明或半透明物体的消隐问题。同时,现代图形库如OpenGL和Direct3D提供了内置的支持,简化了开发者的工作。 通过深入理解这些消隐算法和技术,开发者可以创建出...

    stencil.rar_图形图像处理_C/C++_

    在计算机图形学领域,"Stencil Buffer"是一种关键技术,用于实现复杂的渲染效果,如阴影、反射、边缘检测等。本文将围绕“Stencil Buffer”这一主题,深入探讨如何利用它来改进阴影和反射的质量,特别是针对C/C++...

    stencil_tutorial_stencil_

    Stencil在设计中扮演着重要角色,它是一种预定义的图形元素或形状,可以被重复使用,以保持设计的一致性和效率。在网页设计中,它们可以是按钮、导航元素、图标等,而在图形设计中,它们可能包括复杂的插图或矢量...

    Spacedock stencil

    Spacedock stencil

    Viking Stencil

    Viking Stencil

    [Shader]对NGUI的UISprite和UITexture进行裁剪

    总的来说,利用Shader对NGUI的UISprite和UITexture进行裁剪是一种高效且灵活的方法,它可以让我们在不改变UI元素原始大小的情况下实现各种复杂的裁剪形状。在实际开发中,结合Unity的其他特性,如Layer Culling或...

Global site tag (gtag.js) - Google Analytics