opengl-esglsltextures3d-texture

GLSL: simulating 3D texture with 2D texture


I came up with some code that simulates 3D texture lookup using a big 2D texture that contains the tiles. 3D Texture is 128x128x64 and the big 2D texture is 1024x1024, divided into 64 tiles of 128x128.

The lookup code in the fragment shader looks like this:

#extension GL_EXT_gpu_shader4 : enable

varying float LightIntensity;
varying vec3 pos;

uniform sampler2D noisef;
vec4 flat_texture3D()
{
    vec3 p = pos;
    vec2 inimg = p.xy;

    int d = int(p.z*128.0);
    float ix = (d % 8); 
    float iy = (d / 8);
    vec2 oc = inimg + vec2(ix, iy);
    oc *= 0.125;

    return texture2D(noisef, oc);
}

void main (void)
{
    vec4 noisevec = flat_texture3D();
    gl_FragColor = noisevec;
}

The tiling logic seems to work ok and there is only one problem with this code. It looks like this:

what it looks like

There are strange 1 to 2 pixel wide streaks between the layers of voxels. The streaks appear just at the border when d changes.
I've been working on this for 2 days now and still without any idea of what's going on here.


Solution

  • This looks like a texture filter issue. Think about it: when you come close to the border, the bilinear filter will consider the neighboring texel, in your case: from another "depth layer".

    To avoid this, you can clamp the texture coords so that they are never outside the rect defined outmost texel centers of the tile (similiar to GL_CLAMP_TO_EDGE, but on a per-tile basis). But you should be aware that the problems will become worse when using mipmapping. You should also be aware, that currently you are not able to filter in the z direction, as a real 3D texture would. You could simulate this manually in the shader, of course.

    But really: why not just using 3D textures? The hw can do all this for you, with much less overhead...