How to turn on antialiasing in SDL2, when using SDL_RenderCopyEx?
I find some articles that suggest to use:
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 2);
and
glEnable(GL_MULTISAMPLE);
But this makes no effect. Any ideas?
int Buffers, Samples;
SDL_GL_GetAttribute( SDL_GL_MULTISAMPLEBUFFERS, &Buffers );
SDL_GL_GetAttribute( SDL_GL_MULTISAMPLESAMPLES, &Samples );
cout << "buf = " << Buffers << ", samples = " << Samples;
returns
buf = -858993460, samples = -858993460.
EDIT: CODE:
#include <windows.h>
#include <iostream>
#include <SDL2/include/SDL.h>
#include <SDL2/include/SDL_image.h>
using namespace std;
int main( int argc, char * args[] )
{
// Inicjacja SDL'a
SDL_Init(SDL_INIT_EVERYTHING);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 8);
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
// Tworzenie okna
SDL_Window *win = nullptr;
win = SDL_CreateWindow("abc", 100, 100, 800, 600, SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
if (win == nullptr)
{
std::cout << SDL_GetError() << std::endl;
system("pause");
return 1;
}
int Buffers, Samples;
SDL_GL_GetAttribute( SDL_GL_MULTISAMPLEBUFFERS, &Buffers );
SDL_GL_GetAttribute( SDL_GL_MULTISAMPLESAMPLES, &Samples );
cout << "buf = " << Buffers << ", samples = " << Samples << ".";
// Create Renderer
SDL_Renderer *ren = nullptr;
ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (ren == nullptr)
{
std::cout << SDL_GetError() << std::endl;
return 1;
}
// Create texture
SDL_Texture *tex = nullptr;
tex = IMG_LoadTexture(ren, "circle.png");
SDL_SetTextureAlphaMod(tex, 100);
SDL_Rect s,d;
SDL_Point c;
s.x = s.y = 0;
s.w = s.h = 110;
d.x = 320;
d.y = 240;
d.w = d.h = 110;
c.x = c.y = 55;
// Event Queue
SDL_Event e;
bool quit = false;
int angle = 0;
while(!quit)
{
while (SDL_PollEvent(&e)){
//If user closes he window
if (e.type == SDL_KEYDOWN)
quit = true;
}
angle += 2;
float a = (angle/255.0)/M_PI*180.0;
// Render
SDL_RenderClear(ren);
SDL_RenderCopyEx(ren, tex, &s, &d, a, &c, SDL_FLIP_NONE);
SDL_RenderPresent(ren);
}
// Release
SDL_DestroyTexture(tex);
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
// Quit
SDL_Quit();
return 0;
}
Do not worry about style or errors related to memory deallocation, etc. It was a quick sketch to test the possibility SDL'a
If you're looking for an answer that doesn't require opengl use, then this may be of use:
SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "1" );
https://wiki.libsdl.org/SDL_HINT_RENDER_SCALE_QUALITY
As far as I can tell by trying it out, the values are not set until the context is created, so if you run your SDL_GL_GetAttribute lines before creating the window you will get un-initialised values back as you are doing at present.
So to get correct values use the SDL_GL_GetAttribute call after creating a context and it should work fine.
Let me know how you get on, and if you need any more help/information I will help as I can.
Addendum:
You look like you have created the window before setting its properties, I have pasted some modified code, which should run fine (apologies, I can't test it until I get access to my home PC).
Rearranged code:
#include <windows.h>
#include <iostream>
#include <SDL2/include/SDL.h>
#include <SDL2/include/SDL_image.h>
#include <gl/include/glew.h>
using namespace std;
void myInit()
{
// SDL Init
SDL_Init(SDL_INIT_EVERYTHING);
// Settings
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 32);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 2);
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
glEnable(GL_MULTISAMPLE);
}
int main( int argc, char * args[] )
{
myInit();
// Window Create
SDL_Window *win = nullptr;
win = SDL_CreateWindow("abc", 100, 100, 800, 600, SDL_WINDOW_SHOWN);
if(win == nullptr) return 1;
// Create Renderer
SDL_Renderer *ren = nullptr;
ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (ren == nullptr) return 1;
int Buffers, Samples;
SDL_GL_GetAttribute( SDL_GL_MULTISAMPLEBUFFERS, &Buffers );
SDL_GL_GetAttribute( SDL_GL_MULTISAMPLESAMPLES, &Samples );
cout << "buf = " << Buffers << ", samples = " << Samples << ".";
// Create texture
SDL_Texture *tex = nullptr;
tex = IMG_LoadTexture(ren, "circle.png");
SDL_SetTextureAlphaMod(tex, 100);
SDL_SetTextureColorMod(tex, 255,0,0);
SDL_Rect s,d;
SDL_Point c;
s.x = s.y = 0;
s.w = s.h = 110;
d.x = 320;
d.y = 240;
d.w = d.h = 220;
c.x = c.y = 110;
// Event Queue
SDL_Event e;
bool quit = false;
int angle = 45.0*M_PI/180;
while(!quit)
{
while (SDL_PollEvent(&e)){
//If user closes the window
if (e.type == SDL_QUIT)
quit = true;
}
// Render
SDL_RenderClear(ren);
SDL_RenderCopyEx(ren, tex, &s, &d, angle, &c, SDL_FLIP_NONE);
SDL_RenderPresent(ren);
}
// Release
SDL_DestroyTexture(tex);
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
// Quit
SDL_Quit();
return 0;
}
Related
#include <cstdlib>
#include <stdlib.h>
#include <iostream>
#include <SDL2/SDL.h>
int main ( int argc, char** argv )
{
const int height = 700;
const int width = 800;
if (SDL_Init(SDL_INIT_EVERYTHING) < 0){
std::cout << "SDL Failed to initalize" << std::endl;
return 1;
}
SDL_Window *window = SDL_CreateWindow("Particle Fire Explosion", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_SHOWN);
if (window == NULL){
SDL_Quit();
return 1;
}
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC);
SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC, width, height);
if(renderer == NULL){
std::cout << "COULD NOT CREATE RENDERER" << std::endl;
SDL_DestroyTexture(texture);
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
if(texture == NULL){
std::cout << "COULD NOT CREATE TEXTURE" << std::endl;
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
Uint32 *buffer = new Uint32(width * height);
Uint32 *memsett = new Uint32(width * height * sizeof(Uint32));
memset(buffer, 0xFF, width*height*sizeof(Uint32));
SDL_UpdateTexture(texture, NULL, buffer, width*sizeof(Uint32));
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer,texture, NULL, NULL);
SDL_RenderPresent(renderer);
bool quit = false;
SDL_Event event;
while (quit == false){
while(SDL_PollEvent(&event)){
if(event.type == SDL_QUIT){
quit = true;
}
}
}
SDL_DestroyRenderer(renderer);
SDL_DestroyTexture(texture);
delete [] buffer;
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
this Is my code, Im trying to make an all white window in SDL an dim trying to use memset to so this but it is not working. The bug says: Segmentation fault core dumped. It goes away when I remove the memset function, so I know that the memory meaning that memset is using is using memory not free so how do I change this?
Uin32 *buffer = new Uint32(width * height) allocates a single Uint32 with the value width * height, not an array of width * height Uint32s. Your call to memset then writes beyond the end of that single Uin32 and off into unowned memory.
You want [] instead of ():
Uint32* buffer = new Uint32[width * height];
i'm trying to create a manual color key with pixel manipulation in SDL2, but when i execute the program, the color key doesn't work, these pixels become white, but not transparent.
I tried to Lock the surface and set the surface blendmode, but doesn't work too.
Code:
// IO includes
#include <iostream>
// String includes
#include <string>
// SDL includes
#include <SDL.h>
#include <SDL_image.h>
// Screen constants
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
using namespace std;
// Window variables
SDL_Window *window = NULL;
SDL_Surface *windowSurface = NULL;
// Image surfaces
SDL_Surface *background = NULL;
SDL_Surface *image = NULL;
// Functions
bool initializeSDL();
SDL_Surface *loadSurfaceFromFile(string path);
void SetColorKey(SDL_Surface *surface, Uint32 color);
bool LoadFiles();
void FreeMemory();
// SDL_main
int main(int argc, char* argv[]){
// Try to initialize and load files
if(initializeSDL() == false){
FreeMemory();
return -1;
}
if(LoadFiles() == false){
FreeMemory();
return -1;
}
// Blit images
SDL_BlitSurface(background, NULL, windowSurface, NULL);
SDL_BlitSurface(image, NULL, windowSurface, new SDL_Rect(70, 277, image->w, image->h));
// Update screen
SDL_UpdateWindowSurface(window);
// Loop
SDL_Event ev;
while(true){
if(SDL_PollEvent(&ev) && ev.type == SDL_QUIT) break;
}
return 0;
}
bool initializeSDL(){
// Try to initialize the video
if( SDL_Init(SDL_INIT_VIDEO) < 0 ){
// Print error
cout << "Error to initialize the video: " << SDL_GetError() << endl;
return false;
}
// Try to create the window
window = SDL_CreateWindow("Surface", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if(window == NULL){
// Print error
cout << "Error to create the window: " << SDL_GetError() << endl;
return false;
}
// Try to initialize PNG format
int imgFlags = IMG_INIT_PNG;
if(! (IMG_Init(imgFlags) &imgFlags) ) return false;
// Get the window surface
windowSurface = SDL_GetWindowSurface(window);
// If everything is fine, return true
return true;
}
SDL_Surface* loadSurfaceFromFile(string path){
// Create a temporary surface
SDL_Surface *tmpSurface = NULL;
// Create an optimized surface
SDL_Surface *optimizedSurface = NULL;
// Try to load the tmpSurface
tmpSurface = IMG_Load(path.c_str());
if(tmpSurface == NULL){
// Print error
cout << "Error to load the image: " << SDL_GetError() << endl;
return NULL;
}
// Try to optimize the surface
optimizedSurface = SDL_ConvertSurface(tmpSurface, windowSurface->format, NULL);
SDL_FreeSurface(tmpSurface); // Free tmpSurface memory
delete tmpSurface; // Delete the tmpSurface
if(optimizedSurface == NULL){
// Print error
cout << "Error to optimize the image: " << SDL_GetError() << endl;
}
return optimizedSurface;
}
void SetColorKey(SDL_Surface *surface, Uint32 color){
Uint32 *pixels = (Uint32*)surface->pixels;
int pixelCount = (surface->pitch/4) * surface->h;
Uint32 transparent = SDL_MapRGBA(image->format, 255, 255, 255, 0);
for(int i=0;i<pixelCount;i++){
if(pixels[i] == color){
pixels[i] = transparent;
}
}
}
bool LoadFiles(){
// Try to load the background
background = loadSurfaceFromFile("background.bmp");
if(background == NULL) return false;
// Try to load the image
image = loadSurfaceFromFile("image.png");
if(image == NULL) return false;
// Set manual color key to image
SetColorKey(image, SDL_MapRGB(image->format, 0, 255, 255));
return true;
}
void FreeMemory(){
SDL_FreeSurface(background);
SDL_FreeSurface(image);
SDL_DestroyWindow(window);
IMG_Quit();
SDL_Quit();
}
I'm very new to C++ and SDL and I am trying to create a thread that constantly updates the screen but the I keep getting the following errors:
'std::invoke no matching overloaded function found'
and
'Failed to specialize function template 'unknown-type std::invoke(Callable &&,_Types&&...)''
main.cpp
int main(int argc, char **argv) {
using namespace std::placeholders;
bool gameover = false;
int test;
std::string filepath = getResourcePath("Lesson1");
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) { // Intializes SDL functionality
std::cout << "Could not start SDL" << std::endl;
std::cin >> test;
return 1;
}
else {
std::cout << "SDL started successfully!" << std::endl;
}
viewWindow window; // Class representing the window in which the program is run.
SDL_Renderer *render = window.render(); // Pointer to the renderer used to draw images to the window.
if (render == nullptr) {
std::cout << "There was an error creating the renderer" << std::endl << SDL_GetError() << std::endl;
std::cin >> test;
return 1;
}
SDL_Surface *emptySurface = window.blankSurface(); // Temp surface to draw background to
if (emptySurface == nullptr) {
std::cout << "Unable to create a blank surface " << std::endl << SDL_GetError() << std::endl;;
std::cin >> test;
return 1;
}
surfaces background;
background.filename = "grass.bmp";
SDL_Surface *backgroundSurface = background.loadSurface(filepath);
if (backgroundSurface == nullptr) {
std::cout << "Unable to create background surface" << std::endl << SDL_GetError() << std::endl;
std::cin >> test;
return 1;
}
SDL_Rect backgroundRect;
SDL_Texture *backTexture = background.blitBack(render, backgroundRect, backgroundSurface, emptySurface);
player player;
SDL_Rect playerRect;
playerRect.x = 320;
playerRect.y = 240;
playerRect.h = 16;
playerRect.w = 16;
SDL_Texture *playerTexture = player.createPlayerTexture(render, filepath);
if (playerTexture == nullptr) {
std::cout << "Could not load player texture" << std::endl << SDL_GetError() << std::endl;
std::cin >> test;
return 1;
}
while (!gameover) {
std::thread t((&viewWindow::refreshWindow, render, playerRect, backTexture, playerTexture));
playerRect.x = player.moveX(playerRect);
playerRect.y = player.moveY(playerRect);
t.join();
}
return 0;
}
viewWindow.h
#pragma once
#ifndef VIEWINDOW_H
#define VIEWWINDOW_H
#include "SDL.h"
class viewWindow // Class representing the window.
{
private:
char winName[45] = "Game Test";
int winWidth = 640;
int winHeight = 480;
int xPos = 960;
int yPos = 540;
public:
SDL_Window *view(); // Intializing funtions for creating the window and renderer.
SDL_Renderer *render();
SDL_Surface *blankSurface();
void refreshWindow(SDL_Renderer *renderer, SDL_Rect &playerRect, SDL_Texture *backtex, SDL_Texture *playertex);
};
#endif
viewWindow.cpp
#include "viewWindow.h"
#include <string>
#include "SDL.h"
SDL_Window *viewWindow::view()
{
SDL_Window *createdwindow = SDL_CreateWindow(winName, xPos, yPos, winWidth, winHeight, SDL_WINDOW_SHOWN);
return createdwindow;
}
SDL_Renderer *viewWindow::render() {
SDL_Renderer *render = SDL_CreateRenderer(view(), -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
return render;
}
SDL_Surface *viewWindow::blankSurface() {
SDL_Surface *blacksurface = SDL_CreateRGBSurface(0, winWidth, winHeight, 32, 0, 0, 0, 0);
return blacksurface;
}
void viewWindow::refreshWindow(SDL_Renderer *renderer, SDL_Rect &playerRect, SDL_Texture *backtex, SDL_Texture *playertex) {
while (true) {
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, backtex, NULL, NULL);
SDL_RenderCopy(renderer, playertex, NULL, &playerRect);
SDL_RenderPresent(renderer);
}
}
Method refreshWindow is not static. std::invoke requires the object instance of viewWindow class to call this method. You should pass it as a second parameter into the thread constructor:
std::thread t(&viewWindow::refreshWindow, window, render, std::ref(playerRect), backTexture, playerTexture);
Instead of function pointer you could use lambda function:
std::thread t([&](viewWindow* view){ view->refreshWindow(render, playerRect, backTexture, playerTexture); }, &window);
I was watching this series = https://www.youtube.com/watch?v=2NVgHrOFneg
and for some reason for the guy in the video the code works but for me it compiles fine but doesn't load an image. I really don't know what to do.
#include "SDL.h"
#include <iostream>
#include "SDL_image.h"
SDL_Texture *LoadTexture(std::string filePath, SDL_Renderer *renderTarget) //texture optimization function
{
SDL_Texture *texture = nullptr;
SDL_Surface *surface = IMG_Load(filePath.c_str());
if (surface == NULL)
std::cout << "Error 1" << std::endl;
else
{
texture = SDL_CreateTextureFromSurface(renderTarget, surface);
if (texture == NULL)
std::cout << "Error 2" << std::endl;
}
SDL_FreeSurface(surface);
return texture;
}
int main(int, char *argv[])
{
const int FPS = 144;
int frameTime = 0;
SDL_Window *window = nullptr;
SDL_Texture *currentImage= nullptr;
SDL_Renderer *renderTarget = nullptr;
SDL_Rect playerRect;
int frameWidth, frameHeight;
int textureWidth, textureHeight;
SDL_Init(SDL_INIT_VIDEO );
int imgFlags = IMG_INIT_PNG | IMG_INIT_JPG;
if (!(IMG_Init(imgFlags) != imgFlags))
{
std::cout << "Error: " << IMG_GetError() << std::endl;
}
window = SDL_CreateWindow("SDL Pong", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1024, 720, SDL_WINDOW_SHOWN);
renderTarget = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
currentImage = LoadTexture("Untitled.jpg", renderTarget);
SDL_QueryTexture(currentImage, NULL, NULL, &textureWidth, &textureHeight);
SDL_SetRenderDrawColor(renderTarget, 0xFF, 0, 0, 0xFF);
frameWidth = textureWidth / 3;
frameHeight = textureHeight / 4;
playerRect.x = playerRect.y = 0;
playerRect.y = frameWidth;
playerRect.h = frameHeight;
bool isRunning = true; //game loop
SDL_Event ev;
while (isRunning)
{
while (SDL_PollEvent(&ev) != 0)
{
if (ev.type == SDL_QUIT)
isRunning = false;
}
frameTime++;
if (FPS / frameTime == 4)
{
frameTime = 0;
playerRect.x += frameWidth;
if (playerRect.x >= textureWidth)
playerRect.x =0;
}
SDL_RenderClear(renderTarget);
SDL_RenderCopy(renderTarget, currentImage, &playerRect, NULL);
SDL_RenderPresent(renderTarget);
}
SDL_DestroyWindow(window);
SDL_DestroyTexture(currentImage);
SDL_DestroyRenderer(renderTarget);
window = nullptr;
renderTarget = nullptr;
currentImage = nullptr;
SDL_Quit();
return 0;
}
This is the error message: http://imgur.com/LHMdt5F
IMG_Init returns bitfield of formats that was initialised. If resulting bitfield doesn't contain every format that was requested in flags, something gone wrong.
if (!(IMG_Init(imgFlags) != imgFlags)) checks if there is no error. Then you're trying to get error message, but there were no errors. Remove negation operator.
When you create the .exe and run it from an IDE it often stores the executable in a ../bin/.. directory. If Untitled.jpg is in the same directory as your source files, it will not find it.
SDL_GetBasePath(); will return the base path to your files. Check it out docs for it.
The string from SDL_GetBasePath() + "Untitled.jpg" will find and open the file.
PollEvent is bypassed if mouse isn't moving within window or any key is not pressed when supposed to run animation. Here's the code:
SDL_Init(SDL_INIT_EVERYTHING);
int imgFlags = IMG_INIT_PNG | IMG_INIT_JPG;
if (IMG_Init(imgFlags) != imgFlags)
{
std::cout << IMG_GetError() << std::endl;
}
window = SDL_CreateWindow("NRG", 200, 200, 800, 600, SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED| SDL_RENDERER_PRESENTVSYNC);
isRunning = true;
while (isRunning)
{
while (SDL_PollEvent(&ev))
{
heroImg = LoadTxt("image.png", renderer);
SDL_QueryTexture(heroImg, NULL, NULL, &textureWidth, &textureHeight);
frameWidth = textureWidth / 3;
frameHeight = textureHeight / 4;
heroRct.x = 0;
heroRct.y = 0;
heroRct.h = frameHeight;
heroRct.w = frameWidth;
frameTime++;
if (60 / frameTime == 4)
{
frameTime = 0;
heroRct.x += frameWidth;
if (heroRct.x >= textureWidth)
heroRct.x = 0;
}
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, heroImg, &heroRct, NULL);
SDL_RenderPresent(renderer);
}
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
window = NULL;
windowSurface = NULL;
renderer = NULL;
SDL_Quit();
Other stuff like SDL_Event ev; is included in .h file
For anybody with the same problem:
Put your render etc. outside of the while (SDL_PollEvent(&ev)) loop :)
Stupid mistake, pretty hard to solve for begginer :)