1

Я работаю над некоторыми проектами в SDK Google Cardboard и испытываю некоторые проблемы с моим первым примером, связанным с текстурами. Я собрал свой пример с кодом из Cardboard SDK example и некоторыми online tutorials. Вы можете просмотреть и проверить источник проекта here.Освещение + текстурный шейдер на Android OpenGL ES (и картон SDK) не показывает текстуры

Моя проблема должна быть довольно очевидной, если вы клонируете и строите проект. Я также создал ветку «lighting», которая представляет мою попытку добавить освещение в текстурированный шейдер. Единственное изменение заключается в установке указателя атрибута версальных нормалей и умножении на диффузное значение на цвет в шейдере. Это изменение превращает мой дисплей от этого: enter image description here

к этому: enter image description here

Очевидно, что первое изображение не имеет никакого освещения на земле, а второй имеет освещение, но не текстуры. Что дает?

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

В случае, если вы слишком ленивы, чтобы пойти посмотреть на мой тайник репо, вот некоторые из важных кода;) функция

Draw:

public void draw(float[] view, float[] perspective, float[] model) { 
    GLES20.glUseProgram(program); 

    // Set the active texture unit to texture unit 0. 
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 

    // Bind the texture to this unit. 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId); 

    // Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0. 
    GLES20.glUniform1i(textureParam, 0); 

    Matrix.multiplyMM(modelView, 0, view, 0, model, 0); 
    Matrix.multiplyMM(modelViewProjection, 0, perspective, 0, modelView, 0); 

    GLES20.glUniform3fv(lightPosParam, 1, RenderBox.instance.mainLight.lightPosInEyeSpace, 0); 
    GLES20.glUniform4fv(lightColParam, 1, RenderBox.instance.mainLight.color, 0); 

    // Set the ModelView in the shader, used to calculate lighting 
    GLES20.glUniformMatrix4fv(MVParam, 1, false, modelView, 0); 

    // Set the position of the cube 
    GLES20.glVertexAttribPointer(positionParam, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer); 

    // Set the ModelViewProjection matrix in the shader. 
    GLES20.glUniformMatrix4fv(MVPParam, 1, false, modelViewProjection, 0); 


    // Set the normal positions of the cube, again for shading 
    if(normalParam > -1) 
     GLES20.glVertexAttribPointer(normalParam, 3, GLES20.GL_FLOAT, false, 0, normalBuffer); 
    GLES20.glVertexAttribPointer(texCoordParam, 2, GLES20.GL_FLOAT, false, 0, texCoordBuffer); 


    GLES20.glDrawElements(GLES20.GL_TRIANGLES, numIndices, GLES20.GL_UNSIGNED_SHORT, indexBuffer); 
} 

вершинный шейдер:

uniform mat4 u_MVPMatrix; 
uniform mat4 u_MVMatrix; 

attribute vec4 a_Position; 
attribute vec3 a_Normal; 
attribute vec2 a_TexCoordinate; 

varying vec3 v_Position; 
varying vec3 v_Normal; 
varying vec2 v_TexCoordinate; 

void main() { 
    // Transform the vertex into eye space. 
    v_Position = vec3(u_MVMatrix * a_Position); 

    // Pass through the color. 
    //v_Color = a_Color; 

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

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

    // Multiply the vertex by the matrix to get the final point in normalized screen coordinates. 
    gl_Position = u_MVPMatrix * a_Position; 
} 

фрагмент шейдера:

precision mediump float;  // Set the default precision to medium. We don't need as high of a 
          // precision in the fragment shader. 
uniform vec3 u_LightPos;  // The position of the light in eye space. 
uniform vec4 u_LightCol; 
uniform sampler2D u_Texture; // The input texture. 

varying vec3 v_Position;  // Interpolated position for this fragment. 
          // triangle per 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() { 
    // 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/(1.0 + (0.1 * distance))); 

    // Add ambient lighting 
    //diffuse = diffuse + 0.3; //No ambient lighting.... this is space 

    // Multiply the color by the diffuse illumination level and texture value to get final output color. 
    //gl_FragColor = (v_Color * diffuse * texture2D(u_Texture, v_TexCoordinate)); 
    //gl_FragColor = u_LightCol * diffuse * texture2D(u_Texture, v_TexCoordinate); 
    //gl_FragColor = texture2D(u_Texture, v_TexCoordinate); 
    gl_FragColor = texture2D(u_Texture, v_TexCoordinate) * diffuse; 
    //gl_FragColor = u_LightCol * diffuse; 
} 

ответ

1

Я нашел ответ! Спасибо @jimbo00000 за указание, что мне нужно вызвать glEnableVertexAttribArray для всех моих атрибутов! Я не называл это вообще для этого конкретного материала. Я знал, что это будет просто!

Чтобы было ясно, мне просто нужно добавить

GLES20.glEnableVertexAttribArray(positionParam); 
GLES20.glEnableVertexAttribArray(normalParam); 
GLES20.glEnableVertexAttribArray(texCoordParam); 

в моем шаге настройки шейдера.