I'm trying to implement shadowmapping, so I'm rendering to depth texture. When I don't bind framebuffer which contains depth texture and use default framebuffer, it outputs to screen. However, instead of white color for distant fragments, they're red.
This is my fragment shader:
#version 330
out float fragmentdepth;
uniform sampler2D inputTex;
void main(){
fragmentdepth = gl_FragCoord.z;
}
Is it a problem? Because shadowmapping isn't working and I'd like to rule out this as source of problem.
Depth is a scalar value. Scalar is interpreted by OpenGL as a single component texture. Single component texture means that only the .x or .r element (whatever you use) gets nonzero.
Related
how do you make a cube with a texture mapped, display a different texture inside and outside?
By mapping the texture in the cube, I see both from without and from within the cube the same texture and I need to be different textures.
Working with OpenGL 3.3 or higher and C ++.
Render the cube twice, the second time around with a different texture and the opposite glFrontFace().
There is a built-in gl_FrontFacing variable in the fragment shader, which allows you to test if the currently rendered triangle is front facing. You can use a different texture depending on this value. The relevant pieces of the fragment shader can look like this:
uniform sampler2D FrontTex;
uniform sampler2D BackTex;
in vec2 TexCoord;
out FragColor;
void main() {
if (gl_FrontFacing) {
FragColor = texture(FrontTex, TexCoord);
} else {
FragColor = texture(BackTex, TexCoord);
}
}
In your C++ code, you bind the two textures to different texture units, and set the sampler uniforms accordingly.
I am using freeglut, GLEW and DevIL to render a textured teapot using a vertex and fragment shader. This is all working fine in OpenGL 2.0 and GLSL 1.2 on Ubuntu 14.04.
Now, I want to apply a bump map to the teapot. My lecturer evidently doesn't brew his own tea, and so doesn't know they're supposed to be smooth. Anyway, I found a nice-looking tutorial on old-school bump mapping that includes a fragment shader that begins:
uniform sampler2D DecalTex; //The texture
uniform sampler2D BumpTex; //The bump-map
What they don't mention is how to pass two textures to the shader in the first place.
Previously I
//OpenGL cpp file
glBindTexture(GL_TEXTURE_2D, textureHandle);
//Vertex shader
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
//Fragment shader
gl_FragColor = color * texture2D(DecalTex,gl_TexCoord[0].xy);
so now I
//OpenGL cpp file
glBindTexture(GL_TEXTURE_2D, textureHandle);
glBindTexture(GL_TEXTURE_2D, bumpHandle);
//Vertex shader
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;
//Fragment shader
gl_FragColor = color * texture2D(BumpTex,gl_TexCoord[0].xy);
//no bump logic yet, just testing I can use texture 1 instead of texture 0
but this doesn't work. The texture disappears completely (effectively the teapot is white). I've tried GL_TEXTURE_2D_ARRAY, glActiveTexture and few other likely-seeming but fruitless options.
After sifting through the usual mixed bag of references to OpenGL and GLSL new and old, I've come to the conclusion that I probably need glGetUniformLocation. How exactly do I use this in the OpenGL cpp file to pass the already-populated texture handles to the fragment shader?
How to pass an array of textures with different sizes to GLSL?
Passing Multiple Textures from OpenGL to GLSL shader
Multiple textures in GLSL - only one works
(This is homework so please answer with minimal code fragments (if at all). Thanks!)
Failing that, does anyone have a tea cosy mesh?
It is very simple, really. All you need is to bind the sampler to some texture unit with glUniform1i. So for your code sample, assuming the two uniform samplers:
uniform sampler2D DecalTex; // The texture (we'll bind to texture unit 0)
uniform sampler2D BumpTex; // The bump-map (we'll bind to texture unit 1)
In your initialization code:
// Get the uniform variables location. You've probably already done that before...
decalTexLocation = glGetUniformLocation(shader_program, "DecalTex");
bumpTexLocation = glGetUniformLocation(shader_program, "BumpTex");
// Then bind the uniform samplers to texture units:
glUseProgram(shader_program);
glUniform1i(decalTexLocation, 0);
glUniform1i(bumpTexLocation, 1);
OK, shader uniforms set, now we render. To do so, you will need the usual glBindTexture plus glActiveTexture:
glActiveTexture(GL_TEXTURE0 + 0); // Texture unit 0
glBindTexture(GL_TEXTURE_2D, decalTexHandle);
glActiveTexture(GL_TEXTURE0 + 1); // Texture unit 1
glBindTexture(GL_TEXTURE_2D, bumpHandle);
// Done! Now you render normally.
And in the shader, you will use the textures samplers just like you already do:
vec4 a = texture2D(DecalTex, tc);
vec4 b = texture2D(BumpTex, tc);
Note: For techniques like bump-mapping, you only need one set of texture coordinates, since the textures are the same, only containing different data. So you should probably pass texture coordinates as a vertex attribute.
instead of using:
glUniform1i(decalTexLocation, 0);
glUniform1i(bumpTexLocation, 1);
in your code,
you can have:
layout(binding=0) uniform sampler2D DecalTex;
// The texture (we'll bind to texture unit 0)
layout(binding=1)uniform sampler2D BumpTex;
// The bump-map (we'll bind to texture unit 1)
in your shader. That also mean you don't have to query for the location.
I have written a fragment shader which i would like to change the color of the fragment. for example I would like if the color it receives is black then it should change it to a blue.
This is the shader that I am using:
uniform sampler2D mytex;
layout (pixel_center_integer) in vec4 gl_FragCoord;
uniform sampler2D texture1;
void main ()
{
ivec2 screenpos = ivec2 (gl_FragCoord.xy);
vec4 color = texelFetch (mytex, screenpos, 0);
if (color == vec4 (0.0,0.0,0.0,1.0)) {
color = (0.0,0.0,0.0,0.0);
}
gl_FragColor = texture2D (texture1, gl_TexCoord[0].st);
}
And here is the log that I am getting from it:
WARNING: -1:65535: 'GL_ARB_explicit_attrib_location' : extension is not available in current GLSL version
WARNING: 0:1: 'texelFetch' : function is not available in current GLSL version
I am aware of the warning- but shouldn't it compile anyways?
The shader is not doing what i would like it to do, can someone explain why?
For one thing, you are using functions that are not available in your GLSL implementation. The result of calling these will be undefined.
However, the kicker here is that gl_FragColor has absolutely NOTHING to do with the value of color in this shader. So even if your texelFetch (...) logic actually did work correctly, changing the value of color does nothing to the final output. A smart compiler will see this as a no-op and effectively strip your shader down to this:
uniform sampler2D texture1;
void main ()
{
gl_FragColor = texture2D (texture1, gl_TexCoord[0].st);
}
If that were not enough, texelFetch (...) is completely unnecessary in this shader. If you want to lookup the texel that corresponds to the current fragment in your shader and the texture has the same dimensions as the viewport you are drawing into you can actually use texture2D (texture1, gl_FragCoord.xy); This is because the default behaviour in GLSL is to have gl_FragCoord supply the coordinate of the fragment's center (x+0.5, y+0.5) - this is also the center of the corresponding texel in your texture (if it is the same resolution), so you can do a traditional texture lookup without worrying that texture filtering will alter your sampled result.
texelFetch (...) lets you fetch an explicit texel in a texture without using normalized coordinates, it is sort of like a "grownup" rectangle texture :) It is generally useful if you are using a multisample texture and want a specific sample, or if you want to bypass texture filtering (which includes mipmap level selection). In this case, it is not needed at all.
This is probably what you really want (OpenGL 3.2):
#version 150
uniform sampler2D mytex;
uniform sampler2D texture1;
layout (location=0) out vec4 frag_color;
layout (location=1) out vec4 mytex_color;
void main ()
{
mytex_color = texture2D (mytex, gl_FragCoord.xy);
// This is not black->blue like you explained in your question...
// ... This is generally opaque->transparent, assuming 4th component = alpha
if (mytex_color == vec4 (0.0,0.0,0.0,1.0)) {
mytex_color = vec4 (0.0);
}
frag_color = texture2D (texture1, gl_TexCoord[0].st);
}
In older GLSL versions, you will have to use glBindFragDataLocation (...) and set the data locations manually or use gl_FragData[n] instead of out variables.
Now the real problem here is that you seem to be wanting to change the color of the texture you are sampling from. That will not work, at best you will have to use two fragment data outputs. Writing into the same texture you are sampling from can be done under some very controlled circumstances, but generally what you would do is ping-pong between textures. In other words, you would fetch from one texture, write to another texture and all subsequent render passes that reference to the original texture should be swapped with the one you just wrote to.
See "Fragment Data Location" for more information on Multiple Render Target drawing.
I have a system which allows me to set different blending modes (Those found in Photoshop) for each renderable object.Currently what I do is :
Render the renderable Object into FBO B normally.
Attach blending mode shader program,FBO C , and blend color attachment from FBO B with color attachment from FBO A (FBO A contains previous draws final result).
Blit the result from FBO C into FBO A and proceed with the rest of pipeline .
While this works fine , I would like to spare some frame rate which is currently wasted for this ping pong.I know that by default it is not possible to read pixels at the same time when writing to them so it is not possible to set a texture to read from and write to? Ideally ,What I would like to do is in the stage 1 render geometry right into FBO A processing the blend between FBO A color attachment texture and input material texture.
To make it clear here is the example.
Let's assume all the previously rendered geometry is accumulated in FBO A.And each new rendered object that needs to get blended is rendered into FBO B (just like I wrote above).Then in the blend pass (drawn into FBO C) the following shader is used (here it is darken blending ) :
uniform sampler2D bottomSampler;
uniform sampler2D topSampler;
uniform float Opacity;
// utility function that assumes NON-pre-multiplied RGB...
vec4 final_mix(
vec4 NewColor,
vec4 BaseColor,
vec4 BlendColor
) {
float A2 = BlendColor.a * Opacity;
vec3 mixRGB = A2 * NewColor.rgb;
mixRGB += ((1.0-A2) * BaseColor.rgb);
return vec4(mixRGB,BaseColor.a+BlendColor.a);
}
void main(void) // fragment
{
vec4 botColor = texture2D(bottomSampler,gl_TexCoord[0].st);
vec4 topColor = texture2D(topSampler,gl_TexCoord[0].st);
vec4 comp = final_mix(min(botColor,topColor),botColor,topColor);
gl_FragColor = comp;
}
Here :
uniform sampler2D bottomSampler; - FBO A texture attachment.
uniform sampler2D topSampler; -FBO B texture attachment
I use only plane geometry objects.
The output from this shader is FBO C texture attachment which is blitted into FBO A for the next evolution.
In my shader I already have a special variable that has the entire content of previously rendered screen. It is stored in
uniform sampler2D _GrabTexture;
Which it's content should be:
(As a side note, I'm using Unity's GrabPass{} to get the entire screen. Also please ignore Unity's GUI)
Now how can I render one more pass, using _GrabTexture as a texture for my plane model, so the result is exactly the same as my _GrabTexture?
(The point is, I can apply some effects like blur,sharpen,etc to that screen texture before render one more pass so the plane's texture is now stylized.)
I'm trying this in the final pass. The variable is declared in both Vertex & Fragment Shader.
uniform sampler2D _GrabTexture;
varying vec4 v_Position;
Vertex Shader :
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
v_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
Store the screen coordinate of each model's vertex as varying, to be used in Fragment Shader.
Fragment Shader :
void main()
{
gl_FragColor = texture2D(_GrabTexture,vec2(v_Position));
}
Now use that stored varying position to access the _GrabTexture screen texture. Since it's entire screen my v_Position which is already in screen coordinate should correctly got the right pixel.
But the result is
As you can see the plane's texture is 'sorts of' showing previously rendered screen but the coordinate is not right. How can I fix it so the result is the same as first image?
You're thinking too complicated. OpenGL tells you the on-screen fragment position in the fragment shader built in variable gl_FragCoord.
With GLSL-1.30 or newer you have texelFetch which you can give gl_FragCoord as source coordinate directly. Or you use translate gl_FragCoord into texture space coordinates, see https://stackoverflow.com/a/5879551/524368