openglfragment-shader3d-texture

OpenGL Texture3D FragmentShader Write Into Layers


i want to filter a texture (no mipmapping) and write the filtered levels into a 3D-Texture. I already created a 3D-Texture with following code:

glGenTextures(1, &outTexture);
glBindTexture(GL_TEXTURE_3D, outTexture);
glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, width, height, layer, 0, GL_RGBA, GL_INT, 0);
glBindTexture(GL_TEXTURE_3D, 0);

and i render my models like so:

glFramebufferTexture3D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_3D, outTexture, 0, layer);
entity.render();

is there a way for a fragment-shader to write into multiple layers at the same time and knowing in which layer you are? Like so?

out_color[layer] = vec4(r,g,b,a);

PS: i need to know in which layer in the fragment shader (some filtering things & please no gl_Layer ... can be only used at OpenGL 4 and i can only use OpenGL 3) ... I could write it into a uniform and render multiple times but if there is a way to go with a one pass ... it would be nice :)


Solution

  • An instance of a fragment shader cannot choose what layer it is writing to. This is chosen for it by the geometry shader that constructed the primitive that generates the fragment in question. So if you want to render to multiple layers, you will need to use layered rendering and GS's.

    If your Fragment Shader needs to know what layer it is writing to, then have the Geometry Shader pass that as a per-vertex parameter:

    //Geometry shader
    flat out int layerIndex;
    
    void main()
    {
      for(int currLayer = 0; currLayer < numLayers; ++currLayer)
      {
        for(int currVertex = 0; currVertex < gl_in.length(); ++currVertex)
        {
          layerIndex = currLayer;
          gl_Layer = currLayer;
          //Compute other per-vertex outputs
          EmitVertex();
        }
        EndPrimitive();
      }
      EmitVertex();
    }
    
    //Fragment shader
    flat in int layerIndex;
    
    void main()
    {
      //Do stuff with layerIndex;
    }