How come when i manually change the alpha value in array, being passed to shader, the result is the same for both 0.0f and 1.0f?
I was expecting the object to be drawn with some level of transparency, depending on alpha value.
I'm not using any textures. I always see my red object against a black background.
accessing glsl variable from java ..
float[] color = {1.0f, 0.0f, 0.0f, 1.0f};
gl2.glGetUniformLocation(shaderProgram, "vColor");
gl2.glUniform4fv(mColorHandle, 1, color, 0);
glsl, fragment shader ..
#version 120
uniform vec4 vColor;
void main() {
gl_FragColor = vColor;
gl_FragColor.a = 0.0; // does not make object transparent
// gl_FragColor.a = 1.0; // does not make object transparent
}
Needed to enable blending ..
gl2.glEnable(GL.GL_BLEND);
gl2.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
Related
I am trying to understand how to manipulate my renderings with shaders. I haven't changed the projection matrix of the scene but I draw a triangle with vertices = {-0.5, -0.5} {0.5, -0.5} {0, 0.5}. I then pass in a vec2 position of a "light" to the uniform of my fragment shader that i want to essentially shine onto my triangle from the top right of the triangle (lightPos = (0.5,0.5))
Here is a very bad drawing of where everything is located.
and this is what I aim to have in my triangle (kind of.. it doesnt need to be white to blue it just needs to be brighter near the light and darker further away)
Here is the shader
#version 460 core
in vec3 oPos;
out vec4 fragColor;
uniform vec3 u_outputColor;
uniform vec2 u_lightPosition;
void main(){
float intensity = 1 / length(oPos.xy - u_lightPosition);
vec4 col = vec4(u_outputColor, 1.0f);
fragColor = col * intensity;
}
Here is the basic code to compiling the shader(most of it is abstracted away so it is fairly simple)
/* Test data for shader program. */
program.init("passthrough.vert", "passthrough.frag");
program.setUniformVec3("u_outputColor", 0.3f, 0.3f, 0.8f);
program.setUniformVec2("u_lightPosition", 0.5f, 0.5f);
GLfloat vertices[9] = {-0.5f, -0.5, 0, 0,0.5f,0, 0.5, -0.5, 0};
Here is vertex shader:
#version 460 core
layout (location = 0) in vec3 aPos;
out vec3 oPos;
void main(){
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
Every single test I have run to see why I can't get this to work seems to show me that if there is a slight color change it will change the entire triangle to a different shade. All tests show a triangle of ONE color across the entire thing; no gradient at all. I want the triangle to be a gradient that is brighter near the light and darker further from it. This is driving me crazy because I have been stuck on such a simple thing for 3 hours now and it just seems like any code I write modifies all 3 vertices at once as if they are in the exact same spot. I wrote the math out and I strongly feel as if this should work. Any help is very appreciated.
EDIT
The triangle after the solution fixed my issue:
Try this for your vertex shader:
#version 460 core
layout (location = 0) in vec3 aPos;
out vec3 oPos;
void main(){
oPos.xyz = aPos.xyz; // ADD THIS LINE
gl_Position = vec4(aPos.xyz, 1.0);
}
Your version never writes to oPos, so the fragment shader gets either a) a random value or, in your case b) vec3(0,0,0). Since your color calculation is based off of:
float intensity = 1 / length(oPos.xy - u_lightPosition);
This is basically the same as
float intensity = 1 / length(-1*u_lightPosition);
So the color only depends on the light position.
You can debug and verify this by setting your fragment color to oPos:
vec4 col = vec4(oPos.xy, oPos.z + 0.5, 1.0f);
If oPos was set correctly in the vertex shader, then this line in the fragment shader would show you an RGB ramp. If oPos is not set correctly, you'll see 50% blue.
Always check for errors and logs returned from OpenGL. It should have emitted a warning about this that would have sent you straight to the problem.
Also, I'm surprised that your entire triangle isn't being clipped since vertices have a z of 0.
I'm trying to use an atomic counter in a fragment shader.
Basically I'm displaying just a textured quad and need to make calculations on the texture data, and display the unaltered texture.
I began with writing a simple pass-through fragment shader, but the displayed texture is plain color. Either i'm missing something, i'm not sure if to use also vertex shader, as i'm processing only texture, seemed obsolete to me.
Fragment shader code:
#version 420
uniform vec2 texture_coordinate; uniform sampler2D my_color_texture;
void main() {
gl_FragColor = texture2D(my_color_texture, texture_coordinate);
}
Rendering pipeline - using shaprGL, but it's easily readable:
gl.Enable(OpenGL.GL_TEXTURE_2D);
String s = "my_color_texture"; //name of the texture variable in shader
gl.UseProgram(graycounter); // graycounter is a compiled/linked shader
GLint my_sampler_uniform_location = gl.GetUniformLocation(graycounter, s);
gl.ActiveTexture(OpenGL.GL_TEXTURE0);
gl.BindTexture(OpenGL.GL_TEXTURE_2D, ((dTexture)texture).texture); //texture id, working without shader on
gl.Uniform1ARB(my_sampler_uniform_location, 0);
gl.Begin(OpenGL.GL_QUADS); // show the rectangle
gl.Color(1.0f, 1.0f, 1.0f);
gl.TexCoord(0.0f, 0.0f); gl.Vertex(0.0f, 0.0f, 0.0f); // Bottom Left Of The Texture and Quad
gl.TexCoord(1.0f, 0.0f); gl.Vertex(w, 0.0f, 0.0f); // Bottom Right Of The Texture and Quad
gl.TexCoord(1.0f, 1.0f); gl.Vertex(w, h, 0.0f); // Top Right Of The Texture and Quad
gl.TexCoord(0.0f, 1.0f); gl.Vertex(0.0f, h, 0.0f); // Top Left Of The Texture and Quad
gl.End();
gl.UseProgram(0);
uniform vec2 texture_coordinate;
Uniform values do not change from fragment to fragment; that's why they're called "uniform". You probably wanted in rather than uniform.
Granted, since you're using legacy features, you probably need to hook into the gl_TexCoord[] array. That's what the legacy vertex processor (since you're not using a VS) will spit out. Texture coordinate 0 will map to gl_TexCoord[0].
I did figure it finally out, and if someone has the same problem, here is the vertex shader - note no min.version
out vec4 texCoord;
void main(void)
{
gl_Position = ftransform();
texCoord=gl_TextureMatrix[0] * gl_MultiTexCoord0;
}
and the fragment shader - using version #440 to support atomic counters
#version 440
layout (binding = 0, offset = 0) uniform atomic_uint g1;
uniform sampler2D my_color_texture;
in vec4 texCoord;
out vec4 fragColour;
void main() {
fragColour = texture2D(my_color_texture,texCoord.xy);
if (abs(fragColour.r*255 - 0)<1) atomicCounterIncrement(g1);
}
I created 8x8 pixel bitmap letters to render them with OpenGL, but sometimes, depending on scaling I get weird artifacts as shown below in the image. Texture filtering is set to nearest pixel. It looks like rounding issue, but how could there be some if the line is perfectly horizontal.
Left original 8x8, middle scaled to 18x18, right scaled to 54x54.
Vertex data are unsigned bytes in format (x-offset, y-offset, letter). Here is full code:
vertex shader:
#version 330 core
layout(location = 0) in uvec3 Data;
uniform float ratio;
uniform float font_size;
out float letter;
void main()
{
letter = Data.z;
vec2 position = vec2(float(Data.x) / ratio, Data.y) * font_size - 1.0f;
position.y = -position.y;
gl_Position = vec4(position, 0.0f, 1.0f);
}
geometry shader:
#version 330 core
layout (points) in;
layout (triangle_strip, max_vertices = 4) out;
uniform float ratio;
uniform float font_size;
out vec3 texture_coord;
in float letter[];
void main()
{
// TODO: pre-calculate
float width = font_size / ratio;
float height = -font_size;
texture_coord = vec3(0.0f, 0.0f, letter[0]);
gl_Position = gl_in[0].gl_Position + vec4(0.0f, height, 0.0f, 0.0f);
EmitVertex();
texture_coord = vec3(1.0f, 0.0f, letter[0]);
gl_Position = gl_in[0].gl_Position + vec4(width, height, 0.0f, 0.0f);
EmitVertex();
texture_coord = vec3(0.0f, 1.0f, letter[0]);
gl_Position = gl_in[0].gl_Position + vec4(0.0f, 0.0f, 0.0f, 0.0f);
EmitVertex();
texture_coord = vec3(1.0f, 1.0f, letter[0]);
gl_Position = gl_in[0].gl_Position + vec4(width, 0.0f, 0.0f, 0.0f);
EmitVertex();
EndPrimitive();
}
fragment shader:
#version 330 core
in vec3 texture_coord;
uniform sampler2DArray font_texture_array;
out vec4 output_color;
void main()
{
output_color = texture(font_texture_array, texture_coord);
}
I had the same problem developing with Freetype and OpenGL. And after days of researching and scratching my head, I found the solution. In my case, I had to explicitly call the function 'glBlendColor'. Once, I did that, I did not observe any more artifacts.
Here is a snippet:
//Set Viewport
glViewport(0, 0, FIXED_WIDTH, FIXED_HEIGHT);
//Enable Blending
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendColor(1.0f, 1.0f, 1.0f, 1.0f); //Without this I was having artifacts: IMPORTANT TO EXPLICITLY CALLED
//Set Alignment requirement to 1 byte
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
I figured out the solution after reviewing the source code of this OpenGL-Freetype library on github: opengl-freetype library
Well, when using nearest filtering, you will see such issues if your sample location is very close to the boundary between two texels. And since the tex coords are to be interpolated separately for each fragment you are drawing, slight numerical inaccuracies will result in jumping between those two texels.
When you draw an 8x8 texture to an 18x18 pixel big rectangle, and your rectangle is perfectly aligned to the putput pixel raster, you are almost guaranteed to trigger that behavior:
Looking at the texel coodinates will then reveal that for the very bottom output pixel, the texture coords would be interpolated to 1/(2*18) = 1/36. Going one pixel up will add 1/18 = 2/36 to the t coordinate. So for the fifth row from the bottom, it would be 9/36.
So for the 8x8 texel big texture you are sampling from, you are actually sampling at unnormalized texel coordinates (9/36)*8 == 2.0. This is exactly the boundary between the second and third row of your texture. Since the texture coordinates for each fragment are interpolated by a barycentric interpolation between the tex coords assigned to the three vertices froming the triangle, there can be slight inaccuracies. And even the slightest possible inaccuracy representable in floating point format would result in flipping between two texels in this case.
I think your approach is just not good. Scaling bitmap fonts is always problematic (maybe besides integral scale factors). If you want nicely looking scalable texture fonts, I recommend you to look into signed distance fields. It is quite a simple and powerful technique, and there are tools available to generate the necessary distance field textures.
If you are looking for a quick hack, you coud also just offset your output rectangle slightly. You basically must make sure to keep the offset in [-0.5,0.5] pixels (so that never different fragments are generated during rasterization, and you must make sure that all the potential sample locations will never lie close to an integer, so the offset will depend on the actual scale factor.
At the moment I have simple fragment shader which returns one color (red). If I want to change it a different RGBA color from C code, how should I be doing that?
Is it possible to change an attribute within the fragment shader from C directly or should I be changing a solid color attribute in my vertex shader and then passing that color to the fragment shader? I'm drawing single solid colour rectangles - nothing special.
void main()
{
gl_FragColor = vec4( 1.0, 0, 0, 1 );"
}
If you are talking about generating the shader at runtime, then you COULD use the c string formatting functions to insert the color into the line "gl_FragColor..."
I would not recommend you do this since it will be unneccessary work. The standard method to doing this is using uniforms as so:
// fragment shader:
uniform vec3 my_color; // A UNIFORM
void main()
{
gl_FragColor.rgb = my_color;
gl_FragColor.a = 1; // the alpha component
}
// your rendering code:
glUseProgram(SHADER_ID);
....
GLint color_location = glGetUniformLocation(SHADER_ID, "my_color");
float color[3] = {r, g, b};
glUniform3fv(color_location, 1, color);
....
glDrawArrays(....);
UPDATE: Danvil solved it in a comment below. My texture format was GL_RGB not GL_RGBA which of course means that the alpha values aren't kept. Don't know why I didn't realize... Thanks Danvil.
I am rendering to a texture using a GLSL shader and then sending that texture as input to a second shader. For the first texture I am using RGB channels to send color data to the second GLSL shader, but I want to use the alpha channel to send a floating point number that the second shader will use as part of its program. The problem is that when I read the texture in the second shader the alpha value is always 1.0. I tested this in the following way:
at the end of the first shader I did this:
gl_FragColor = vec4(r, g, b, 0.1);
and then in the second texture I read the value of the first texture using something along the lines of
vec4 f = texture2D(previous_tex, pos);
if (f.a != 1.0) {
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
return;
}
No pixels in my output are black, whereas if I change the above code to read
gl_FragColor = vec4(r, g, 0.1, 1.0); //Notice I'm now sending 0.1 for blue
and in the second shader
vec4 f = texture2D(previous_tex, pos);
if (f.b != 1.0) {
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
return;
}
All the appropriate pixels are black. This means that for some reason when I set the alpha value to something other than 1.0 in the first shader and render to a texture, it is still seen as being 1.0 by the second shader.
Before I render to texture I glDisable(GL_BLEND);
It seems pretty clear to me that the problem has to do with OpenGL handling alpha values in some way that isn't obvious to me since I can use the blue channel in the way I want, and figured someone out there will instantly see the problem.
Also, the way I invoke the shader programs is by drawing a quad (I'm rendering to a framebuffer that has a texture):
gl.glUseProgram(shaderprogram);
gl.glUniform1iARB(gl.glGetUniformLocationARB(shaderprogram, "previous_tex"), 1);
gl.glDisable(GL.GL_BLEND);
gl.glBegin(GL.GL_QUADS);
{
gl.glVertex3f(0.0f, 1.0f, 1.0f);
gl.glVertex3f(1.0f, 1.0f, 1.0f);
gl.glVertex3f(1.0f, 0.0f, 1.0f);
gl.glVertex3f(0.0f, 0.0f, 1.0f);
}
gl.glEnd();
gl.glUseProgram(0);