Creating and blending a dynamic texture in OpenGL - c++

I need to render a sphere to a texture (done using a Framebuffer Object (FBO)), and then alpha blend that texture with the back buffer. So far I'm not doing any processing with the texture except clearing it at the beginning of every frame.
I should say that my scene consists of nothing but a planet in empty space, the sphere should appear next to or around the planet (kind of like a moon for now). When I render the sphere directly to the back buffer, it displays correctly; but when I do the intermediary step of rendering it to a texture and then blending that texture with the back buffer, the sphere only shows up when it is in front of the planet, the part that isn't in front is just "cut off":
I render the sphere using glutSolidSphere to a RGBA8 fullscreen texture that's bound to an FBO, making sure that every sphere pixel receives an alpha value of 1.0. I then pass the texture to a fragment shader program, and use this code to render a fullscreen quad - with the texture mapped onto it - to the backbuffer while alpha blending:
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glBegin(GL_QUADS);
glTexCoord2i(0, 1);
glVertex3i(-1, 1, -1); // TOP LEFT
glTexCoord2i(0, 0);
glVertex3i(-1, -1, -1); // BOTTOM LEFT
glTexCoord2i(1, 0);
glVertex3i( 1, -1, -1); // BOTTOM RIGHT
glTexCoord2i(1, 1);
glVertex3i( 1, 1, -1); // TOP RIGHT
glEnd();
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
This is the shader code (taken from an FX file written in Cg):
sampler2D BlitSamp = sampler_state
{
MinFilter = LINEAR;
MagFilter = LINEAR;
MipFilter = LINEAR;
AddressU = Clamp;
AddressV = Clamp;
};
float4 blendPS(float2 texcoords : TEXCOORD0) : COLOR
{
float4 outColor = tex2D(BlitSamp, texcoords);
return outColor;
}
I don't even know whether this is a problem with the depth buffer or with alpha blending, I've tried a lot of combinations of enabling and disabling depth testing (with a depth buffer attached to the FBO) and alpha blending.
EDIT: I tried just rendering a blank fullscreen quad straight to the back buffer and even that was cropped around the planet's edges. For some reason, enabling depth testing for rendering the quad (that is, removing the lines glDisable(GL_DEPTH_TEST) and glEnable(GL_DEPTH_TEST) in the code above) got rid of the problem, but now everything but the planet and the sphere appears white:
I made sure (and could confirm) that the alpha channel of the texture is 0 at every pixel but the sphere's, so I don't understand where the whiteness could be introduced. (Would also still be interested in an explanation why enabling depth testing has this effect.)

I see two possible sources of error here:
1. Rendering to the FBO
If the missing pixels are not even present in the FBO after rendering, there must be some mechanism which discarded the corresponding fragments. The OpenGL pipeline includes four different types of fragment tests which can lead to fragments being discarded:
Scissor Test: Unlikely to be the cause, as the scissor test only affects a rectangular portion of the screen.
Alpha Test: Equally unlikely, as your fragments should all have the same alpha value.
Stencil Test: Also unlikely, unless you use stencil operations when drawing the background planet and copy over the stencil buffer from the back buffer to the FBO.
Depth Test: Same as for stencil test.
So there's a good chance that rendering into FBO is not the issue here. But just to be absolutely sure, you should read back your color attachment texture and dump it into a file for inspection. You can use the following function for that:
void TextureToFile(GLuint texture, const char* filename) {
glBindTexture(GL_TEXTURE_2D, texture);
GLint width, height;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
std::vector<GLubyte> pixels(3 * width * height);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, &pixels[0]);
std::ofstream out(filename, std::ios::out | std::ios::binary);
out << "P6\n"
<< width << '\n'
<< height << '\n'
<< 255 << '\n';
out.write(reinterpret_cast<const char*>(&pixels[0]), pixels.size());
}
The resulting file is a portable pixmap (.ppm). Be sure to unbind the FBO before reading back the texture.
2. Texture mapping
Assuming rendering into the FBO works as expected, the only other source of error is blending the texture over the previously rendered scene. There are two scenarios:
a) Fragments get discarded
The possible reasons for fragments to get discarded are the same as in 1.:
Scissor Test: Nope, affects rectangular areas only.
Alpha Test: Probably not, the texels covered sphere should all have the same alpha value.
Stencil Test: Might be the cause if you use stencil operations/stencil testing when drawing the background planet and the old stencil state is still active.
Depth Test: Might be the cause, but as you already disable it, it really shouldn't have any effect.
So you should make sure that all of these tests are disabled, especially the stencil test.
b) Wrong results from blending
Assuming all fragments reach the back buffer, blending is the only thing which could still cause the wrong result. With your blending function (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) the values in the back buffer are irrelevant for blending, and we assume that the alpha values in the texture are correct. So I see no reason for why blending should be the root cause here.
Conclusion
In conclusion, the only sensible cause for the observed result seems to be stencil testing. If it's not, I'm out of options :)

I solved it or at least came up with a work around.
First off, the whiteness stems from the fact that glClearColor had been set to glClearColor(1.0f, 1.0f, 1.0f, 1000.0f), so everything but the planet wasn't even written to in the end. I now copy the contents of the back buffer (which is the planet, the atmosphere, and the space around it) to the texture before rendering the sphere, and I render the atmosphere and space before that copy/blit operation, so they are included in it. Previously, everything but the planet itself was rendered after my quad, which - when using depth testing - apparently placed everything behind the quad, making it invisible.
The reference implementation of the effect I'm trying to achieve has always used this kind of blit operation in its code but I didn't think it was necessary for the effect. Now I feel like there might be no other way...

Related

Qt & OpenGL : texture transparency

I have two textures rendered in the same way. The green texture has the right transparency in the right places, but when I move the pink texture in front, it shows the background color where it should be transparent.
This is the snippet code of the paintGL method that renders the textures.
void OpenGLWidget::paintGL()
{
// ...
for (int i = 0; i < lights.size(); i++)
{
glUseProgram(lights[i].program);
setUniform3fv(program, "lightPosition", 1, &lights[i].position[0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, lights[i].texture);
lights[i].svg.setColor(toColor(lights[i].diffuse));
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, lights[i].svg.width(), lights[i].svg.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, lights[i].svg.toImage().constBits());
glGenerateMipmap(GL_TEXTURE_2D);
glBindVertexArray(lights[i].vertexArray);
glDrawElements(GL_TRIANGLES, lights[i].indices.size(), GL_UNSIGNED_BYTE, nullptr);
}
update();
}
The toImage method of the svg class generates a new QImage object from the svg file, so the new texture value should be updated with each frame.
Where am I doing wrong? Thanks!
This probably happens because you have depth testing enabled. Even though parts of the texture are (partly or fully) transparent, OpenGL still writes to the depth buffer, so the pink light's quad appears to obscure the green light. It works the other way round, because the pink light is drawn first, so the green light hasn't been written to the depth buffer at that point.
The usual solution to this is to render transparent textures in back to front order.
You could also just write your fragment shader to discard fragments if they are transparent. But this results in artifacts if you have semi-transparent fragments, which you have, because of texture filtering and mipmaps.

Heat haze/distortion effect in OpenGL (GLSL) and how it should be achieved

