SDL 2.0 sprite draws skewed (transformed) after OpenGL draws - c++

I'm using SDL to create a window and draw OpenGL in it and after drawing OpenGL I use SDL to show sprites (UI). It worked for me on Windows, OSX and NDK but it doesn't work for me on iOS. This is how I draw the sprite:
I create the window:
int flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;
gWindow = SDL_CreateWindow("example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 400, 800, flags);
I create the renderer:
gRenderer = SDL_CreateRenderer(gWindow, id, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
I load the texture:
SDL_Texture* newTexture = NULL;
SDL_Surface* loadedSurface = SDL_LoadBMP(path.c_str());
newTexture = SDL_CreateTextureFromSurface(gRenderer, loadedSurface);
SDL_FreeSurface(loadedSurface);
That's where I do OpenGL drawing. I load .3ds models, load textures, use blending etc.
And then
I draw the sprite:
dstRect.x = 0.0f;
dstRect.y = 0.0f;
dstRect.w = 128.0f;
dstRect.h = 64.0f;
SDL_RenderCopy(gRenderer, newTexture, NULL , &dstRect);
SDL_RenderPresent(gRenderer);
the result is strange. The sprite shows skewed instead of being drawn in a rectangle.
result http://vvcap.net/db/zHhZwoZa1ng7caeP1BG3.png
What could be the reason of the sprite being transformed like that ? How can I fix this ?
Has anybody had a similar problem ?

It almost looks to me as if the camera transform is rotated slightly around the y-axis and the perspective projection is making it looked skewed.
If the sprite is meant to be draw into the screen-space make sure that you have an orthographic projection enabled before the draw, with the width and height being the size of the physical screen (ie. 480x800).

I didn't find a solution but I just used SDL_RenderCopyEx instead of SDL_RenderCopy and it worked.

Related

SDL2 Draw scene to texture. SDL2 RenderTexture like SFML

I've been developing a 2D Engine using SFML + ImGui.
The editor is rendered using ImGui and the scene window is a sf::RenderTexture where I draw the GameObjects and then is converted to ImGui::Image to render it in the editor.
Now I need to create a 3D Engine during this year in my Bachelor Degree but using SDL2 + ImGui and I want to recreate what I did with the 2D Engine.
I've managed to render the editor like I did in the 2D Engine using this Example that comes with ImGui.
But I don't know how to create an equivalent of sf::RenderTexture in SDL2, so I can draw the 3D scene there and convert it to ImGui::Image to show it in the editor.
If you can provide code will be better. And if you want me to provide any specific code tell me.
Here's my solution.
SDL2window::SDL2window()
{
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow(...);
renderer = SDL_CreateRenderer(window,...);
texture = SDL_CreateTexture(renderer,..., width, height);
// create another texture for your imgui window here
ImTexture = SDL_CreateTexture(renderer,..., tex_width, tex_height);
...
}
void SDL2window::update(Uint32 *framebuffer)
{
...
// update your main window is necessary
SDL_RenderCopyEx(renderer, texture, NULL, NULL, 0, 0, SDL_FLIP_VERTICAL);
// be care of the size of framebuffer
SDL_UpdateTexture(ImTexture, NULL, framebuffer, tex_width * sizeof(Uint32));
ImGui::Render();
ImGui_ImplSDLRenderer_RenderDrawData(ImGui::GetDrawData());
SDL_RenderPresent(renderer);
}
void SDL2window::MyImgui()
{
...
ImGui::Begin("My Texture");
ImGui::Image(ImTexture, ImVec2(tex_width, tex_height));
ImGui::End();
}
Then run MyImgui() in your main loop, it will work.
ImTexture Window
P.S. I like your SFML 2D engine's UI, it looks great.
Think you're looking for something like this:
// Create a render texture
SDL_Texture *target = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height);
// Activate the render texture
SDL_SetRenderTarget(renderer, target);
// (Do your rendering here)
// Disable the render texture
SDL_SetRenderTarget(renderer, NULL);
// (Use the render texture)

SDL Rendering transparent rectangle using SDL_Rect

I could find nothing about rendering transparent rectangles in SDL2 documentaries. I want to render SDL_Rect as transparent texture/surface/anything used as "fog of war". Maybe you know any way to make surface or texture from SDL_Rect or just render it transparent. I don't want new texture in game files because player could just delete file and he would not have that fog of war.
Ok I managed to do it by myself and if anyone else will have same question thats the answer:
SDL_Surface* Fog = NULL;
SDL_Texture* gFog = NULL;
Fog = SDL_CreateRGBSurface(0, SCREEN_WIDTH, SCREEN_HEIGHT, 32, 0, 0, 0, 0);
if (Fog == NULL)std::cout << SDL_GetError();
gFog = SDL_CreateTextureFromSurface(gRenderer, Fog);
if (gFog == NULL)std::cout<<SDL_GetError();
SDL_SetTextureBlendMode(gFog, SDL_BLENDMODE_BLEND);
SDL_SetTextureAlphaMod(gFog, 150);

Set the pixel format AND create texture from surface in SDL

I am currently trying some things using pixel manipulation and I would like to set the pixel format of a SDL_Surface. The problem here is that I am loading up an image with the SDL_image.h. So I have to create a texture from a surface like this:
surface = IMG_Load(filePath);
texture = SDL_CreateTextureFromSurface(renderer, surface);
So I can't use the following function, which I would like to, or can I?:
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, 640, 480);
The thing is, that I want to set the SDL_PixelFormat to be able to mess around with the pixels. How can I both do this and create the texture based on a surface?
The SDL2 API provides the function SDL_ConvertSurface:
SDL_Surface* SDL_ConvertSurface(SDL_Surface* src,
const SDL_PixelFormat* fmt,
Uint32 flags)
You should be able to do
surface = IMG_Load(filePath);
// Call SDL_ConvertSurface to set the pixel format of the surface you have created.
texture = SDL_CreateTextureFromSurface(renderer, surface);
Reference: https://wiki.libsdl.org/SDL_ConvertSurface

