Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 5 of 5

Thread: [SOLVED] GLSL subroutine unselectable

  1. #1
    Junior Member Newbie
    Join Date
    Apr 2012
    Posts
    6

    [SOLVED] GLSL subroutine unselectable

    I'm using a gaussian blur fragment shader. In it, I thought it would be concise to include 2 subroutines: one for selecting the horizontal texture coordinate offsets, and another for the vertical texture coordinate offsets. This way, I just have one gaussian blur shader to manage.

    Here is the code for my shader. The {{NAME}} bits are template placeholders that I substitute in at shader compile time:

    Code :
        #version 420
     
        subroutine vec2 sample_coord_type(int i);
        subroutine uniform sample_coord_type sample_coord;
     
        in vec2 texcoord;
        out vec3 color;
     
        uniform sampler2D tex;
        uniform int texture_size;
     
        const float offsets[{{NUM_SAMPLES}}] = float[]({{SAMPLE_OFFSETS}});
        const float weights[{{NUM_SAMPLES}}] = float[]({{SAMPLE_WEIGHTS}});
     
     
        subroutine(sample_coord_type) vec2 vertical_coord(int i) {
        	return vec2(0.0, offsets[i] / texture_size);
        }
     
        subroutine(sample_coord_type) vec2 horizontal_coord(int i) {
        	//return vec2(offsets[i] / texture_size, 0.0);
        	return vec2(0.0, 0.0); // just for testing if this subroutine gets used
        }
     
        void main(void) {    
            color = vec3(0.0);
     
            for (int i=0; i<{{NUM_SAMPLES}}; i++) {
                color += texture(tex, texcoord + sample_coord(i)).rgb * weights[i];
                color += texture(tex, texcoord - sample_coord(i)).rgb * weights[i];
            }
        }


    Here is my code for selecting the subroutine:

    Code :
        blur_program->start();
        blur_program->set_subroutine("sample_coord", "vertical_coord", GL_FRAGMENT_SHADER);
        blur_program->set_int("texture_size", width);
        blur_program->set_texture("tex", *deferred_output);
        blur_program->draw(); // draws a quad for the fragment shader to run on

    and:

    Code :
        void ShaderProgram::set_subroutine(constr name, constr routine, GLenum target) {
        	GLuint routine_index = glGetSubroutineIndex(id, target, routine.c_str());
        	GLuint uniform_index = glGetSubroutineUniformLocation(id, target, name.c_str());
        	glUniformSubroutinesuiv(target, 1, &amp;routine_index);
     
        	// debugging
        	int num_subs;
        	glGetActiveSubroutineUniformiv(id, target, uniform_index, GL_NUM_COMPATIBLE_SUBROUTINES, &amp;num_subs);
        	std::cout << uniform_index << " " << routine_index << " " << num_subs << "\n";
        }


    I've checked for errors, and there are none. When I pass in `vertical_coord` as the routine to use, my scene is blurred vertically, as it should be. The `routine_index` variable is also 1 (which is weird, because `vertical_coord` subroutine is the first listed in the shader code...but no matter, maybe the compiler is switching things around)

    However, when I pass in `horizontal_coord`, my scene is STILL blurred vertically, even though the value of `routine_index` is 0, suggesting that a different subroutine is being used. Yet the `horizontal_coord` subroutine explicitly does not blur.

    What's more is, whichever subroutine comes first in the shader, is the subroutine that the shader uses permanently. Right now, `vertical_coord` comes first, so the shader blurs vertically always. If I put `horizontal_coord` first, the scene is unblurred, as expected, but then I cannot select the `vertical_coord` subroutine!

    Also, the value of `num_subs` is 2, suggesting that there are 2 subroutines compatible with my `sample_coord` subroutine uniform.

    Just to re-iterate, all of my return values are fine, and there are no glGetError() errors happening.

    Any ideas?

  2. #2
    Member Regular Contributor
    Join Date
    Nov 2003
    Location
    Czech Republic
    Posts
    317

    Re: GLSL subroutine unselectable

    I'd rather use numeric uniform and a bit of math.
    Code :
    uniform vec2 coord_axis;
     
    vec2 sample_coord(int i) {
        	return coord_axis * offsets[i] / texture_size;
    }

    Set coord_axis to either [0,1] or [1,0].

  3. #3
    Junior Member Newbie
    Join Date
    Apr 2012
    Posts
    6

    Re: GLSL subroutine unselectable

    @mfort, that is clever.. Much more simple than my subroutine method

    So I solved my issue:

    I was indirectly calling glUseProgram() twice with my framework. The first time, to set the subroutine, the second time, in the draw() method of my shader program object. Apparently subroutine selection *do not* persist in shader program state, so it was being reset on the second call.

    Hopefully this saves someone some time!

  4. #4
    Senior Member OpenGL Pro
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    1,117

    Re: GLSL subroutine unselectable

    amoffat,
    just to clarify

    glUseProgram(progID)
    ...
    glUniformSubroutinesuiv
    ...
    glUseProgram(progID)

    now I have to reset the subroutines

  5. #5
    Junior Member Newbie
    Join Date
    Apr 2012
    Posts
    6

    Re: GLSL subroutine unselectable

    tonyo_au, that's right. Thanks for clarifying

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •