'OpenGL texture arrays render the texture completely black

I'm attempting to render a .png image as a texture. However, all that is being rendered is a black square.

Can anybody see any mistakes in my OpenGL GL_TEXTURE_2D setup that might give me a block black square.

#![allow(non_upper_case_globals)]
extern crate glfw;
use self::glfw::{Action, Context, Key};
use std::path::Path;

extern crate gl;
use self::gl::types::*;

use std::ffi::CString;
use std::mem;
use std::os::raw::c_void;
use std::ptr;
use std::str;
use std::sync::mpsc::Receiver;

// settings
const SCR_WIDTH: u32 = 800;
const SCR_HEIGHT: u32 = 600;

const vertexShaderSource: &str = r#"
#version 430 core
layout(location = 0) in vec2 position;
layout(location = 1) in vec2 texCoord;
layout(location = 2) in float layer;
out vec2 uv;
out float layer_get;
void main()
{
    gl_Position = vec4(position.x, position.y, 0.0, 1.0);
    uv = texCoord;
    layer_get = layer;
}
"#;

const fragmentShaderSource: &str = r#"
#version 430 core
out vec4 color;

in vec2 uv;
in float layer_get;

layout (binding=0) uniform sampler2DArray textureArray;

void main()
{
    color = texture(textureArray, vec3(uv.x,uv.y, layer_get));
}
"#;

#[allow(non_snake_case)]
pub fn main() {
    // glfw: initialize and configure
    // ------------------------------
    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
    glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3));
    glfw.window_hint(glfw::WindowHint::OpenGlProfile(
        glfw::OpenGlProfileHint::Core,
    ));
    #[cfg(target_os = "macos")]
    glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));

    // glfw window creation
    // --------------------
    let (mut window, events) = glfw
        .create_window(
            SCR_WIDTH,
            SCR_HEIGHT,
            "LearnOpenGL",
            glfw::WindowMode::Windowed,
        )
        .expect("Failed to create GLFW window");

    window.make_current();
    window.set_key_polling(true);
    window.set_framebuffer_size_polling(true);

    // gl: load all OpenGL function pointers
    // ---------------------------------------
    gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);

    let (shaderProgram, VAO) = unsafe {
        // build and compile our shader program
        // ------------------------------------
        // vertex shader
        let vertexShader = gl::CreateShader(gl::VERTEX_SHADER);
        let c_str_vert = CString::new(vertexShaderSource.as_bytes()).unwrap();
        gl::ShaderSource(vertexShader, 1, &c_str_vert.as_ptr(), ptr::null());
        gl::CompileShader(vertexShader);

        // check for shader compile errors
        let mut success = gl::FALSE as GLint;
        let mut infoLog = Vec::with_capacity(512);
        infoLog.set_len(512 - 1); // subtract 1 to skip the trailing null character
        gl::GetShaderiv(vertexShader, gl::COMPILE_STATUS, &mut success);
        if success != gl::TRUE as GLint {
            gl::GetShaderInfoLog(
                vertexShader,
                512,
                ptr::null_mut(),
                infoLog.as_mut_ptr() as *mut GLchar,
            );
            println!(
                "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n{}",
                str::from_utf8(&infoLog).unwrap()
            );
        }

        // fragment shader
        let fragmentShader = gl::CreateShader(gl::FRAGMENT_SHADER);
        let c_str_frag = CString::new(fragmentShaderSource.as_bytes()).unwrap();
        gl::ShaderSource(fragmentShader, 1, &c_str_frag.as_ptr(), ptr::null());
        gl::CompileShader(fragmentShader);
        // check for shader compile errors
        gl::GetShaderiv(fragmentShader, gl::COMPILE_STATUS, &mut success);
        if success != gl::TRUE as GLint {
            gl::GetShaderInfoLog(
                fragmentShader,
                512,
                ptr::null_mut(),
                infoLog.as_mut_ptr() as *mut GLchar,
            );
            println!(
                "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n{}",
                str::from_utf8(&infoLog).unwrap()
            );
        }

        // link shaders
        let shaderProgram = gl::CreateProgram();
        gl::AttachShader(shaderProgram, vertexShader);
        gl::AttachShader(shaderProgram, fragmentShader);
        gl::LinkProgram(shaderProgram);
        // check for linking errors
        gl::GetProgramiv(shaderProgram, gl::LINK_STATUS, &mut success);
        if success != gl::TRUE as GLint {
            gl::GetProgramInfoLog(
                shaderProgram,
                512,
                ptr::null_mut(),
                infoLog.as_mut_ptr() as *mut GLchar,
            );
            println!(
                "ERROR::SHADER::PROGRAM::COMPILATION_FAILED\n{}",
                str::from_utf8(&infoLog).unwrap()
            );
        }
        gl::DeleteShader(vertexShader);
        gl::DeleteShader(fragmentShader);

        let vertices: [f32; 20] = [
            0.5, 0.5, 0.0, 1.0, 0.0,
            0.5, -0.5, 1.0, 0.0, 0.0, 
            -0.5, -0.5, 1.0, 1.0, 0.0, 
            -0.5, 0.5, 0.0, 1.0, 0.0, 
        ];
        let indices = [
            0, 1, 3,
            1, 2, 3, 
        ];
        let (mut VBO, mut VAO, mut EBO) = (0, 0, 0);
        gl::GenVertexArrays(1, &mut VAO);
        gl::GenBuffers(1, &mut VBO);
        gl::GenBuffers(1, &mut EBO);
        gl::BindVertexArray(VAO);

        gl::BindBuffer(gl::ARRAY_BUFFER, VBO);
        gl::BufferData(
            gl::ARRAY_BUFFER,
            (vertices.len() * mem::size_of::<GLfloat>()) as GLsizeiptr,
            &vertices[0] as *const f32 as *const c_void,
            gl::STATIC_DRAW,
        );

        gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, EBO);
        gl::BufferData(
            gl::ELEMENT_ARRAY_BUFFER,
            (indices.len() * mem::size_of::<GLfloat>()) as GLsizeiptr,
            &indices[0] as *const i32 as *const c_void,
            gl::STATIC_DRAW,
        );

        let stripe = 5 * mem::size_of::<GLfloat>() as GLsizei;
        gl::VertexAttribPointer(0, 2, gl::FLOAT, gl::FALSE, stripe, ptr::null());
        gl::EnableVertexAttribArray(0);

        gl::VertexAttribPointer(
            1,
            2,
            gl::FLOAT,
            gl::FALSE,
            stripe,
            (2 * mem::size_of::<GLfloat>()) as *const c_void,
        );
        gl::EnableVertexAttribArray(1);

        gl::VertexAttribPointer(
            2,
            1,
            gl::FLOAT,
            gl::FALSE,
            stripe,
            (4 * mem::size_of::<GLfloat>()) as *const c_void,
        );
        gl::EnableVertexAttribArray(2);

        gl::BindBuffer(gl::ARRAY_BUFFER, 0);

        gl::BindVertexArray(0);

        let mut texture = 0;
        gl::GenTextures(1, &mut texture);
        gl::ActiveTexture(gl::TEXTURE0);
        gl::BindTexture(gl::TEXTURE_2D_ARRAY, texture);

        // Create storage for the texture. (1 layer of 1000x1000 texels)
        gl::TexStorage3D(
            gl::TEXTURE_2D_ARRAY,
            1,        // no mipmaps
            gl::RGB8, // internal format
            1000,
            1000, // WxH
            1,    // Number of layers
        );

        let img = image::open(&Path::new("FILE_PATH.png")).unwrap();

        let to_rgba = img.to_rgba();
        let data = to_rgba.into_vec();

        gl::TexSubImage3D(
            gl::TEXTURE_2D_ARRAY,
            0, // mipmap number
            0,
            0,
            0, //x, y, z
            325,
            325,
            1,
            gl::RGBA,                               // format
            gl::UNSIGNED_BYTE,                      // type
            &data[0] as *const u8 as *const c_void, // pointer to data
        );

        gl::GenerateMipmap(gl::TEXTURE_2D_ARRAY);
        gl::TexParameteri(
            gl::TEXTURE_2D_ARRAY,
            gl::TEXTURE_MIN_FILTER,
            gl::LINEAR as i32,
        );
        gl::TexParameteri(
            gl::TEXTURE_2D_ARRAY,
            gl::TEXTURE_MAG_FILTER,
            gl::LINEAR as i32,
        );
        gl::TexParameteri(
            gl::TEXTURE_2D_ARRAY,
            gl::TEXTURE_WRAP_S,
            gl::CLAMP_TO_EDGE as i32,
        );
        gl::TexParameteri(
            gl::TEXTURE_2D_ARRAY,
            gl::TEXTURE_WRAP_T,
            gl::CLAMP_TO_EDGE as i32,
        );

        (shaderProgram, VAO)
    };

    // render loop
    // -----------
    while !window.should_close() {
        // render
        // ------
        unsafe {
            gl::ClearColor(0.2, 0.3, 0.3, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT);

            // draw our first triangle
            gl::UseProgram(shaderProgram);
            gl::BindVertexArray(VAO);
            gl::DrawElements(gl::TRIANGLES, 6, gl::UNSIGNED_INT, ptr::null());
        }

        window.swap_buffers();
        glfw.poll_events();
    }
}