you can skip to the TL;DR at the bottom for the conclusion. I preferred to provide as much information as I could, so as to help narrow down the question further.
I've been having an issue with a heat haze effect I've been working on.
This is the sort of effect that I was thinking of but since this is a rather generalized system it would apply to any so called screen space refraction:
The haze effect is not where my issue lies as it is just a distortion of sampling coordinates, rather it's with what is sampled. My first approach was to render the distortions to another render target. This method was fairly successful but has a major downfall that's easy to foresee if you've dealt with screen space textures before. the problem is that because of the offset to the sampling coordinate, if an object is in front of the refractor, its edges will be taken into the refraction calculation.
as you can see it looks fine when all the geometry is either the environment (no depth test) or back geometry. and here with a cube closer than the refractor. As you can see it, there is this effect I'll call bleeding of the closer geometry.
relevant shader code for reference:
/* transparency.frag */
layout (location = 0) out vec4 out_color; // frag color
layout (location = 1) out vec4 bright; // used for bloom effect
layout (location = 2) out vec4 deform; // deform buffer
[...]
void main(void) {
[...]
vec2 n = __sample_noise_texture_with_time__{};
deform = vec4(n * .1, 0, 1);
out_color = vec4(0, 0, 0, .0);
bright = vec4(0.0, 0.0, 0.0, .9);
}
/* post_process.frag */
in vec2 texel;
uniform sampler2D screen_t;
uniform sampler2D depth_t;
uniform sampler2D bright_t;
uniform sampler2D deform_t;
[...]
void main(void) {
[...]
vec3 noise_sample = texture(deform_t, texel).xyz;
vec2 texel_c = texel + noise_sample.xy;
[sample screen and bloom with texel_c, gama corect, output to color buffer]
}
To try to combat this, I tried a technique that involved comparing depth components. to do this, i made the transparent object write its frag_depth tp the z component of my deform buffer like so
/* transparency.frag */
[...]
deform = vec4(n * .1, gl_FragCoord.z, 1);
[...]
and then to determine what is in front of what a quick check in the post processing shader.
[...]
float dist = texture(depth_t, texel_c).x;
float dist1 = noise_sample.z; // what i wrote to the deform buffer z
if (dist + .01 < dist1) { /* do something liek draw debug */ }
[...]
this worked somewhat but broke down as i moved away, even i i linearized the depth values and compared the distances.
EDIT 3: added better screenshots for the depth test phase
(In yellow where it's sampling something that's in front, couldn't be bothered to make it render the polygons as well so i drew them in)
(and here demonstrating it partially failing the depth comparison test from further away)
I also had some 'fun' with another technique where i passed the color buffer directly to the transparency shader and had it output the sample to its color output. In theory if the scene is Z sorted, this should produce the desired result. i'll let you be the judge of that.
(I have a few guesses as to what the patterns that emerge are since they are similar to the rasterisation patterns of GPUs however that's not very relevant sine that 'solution' was more of a desperation effort than anything)
TL;DR and Formal Question: I've had a go at a few techniques based on my knowledge and haven't been able to find much literature on the subject. so my question is: How do you realize sch effects as heat haze/distortion (that do not cover the whole screen might i add) and is there literature on the subject. For reference to what sort of effect I would be looking at, see my Overwatch screenshot and all other similar effects in the game.
Thought I would also mention just for completeness sake I'm running OpenGL 4.5 (on windows) with most shaders being version 4.00, and am working with a custom engine.
EDIT: If you want information about the software part of the engine feel free to ask. I didn't include any because it I didn't deem it relevant however i'd be glad to provide specs and code snippets as well as more shaders on demand.
EDIT 2: I thought i'd also mention that this could be achieved by using a second render pass and a clipping plane however, that would be costly and feels unnecessary since the viewpoint is the same. It might be that's this is the only solution but i don't believe so.
Thanks for your answers in advance!
I think the issue is you are trying to distort something that's behind an occluded object and that information is not available any more, because the object in front have overwitten the color value there. So you can't distort in information from a color buffer that does not exist anymore.
You are trying to solve it by depth testing and skipping the pixels that belong to an object closer to the camera than your transparent heat object, but this is causing the edge to leak into the distortion. Even if you get the edge skipped, if there was an object right behind the transparent object, occluded by the cube in the front, it wont distort in because the color information is not available.
Additional Render Pass
As you mention additional rendering pass with a clipping plane is certainly one solution to this problem.
Multiple render targets
Another solution similar to that would be to use multiple render targets, render the depth of the transparent object before hand, test for fragments that are behind it, and render them to another color buffer. Later use this buffer to distort instead of the full color buffer. You could also consider deffered shading.
Here is a code snippet of how you would setup multiple render targets.
//create your fbo
GLuint fboID;
glGenFramebuffers(1, &fboID);
glBindFramebuffer(GL_FRAMEBUFFER, fboID);
//create the rbo for depth
GLuint rboID;
glGenRenderbuffers(1, &rboID);
glBindRenderbuffer(GL_RENDERBUFFER, &rboID);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboID);
//create two color textures (one for distort)
Gluint colorTexture, distortcolorTexture;
glGenTextures(1, &colorTexture);
glGenTextures(1, &distortcolorTexture);
glBindTexture(GL_TEXTURE_2D, colorTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, distortcolorTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
//attach both textures
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture, 0);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, distortcolorTexture, 0);
//specify both the draw buffers
GLenum drawBuffers[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
glDrawBuffers(2, DrawBuffers);
First render the transparent obj's depth. Then in your fragment shader for other objects
//compute color with your lighting...
//write color to colortexture
gl_FragData[0] = color;
//check if fragment behind your transparent object
if( depth >= tObjDepth )
{
//write color to distortcolortexture
gl_FragData[1] = color;
}
finally use the distortcolortexture for your distort shader.
Depth test for a matrix of pixels instead of single pixel.
I think the edge is leaking because maybe you don't simply distort one pixel but more of a matrix of pixels, perhaps you could also try checking the max depth for the matrix (eg: 3x3 pixels centered on current pixel) and discard it if it fails the depth test. (note : this still won't distort objects behind the occluding object which you might want distorted in).