SDL draws images blurred without scaling

I'm working on a project in C++ using SDL (Simple Directmedia Layer) but when I draw a SDL_Texture to the screen it's blurred eventhough it is not scaled.
How the image is loaded:
SDL_Surface* loadedSurface = IMG_Load("image.png");
SDL_Texture* gImage = SDL_CreateTextureFromSurface( gRenderer, loadedSurface);
How the image is drawn to the screen:
SDL_Rect renderQuad = { x, y, width, height };
SDL_RenderCopy(gRenderer, gImage , NULL, &renderQuad );
See image, left is in the program and right is the original:
Is there a parameter a forgot to set? And is it normal that SDL does this?
I'm using SDL 2.0 32-bit on a Windows 8.1 64-bit machine.
Ahead of your call to SDL_CreateTextureFromSurface try calling:
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0");
According to SDL Wiki this should affect how SDL_CreateTextureFromSurface calls interpolate the surface. "0" should result in nearest neighbour removing the blurring effect you are seeing.

SDL (Simple MediaDirect Layer) trying to scale my sprite (character)

I am just trying to scale (make bigger proportionally) my character based on windows weight and height. How can I do that?
I tried SDL_BlitScaled(newsurface, NULL, screen, NULL); but it did not work.
My code:
SDL_Surface* screen = SDL_GetWindowSurface(win);
SDL_Surface* mySprite = IMG_Load( SPRITE_PNG_PATH);
SDL_Rect rcSprite;
rcSprite.x = 250;
rcSprite.y = 100;
SDL_BlitSurface(mySprite, NULL, screen, &rcSprite);
The best way to accomplish this is to have a middle surface, whose width and height are your game's native resolution. You then render the entire frame to this surface, and render that surface to the window using the SDL_BlitScaled function.
For example, if you want your native resolution to be 600x400, you would create a 600x400 surface, blit your character and whatever else to that surface, and then finally scaled blit that surface to the window. If you resize your window to 1200x800, everything will look twice as big.
SDL_Surface* screen = SDL_GetWindowSurface(win);
// Create a surface with our native resolution
int NATIVE_WIDTH = 600;
int NATIVE_HEIGHT = 400;
SDL_Surface* frame = SDL_CreateRGBSurface(0, NATIVE_WIDTH, NATIVE_HEIGHT,
screen->format->BitsPerPixel, screen->format->Rmask,
screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
assert(frameSurface);
SDL_Surface* mySprite = IMG_Load( SPRITE_PNG_PATH);
SDL_Rect rcSprite;
rcSprite.x = 250;
rcSprite.y = 100;
// Blit everything to the intermediate surface, instead of the screen.
SDL_BlitSurface(mySprite, NULL, frame, &rcSprite);
// Once we've drawn the entire frame, we blit the intermediate surface to
// the window, using BlitScaled to ensure it gets scaled to fit the window.
SDL_BlitScaled(frame, NULL, screen, NULL);