物体勾边(译)

来源:互联网 发布:淘宝店铺显示地址 编辑:程序博客网 时间:2024/05/16 09:12
作者:Max McGuire(06 May 2002)
翻译:azure

Object Outlining
物体勾边

Introduction


I was recently charged with the task of rendering outlines around models in the game I am working on to show when they are selected. There are a number of techniques available for accomplishing this, however they typically produce outlines of inconsistent line weight or fail to accurately represent the silhouette of the object.

In this short article I'll present my solution to the problem of producing an accurate, constant weight outline around a polygonal mesh. It recently came to my attention that a similar method was originally published by Rossignac and van Emmerik [1] in 1992.

简介

我当前正在处理一项关于渲染当他们在游戏中被选中的时候,绘制一圈围绕模型周围的轮廓的任务。当前有很多方法可以实现这个效果,但是一般产生的都是不连续的线宽权重并不能完好的表现这个物体的外部轮廓。

在这篇文章中,我将阐述一种我的方法来生成一种,精确,连续权重的围绕多边网格模型的外部轮廓线,最近我才注意到,Rossignac 和 van Emmerik 在 1992年出版过的一条相似的技术。

uploads/200702/10_001314_article_outline.png


The technique is very simple:

When rendering the object, write a constant value into the stencil buffer. Then to draw the outline, render the object in wireframe using thick lines wherever the stencil buffer is unset. This will leave a outline around the border of the mesh which is one half the wireframe line thickness.

This can be implemented in OpenGL as shown in the following code snippet.

这个技术非常简单:

当渲染物体时,写一个常数值到模板缓冲中,然后去绘制轮廓,当模板缓冲没有设置的时候,用粗线的线框方式渲染此物体。这样将会留下一个围绕网格模型边缘的轮廓线,其只有网格线宽的二分之一。

这个技术可以在OpenGL中用以下代码段描述。
 glClearStencil(0);
 glClear(GL_STENCIL_BUFFER_BIT);

 // Render the mesh into the stencil buffer.
  
 glEnable(GL_STENCIL_TEST);

 glStencilFunc(GL_ALWAYS, 1, -1);
 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);

 RenderMesh();

 // Render the thick wireframe version.

 glStencilFunc(GL_NOTEQUAL, 1, -1);
 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);

 glLineWidth(3);
 glPolygonMode(GL_FRONT, GL_LINE);
  
 RenderMesh();

One additional detail demonstrated in the sample code is that the stencil buffer can be reset to zero as the wireframe mesh is being rendered. This is done so that each pixel in the outline is rendered only once. When drawing the outline using alpha blending this can be essential to ensure a uniform opacity along the entire outline.

这个代码段中另外一个细节阐释了,当线框网格模型被渲染时,模板缓冲可以重置到零。这样的话保证了在轮廓线中的每个像素都被只渲染一次。当使用alpha混合来渲染轮廓线的时候,它可以足够的保证整个轮廓线围绕的一种一致相同的不透明度。

Additional Notes

If rendering the wireframe version of the mesh is a performance bottleneck, then a simple geometric silhouette detection method can be used to reduce the number of lines which need to be drawn. This algorithm works by identifying edges in the mesh which are bordered by a 'front facing' face and a 'back facing' face. In addition to including all of the lines which make up the true silhouette of the mesh, this set of edges may also include lines which will fall in the interior of the mesh when they are rendered, however these lines will be discarded by the stencil operation described in the first section.

Direct3D does not support thick line rendering, however the same result can be achieved by drawing the lines using a camera-facing quad. Pierre Terdiman presents source code [2] to accomplish this.

Finally, it may be prohibitive for an application to require a stencil buffer just to achieve the outline effect. In the abscense of a stencil buffer, the depth buffer can be used in a similar manner as descibed by Rossignac and van Emmerik [1].

附注

如果网格模型渲染线框的这个版本是性能的瓶颈,那么使用简单的几何轮廓查找方法可以用来有效的减少需要绘制线段的数目。此算法通过标识网格模型里面的边(edges)通过正面向(front facing)和背面向(back facing)区分开来。除了包含网格模型中所有组成最终轮廓的线,这些边的集合在渲染时可能仍然包括网格模型中那些落到内部的线段,尽管如此这些线段将会被在第一节中描述模板操作抛弃掉。

译者注:以上描述算法,即为查找shadow volumne轮廓的算法。

Direct3D 并不支持粗线的渲染(很老的文章了,现在应该支持了),尽管如此,通过使用正面向摄象机的quad来绘制直线同样可以实现此效果。Pierre Terdiman 实现了此方法的代码[2]。

最后,可能一个程序需要使用模板缓冲,仅仅是实现一个勾边效果,会让人望而却步。当缺少模板缓冲的时候,深度缓冲可以使用一个相似的方法来实现,Rossignac 和 van Emmerik 在[1]中描述过。
原创粉丝点击