WEBGL_depth_texture iPhone 中的精度太低
WEBGL_depth_texture precision is too low in iPhone
最近,我尝试在 WebGL 中为移动浏览器制作延迟渲染器。
为了制作延迟渲染器,我需要将场景对象的深度渲染到纹理中一次。
我知道我可以在渲染场景对象的深度时将深度值打包到 UBYTE RGBA 纹理中。
不过,我不知怎么知道 iPhone 支持 WEBGL_depth_texture。所以,现在我尝试使用该功能而不是使用 UBYTE RGBA。
当我在 PC 浏览器中调试渲染器时效果很好,但深度纹理在 iPhone 浏览器中的精度太低。
这是从渲染的深度纹理渲染到 UBYTE RGBA 的这些深度纹理。
校正深度纹理图像(PC浏览器)
不正确的深度纹理图像(iPhone safari/chrome)
而且,Mac 中的模拟器生成了与 PC 浏览器相同的图像。
这是我用来获取深度纹理像素并渲染成 UBYTE RGBA 纹理的代码。
vec3 packUNorm24(const highp float value){
const vec3 bitSh = vec3(256.0*256.0, 256.0, 1.0);
const vec3 bitMsk = vec3(0.0, 1.0/256.0, 1.0/256.0);
vec3 highp res = fract(value * bitSh);
res -= res.xxy * bitMsk;
return res;
}
vec3 packRanged24(const highp float value,const highp float minimum,const highp float maximum){
return packUNorm24((value - minimum)/(maximum - minimum));
}
uniform sampler2D _depthBuffer;
void main(void)
{
gl_FragColor.rgb = packRanged24(texture2D(_depthBuffer,uv).r,-1.,1.);
gl_FragColor.a = 1.;
}
为什么这些精度太低?
我认为 WEBGL_Depth_Texture 规范 (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) 允许实现在 16、24 或 32 位深度值之间做出决定。
虽然精度可能对您的需求来说太低了,但我认为如果 iPhone 实现选择 16 位而桌面实现选择 24 位或更高版本是不正确的。
As per the OpenGL ES spec, there is no guarantee that the OpenGL ES implementation will use the texture type to determine how to store the depth texture internally. It may choose to downsample the 32-bit depth values to 16-bit or even 24-bit.
最近,我尝试在 WebGL 中为移动浏览器制作延迟渲染器。 为了制作延迟渲染器,我需要将场景对象的深度渲染到纹理中一次。 我知道我可以在渲染场景对象的深度时将深度值打包到 UBYTE RGBA 纹理中。
不过,我不知怎么知道 iPhone 支持 WEBGL_depth_texture。所以,现在我尝试使用该功能而不是使用 UBYTE RGBA。
当我在 PC 浏览器中调试渲染器时效果很好,但深度纹理在 iPhone 浏览器中的精度太低。
这是从渲染的深度纹理渲染到 UBYTE RGBA 的这些深度纹理。
校正深度纹理图像(PC浏览器)
而且,Mac 中的模拟器生成了与 PC 浏览器相同的图像。
这是我用来获取深度纹理像素并渲染成 UBYTE RGBA 纹理的代码。
vec3 packUNorm24(const highp float value){
const vec3 bitSh = vec3(256.0*256.0, 256.0, 1.0);
const vec3 bitMsk = vec3(0.0, 1.0/256.0, 1.0/256.0);
vec3 highp res = fract(value * bitSh);
res -= res.xxy * bitMsk;
return res;
}
vec3 packRanged24(const highp float value,const highp float minimum,const highp float maximum){
return packUNorm24((value - minimum)/(maximum - minimum));
}
uniform sampler2D _depthBuffer;
void main(void)
{
gl_FragColor.rgb = packRanged24(texture2D(_depthBuffer,uv).r,-1.,1.);
gl_FragColor.a = 1.;
}
为什么这些精度太低?
我认为 WEBGL_Depth_Texture 规范 (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) 允许实现在 16、24 或 32 位深度值之间做出决定。
虽然精度可能对您的需求来说太低了,但我认为如果 iPhone 实现选择 16 位而桌面实现选择 24 位或更高版本是不正确的。
As per the OpenGL ES spec, there is no guarantee that the OpenGL ES implementation will use the texture type to determine how to store the depth texture internally. It may choose to downsample the 32-bit depth values to 16-bit or even 24-bit.