Deferred Rendering Skybox OpenGL

I've just implemented deferred rendering and am having trouble getting my skybox working. I try rendering my skybox at the very end of my rendering loop and all I get is a black screen. Here's the rendering loop:
//binds the fbo
gBuffer.Bind();
//the shader that writes info to gbuffer
geometryPass.Bind();
glDepthMask(GL_TRUE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
//draw geometry
geometryPass.SetUniform("model", transform.GetModel());
geometryPass.SetUniform("mvp", camera.GetViewProjection() * transform.GetModel());
mesh3.Draw();
geometryPass.SetUniform("model", transform2.GetModel());
geometryPass.SetUniform("mvp", camera.GetViewProjection() * transform2.GetModel());
sphere.Draw();
glDepthMask(GL_FALSE);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT);
//shader that calculates lighting
pointLightPass.Bind();
pointLightPass.SetUniform("cameraPos", camera.GetTransform().GetPosition());
for (int i = 0; i < 2; i++)
{
pointLightPass.SetUniformPointLight("light", pointLights[i]);
pointLightPass.SetUniform("mvp", glm::mat4(1.0f));
//skybox.GetCubeMap()->Bind(9);
quad.Draw();
}
//draw skybox
glEnable(GL_DEPTH_TEST);
skybox.Render(camera);
window.Update();
window.SwapBuffers();
The following is the skybox's render function
glCullFace(GL_FRONT);
glDepthFunc(GL_LEQUAL);
m_transform.SetPosition(camera.GetTransform().GetPosition());
m_shader->Bind();
m_shader->SetUniform("mvp", camera.GetViewProjection() * m_transform.GetModel());
m_shader->SetUniform("cubeMap", 0);
m_cubeMap->Bind(0);
m_cubeMesh->Draw();
glDepthFunc(GL_LESS);
glCullFace(GL_BACK);
And here is the skybox's vertex shader:
layout (location = 0) in vec3 position;
out vec3 TexCoord;
uniform mat4 mvp;
void main()
{
vec4 pos = mvp * vec4(position, 1.0);
gl_Position = pos.xyww;
TexCoord = position;
}
The skybox's fragment shader just sets the output color to texture(cubeMap, TexCoord).
As you can see from the vertex shader, I'm setting the position's z component to be w so that it will always have a depth of 1. I am also setting the depth function to be GL_LEQUAL so that it will fail the depth test. Should this not only draw the skybox in places where other objects weren't already drawn? Why does it result in a black screen?
I know I have set up the skybox correctly because if I just draw the skybox by itself it shows up just fine.
I can briefly see for a split second the geometry that should be drawn before the skybox is drawn on top of everything.
Since you're using double buffering, seeing different things must be due to a different frame being drawn. The depth buffer in the default framebuffer isn't being cleared, which I believe is the cause of the temporal instability at least.
In your case, you want the default depth buffer to be the same as the GBuffer when you draw the skybox. A quick way to achieve this is with glBlitFramebuffer, also avoiding the need to clear it:
glBindFramebuffer(GL_READ_FRAMEBUFFER, gbuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer(..., GL_DEPTH_BUFFER_BIT, ...);
Now to explain the black screen when the skybox fills the screen. Without the depth test, of course the skybox just draws. With the depth test, the skybox still draws on the first frame, but shortly after the second frame clears only the colour buffer. The depth buffer still contains stale skybox values so it does not get re-draw for this frame and you're left with black...
However your geometry pass draws without depth testing enabled, so this should still be visible even if the skybox isn't. Also this would only happen with GL_LESS and you have GL_LEQUAL. And you have glDepthMask false, which means nothing should write to the default depth buffer in your code. This points to the depth buffer containing other values, perhaps uninitialized, but in my experience it's initially zero. Also this still happens when the skybox doesn't fill the screen, drawn as a cube away from the camera, which blows away that argument. Now, perhaps if the geometry failed to draw in the second frame that would explain it. For that matter blatant driver bugs would too, but I'm not seeing any problems in the given code.
TLDR: Many unexplained things, so **I tried it myself and can't reproduce your problem...
Here's a quick example based on your code and it works fine for me...
(green sphere is the geometry, red cube is the skybox)
gl_Position = pos:
Note the yellow from additive blending even if the skybox is drawn over the top. I would have thought you'd be seeing this too.
gl_Position = pos.xyww:
Now for the code...
//I haven't enabled back face culling, but that shouldn't affect anything
//binds the fbo
fbo.bind();
//the shader that writes info to gbuffer
//geometryPass.Bind(); //fixed pipeline for now
glDepthMask(GL_TRUE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glColor3f(0,1,0);
fly.uploadCamera(); //glLoadMatrixf
sphere.draw();
glDepthMask(GL_FALSE);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE);
fbo.unbind(); //glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT);
//shader that calculates lighting
drawtex.use();
//pointLightPass.SetUniform("cameraPos", camera.GetTransform().GetPosition());
drawtex.set("tex", *(Texture2D*)fbo.colour[0]);
for (int i = 0; i < 2; i++)
{
//pointLightPass.SetUniformPointLight("light", pointLights[i]);
//pointLightPass.SetUniform("mvp", glm::mat4(1.0f));
//skybox.GetCubeMap()->Bind(9);
drawtex.set("modelviewMat", mat44::identity());
quad.draw();
}
drawtex.unuse();
//draw skybox
glEnable(GL_DEPTH_TEST);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer(0, 0, fbo.size.x, fbo.size.y, 0, 0, fbo.size.x, fbo.size.y, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//glCullFace(GL_FRONT);
glDepthFunc(GL_LEQUAL);
//m_transform.SetPosition(camera.GetTransform().GetPosition());
skybox.use();
skybox.set("mvp", fly.camera.getProjection() * fly.camera.getInverse() * mat44::translate(1,0,0));
//m_shader->SetUniform("mvp", camera.GetViewProjection() * m_transform.GetModel());
//m_shader->SetUniform("cubeMap", 0);
//m_cubeMap->Bind(0);
cube.draw();
skybox.unuse();
glDepthFunc(GL_LESS);
//glCullFace(GL_BACK);
//window.Update();
//window.SwapBuffers();

Passing data between CPU and GPU in textures

So I have a very complicated R^4 -> R^4 function, which I need to calculate for a lot of input glm::vec4s, in real time, so I want to do it on the GPU, for all vec4s parallel.
What I figured is that I would create a GL_RGBA32F texture, 1920x1 resolution (1920 is enough for my purposes), copy my input data onto the texture, then call a drawing of a line, so the rasterizer calls a fragment for each of my vec4s. Then either write the results back to the texture using imageload/store or render it to a 1920x1 framebuffer, and read it from there.
Problem is that for some reason opengl can't read my GL_RGBA32F texture.
Here is my code:
Setting up the texture (currently loaded with dummy data):
glm::vec4 texturedata[1920];
for (unsigned int i = 0; i < 1920; i++)
{
texturedata[i] = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
}
glGenTextures(1, &datatexture);
glBindTexture(GL_TEXTURE_2D, datatexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1920, 1, 0, GL_RGBA, GL_FLOAT, texturedata);
Before each rendering:
glUseProgram(mprogram);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, datatexture);
glBindVertexArray(rasterizertriggervao);
glUniform1i(glGetUniformLocation(mprogram, "datatexture"), 0);
glDrawArrays(GL_LINES, 0, 2);
The rasterizertriggervao is 2 floats: -1, 1, and the vertex shader draws a nice line through the middle of my screen from that.
Fragment shader:
layout(binding = 0) uniform sampler2D datatexture;
out vec4 x;
void main()
{
x = vec4( (texture(datatexture, vec2(gl_FragCoord.x/1920.0, 0.0))).x, 0.0f, 0.0f, 1.0f );
}
So this should draw a nice red line in the middle of my screen for me. It draws a black one. The rasterizer called all 1920x1 fragments, and the texture is correctly copied to the GPU (I have Nvidia Nsight installed, which allows me to debug the GPU, check the contents of textures and whatnot on the GPU directly, and I checked, the texture is full of 1.0f).
However for some reason the sampling doesn't work.
I know that there are better ways to do GPGPU but this thing has to fit into a much bigger program nicely, and this is the way I need it to work, through textures :)
Your seem not to set the texture filter modes for your texture. Now, GL's defaults are (unfortunately) to use mip-mapping. But your texture is not mipmap-complete, so sampling from it will not work. You should add glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_NEAREAST) and probably also glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_NEAREAST).
As Andon M. Coleman already pointed out in the comments, you are not sampling the texture at the correct location. You should use vec2(gl_FragCoord.x/1920.0 + 0.5/1920.0, 0.5) in your case. I also agree with Andon M. Coleman's suggestion to directly use texelFetch(), since you can directly use the integer value `gl_FragCoord.x'.

