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

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

问题描述

如果你将一个圆柱体细分为一个 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天全站免登陆