Warning: Undefined array key "HTTP_ACCEPT_LANGUAGE" in /var/www/vhosts/bilgigunlugum.net/httpdocs/index.php on line 43
SDL Oyun Programlama

SDL3 Oyun Programlama sayfalarımız yayında...

Ana sayfa > Oyun programlama > SDL3 programming > Color modulation

Color modulation

In this section, we will examine the program that changes the texture pixel colors created from an image file with the .png extension with the SDL_SetTextureColorMod() function.

When the program runs, in addition to the basic operations, the following operations occur:

  1. At the beginning of the program, the global variables shown below are first defined:
    • bool r, g, b: Color variables
    • int level_rgb: RGB level variable
  2. The init_vals() function initializes the r, g, b and level_rgb variables.
  3. In the load_img() function, a texture is created by loading an image with the .png extension with the IMG_LoadTexture() function.
  4. In the process_event() function,
    • When one of the R, G and B keys is pressed, the r, g and b variables are reversed.
    • When the F key is pressed, the r, g and b variables are true.
    • When the up arrow key is pressed, the level_rgb variable value is increased by 5 if it is less than 255.
    • When the down arrow key is pressed, the level_rgb variable value is decreased by 5 if it is greater than 0.
  5. In the update_screen() function, the color values ​​used in the SDL_SetWindowTitle() function and the color process status are shown in the main window title.
  6. In the draw_screen() function,
    • The texture is recreated by adjusting the color modulation on it, multiplying the color channels of the texture by a certain color value with SDL_SetTextureColorMod() function.
    • The texture is transferred to the main window with SDL_RenderTexture() function.

The program runss as follows:

  1. Since the level_rgb variable value will decrease by 5 with each press of the down arrow key, the SDL_SetTextureColorMod() function is actively running and after the R, G and B values ​​in each pixel on the texture are rearranged, the texture is loaded to the main window with the SDL_RenderTexture() function. When the variable value is 0, the texture content is completely black.
  2. Since the level_rgb variable value will increase by 5 each time the up arrow key is pressed, the R, G and B values ​​in each pixel on the texture are rearranged and then the texture is loaded into the main window with the SDL_RenderTexture() function. When the variable value is 255, the texture content consists entirely of the original colors of the image.
  3. When the user presses one of the R, G or B keys before pressing the up or down arrow keys, the color operation represented by the pressed key is disabled. When the same key is pressed again, it is reactivated. For example, when the R key is pressed, the R value of the SDL_SetTextureColorMod() function always takes 255, regardless of the level_rgb variable value. When the same key is pressed again, the R value is affected by the level_rgb variable value.
  4. When the F key is pressed, all colors are reactivated.

SDL_SetTextureColorMod() function

The SDL_SetTextureColorMod() function sets the color modulation on an SDL_Texture. This process recreates the color channels of an image by multiplying them by a specific color value. This allows you to dynamically change the color tone of the image.


bool SDL_SetTextureColorMod(SDL_Texture *texture, Uint8 r, Uint8 g, Uint8 b);

texture: The SDL_Texture object to set.

r: Red color value (a number in the range of 0-255).

g: Green color value (a number in the range of 0-255).

b: Blue color value (a number in the range of 0-255).

This function multiplies all color channels on the SDL_Texture with the specified color values ​​and recreates them. Color modulation is performed using the following formula:

Color modulation allows us to change the pixel colors of textures. When we perform operations with the texture and RGB parameters that we pass to the SDL_SetTextureColorMod() function, each value that is different from 255 in the SDL_SetTextureColorMod() RGB values ​​changes the corresponding R, G or B value for each pixel in the texture.

The R, G or B value for each pixel in the texture is determined again according to the following formula:

A pixel's new R value = A pixel's old R value * (SDL_SetTextureColorMod() R value / 255)

If we assume that the SDL_SetTextureColorMod() R value is 100 and that the R value of any pixel is 200:

A pixel's new R value = 200 * (100/255) = 78.43

as is calculated.

If 255 is used for any color value in the SDL_SetTextureColorMod() function, there will be no change in that color in any pixel in the texture. In this case, if the R value of SDL_SetTextureColorMod() is 255, the value of the pixel will not change since the neutral value of the multiplication in the parentheses will be 1.

main.c file content will be as follows:


#include <stdio.h>
#include <SDL3/SDL.h>
#include <SDL3_image/SDL_image.h>

// Window width and height
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480

