I've been trying to display graphics using Rust, SDL2 and OpenGL (GLSL). The geometry renders fine, but I'm having problems with color in the fragment shader. Im currently rendering two triangles that together form a square covering the entire screen.
The vertices being drawn:
let vertices: Vec<f32> = vec![
// positions
1.0, -1.0, 0.0, // bottom right
-1.0, -1.0, 0.0, // bottom left
-1.0, 1.0, 0.0, // top
-1.0, 1.0, 0.0, // top
1.0, 1.0, 0.0, // top right
1.0, -1.0, 0.0, // bottom right
];
This is my vertex shader:
#version 330 core
layout (location = 0) in vec3 Position;
out vec2 fragCoord;
void main() {
gl_Position = vec4(Position, 1.0);
fragCoord = Position.xy;
}
And my fragment shader:
#version 330 core
uniform vec2 u_resolution;
in vec2 fragCoord;
out vec4 fragColor;
void main() {
vec2 uv = fragCoord.xy/u_resolution.xy;
vec3 col = vec3(uv,0.0);
fragColor = vec4(col, 1.0);
}
u_resolution
variable is just the dimension of the screen (800 by 600). The corresponding render is:
I submitted the following shader to Shadertoy.com, which should be equivalent to mine:
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
vec2 uv = fragCoord/iResolution.xy;
vec3 col = vec3(uv,0.0);
fragColor = vec4(col,1.0);
}
And the output on the site is:
I dont understand what is happening here, is the geometry on the site somehow different? The eventual purpose of my program is to run a ray-marcher algorithm on the GPU, but I'm unsure as to what geometry to render. My guess was just a rectangle that covers the whole screen (and transforms in line with the camera), but do I need something different? I want to be able to control the color of each pixel individually and render geometry with ray marching, not the rasterizer. Is my approach completely off?
Note: The far left side in the pictures are the result of bad cropping on my part.
Your fragCoord
and Shadertoy's fragCoord
are actually not the same.
fragCoord
is in the range of vec2(-1.0)
to vec2(1.0)
, i.e. normalized device coordinates (NDC)fragCoord
is in the range of vec2(0.0)
to iResolution
, i.e. window relative coordiantes (which is what you want)Shadertoy's fragCoord
is simply gl_FragCoord.xy
, which is the window relative coordinate of the current fragment.
Additionally, the reason you're seeing 4 colors like that, is suggesting that the value of u_resolution
is actually vec2(0.0)
.
Because again, your fragCoord
is in NDCs. So when a fragCoord
component is below 0.0
it would result in negative infinite. Then when a fragCoord
component is above zero it would result in positive infinite.
These infinite values would then effectively be clamped and result in the color extremes you're seeing.
You can mirror this behavior on Shadertoy by converting fragCoord
back into NDC, and then dividing by vec2(0.0)
.
void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
vec2 ndc = (fragCoord / iResolution.xy) * 2.0 - 1.0;
vec2 wrongResolution = vec2(0.0);
vec2 uv = ndc / wrongResolution;
fragColor = vec4(vec3(uv, 0.0), 1.0);
}