Rendering artifacts when using dot(n,l) as texture lookup coordinate Webgl

时间:2016-07-11 23:23:10

标签: three.js glsl webgl

I'm implementing the xToon shader(pdf) in glsl to use as a shader with Three.js.

I'm getting some rendering artifacts, and I think the problem is due to webgl strangeness that I am not knowledgable about, perhaps relating to a Nan or Inf or something... I'm pulling my hair out.

I'll include the complete fragment and vertex shaders below, but I think this is the offending code located in the fragment shader:

....
vec3 n = normalize(vNormal);
vec3 l = normalize(lightDir);

float d = dot(n, l) * 0.5 + 0.5;

//vec2 texLookUp = vec2(d, loa);
vec2 texLookUp = vec2(d, 0.055);
vec4 dColor = texture2D(texture, texLookUp);
gl_FragColor = dColor;
....

To the best of my debugging efforts there seems to be some problem with using the value d as a component of the texture look up vector. This code produces these strange artifacts:

Shader render

There shouldn't be those yellow "lines" on those contours...

As you may have noted, I'm not actually using the "loa" value in this code. For a while I thought that this problem was in the way I was calculating loa, but it seems that this bug is independent of loa.

Any help would be much appreciated!

The fragment shader:

uniform vec3 lightDir;
uniform sampler2D texture;

varying vec3 vNormal;
varying vec3 vPosition;
varying vec2 vUv;

// loa calculation for texture lookup
varying highp float loa;

void main() {

vec3 n = normalize(vNormal);
vec3 l = normalize(lightDir);

float d = dot(n, l) * 0.5 + 0.5;

//vec2 texLookUp = vec2(d, loa);
vec2 texLookUp = vec2(d, 0.055);
vec4 dColor = texture2D(texture, texLookUp);

gl_FragColor = dColor;
}

And the vertex shader:

uniform vec3 cameraPos;
uniform vec3 lightDir;
uniform vec3 focalPos;
uniform float inflate;
uniform float zmin;
uniform float r;


varying vec3 vNormal;
varying vec2 vUv;

varying float loa;

void main() {
vec3 n = normalize(normal);

// euclidiean distance to point from camera pos
float depth = length(cameraPos - position);

// 1. detail mapping correcting for perspective projection
float z = depth / zmin;

loa = 1.0 - (log2(z)/log2(r));

loa = clamp(loa, 0.055, 0.9);

vNormal = n;
vUv = uv;

gl_Position = projectionMatrix * modelViewMatrix * vec4(normal * inflate + position, 1.0 );
}

1 个答案:

答案 0 :(得分:1)

我通过将纹理设置为ClampToEdgeWrapping而不是RepeatWrapping来解决问题。我被这个堆栈溢出问题引出了这个答案:

MSDN

此博客文章中解释了解决方案: Using floor() function in GLSL when sampling a texture leaves glitch

在THREEjs中处理这个问题的函数是Texture的成员,并在THREEjs文档中进行了解释: http://webglfundamentals.org/webgl/lessons/webgl-3d-textures.html

此外,我需要将min过滤器设置为Nearest以完全摆脱伪影。