Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 4 of 4

Thread: How do you implement texture arrays?

  1. #1
    Newbie Newbie
    Join Date
    Dec 2016
    Posts
    4

    Question How do you implement texture arrays?

    Hi! I'm trying to use texture arrays (OpenGL 4.4, GTX 980, Win 10) to make it so I don't have to bind textures each frame, but the fragment shader always outputs a black pixel. Does anyone know what I'm doing wrong? It was working fine with normal textures. Here is my current code (simplified to just show necessary parts, the full code can be found here)

    1. Fragment Shader (GLSL)
    Code :
    	#version 440 core
     
    	in vec2 TexCoords;
    	out vec4 color;
     
    	layout (binding=0) uniform sampler2DArray textureArray;
    	layout (location=1) uniform int layer;
     
    	void main()
    	{    
    	    color = vec4(texture(textureArray, vec3(TexCoords.xy, layer)));
    	}
    2. Initialize Texture Array
    Code :
    	glGenTextures(1, &arrayTexture);
    	glActiveTexture(GL_TEXTURE0);
    	glBindTexture(GL_TEXTURE_2D_ARRAY, arrayTexture);
     
    	glTexStorage3D(GL_TEXTURE_2D_ARRAY,
    		5,                    //5 mipmaps
    		GL_RGB,               //Internal format
    		1024, 1024,           //width,height
    		256                   //Number of layers
    	);
     
    	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);
    2. For each unique texture, upload it using glTexSubImage3D
    Code :
    	glActiveTexture(GL_TEXTURE0);
    	glBindTexture(GL_TEXTURE_2D_ARRAY, arrayTexture);
     
    	if (!texture->loaded) texture->loadImageData();
    	glTexSubImage3D(GL_TEXTURE_2D_ARRAY,
    		0,                      //Mipmap number
    		0, 0, currentSpotInArrayTexture, //xoffset, yoffset, zoffset
    		1024, 1024, 1,          //width, height, depth
    		GL_RGB,                 //format
    		GL_UNSIGNED_BYTE,       //type
    		texture->image); //pointer to data
    	texture->freeImageData();
     
    	texture->textureArrayLocation = currentSpotInArrayTexture;
    	currentSpotInArrayTexture++;
    3. Once all the textures are uploaded, generate mipmaps
    Code :
    	glBindTexture(GL_TEXTURE_2D_ARRAY, arrayTexture);
    	glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
     
    	glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
    4. In the render loop, for each mesh, set the shader's layer uniform (explicitly set at location 1) to the location of that mesh's texture, and bind it (only binding it every frame for testing purposes)
    Code :
    	glActiveTexture(GL_TEXTURE0);
    	glUniform1i(1, textures->at(i).textureArrayLocation);
    	glBindTexture(GL_TEXTURE_2D_ARRAY, arrayTexture);
    Last edited by BrianH; 12-10-2016 at 10:23 AM.

  2. #2
    Member Regular Contributor
    Join Date
    May 2016
    Posts
    467
    did you check for GL / shader compilation / linking errors ?
    https://www.opengl.org/wiki/OpenGL_E...ing_for_errors
    https://www.opengl.org/wiki/Shader_Compilation#Example

    here are 2 examples:
    https://www.opengl.org/wiki/Array_Te...and_Management
    https://sites.google.com/site/john87...-array-texture

    the setup seems correct to me
    set the internal format in glTexStorage3D(...) to GL_RGB8

    there are basically 2 steps:
    -- building the texture
    -- connecting the texture to the sampler in your fragment shader

    go a few steps back, create a texture array with 1 layer, 1 texel / layer, set it to green
    set the texture layer in the fragment shader to index "0" (not a uniform variable)

    can you access green ?

    the next step: set the layer count to 3, set them to
    red= layer 0
    green = layer 1
    blue= layer 2

    change the layer index in the fragment shader to 1
    can you access green ?
    can you access red ?
    can you access blue ?

    then expand each layer to 1024 x 1024, and set each layer to the desired image data
    can you access any image ?

    then use a uniform int to access any layer
    Last edited by john_connor; 12-10-2016 at 11:27 AM.

  3. #3
    Newbie Newbie
    Join Date
    Dec 2016
    Posts
    4
    It started working, not really sure exactly why, but here is the diff if anyone wants to see what I changed. Thank you john_connor, I did use your method of doing 1x1 textures first then moving up to real textures.

  4. #4
    Senior Member OpenGL Pro
    Join Date
    Jan 2007
    Posts
    1,789
    The main thing I see from a cursory glance at the code is that you changed from an unsized to a sized internal format: GL_RGB8 instead of GL_RGB. https://www.opengl.org/sdk/docs/man/...torage3D.xhtml - glTexStorage requires a sized internal format.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •