How to properly upscale a texture in opengl? - c++

Let's say, for the simplicity of this question, I want to create a texture containing a color gradient from black to red. I know there are much easier ways to achieve this but it is a good example for my problem.
I figured, i could simply create a texture from an float array like so:
float values[4] {
0.f, 1.f,
0.f, 1.f
}
// gen texture
unsigned int texId;
glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D, texId);
// set filter and wrap
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// copy values
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, 2, 2, 0, GL_RED, GL_FLOAT, values);
And draw it:
float vertices[8] {
-1.f, -1.f, 0.f, 0.f,
1.f, -1.f, 1.f, 0.f,
1.f, 1.f, 1.f, 1.f,
-1.f, 1.f, 0.f, 1.f
}
// generate vertex buffer, vertex buffer layout and vertex array
unsigned int[6] indices {
0, 1, 2,
2, 3, 1
}
// generate index buffer
// bind everything
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
Where the bound vertex shader looks like this:
#version 330 core
layout(location=0) in vec2 in_position;
layout(location=1) in vec2 in_texCoords;
out vec2 texCoords;
void main() {
gl_Position = vec4(in_position, 0.f, 1.f);
texCoords = in_texCoords;
}
And the fragment shader like this:
#version 330 core
layout(location = 0) out vec4 out_color;
in vec2 texCoords;
uniform sampler2D u_gradient;
void main() {
float red = texture(u_gradient, texCoords).r;
out_color = vec4(red, 0.f, 0.f, 1.f);
}
Following this I'd expect to get an color gradient from left to right (black to red) across my entire window.
However what I get is a gradient from about 1/4 to 3/4 of the window in x and y direction (See image below). I've also noted that the wrap of repeat does not seem to apply here as what I get looks like mirror-repeat.
Result:
I've played around with the fragment shader using fixed values instead of texCoords and figured that a range from .25 to .75 on the x axis represents the entire gradient (.25 maps to 0 for red and .75 to 1).
Changing the amount of 'steps' passed as values to the texture (eg. a 4x4 array) did not change the results.
I've also tried using an image as texture (loaded with stb_image, resolution 1920x1080) which works perfectly fine and spreads across the entire screen.
For clarification: Why do the texCoords for the gradient range from .25 to .75 and not from 0 to 1 and how can I fix it (besides adjusting the texCoords itself)?

Lets assume you have a 2x2 texture
2x2 Texture
If this texture is wrapped on a grid of 6x6 fragments, the the center of a texel is on exactly on the texel in the middel of 3x3 tile of the 6x6 square:
6x6 quad
The color of the other fragments depends on the the texture parameters - see glTexParameter.
Since the texture is magnified, the GL_TEXTURE_MAG_FILTER is significant.
If it is GL_NEAREST, then the color of the fragments is that one of the closest texel, to the texture coordinates of the fragment:
If it is GL_LINEAR, then the color is interpolated, by the weighted average of the 4 pixels which are closest to the texture coordinates.
The interpolation at the borders of the 6x6 quad depends on the wrap parameters GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T.
If the parameters are GL_REPEAT (which is default), the the texture is treated as an endless texture and the interpolation of the interpolation of the color at the borders takes into account the texels on the opposite side of the texture. This is used for seamless textures and tiling:
If it is GL_CLAMP_TO_EDGE, then the interpolated color at the borders is clamped to the color of the texels at the border of the texture:
Apply the texture wrap parameter GL_CLAMP_TO_EDGE to the texture object,
float values[4] { 0.f, 1.f, 0.f, 1.f };
unsigned int texId;
glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D, texId);
// set filter and wrap
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// copy values
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, 2, 2, 0, GL_RED, GL_FLOAT, values);
to get the following gradient:

Related

OpenGL Frag Shader texture fades after every write

