In this simple triangle drawing application made with opengl3.3 and sdl2, the cpu's usage shoots up to 50+% with vsync enabled. The vsync is enabled using SDL_GL_SetSwapInterval( 1 ). When i remove the vsync by setting the previous function to 0 and capped the fps to 60 manually in the main loop the cpu usage sits at around 5% average.
What is the problem here? Am i misunderstanding something fundamental here? below is my code. (The vsync function is in the initialize() loop provided below).
Main file:
unsigned int triangle_Gen()
{
float vertices[] = {
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f,
};
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), (void*)(3*sizeof(float)));
glEnableVertexAttribArray(1);
return VAO;
}
int main(int argc, char* args[])
{
float StartTicks = 0;
float EndTicks = 0;
float timeStep = 0;
int fps = 0;
float frameStartTime = 0;
float frameEndTime = 0;
float onesectime = 0;
bool enableEditor = false;
int editor_keyCount = 0;
if(!initialize())
{
std::cout<<"Failed to initiate instance!!!"<<std::endl;
}
else
{
std::cout << glGetString(GL_VERSION) <<std::endl;
int color_shaderProgram = Shaders("ShaderFiles/color_shader.vs","ShaderFiles/color_shader.fs");
unsigned int triangle = triangle_Gen();
glUseProgram(color_shaderProgram);
glBindVertexArray(triangle);
while(isRunning)
{
SDL_GetWindowSize(window, &SCREEN_WIDTH, &SCREEN_HEIGHT);
glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
if(!enableEditor)
{ SDL_SetRelativeMouseMode(SDL_TRUE); } //disable cursor
else
{ SDL_SetRelativeMouseMode(SDL_FALSE); } //enable cursor
Uint32 time = 0;
time = SDL_GetTicks() - StartTicks;
timeStep = time/1000.f;
StartTicks = SDL_GetTicks();
fps++; //fps counter
onesectime += timeStep; //1 sec counter
frameStartTime = SDL_GetTicks();
//=========================================input handle sector =========================================//
while (SDL_PollEvent(&e) != 0)
{
if (e.type == SDL_QUIT)
isRunning = false;
if( e.type == SDL_KEYDOWN && e.key.repeat == 0 )
{
switch(e.key.keysym.sym)
{
case SDLK_e: editor_keyCount++; break;
}
if(editor_keyCount == 1)
{ enableEditor = !enableEditor; }
}
if( e.type == SDL_KEYUP && e.key.repeat == 0 )
{
switch(e.key.keysym.sym)
{
case SDLK_e: editor_keyCount--; break;
}
}
}
//=========================================render sector=========================================//
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
//--------------------------------------fps stuff --------------------------------------------------------------//
frameEndTime = SDL_GetTicks();
/*if((frameEndTime - frameStartTime) < 16.67) //60fps manual cap
{
SDL_Delay(16.67-(frameEndTime-frameStartTime));
}*/
if(onesectime >= 1) //print fps
{
std::cout<<fps<<std::endl;
onesectime = 0;
fps = 0;
}
SDL_GL_SwapWindow( window );
}
}
close();
return 0;
}
initialize() function:
bool initialize()
{
Uint32 flags = SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS;
//initializing
if(SDL_Init(flags) < 0)
{
std::cout<<"SDL could not initialize! SDL Error: " << SDL_GetError() << std::endl;
isRunning = false;
}
else
{
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 3 );
flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;//SDL_WINDOW_INPUT_GRABBED;
window = SDL_CreateWindow("Test Application", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, flags);
if( window == NULL )
{
std::cout<<"Window could not be created! SDL Error:" << SDL_GetError() << std::endl;
isRunning = false;
}
else
{
openGL_Context = SDL_GL_CreateContext( window );
if(openGL_Context == NULL)
{
std::cout<<"OpenGL context could not be created! SDL Error: %s\n" << SDL_GetError() <<std::endl;
isRunning = false;
}
else
{
//enable(1)or disable(0) vsync
if(SDL_GL_SetSwapInterval( 1 ) < 0)
{
std::cout<<"Warning, vsync disabled!"<<std::endl;
}
glewExperimental = GL_TRUE;
if( glewInit() != GLEW_OK)
{
std::cout<<"Unable to initialize glew!"<<std::endl;
isRunning = false;
}
else
{
SDL_WarpMouseInWindow(window, (SCREEN_WIDTH/2), (SCREEN_HEIGHT/2));
}
}
}
}
return isRunning;
}
Related
I am currently following along on an openGL course and when organising my code into classes, I am getting an access violation error along with this on the console terminal.
SDL window creation failed! (I programmed it to output that when the window cannot be created)
Here's my code:
main.cpp
#include <stdio.h>
#include <string.h>
#include <cmath>
#include <vector>
#include <GL/glew.h>
#define SDL_MAIN_HANDLED
#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "Window.h"
#include "Mesh.h"
#include "Shader.h"
//Window dimensions
const GLint width = 800, height = 600;
const float toRadians = 3.14159265f / 180.0f;
Window mainWindow;
std::vector<Mesh*> meshList;
std::vector<Shader*> shaderList;
bool direction = true;
float triOffSet = 0.0f;
float triMaxOffSet = 0.7f;
float triIncrement = 0.010f;
float curAngle = 0.0f;
bool sizeDirection = true;
float curSize = 0.4f;
float maxSize = 0.8f;
float minSize = 0.1f;
//Vertex shader
static const char* vShader = "Shaders/shader.vert";
//Fragment shader
static const char* fShader = "Shaders/shader.frag";
void CreateObjects() {
unsigned int indices[] = {
0, 3, 1,
1, 3, 2,
2, 3, 0,
0, 1, 2
};
GLfloat vertices[] = {
-1.0f, -1.0f, 0.0f,
0.0f, -1.0f, 1.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f
};
Mesh* obj1 = new Mesh();
obj1->CreateMesh(vertices, indices, 12, 12);
meshList.push_back(obj1);
Mesh* obj2 = new Mesh();
obj2->CreateMesh(vertices, indices, 12, 12);
meshList.push_back(obj2);
Mesh* obj3 = new Mesh();
obj3->CreateMesh(vertices, indices, 12, 12);
meshList.push_back(obj3);
}
void CreateShaders() {
Shader *shader1 = new Shader();
shader1->CreateFromFiles(vShader, fShader);
shaderList.push_back(shader1);
}
int main() {
mainWindow = Window(800, 600);
mainWindow.Initialise();
CreateObjects();
CreateShaders();
GLuint uniformProjection = 0, uniformModel = 0;
glm::mat4 projection = glm::perspective(45.0f, (GLfloat)mainWindow.getBufferWidth() / mainWindow.getBufferHeight(), 0.1f, 100.0f);
SDL_Event windowEvent;
while (true) {
if (SDL_PollEvent(&windowEvent)) {
if (windowEvent.type == SDL_QUIT) {
break;
}
}
if (direction) {
triOffSet += triIncrement;
}
else {
triOffSet -= triIncrement;
}
if (abs(triOffSet) >= triMaxOffSet) {
direction = !direction;
}
curAngle += 1.0f;
if (curAngle >= 360) {
curAngle -= 360;
}
if (direction) {
curSize += 0.001f;
}
else {
curSize -= 0.001f;
}
if (curSize >= maxSize || curSize <= minSize) {
sizeDirection = !sizeDirection;
}
//Clear window
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shaderList[0]->UseShader();
uniformModel = shaderList[0]->GetModelLocation();
uniformProjection = shaderList[0]->GetProjectionLocation();
glm::mat4 model(1.0f);
model = glm::translate(model, glm::vec3(0.0f, 0.0f, -2.5f));
model = glm::rotate(model, curAngle * toRadians, glm::vec3(0.0f, 1.0f, 0.0f));
model = glm::scale(model, glm::vec3(0.4f, 0.4f, 1.0f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(uniformProjection, 1, GL_FALSE, glm::value_ptr(projection));
meshList[0]->RenderMesh();
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(-triOffSet, 1.0f, -2.5f));
model = glm::scale(model, glm::vec3(0.4f, 0.4f, 1.0f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));
meshList[1]->RenderMesh();
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(triOffSet, -1.0f, -2.5f));
model = glm::scale(model, glm::vec3(0.4f, 0.4f, 1.0f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));
meshList[2]->RenderMesh();
glUseProgram(0);
mainWindow.swapWindows();
}
return 0;
}
Mesh.h
#pragma once
#include <GL/glew.h>
class Mesh
{
private:
GLuint VAO, VBO, IBO;
GLsizei indexCount;
public:
Mesh();
void CreateMesh(GLfloat *vertices, unsigned int *indices, unsigned int numOfVertices, unsigned int numOfIndices);
void RenderMesh();
void ClearMesh();
~Mesh();
};
Mesh.cpp
#include "Mesh.h"
#include <GL/glew.h>
Mesh::Mesh() {
VAO = 0;
VBO = 0;
IBO = 0;
indexCount = 0;
}
void Mesh::CreateMesh(GLfloat* vertices, unsigned int* indices, unsigned int numOfVertices, unsigned int numOfIndices) {
indexCount = numOfIndices;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices[0]) * numOfIndices, indices, GL_STATIC_DRAW);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * numOfVertices, vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
void Mesh::RenderMesh() {
glBindVertexArray(VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void Mesh::ClearMesh() {
if (IBO != 0) {
glDeleteBuffers(1, &IBO);
IBO = 0;
}
if (VBO != 0) {
glDeleteBuffers(1, &VBO);
VBO = 0;
}
if (VAO != 0) {
glDeleteBuffers(1, &VAO);
VAO = 0;
}
indexCount = 0;
}
Mesh::~Mesh() {
ClearMesh();
}
Shader.h
#pragma once
#include <stdio.h>
#include <string>
#include <iostream>
#include <fstream>
#include <GL/glew.h>
class Shader
{
private:
GLuint shaderID, uniformProjection, uniformModel;
void CompileShader(const char* vertexCode, const char* fragmentCode);
void AddShader(GLuint theProgram, const char* shaderCode, GLenum shaderType);
public:
Shader();
void CreateFromString(const char* vertexCode, const char* fragmentCode);
void CreateFromFiles(const char* vertexLocation, const char* fragmentLocation);
std::string ReadFile(const char* fileLocation);
GLuint GetProjectionLocation();
GLuint GetModelLocation();
void UseShader();
void ClearShader();
~Shader();
};
Shader.cpp
#include "Shader.h"
Shader::Shader()
{
shaderID = 0;
uniformModel = 0;
uniformProjection = 0;
}
void Shader::CreateFromString(const char* vertexCode, const char* fragmentCode)
{
CompileShader(vertexCode, fragmentCode);
}
void Shader::CreateFromFiles(const char* vertexLocation, const char* fragmentLocation)
{
std::string vertexString = ReadFile(vertexLocation);
std::string fragmentString = ReadFile(fragmentLocation);
const char* vertexCode = vertexString.c_str();
const char* fragmentCode = fragmentString.c_str();
CompileShader(vertexCode, fragmentCode);
}
std::string Shader::ReadFile(const char* fileLocation)
{
std::string content;
std::ifstream fileStream(fileLocation, std::ios::in);
if (!fileStream.is_open()) {
printf("Failed to read %s! File doesn't exist.", fileLocation);
return "";
}
std::string line = "";
while (!fileStream.eof())
{
std::getline(fileStream, line);
content.append(line + "\n");
}
fileStream.close();
return content;
}
void Shader::CompileShader(const char* vertexCode, const char* fragmentCode)
{
shaderID = glCreateProgram();
if (!shaderID)
{
printf("Error creating shader program!\n");
return;
}
AddShader(shaderID, vertexCode, GL_VERTEX_SHADER);
AddShader(shaderID, fragmentCode, GL_FRAGMENT_SHADER);
GLint result = 0;
GLchar eLog[1024] = { 0 };
glLinkProgram(shaderID);
glGetProgramiv(shaderID, GL_LINK_STATUS, &result);
if (!result)
{
glGetProgramInfoLog(shaderID, sizeof(eLog), NULL, eLog);
printf("Error linking program: '%s'\n", eLog);
return;
}
glValidateProgram(shaderID);
glGetProgramiv(shaderID, GL_VALIDATE_STATUS, &result);
if (!result)
{
glGetProgramInfoLog(shaderID, sizeof(eLog), NULL, eLog);
printf("Error validating program: '%s'\n", eLog);
return;
}
uniformProjection = glGetUniformLocation(shaderID, "projection");
uniformModel = glGetUniformLocation(shaderID, "model");
}
GLuint Shader::GetProjectionLocation()
{
return uniformProjection;
}
GLuint Shader::GetModelLocation()
{
return uniformModel;
}
void Shader::UseShader()
{
glUseProgram(shaderID);
}
void Shader::ClearShader()
{
if (shaderID != 0)
{
glDeleteProgram(shaderID);
shaderID = 0;
}
uniformModel = 0;
uniformProjection = 0;
}
void Shader::AddShader(GLuint theProgram, const char* shaderCode, GLenum shaderType)
{
GLuint theShader = glCreateShader(shaderType);
const GLchar* theCode[1];
theCode[0] = shaderCode;
GLint codeLength[1];
codeLength[0] = strlen(shaderCode);
glShaderSource(theShader, 1, theCode, codeLength);
glCompileShader(theShader);
GLint result = 0;
GLchar eLog[1024] = { 0 };
glGetShaderiv(theShader, GL_COMPILE_STATUS, &result);
if (!result)
{
glGetShaderInfoLog(theShader, sizeof(eLog), NULL, eLog);
printf("Error compiling the %d shader: '%s'\n", shaderType, eLog);
return;
}
glAttachShader(theProgram, theShader);
}
Shader::~Shader()
{
ClearShader();
}
Window.h
#pragma once
#include <stdio.h>
#include <GL/glew.h>
#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
class Window
{
private:
SDL_Window* mainWindow;
SDL_Event windowEvent;
GLint width, height;
public:
Window();
Window(GLint windowWidth, GLint windowHeight);
int Initialise();
GLint getBufferWidth() { return width; }
GLint getBufferHeight() { return height; }
void swapWindows() { SDL_GL_SwapWindow(mainWindow); }
~Window();
};
Window.cpp
#include "Window.h"
Window::Window() {
width = 800;
height = 600;
}
Window::Window(GLint width, GLint height) {
width = width;
height = height;
}
int Window::Initialise() {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("SDL initialisation failed\n");
SDL_Quit();
return 1;
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
mainWindow = SDL_CreateWindow("Test game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL);
if (!mainWindow) {
printf("SDL window creation failed!\n");
SDL_Quit();
return 1;
}
//Set context for GLEW to use
SDL_GLContext context = SDL_GL_CreateContext(mainWindow);
//Allow modern extension features
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK) {
printf("GLEW initialization failed!\n");
SDL_DestroyWindow(mainWindow);
SDL_Quit();
return 1;
}
glEnable(GL_DEPTH_TEST);
//Setup viewport size
glViewport(0, 0, 800, 600);
}
Window::~Window() {
SDL_DestroyWindow(mainWindow);
SDL_Quit();
}
I've heard that a solution to this could be to put glewExperimental = GL_True before glewInit() but that hasn't worked because those two lines are in Window.cpp and I don't know how that could affect Mesh.cpp.
The debug reads this at the bottom:
Exception thrown at 0x00000000 in OpenGLCourseApp.exe: 0xC0000005: Access violation executing location 0x00000000.
Call stack
Your Window constructor does not actually initialize the fields of the Window object, which means you call SDL_CreateWindow with random width and height.
Use an initializer list instead, which does not suffer this problem:
Window::Window(int width, int height)
: width(width), height(height) {
}
Once you get past that, keep in mind that the statement
mainWindow = Window(800, 600);
will create a temporary Window object, assign it to mainWindow, and then immediately destroy it!
I suggest you change the type of mainWindow to Window* (or better yet a std::unique_ptr<Window>),
and change that line to
mainWindow = new Window(800, 600);
or
mainWindow = std::make_unique<Window>(800, 600);
My complete code -
#include <SDL.h>
#include <SDL_opengl.h>
#include <GL\GLU.h>
#include <fstream>
using namespace std;
int index = 0;
int speed = 0;
int frames = 0;
int lasttime = 0;
int mousex = 0;
int mousey = 0;
bool postRedraw = true;
int screenWidth = 640;
int screenHeight = 480;
float screenAspect = screenWidth/screenHeight;
bool init();
bool initGL();
void handleKeys( unsigned char key, int x, int y );
void update();
void render();
void close();
void Initialize();
void handleEvents();
ofstream logFile;
SDL_Window* gWindow = NULL;
bool isRunning = true;
SDL_GLContext gContext;
float xpos = 0.0;
float ypos = 0.0;
float zpos = 0.0;
void Initialize()
{
gluPerspective(60.0f, screenAspect, 1.0, 400.0);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_NORMALIZE);
glTranslatef(0.0f, 0.0f, -5.0f);
glFrontFace(GL_CCW);
glEnable(GL_LIGHT0);
}
void render()
{
glTranslatef(xpos, ypos, zpos);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_TRIANGLES);
glVertex3f(-1.0f,0.0f,-1.0f);
glVertex3f(0.0f, 1.0f, -1.0f);
glVertex3f(0.0f, 2.0f, -2.0f);
glEnd();
postRedraw = true;
}
void handleEvents()
{
const Uint8* keystates = SDL_GetKeyboardState(NULL);
if(keystates[SDL_GetScancodeFromKey(SDLK_w)])
{
zpos += 0.01;
}
if(keystates[SDL_GetScancodeFromKey(SDLK_s)])
{
zpos -= 0.01;
} else {
}
}
bool init()
{
bool success = true;
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
logFile<<"SDL could not initialize! SDL Error: "<<SDL_GetError()<<endl;
success = false;
}
else
{
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 2 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 1 );
gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screenWidth, screenHeight, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE );
if( gWindow == NULL )
{
logFile<<"Window could not be created! SDL Error: "<<SDL_GetError()<<endl;
success = false;
}
else
{
gContext = SDL_GL_CreateContext( gWindow );
if( gContext == NULL )
{
logFile<<"OpenGL context could not be created! SDL Error: "<<SDL_GetError()<<endl;
success = false;
}
else
{
if( SDL_GL_SetSwapInterval( 1 ) < 0 )
{
logFile<<"Warning: Unable to set VSync! SDL Error: "<<SDL_GetError()<<endl;
}
if( !initGL() )
{
logFile<<"Unable to initialize OpenGL!"<<endl;
success = false;
}
}
}
}
logFile.open("log.txt");
if(logFile.is_open())
{
success = true;
} else {
success = false;
}
return success;
}
bool initGL()
{
bool success = true;
GLenum error = GL_NO_ERROR;
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
error = glGetError();
if( error != GL_NO_ERROR )
{
logFile<<"Error initializing OpenGL! "<<gluErrorString( error )<<endl;
success = false;
}
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
error = glGetError();
if( error != GL_NO_ERROR )
{
logFile<<"Error initializing OpenGL! "<<gluErrorString( error )<<endl;
success = false;
}
glClearColor( 0.f, 0.f, 0.f, 1.f );
error = glGetError();
if( error != GL_NO_ERROR )
{
logFile<<"Error initializing OpenGL! "<<gluErrorString( error );
success = false;
}
return success;
}
void close()
{
logFile.close();
SDL_DestroyWindow( gWindow );
gWindow = NULL;
SDL_Quit();
}
int main( int argc, char* args[] )
{
if( !init() )
{
logFile<<"Failed to initialize!"<<endl;
}
else
{
SDL_Event event;
Initialize();
lasttime = SDL_GetTicks();
while(isRunning)
{
while( SDL_PollEvent( &event ) != 0 )
{
if(event.type == SDL_QUIT)
{
isRunning = false;
} else if(event.type == SDL_MOUSEMOTION) {
SDL_GetMouseState(&mousex, &mousey);
} else if(event.type == SDL_MOUSEBUTTONDOWN) {
SDL_GetMouseState(&mousex, &mousey);
} else if(event.type == SDL_MOUSEBUTTONUP) {
SDL_GetMouseState(&mousex, &mousey);
}
}
handleEvents();
if(postRedraw)
{
postRedraw = false;
render();
SDL_GL_SwapWindow( gWindow );
}
if((SDL_GetTicks()-lasttime)>=1000)
{
lasttime = SDL_GetTicks();
speed = frames;
logFile<<speed<<endl;
frames = 0;
} else {
frames++;
}
}
}
close();
return 0;
}
The above code is just for testing, the minimalistic code where I have problem is -
void handleEvents()
{
const Uint8* keystates = SDL_GetKeyboardState(NULL);
if(keystates[SDL_GetSancodeFromKey(SDLK_w)]) {
zpos += 0.01;
}
if(keystates[SDL_GetScancodeFromKey(SDLK_s)])
{
zpos -= 0.01;
} else {
}
}
Expected:
the trangle drawn will move forword/ backward while w/s key is pressed.
Output:
the triangle keeps on moving in the desired direction even if the key was released.
You accumulate your matrix changes over time. glTranslatef modifies current matrix with translation. The next frame it modifies it again. And again, ....
You shoud reset matrix with glLoadIdentity() call. Be aware that it modifies currently selected matrix and will undo matrix changes you've made in Initialize (at least your glTranslatef here - perspective should go to GL_PROJECTION matrix, which you haven't done).
I am trying to render a simple Triangle in OpenGL ES 2.x using c++ and SDL 2.
But the glCreateShader and glCreatProgram returning zero.
Bellow Is the code I am using
#include "SDL.h"
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
#include <iostream>
#include <string>
#include <memory>
using namespace std;
GLuint programObject;
class Graphics
{
private:
SDL_Window* _window;
public:
Graphics(SDL_Window* window)
{
_window = window;
}
void update()
{
glClearColor(255.0f, 0.0f, 255.0f, 1);
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
GLfloat vVertices[] = {
0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f
};
glViewport (0, 0, 320, 480);
glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
glClear (GL_COLOR_BUFFER_BIT);
glUseProgram (programObject);
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, vVertices);
glEnableVertexAttribArray (0);
glDrawArrays (GL_TRIANGLES, 0, 3);
SDL_GL_SwapWindow(_window);
}
};
void UpdateFrame(void* param)
{
Graphics* graphics = (Graphics*)param;
graphics->update();
}
///
// Create a shader object, load the shader source, and
// compile the shader.
//
GLuint LoadShader(GLenum type, const GLchar *shaderSrc)
{
GLuint shader;
GLint compiled;
// Create the shader object
shader = glCreateShader(type);
if(shader == 0)
{
cerr << "Could not create OpenGL shader " << endl;
return 0;
}
// Load the shader source
glShaderSource(shader, 1, &shaderSrc, NULL);
// Compile the shader
glCompileShader(shader);
// Check the compile status
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if(!compiled)
{
GLint infoLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
if(infoLen > 1)
{
char* infoLog = (char*)malloc(sizeof(char) * infoLen);
glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
SDL_Log("Error compiling shader:\n%s\n", infoLog);
free(infoLog);
}
glDeleteShader(shader);
return 0;
}
return shader;
}
///
// Initialize the shader and program object
//
int Init()
{
const char vertexShaderString[] =
"attribute vec4 vPosition; \n"
"void main() \n"
"{ \n"
" gl_Position = vPosition; \n"
"} \n";
const char fragmentShaderString[] =
"precision mediump float;\n"\
"void main() \n"
"{ \n"
" gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n"
"} \n";
GLuint vertexShader;
GLuint fragmentShader;
GLint linked;
vertexShader = LoadShader (GL_VERTEX_SHADER, vertexShaderString);
fragmentShader = LoadShader (GL_FRAGMENT_SHADER, fragmentShaderString);
programObject = glCreateProgram ();
if (programObject == 0) {
cerr << "Could not create OpenGL program" << endl;
return 0;
}
glAttachShader (programObject, vertexShader);
glAttachShader (programObject, fragmentShader);
glBindAttribLocation (programObject, 0, "vPosition");
glLinkProgram (programObject);
glGetProgramiv (programObject, GL_LINK_STATUS, &linked);
if (!linked) {
GLint infoLen = 0;
glGetProgramiv (programObject, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 1) {
char* infoLog = (char*) malloc (sizeof (char) * infoLen);
glGetProgramInfoLog (programObject, infoLen, NULL, infoLog);
cerr << "Error linking program: " << infoLog << endl;
free (infoLog);
}
glDeleteProgram (programObject);
return 0;
}
glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
return true;
}
int EventFilter(void* userdata, SDL_Event* event)
{
switch (event->type)
{
case SDL_FINGERMOTION:
SDL_Log("Finger Motion");
return 0;
case SDL_FINGERDOWN:
SDL_Log("Finger Down");
return 0;
case SDL_FINGERUP:
SDL_Log("Finger Up");
return 0;
}
return 1;
}
int main(int argc, char** argv)
{
/* initialize SDL */
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf("Could not initialize SDL\n");
return 1;
}
SDL_DisplayMode displayMode;
SDL_GetDesktopDisplayMode(0, &displayMode);
/* create window and renderer */
SDL_Window* window = SDL_CreateWindow(NULL, 0, 0, displayMode.w, displayMode.h, SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_RESIZABLE);
if (!window) {
printf("Could not initialize Window\n");
return 1;
}
auto gl = SDL_GL_CreateContext(window);
if (!Init()) {
cerr << "Error initializing OpenGL" << endl;
return 1;
}
unique_ptr<Graphics> graphics = unique_ptr<Graphics>(new Graphics(window));
SDL_iPhoneSetAnimationCallback(window, 1, UpdateFrame, graphics.get());
SDL_AddEventWatch(EventFilter, NULL);
//Game Loop
SDL_Event event;
auto done = false;
while (!done)
{
SDL_PumpEvents();
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
done = true;
break;
case SDL_APP_DIDENTERFOREGROUND:
SDL_Log("SDL_APP_DIDENTERFOREGROUND");
break;
case SDL_APP_DIDENTERBACKGROUND:
SDL_Log("SDL_APP_DIDENTERBACKGROUND");
break;
case SDL_APP_LOWMEMORY:
SDL_Log("SDL_APP_LOWMEMORY");
break;
case SDL_APP_TERMINATING:
SDL_Log("SDL_APP_TERMINATING");
break;
case SDL_APP_WILLENTERBACKGROUND:
SDL_Log("SDL_APP_WILLENTERBACKGROUND");
break;
case SDL_APP_WILLENTERFOREGROUND:
SDL_Log("SDL_APP_WILLENTERFOREGROUND");
break;
case SDL_WINDOWEVENT:
{
switch (event.window.event)
{
case SDL_WINDOWEVENT_RESIZED:
{
SDL_Log("Window %d resized to %dx%d", event.window.windowID, event.window.data1, event.window.data2);
break;
}
}
}
}
}
}
SDL_GL_DeleteContext(gl);
// Done! Close the window, clean-up and exit the program.
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
Maybe I am missing something here, any help would be appreciated .
Thanks,
Khaled
This is most likely caused by a problem with the context created by SDL, specifically there were no attributes for the MAJOR/MINOR and MASK attributes which tend to be more important for iOS, OS X etc
What needs to be done is as follows. Before the creation of the SDL_Window do the following:
/* Set the correct attributes for MASK and MAJOR version */
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
/* create window and renderer */
SDL_Window* window = SDL_CreateWindow(NULL, 0, 0, displayMode.w, displayMode.h, SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_RESIZABLE);
Another situation which can cause the same error output is calling glCreateShader or glCreateProgram inside of a glBegin / glEnd block.
Ok, I think I'm going crazy.
I've been developing a 3D game in OpenGL for a while now - all working well.
Then I decided to redesign it from scratch since it was turning to custard. So I set up a basic framework for rendering with OpenGL, and I can't for the life of me get the thing to render a triangle.
I have gone over every line of code about 60 times, gone through every checklist I can find on the internet, checked it against my old project which worked, and still can't see anything wrong with it.
So here is where it all starts (the main method):
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, char* cmdLine, int cmdShow)
{
try
{
GLContext gl(WINDOW_TITLE, 800, 600);
TestRenderable test;
while(true)
{
glClearColor(0.0f, 0.15f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
test.draw();
gl.swapBuffers();
}
}
catch(const std::string& err)
{
std::string msg = "Error: ";
msg += err;
MessageBox(NULL, msg.c_str(), WINDOW_TITLE, MB_OK | MB_ICONERROR);
}
catch(...)
{
MessageBox(NULL, "Unknown Error", WINDOW_TITLE, MB_OK | MB_ICONERROR);
}
}
And all class methods are below:
GLContext::GLContext(const std::string& title, int width, int height)
{
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_BUFFER_SIZE, 32);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
m_pWindow = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL);
m_glContext = SDL_GL_CreateContext(m_pWindow);
if(glewInit() != GLEW_OK)
throw(std::string("Failed to initialize GLEW"));
}
GLContext::~GLContext()
{
SDL_GL_DeleteContext(m_glContext);
SDL_DestroyWindow(m_pWindow);
}
void GLContext::swapBuffers()
{
SDL_GL_SwapWindow(m_pWindow);
}
TestRenderable::TestRenderable() : m_pShader(nullptr), m_pMesh(nullptr)
{
std::vector<std::string> attributes;
attributes.push_back("position");
attributes.push_back("color");
m_pShader = new Shader("shaders\\shader", attributes);
m_pShader->addUniform("transform");
glm::vec3 positions[] =
{
{ 10.0f, 10.0f, 0.0f },
{ 200.0f, 10.0f, 0.0f },
{ 10.0f, 100.0f, 0.0f }
};
glm::vec4 colors[] =
{
{ 0.0f, 1.0f, 0.0f, 1.0f },
{ 1.0f, 0.0f, 0.0f, 1.0f },
{ 0.0f, 0.0f, 1.0f, 1.0f }
};
m_pMesh = new Mesh_PC(positions, colors, 3);
m_projection = glm::ortho<float>(0.0f, 800.0f, 600.0f, 0.0f, 0.0f, 1.0f);
}
TestRenderable::~TestRenderable()
{
if(m_pShader != nullptr)
delete m_pShader;
if(m_pMesh != nullptr)
delete m_pMesh;
}
void TestRenderable::draw()
{
m_pShader->bind();
m_pShader->setUniformMatrix("transform", m_projection);
m_pMesh->draw();
}
Mesh_PC::Mesh_PC(glm::vec3 positions[], glm::vec4 colors[], unsigned numVertices) : m_vertexCount(numVertices)
{
glGenVertexArrays(1, m_vertexArray);
glBindVertexArray(m_vertexArray[0]);
glGenBuffers(NUM_BUFFERS, m_buffers);
glBindBuffer(GL_ARRAY_BUFFER, m_buffers[POSITIONS_BUFFER]);
glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(positions[0]), positions, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, m_buffers[COLORS_BUFFER]);
glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(colors[0]), colors, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
glBindVertexArray(0);
}
Mesh_PC::~Mesh_PC()
{
glDeleteBuffers(NUM_BUFFERS, m_buffers);
glDeleteVertexArrays(1, m_vertexArray);
}
void Mesh_PC::draw()
{
glBindVertexArray(m_vertexArray[0]);
glDrawArrays(GL_TRIANGLES, 0, m_vertexCount);
glBindVertexArray(0);
}
Shader::Shader(const std::string& filename, const std::vector<std::string>& attributes)
{
m_program = glCreateProgram();
m_shaders[0] = createShader(loadShader(filename + ".vs"), GL_VERTEX_SHADER);
m_shaders[1] = createShader(loadShader(filename + ".fs"), GL_FRAGMENT_SHADER);
for(unsigned int i = 0; i < NUM_SHADERS; ++i)
glAttachShader(m_program, m_shaders[i]);
for(unsigned int i = 0; i < attributes.size(); ++i)
glBindAttribLocation(m_program, i, attributes[i].c_str());
glLinkProgram(m_program);
checkShaderError(m_program, GL_LINK_STATUS, true, "Program linking failed");
glValidateProgram(m_program);
checkShaderError(m_program, GL_VALIDATE_STATUS, true, "Program is invalid");
}
Shader::~Shader()
{
for(unsigned int i = 0; i < NUM_SHADERS; ++i)
{
glDetachShader(m_program, m_shaders[i]);
glDeleteShader(m_shaders[i]);
}
glDeleteProgram(m_program);
}
void Shader::addUniform(const std::string& name)
{
m_uniforms.insert(std::make_pair(name, glGetUniformLocation(m_program, name.c_str())));
}
void Shader::bind()
{
glUseProgram(m_program);
}
void Shader::setUniformMatrix(const std::string& name, const glm::mat4& value)
{
bind();
auto it = m_uniforms.find(name);
if(it != m_uniforms.end())
{
glUniformMatrix4fv(it->second, 1, GL_FALSE, &value[0][0]);
}
}
void Shader::setUniformVec4(const std::string& name, const glm::vec4& value)
{
bind();
auto it = m_uniforms.find(name);
if(it != m_uniforms.end())
{
glUniform4fv(it->second, 1, &value[0]);
}
}
std::string Shader::loadShader(const std::string& filename)
{
std::ifstream file;
file.open(filename.c_str());
std::string output;
std::string line;
if(file.is_open())
{
while(file.good())
{
getline(file, line);
output.append(line + "\n");
}
file.close();
}
else
{
std::string err("Unable to load shader: ");
err.append(filename);
throw(err);
}
return output;
}
void Shader::checkShaderError(GLuint shader, GLuint flag, bool isProgram, const char* errorMessage)
{
GLint success = 0;
GLchar error[1024] = { 0 };
if(isProgram)
glGetProgramiv(shader, flag, &success);
else
glGetShaderiv(shader, flag, &success);
if(success == GL_FALSE)
{
if(isProgram)
glGetProgramInfoLog(shader, sizeof(error), NULL, error);
else
glGetShaderInfoLog(shader, sizeof(error), NULL, error);
std::string err(errorMessage);
err.append(": '");
err.append(error);
err.append("'");
throw(err);
}
}
GLuint Shader::createShader(const std::string& text, GLenum shaderType)
{
GLuint shader = glCreateShader(shaderType);
if(shader == 0)
throw("Shader creation failed");
const GLchar *shaderSourceStrings[1];
GLint shaderSourceStringLengths[1];
shaderSourceStrings[0] = text.c_str();
shaderSourceStringLengths[0] = static_cast<GLint>(text.length());
glShaderSource(shader, 1, shaderSourceStrings, shaderSourceStringLengths);
glCompileShader(shader);
checkShaderError(shader, GL_COMPILE_STATUS, false, "Shader compilation failed");
return shader;
}
And by the way I am initalizing SDL - I have an object of the below type in the GLContext class:
class SDL
{
public:
SDL() { SDL_Init(SDL_INIT_VIDEO); }
~SDL() { SDL_Quit(); }
};
And my shaders:
Vertex Shader:
#version 120
attribute vec3 position;
attribute vec4 color;
varying vec4 color0;
uniform mat4 transform;
void main(void)
{
gl_Position = transform * vec4(position, 1.0);
color0 = color;
}
Fragment Shader:
#version 120
varying vec4 color0;
void main(void)
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
I know there is unused stuff in the shaders etc but this is just for testing purposes.
Can anyone help me here?
You need to call glBindBuffer before calling glVertexAttribPointer. At the moment, both attributes will be using the last buffer bound (the one with the color values).
I'm trying to set up an OpenGL context with sfml2. Everthing worked fine and I was able to draw a triangle. In the next step I want to draw some 2D elements with SFML on top of the GL stuff. So I first changed all "Window" entries to "RenderWindow" to be able to draw something. There arno errors but when I compile the program, but it always crashes before drawing, and I don't know why. With sfml1.6 it worked with a RenderWindow. What makes it crash?
this is my code:
#include <iostream>
#include <glew.h>
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
using namespace std;
using namespace sf;
void handleEvents(RenderWindow*);
void fillVBO();
void drawGL();
bool running = true;
GLuint vertexBuffer;
static const GLfloat vertex_buffer_data[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
};
int main() {
VideoMode mode;
mode.BitsPerPixel = 32;
mode.Width = 1024;
mode.Height = 768;
ContextSettings cs;
cs.AntialiasingLevel = 4;
cs.DepthBits = 32;
cs.StencilBits = 16;
cs.MajorVersion = 3;
cs.MinorVersion = 3;
RenderWindow App(mode, "SFML window", Style::Close|Style::Resize, cs);
cout << "Window OK" << endl;
if(glewInit() != GLEW_OK) {
cout << "Unable it initialize Glew!" << endl;
return -1;
}
else {
cout << "GLEW initialization OK" << endl;
}
glClearColor(0.0f, 0.0f, 0.3f, 0.0f);
fillVBO();
cout << "Fill VBO OK" << endl;
while(running) {
App.SetActive();
handleEvents(&App);
cout << "Handle Events OK" << endl;
drawGL();
cout << "Draw GL OK" << endl;
App.Display();
}
return EXIT_SUCCESS;
}
void handleEvents(RenderWindow* wnd) {
Event ev;
while(wnd->PollEvent(ev)) {
switch(ev.Type) {
case Event::Closed:
running = false;
break;
case Event::KeyPressed:
switch(ev.Key.Code) {
case Keyboard::Escape:
running = false;
break;
default:
break;
}
break;
case Event::Resized:
glViewport(0, 0, ev.Size.Width, ev.Size.Height);
break;
default:
break;
}
}
}
void fillVBO() {
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_buffer_data), vertex_buffer_data, GL_STATIC_DRAW);
}
void drawGL() {
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangle !
glDrawArrays(GL_TRIANGLES, 0, 3); // Starting from vertex 0; 3 vertices total -> 1 triangle
glDisableVertexAttribArray(0);
}
I found help on the sfml forum and thought I should post the solution here.
http://www.sfml-dev.org/forum/viewtopic.php?p=46348#46348
To get rid of this error you have to disable all arrays you don't use with glDisableClientState(). Then everything should work fine.