Opengl ES 2.0: части модели закрыты там, где не должны. Виноват ли z-буфер?

Я использую Assimp для рендеринга 3D-моделей с помощью OpenGL ES 2.0. У меня в настоящее время странная проблема, при которой некоторые части модели не видны, даже когда они должны быть. Это легко увидеть на этих картинках:

Текстурированная модель

На этом втором изображении я визуализировал (линеаризованную версию) z-буфера на экране, чтобы увидеть, может ли это быть проблемой z-буфера. Черные пиксели находятся рядом с камерой:

zbuffer render

Я пытался изменить значения для z-near и z-far без какого-либо эффекта. Сейчас я делаю это при инициализации:

glEnable(GL_CULL_FACE);// Cull back facing polygons
glEnable(GL_DEPTH_TEST);

И я также делаю это для каждого кадра:

glClearColor(0.7f, 0.7f, 0.7f, 1.0f);
glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

Я подумал, что это может быть проблема с намоткой лица, поэтому я попытался отключить GL_CULL_FACE, но это не сработало. Я почти уверен, что модель в порядке, поскольку Blender может правильно ее отобразить.

Я использую эти шейдеры прямо сейчас:

// vertex shader
uniform mat4 u_ModelMatrix; // A constant representing the model matrix.
uniform mat4 u_ViewMatrix; // A constant representing the view matrix.
uniform mat4 u_ProjectionMatrix; // A constant representing the projection matrix.

attribute vec4 a_Position; // Per-vertex position information we will pass in.
attribute vec3 a_Normal; // Per-vertex normal information we will pass in.
attribute vec2 a_TexCoordinate; // Per-vertex texture coordinate information we will pass in.

varying vec3 v_Position; // This will be passed into the fragment shader.
varying vec3 v_Normal; // This will be passed into the fragment shader.
varying vec2 v_TexCoordinate; // This will be passed into the fragment shader.


void main()
{
    // Transform the vertex into eye space.
    mat4 u_ModelViewMatrix = u_ViewMatrix * u_ModelMatrix;
    v_Position = vec3(u_ModelViewMatrix * a_Position);

    // Pass through the texture coordinate.
    v_TexCoordinate = a_TexCoordinate;

    // Transform the normal's orientation into eye space.
    v_Normal = vec3(u_ModelViewMatrix * vec4(a_Normal, 0.0));

    // gl_Position is a special variable used to store the final position.
    // Multiply the vertex by the matrix to get the final point in normalized screen coordinates.
    gl_Position = u_ProjectionMatrix * u_ModelViewMatrix * a_Position;
}

А это фрагментный шейдер:

// fragment shader
uniform sampler2D u_Texture; // The input texture.
uniform int u_TexCount;

varying vec3 v_Position; // Interpolated position for this fragment.
varying vec3 v_Normal; // Interpolated normal for this fragment.
varying vec2 v_TexCoordinate; // Interpolated texture coordinate per fragment.

// The entry point for our fragment shader.
void main()
{
    vec3 u_LightPos = vec3(1.0);
    // Will be used for attenuation.
    float distance = length(u_LightPos - v_Position);

    // Get a lighting direction vector from the light to the vertex.
    vec3 lightVector = normalize(u_LightPos - v_Position);

    // Calculate the dot product of the light vector and vertex normal. If the normal and light vector are
    // pointing in the same direction then it will get max illumination.
    float diffuse = max(dot(v_Normal, lightVector), 0.0);

    // Add attenuation.
    diffuse = diffuse * (1.0 / distance);

    // Add ambient lighting
    diffuse = diffuse + 0.2;
    diffuse = 1.0;

    //gl_FragColor = (diffuse * texture2D(u_Texture, v_TexCoordinate));// Textured version

    float d = (2.0 * 0.1) / (100.0 + 0.1 - gl_FragCoord.z * (100.0 - 0.1));
    gl_FragColor = vec4(d, d, d, 1.0);// z-buffer render
}

Я использую VBO с индексами для загрузки геометрии и прочего.

Конечно, я могу вставить какой-нибудь другой код, который, по вашему мнению, может быть уместным, но сейчас я рад получить некоторые идеи о том, что может вызвать это странное поведение, или некоторые возможные тесты, которые я могу провести.


person Esparver    schedule 16.02.2013    source источник


Ответы (1)


Хорошо, я решил проблему. Я публикую решение, так как оно может быть полезно для будущих пользователей Google.

По сути, я не запрашивал буфер глубины. Я делаю весь рендеринг в нативном коде, но вся инициализация контекста Open GL выполняется на стороне Java. Я использовал один из примеров Android (GL2JNIActivity) в качестве отправной точки, но они не запрашивали никакого буфера глубины, и я этого не заметил.

Я решил установить размер буфера глубины равным 24 при настройке ConfigChooser:

setEGLConfigChooser( translucent ?
                         new ConfigChooser(8, 8, 8, 8, 24 /*depth*/, 0) :
                         new ConfigChooser(5, 6, 5, 0, 24 /*depth*/, 0 );
person Esparver    schedule 01.03.2013