How to achieve depth value invariance between two passes? - opengl
I have two geometry passes. In the first pass, I write the fragment's depth value to a float texture with glBlendEquation(GL_MIN), similar to dual depth peeling. In the second pass I use it for early depth testing in the fragment shader.
However, for some fragments the depth test fails unless I slightly offset the min depth value (eps below):
Setting up the texture:
glBindTexture(GL_TEXTURE_2D, offscreenDepthMapTextureId);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG32F, screenWidth, screenHeight);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, offscreenDepthMapFboId);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
offscreenDepthMapTextureId, 0);
Note that the texture is used as a color attachment, not the depth attachment. I have disabled GL_DEPTH_TEST in both passes, since I can't use it in the final pass.
Vertex shader, used in both passes:
#version 430
layout(location = 0) in vec4 position;
uniform mat4 mvp;
invariant gl_Position;
void main()
{
gl_Position = mvp * position;
}
First pass fragment shader, with offscreenDepthMapFboId bound, so it writes the depth as color to the texture. Blending makes sure that only the min value ends up in the red component.
#version 430
out vec4 outputColor;
void main()
{
outputColor.rg = vec2(gl_FragCoord.z, -gl_FragCoord.z);
}
Second pass, writing to the default framebuffer. The texture is used as depthTex.
#version 430
out vec4 outputColor;
uniform sampler2D depthTex;
void main()
{
vec2 zwMinMax = texelFetch(depthTex, ivec2(gl_FragCoord.xy), 0).rg;
float zwMin = zwMinMax.r;
float zwMax = -zwMinMax.g;
float eps = 0;// doesn't work
//float eps = 0.0000001; // works
if (gl_FragCoord.z > zwMin + eps)
discard;
outputColor = vec4(1, 0, 0, 1);
}
The invariant qualifier in the vertex shader didn't help. Using eps = 0.0000001 seems like a crude workaround as I can't be sure that this particular value will always work. How do I get the two shaders to produce the exact same gl_FragCoord.z? Or is the depth texture the problem? Wrong format? Are there any conversions happening that I'm not aware of?
Have you tried glDepthFunc(GL_EQUAL) instead of your in-shader-comparison-approach?
Are you reading and writing to the same depth-texture in the same pass?
Im not sure if gl_FragCoord's format and precision is correlated with the one of the depth-buffer. Also it might be a driver glitch, but glDepthFunc(GL_EQUAL) should work as expected.
Do not use gl_FragCoord.z as the depth value.
In vertex shader:
out float depth;
void main()
{
...
depth = ((gl_DepthRange.diff * (gl_Position.z / glPosition.w)) +
gl_DepthRange.near + gl_DepthRange.far) / 2.0;
}
Related
OpenGL - uniform presence causing shader to be bypassed
UPDATE: So it turns out this was due to a bug in the C side of things, causing some of the matrix to become malformed. The shaders are all fine. So if adding uniforms causes weird things to happen, my advice would be to use a debugger to check the value of ALL uniforms and make sure that they are all being set correctly. So I am trying to render depth to a cube map to use as a shadow map, but when I add and use a uniform in the fragment shader everything becomes white as if the shader isn't being used. No warnings or errors are generated when compiling/linking the shader. The shader program I am using to render the depth map (setting the depth simply to the fragment z position as a test) is as follows: //vertex shader #version 430 in layout(location=0) vec4 vertexPositionModel; uniform mat4 modelToWorldMatrix; void main() { gl_Position = modelToWorldMatrix * vertexPositionModel; } //geometry shader #version 430 layout (triangles) in; layout (triangle_strip, max_vertices=18) out; out vec4 fragPositionWorld; uniform mat4 projectionMatrices[6]; void main() { for (int face = 0; face < 6; face++) { gl_Layer = face; for (int i = 0; i < 3; i++) { fragPositionWorld = gl_in[i].gl_Position; gl_Position = projectionMatrices[face] * fragPositionWorld; EmitVertex(); } EndPrimitive(); } } //Fragment shader #version 430 in vec4 fragPositionWorld; void main() { gl_FragDepth = abs(fragPositionWorld.z); } The main shader samples from the cubemap and simply renders the depth as greyscale colour: vec3 lightDirection = fragPositionWorld - pointLight.position; float closestDepth = texture(shadowMap, lightDirection).r; finalColour = vec4(vec3(closestDepth), 1.0); The scene is a small cube in a larger cubic room, and renders as expected, dark near z = 0 and the cube projected back onto the wall (The depth map is being rendered from the centre of the room): Good: [2 I can move the small cube around and the projection projects correctly onto all the sides of the cubemap. All good so far. The problem is when I add a uniform to the fragment shader, i.e: #version 430 in vec4 fragPositionWorld; uniform vec3 lightPos; void main() { gl_FragDepth = min(lightPos.y, 0.5); } Everything renders as white, same as if the render failed to compile: Bad: gDEBugger reports that the uniform is set correctly (0,4,0) but regardless of what that lightPos is, gl_FragDepth should be set to a value less than 0.5 and appear a shade of grey (which is what happens if I set gl_FragDepth = 0.5 directly), so I can only conclude that the fragment shader is not being used for some reason and the default one is being use instead. Unfortunately I have no idea why.
Fragment shader always uses 1.0 for alpha channel
I have a 2d texture that I loaded with glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, gs.width(), gs.height(), 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, gs.buffer()); where gs is an object that with methods that return the proper types. In the fragment shader I sample from the texture and attempt to use that as the alpha channel for the resultant color. If I use the sampled value for other channels in the output texture it produces what I would expect. Any value that I use for the alpha channel appears to be ignored, because it always draws Color. I am clearing the screen using: glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); Can anyone suggest what I might be doing wrong? I am getting an OpenGL 4.0 context with 8 red, 8 green, 8 blue, and 8 alpha bits. Vertex Shader: #version 150 in vec2 position; in vec3 color; in vec2 texcoord; out vec3 Color; out vec2 Texcoord; void main() { Texcoord = texcoord; Color = color; gl_Position = vec4(position, 0.0, 1.0); } Fragment Shader: #version 150 in vec3 Color; in vec2 Texcoord; out vec4 outColor; uniform sampler2D tex; void main() { float t = texture(tex, Texcoord); outColor = vec4(Color, t); }
Frankly, I am surprised this actually works. texture (...) returns a vec4 (unless you are using a shadow/integer sampler, which you are not). You really ought to be swizzling that texture down to just a single component if you intend to store it in a float. I am guessing you want the alpha component of your texture, but who honestly knows -- try this instead: float t = texture (tex, Texcoord).a; // Get the alpha channel of your texture A half-way decent GLSL compiler would warn/error you for doing what you are trying to do right now. I suspect yours is as well, but you are not checking the shader info log when you compile your shader. Update: The original answer did not even begin to address the madness you are doing with your GL_DEPTH_COMPONENT internal format texture. I completely missed that because the code did not fit on screen. Why are you using gs.rgba() to pass data to a texture whose internal and pixel transfer format is exactly 1 component? Also, if you intend to use a depth texture in your shader then the reason it is always returning a=1.0 is actually very simple: Beginning with GLSL 1.30, when sampled using texture (...), depth textures are automatically setup to return the following vec4: vec4 (r, r, r, 1.0). The RGB components are replaced with the value of R (the floating-point depth), and A is replaced with a constant value of 1.0.
Your issue is that you're only passing in a vec3 when you need a vec4. RGBA - 4 components, not just three.
How do I get textures to work in OpenGL?
I'm using the tutorials on http://arcsynthesis.org/gltut/ to learn OpenGL, it's required, I have to use it. Mostly I want to apply the textures from Tutorial 15 onto objects in tutorial 7 (world with UBO). For now it seemed like the textures only work when mipmaps are turned on. This comes with a downside: The only mipmap used is the one with an index of zero, and that's the 1 colored 1x1 pixel one. I tried setting the minimum level of a mipmap higher or turning off mipmaps entirely, but even that doesn't fix thing, because then everything turns pitch black. Now I'll list the most important parts of my program EDIT: I guess I'll add more details... The vertex shader has something like this: #version 330 layout(location = 0) in vec4 position; layout(location = 1) in vec4 color; layout(location = 2) in vec3 normal; //Added these later layout(location = 5) in vec2 texCoord; out vec2 colorCoord; smooth out vec4 interpColor; out vec3 vertexNormal; out vec3 modelSpacePosition; out vec3 cameraSpacePosition; uniform mat4 worldToCameraMatrix; uniform mat4 modelToWorldMatrix; uniform mat3 normalModelToCameraMatrix; uniform vec3 dirToLight; uniform vec4 lightIntensity; uniform vec4 ambientIntensity; uniform vec4 baseColor; uniform mat4 cameraToClipMatrix; void main() { vertexNormal = normal; vec3 normCamSpace = normalize(normalModelToCameraMatrix * vertexNormal); cameraSpacePosition = normCamSpace; float cosAngIncidence = dot(normCamSpace, dirToLight); cosAngIncidence = clamp(cosAngIncidence, 0, 1); modelSpacePosition.x = position.x; modelSpacePosition.y = position.y; modelSpacePosition.z = position.z; vec4 temp = modelToWorldMatrix * position; temp = worldToCameraMatrix * temp; gl_Position = cameraToClipMatrix * temp; interpColor = ((lightIntensity * cosAngIncidence) + (ambientIntensity)) * baseColor; colorCoord= texCoord ; } The fragment shader like this: #version 330 in vec3 vertexNormal; in vec3 modelSpacePosition; smooth in vec4 interpColor; uniform vec3 modelSpaceLightPos; uniform vec4 lightIntensity2; uniform vec4 ambientIntensity2; out vec4 outputColor; //Added later in vec2 colorCoord; uniform sampler2D colorTexture; void main() { vec3 lightDir2 = normalize(modelSpacePosition - modelSpaceLightPos); float cosAngIncidence2 = dot(normalize(vertexNormal), lightDir2); cosAngIncidence2 = clamp(cosAngIncidence2, 0, 1); float light2DistanceSqr = dot(modelSpacePosition - modelSpaceLightPos, modelSpacePosition - modelSpaceLightPos); //added vec4 texture2 = texture(colorTexture, colorCoord); outputColor = ((ambientIntensity2 + (interpColor*2))/4) + ((((interpColor) * lightIntensity2/200 * cosAngIncidence2) + (ambientIntensity2* interpColor )) /( ( sqrt(light2DistanceSqr) + light2DistanceSqr)/200 )); //No outputColor for texture testing outputColor = texture2 ; } } Those were both shaders. And here are the parts added to the .cpp: #include <glimg/glimg.h> #include "../framework/directories.h" [...] const int g_colorTexUnit = 0; GLuint g_checkerTexture = 0; And here's the loader for the texture: void LoadCheckerTexture() { try { std::string filename(LOCAL_FILE_DIR); filename += "checker.dds"; std::auto_ptr<glimg::ImageSet> pImageSet(glimg::loaders::dds::LoadFromFile(filename.c_str())); glGenTextures(1, &g_checkerTexture); glBindTexture(GL_TEXTURE_2D, g_checkerTexture); glimg::SingleImage image = pImageSet->GetImage(0, 0, 0); glimg::Dimensions dims = image.GetDimensions(); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, dims.width, dims.height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, image.GetImageData()); glBindTexture(GL_TEXTURE_2D, 0); } catch(std::exception &e) { printf("%s\n", e.what()); throw; } } Naturally I've got this in void init(): LoadCheckerTexture(); And then when rendering the object: glActiveTexture(GL_TEXTURE0 + g_colorTexUnit); glBindTexture(GL_TEXTURE_2D,g_checkerTexture); g_pLeftMesh->Render(); glBindSampler(g_colorTexUnit, 0); glBindTexture(GL_TEXTURE_2D, 0); With all of this, I get put pitch black for everything, however when I change the outputColor equation into "texture + outputColor;", everything looks normal. I have no idea what I'm doing wrong here. A friend tried to help me, we removed some unnecessairy stuff, but we got nothing running.
Ok guys, I've worked on this whole thing, and did manage to somehow get it running. First off I had to add samplers: GLuint g_samplers; //Add Later void CreateSamplers() { glGenSamplers(1, &g_samplers); glSamplerParameteri(g_samplers, GL_TEXTURE_WRAP_S, GL_REPEAT); glSamplerParameteri(g_samplers, GL_TEXTURE_WRAP_T, GL_REPEAT); //Linear mipmap Nearest glSamplerParameteri(g_samplers, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glSamplerParameteri(g_samplers, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } I also added this to the file thing: glimg::OpenGLPixelTransferParams xfer = glimg::GetUploadFormatType(pImageSet->GetFormat(), 0); glimg::SingleImage image = pImageSet->GetImage(0, 0, 0); glimg::Dimensions dims = image.GetDimensions(); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dims.width, dims.height, 0, xfer.format, xfer.type, image.GetImageData()); The xfer variable does get the format and type adjusted to the dds. Also the render code got turned into this: //Added necessary glActiveTexture(GL_TEXTURE0 + g_colorTexUnit); glBindTexture(GL_TEXTURE_2D,g_checkerTexture); glBindSampler(g_colorTexUnit, g_samplers); g_pLeftMesh->Render(); glBindSampler(g_colorTexUnit, 0); glBindTexture(GL_TEXTURE_2D, 0); And of course at the end of init() I needed to add the CreateSamplers thing: //Added this later LoadCheckerTexture(); CreateSamplers(); I'm sorry for all the trouble with all this, but guess OpenGL really is just this confusing and it was just dumb luck that I got it right. Just posting this so that people know
Your fail to add textures may be caused by: Have you add texture coordinates to objects? (this is the most probable cause, because you are adding textures to non textured tutorial), add textures to VAO. Did you add uniform textureunit (Sampler2D)? (it must be uniform, else texturing will not work properly) Is your texture loaded,binded,enabled (GL_TEXTURE_2D) ? Is your active texture unit - 0? if not change layout/multitexture coords or set active texture 0 This two codes are simple texturing shaders (texture unit 0) no special things (like light,blend,bump,...): tm_l2g is transformation local obj space -> world space (Modelview) tm_g2s is transformation world space -> screen space (Projection) pos are vertex coordinates txt are texture coordinates col are colors Do not forget to change uniform names and layout locations to yours. Vertex: //------------------------------------------------------------------ #version 420 core //------------------------------------------------------------------ uniform mat4x4 tm_l2g; uniform mat4x4 tm_g2s; layout(location=0) in vec3 pos; layout(location=1) in vec4 col; layout(location=2) in vec2 txr; out smooth vec4 pixel_col; out smooth vec2 pixel_txr; //------------------------------------------------------------------ void main(void) { vec4 p; p.xyz=pos; p.w=1.0; p=tm_l2g*p; p=tm_g2s*p; gl_Position=p; pixel_col=col; pixel_txr=txr; } //------------------------------------------------------------------ fragment: //------------------------------------------------------------------ #version 420 core //------------------------------------------------------------------ in smooth vec4 pixel_col; in smooth vec2 pixel_txr; uniform sampler2D txr_texture0; out layout(location=0) vec4 frag_col; //------------------------------------------------------------------ void main(void) { vec4 col; col=texture(txr_texture0,pixel_txr.st); frag_col=col*pixel_col; } //------------------------------------------------------------------ [edit1] CPU old style OpenGL render code (initializations are not included its only render code they can be found here) //------------------------------------------------------------------ // set modelview,projection,textures,bind GLSL programs... GLfloat a=10.0,z=0.0; glColor3f(1.0,1.0,1.0); glBegin(GL_QUADS); // textured quad glTexCoord2f(0.0,0.0); glVertex3f(-a,-a,z); glTexCoord2f(0.0,1.0); glVertex3f(-a,+a,z); glTexCoord2f(1.0,1.0); glVertex3f(+a,+a,z); glTexCoord2f(1.0,0.0); glVertex3f(+a,-a,z); // reverse order quad to be shore that at least one passes by CULL_FACE glTexCoord2f(1.0,0.0); glVertex3f(+a,-a,z); glTexCoord2f(1.0,1.0); glVertex3f(+a,+a,z); glTexCoord2f(0.0,1.0); glVertex3f(-a,+a,z); glTexCoord2f(0.0,0.0); glVertex3f(-a,-a,z); glEnd(); //------------------------------------------------------------------ [edit2] ok here goes VAO/VBO render code,... //------------------------------------------------------------------------------ // enum of VBO locations (it is also your layout location) I use enums for simple in code changes enum _vbo_enum { _vbo_pos=0, // glVertex _vbo_col, // glColor _vbo_tan, // glNormal _vbo_unused0, // unused (at least i dont see anything at this location in your code) _vbo_unused1, // unused (at least i dont see anything at this location in your code) _vbo_txr, // glTexCoord _vbos }; //------------------------------------------------------------------------------ // 'global' names and size for OpenGL mesh in VAO/VBO ... similar ot texture names/handles GLuint vao[1],vbo[_vbos],num_pnt=0; //------------------------------------------------------------------------------ void VAO_init_cube() // call this before VAO use,...but after OpenGL init ! { //[1] first you need some model to render (mesh), here is a simple cube // size,position of cube - change it that it is visible in your scene const GLfloat a=1.0,x=0.0,y=0.0,z=0.0; // cube points 3f x,y,z GLfloat mesh_pos[]= { x-a,y-a,z-a,x-a,y+a,z-a,x+a,y+a,z-a,x+a,y-a,z-a, x-a,y-a,z+a,x-a,y+a,z+a,x+a,y+a,z+a,x+a,y-a,z+a, x-a,y-a,z-a,x-a,y-a,z+a,x+a,y-a,z+a,x+a,y-a,z-a, x-a,y+a,z-a,x-a,y+a,z+a,x+a,y+a,z+a,x+a,y+a,z-a, x-a,y-a,z-a,x-a,y+a,z-a,x-a,y+a,z+a,x-a,y-a,z+a, x+a,y-a,z-a,x+a,y+a,z-a,x+a,y+a,z+a,x+a,y-a,z+a, }; // cube colors 3f r,g,b GLfloat mesh_col[]= { 0.0,0.0,0.0,0.0,1.0,0.0,1.0,1.0,0.0,1.0,0.0,0.0, 0.0,0.0,1.0,0.0,1.0,1.0,1.0,1.0,1.0,1.0,0.0,1.0, 0.0,0.0,0.0,0.0,0.0,1.0,1.0,0.0,1.0,1.0,0.0,0.0, 0.0,1.0,0.0,0.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,0.0, 0.0,0.0,0.0,0.0,1.0,0.0,0.0,1.0,1.0,0.0,0.0,1.0, 1.0,0.0,0.0,1.0,1.0,0.0,1.0,1.0,1.0,1.0,0.0,1.0, }; // cube normals 3f x,y,z GLfloat mesh_tan[]= { -0.6,-0.6,-0.6,-0.6,+0.6,-0.6,+0.6,+0.6,-0.6,+0.6,-0.6,-0.6, -0.6,-0.6,+0.6,-0.6,+0.6,+0.6,+0.6,+0.6,+0.6,+0.6,-0.6,+0.6, -0.6,-0.6,-0.6,-0.6,-0.6,+0.6,+0.6,-0.6,+0.6,+0.6,-0.6,-0.6, -0.6,+0.6,-0.6,-0.6,+0.6,+0.6,+0.6,+0.6,+0.6,+0.6,+0.6,-0.6, -0.6,-0.6,-0.6,-0.6,+0.6,-0.6,-0.6,+0.6,+0.6,-0.6,-0.6,+0.6, +0.6,-0.6,-0.6,+0.6,+0.6,-0.6,+0.6,+0.6,+0.6,+0.6,-0.6,+0.6, }; // cube texture coords 2f s,t GLfloat mesh_txr[]= { 0.0,0.0,0.0,1.0,1.0,1.0,1.0,0.0, 0.0,0.0,0.0,1.0,1.0,1.0,1.0,0.0, 0.0,0.0,0.0,1.0,1.0,1.0,1.0,0.0, 0.0,0.0,0.0,1.0,1.0,1.0,1.0,0.0, 0.0,0.0,0.0,1.0,1.0,1.0,1.0,0.0, 0.0,0.0,0.0,1.0,1.0,1.0,1.0,0.0, }; // init VAO/VBO glGenVertexArrays(1,vao); // allocate 1 x VAO glGenBuffers(_vbos,vbo); // allocate _vbos x VBO // copy mesh to VAO/VBO ... after this you do not need the mesh anymore GLint i,sz,n; // n = number of numbers per 1 entry glBindVertexArray(vao[0]); num_pnt=sizeof(mesh_pos)/(sizeof(GLfloat)*3); // num of all points in mesh i=_OpenGLVAOgfx_pos; n=3; sz=sizeof(GLfloat)*n; glBindBuffer(GL_ARRAY_BUFFER,vbo[i]); glBufferData(GL_ARRAY_BUFFER,sz*num_pnt,mesh_pos,GL_STATIC_DRAW); glEnableVertexAttribArray(i); glVertexAttribPointer(i,n,GL_FLOAT,GL_FALSE,0,0); i=_OpenGLVAOgfx_col; n=3; sz=sizeof(GLfloat)*n; glBindBuffer(GL_ARRAY_BUFFER,vbo[i]); glBufferData(GL_ARRAY_BUFFER,sz*num_pnt,mesh_col,GL_STATIC_DRAW); glEnableVertexAttribArray(i); glVertexAttribPointer(i,n,GL_FLOAT,GL_FALSE,0,0); i=_OpenGLVAOgfx_tan; n=3; sz=sizeof(GLfloat)*n; glBindBuffer(GL_ARRAY_BUFFER,vbo[i]); glBufferData(GL_ARRAY_BUFFER,sz*num_pnt,mesh_tan,GL_STATIC_DRAW); glEnableVertexAttribArray(i); glVertexAttribPointer(i,n,GL_FLOAT,GL_FALSE,0,0); i=_OpenGLVAOgfx_txr; n=2; sz=sizeof(GLfloat)*n; glBindBuffer(GL_ARRAY_BUFFER,vbo[i]); glBufferData(GL_ARRAY_BUFFER,sz*num_pnt,mesh_txr,GL_STATIC_DRAW); glEnableVertexAttribArray(i); glVertexAttribPointer(i,n,GL_FLOAT,GL_FALSE,0,0); glBindVertexArray(0); } //------------------------------------------------------------------------------ void VAO_draw() // call this to draw your mesh,... need to enable and bind textures,... before use { glDisable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glBindVertexArray(vao[0]); glEnableVertexAttribArray(_vbo_pos); glEnableVertexAttribArray(_vbo_col); glEnableVertexAttribArray(_vbo_tan); glDisableVertexAttribArray(_vbo_unused0); glEnableVertexAttribArray(_vbo_txr); glDrawArrays(GL_QUADS,0,num_pnt); glDisableVertexAttribArray(_vbo_pos); glDisableVertexAttribArray(_vbo_col); glDisableVertexAttribArray(_vbo_tan); glDisableVertexAttribArray(_vbo_unused0); glDisableVertexAttribArray(_vbo_unused1); glDisableVertexAttribArray(_vbo_txr); glBindVertexArray(0); } //------------------------------------------------------------------------------ void VAO_exit() // clean up ... call this when you do not need VAO/VBO anymore { glDisableVertexAttribArray(_vbo_pos); glDisableVertexAttribArray(_vbo_col); glDisableVertexAttribArray(_vbo_tan); glDisableVertexAttribArray(_vbo_unused0); glDisableVertexAttribArray(_vbo_unused1); glDisableVertexAttribArray(_vbo_txr); glBindVertexArray(0); glDeleteVertexArrays(1,vao); glDeleteBuffers(_vbos,vbo); } //------------------------------------------------------------------------------ [edit3] if you are win32/64 user you can try my IDE for GLSL It is very simple and easy to use, but cannot change texture/attrib locations. Press [F1] for help,... [F9] for run [F10] for return to normal OpenGL mode. Also txt-editor is little buggy sometimes but it is enough for my purpose. GLSL IDE
OpenGL two pass shader effect with FBO render to texture gives noise in result on Windows only
What is the correct way of doing the following: Render a scene into a texture using a FBO (fbo-a) Then apply an effect using the texture (tex-a) and render this into another texture (tex-b) using the same fbo (fbo-a) Then render this second texture, with the applied effect (tex-b) as a full screen quad. My approach is this, but this gives me a texture filled with "noise" on window + the applied effect (all pixels are randomly colored red, green, blue white, black). I'm using one FBO, with two textures set to GL_COLOR_ATTACHENT0 (tex-a) and GL_COLOR_ATTACHMENT1 (tex-b) I bind my fbo, make sure it's rendered into the tex-a using glDrawBuffer(GL_COLOR_ATTACHMENT0) Then I apply the effect in a shader with tex-a bound and set as 'sampler2D'. Using texture unit 1, and switch to the second color attachment (glDrawBuffer(GL_COLOR_ATTACHMENT1)). and render a full screen quad. Everything is now rendered into tex-b Then I switch back to the default FBO (0) and use tex-b with a full screen quad to render the result. Example of the result when applying my shader This is the shader I'm using. I'm not aware this could be what is causing this, but maybe the noise is caused by a overflow? Vertex shader attribute vec4 a_pos; attribute vec2 a_tex; varying vec2 v_tex; void main() { mat4 ident = mat4(1.0); v_tex = a_tex; gl_Position = ident * a_pos; } Fragment shader uniform int u_mode; uniform sampler2D u_texture; uniform float u_exposure; uniform float u_decay; uniform float u_density; uniform float u_weight; uniform float u_light_x; uniform float u_light_y; const int NUM_SAMPLES = 100; varying vec2 v_tex; void main() { if (u_mode == 0) { vec2 pos_on_screen = vec2(u_light_x, u_light_y); vec2 delta_texc = vec2(v_tex.st - pos_on_screen.xy); vec2 texc = v_tex; delta_texc *= 1.0 / float(NUM_SAMPLES) * u_density; float illum_decay = 1.0; for(int i = 0; i < NUM_SAMPLES; i++) { texc -= delta_texc; vec4 sample = texture2D(u_texture, texc); sample *= illum_decay * u_weight; gl_FragColor += sample; illum_decay *= u_decay; } gl_FragColor *= u_exposure; } else if(u_mode == 1) { gl_FragColor = texture2D(u_texture, v_tex); gl_FragColor.a = 1.0; } } I've read this FBO article on opengl.org, where they describe a feedback loop at the bottom of the article. The description is not completely clear to me and I'm wondering if I'm exactly doing what they describe there. Update 1: Link to source code Update 2: When I first set gl_FragColor.rgb = vec3(0.0, 0.0, 0.0); before I start the sampling loop (with NUM_SAMPLES), it works find. No idea why though.
The problem is that you're not initializing gl_FragColor, and you're modifying it with the lines gl_FragColor += sample; and gl_FragColor *= u_exposure; both of which depend on the previous value of gl_FragColor. So you're getting some random junk (whatever happened to be in the register that the shader compiler decided to use for the gl_FragColor computation) added in. This has a strong possibility of working fine on some driver/hardware combinations (because the compiler decided to use a register that was always 0 for some reason) and not on others.
opengl 3d texture issue
I'm trying to use a 3d texture in opengl to implement volume rendering. Each voxel has an rgba colour value and is currently rendered as a screen facing quad.(for testing purposes). I just can't seem to get the sampler to give me a colour value in the shader. The quads always end up black. When I change the shader to generate a colour (based on xyz coords) then it works fine. I'm loading the texture with the following code: glGenTextures(1, &tex3D); glBindTexture(GL_TEXTURE_3D, tex3D); unsigned int colours[8]; colours[0] = Colour::AsBytes<unsigned int>(Colour::Blue); colours[1] = Colour::AsBytes<unsigned int>(Colour::Red); colours[2] = Colour::AsBytes<unsigned int>(Colour::Green); colours[3] = Colour::AsBytes<unsigned int>(Colour::Magenta); colours[4] = Colour::AsBytes<unsigned int>(Colour::Cyan); colours[5] = Colour::AsBytes<unsigned int>(Colour::Yellow); colours[6] = Colour::AsBytes<unsigned int>(Colour::White); colours[7] = Colour::AsBytes<unsigned int>(Colour::Black); glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colours); The colours array contains the correct data, i.e. the first four bytes have values 0, 0, 255, 255 for blue. Before rendering I bind the texture to the 2nd texture unit like so: glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_3D, tex3D); And render with the following code: shaders["DVR"]->Use(); shaders["DVR"]->Uniforms["volTex"].SetValue(1); shaders["DVR"]->Uniforms["World"].SetValue(Mat4(vl_one)); shaders["DVR"]->Uniforms["viewProj"].SetValue(cam->GetViewTransform() * cam->GetProjectionMatrix()); QuadDrawer::DrawQuads(8); I have used these classes for setting shader params before and they work fine. The quaddrawer draws eight instanced quads. The vertex shader code looks like this: #version 330 layout(location = 0) in vec2 position; layout(location = 1) in vec2 texCoord; uniform sampler3D volTex; ivec3 size = ivec3(2, 2, 2); uniform mat4 World; uniform mat4 viewProj; smooth out vec4 colour; void main() { vec3 texCoord3D; int num = gl_InstanceID; texCoord3D.x = num % size.x; texCoord3D.y = (num / size.x) % size.y; texCoord3D.z = (num / (size.x * size.y)); texCoord3D /= size; texCoord3D *= 2.0; texCoord3D -= 1.0; colour = texture(volTex, texCoord3D); //colour = vec4(texCoord3D, 1.0); gl_Position = viewProj * World * vec4(texCoord3D, 1.0) + (vec4(position.x, position.y, 0.0, 0.0) * 0.05); } uncommenting the line where I set the colour value equal to the texcoord works fine, and makes the quads coloured. The fragment shader is simply: #version 330 smooth in vec4 colour; out vec4 outColour; void main() { outColour = colour; } So my question is, what am I doing wrong, why is the sampler not getting any colour values from the 3d texture? [EDIT] Figured it out but can't self answer (new user): As soon as I posted this I figured it out, I'll put the answer up to help anyone else (it's not specifically a 3d texture issue, and i've also fallen afoul of it before, D'oh!). I didn't generate mipmaps for the texture, and the default magnification/minification filters weren't set to either GL_LINEAR, or GL_NEAREST. Boom! no textures. Same thing happens with 2d textures.
As soon as I posted this I figured it out, I'll put the answer up to help anyone else (it's not specifically a 3d texture issue, and i've also fallen afoul of it before, D'oh!). I didn't generate mipmaps for the texture, and the default magnification/minification filters weren't set to either GL_LINEAR, or GL_NEAREST. Boom! no textures. Same thing happens with 2d textures.