6

我在从 OBJ 文件加载的对象上使用片段着色器进行 Lambert 和雾着色,但我对多边形有一个小问题。当我将相机位置从对象移开时,我的网格中的一些多边形被“剔除”。

例子:

老实说,我不知道为什么会发生这种情况,以及为什么只有当我远离物体时才会发生这种情况。这是我的着色器:

顶点着色器

# version 400

out struct vData {
    vec4 pos;
    vec4 texcoord;
    vec3 normal;
} fdata;

void main() {
    fdata.texcoord = gl_MultiTexCoord0;
    fdata.normal = normalize(gl_NormalMatrix * gl_Normal);
    fdata.pos = gl_Vertex;
    gl_Position = gl_ModelViewProjectionMatrix * fdata.pos;
}

片段着色器

# version 400

layout(binding=0) uniform sampler2D mainTexture;
uniform vec4 lightColor;
uniform vec4 lightPos;

in struct vData {
    vec4 pos;
    vec4 texcoord;
    vec3 normal;
} fdata;

vec4 ComputeLambert(const in vec3 lightdir, const in vec4 lightColor, const in vec3 normal, const in vec4 diffuse) {
    float nDotL = dot(normal, lightdir);
    return diffuse * lightColor * max(nDotL, 0.0);
}

float ComputeFogFactor(const in vec4 coord, const in float density) {
    const float LOG2 = 1.442695;
    float z = coord.z / coord.w;
    float fogFactor = exp2( -density * density * z * z * LOG2 );
    return clamp(fogFactor, 0.0, 1.0);
}

void main() {
    vec3 mypos = fdata.pos.xyz / fdata.pos.w;
    vec3 lightdir = lightPos.xyz / lightPos.w;
    vec3 direction = normalize(lightdir - mypos);

    vec4 diffuse = texture2D(mainTexture, fdata.texcoord.st);
    diffuse = ComputeLambert(direction,lightColor, fdata.normal, diffuse);

    float fogFactor = ComputeFogFactor(gl_FragCoord,gl_Fog.density);

    vec4 finalcolor = mix(gl_Fog.color, diffuse, fogFactor);
    //vec4 finalcolor = vec4(1.0,1.0,1.0,1.0);
    finalcolor.a = 1.0;
    gl_FragColor = finalcolor;
}

我确保在调用绘图之前禁用面部剔除,所以我很确定这不是问题。有谁知道我能做些什么吗?

4

2 回答 2

1

看起来像 Z-buffer 问题...我知道您已经通过评论查看了它,但是:

  1. 你的截头锥是如何设置的?

    znear,zfar?

  2. 您为 Z 缓冲区使用的位深度是多少?

    当您将这两件事结合在一起时,您可以估计深度精度。

    例如z = <0.1m - 10000.1m>,当然正常的 gl 16 bitfrustrum10000.0/65536=0.15 [m/step]具有非线性 Z 值,因此更接近的精度和远得多的精度

    当您比较模型的步骤和最小细节时,它们与您的问题没有太大不同。

要修复此问题,您可以执行以下操作:

  1. 改变挫折

    放大近值或降低远值

  2. 每个 z 缓冲区使用更多深度位(不适用于所有卡)

  3. 使用更多的截头锥

    对于非常大的渲染范围,我使用更多具有相同视图的截锥体,但

    view1  z = <  0.1,   10.0 >
    view2  z = < 10.0,  100.0 >
    view3  z = <100.0,10000.0 >
    

    当然,您需要在使用另一个截锥体之前清除 z-buffer。视图可以重叠绘制模型的最大尺寸(那么您不需要所有视图中的所有模型只需按范围视图渲染对象)。

    由于多次渲染通道,它比较慢,但在重叠的情况下,减速只是通过范围选择if,这没什么大不了的。

  4. 使用线性 Z 缓冲区值...

    GLSL内部不要使用转换后的 Z 值,而是自己转换它,这使得所有范围内的准确度都相同。而不是在更远的位置呈指数下降

  5. 对模型使用 LOD

    在远距离范围内较低的最小安全精度,但如果您的模型没有 LOD 范围,则很难自己正确计算

PS。它没有剔除,但正面和背面的 z 值精度较低,这可能导致它们错位(甚至将正面更改为背面,反之亦然)

于 2013-11-15T08:19:23.927 回答
1

据我所知,深度缓冲区值不是线性的,因此多边形离相机越远,在某些深度范围内给出的位就越少,从而导致 z 冲突。当您选择视锥体的远平面非常远(如您所说:是地形大小的两倍)时,这个问题会变得更糟。

所以尝试减小截锥体大小(长度)和/或增加 z 缓冲区深度

于 2013-11-15T10:43:40.563 回答