I get a black cube

Hello. The programs renders a cube. If I set the color in the fragment shader manually, it works, but when I use a texture color, the cube becomes black. I wonder how to fix this?

The cube is rendered using glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0);

The texture is set up as follows:


    GLsizei width = 2;
    GLsizei height = 2;
    GLsizei layerCount = 1;
    GLsizei mipLevelCount = 1;
    float * data_test = new float[width * height * 4];
    for (int i = 0; i < width*height*4; i+=4)
    {
        data_test[i + 0] = 0.25f;
        data_test[i + 1] = 0.45f;
        data_test[i + 2] = 0.95f;
        data_test[i + 3] = 1.00f;
    }

    glGenTextures(1, &game_graphics_admin.texture);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D_ARRAY, game_graphics_admin.texture);
    glTexStorage3D(GL_TEXTURE_2D_ARRAY, mipLevelCount, GL_RGBA, width, height, layerCount);
    glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, layerCount, GL_RGBA, GL_FLOAT, data_test);
    delete[] data_test;

    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glGenerateMipmap(GL_TEXTURE_2D_ARRAY);

Vertex shader fetch:
12 triangles x 3 vertices = 36 vertices that are indexed.
36 x 2 uv texture coordinates

Vertex shader code:


#version 430 core
layout(location = 0) in vec4 position;
layout(location = 5) in vec2 texCoord;
uniform mat4 mv_matrix; 
uniform mat4 proj_matrix; 
out vec2 TexCoords;
void main(void)   
{
   gl_Position = proj_matrix * mv_matrix * position;
   TexCoords = texCoord;
}

Fragment shader code:


#version 430 core
in vec2 TexCoords;
layout (binding=0) uniform sampler2DArray textureArray;
//layout (location=1) uniform int layer;
out vec4 color;

void main(void)  
{
    color = vec4(texture2DArray(textureArray, vec3(TexCoords.xy, 0)));  
}

Texture UV coordinate attribute is taken from a uv-buffer, and for simplicity is made of repeating the 3 coordinate pairs (0.0f,0.0f),(0.0f,1.0f),(1.0f,1.0f), … . It total, 36 uv-pairs.

is

glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2*sizeof(GL_FLOAT), NULL);
glEnableVertexAttribArray(2);

suppose to be…

glVertexAttribPointer(5, 2, GL_FLOAT, GL_FALSE, 2*sizeof(GL_FLOAT), NULL);
glEnableVertexAttribArray(5);

You specify the location in the vertex shader for tex coords to be: layout(location = 5) in vec2 texCoord;

[QUOTE=BenSwolo;1291281]is

glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2*sizeof(GL_FLOAT), NULL);
glEnableVertexAttribArray(2);

suppose to be…

glVertexAttribPointer(5, 2, GL_FLOAT, GL_FALSE, 2*sizeof(GL_FLOAT), NULL);
glEnableVertexAttribArray(5);

You specify the location in the vertex shader for tex coords to be: layout(location = 5) in vec2 texCoord;[/QUOTE]

Thank you for your answer. I tried your advise, currently it doesn’t work.
Take a look at uv-buffer code:


    glGenBuffers(1, &game_graphics_admin.uv_buffer);
    glBindBuffer(GL_ARRAY_BUFFER, game_graphics_admin.uv_buffer);
    GLfloat uv_data[72];
    for (int i = 0; i < 72; i += 6)
    {
        uv_data[i + 0] = 0.0f;
        uv_data[i + 1] = 0.0f;
        uv_data[i + 2] = 0.0f;
        uv_data[i + 3] = 1.0f;
        uv_data[i + 4] = 1.0f;
        uv_data[i + 5] = 1.0f;
    }
    glBufferData(GL_ARRAY_BUFFER,
        sizeof(uv_data),
        &uv_data[0],
        GL_STATIC_DRAW);
    glVertexAttribPointer(5, 2, GL_FLOAT, GL_FALSE, 0, NULL);
    glEnableVertexAttribArray(5);

Here, The uv-coordinates are inputted to the vertex shader via Attribute 5.

But, the texture array is inputted straight to the fragment shader via attribute 2.
Still don’t understand how to fix this error.

[QUOTE=wenhaug;1291289]But, the texture array is inputted straight to the fragment shader via attribute 2.
Still don’t understand how to fix this error.[/QUOTE]

The texture array is specified by a uniform (attributes can’t be samplers):

The [var]binding[/var] qualifier initialises the uniform to refer to texture unit 2, but your code binds the texture to texture unit 0:

Thank you for your answer. I have applied your corrections, and updated my first post’s code to take account for all the replies.
But the cube is unfortunately still black.

In my opinion, the error is about textures, because I checked uv-coordinate correctness by adding the following condition to the fragment shader, and got an expected pattern.


if((TexCoords.x >= 0.1f) && (TexCoords.x <= 0.9f))
    {
        if((TexCoords.y >= 0.1f) && (TexCoords.y <= 0.9f))
        {
            color = vec4(1.0f,1.0f,1.0f,1.0f);
        }        
    } 

Still don’t know how to fix it.

Are you checking for GL errors and shader compile/link errors?

[ul]
[li]OpenGL Error [/li][li]Example/GLSL Shader Compile Error Testing [/li][li]Example/GLSL Program Link Error Testing [/li][/ul]
The texture2DArray() function reference in a #version 430 core shader w/o any #extension present caught my eye. See arekkusu’s post here: LINK, and also EXT_texture_array.

That link is broken due to an extraneous space in the URL (“disc ussion”); should be: LINK.

Gentlemen, I have applied error checking. The results are:
-the shaders compiled ok.
-the shaders linked in a program ok.

But, in this line, the GL_INVALID_ENUM error appears.


glTexStorage3D(GL_TEXTURE_2D_ARRAY, mipLevelCount, GL_RGBA, width, height, layerCount);

See previous answer.

Unsized internal formats are invalid for glTexStorage*. Use e.g. GL_RGBA8.

Now it finally works. Thank you all.