// Global variables
int is_running = false;            // Variable that controls the execution of the main loop of the program
SDL_Window *window = NULL;         // Main window variable
SDL_Texture *texture = NULL;       // Texture variable
SDL_Renderer *renderer = NULL;     // Renderer variable
bool r, g, b;                      // Color variables
int level_rgb;                     // RGB level variable

// Function prototypes
int init_window(void);             // Create window and renderer
void init_vals(void);              // Initialize values
void load_img(void);               // Load image to texture
void process_event(void);          // Process events
void update_screen();              // Update values
void draw_screen(void);            // Draw screen
void destroy_window(void);         // Destroy window

int main(int argc, char* argv[])
{
    // Create window and renderer
    is_running = init_window();

    // Initialize values
    init_vals();

    // Load .png file to texture
    load_img();

    // Main loop
    while (is_running) {
        process_event();       // Processing SDL events (Here keyboard inputs).
        update_screen();       // Updating variables
        draw_screen();         // Drawing objects on the window (Rendering)
    }

    // Destroy renderer and SDL window
    destroy_window();

    return 0;
}

// Create window and renderer
int init_window(void)
{
    // Initialize the SDL library.
    if(SDL_Init(SDL_INIT_VIDEO) == false) {
       SDL_Log("SDL init error: %s\n", SDL_GetError());
       return false;
    }

    // Create a window and a 2D rendering context for the window.
    if(!SDL_CreateWindowAndRenderer("SDL3 window - Color modulation", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
       return false;
    }

    return true;
}

// Initialization function that runs only once at the beginning of the program
void init_vals(void)
{
     r = true;
     g = true;
     b = true;

     level_rgb = 255;
}

// Load image to texture
void load_img(void)
{
     // Load image into a GPU texture.
     texture = IMG_LoadTexture(renderer, "color_mod.png");

	 if(texture == NULL)	{
	    SDL_Log("Load texture error: %s\n", SDL_GetError());
	 }
}

// Function to control SDL events and process keyboard inputs
void process_event(void)
{
     SDL_Event event;

     // Creating a loop to process user inputs
     while (SDL_PollEvent(&event)) {
        switch (event.type) {
            case SDL_EVENT_QUIT: // Logout action by the user (x button at the top right of the window)
                 is_running = false; // Terminates the execution of the program main loop.
                 break;

            case SDL_EVENT_KEY_DOWN: // Indicate that a key was pressed.
                 switch (event.key.key) {
                     case SDLK_R:
                          r = !r;
                          break;
                     case SDLK_G:
                          g = !g;
                          break;
                     case SDLK_B:
                          b = !b;
                          break;
                     case SDLK_F:
                          r = true;
                          g = true;
                          b = true;
                          break;
                     case SDLK_UP:
                          if(level_rgb<255) level_rgb+=5;
                          break;
                     case SDLK_DOWN:
                          if(level_rgb>0) level_rgb-=5;
                          break;
                     case SDLK_ESCAPE:
                          is_running = false;
                          break;
                 }
                 break;
        }
     }
}

// Updates objects in the main window
void update_screen(void)
{
     int r_color = r ? level_rgb : 255;
     int g_color = g ? level_rgb : 255;
     int b_color = b ? level_rgb : 255;

     char cdizi[100];
     sprintf(cdizi, "Color modulation - SDL_SetTextureColorMod(texture, %d, %d, %d) R: %s G: %s B: %s", 
	                 r_color, g_color, b_color, r ? "On" : "Off", g ? "On" : "Off", b ? "On" : "Off");
     SDL_SetWindowTitle(window, cdizi);
}

// Render function used to draw game objects in the main window
void draw_screen(void)
{
     SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // Set the color used for drawing operations.
     SDL_RenderClear(renderer); // Clear the current rendering target with the drawing color.

	 // Recreates an texture by multiplying its color channels by a specific color value.
	 SDL_SetTextureColorMod(texture, r ? level_rgb : 255, g ? level_rgb : 255, b ? level_rgb : 255);
     SDL_RenderTexture(renderer, texture, NULL, NULL);

     // Loading all objects drawn one by one to the back buffer to the front buffer at once and loading them onto the screen
     // This process prevents each drawn object from being displayed on the screen one by one.
     SDL_RenderPresent(renderer); // Update on screen all operations performed since the previous call
}

// Destroy Renderer and SDL window, exit from SDL3
void destroy_window(void)
{
     SDL_DestroyTexture(texture);
     SDL_DestroyRenderer(renderer);
     SDL_DestroyWindow(window);
     SDL_Quit();
}