SDL layered rendering system - sdl

I would like help with building a layered rendering system in SDL2.
I have a first layer containing a map of Paris with its roads.
I need to draw a line between two points on this map - the problem occurs when the before state of this line does not disappear.
I need to draw this line over the map and keep this.
How do I make s a system to save the map state whithout any overlaid lines drawn, and such that frame by frame I can show the map with the new state of the line overlaid on top of this?

Solved, below an example !! Thank you all
SDL_Window *window;
SDL_Renderer *render;
SDL_Texture *map; //map texture (my layer)
window = SDL_CreateWindow("Test window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
render = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
map = SDL_CreateTexture(render, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 640, 480); //Creating a texture
/*Map is a red background stored in map texture*/
SDL_SetRenderDrawColor(render, 255, 0, 0, 255);
SDL_SetRenderTarget(render, map);
SDL_RenderClear(render);
SDL_SetRenderTarget(render, NULL);
/*Seting the line color*/
SDL_SetRenderDrawColor(render, 0, 255, 0, 255);
/*Coping the map texture to the render and drawing a green line on top of this*/
SDL_RenderCopy(render, map, NULL, NULL);
SDL_RenderDrawLine(render, 0, 0, 640, 480);
SDL_RenderPresent(render);
SDL_Delay(2000);
/*Another line*/
SDL_RenderCopy(render, map, NULL, NULL);
SDL_RenderDrawLine(render, 0, 480, 640, 0);
SDL_RenderPresent(render);
SDL_Delay(2000);
SDL_DestroyWindow(window);
SDL_DestroyRenderer(render);
SDL_Quit();

Related

X11 Window/GLXWindow attributes to GLFWwindow

Im created GLX window, that contains CWOverrideRedirect attribute, and destroyed input shape, so it looks like OpenGL overlay. Now I am wanted to draw a 2d text or use ImGUI. A lot of examples use GLFW library. So, the main problem is to make GLFWwindow transparency and without input shape.
int attr_mask =
CWOverrideRedirect| //borderless, always on top
CWColormap|
CWBorderPixel|
CWEventMask;
window_handle = XCreateWindow( Xdisplay,
Xroot,
x, y, width, height,
0,
visual->depth,
InputOutput,
visual->visual,
attr_mask, &attr);
..............
// Destroy input shape
XRectangle rect;
XserverRegion region = XFixesCreateRegion(Xdisplay, &rect, 1);
XFixesSetWindowShapeRegion(Xdisplay, window_handle, ShapeInput, 0, 0, region);
XFixesDestroyRegion(Xdisplay, region);
if ((del_atom = XInternAtom(Xdisplay, "WM_DELETE_WINDOW", 0)) != None) {
XSetWMProtocols(Xdisplay, window_handle, &del_atom, 1);
}
From ImGUI opengl3 example
GLFWwindow* window = glfwCreateWindow(1280, 720, "ImGui OpenGL3 example", NULL, NULL);
glfwMakeContextCurrent(window);
gl3wInit();

Window Changes Color Over Time In SDL2

I've created a window in SDL2 that opens in the color red. I need the window to change color after a few seconds and continue to do so as long as the window is open. So the window may open red, stay for five seconds then become green for five seconds then become blue for five seconds then loop back to red and begin the whole process again.
int WindowOpen() {
bool quit = false;
SDL_Window *window; // Declare a pointer
SDL_Init(SDL_INIT_VIDEO); // Initialize SDL2
// Create an application window with the following settings:
window = SDL_CreateWindow(
"My SDL2 window", // window title
SDL_WINDOWPOS_UNDEFINED, // initial x position
SDL_WINDOWPOS_UNDEFINED, // initial y position
640, // width, in pixels
480, // height, in pixels
SDL_WINDOW_OPENGL // flags - see below
);
SDL_Renderer *renderer = NULL;
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_Event* MainEvent = new SDL_Event();
SDL_RenderClear(renderer);
// Up until now everything was drawn behind the scenes.
// This will show the new, red contents of the window.
SDL_RenderPresent(renderer);
// Check that the window was successfully created
if (window == NULL) {
// In the case that the window could not be made...
printf("Could not create window: %s\n", SDL_GetError());
return 1;
}
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);//red. Was testing to see if window would open red and change to green then blue but this doesn't work.
//SDL_Delay(3000);
//SDL_SetRenderDrawColor(renderer, 300, 150, 0, 155);//green
//SDL_Delay(3000);
//SDL_SetRenderDrawColor(renderer, 129, 150, 500, 105);//blue
while (quit == false && MainEvent->type != SDL_QUIT) { //While quit is false, run window and renderer.
SDL_PollEvent(MainEvent);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
// The window is open: could enter program loop here (see SDL_PollEvent())
//SDL_Delay(3000); // Pause execution for 3000 milliseconds, for example
// Close and destroy the window
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
delete MainEvent;
// Clean up
SDL_Quit();
}
SDL_SetRenderDrawColor is just setting the colour the renderer would paint, if you asked it to. To fill the back buffer with that colour you should follow it up with SDL_RenderClear. With the back buffer filled, to then draw it on the screen you need to call SDL_RenderPresent.
while (quit == false && MainEvent->type != SDL_QUIT) { //While quit is false, run window and renderer.
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);//red. Was testing to see if window would open red and change to green then blue but this doesn't work.
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
SDL_Delay(3000);
SDL_SetRenderDrawColor(renderer, 300, 150, 0, 155);//green
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
SDL_Delay(3000);
SDL_SetRenderDrawColor(renderer, 129, 150, 500, 105);//blue
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
SDL_Delay(3000);
SDL_PollEvent(MainEvent);
}
Changing your main loop to something like that will do similar to what you want, but the delay is three seconds. Also, this way your main loop will take 9 seconds to execute, which means event handling for quit could take up to 9 seconds. This isn't very good, but fixing it is left as an exercise for the reader.

