如何在一个四边形上对法线进行双线性插值? [英] How to do bilinear interpolation of normals over a quad?

查看:264
本文介绍了如何在一个四边形上对法线进行双线性插值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究一个类似于Minecraft的引擎,这是一个业余项目,目的是了解在现代硬件和OpenGL> = 3上可以将体素地形的概念推进多远.因此,我所有的几何图形都由四边形或正方形组成准确点.

I'm working on a Minecraft-like engine as a hobby project to see how far the concept of voxel terrains can be pushed on modern hardware and OpenGL >= 3. So, all my geometry consists of quads, or squares to be precise.

我已经建立了一个光线投射器来估计环境光的遮挡,并使用弯曲法线"技术进行照明.因此,我的法线不垂直于四边形,也没有单位长度.相反,它们大致指向发生最少遮挡的空间,当四边形接收的光线较少时,它们会较短.该技术的优点在于,它只需要对遮挡进行一次计算,并且在渲染时基本上是免费的.

I've built a raycaster to estimate ambient occlusion, and use the technique of "bent normals" to do the lighting. So my normals aren't perpendicular to the quad, nor do they have unit length; rather, they point roughly towards the space where least occlusion is happening, and are shorter when the quad receives less light. The advantage of this technique is that it just requires a one-time calculation of the occlusion, and is essentially free at render time.

但是,当我尝试为同一四边形的不同顶点分配不同的法线以获取平滑的光照时,我遇到了麻烦.因为四边形被分成三角形,并且线性插值发生在每个三角形上,所以插值的结果清楚地表明三角形的存在是丑陋的对角线伪影:

However, I run into trouble when I try to assign different normals to different vertices of the same quad in order to get smooth lighting. Because the quad is split up into triangles, and linear interpolation happens over each triangle, the result of the interpolation clearly shows the presence of the triangles as ugly diagonal artifacts:

问题是OpenGL在每个三角形上使用重心插值,这是4个角中的3个角的加权和.理想情况下,我想使用双线性插值法,其中所有4个角都用于计算结果.

The problem is that OpenGL uses barycentric interpolation over each triangle, which is a weighted sum over 3 out of the 4 corners. Ideally, I'd like to use bilinear interpolation, where all 4 corners are being used in computing the result.

我可以想到一些解决方法:

I can think of some workarounds:

  1. 将法线填充为2x2 RGB纹理,然后让纹理处理器执行双线性插值.发生这种情况的代价是在片段着色器中进行纹理查找.我还需要将所有这些微型纹理打包成更大的纹理,以提高效率.

  1. Stuff the normals into a 2x2 RGB texture, and let the texture processor do the bilinear interpolation. This happens at the cost of a texture lookup in the fragment shader. I'd also need to pack all these mini-textures into larger ones for efficiency.

使用顶点属性将所有4个法线附加到每个顶点.还将[0..1]系数附加到每个顶点,就像纹理坐标一样,并在片段着色器中进行双线性插值.发生这种情况的代价是将4个法线传递给着色器,而不是仅传递1个.

Use vertex attributes to attach all 4 normals to each vertex. Also attach some [0..1] coefficients to each vertex, much like texture coordinates, and do the bilinear interpolation in the fragment shader. This happens at the cost of passing 4 normals to the shader instead of just 1.

我认为这两种技术都可以使之起作用,但它们使我为简单得多的东西而感到困惑.也许我可以以某种方式转换法线,以便OpenGL的插值将得出不依赖于所使用的特定三角剖分的结果.

I think both these techniques can be made to work, but they strike me as kludges for something that should be much simpler. Maybe I could transform the normals somehow, so that OpenGL's interpolation would give a result that does not depend on the particular triangulation used.

(请注意,该问题并非特定于法线;它同样适用于颜色或需要在四边形上平滑插值的任何其他值.)

(Note that the problem is not specific to normals; it is equally applicable to colours or any other value that needs to be smoothly interpolated across a quad.)

有什么想法还可以解决这个问题吗?如果不是,那么以上两种技术中哪一种是最好的?

Any ideas how else to approach this problem? If not, which of the two techniques above would be best?

推荐答案

您清楚地了解,GL将要执行的三角插值并不是您想要的. 因此普通数据不能直接来自顶点数据.

As you clearly understands, the triangle interpolation that GL will do is not what you want. So the normal data can't be coming directly from the vertex data.

恐怕您正在设想的解决方案是您可以实现的最佳解决方案.而且无论您选择什么,都需要将[0..1]系数从顶点传递到着色器(包括2x2纹理.您需要它们作为纹理坐标).

I'm afraid the solutions you're envisioning are about the best you can achieve. And no matter what you pick, you'll need to pass down [0..1] coefficients from the vertex to the shader (including 2x2 textures. You need them for texture coordinates).

不过,您可以采取一些技巧来简化流程.

There are some tricks you can do to somewhat simplify the process, though.

  • 使用顶点ID可以帮助您找到要从顶点传递到片段着色器的顶点角"(我们的[0..1]值).对最低的2位进行简单的位测试可以让您知道要向下传递的角,而无需实际的顶点数据输入.如果要打包纹理数据,则仍需要在纹理内部传递一个标识符,因此可能没有意义.
  • 如果您使用2x2纹理进行插值,则有一些问题.如果源开始时的精度较低,则某些纹理插值器不一定会提供高精度插值.这可能需要您将纹理数据类型更改为更高的精度,以避免出现条带失真.

这篇关于如何在一个四边形上对法线进行双线性插值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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