OpenGL Texture transparency doesn't work

I'm having an OpenGL texture that is binded to a simple quad.
My problem is: My texture is 128x128 pixels image. I'm only filling up about 100x60 pixels on that image, the other pixels are transparent. I saved it in a .png file. When I'm drawing, the transparent part of the binded texture is white.
Let's say I have a background. When I draw this new quad on this background I can't see the through the transparent part of my texture.
Any suggestions?
Code:
// Init code...
gl.glEnable(gl.GL_TEXTURE_2D);
gl.glDisable(gl.GL_DITHER);
gl.glDisable(gl.GL_LIGHTING);
gl.glDisable(gl.GL_DEPTH_TEST);
gl.glTexEnvi(gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_MODE, gl.GL_MODULATE);
// Drawing code...
gl.glBegin(gl.GL_QUADS);
gl.glTexCoord2d(0.0, 0.0);
gl.glVertex3f(0.0f, 0.0f, 0.0f);
gl.glTexCoord2d(1.0, 0.0);
gl.glVertex3f(1.0f, 0.0f, 0.0f);
gl.glTexCoord2d(1.0, 1.0);
gl.glVertex3f(1.0f, 1.0f, 0.0f);
gl.glTexCoord2d(0.0, 1.0);
gl.glVertex3f(0.0f, 1.0f, 0.0f);
gl.glEnd();
I've tried almost everything, from enabling blending to change to GL_REPLACE, however I can't get it to work.
Edit:
// Texture. Have tested both gl.GL_RGBA and gl.GL_RGB8.
gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, (int)gl.GL_RGBA, imgWidth, imgHeight,
0, gl.GL_BGR_EXT, gl.GL_UNSIGNED_BYTE, bitmapdata.Scan0);
Check that your texture is of RGBA format, and enable blending and set the blending func:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
And draw the texture. If your texture is not RGBA, then there is no alpha and blending won't do anything.
EDIT: Since you posted your code, i can a spot a serious error:
glTexImage2D(gl.GL_TEXTURE_2D, 0, (int)gl.GL_RGBA, imgWidth, imgHeight, 0, gl.GL_BGR_EXT, gl.GL_UNSIGNED_BYTE, bitmapdata.Scan0);
You're telling GL that the texture has internalFormat RGBA, but the bitmap data has BGR format, so, no alpha from your texture data. This assumes alpha = 1.0.
To correct it, load your PNG with RGBA format and use GL_RGBA as internalFormat and format parameters for glTexImage2D.
When I'm drawing, the transparent part of the binded texture is white.
That means your PNG-parser converted transparent regions to the value of white. If you want to render transparent layers with OpenGL you dont typically depend on texture-files to hold the transparency but instead use the GLBlendFunc(). More information here:
http://www.opengl.org/resources/faq/technical/transparency.htm
Also, should you render to a frame buffer and copy the result into a texture, check that the frame buffer has alpha turned on. For example when using osgViewer this can be achived by (do this before calling setUpViewInWindow):
osg::DisplaySettings *pSet = myviewer.getDisplaySettings();
if(pSet == NULL)
pSet = new osg::DisplaySettings();
pSet->setMinimumNumAlphaBits(8);
myviewer.setDisplaySettings(pSet);
and under qt it should work with (from http://forum.openscenegraph.org/viewtopic.php?t=6411):
QGLFormat f;
f.setAlpha( true ); //enables alpha channel for this format
QGLFormat::setDefaultFormat( f ); //set it as default before instantiations
setupUi(this); //instantiates QGLWidget (ViewerQT)
Normally it is better to render directly into a frame buffer but I came alonge this while preparing some legacy code and in the beginning it was very hard to find this.