使用SDL2和OpenGL编译一个简单的三角形

时间:2018-07-30 08:57:03

标签: c++ opengl sdl nvidia ubuntu-18.04

这个问题已经遍及整个互联网,但是我尝试的每个代码示例似乎都具有与我个人为使用OpenGL和SDL2生成一个简单三角形所做的所有尝试相同的结果。在切换到其他窗口API之前,我的好奇心不允许我简单地解决这个难题。

至于我要解决的问题,我只是想弄清楚源是否是我的系统(考虑到我发现的所有代码示例看上去都相似,并且似乎在两台不同的计算机上广为人知这一事实。 ),或者我自己做错了什么。

我的PC在ubuntu 18.04上运行了GTX 1050m,我的驱动程序是它能够支持OpenGL 4.6的ubuntu ppa上的官方nvidia驱动程序。

这是display.h我的头文件,用于初始化SDL2和Glew

layout-land

这是display.cpp

#ifndef DISPLAY_H
#define DISPLAY_H

#include<SDL2/SDL.h>
#include<string>

class Display
{
public:
    //initializes SDL2 and Glew
    Display( int width, int height, const std::string& title );

    //Clears the screen and creates a triangle
    void Clear();
    //Calls SDL_GL_SwapWindow()
    void Update();
    //Determines whether or not SDL_QUIT Event is called
    bool IsClosed();

    //Destroys application
    virtual ~Display();
protected:
private:
    Display( const Display& other )
    void operator=( const Display& other );

    SDL_Window* m_window;
    SDL_GLContext m_glContext;
    bool m_isClosed;

};
#endif //DISPLAY_H

最后这是我简单的main.cpp

//Constructor and Destructor container 
#include"display.h"
//Glew container
#include<GL/glew.h>
//Standard I\0 lib
#include<cstdio>

//Constructor
Display::Display( int width, int height, const std::string& title )
{
    //SDL2 initialization and error check 
    if( SDL_Init( SDL_INIT_VIDEO ) != 0 ){
    printf( "Unable to initialize SDL: %s\n", SDL_GetError() );
    SDL_ClearError();
    }

    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_DEPTH_SIZE, 16);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
                        SDL_GL_CONTEXT_PROFILE_COMPATIBILITY );

    //SDL Create window stored in variable m_window
    m_window = SDL_CreateWindow( title.c_str(),
                                 SDL_WINDOWPOS_UNDEFINED,
                                 SDL_WINDOWPOS_UNDEFINED,
                                 width,
                                 height,
                                 SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE );

    // Error checking window
    if( !m_window ) {
    fprintf( stderr, "Could not create window: %s\n", SDL_GetError() );
    return;
    }

    //Creates OpenGL context
    m_glContext = SDL_GL_CreateContext( m_window );
    if ( !m_glContext ){
    fprintf( stderr, "Couldn't create context: %s\n", SDL_GetError() );
    return;
    }

    //Makes the open window the current context
    SDL_GL_MakeCurrent( m_window, m_glContext );

    //Checks How OpenGL handled setting 
    int rs, gs,bs;

    SDL_GL_GetAttribute( SDL_GL_RED_SIZE, &rs );
    SDL_GL_GetAttribute( SDL_GL_GREEN_SIZE, &gs );
    SDL_GL_GetAttribute( SDL_GL_BLUE_SIZE, &bs );
    printf( "Red size: %d, Green size: %d, Blue size: %d\n", rs, gs, bs );


    //To be implemented
    //glewExperimental = GL_TRUE;

    //initialization of glew
    GLenum status = glewInit();
    if(GLEW_OK != status ){
        printf( "GLEW Error: ", glewGetErrorString( status ) );
    }
        printf( "Status: Using GLEW: %s\n", glewGetString( GLEW_VERSION ) );

}

//Destructer
Display::~Display()
{
    //Deletes GL context
    SDL_GL_DeleteContext( m_glContext );

    //Close and destroy the window
    SDL_DestroyWindow( m_window );

    //Clean up
    SDL_Quit();
}

void Display::Clear()
{
    //Clears the screen
    glClear( GL_COLOR_BUFFER_BIT );

    //Creating a triangle
    glBegin( GL_POLYGON );

    glColor3f( 1, 0, 0 );
    glVertex3f( -0.6, -0.75, 0.5 );

    glColor3f( 0, 1, 0 );
    glVertex3f( 0.6, -0.75, 0 );

    glColor3f( 0, 0, 1 );
    glVertex3f( -0, -0.75, 0 );
    glEnd();
    glFlush();
}

//Closes the window on SDL_QUIT event 
bool Display::IsClosed()
{
    return m_isClosed;
}

void Display::Update()
{
    SDL_GL_SwapWindow( m_window );

    SDL_Event e;

    while( SDL_PollEvent( &e ) )
    {
        if( e.type == SDL_QUIT )
        m_isClosed = true;
    }
}

便捷的Makefile

#include<GL/glew.h>
#include<iostream>
#include"display.h"

int main( int argc, char* argv[] )
{
    Display display( 640, 480, "flagShip" );

    while( !display.IsClosed() )
          {
    display.Clear();

    display.Update();
    }

    return 0;
}

2 个答案:

答案 0 :(得分:0)

拿一张方格纸,然后画出“三角形”的顶点坐标。你注意到什么了吗?

  • 提示1:绘制的三角形的面积为零。

  • 提示2:查看最后一次glVertex调用的y值。

答案 1 :(得分:0)

您不使用任何视图矩阵或投影矩阵。这意味着您必须分别在片段空间和规范化设备空间中设置三角形的顶点坐标。

归一化设备空间是一个立方体,其中左,下,近坐标为(-1,-1,-1),右,上,远坐标为(1、1、1):

NDC

x轴到视口的投影,从左到右指向,y轴的投影从底部到顶部。
由于三角形的所有y坐标都相等,因此三角形垂直于视口:

glVertex3f( -0.6, -0.75, 0.5 );
...
glVertex3f(  0.6, -0.75, 0 );
...
glVertex3f(   -0, -0.75, 0 );   

交换三角形顶点坐标的y和z分量以解决此问题:

glVertex3f( -0.6, 0.5, -0.75 );
...
glVertex3f(  0.6, 0.0, -0.75 );
...
glVertex3f( -0.0, 0.0, -0.75 ); 

预览:

preview