游戏开发论坛

 找回密码
 立即注册
搜索
查看: 3859|回复: 12

物体勾边(译)

[复制链接]

32

主题

1259

帖子

1351

积分

金牌会员

Rank: 6Rank: 6

积分
1351
发表于 2007-2-10 00:11:00 | 显示全部楼层 |阅读模式
原文出处:
http://www.azure.com.cn/article.asp?id=289

如有转载,请注明:
http://www.azure.com.cn

作者: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年出版过的一条相似的技术。



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中用以下代码段描述。


  1.      glClearStencil(0);
  2.      glClear(GL_STENCIL_BUFFER_BIT);

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

  6.      glStencilFunc(GL_ALWAYS, 1, -1);
  7.      glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);

  8.      RenderMesh();

  9.      // Render the thick wireframe version.

  10.      glStencilFunc(GL_NOTEQUAL, 1, -1);
  11.      glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);

  12.      glLineWidth(3);
  13.      glPolygonMode(GL_FRONT, GL_LINE);
  14.        
  15.      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]中描述过。

www.azure.com.cn

197

主题

1041

帖子

1104

积分

金牌会员

Rank: 6Rank: 6

积分
1104
QQ
发表于 2007-2-10 00:16:00 | 显示全部楼层

Re:物体勾边(译)

小小吐巢一下,像楼主这种强人,应该做好引导作用,新人如果照抄你的写法很容易出问题的;)

望了几条关键处理,帮你修补一下

1.
glstencilmask

2.
pushattrib(gl_all_attri)
popattrib

197

主题

1041

帖子

1104

积分

金牌会员

Rank: 6Rank: 6

积分
1104
QQ
发表于 2007-2-10 00:21:00 | 显示全部楼层

Re:物体勾边(译)

对了。楼主,我现在也在弄stencil。

我有一个问题,我做了stencil的参数指定以后,我能不能直接给纹理,glTexCoord,glv...之类的,直接往stencil buffer里面画?我看过大多数处理都是gldrawpixel,拿来处理shadow。

望解答一下,或则直接给我个方法,谢谢

32

主题

1259

帖子

1351

积分

金牌会员

Rank: 6Rank: 6

积分
1351
 楼主| 发表于 2007-2-10 00:31:00 | 显示全部楼层

Re:物体勾边(译)

是shadow volume 吗,
可以参考 www.codesampler.com 中一个例子。

http://www.codesampler.com/usersrc/usersrc_3.htm#oglu_shadow_volume_zfail

197

主题

1041

帖子

1104

积分

金牌会员

Rank: 6Rank: 6

积分
1104
QQ
发表于 2007-2-10 00:41:00 | 显示全部楼层

Re:物体勾边(译)

no no no
不是shadow volume,纹理影射,用来代替projected texture的功能。

我用stencil buffer主要是避免多次渲染。shadow volume是先限定绘制,然后gldrawpixel。shadow volume主要是要算一下light source的位置,这一块算法很复杂。

我再说一次,我要实现直接处理纹理,比如glteximage2d和gldrawpixel的结合,我到现在已经试验了3天了。要是你知道革命的去路,给我指点一下,给个论坛也好。

197

主题

1041

帖子

1104

积分

金牌会员

Rank: 6Rank: 6

积分
1104
QQ
发表于 2007-2-10 00:45:00 | 显示全部楼层

Re:物体勾边(译)

另,我用stencil buffer影射纹理的时候,我还需要light发生作用,这里面还有个对我而言超难得算法。毕竟我不是图形学专业为主,一个做游戏的小虾。

这个算法要是这样的,我影射出去的纹理,受光源引想的话,会涉及到根据影射的高度来计算光到影射纹理的参数(超难的)。

197

主题

1041

帖子

1104

积分

金牌会员

Rank: 6Rank: 6

积分
1104
QQ
发表于 2007-2-10 00:50:00 | 显示全部楼层

Re:物体勾边(译)

另:glut是一套封装基本glfunc的包。我不用glut的(感觉这个包封得倒强不弱,还不如用一些ctrl+v的代码管用)。我都是直接面对汇编级的glfunc在做引擎的图形。

我近两天在搞这块影射的时候,我做了一件很变态的事,我把www.opengl.org全站镜像下来,然后拿uedit在查找stencil buffer的处理技术。发挥想象。。。。

32

主题

1259

帖子

1351

积分

金牌会员

Rank: 6Rank: 6

积分
1351
 楼主| 发表于 2007-2-10 00:56:00 | 显示全部楼层

Re:物体勾边(译)

也许你走了弯路,
不仿把你想实现的效果,说一下。

可能有种更好的解决办法。

197

主题

1041

帖子

1104

积分

金牌会员

Rank: 6Rank: 6

积分
1104
QQ
发表于 2007-2-10 01:04:00 | 显示全部楼层

Re:物体勾边(译)

好。

我要的是,在terrain向放电影那样,高频率,高速的影射纹理。这些发射出去的纹理,用projected texture是可以直接实现的。但是有一点不要忽略。"glTexEnv" 函数的工作机制是,一次只能处理一次影射,如果要大量处理影射,就要反复渲染目标。这是行不通的。

所以我就需要一种,可以面向3维世界的发射纹理出去和目标混合的方法。而当我尝试从stencil中去写纹理像素时,我发现,stencil直接用pixel级的函数操作,而不能直接用纹理级函数,也许stencil可以用纹理级函数,我没找到方法而已。

197

主题

1041

帖子

1104

积分

金牌会员

Rank: 6Rank: 6

积分
1104
QQ
发表于 2007-2-10 01:07:00 | 显示全部楼层

Re:物体勾边(译)

说白了。我要在terrain的地表上,实现纹理影射。我会找个图段,比如沙尘,雨水落下时候的水花,等等。其实这就是在terrain上放电影。这一步关系引擎的技术高度,这点很重要。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-26 10:41

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表