• Advertisement


  • Content count

  • Joined

  • Last visited

Community Reputation

100 Neutral

About d0Sm4o20

  • Rank
  1. After a lot of pain, I figured out that 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!
  2. 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]; } } [/CODE] 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[/CODE] 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, &routine_index); // debugging int num_subs; glGetActiveSubroutineUniformiv(id, target, uniform_index, GL_NUM_COMPATIBLE_SUBROUTINES, &num_subs); std::cout << uniform_index << " " << routine_index << " " << num_subs << "\n"; }[/CODE] 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! [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img] 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?
  3. Bizarre GLSL link error

    [quote name='dpadam450' timestamp='1323038676' post='4890513'] So the last one just doesnt link still? Or does it give you an invalid uniform location? [/quote] Well, it never actually gets to the point where I get the uniform location. The code fails on linking the compiled shaders, so I can't even assign a uniform yet. That's a weird limitation if I can only use a uniform for loops that don't modify an "out" variable, but I'll have to accept it I guess if it's true.
  4. Bizarre GLSL link error

    After a lot of poking at the shader code (and updating my drivers), I've come to the conclusion that I can't do the following things together: I can't have a loop based on a uniform expression AND have that loop alter an "out" array. For example, this works: [code] #version 420 layout(location = 0) in vec4 position; out int derp[10]; uniform int num_lights; void main(void) { for (int i=0; i<10; i++) { derp[i] = i; } gl_Position = position; }[/code] And this works: [code] #version 420 layout(location = 0) in vec4 position; out int derp[10]; uniform int num_lights; void main(void) { int j = 0; for (int i=0; i<num_lights; i++) { j += i; } gl_Position = position; }[/code] But this doesn't: [code] #version 420 layout(location = 0) in vec4 position; out int derp[10]; uniform int num_lights; void main(void) { for (int i=0; i<num_lights; i++) { derp[i] = i; } gl_Position = position; }[/code] Really bizarre behavior.
  5. Bizarre GLSL link error

    Yeah, I think I see what you're saying about unrolling the loops. I googled "glsl uniform loop" and it seems that there have been a lot of people with issues of using a uniform in the expression part of a loop. This could be my problem. If I set the expression to a constant value, either through a #define, or with some fixed value in the code, it works fine. I double-checked my glGetUniformLocation and it's not returning -1, so I think that's fine. It must be the uniform in the loop creating undefined behavior. Might be a bug in the driver. I'm going to upgrade my driver right now actually and see if that solves it.
  6. Bizarre GLSL link error

    [quote name='dpadam450' timestamp='1322971573' post='4890305'] What may be going on is that I have had (and others) where shaders do not work if you dont explicitly use a uniform. Sometimes shaders unroll your loops and since your loop never uses the index "i", it again is probably optimizing it. So STOP IT! [/quote] I probably should've clarified why I wasn't using "i" to index vlight. I was using "i" first, which is where the error first surfaced. So instead, I created "j" just to see if I could get the same bad behavior with a variable that wasn't being compared to num_lights, which it did. I'll keep poking at it more. I'm clearly messing around with some very undefined behavior, so this is turning out to not be easy.
  7. Bizarre GLSL link error

    Update: I've managed to narrow it down to the uniform "num_lights". From my client code, I'm setting num_lights to 1. However, if I comment out "uniform int num_lights" and add an "int num_lights = 1;" to my main(), the code works again. So there's some weirdness with setting the uniform, which is creating even more weirdness in the code. I'm using glProgramUniform1i, and the uniform location is non-negative (it's 34), and the value is an integer. So there doesn't seem to be any error with that. Any insight? Thanks
  8. Hi guys, this is driving my crazy. I have 1 vertex shader and 1 fragment shader linked into 1 program (so far, so good :) However, on the linking stage, my shader crashes, *but only if I make a very specific code alteration*. Here's what *works*: fragment: [code] #version 410 in vec3 vnormal; in vec3 vlight[10]; out vec4 color; uniform vec4 fill_color; void main(void) { color = fill_color; }[/code] vertex: [code] #version 410 layout(location = 0) in vec4 position; layout(location = 1) in vec3 normal; layout(std140) uniform matrices_block { mat4 projection; mat4 modelview; mat3 normal; } mat; out vec3 vnormal; out vec3 vlight[10]; uniform int num_lights; void main(void) { vnormal = mat.normal * normal; vec4 vertex_eye = mat.modelview * position; int j = 0; for (int i=0; i<num_lights; i++) { j = 0; vlight[j] = vec3(0.0); } gl_Position = mat.projection * mat.modelview * position; }[/code] This works fine. Compiles, runs, etc. I know it looks a little crazy that I'm using "j" to index vlight, and setting j=0 every time in the loop, but hear me out for a second. Here's what doesn't work in the vertex shader: If i move this: [code] j = 0; vlight[j] = vec3(0.0);[/code] To this: [code] vlight[j] = vec3(0.0); j = 0;[/code] The shader programs refuse to link. What's worse is, there's no output log from glGetShaderInfoLog, so I can't tell what's going wrong. This is really weird behavior, and it's starting to make me question my drivers. If it's any help, my graphics card is an Nvidia GeForce GTX 485M with driver 280.13. Anyone have any insight on what I can poke at next? Thanks!
  9. [quote name='karwosts' timestamp='1297668631' post='4773989'] You may want to try unbinding the draw texture after you're done using it, it may not like that you're trying to draw to a bound texture, but I'm not sure. [/quote] You beautiful bastard. That's exactly what it was. [img]http://public.gamedev.net/public/style_emoticons/default/laugh.gif[/img] I should've known better too, I remember reading this from the Blue Book: [quote] You may at this point have already asked yourself, “What happens if I have a texture attached to the current FBO and also bound to a texture unit that’s currently in use? Isn’t there a paradox in which I’m currently rendering from the same surface I’m rendering to?” The answer is, “Yes, there’s a paradox, and you’ll tear apart the very fabric of space and time, causing the universe to cease existence.” Or your rendering will be undefined. Either way, don’t do it, I implore you.[/quote] Thanks a ton, karwosts!
  10. It's just really bizarre to me that it would work for the first frame, and not for any of the others. I don't think i'm doing anything permanent to the OpenGL state in that draw() function.
  11. [quote name='karwosts' timestamp='1297665768' post='4773977'] You've called glGetError? [/quote] I've added assert(glGetError() == GL_NO_ERROR); in the draw() function, and everything seems fine :\
  12. [quote name='Asem' timestamp='1297662676' post='4773968'] how did you setup the fbo texture? Are you setting to texture to use mipmap filtering like gl_linear_mipmap_linear? It could be the reason that nothing shows up. Check to see what happens if you take away glgeneratemipmaps function. [/quote] Hey Asem, The problem is that it's rendering correctly for one frame, the first frame, and then getting cleared for all subsequent frames. Here's what I mean: Frame 0: [url="http://i.imgur.com/dkqUs.png"]http://i.imgur.com/dkqUs.png[/url] Frame 1: [url="http://i.imgur.com/1VKYl.png"]http://i.imgur.com/1VKYl.png[/url] Somehow, when draw() is called a second time, it's refusing to draw the white square. Here's how the FBO is getting set up: [code] glGenTextures(1, &fbo_tex); glBindTexture(GL_TEXTURE_2D, fbo_tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, WIDTH, HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glBindTexture(GL_TEXTURE_2D, 0); GLuint rboId; glGenRenderbuffersEXT(1, &rboId); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rboId); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, WIDTH, HEIGHT); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); glGenFramebuffersEXT(1, &fbo); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbo_tex, 0); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rboId); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); GLuint fbo_l = glGetUniformLocation(blur_program, "fbo"); glUseProgram(blur_program); glUniform1i(fbo_l, 0); glUseProgram(0); glBindTexture(GL_TEXTURE_2D, 0);[/code]
  13. Hi guys, I have a texture attached to an FBO that i'm rendering to, and then sending that texture to a shader. It all works fine and well....for 1 frame, the first frame. Then the texture is always black. It seems like the FBO texture can only be drawn to once(!?) in my code, and afterwards, it is erased and only black is drawn to it. It's really driving my nuts. I feel like I'm missing something completely obvious. Here is my main draw function: [code]void draw() { printf("Beginning of draw\n"); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo); // clear the FBO texture and set the draw color glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); // draw a square where the mouse is float x, y, w, h; w = 100.0f; h = 100.0f; x = mouse.x; y = mouse.y; glRectf(x, y, x+w, y+h); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // generate mipmaps for the FBO texture glBindTexture(GL_TEXTURE_2D, fbo_tex); glGenerateMipmapEXT(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); // this should all apply to the actual screen now glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glColor3f(1.0f, 1.0f, 1.0f); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, fbo_tex); // draw a quad which we'll screen align in a vertex shader, and then paint // with the FBO texture in the fragment shader glUseProgram(blur_program); glRecti(0, 0, 1, 1); glFlush(); glUseProgram(0); printf("End of draw\n"); SDL_Delay(1000); }[/code] This is the vertex shader that aligns that second glRecti call to the screen: [code]void main(void) { gl_Position = gl_Vertex * 2.0 - 1.0; gl_TexCoord[0] = gl_Vertex; }[/code] And the fragment shader: uniform sampler2D fbo; [code]void main(void) { gl_FragColor = vec4(texture2D(fbo, gl_TexCoord[0].st)); } [/code] Like I said, it seems to work for only *one frame* (I can see the 100x100 white square for 1 second, thanks to the SDL_Delay(1000))....so it is getting drawn to the FBO texture and the shaders are processing everything correctly. It's just that every time draw() is called *after the first time*, the FBO texture is painted with black. I've changed the clear color on the FBO to red, and indeed the screen is rendered red instead of black, showing that the FBO texture is still being painted, even when the square for some reason is not. I've also tried attaching an arbitrary image as the texture getting fed into my shader, and that works on every frame, showing that the error isn't in my shaders. I'm really at a loss here...why isn't that white 100x100 square being drawn on every draw() call? Any ideas? Thanks in advance!
  • Advertisement