WebGL:移动设备上的 Z-Buffer 伪像
WebGL: Z-Buffer artifacts on mobile devices
我有 WebGL 上下文,我正在渲染房间和家具的 3d 模型。它在 PC 上工作正常,但当我在房间内并且我的近平面靠近相机时,它在移动设备上给了我奇怪的 z-fighting 伪像。
当我的裁剪平面远离相机时,即使在移动设备上也一切正常:
近:4267.639824060027,远:11183.900282644734
投影矩阵 = [1.9196896450555059, 0, 0, 0, 0, 1.7320508075688774, 0, 0, 0, 0, -2.234082350944259, -1, 0, 0, -13801.866294355888=1, 0];
但是当
zLimits = {近:30,远:5960.493230110447}
projectionMatrix = [1.9196896450555059, 0, 0, 0, 0, 1.7320508075688774, 0, 0, 0, 0, -1.0101172023425247, -1, 0, 0, -60.303516070275=74, 0]
图片因 z-fighting 和距离第二个对象 1000 个单位的第一个对象的三角形而损坏,并且在第二个对象三角形后面不断闪烁
PS:我尝试在我的着色器中使用
precision highp float
precision highp int
和gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_FLOAT);结果是
WebGLShaderPrecisionFormat {rangeMin: 127, rangeMax: 127, precision: 23}
但它对我没有影响
gl.getParameter(gl.DEPTH_BITS) returns 24;
我有两个渲染路径(前向和延迟DEPTH_COMPONENT32F)并且都给我相同的人工制品
PPS:我通过使用 ThreeJS 渲染的应用程序在同一设备上打开相似的场景,它渲染了相似大小的场景而没有伪影
PPPS:我在前向渲染中使用的顶点和片段着色器
export const geometry = new ShaderProgram(
// vertex shader
`
precision highp float;
uniform mat4 u_transformMatrix;
uniform mat4 u_modelViewMatrix;
uniform mat4 u_meshMatrix;
uniform vec3 u_viewDir;
attribute vec4 a_position;
attribute vec3 a_normal;
attribute vec2 a_texcoord;
varying float v_lighting;
varying vec3 v_normal;
varying vec3 v_position;
varying vec2 v_texcoord;
void main(void)
{
vec4 vertex4 = u_meshMatrix * a_position;
vec3 normal = (u_meshMatrix * vec4(a_normal, 0.0)).xyz;
v_normal = (u_modelViewMatrix * vec4(normal, 0.0)).xyz;;
v_position = (u_modelViewMatrix * vertex4).xyz;
gl_Position = u_transformMatrix * vertex4;
v_lighting = min(abs(dot(normal, u_viewDir)) + 0.4, 1.0);
v_texcoord = a_texcoord;
}
`
,
// fragment shader
`
precision highp float;
uniform lowp vec4 color;
uniform lowp float u_selection;
uniform sampler2D u_texture;
uniform lowp float u_opacity;
uniform lowp vec2 u_textureOffset;
uniform lowp vec2 u_textureScale;
varying float v_lighting;
varying vec2 v_texcoord;
varying vec3 v_normal;
varying vec3 v_position;
void main(void)
{
vec3 cur_color = vec3(0.0, 1.0, 1.0);
float ligtMapVal = v_lighting;
vec2 texCoord = (v_texcoord + u_textureOffset) * u_textureScale;
vec3 texColor = texture2D(u_texture, texCoord).xyz;
//vec3 texColor = vec3(0.4, 0.4, 0.6);
vec3 selectionColor = vec3(0.0, 0.0, 1.0);
vec3 color = mix(texColor, selectionColor, u_selection);
vec3 lightDirection = normalize(vec3(1.0, 1.0, 1.0));
float diffuseWeight = max(dot(v_normal, vec3(0, 0, 1)) + 0.2, 0.5);
vec3 eyeDirection = normalize(-v_position);
vec3 halfVector = normalize(lightDirection + eyeDirection);
float uShininess = 25.1;
float specularWeight = pow(max(dot(v_normal, halfVector), 0.0), uShininess);
vec3 lightSpecular = vec3(1.0, 1.0, 1.0);
gl_FragColor = vec4(color * diffuseWeight + specularWeight * lightSpecular, u_opacity);
}
`
);
问题的主要原因是我编译了一些中等精度的着色器。它们甚至不会被渲染路径使用,而是首先加载。
删除这些着色器可以解决问题。
感谢 LJ 伟大的文档进一步优化它!
我有 WebGL 上下文,我正在渲染房间和家具的 3d 模型。它在 PC 上工作正常,但当我在房间内并且我的近平面靠近相机时,它在移动设备上给了我奇怪的 z-fighting 伪像。
当我的裁剪平面远离相机时,即使在移动设备上也一切正常:
近:4267.639824060027,远:11183.900282644734
投影矩阵 = [1.9196896450555059, 0, 0, 0, 0, 1.7320508075688774, 0, 0, 0, 0, -2.234082350944259, -1, 0, 0, -13801.866294355888=1, 0];
但是当
zLimits = {近:30,远:5960.493230110447}
projectionMatrix = [1.9196896450555059, 0, 0, 0, 0, 1.7320508075688774, 0, 0, 0, 0, -1.0101172023425247, -1, 0, 0, -60.303516070275=74, 0]
图片因 z-fighting 和距离第二个对象 1000 个单位的第一个对象的三角形而损坏,并且在第二个对象三角形后面不断闪烁
PS:我尝试在我的着色器中使用
precision highp float
precision highp int
和gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_FLOAT);结果是 WebGLShaderPrecisionFormat {rangeMin: 127, rangeMax: 127, precision: 23} 但它对我没有影响
gl.getParameter(gl.DEPTH_BITS) returns 24;
我有两个渲染路径(前向和延迟DEPTH_COMPONENT32F)并且都给我相同的人工制品
PPS:我通过使用 ThreeJS 渲染的应用程序在同一设备上打开相似的场景,它渲染了相似大小的场景而没有伪影
PPPS:我在前向渲染中使用的顶点和片段着色器
export const geometry = new ShaderProgram(
// vertex shader
`
precision highp float;
uniform mat4 u_transformMatrix;
uniform mat4 u_modelViewMatrix;
uniform mat4 u_meshMatrix;
uniform vec3 u_viewDir;
attribute vec4 a_position;
attribute vec3 a_normal;
attribute vec2 a_texcoord;
varying float v_lighting;
varying vec3 v_normal;
varying vec3 v_position;
varying vec2 v_texcoord;
void main(void)
{
vec4 vertex4 = u_meshMatrix * a_position;
vec3 normal = (u_meshMatrix * vec4(a_normal, 0.0)).xyz;
v_normal = (u_modelViewMatrix * vec4(normal, 0.0)).xyz;;
v_position = (u_modelViewMatrix * vertex4).xyz;
gl_Position = u_transformMatrix * vertex4;
v_lighting = min(abs(dot(normal, u_viewDir)) + 0.4, 1.0);
v_texcoord = a_texcoord;
}
`
,
// fragment shader
`
precision highp float;
uniform lowp vec4 color;
uniform lowp float u_selection;
uniform sampler2D u_texture;
uniform lowp float u_opacity;
uniform lowp vec2 u_textureOffset;
uniform lowp vec2 u_textureScale;
varying float v_lighting;
varying vec2 v_texcoord;
varying vec3 v_normal;
varying vec3 v_position;
void main(void)
{
vec3 cur_color = vec3(0.0, 1.0, 1.0);
float ligtMapVal = v_lighting;
vec2 texCoord = (v_texcoord + u_textureOffset) * u_textureScale;
vec3 texColor = texture2D(u_texture, texCoord).xyz;
//vec3 texColor = vec3(0.4, 0.4, 0.6);
vec3 selectionColor = vec3(0.0, 0.0, 1.0);
vec3 color = mix(texColor, selectionColor, u_selection);
vec3 lightDirection = normalize(vec3(1.0, 1.0, 1.0));
float diffuseWeight = max(dot(v_normal, vec3(0, 0, 1)) + 0.2, 0.5);
vec3 eyeDirection = normalize(-v_position);
vec3 halfVector = normalize(lightDirection + eyeDirection);
float uShininess = 25.1;
float specularWeight = pow(max(dot(v_normal, halfVector), 0.0), uShininess);
vec3 lightSpecular = vec3(1.0, 1.0, 1.0);
gl_FragColor = vec4(color * diffuseWeight + specularWeight * lightSpecular, u_opacity);
}
`
);
问题的主要原因是我编译了一些中等精度的着色器。它们甚至不会被渲染路径使用,而是首先加载。 删除这些着色器可以解决问题。
感谢 LJ 伟大的文档进一步优化它!