模板缓冲与阴影体 【转】

一、模板缓冲

与模板缓冲相关的操作有两种——比较操作和更新操作。

1. 比较操作

Stencil Test 比较的是Reference和Stencil Buffer中的值,公式如下:

(Stencil Ref \ &mask ) op (Stencil Buffer \ &mask )      // 左右顺序不可颠倒

相应的DX和OpenGL中的命令为:

glStencil(cmp_fun, ref, mask) 和 device->SetRenderState(D3DRS_STENCILFUNC, cmp_fun)

其中的cmp_fun就是上式中的“op”,实际为 “〉”、“〈”、“〉=”、“〈=”等比较运算。所谓的Stencil Test就是进行op运算。op运算的结果是与Stencil Test的状态相对应的(Stencil Test只有pass、fail两种状态),其对应关系如下:

op的运算结果         Stencil Test

true                 pass

false                fail

当op被设为always(DX:D3DCMP_ALWAYS | OPENGL:GL_ALWAYS)运算时,无论Stencil Ref和Stencil Buffer的当前值如何,Stencil Test永远为pass。

2. 更新操作

Stencil Test有pass/fail两种结果,Z-Buffer Test也有pass/fail两种结果。Stencil Buffer中的值的更新,需要同时指明是在何种状态(实际上是由Stencil Test和Z-Buffer Test运算结果两两组合而成的一共四种状态)下进行的何种更新。更新操作命令格式如下:

DX:  device->SetRenderState(state, op)

OpenGL:  glstencilOp(op1, op2, op3)

OpenGL              DX(state值)

Stencil Test pass       参数op3         D3DRS_STENCILPASS

Stencil Test fail         参数op1         D3DRS_STENCILFAIL

Z Buffer Test fail       参数op2         D3DRS_STENCILZFAIL

OpenGL(op1/op2/op3的值)                DX(op的值)

GL_KEEP                             D3DSTENCILOP_KEEP

GL_ZERO                            D3DSTENCILOP_ZERO

GL_REPLACE                        D3DSTENCILOP_REPLACE                 //用reference值替换模板缓冲中相应位置的值

GL_INCR                             D3DSTENCILOP_INCRSAT

GL_DECR                            D3DSTENCILOP_DECRSAT

GL_INCR_WRAP                   D3DSTENCILOP_INCR

GL_DECR_WRAP                  D3DSTENCILOP_DECR

要注意加以区分的两个概念——“stencil test通过后对颜色缓冲值的更新”和“stencil test通过后对模板缓冲值的更新”。

3. Stencil Reference

Stencil Reference主要有两个作用:

一是,在比较操作中用作进行比较的一个值;二是,在更新操作中用来替换模板缓冲中的相应数据(GL_REPLACE/D3DSTENCILOP_REPLACE)。

4. Z-Buffer Test 与 Stencil Test 的先后顺序

在OpenGL中Depth Test(Z-Buffer Test)是在Stencil Test之后,参见

而在DirectX中Z-Buffer Test 是在Stencil Test之前,参见。 // 这里是DX9的资料,DX11后渲染管线有较大变化,不知道这一顺序是否有变。

 二、阴影体(Shadow Volume)

通过阴影体来描绘物体投影的技术,在很多地方都有相关的介绍,但多不够直观。将阴影体(Shadow Volume)与Stencil Test结合来形成物体阴影的技术是其中最常见的一种方式,现结合下图作简单介绍。

假设,有一个对象OB在光源L作用下,在平面P上形成自身的阴影W,阴影在屏幕窗口S上对应的区域为W‘(如上图)。此时光源L与OB相交的边沿光照方 向的延长线,和OB的背光面一起将形成一个棱台VL。Shadow Volume的基本思想是这样的:先生成一个VL的实体并将其投影到S上,但并不真的把它画出来(也就是说,在将VL投影到S上时,并不真正地更新相应的 颜色缓冲),而只是借此操作来设置S上的W‘区域所对应的模板缓冲的值,同时使W‘所对应的模板缓冲中的值与其它区域所对应的模板缓冲中的值区别开来。这 样就可以在接下来的过程中,借助模板缓冲将S上的W‘区域涂黑,形成最终的阴影。

