-1

I cannot get sampler3D value in my GLSL fragment shader.

I am writing a shader in GLSL and want to take sampler3D (3d texture) as volume data and do volume rendering. However, seems I cannot bind 3d texture to my shader's sampler3D. texture3D() always returns (0,0,0,0) on shader side. But on my application side, I can use glGetTexImage to get the data.

Application Side (dS is a Shader class object):

dS.use();
dS.setInt("volumeData", 0);
uint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_3D, texture);
float data[64];
for (int i = 0; i < 64; ++i)    data[i] = 1.0f;
glTexImage3D(GL_TEXTURE_3D, 0, GL_R16F, 4, 4, 4, 0, GL_RED, GL_FLOAT, data);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_3D, 0);
float read[64];
glBindTexture(GL_TEXTURE_3D, texture);
glGetTexImage(GL_TEXTURE_3D, 0, GL_RED, GL_FLOAT, read);
std::cout << read[0] << "," << read[63] << std::endl;   // 1,1
glBindTexture(GL_TEXTURE_3D, 0);

// When drawing.

dS.use();
dS.setMat4("model", glm::mat4(1.0f));
dS.setMat4("view", view);
dS.setMat4("projection", projection);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D, texture);
cube.draw();

Vertex Shader

#version 330 core
// for snow rendering
layout (location = 0) in vec3 aPos;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    gl_Position = projection * view * model * vec4(aPos, 1.0);
}

Fragment Shader

#version 330
out vec4 FragColor;

uniform sampler3D volumeData;

void main()
{
    ivec3 size = textureSize(volumeData, 0);
    float c = texture3D(volumeData, vec3(0)).x;
    if (size.x == 1)
        FragColor = vec4(1.0, 0.0, c, 1.0);
    else if (size.x > 2)
        FragColor = vec4(0.0, 1.0, 0.0, 1.0);
    else if (size.x == 0)
        FragColor = vec4(0.0, 0.0, 1.0, 1.0);
    else
        FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}

I only got a red cube, which means size.x == 1 and texture3D returns 0, which is expected to be size.x == 4 and texture3D returns 1.0

I used similar method for 2d texture and it works. So I guess my Shader class is right. And I also tried to add glEnable(GL_TEXTURE_3D) before I did any 3d texture operation.

And I am not sure if this helps: I used glfw-3.2.1 WIN64 and glad.

XY Li
  • 1
  • 2
  • 4
    "*If sampler3D works, then at least textureSize should not return (0,0,0).*" Unless it's `textureSize` that's broken, not the sampler. Why don't you remove all of the unneeded bits and verify whether or not you can fetch data from the texture? – Nicol Bolas Apr 24 '19 at 16:58
  • @NicolBolas, I added textureSize because I have tried to just fetch data from the texture using texture3D but it failed. So I combined textureSize and texture3D together to see if it's because I used wrong UVW coordinates or because sampler3D is wrong. – XY Li Apr 25 '19 at 01:32
  • There's no right or wrong texture coordinate when the values in your texture are all the same. Also, `texture3D` is an old function; you're supposed to just use `texture`. And what does "it failed" mean? What color did you get? – Nicol Bolas Apr 25 '19 at 01:49
  • @NicolBolas, "it failed" means texture() or texture3D() only returns (0,0,0,0). Then I used textureSize() and found the size is always (1,1,1). So I think it's because I cannot bind 3d texture to this uniform sampler3D. – XY Li Apr 25 '19 at 02:28
  • @NicolBolas, I solved it, I just used GL_TEXTURE_2D to set MIN and MAG filters, which led to mipmap incompleteness. It's really a stupid typo. Sorry for wasting your time. – XY Li Apr 25 '19 at 02:59
  • see [GPU ray casting (single pass) with 3d textures in spherical coordinates](https://stackoverflow.com/a/55568396/2521214) I used 3D texture in there so just compare for differences ... You can verify the contents and clamping by this [GLSL debug prints](https://stackoverflow.com/a/44797902/2521214) – Spektre Apr 25 '19 at 04:36

1 Answers1

0

I solved it. It's a really stupid typo.

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

should use GL_TEXTURE_3D instead of GL_TEXTURE_2D. And since GL_TEXTURE_MIN_FILTER default state is GL_NEAREST_MIPMAP_LINEAR. It leads to mipmap incompleteness.

XY Li
  • 1
  • 2