SDL Texture transparent background

This is probably rather simple problem, but after an hour of searching and trying I still didn't manage to solve it.
I have two png files. One is a background image and second is foreground. The foreground has an alpha channel. I want to display foreground on top of background.
I'm loading foreground using:
SDL_Surface *clip = SDL_CreateRGBSurface(0, SCREEN_WIDTH, SCREEN_HEIGHT, 32, 0, 0, 0, 0xff);
SDL_Rect rect = { x, 0, SCREEN_WIDTH, SCREEN_HEIGHT };
SDL_BlitSurface(map, &rect, clip, NULL);
*block = SDL_CreateTextureFromSurface(gRenderer, clip);
Where map is some SDL_Surface.
I'm loadin backgroun using:
SDL_Surface* loadedSurface = IMG_Load(path);
//Create texture from surface pixels
SDL_Texture* newTexture = SDL_CreateTextureFromSurface(gRenderer, loadedSurface);
SDL_FreeSurface(loadedSurface);
Then I trying to connect them:
SDL_RenderCopy(gRenderer, background, NULL, &cur);
SDL_RenderCopy(gRenderer, map, NULL, &cur);
But it results in foreground image with black background. What am i doing wrong?
You should add these 2 lines,
Uint32 colorkey = SDL_MapRGB(loadedSurface->format, 0, 0, 0);
SDL_SetColorKey(loadedSurface, SDL_TRUE, colorkey);
before this line in your code
SDL_Texture* newTexture = SDL_CreateTextureFromSurface(gRenderer, loadedSurface);

8 Bit Surfaces in SDL 2

Originally in SDL, the following code could be used to setup a surface:
SDL_Surface *screen = SDL_SetVideoMode(800, 600, 8, 0);
Now, in SDL2 the following code must be used:
SDL_Window *window = SDL_CreateWindow("Title", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, 0);
SDL_Surface *surface = SDL_GetWindowSurface(window);
My problem is that SDL_CreateWindow offers no way to set the bbp of the window or surface. It seems to default to 32 bit. I've tried using SDL_ConvertSurfaceFormat but surface->format->BitsPerPixel stays at 32.
How can I create a 8 bit surface in SDL 2? I realize I will need a color palette.
Use SDL_CreateRGBSurface where you can specify number of bits.
Example:
SDL_Window *sdlWindow;
SDL_Renderer *sdlRenderer;
SDL_CreateWindowAndRenderer(0, 0, SDL_WINDOW_FULLSCREEN_DESKTOP, &sdlWindow, &sdlRenderer);
SDL_Surface *screen = SDL_CreateRGBSurface(0, 640, 480, 32,
0x00FF0000,
0x0000FF00,
0x000000FF,
0xFF000000);
SDL_Texture *sdlTexture = SDL_CreateTexture(sdlRenderer,
SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING,
640, 480);
SDL_UpdateTexture(sdlTexture, NULL, screen->pixels, screen->pitch);
SDL_RenderClear(sdlRenderer);
SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL);
SDL_RenderPresent(sdlRenderer);

What exactly is a renderer in SDL2?

I dont exactly understand what renderer is. Can I have multiple renderers or is there always just one?
For example, how can I draw a rectangle with a certain color on a background with a different color using a renderer?
I believe the answer lies in the functions SDL_RenderDrawRect() and SDL_RenderFillRect(). Am I right?
I know how surfaces and bliting works but I dont know what exactly the renderer symbolizes.
If someone could show me how to draw a rectangle, I think i will understand how renderers work.
So far I have this:
#include <SDL.h>
int main(int argc, char* argv[]) {
//Initialization
SDL_Init(SDL_INIT_EVERYTHING);
//Window
SDL_Window *MainWindow = SDL_CreateWindow("My Game Window",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
640, 480,
SDL_WINDOW_SHOWN
);
//Renderer
SDL_Renderer *Background = SDL_CreateRenderer(MainWindow, -1, 0);
SDL_SetRenderDrawColor(Background, 255, 255, 255, 255);
SDL_RenderClear(Background);
SDL_Delay(3000);
//Clean up
SDL_DestroyWindow(MainWindow);
SDL_Quit();
return 0;
}
for the first part of your question see this SO question.
as to why your code doesnt do much:
you are correct that you need to use either SDL_RenderDrawRect(), or SDL_RenderFillRect().
SDL_RenderDrawRect will draw an unfilled rectangle. SDL_RenderFillRect will be filled (hopefully that is obvious).
With SDL_renderer you need to call SDL_RenderPresent to copy the "scene" to the screen.
...
//Renderer
SDL_Renderer* renderer = SDL_CreateRenderer(MainWindow, -1, 0);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderClear(renderer); // fill the scene with white
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); // the rect color (solid red)
SDL_Rect rect(0, 0, 100, 50); // the rectangle
SDL_RenderFillRect(renderer, &rect);
SDL_RenderPresent(renderer); // copy to screen
SDL_Delay(3000);
...