The coordinates of the texture

[0.0, 1.0],
[1.0, 0.0],
[1.0, 1.0],
[0.0, 1.0]


Solution 1:[1]

Your texture coordinates are wrong:

let vertices: [f32; 20] = [
   0.5,  0.5, 0.0, 1.0, 0.0,
   0.5, -0.5, 1.0, 0.0, 0.0, 
  -0.5, -0.5, 1.0, 1.0, 0.0, 
  -0.5,  0.5, 0.0, 1.0, 0.0, 
];

The texture coordinate (0, 1) is twice, but (0, 0) is missing.

Correct vertex attributes:

let vertices: [f32; 20] = [
   0.5,  0.5,  1.0, 0.0, 0.0,
   0.5, -0.5,  1.0, 1.0, 0.0, 
  -0.5, -0.5,  0.0, 1.0, 0.0, 
  -0.5,  0.5,  0.0, 0.0, 0.0, 
];
---

You cannot run a version 4.30 GLSL shader in a version 3.3 OpenGL core profile context.

If your hardware supports OpenGL 4.3, switch to a 4.3 OpenGL context:

<s>`glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3));`</s> 
```lang-rust
glfw.window_hint(glfw::WindowHint::ContextVersion(4, 3));

If your hardware does not support OpenGL 4.3, you will need to downgrade the shader program.
GLSL 3.30 doesn't support "binding" layout qualifiers (Binding points). Fortunately, this isn't a huge problem as the default binding point is 0. Therefore, it is sufficient to remove layout (binding=0):

3.30 vertex shader:

#version 330 core
layout(location = 0) in vec2 position;
layout(location = 1) in vec2 texCoord;
layout(location = 2) in float layer;
out vec2 uv;
out float layer_get;
void main()
{
    gl_Position = vec4(position.x, position.y, 0.0, 1.0);
    uv = texCoord;
    layer_get = layer;
}

3.30 fragment shader:

#version 330 core
out vec4 color;

in vec2 uv;
in float layer_get;

//layout (binding=0) uniform sampler2DArray textureArray;
uniform sampler2DArray textureArray;

void main()
{
    color = texture(textureArray, vec3(uv.x,uv.y, layer_get));
}

Result:

Solution 2:[2]

There is also a little issue when shader program fail.

let mut infoLog = Vec::with_capacity(512);
infoLog.set_len(512 - 1); // subtract 1 to skip the trailing null character
   
if success != gl::TRUE as GLint {
  gl::GetShaderInfoLog(
    vertexShader,
    512,
    ptr::null_mut(),
    infoLog.as_mut_ptr() as *mut GLchar,
  );
  let cstr = CStr::from_ptr(infoLog.as_mut_ptr() as *mut GLchar);
  println!(
    "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n{}",
    // str::from_utf8(&infoLog).unwrap() // memory storage as *i8.
    cstr.to_str().unwrap()               // interpret as cstr
  );
}

infoLog is declared as Vec<u8>, but used as *i8 in gl, if we keep treat as Vec<u8> at str::from_utf8(&infoLog).unwrap(), may gets crash.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 xxrl