Rendering to a 3D texture

I am planing to implement a rendering process, which calculates the distance to a mesh into each voxel of a volume grid. I want to represent this volume grid with a 3d texture, or 2D array, … I am not sure which one to choose and further I tried to implement some variants and they don’t seem to work. Ma questions are:

[ol]
[li]Which texture typ whould be the best for my case
[/li][li]How do I implement it
[/li][li]How to write an read into this volume grid
[/li][li]How can I check for debugin what is written in a texture/frame buffer
[/li][/ol]

I started with an implementation which doesn’t seem to work:


    glGenFramebuffers(1, &_fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, _fbo);
    
    
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_3D, texture);
    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, GRID_SIZE, GRID_SIZE, GRID_SIZE, 0, GL_RGBA, GL_FLOAT, NULL);
    
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glBindTexture(GL_TEXTURE_3D, 0);
    
    glFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D, texture, 0, 0);
    
    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {
        std::cout << "FBO successfully loadet" << std::endl;
    }else{
        std::cout << "FBO had en ERROR" << std::endl;
    }
    glBindFramebuffer(GL_FRAMEBUFFER, 0);


for the rendering process:

    
    glBindFramebuffer(GL_FRAMEBUFFER, fbo->getFBO());
    
    _shader.use();
    
    glBindVertexArray(_vao);
    
    for (int i = 0; i < GRID_SIZE; ++i) {
        glFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D, fbo->getTextureID(), 0, i);
        glDrawArrays(GL_POINTS, 0, _PointSize);
    }
    
    glBindVertexArray(0);

Here also a thing I don’t really understand. Do I really load a 3Dtexture for each layer that is been rendered? So does he only render in this layer? Or can’t I attache a 3DTexture to the buffer and render to 2DTextures that are been loaded to the layer of the 3DTexture.

The shaders for the moment are straight forward. They are for the moment only rendering white points. I actually wan’t to test that if I render only white points to the 0 layer, than the rest should be black. But as a result either all pixels are black or alle pixels are white :S I hope someone can show me a nice simple implementation for a 3Dtexture or 2DTexture-Array or something similar which i can use, and where I can read out data to, to see that it is written properly. Because something i am doing wrong the hole time :S

OpenGL rendering operations involve modifying a 2D grid of pixels. You can’t directly render primitives into a voxel grid. So you can either:

  • render each layer as a separate operation,
  • attach an entire 3D (or 2D array) texture as a layered framebuffer and select the target layer with a geometry shader which assigns to [var]gl_Layer[/var], or
  • modify the texture directly using image store operations, either in a compute shader or some other shader.

As to whether to use a 3D texture or a 2D array texture, it depends upon what you’re going to do with the resulting texture. The two texture types differ in how they’re accessed (3D textures use texture coordinates with 3 normalised (0…1) components, array textures use 2 normalised components and an non-normalised layer index) and how filtering is handled (3D textures apply linear filtering and mipmapping in all 3 dimensions, array textures only in 2 dimensions).

And for rendering into a certain layer of a 2D array texture, does it work similar as my rendering pass? I iterate through all layers, render for each iteration. If I want to read out the information of the texture, can I read out all informations of all layers at once with glGetTexImage() or do I have to load each 2Dtexture layer with glFramebufferTexture3D()?

In these two situations, there’s no difference between a 3D texture and a 2D array texture (apart from the size of the data when using glGetTexImage() for a level other than zero). The differences are mostly in how sampling behaves.