通过VL的投影过程来形成W‘区域与其它区域的Stenclil Buffer值的差别,是基于这样一种思想:假设有一条视线V1与VL正面(面对观察者或摄像机)相交于点b,然后又与VL背面(背对观察者或摄像机)相交于点c,那么说明V1所经过的区域没有其它的物体,所以VL就不会在此处有阴影投射,也就是说V1与S的交点a上的颜色,将由场景中的其它对象来决定;假设有另一条视线V2与VL正面相交于点e,在与VL背面相交之前先与平面P相交于点f,这就说明点f必处于OB的阴影中,那么V2与S的交点d上的颜色必然要带上阴影色。以下的技术手段是对这一原理的实现。

先将VL的正面(面向观察者或摄像机)在S上作一次投影(不更新颜色缓冲值),同时使S上与其相应的区域(在上图中没有画出)所对应的模板缓冲值加一;然后,再将VL的背面(背向观察者或摄像机)在S上再作一次投影(不更新颜色缓冲值),同时使S上与其相应的区域(在上图中没有画出)所对应的模板缓冲值减一。当然,在此过程中场景里所有其它对象也要渲染到S上。

在 渲染平面P时,Z-Buffer的Test和Write功能正常开启,在对VL的正、背面进行投影时,Z-Buffer的Test功能开启,而Write 功能关闭。这样就使得在VL正面投影到S上时,不会更新Z-Buffer中的值,而平面P在渲染时会更新Z-Buffer的值。在V2所 经过的路径上,由于平面P处于构成VL背面的诸三角形之前,因此,在Z-Buffer Test阶段,构成VL背面的诸三角形在光栅化阶段将被丢弃,所以,VL背面投影操作所附带的对相应区域的模板缓冲值的减一操作也就自动取消了,最终使得 f点所对应的模板缓冲值,在加一操作(进行VL正面投影时进行)后就一直不变了;而在V1所经过的路径上,由于没有其它的物体的阻隔,对模板缓冲区的加一、减一操作都会按预期进行。这样一来,W‘区域与其它区域相应的模板缓冲值就被区别开来了。

(注意,DX与OpenGL虽然在Stencil Test和Z-Buffer Test的先后顺序上有所不同,但两者对Stencil Buffer值的设置都是在Z-Buffer Test和Stencil Test都完成之后才进行的。)

时间: 2024-10-07 06:19:17

模板缓冲与阴影体 【转】的相关文章

Shadow Volume( 阴影体)渲染技术的实现细节及感受(一)之 阴影体生成

首先贴一个链接,该链接内有大量基于OpenGL的渲染技术教程和Code Sample,本文基本上在其Tutorial 40的基础上进行了翻译,并加入了部分自己的理解.原文在此: http://ogldev.atspace.co.uk/index.html Shadow Volume,即阴影体技术.是CG中非常常见的阴影渲染技术.在自己动手实现之前,也看了好多原理上的东西.但是纸上得来终觉浅,绝知此事要躬行啊! 以此文记录下Shadow Volume实现过程中的种种. 简单地讲,光线照射空间几何物

OpenGL ES 学习教程(十三) Stencil_TEST(模板缓冲测试)

模板缓冲测试,是指 将模版缓冲区中的值 与 一个参考值 进行比较,根据比较的结果,来对缓冲区中的值进行修改.进而决定该片段是否有效. 在应用中的体现就比如:Unity中的Mask . 大致的工作流程: 1.第一次Draw的时候,将所有的片段都设置为不通过模版测试.然后修改模版缓冲区的值,比如+1. 2.第二次Draw的时候,给定一个值 与 模版缓冲区中的值进行比较,比如用 1 与模版缓冲区中的值进行比较 . 因为第一步中,已经+1,所以模版缓冲区中值已经是1,然后用相等 作为条件判定 模版测试通

webgl 模板缓冲

先思考个问题, 想实现遮罩怎么办? <!doctype html> <html> <head> <meta charset="utf-8" /> <title>Stencil Buffer</title> <script id="shader-vs" type="x-shader/x-vertex"> precision highp float; attribut

3D模板阴影原理

3D模板阴影原理 1:先从3dsMax中导出一个简单的场景,一个园环,球,平面. 2:园环直接面向光源,园环对球体来说是一个光线的阻挡物,园环在它上面形成阴影,同时,园环和球体对平面来说是光线的阻挡物,所以,同时在其上面形成阴影. 3: 要产生模板阴影,先要找出在园环和球体上面面向光线的面,去除背向光线的面,通过测试光线同园环和球体上面每一个所组成的小角形的法线的夹角是否小于90度,即光线矢量同法线矢量的点积要大于零. 4:在余下的所有面向光线的面中,把每个面的每条边可以保存到一个Vector中

OpenGL阴影,Shadow Mapping(附源程序)

实验平台:Win7,VS2010 先上结果截图(文章最后下载程序,解压后直接运行BIN文件夹下的EXE程序): 本文描述图形学的两个最常用的阴影技术之一,Shadow Mapping方法(另一种是Shadow Volumes方法).在讲解Shadow Mapping基本原理及其基本算法的OpenGL实现之后,将继续深入分析解决几个实际问题,包括如何处理全方向点光源.多个光源.平行光.最近还有可能写一篇Shadow Volumes的博文(目前已经将基本理论弄清楚了),在那里,将对Shadow Ma

OpenGL 阴影之Shadow Mapping和Shadow Volumes

先说下开发环境.VS2013,C++空项目,引用glut,glew.glut包含基本窗口操作,免去我们自己新建win32窗口一些操作.glew使我们能使用最新opengl的API,因winodw本身只包含opengl 1.1版本的API,根本是不能用的. 其中矩阵计算采用gitHub项目openvr中的三份文件, Vectors.h ,Matrices.h, Matrices.cpp,分别是矢量与点类,矩阵类,我们需要的一些操作,矢量的叉乘和点乘,矩阵转置,矩阵的逆,矩阵与矢量相剩等. 这里主要

【一步步学OpenGL 23】 -《阴影贴图1》

教程 23 阴影贴图1 原文: http://ogldev.atspace.co.uk/www/tutorial23/tutorial23.html CSDN完整版专栏: http://blog.csdn.net/column/details/13062.html 背景 阴影和光是紧密联系的,正如你需要光才能投射出阴影.有许多的技术可以生成阴影,在接下来的两个章节中我们将学习一种基础而简单的技术-阴影贴图. 当涉及到光栅化和阴影的问题时,你可能会问这个像素是否位于阴影中?或者说,从光源到像素的路

Ogre参考手册(十一) 7 Shadows阴影

7 Shadows阴影 阴影渲染是很重要且很活跃的领域.渲染阴影的技术有很多,各有优点和缺点.为此Ogre提供了多种阴影实现,并提供大量的配置选项,以便根据场景选择最合适的方式. 根据阴影形状产生方式阴影可分为两类:模板和纹理.另外还由多种将阴影渲染到场景中的方法: 1 调制阴影(Modulative),将阴影区域变暗(将没有灯光照射的部分变暗,多个光源时,共同阴影会更暗:这样如果阴影调制色固定,灯光越多,阴影越暗.这种情况下,开灯的同时,需要同时变亮调制色) 2 灯光叠加(Additive),

转:体积阴影(Shadow Volumes)生成算法

下面以最快的速度简单谈谈阴影生成技术,目前普遍采用的一般有三种:Planar Shadow.Shadow Mapping和Shadow Volume,前者类似投影,计算最简单,缺点只能绘制抛射在平面上的阴影:Shadow mapping利用站在光源处所沿光源法线看去所生成的深度图来检测场景中的体象素是否处于阴影中,缺点是光源与物体位置相对固定.且在极端情况下计算精度差,不太适合精确到象素的动态光阴场合:Shadow Volume是目前最适合精确表现动态光阴场景的技术,适用性最广,其典型的适用范例