Why does sf::Shader cause segmentation fault.I am going to show the code and i am telling to those that look the code that i use an engine and it works perfectly.So it doesn't cause the crash except with sf::Shader.And the code stops when i load the shader.
main.cpp
#include <iostream>
#include "CoreEngine.h"
#include "maingame.h"
int main()
{
//CoreEngine e(new MainGame(new Vector2i(800, 600), "Mama"));
//e.start();
Window::createWindow(800, 600, "Mama");
Window::clearColor(124, 32, 125);
bool running = true;
while(running){
if(Window::isWindowClosed())
running = false;
sf::RectangleShape shape(sf::Vector2f(20, 20));
shape.setPosition(10, 10);
sf::Shader shader;
if(!shader.loadFromFile("fragment.fs", sf::Shader::Fragment))
std::cout << "dfsfsdf";
Window::clear();
Window::getDrawer()->draw(shape, &shader);
Window::render();
}
}
Here is a compiled version of the code.
#include <iostream>
#include <SFML/Graphics.hpp>
int main()
{
//CoreEngine e(new MainGame(new Vector2i(800, 600), "Mama"));
//e.start();
sf::RenderWindow window(sf::VideoMode(800, 600), "Msadama");
sf::Shader shader;
if(!shader.loadFromFile("fragment.fs", sf::Shader::Fragment)){
std::cerr << "Shader failed to load" << std::endl;
return 0;
}
sf::RectangleShape shape(sf::Vector2f(20, 20));
shape.setPosition(10, 10);
while(window.isOpen()){
sf::Event event;
while(window.pollEvent(event)){
if(event.type == sf::Event::Closed)
window.close();
}
window.clear();
window.draw(shape);
window.display();
}
}
Your call to sf::Shader::loadFromFile is failing, which triggers your if statement because you are checking for the wrong condition. What you really want is:
sf::Shader shader;
if(!shader.loadFromFile("fragment.fs", sf::Shader::Fragment))
std::cerr << "Shader failed to load" << std::endl;
return 0;
}
std::cout << "dfsfsdf";
Window::clear();
Window::getDrawer()->draw(shape, &shader);
Window::render();
Regardless, you shouldn't be loading your shader from a file every frame. Do it once, check the error, then enter the main loop. Something like this (untested):
int main()
{
Window::createWindow(800, 600, "Mama");
Window::clearColor(124, 32, 125);
sf::Shader shader;
if(!shader.loadFromFile("fragment.fs", sf::Shader::Fragment))
{
std::cerr << "Failed to load shader" << std::endl;
return 0;
}
bool running = true;
while(running){
if(Window::isWindowClosed())
running = false;
sf::RectangleShape shape(sf::Vector2f(20, 20));
shape.setPosition(10, 10);
Window::clear();
Window::getDrawer()->draw(shape, &shader);
Window::render();
}
}
Related
I have a C++ project where I'm initially trying to display a PNG image to the screen.
This is my code.
RenderWindow.hpp
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
class RenderWindow
{
public:
RenderWindow(const char *p_title, int p_width, int p_height);
void render();
void cleanUp();
private:
SDL_Window *window;
SDL_Renderer *renderer;
SDL_Surface *image = IMG_Load("~/SDL2_Game/images/Green_Tile.png");
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, image);
};
RenderWindow.cpp
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <iostream>
#include "RenderWindow.hpp"
RenderWindow::RenderWindow(const char* p_title, int p_w, int p_h):window(NULL), renderer(NULL)
{
window = SDL_CreateWindow(p_title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, p_w, p_h, SDL_WINDOW_SHOWN);
if (window == NULL) std::cout << "Window failed to init: " << SDL_GetError() << std::endl;
renderer = SDL_CreateRenderer(window,-1,SDL_RENDERER_ACCELERATED);
}
void RenderWindow::render(){
SDL_RenderClear(renderer);
//SDL_Rect dstrect = { 5, 5, 320, 240 };
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
void RenderWindow::cleanUp(){
SDL_DestroyTexture(texture);
SDL_FreeSurface(image);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
}
main.cpp
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <iostream>
#include "RenderWindow.hpp"
int main(int argc, char** argv){
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
std::cout << "Problem with initialization. " << SDL_GetError() << std::endl;
}
else {
std::cout << "Initialization success!" <<std::endl;
}
if (!IMG_Init(IMG_INIT_PNG)){
std::cout << "Problem with Image initialization " <<SDL_GetError() << std::endl;
}
RenderWindow win("RPG_Game_v_1.0", 800, 600);
win.render();
bool gameRunning = true;
SDL_Event event;
while(gameRunning){
while(SDL_PollEvent(&event)){
if (event.type == SDL_QUIT) gameRunning = false;
}
}
win.cleanUp();
IMG_Quit();
SDL_Quit();
return 0;
}
I'm on a Linux machine.
I compile this with
g++ -g -o game ./*.cpp -lSDL2main -lSDL2 -lSDL2_image
Only a window is displaying. There is no image. I've tried refactoring my code with SDL_BlitSurface() and it does indeed display the PNG image. But why is this code not working? is it due to the fact that I'm using SDL_Texture* and my current system does not have a discrete graphics card?
I think that the call to SDL_CreateTextureFromSurface fails because it is called before SDL_CreateWindow and SDL_CreateRenderer, thereby initializing texture to NULL.
Please move the initizalization of texture (and image) to after window and renderer are initialized.
To further help with such issues, please check if the result of SDL functions != NULL and print SDL_GetError() to get more information about what went wrong.
I want to create a little program, which should draw some Math Functions.
At first a just wrote the code, that should create a little Window, that should just be visisble until I hit the X at the window.
#include <iostream>
#include <SDL2/SDL.h>
SDL_Window* window;
SDL_Renderer* renderer;
bool running = true;
bool init() {
if(SDL_Init(SDL_INIT_EVERYTHING) < 0) return false;
window = SDL_CreateWindow("Visual Functions", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 100, 200, SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if(window == NULL) return false;
if(renderer == NULL) return false;
std::cout << "App and SDL init success" << std::endl;
return true;
}
void onEvent(SDL_Event* event) {
switch (event->type)
{
case SDL_QUIT:
running = false;
break;
default:
break;
}
}
void loop() {
SDL_Event* event;
while(SDL_PollEvent(event)) onEvent(event);
}
void cleanUp() {
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}
int main(int, char**) {
if(!init()) {
std::cout << "SDL or/and App init failed" << std::endl;
exit(-1);
}
while(running) loop();
cleanUp();
}
But the window pops so fast up and again down, that I couldn't even see it and in the command is at first App and SDL init success but then there stands Segmentation fault.
In a other code, which has the same Initialization and Loop code runs very well and everything is displayed displayed normally (at least for the SDL part).
I found out with some debug messages, that the loop comes not to the Event Function, but also not to the end of the Loop Function, so the problem is SDL_PollEvent(event), but what is the prolem and how to I fix it ?
You never create the SDL_Event struct that you are using:
void loop() {
SDL_Event* event;
while(SDL_PollEvent(event)) onEvent(event);
}
should be this
void loop() {
SDL_Event event;
while(SDL_PollEvent(&event)) onEvent(&event);
}
My problem is that the function don't do what I want.
This "CreateWindow" function has the main loop. In the main loop I want a fixed background and, every time I press the H button, I want to draw a Card (sprite) on the background.
What's the problem here? My function draw the cards but when I press H the previous card is deleted and the next card is drawn.
This is something about the event I think, because every time an event happens (I move the mouse, I press an other key etc) the previous card is deleted...
I'm using sfml 2.0
Here is my implementation of the Graphic class
#include "Graphic.h"
#include "SFML/Graphics.hpp"
#include <iostream>
#include <string>
#include "Card.h"
#include <string>
#include <sstream>
Graphic::Graphic(int offset)
{
this->offset = offset;
}
Graphic::~Graphic()
{
//dtor
}
int Graphic::CreateWindow(sf::RenderWindow& window, Deck &deck0)
{
sf::Vector2i screenDimensions(800, 600);
//Dimensioni della window
window.create(sf::VideoMode(screenDimensions.x, screenDimensions.y), "BlackJack", sf::Style::Titlebar | sf::Style::Close);
int index = 0;
window.setKeyRepeatEnabled(false);
//settare il background
sf::Texture bTexture;
sf::Sprite bImage;
if(!bTexture.loadFromFile("Background.png"))
std::cout << "Error" << std::endl;
bImage.setTexture(bTexture);
bImage.setScale(1.0, (float)screenDimensions.y / bTexture.getSize().y);
//MAIN LOOP----------------------
while(window.isOpen())
{
sf::Event Event;
while(window.pollEvent(Event))
{
window.clear();
window.draw(bImage); // this is the function which draw the background
if (Event.type == sf::Event::Closed)
{
window.close();
}
if(Event.key.code == sf::Keyboard::H)
{
Card * y = deck0.dealFirst();
drawCard(window,y->graphNumber,y->getSeed(),offset);
offset = offset + 50;
}
window.display();
}
}
}
int Graphic::drawCard(sf::RenderWindow &window, int graphNumber, string seed, int offset)
{
std::ostringstream oss;
oss << graphNumber << seed << ".png";
std::string var = oss.str();
sf::Texture QHTexture;
sf::Sprite QHImage;
if(!QHTexture.loadFromFile(var))
std::cout<< "Error" <<std::endl;
QHImage.setTexture(QHTexture);
QHImage.setScale(0.5, 0.5);
QHImage.setPosition(offset + 100, 400);
window.draw(QHImage); //this is the function which draw the card's sprite
return 0;
}
Alright you shouldn't be drawing inside of your while(window.pollEvent()) loop, you should be drawing something like this:
while(window.isOpen())
{
sf::Event Event;
while(window.pollEvent(Event))
{
if (Event.type == sf::Event::Closed)
{
window.close();
}
if(Event.key.code == sf::Keyboard::H)
{
Card * y = deck0.dealFirst();
drawCard(window,y->graphNumber,y->getSeed(),offset);
offset = offset + 50;
}
}
window.clear();
window.draw(bImage); // this is the function which draw the background
window.display();
}
The way you were drawing your draw call will only happen if there is an SFML event, and will only ever clear if there is an sfml event(Which is ok if you dont want it to constantly render every frame... and aren't planning any kind of animations...).
So when you hit H an sfml event was being triggers that called your draw card function, however since your card is a local variable to the function you wrote, at the end of the function it is cleared out. You need to store your cards somewhere, such as a vector or list of sf::Sprite. So an example would be:
#include "Graphic.h"
#include "SFML/Graphics.hpp"
#include <iostream>
#include <string>
#include "Card.h"
#include <string>
#include <sstream>
Graphic::Graphic(int offset)
{
this->offset = offset;
}
Graphic::~Graphic()
{
//dtor
}
int Graphic::CreateWindow(sf::RenderWindow& window, Deck &deck0)
{
sf::Vector2i screenDimensions(800, 600);
//Dimensioni della window
window.create(sf::VideoMode(screenDimensions.x, screenDimensions.y), "BlackJack", sf::Style::Titlebar | sf::Style::Close);
int index = 0;
window.setKeyRepeatEnabled(false);
//settare il background
sf::Texture bTexture;
sf::Sprite bImage;
if(!bTexture.loadFromFile("Background.png"))
std::cout << "Error" << std::endl;
bImage.setTexture(bTexture);
bImage.setScale(1.0, (float)screenDimensions.y / bTexture.getSize().y);
//MAIN LOOP----------------------
while(window.isOpen())
{
sf::Event Event;
while(window.pollEvent(Event))
{
if (Event.type == sf::Event::Closed)
{
window.close();
}
if(Event.key.code == sf::Keyboard::H)
{
Card * y = deck0.dealFirst();
drawCard(window,y->graphNumber,y->getSeed(),offset);
offset = offset + 50;
}
}
window.clear();
window.draw(bImage); // this is the function which draw the background
for(int i = 0; i < cardList.size(); ++i)
{
window.draw(cardList[i]);
}
window.display();
}
}
int Graphic::drawCard(sf::RenderWindow &window, int graphNumber, string seed, int offset)
{
std::ostringstream oss;
oss << graphNumber << seed << ".png";
std::string var = oss.str();
sf::Texture QHTexture;
sf::Sprite QHImage;
if(!QHTexture.loadFromFile(var))
std::cout<< "Error" <<std::endl;
QHImage.setTexture(QHTexture);
QHImage.setScale(0.5, 0.5);
QHImage.setPosition(offset + 100, 400);
cardList.push_back(QHImage); //this adds the sprite to our list
return 0;
}
I was following the SDL Game development book and I cant even get the first file to work right. Upon the application starting it renders the window and then after a few seconds Linux says the game is not responding and ask me to force quit. This repeats every few seconds if I click wait. One thing I have noticed is that SDL_PollEvent never returns true.I am not sure why things are not working. Here is my code.
Main.cpp
#ifdef __cplusplus
#include <cstdlib>
#else
#include <stdlib.h>
#endif
#include "Game.h"
// our Game object
Game* g_game = 0;
int main(int argc, char* argv[]) {
g_game = new Game();
g_game->init("Chapter 1", 100, 100, 640, 480, 0);
while(g_game->running()) {
g_game->handleEvents();
//g_game->update();
g_game->render();
}
g_game->clean();
return 0;
}
Game.h
#ifndef __Game__
#define __Game__
#if !WINDOWS
#include <SDL2/SDL.h>
#else
#include <SDL.h>
#endif
class Game {
public:
Game() {}
~Game() {}
// simply set the running variable to true
bool init(const char* title, int xpos, int ypos, int width, int
height, bool fullscreen);
void render();
void update();
void handleEvents();
void clean();
// a function to access the private running variable
bool running() {
return m_bRunning;
}
private:
SDL_Window* m_pWindow;
SDL_Renderer* m_pRenderer;
bool m_bRunning;
};
#endif /* defined(__Game__) */
Game.cpp
#include "Game.h"
#include <iostream>
bool Game::init(const char* title, int xpos, int ypos, int width,
int height, bool fullscreen) {
// attempt to initialize SDL
if(SDL_Init(SDL_INIT_EVERYTHING) == 0) {
std::cout << "SDL init success\n";
// init the window
int flags = 0;
if(fullscreen) {
flags = SDL_WINDOW_FULLSCREEN;
}
m_pWindow = SDL_CreateWindow(title, xpos, ypos,
width, height, flags);
if(m_pWindow != 0) { // window init success
std::cout << "window creation success\n";
m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);
if(m_pRenderer != 0) { // renderer init success
std::cout << "renderer creation success\n";
SDL_SetRenderDrawColor(m_pRenderer,
255,0,255,255);
} else {
std::cout << "renderer init fail\n";
return false; // renderer init fail
}
} else {
std::cout << "window init fail\n";
return false; // window init fail
}
} else {
std::cout << "SDL init fail\n";
return false; // SDL init fail
}
std::cout << "init success\n";
m_bRunning = true; // everything inited successfully, start the main loop
return true;
}
void Game::render() {
SDL_RenderClear(m_pRenderer); // clear the renderer to the draw color
SDL_RenderPresent(m_pRenderer); // draw to the screen
}
void Game::clean() {
std::cout << "cleaning game\n";
SDL_DestroyWindow(m_pWindow);
SDL_DestroyRenderer(m_pRenderer);
SDL_Quit();
}
void Game::handleEvents() {
SDL_Event event;
while(SDL_PollEvent(&event)) {
std::cout << "Checking Events";
switch(event.type) {
case SDL_QUIT:
std::cout << "Quiting";
m_bRunning = false;
break;
default:
break;
}
}
}
Edit:
so I made a minamal version of the code and now i get a new error. The error says "Segmentation Fault (core dumped)". Based on running it to a specific line in debug the error seems to appear at the line that says "SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, bmp);" I am not sure what the error is though
Here is the minial code:
#ifdef __cplusplus
#include <cstdlib>
#else
#include <stdlib.h>
#endif
#include <iostream>
#include <SDL2/SDL.h>
int main(int argc, char** argv) {
if(SDL_Init(SDL_INIT_EVERYTHING) != 0) {
std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
return 1;
}
SDL_Window *win = SDL_CreateWindow("Hello World!", 100, 100, 640, 480, SDL_WINDOW_SHOWN);
if(win == NULL) {
std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if(ren == NULL) {
SDL_DestroyWindow(win);
std::cout << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
std::string imagePath = "cb.bmp";
SDL_Surface *bmp = SDL_LoadBMP(imagePath.c_str());
if(bmp == NULL) {
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
std::cout << "SDL_LoadBMP Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, bmp);
if(tex == NULL) {
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
std::cout << "SDL_CreateTextureFromSurface Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
SDL_FreeSurface(bmp);
SDL_Event e;
bool quit = false;
while(!quit) {
while(SDL_PollEvent(&e)) {
//If user closes the window
if(e.type == SDL_QUIT) {
quit = true;
}
//If user presses any key
if(e.type == SDL_KEYDOWN) {
quit = true;
}
//If user clicks the mouse
if(e.type == SDL_MOUSEBUTTONDOWN) {
quit = true;
}
}
SDL_RenderClear(ren);
SDL_RenderPresent(ren);
}
SDL_DestroyTexture(tex);
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}
I have compiled and run your minimal code successfully under Linux with SDL 2.0.4. I used a simple image as "cb.bmp".
Try the following :
compile like this : g++ -Wall -ggdb $(sdl2-config --cflags) -o program main.cpp -lSDL2
gdb ./program, then type 'run'
when it crashes, type 'bt' (for backtrace)
copy the output here
My guess is : either the "bmp" file format is not supported or the rendering driver is not supported. try to use :
SDL_CreateRenderer(win, -1, 0);
Visual Studio Express 2012, CTP1 c++ compiler
The following code works. It loads an image and displays it on the window until you close it.
#include <memory>
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(800,600), "hello");
auto Load = []() -> std::unique_ptr<sf::Texture> {
std::unique_ptr<sf::Texture> tex_ptr(new sf::Texture);
tex_ptr->loadFromFile("hello.png");
return tex_ptr;
};
auto tex_ptr = Load();
sf::Sprite spr(*tex_ptr);
while (window.isOpen())
{
sf::Event ev;
while (window.pollEvent(ev))
{
if (ev.type == sf::Event::Closed)
window.close();
}
window.clear();
window.draw(spr);
window.display();
}
}
In the following code, I'm trying to load the image asyncronously using std::async. It prints "load success", which indicates that the load succeeded in the lambda. Then, outside, after I've retrieved the texture from the future, I check other properties of the texture. The size prints out correctly. However, no image shows up. I just get a black window, which closes on command.
#include <future>
#include <memory>
#include <iostream>
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(800,600), "hello");
auto Load = []() -> std::unique_ptr<sf::Texture> {
std::unique_ptr<sf::Texture> tex_ptr(new sf::Texture);
if (tex_ptr->loadFromFile("hello.png"))
std::cout << "load success\n";
else
std::cout << "load failure\n";
return tex_ptr;
};
auto tex_ptr_future = std::async(std::launch::async, Load);
auto tex_ptr = tex_ptr_future.get();
sf::Sprite spr(*tex_ptr);
// Oddly, this prints out exactly what I expect
auto size = tex_ptr->getSize();
std::cout << size.x << 'x' << size.y << '\n';
while (window.isOpen())
{
sf::Event ev;
while (window.pollEvent(ev))
{
if (ev.type == sf::Event::Closed)
window.close();
}
window.clear();
window.draw(spr); // nothin'
window.display();
}
}
Does anybody see anything I'm doing wrong?