首页 > 解决方案 > 使用 SDL2 和 OpenGL 编译一个简单的三角形

问题描述

这个问题已经在整个互联网上提出,但我尝试的每个代码示例似乎都与我个人使用 OpenGL 和 SDL2 生成简单三角形的所有尝试具有相同的结果。在切换到不同的窗口 API 之前,我的好奇心不会让我让这个困境简单地存在。

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

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

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

#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

这是 display.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;
    }
}

最后这是我的简单 main.cpp

#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;
}

方便的 Makefile

CC=g++
OBJS= main.cpp
LINKER_FLAGS= -lSDL2 -lGL -lGLEW
COMPILER_FLAGS= -w -pedantic
OBJ_NAME=flagShip

$(OBJ_NAME):main.o display.o
    $(CC) $(COMPILER_FLAGS) -o $(OBJ_NAME) main.o display.o $(LINKER_FLAGS)

main.o:$(OBJS) display.h
    $(CC) $(COMPILER_FLAGS) -c $(OBJS) 

display.o: display.cpp display.h
    $(CC) $(COMPILER_FLAGS) -c display.cpp                                         

标签: c++openglsdlnvidiaubuntu-18.04

解决方案


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

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

国家数据中心

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

预习:

预习


推荐阅读