OpenGL + SDL + glew 初始化成功后不绘制任何东西

Posted

技术标签:

【中文标题】OpenGL + SDL + glew 初始化成功后不绘制任何东西【英文标题】:OpenGL + SDL + glew doesn't draw anything after successful initialization 【发布时间】:2016-11-27 13:44:51 【问题描述】:

所以我一直在寻找解决这个问题的方法,但我能找到的都是相当过时的。我的问题是,在初始化 SDL 并且没有错误地闪烁之后,窗口打开并且 Z 上除 1、0 或 -1 以外的任何东西都不会呈现。并且将 Z 设置为这三个值中的任何一个都不会做任何事情。这是我的代码。我在 header 中包含了 glew 和 sdl,并且循环方法是主程序循环。

#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();

【问题讨论】:

【参考方案1】:

Z 上除 1、0 或 -1 以外的任何东西都不会渲染。

在 OpenGL 的标准化设备坐标系中,可视体积只是在所有三个维度上从 -1 到 1 的标准化立方体。

由于您没有应用任何转换,因此您基本上直接在 NDC 空间中绘制(实际上是剪辑空间,但是如果您输入的 w 坐标为 1,则与 NDC 相同,默认情况下) .因此,将 z 设置为 1.0 将导致顶点位于查看体积之外。不过,介于两者之间的任何值(不仅仅是 0.0)都应该有效。

而且将 Z 设置为这三个值中的任何一个都不会做任何事情。

我不能 100% 确定我是否正确理解了这个问题。我认为您希望沿 z 将对象移得越远,对象就会显得越小。但是 GL 将总是通过简单地在 xy 平面上光栅化来进行正交(非透视)投影。如果你想要透视效果,你必须做一些透视变换,通常是通过一个 4x4 同质投影矩阵来完成的。

我建议您先学习线性代数和齐次空间/投影变换的基础知识,然后再尝试深入研究 OpenGL 或 D3D 等渲染 API。

此外,您的代码也存在一些问题:

您在创建上下文之后请求 GL 上下文版本,这将不起作用(它只会告诉 SDL 在下次创建 GL 上下文时要做什么)。您似乎还要求使用“现代” OpenGL 版本 3.3。但是,您用于绘图的代码在现代 GL 中已弃用,并且这些功能已在核心配置文件中完全删除。如果您现在开始学习 GL,我强烈建议您学习现代 OpenGL,而不是 20 年前的这种过时的东西。看看this tutorial,它还涉及数学的某些方面。

【讨论】:

感谢您的回答。我已经从多个教程中将这段代码放在一起,我发现没有一个是我需要知道的一切。我完全忘记了 Z 属性的范围是从 0 到 1。我不想在能够绘制一个简单的三角形之前进行转换。而且我找到的所有教程都是这种老式绘图。【参考方案2】:

您没有任何转换矩阵。因此,可见 z 的范围是 [-1, 1]。如果您从中指定值,则相应的部分将被剪掉(并且不可见)。

【讨论】:

以上是关于OpenGL + SDL + glew 初始化成功后不绘制任何东西的主要内容,如果未能解决你的问题,请参考以下文章

SDL + OpenGL:创建缓冲区时访问冲突

OpenGL 深度测试不工作 (GLEW/SDL2)

SDL OpenGL 应用程序在发布模式下崩溃 [重复]

带有 SDL 和 GLEW 的 OpenGL,错误:48

如何使用 GLEW、OpenGL 或 SDL2 以椭圆运动围绕另一个圆圈旋转一个圆圈?

glew Missing GL version c++ using SDL2 2.0.5 and glew 2.0.0