Opengl es 在threejs中实现32位heightmap顶点着色器

Opengl es 在threejs中实现32位heightmap顶点着色器,opengl-es,webgl,vertex-shader,heightmap,Opengl Es,Webgl,Vertex Shader,Heightmap,我试图重新利用heightmap着色器示例,使其能够以32位精度而不是8位精度工作。正在进行的工作代码位于github上: 正在.NET中生成高度贴图。高度在0f…200f范围内,并使用以下方法转换为32位颜色值(单位): private static Color DepthToColor(float height) { var depthBytes = BitConverter.GetBytes(height); int enc = BitConverter.ToInt32(d

我试图重新利用heightmap着色器示例,使其能够以32位精度而不是8位精度工作。正在进行的工作代码位于github上:

正在.NET中生成高度贴图。高度在0f…200f范围内,并使用以下方法转换为32位颜色值(单位):

private static Color DepthToColor(float height)
{
    var depthBytes = BitConverter.GetBytes(height);
    int enc = BitConverter.ToInt32(depthBytes, 0);
    return new Color((enc >> 24 & 255)/255f, (enc >> 16 & 255)/255f, (enc >> 8 & 255)/255f,
            (enc & 255)/255f);
}
颜色数据编码为png,结果如下所示:

顶点着色器获取该图像数据并将RBGA值转换回原始高度值(使用我问题中回答的技术):

结果肯定是一团糟:

我可以通过改变这一行使它变得更平坦:

vAmount = dot(bumpData, vec4(1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0));
这将给我一个更平坦的图像,它至少显示了生成的地形的一个很好的轮廓,但几乎是完全平坦的平面(有轻微的变化,尽管不明显):

我想我做错了一些事情,我只是不知道是什么。我不确定是否正确编码了原始浮点。我不确定是否在顶点着色器中正确解码(我得到的值肯定超出了0…200的范围)。一般来说,我对3d图形也不是很有经验。因此,任何关于我做错了什么或如何实现这一点的指点都将不胜感激


同样,可以在此处找到自包含的“正在进行的工作”代码:

如果将宽整数编码到RGBA向量的分量中,则必须关闭过滤,以便值之间不会发生插值。此外,OpenGL可能会在内部转换为不同的格式,但这只会减少采样深度。

您的颜色:

return new Color((enc >> 24 & 255)/255f, (enc >> 16 & 255)/255f, (enc >> 8 & 255)/255f,
        (enc & 255)/255f);
。。。包含
r
enc
的最高有效字节,以及
g
中的第二个最高有效字节,等等

这:

生成
vAmount
,其中
r
位于最低有效字节,而
g
位于下一个最低有效字节,等等(尽管被乘数应为256、65536等*)。因此字节的顺序不正确。更平淡的版本:

vAmount = dot(bumpData, vec4(1.0, 1.0/255.0, 1.0/65025.0, 1.0/160581375.0));
以正确的顺序获取字节,但将输出值缩放到范围
[0.0,1.0]
,这可能就是它看起来基本平坦的原因

因此,切换编码或解码字节的顺序,并选择适当的比例


(*)这样想:任何频道上可以播放的最小数字是
1.0/255.0
。最低有效通道的范围为
[0,1.0]
-从
0/255.0
255.0/255.0
。您希望缩放下一个通道,使其最小值成为该比例上的下一个对象。所以它的最小值应该是
256/255.0
。因此,您需要将
1.0/255.0
转换为
256.0/255.0
。通过乘以
256
,而不是乘以
255

可以实现这一点。高度贴图的
png
中的噪波看起来肯定是错误的。即使在使用所有通道的深度,你应该至少有一个平滑的渐变在一种颜色,如果你有噪音,它不应该是极端的。因此,我建议将搜索范围缩小到创建高度图的部分。我猜你可能在某个地方访问了未初始化的内存。我假设噪声是使用alpha通道的结果(在这样做时,预期会有噪声)。以下是不使用alpha通道生成的高度贴图;:。诚然,考虑到渐变应该代表的高度,渐变看起来仍然不正确。对不起,我认为我有一个错误的假设:白点实际上是透明像素?png最初是否具有平滑的透明度?您是否将其保存为png-8以在此处显示,并且alpha通道从此丢失?这可以解释为什么会有白点。如果将导出的图像用于着色器,则需要检查PNG创建(如果可以选择8到24)。(使用带有alpha通道的png可能是个问题,因为压缩可能会在图像完全透明的区域产生问题)。它实际上是一个32位png。这是一张在红色背景上的PNG图片,显示了alpha通道:。好的,PNG使用无损压缩,所以顶点着色器应该在无损解压缩数据上运行。
255^3
16581375.0
而不是16 0 581375.0真的很欣赏这个解释。这让我意识到我是如何以及为什么用一种非常天真、错误的方式来编码高度图的。至少现在,一旦我做对了,我就会知道如何在着色器中正确地获得ARGB值。再次感谢!
vAmount = dot(bumpData, vec4(1.0, 255.0, 65025.0, 160581375.0));
vAmount = dot(bumpData, vec4(1.0, 1.0/255.0, 1.0/65025.0, 1.0/160581375.0));