Maroš Beťko Maroš Beťko - 5 days ago 5
C++ Question

OpenGL + SDL + glew doesn't draw anything after successful initialization

so I've been searching around for a solution to this for a while but all I could find was pretty outdated. My problem is that after initializing SDL and glew without errors, window opens and anything on other Z than 1, 0 or -1 won't render. And also setting Z to any of those three values doesn't do anything at all. Here is my code. I have both glew and sdl included in header and the loop method is the main program loop.

#include "Controller.h"

int Controller::loop() {
// Initialize
if(!init())
return -1;

SDL_Event _event;

// Main loop
while(_running) {
// Loop through all input
while(SDL_PollEvent(&_event))
event(_event);
// Game logic
step();
// Game drawing
draw();
}

// End game
end();
return 0;
}

bool Controller::init() {
// Initialize SDL
if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
return false;

// Create window
if ((_mainWindow = SDL_CreateWindow("GAME", 200, 200, 640, 480, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL)) == NULL)
return false;

// Create context
_mainContext = SDL_GL_CreateContext(_mainWindow);

// Make it active
SDL_GL_MakeCurrent(_mainWindow, _mainContext);

SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);

// Initialize glew
glewExperimental = GL_TRUE;
if (glewInit() != 0)
return false;

return true;
}

void Controller::event(SDL_Event& _event) {
switch(_event.type) {
case SDL_KEYDOWN:
switch (_event.key.keysym.sym) {
case SDLK_ESCAPE:
_running = false;
break;
default:
std::cout << "Key has been pressed." << std::endl;
}
default:
break;
}
_world[_currentWorld].event(_event);
}

void Controller::step() {
_world[_currentWorld].step();
}

void Controller::draw() {
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);

glColor3f(1.0f, 0.0f, 0.0f);

glBegin(GL_TRIANGLES);

glVertex3f(-1.0f, -0.5f, -4.0f); // A
glVertex3f(1.0f, -0.5f, -4.0f); // B
glVertex3f(0.0f, 0.5f, -4.0f); // C

glEnd();

//_world[_currentWorld].draw();
SDL_GL_SwapWindow(_mainWindow);
}

void Controller::end() {
SDL_GL_DeleteContext(_mainContext);
SDL_DestroyWindow(_mainWindow);
SDL_Quit();
}

Answer

anything on other Z than 1, 0 or -1 won't render.

In OpenGL's normalized device coordinate system, the viewing volume is just the normalized cube going from -1 to 1 along all three dimensions.

Since you do not apply any transformations, you basically directly draw in NDC space (actually, it would be clip space, but that one will be identical to NDC if your input w coordinate is 1 everythere, and it is by default). As a result, setting z to < -1.0 or > 1.0 will result in the vertices lying outside of the viewing volume. Any values in-between (not just 0.0) should work, though.

And also setting Z to any of those three values doesn't do anything at all.

I'm not 100% sure that I understand that question right. I think you expect that objects should appear smaller the farther you move them away along z. But the GL will always do an orthogonal (non-perspective) projection, by simply rasterizing in the xy-plane. You have to do some perspectivee transformation if you want the perspective effect, and typically, that is done via a 4x4 homogenous projection matrix.

I would recommend you to learn the basics of linear algebra and homogenous spaces / projective transformations first, before trying to dive into render APIs like OpenGL or D3D.

Also, there are a few issues with your code:

You request the GL context version after you created the context, which will have no effect (it will only tell SDL what to do the next time it creates a GL context). YOu also seem to request a "modern" OpenGL version, 3.3. However, the code you are using for drawing is deprecated in modern GL, and those features are completely removed in core profiles. If you start learning GL nowadays, I strongly recommend learn modern OpenGL instead, and not this obsolete cruft from 20 years ago. Have a look at this tutorial, it also deals with some aspects of the maths.

Comments