低多边形锥体 - 尖端的平滑阴影 [英] Low polygon cone - smooth shading at the tip

查看:21
本文介绍了低多边形锥体 - 尖端的平滑阴影的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果你将一个圆柱体细分为一个 8 边棱柱体,根据它们的位置计算顶点法线(平滑着色"),它看起来很不错.

If you subdivide a cylinder into an 8-sided prism, calculating vertex normals based on their position ("smooth shading"), it looks pretty good.

如果你将一个圆锥细分为一个 8 边棱锥,根据它们的位置计算法线,你会卡在圆锥的尖端(技术上是圆锥的顶点,但我们称之为尖端以避免与网格顶点).

If you subdivide a cone into an 8-sided pyramid, calculating normals based on their position, you get stuck on the tip of the cone (technically the vertex of the cone, but let's call it the tip to avoid confusion with the mesh vertices).

对于每个三角形面,您希望沿着两条边匹配法线.但是因为您只能在三角形的每个顶点指定一个法线,所以您可以匹配一条边或另一条边,但不能同时匹配两者.您可以通过选择两条边的平均值作为尖端法线来妥协,但现在您的任何一条边都不好看.这是为每个尖端顶点选择平均法线的详细信息.

For each triangular face, you want to match the normals along both edges. But because you can only specify one normal at each vertex of a triangle, you can match one edge or the other, but not both. You can compromise by choosing a tip normal that is the average of the two edges, but now none of your edges look good. Here is a detail of what choosing the average normal for each tip vertex looks like.

在一个完美的世界中,GPU 可以光栅化一个真正的四边形,而不仅仅是三角形.然后我们可以用退化四边形指定每个面,允许我们为每个三角形的两个相邻边指定不同的法线.但是我们只需要处理三角形......我们可以将锥体切割成多个堆叠",这样边缘的不连续性只在锥体的尖端可见,而不是沿着整个物体可见,但仍然会有一个提示!

In a perfect world, the GPU could rasterize a true quad, not just triangles. Then we could specify each face with a degenerate quad, allowing us to specify a different normal for the two adjoining edges of each triangle. But all we have to work with are triangles... We can cut the cone into multiple "stacks", so that the edge discontinuities are only visible at the tip of the cone rather than along the whole thing, but there will still be a tip!

有人对平滑阴影的低多边形锥体有什么技巧吗?

Anybody have any tricks for smooth-shaded low-poly cones?

推荐答案

我在现代 OpenGL(即着色器)中遇到了由三角形组成的锥体问题,但后来我找到了一个非常简单的解决方案!我会说它比当前接受的答案中建议的要好得多,也更简单.

I was struggling with cones in modern OpenGL (i.e. shaders) made up from triangles a bit but then I found a surprisingly simple solution! I would say it is much better and simpler than what is suggested in the currently accepted answer.

我有一组三角形(显然每个三角形有 3 个顶点),它们构成了锥面.我不关心底面(圆形底座),因为这真的很简单.在我所有的工作中,我使用以下简单的顶点结构:

I have an array of triangles (obviously each has 3 vertices) which form the cone surface. I did not care about the bottom face (circular base) as this is really straightforward. In all my work I use the following simple vertex structure:

  • position: vec3(在着色器中通过添加 1.0f 作为最后一个元素自动转换为 vec4)

  • position: vec3 (was automatically converted to vec4 in the shader by adding 1.0f as the last element)

normal_vector: vec3(在着色器中保持为 vec3,因为它用于计算与光方向的点积)

normal_vector: vec3 (was kept as vec3 in the shaders as it was used for calculation dot product with the light direction)

color: vec3(我没有使用透明度)

在我的顶点着色器中,我只变换了顶点位置(乘以投影和模型-视图矩阵),也变换了法向量(乘以变换后的模型-视图矩阵的逆).然后将转换后的位置、法线向量和未转换的颜色传递给片段着色器,在那里我计算光方向和法线向量的点积,并将这个数字与颜色相乘.

In my vertex shader I was only transforming the vertex positions (multiplying by projection and model-view matrix) and also transforming the normal vectors (multiplying by transformed inverse of model-view matrix). Then the transformed positions, normal vectors and untransformed colors were passed to fragment shader where I calculated the dot product of light direction and normal vector and multiplied this number with the color.

让我从我做了但不满意的事情开始:

Let me start with what I did and found unsatisfactory:

尝试#1:每个锥面(三角形)都使用一个恒定的法向量,即一个三角形的所有顶点都具有相同的法向量.这很简单,但没有实现平滑的照明,每个面都有一个恒定的颜色,因为三角形的所有片段都有相同的法向量.错了.

Attempt#1: Each cone face (triangle) was using a constant normal vector, i.e. all vertices of one triangle had the same normal vector. This was simple but did not achieve smooth lighting, each face had a constant color because all fragments of the triangle had the same normal vector. Wrong.

尝试#2:我分别计算了每个顶点的法线向量.这对于圆锥的圆形底部的顶点来说很容易,但是圆锥的尖端应该使用什么?我使用了整个三角形的法向量(即与尝试#中的值相同).嗯,这更好,因为我在靠近锥体底部的部分有平滑的照明,但在靠近尖端的部分不平滑.错了.

Attempt#2: I calculated the normal vector for each vertex separately. This was easy for the vertices on the circular base of the cone but what should be used for the tip of the cone? I used the normal vector of the whole triangle (i.e. the same value as in attempt#). Well this was better because I had smooth lighting in the part closer to the base of the cone but not smooth near the tip. Wrong.

但后来我找到了解决方案:

But then I found the solution:

尝试#3:除了我在锥尖顶点中分配的法向量等于零向量 vec3(0.0f, 0.0f, 0.0F).这是诀窍的关键! 然后将这个零法向量传递给片段着色器(即在顶点和片段着色器之间,它会自动与其他两个顶点的法向量进行插值).当然那么您需要在片段 (!) 着色器中对向量进行归一化,因为它的大小不是固定的 1(我需要点积).所以我将它标准化 - 当然这对于法线向量大小为零的圆锥体的最尖端是不可能的.但它适用于所有其他点.就是这样.

Attempt#3: I did everything as in attempt#2 except I assigned the normal vector in the cone-tip vertices equal to zero vector vec3(0.0f, 0.0f, 0.0f). This is the key to the trick! Then this zero normal vector is passed to the fragment shader, (i.e. between vertex and fragment shaders it is automatically interpolated with the normal vectors of the other two vertices). Of course then you need to normalize the vector in the fragment (!) shader because it does not have constant size of 1 (which I need for the dot product). So I normalize it - of course this is not possible for the very tip of the cone where the normal vector has the size of zero. But it works for all other points. And that's it.

有一件重要的事情要记住,要么你只能在片段着色器中归一化法线向量.如果您尝试在 C++ 中归一化零大小的向量,肯定会出错.因此,如果由于某种原因在进入片段着色器之前需要标准化,请确保排除大小为零的法线向量(即锥体的尖端,否则会出错).

There is one important thing to remember, either you can only normalize the normal vector in the fragment shader. Sure you will get error if you try to normalize vector of zero size in C++. So If you need normalization before entering into fragment shader for some reason make sure you exclude the normal vectors of size of zero (i.e. the tip of the cone or you will get error).

这会在除锥尖的点之外的所有点上产生锥体的平滑阴影.但这一点并不重要(谁在乎一个像素......)或者你可以用一种特殊的方式来处理它.另一个优点是您甚至可以使用非常简单的着色器.唯一的变化是在片段着色器中标准化法向量,而不是在顶点着色器中甚至之前.

This produces smooth shading of the cone in all points except the very point of the cone-tip. But that point is just not important (who cares about one pixel...) or you can handle it in a special way. Another advantage is that you can use even very simple shader. The only change is to normalize the normal vectors in the fragment shader rather than in vertex shader or even before.

这篇关于低多边形锥体 - 尖端的平滑阴影的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