I have a program that takes the following texture:
which is generated via FreeType2. Basically, it's creating a texture atlas for every character that I've requested to be drawn. As you can see, the characters are bright and clear. In fact, you can see that the top-leftmost pixel of the lowercase 'i' has a value of 71 (out of 255) or 0.7098 when I inspect the texture in RenderDoc.
Next, the engine blits letters onto a Framebuffer Object. This is done via textured quads. The vertex shader:
#version 330
layout(location=0) in vec2 inVertexPosition;
layout(location=1) in vec2 inTexelCoords;
layout(location=2) in float inDepth;
out vec2 texelCoords;
out float depth;
void main()
{
gl_Position = vec4(inVertexPosition.x,-inVertexPosition.y, 0.0, 1.0);
texelCoords = vec2(inTexelCoords.x,1-inTexelCoords.y);
depth = inDepth;
}
And the frag shader:
#version 330
layout(location=0) out vec4 frag_colour;
in vec2 texelCoords;
in float depth;
uniform sampler2D uTexture;
uniform vec4 uTextColor;
void main()
{
vec4 c = texture(uTexture,texelCoords);
frag_colour = uTextColor * c.r;
gl_FragDepth = depth;
}
As you can see, it's sets the pixel color to be a factor of the red channel.
However, when I view the contents of the FBO via RenderDoc, and saved out to file here, you see this:
If you look at this without transparency (just a second layer added underneath in Gimp to illustrate better):
You can see that the text is a little faded compared to what it was before. If you look at the top-leftmost pixel of the lowercase 'i', it's now a value of 50.2, or for a range of 0-1 it's 0.50196 (via RenderDoc).
Next, when the FBO is finally put onto the screen via another textured quad it fades even more. First here's the vertex shader:
#version 330
layout(location=0) in vec2 inVertexPosition;
layout(location=1) in vec2 inTexelCoords;
varying vec2 texelCoords;
void main()
{
gl_Position = vec4(inVertexPosition.x,-inVertexPosition.y, 0.0, 1.0);
texelCoords = vec2(inTexelCoords.x,1-inTexelCoords.y);
}
and the fragment shader:
#version 330
precision highp float;
layout(location=0) out vec4 frag_colour;
varying vec2 texelCoords;
uniform sampler2D uTexture;
void main()
{
vec4 c = texture(uTexture,texelCoords);
frag_colour = c;
}
The results, as I said are more faded than before:
original:
gimp background for clarity:
now that pixel has a value of 25.1 or 0.05139.
What is causing this fading after every render?
I think it's important to note that the brighter areas don't fade.
My Framebuffer creation code
glGenFramebuffers(1, &m_framebuffer);
glGenTextures(1, &m_fboColorAttachment);
glGenTextures(1, &m_fboAdditionalInfo);
glGenTextures(1, &m_fboDepthStencil);
glCall(glBindFramebuffer,GL_FRAMEBUFFER, m_framebuffer);
/* setup color output 0 */
glBindTexture(GL_TEXTURE_2D, m_fboColorAttachment);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
glCall(glTexImage2D, GL_TEXTURE_2D, 0, GL_RGBA8, screenDimensionsX, screenDimensionsY, 0, GL_BGRA, GL_UNSIGNED_BYTE, nullptr);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_fboColorAttachment, 0);
glBindTexture(GL_TEXTURE_2D, 0);
/* setup color output 1 */
glBindTexture(GL_TEXTURE_2D, m_fboAdditionalInfo);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
glCall(glTexImage2D, GL_TEXTURE_2D, 0, GL_R32UI, screenDimensionsX, screenDimensionsY, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, nullptr);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, m_fboAdditionalInfo, 0);
glBindTexture(GL_TEXTURE_2D, 0);
/* setup depth and stencil */
glBindTexture(GL_TEXTURE_2D, m_fboDepthStencil);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
glCall(glTexImage2D, GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, screenDimensionsX, screenDimensionsY, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_fboDepthStencil, 0);
glBindTexture(GL_TEXTURE_2D, 0);
The initial (red) texture creation:
glActiveTexture(GL_TEXTURE0);
glGenTextures(1,&textureData.texture);
glBindTexture(GL_TEXTURE_2D,textureData.texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 500, 500, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
My blending is done as
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
has a value of 71 (out of 255) or 0.7098
No idea, what you even mean here. 71/255 would be 0.278. 0.7098 normalized would be 181 out of 255. Looks like your "out of 255" are just percentage values, out of 100%.
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
You use that color values from the red channel also as alpha, so, when you have blending enabled, you end up with 0.7098*0.7098=.5038. Since the result will be rounded to the nearest reprersentable value, we rather end with 181/255 * 181/255 = .50382 rounded to 128/255
it's now a value of 50.2, or for a range of 0-1 it's 0.50196
128/255 is 0.50196078....
So the solution is: disable blending for all steps when you don't need it. Or if you need it, set useful alpha values.
Side note:
now that pixel has a value of 25.1 or 0.05139.
No Idea what this means, the 25.1 does not relate to 0.05139 in any obvious way, you definitively switched the meaning of those values again.

Why is my texture loaded into opengl not mapped correctly?

I am trying to load a simple model in openGL. Currently, I have a problem with the textures. The texture definitely does show up, but it is messed up and it also does not cover all the model (part of the model is black). I have tried several things to determine what is the source of the problem. I passed in a uniform red texture and it renders correctly. I used the texture coord as R and G value in the fragment shader and I get a red-green model so I assume the texture coordinate is also fine.
The texture is messed up, and part of it is black. This is just a simple minecraft character
the model's texture, which is a png
Here's how I am creating texture:
imageData = stbi_load(path.c_str(), &width, &height, &colorFormat, 0);
glGenTextures(1, &texID);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texID);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
My fragment shader:
void main(){
vec4 l = normalize(lightSourcePosition - positionEyeCoord);
vec4 normalFrag = normalize(normalEyeCoord);
if (hasTexture == 1){
vec4 textureKD = vec4(texture(textureSampler, texCoord).rgba);
vec4 diffuse = vec4(lightIntensity, 0.0) * textureKD * max(0.0, dot(l, normalFrag));
vec4 ambient = vec4(ambientIntensity, 0.0) * textureKD;
gl_FragColor = ambient + diffuse;
}
else {
vec4 diffuse = vec4(lightIntensity * KD, 0.0) * max(0.0, dot(l, normalFrag));
vec4 ambient = vec4(ambientIntensity * KA, 0.0);
gl_FragColor = ambient + diffuse;
}
}
Most likely, your character has been modeled using DirectX conventions for texturing. In DirectX, the texture coordinate origin is the top left of the image, whereas it is the bottom left corner in OpenGL.
There are a couple of things you can do (choose one):
When you load the model, replace all texture coordinates (u, v) by (u, 1 - v).
When you load the texture, flip the image vertically
In your shader, use vec2(texCoord.x, 1 - texCoord.y) for your texture coordinates.
I advise against using the third option for anything other than quick testing.

