【问题标题】:Normal map from height map artifact来自高度贴图神器的法线贴图
【发布时间】:2013-02-17 03:55:55
【问题描述】:

我正在从高度贴图的片段着色器上烘焙法线贴图。高度图看起来很棒并且看起来很平滑。然而,当我生成法线贴图时,我得到了非常奇怪的结果。

这里有两张显示问题的渲染图像,一张包含所有照明计算,第二张将法线贴图图像应用于网格顶部。

我烘焙法线贴图的方法是在片段着色器上对相邻像素进行采样。

网格为 32x32,法线贴图和高度贴图为 64x64。这是对相邻像素进行采样的片段着色器代码:

float NORMAL_OFF = (1.0 / 64.0);
vec3 off = vec3(-NORMAL_OFF, 0, NORMAL_OFF);

// s11 = Current
float s11 = texture2D(uSampler, texturePos).x;

// s01 = Left
float s01 = texture2D(uSampler, vec2(texturePos.xy + off.xy)).x;

// s21 = Right
float s21 = texture2D(uSampler, vec2(texturePos.xy + off.zy)).x;

// s10 = Below
float s10 = texture2D(uSampler, vec2(texturePos.xy + off.yx)).x;

// s12 = Above
float s12 = texture2D(uSampler, vec2(texturePos.xy + off.yz)).x;

vec3 va = normalize( vec3(off.z, 0.0, s21 - s11) );
vec3 vb = normalize( vec3(0.0, off.z, s12 - s11) );

vec3 normal = normalize( cross(va, vb) );

texturePos 在顶点着色器上计算为 vertexPosition.x / 128(128 因为顶点之间的距离是 4 个像素。所以 32 * 4 = 128)。

为什么我的结果这么奇怪?

【问题讨论】:

    标签: opengl webgl shader normals heightmap


    【解决方案1】:

    您的高度图的采样深度分辨率太低,导致这些步骤很困难。可能您的高度图是 8 位,最多可提供 256 个高度级别。现在,如果您的高度图的平面分辨率高于 256,则横向分辨率不足以表示平滑的高度场。

    解决方案:为您的高度图使用更高的采样分辨率。 16 位是一种流行的选择。

    虽然您的着色器和烘焙代码很好,但它们只是没有获得足够分辨率的输入数据。

    【讨论】:

    • 谢谢!当我将高度图渲染到我的帧缓冲区时,我使用的是 gl.UNSIGNED_BYTE 而不是 gl.FLOAT。这似乎解决了它:-)
    • @raRaRa:您可能还想使用 GL_R16 作为内部格式(OpenGL-3 及更高版本)。根据您的 GPU/驱动程序组合,它可能会产生比 GL_FLOAT 更好或更差的性能。确定它的唯一方法是进行基准测试。
    • 哦,是的。谢谢!对于那些对这里的现场演示感兴趣的人:rarara.minecraft.is
    • @raRaRa:也可以考虑使用 GL_R16F。它提供浮点精度,但没有完整的 GL_R32F 的大小。
    • @NicolBolas:浮点并没有真正提高精度(事实上,半浮点只提供 12 位精度)而是更宽的值范围,其中精度与值的数量级成反比.在某些应用中,这是不可取的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-12
    • 2018-02-02
    • 1970-01-01
    • 2019-01-25
    相关资源
    最近更新 更多