Search code examples
c++openglglsltexturesfragment-shader

Fragment Shader seems to fail after combining GL_TEXTURE_BUFFER and GL_TEXTURE_1D


Currently, I'm trying to implement a fragment shader, which mixes colors of different fluid particles by combining the percentage of the fluids' phases inside the particle. So for example, if fluid 1 possesses 15% of the particle and fluid 2 possesses 85%, the resulting color should reflect that proportion. Therefore, I have a buffer texture containing the percentage reflected as a float value in [0,1] per particle and per phase and a texture containing the fluid colors.

The buffer texture does currently contain the percentages for each particle in a subsequential list. That is for example:

| Particle 1 percentage 1 | Particle 1 percentage 2 | Particle 2 percentage 1 | Particle 2 percentage 2 | ...

I already tested the correctness of the textures by assigning them to the particles directly or by assigning the volFrac to the red part of the final color. I also tried different GLSL debuggers trying to analyze the problem, but none of the popular options did work on my machine after trying.

#version 330

uniform float radius;
uniform mat4 projection_matrix;

uniform uint nFluids;

uniform sampler1D colorSampler;
uniform samplerBuffer volumeFractionSampler;

in block
{
    flat vec3 mv_pos;
    flat float pIndex;
}
In;

out vec4 out_color;

void main(void)
{
    vec3 fluidColor = vec3(0.0, 0.0, 0.0);

    for (int fluidModelIndex = 0; fluidModelIndex < int(nFluids); fluidModelIndex++)
    {
        float volFrac = texelFetch(volumeFractionSampler, int(nFluids * In.pIndex) + fluidModelIndex).x;

        vec3 phaseColor = texture(colorSampler, float(fluidModelIndex)/(int(nFluids) - 1)).xyz;

        fluidColor = volFrac * phaseColor;
    }

    out_color = vec4(fluidColor, 1.0);
}

And also a short snippet of the texture initialization

    //Texture Initialisation and Manipulation here
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_1D, m_textureMap);

    glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, nFluids, 0, GL_RGB, GL_FLOAT, color_map);

    //Creation and Initialisation for Buffer Texture containing the volume Fractions
    glBindBuffer(GL_TEXTURE_BUFFER, m_texBuffer);
    glBufferData(GL_TEXTURE_BUFFER, nFluids * nParticles * sizeof(float), m_volumeFractions.data(), GL_STATIC_DRAW);
    glBindBuffer(GL_TEXTURE_BUFFER, 0);

    glBindTexture(GL_TEXTURE_BUFFER, m_bufferTexture);
    glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, m_texBuffer);

The problem now is, that if I multiply the information of the buffer texture with the information of the texture, the particles that should be rendered disappear completely without any warnings or other error messages. So the particles disappear if I use the statement:

fluidColor = volFrac * phaseColor;

Does anybody know, why this is the case or how I can further debug this problem?


Solution

  • Does anybody know, why this is the case

    Yes. You seem to use the same texture unit for both colorSampler and volumeFractionSampler which is simply not allowed as per the spec. Quoting from section 7.11 of the OpenGL 4.6 core profile spec:

    It is not allowed to have variables of different sampler types pointing to the same texture image unit within a program object. This situation can only be detected at the next rendering command issued which triggers shader invocations, and an INVALID_OPERATION error will then be generated.

    So while you can bind different textures do the different targets of texture unit 0 at the same time, each draw call can only use one particular target per texture unit. If you only use one sampler or the other (and the shader compilere will aggresively optimize these out if they don't influence the outputs of your shader), you are in a legal use case, but as soon as you use both, it will not work.