opengl - texture clamping not working in post processing

I'm having a problem with post processing in my deferred renderer.
When I'm applying an effect like bloom on top of my scene, the bottom of the bloom effect texture leaks into the top of my screen, the top of the texture leaks into the bottom of the screen, the left into the right of the screen and so on.
Looks like the uv coords don't get clamped correctly, although I thought I'd have set that all correctly.
The bloom effect in this case is created in a lower resolution and the gets upsampled using linear filtering.
This image that shows the problem:
I render the postprocessing effects using a simple quad:
glm::vec3(-1.f, -1.f, 0.f),
glm::vec3(1.f, -1.f, 0.f),
glm::vec3(1.f, 1.f, 0.f),
glm::vec3(-1.f, 1.f, 0.f)
This is the vertex shader I use to render the quad:
#version 430 core
layout(location = 0) in vec3 POSITION;
noperspective out vec2 tex_coord;
void main(void)
{
tex_coord = POSITION.xy * 0.5 + 0.5;
gl_Position = vec4(POSITION.xy, 0.0, 1.0);
}
And if course in the fragment shader I'm doing something like this:
#version 430 core
uniform sampler2D uTexture;
noperspective in vec2 tex_coord;
out vec4 frag_color;
void main(void)
{
frag_color = texture(uTexture, tex_coord);
}
The effect got rendered into a frame buffer object which got set up like this:
glGenFramebuffers(1, &_filterFbo);
glBindFramebuffer(GL_FRAMEBUFFER, _filterFbo);
// filter texture
glGenTextures(1, &_filterTexture);
glBindTexture(GL_TEXTURE_2D, _filterTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, _effectWidth, _effectHeight, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _filterTexture, 0);
I really don't know what's the problem here, I hope anyone got an idea.

Shadow mapping in OpenGL with a spotlight produces unusual effect

