Implementing Shaders in my Engine

Apr 29, 2025

So The past few days I’ve been messing around in Shader Toy and trying to get learn more about the glsl language. Here is a Shader that I made on my own yesterday. Paste the code below to ShaderToy.com to see it in action.

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = (fragCoord * 2. - iResolution.xy) / iResolution.y;
    vec2 uv0 = uv;
    float distance = length(uv / .2);
    distance -= iTime; 
    distance = fract(distance);
    distance = length(uv) * sin(distance) -.8;
    distance = abs(distance);
    
    float new = length(uv0);
    distance = sin(new) * distance;
    
    fragColor = vec4(distance, distance, distance * 2., 1.0);
}
undefined

It’s not the best shader, and not even close to the tutorial one, but now I’m practicing what I’m learning and trying to use what i’ve learned in my own way so I can put the pieces together.

Ultimately I want to be able to work with these shaders in my own engine. So I’m trying to implement some of these concepts and it’s tricky. There are two attributes that Shader Toy uses; iTime and iResolution that I can’t figure out how to pass into my shader glsl file.

From learnopengl.com

// In the main.cpp file
while(!glfwWindowShouldClose(window)) {
	[...] // previous code
		glUseProgram(shaderProgram);
		// update the uniform color
    float timeValue = glfwGetTime();
    float greenValue = sin(timeValue) / 2.0f + 0.5f;
    int vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor");
    glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f);
	[...] // other code after
}

// Fragment Shader
#version 330 core

uniform vec4 ourColor;
out vec4 FragColor;

void main() {
  FragColor = ourColor;
}

So in this specific example they’re dealing with the color value, but I can take this and try to rework it into passing the time value to the shader.


int vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor");

  • On this line of code they’re setting vertexColorLocation to reference the Uniform attribute “ourColor” that is defined in the Fragment Shader.


glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f)

  • And on this line they’re using the glUniform4f() function to set the uniform “ourColor” to a vec4 by passing in vertexColorLocation as the first argument, and the 4 values of the vec4 as the last 4 arguments of the function.

So I wonder if it would work if I were to create a uniform float iTime; in my shader file and pass in the time with the glUniform1f() function.

And that works!!!!

Now I can start working with shaders on my own engine! Just have to follow these same steps to pass in the resolution!

Resolution isn’t as easy as I thought… I passed in the width and height of my viewport to the shader using the function glUniform2f() but it’s not reacting the same way Shader Toy does… so I’m uncertain what shader toy is doing to get the dimensions…

The point of having the iResolution is so I can prevent the shaders from stretching with calculations that depend on the screen resolution in the shader file. I was having some issues because I wasn’t aware that my vertexShader is already normalizing the fragCoord (Which is the position of the pixel being passed to the fragment shader), and I was trying to do it again in the fragment shader which was causing visual errors… It has nothing to do with the resolution being passed improperly, in fact I was doing it correctly. After realizing this issue and making the proper adjustments in my fragment shader I now have an Ellipse that is not being stretched. However if I stretch the window during runtime then I do get issues with the shaders being stretched. This is because I’m not checking and updating the resolution if the user has stretched the screen.

And the problem is now fixed! I created global screenWidth and screenHeight variables and update them in the main loop with these lines of code.

int width, height;
glfwGetFramebufferSize(window, &width, &height);
screenWidth = width;
screenHeight = height;

And in the glUniform2f() we pass in the screenWidth and screenHeight variables and now I no longer have any stretching issues!


Blog

Kero Mena