I have been trying to implement shadow mapping. Whilst I think that I am now close, I have come stuck with a strange effect (illustrated below):
As you can see, the shadow region appears too small. There is also an unusual effect on the cube itself.
The geometry being rendered is a cube of dimensions 1.0 on a square plane of dimensions 100.0. The scene contains a single spotlight with an angle (from one side to the other) of 0.5 radians and a range of 100.0. This spotlight orbits about the y-axis and adjusts its rotation to look at the origin.
I setup the framebuffer and depth texture (512 x 512) as follows:
// Create and configure the depth texture.
glGenTextures(1, &m_depthTexture);
glBindTexture(GL_TEXTURE_2D, m_depthTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
GLfloat border[] = { 1.0f, 1.0f, 1.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, (void*)0);
// Assign the depth texture to texture channel 0.
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_depthTexture);
// Create and configure the framebuffer.
glGenFramebuffers(1, &m_framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthTexture, 0);
GLenum drawBuffers[] = { GL_NONE };
glDrawBuffers(1, drawBuffers);
I then render the scene to the shadow map framebuffer from the perspective of the spotlight. This seems to be working. Inspecting the depth texture using an OpenGL debugging tool revealed the following:
The scene is rendered a second time, where I set the uniforms for the depth texture and shadow matrix:
glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_2D, shadowMap.depthTexture());
program->uniform("shadowMap", 1);
const M3D::Matrix4 lightViewMatrix = lightTransformComponent->transformationMatrix().inverse();
const float invTanHalfFov = 1.0f / std::tan(coneAngle * 0.5f);
const float nearClipPlane = 0.3f;
const float farClipPlane = lightLightComponent->range();
const float zRange = nearClipPlane - farClipPlane;
const Matrix4 lightProjectionMatrix(
invTanHalfFov, 0.0f, 0.0f, 0.0f,
0.0f, invTanHalfFov, 0.0f, 0.0f,
0.0f, 0.0f, -(nearClipPlane + farClipPlane) / zRange, 2.0f * nearClipPlane * farClipPlane / zRange,
0.0f, 0.0f, 1.0f, 0.0f
);
const Matrix4 shadowMatrix = lightProjectionMatrix * lightViewMatrix * modelMatrix;
program->uniform("shadowMatrix", shadowMatrix);
I compute the shadow coordinate in the vertex shader:
f_shadowCoordinate = shadowMatrix * vec4(v_position, 1.0f);
Then, in the fragment shader, I project this coordinate and bias it to range in the interval [0, 1].
vec2 projectedShadowCoordinates = (f_shadowCoordinate.xy / f_shadowCoordinate.w) * 0.5f + vec2(0.5f, 0.5f);
float shadowDistance = texture(shadowMap, projectedShadowCoordinates).x;
return vec4(1.0f) * shadowDistance;
The problem was caused by mistakenly setting the projection matrix uniform to the camera's projection matrix (instead of the light's projection matrix) when rendering to the shadow framebuffer.

GLSL sampler2DRect and single channel (GL_RED) data

I have pixel map data 1 channel, 8 bit.
I have pixel map width and height.
I'm trying to submit pixmap data to fragment shader.
I'm using ogl3 with VAO and VBO.
My setup:
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_RECTANGLE, texture);
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, data);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, ..., vertices, GL_STATIC_DRAW);
...create program...
glUseProgram(program);
glUniform1i(glGetUniformLocation(program, "image"), 0);
glDrawArrays(GL_TRIANGLE_FAN, 0, ...);
And fragment shader:
uniform sampler2DRect image;
varying vec2 varying_texcoord;
void main() {
vec4 sample = texture2DRect(image, varying_texcoord);
gl_FragColor = vec4(1.0, 0.0, 0.0, sample.a);
}
gl_FragColor should paint pixels light and dark red depending of sample.a value, however it seems that sample.a is always 1.0 - I'm getting pure red #ff0000.
I think the problem is in glTexImage2D, isn't it?
Please assume program and data are valid.
I believe the answer you are looking for is in the documentation for glTexImage2D. It says
"GL_RED:
Each element is a single red component.The GL converts it to floating point and assembles it into an RGBA elementby attaching 0 for green and blue, and 1 for alpha. Each component is then multiplied by the signed scale factor GL_c_SCALE, added to the signed bias GL_c_BIAS, and clamped to the range [0,1]."
You're asking for the .a component, which is always 1. You need to use the component the texture actually contains data in - which is .r
Hope this helps!
The question is very old but the answer could help others.
You need to use true pixel coordinates if you use sampler2DRect.
I assume you copy the incoming texture coordinates in the vertex shader to your varying_texcoord.
If you do so, you need to compute the coordinates:
vec2 coords = varying_texcoord * imageSize(image);
Then pass the coordinates:
vec4 sample= texture(image, coords);