为啥我的 OpenGL 不绘制任何东西?

Posted

技术标签:

【中文标题】为啥我的 OpenGL 不绘制任何东西?【英文标题】:Why won't my OpenGL draw anything?为什么我的 OpenGL 不绘制任何东西? 【发布时间】:2009-02-11 09:56:24 【问题描述】:

我正在将我的开源粒子引擎测试从 SDL 移植到 SDL + OpenGL。我已经设法让它编译和运行,但无论我做什么,屏幕都保持黑色。 main.cpp:

#include "glengine.h"



int WINAPI WinMain(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow
)

//Create a glengine instance
ultragl::glengine *gle = new ultragl::glengine();

if(gle->init())
    gle->run();

else
    std::cout << "glengine initializiation failed!" << std::endl;

//If we can't initialize, or the lesson has quit we delete the instance
delete gle;

return 0;
;

glengine.h:

//we need to include window first because GLee needs to be included before GL.h
#include "window.h"
#include <math.h>           // Math Library Header File
#include <vector>
#include <stdio.h>

using namespace std;

namespace ultragl

    class glengine
    
        protected:
                window m_Window; ///< The window for this lesson
                unsigned int m_Keys[SDLK_LAST]; ///< Stores keys that are pressed
                float piover180;

                virtual void draw();
                virtual void resize(int x, int y);
                virtual bool processEvents();
                void controls();

        private:
            /*
             * We need a structure to store our vertices in, otherwise we
             * just had a huge bunch of floats in the end
             */
            struct Vertex
            
                float x, y, z;

                Vertex()

                Vertex(float x, float y, float z)
                
                    this->x = x;
                    this->y = y;
                    this->z = z;
                
            ;

            struct particle
            
                public :
                double angle;
                double speed;
                Vertex v;
                int r;
                int g;
                int b;
                int a;

                particle(double angle, double speed, Vertex v, int r, int g, int b, int a)
                
                    this->angle = angle;
                    this->speed = speed;
                    this->v = v;
                    this->r = r;
                    this->g = g;
                    this->b = b;
                    this->a = a;
                

                particle()
                

                

            ;

            particle p[500];
            float particlesize;


        public:
            glengine();
            ~glengine();

            virtual void run();
            virtual bool init();
            void glengine::test2(int num);
            void glengine::update();
    ;
;

window.h:

#include <string>
#include <iostream>

#include "GLee/GLee.h"

#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
#include <GL/glu.h>

using namespace std;

namespace ultragl

    class window
    
        private:
            int w_height;
            int w_width;
            int w_bpp;
            bool w_fullscreen;
            string w_title;

        public:
            window();
            ~window();

            bool createWindow(int width, int height, int bpp, bool fullscreen, const string& title);
            void setSize(int width, int height);
            int getHeight();
            int getWidth();
    ;
;

glengine.cpp(主要看的):

#include "glengine.h"

namespace ultragl

    glengine::glengine()
    
        piover180 = 0.0174532925f;
    

    glengine::~glengine()
    

    

    void glengine::resize(int x, int y)
    
        std::cout << "Resizing Window to " << x << "x" << y << std::endl;

        if (y <= 0)
        
            y = 1;
        

        glViewport(0,0,x,y);

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45.0f,(GLfloat)x/(GLfloat)y,1.0f,100.0f);

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    

    bool glengine::processEvents()
    
        SDL_Event event;

        while (SDL_PollEvent(&event))//get all events
        
            switch (event.type)
            
                // Quit event
                case SDL_QUIT:
                
                    // Return false because we are quitting.
                    return false;
                

                case SDL_KEYDOWN:
                
                    SDLKey sym = event.key.keysym.sym;

                    if(sym == SDLK_ESCAPE) //Quit if escape was pressed
                    
                        return false;
                    

                    m_Keys[sym] = 1;
                    break;
                

                case SDL_KEYUP:
                
                    SDLKey sym = event.key.keysym.sym;
                    m_Keys[sym] = 0;
                    break;
                

                case SDL_VIDEORESIZE:
                
                    //the window has been resized so we need to set up our viewport and projection according to the new size
                    resize(event.resize.w, event.resize.h);
                    break;
                
                // Default case
                default:
                
                    break;
                
            
        

        return true;
    


    bool glengine::init()
    
        srand( time( NULL ) );

        for(int i = 0; i < 500; i++)
            p[i] = particle(0, 0, Vertex(0.0f, 0.0f, 0.0f), 0, 0, 0, 0);


        if (!m_Window.createWindow(640, 480, 32, false, "Paricle Test GL"))
        
            return false;
        

        particlesize = 0.01;
        glShadeModel(GL_SMOOTH);                // Enable Smooth Shading
        glClearColor(0.0f, 0.0f, 0.0f, 0.5f);   // Black Background
        glClearDepth(1.0f);                     // Depth Buffer Setup
        glEnable(GL_DEPTH_TEST);                // Enables Depth Testing
        glDepthFunc(GL_LEQUAL);                 // The Type Of Depth Testing To Do
        glEnable(GL_BLEND);
        glBlendFunc(GL_ONE , GL_ONE_MINUS_SRC_ALPHA);

        return true;
    

    void glengine::test2(int num)
    
        glPushMatrix();
            glTranslatef(p[num].v.x, p[num].v.y, p[num].v.z);
            glBegin(GL_QUADS);
                glColor4i(p[num].r, p[num].g, p[num].b, p[num].a);                // Green for x axis
                    glVertex3f(-particlesize, -particlesize,  particlesize);
                    glVertex3f( particlesize, -particlesize,  particlesize);
                    glVertex3f( particlesize,  particlesize,  particlesize);
                    glVertex3f(-particlesize,  particlesize,  particlesize);
            glEnd();

        glPopMatrix();
    

    void glengine::draw()
    
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
        glLoadIdentity();                   // Reset The Current Modelview Matrix

        gluLookAt(0, 5, 20, 0, 0, 0, 0, 0, 0);
        for(int i = 0; i < 500; i++)
            test2(i);
    

    void glengine::update()
    
        for(int i = 0; i < 500; i++)
        
            if(p[i].a <= 0)
                p[i] = particle(5 + rand() % 360, (rand() % 10) * 0.1, Vertex(0.0f, 0.0f, 0.0f), 0, 255, 255, 255);

            else
                p[i].a -= 1;

            p[i].v.x += (sin(p[i].angle * (3.14159265/180)) * p[i].speed);
            p[i].v.y -= (cos(p[i].angle * (3.14159265/180)) * p[i].speed);
        
    

    void glengine::run()
    
        while(processEvents())
        
            update();
            draw();
            SDL_GL_SwapBuffers();
        
    
;

最后是 window.cpp:

#include "window.h"

namespace ultragl

    window::window(): w_width(0), w_height(0), w_bpp(0), w_fullscreen(false)
    

    

    window::~window()
    
        SDL_Quit();
    

    bool window::createWindow(int width, int height, int bpp, bool fullscreen, const string& title)
    
        if( SDL_Init( SDL_INIT_VIDEO ) != 0 )
            return false;

        w_height = height;
        w_width = width;
        w_title = title;
        w_fullscreen = fullscreen;
        w_bpp = bpp;

        //Set lowest possiable values.
        SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
        SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
        SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
        SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 5);
        SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

        //Set title.
        SDL_WM_SetCaption(title.c_str(), title.c_str());

        // Flags tell SDL about the type of window we are creating.
        int flags = SDL_OPENGL;

        if(fullscreen == true)
            flags |= SDL_FULLSCREEN;

        // Create window
        SDL_Surface * screen = SDL_SetVideoMode( width, height, bpp, flags );

        if(screen == 0)
            return false;

        //SDL doesn't trigger off a ResizeEvent at startup, but as we need this for OpenGL, we do this ourself
        SDL_Event resizeEvent;
        resizeEvent.type = SDL_VIDEORESIZE;
        resizeEvent.resize.w = width;
        resizeEvent.resize.h = height;

        SDL_PushEvent(&resizeEvent);

        return true;
    

    void window::setSize(int width, int height)
    
        w_height = height;
        w_width = width;
    

    int window::getHeight()
    
        return w_height;
    

    int window::getWidth()
    
        return w_width;
    
;

无论如何,我真的需要完成这个,但我已经尝试了我能想到的一切。我以多种不同的方式测试了 glengine 文件,使其在某一时刻看起来像这样:

#include "glengine.h"
#include "SOIL/SOIL.h"
#include "SOIL/stb_image_aug.h"
#include "SOIL/image_helper.h"
#include "SOIL/image_DXT.h"

namespace ultragl

    glengine::glengine()
    
        piover180 = 0.0174532925f;
    

    glengine::~glengine()
    

    

    void glengine::resize(int x, int y)
    
        std::cout << "Resizing Window to " << x << "x" << y << std::endl;

        if (y <= 0)
        
            y = 1;
        

        glViewport(0,0,x,y);

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45.0f,(GLfloat)x/(GLfloat)y,1.0f,1000.0f);

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    

    bool glengine::processEvents()
    
        SDL_Event event;

        while (SDL_PollEvent(&event))//get all events
        
            switch (event.type)
            
                // Quit event
                case SDL_QUIT:
                
                    // Return false because we are quitting.
                    return false;
                

                case SDL_KEYDOWN:
                
                    SDLKey sym = event.key.keysym.sym;

                    if(sym == SDLK_ESCAPE) //Quit if escape was pressed
                    
                        return false;
                    

                    m_Keys[sym] = 1;
                    break;
                

                case SDL_KEYUP:
                
                    SDLKey sym = event.key.keysym.sym;
                    m_Keys[sym] = 0;
                    break;
                

                case SDL_VIDEORESIZE:
                
                    //the window has been resized so we need to set up our viewport and projection according to the new size
                    resize(event.resize.w, event.resize.h);
                    break;
                
                // Default case
                default:
                
                    break;
                
            
        

        return true;
    


    bool glengine::init()
    
        srand( time( NULL ) );

        for(int i = 0; i < 500; i++)
            p[i] = particle(0, 0, Vertex(0.0f, 0.0f, 0.0f), 0, 0, 0, 0);


        if (!m_Window.createWindow(640, 480, 32, false, "Paricle Test GL"))
        
            return false;
        

        particlesize = 10.01;
        glShadeModel(GL_SMOOTH);                // Enable Smooth Shading
        glClearColor(0.0f, 0.0f, 0.0f, 0.5f);   // Black Background
        glClearDepth(1.0f);                     // Depth Buffer Setup
        glEnable(GL_DEPTH_TEST);                // Enables Depth Testing
        glDepthFunc(GL_LEQUAL);                 // The Type Of Depth Testing To Do
        glEnable(GL_BLEND);
        glBlendFunc(GL_ONE , GL_ONE_MINUS_SRC_ALPHA);

        return true;
    

    void glengine::test2(int num)
    
        //glPushMatrix();
            //glTranslatef(p[num].v.x, p[num].v.y, p[num].v.z);
                glColor4i(255, 255, 255, 255);

        glBegin(GL_QUADS);
            glNormal3f( 0.0f, 0.0f, 1.0f);
            glVertex3f(-particlesize, -particlesize,  particlesize);
            glVertex3f( particlesize, -particlesize,  particlesize);
            glVertex3f( particlesize,  particlesize,  particlesize);
            glVertex3f(-particlesize,  particlesize,  particlesize);
        glEnd();

        // Back Face
        glBegin(GL_QUADS);
            glNormal3f( 0.0f, 0.0f,-1.0f);
            glVertex3f(-particlesize, -particlesize, -particlesize);
            glVertex3f(-particlesize,  particlesize, -particlesize);
            glVertex3f( particlesize,  particlesize, -particlesize);
            glVertex3f( particlesize, -particlesize, -particlesize);
        glEnd();

        // Top Face
        glBegin(GL_QUADS);
            glNormal3f( 0.0f, 1.0f, 0.0f);
            glVertex3f(-particlesize,  particlesize, -particlesize);
            glVertex3f(-particlesize,  particlesize,  particlesize);
            glVertex3f( particlesize,  particlesize,  particlesize);
            glVertex3f( particlesize,  particlesize, -particlesize);
        glEnd();

        // Bottom Face
        glBegin(GL_QUADS);
            glNormal3f( 0.0f,-1.0f, 0.0f);
            glVertex3f(-particlesize, -particlesize, -particlesize);
            glVertex3f( particlesize, -particlesize, -particlesize);
            glVertex3f( particlesize, -particlesize,  particlesize);
            glVertex3f(-particlesize, -particlesize,  particlesize);
        glEnd();

            // Right face
        glBegin(GL_QUADS);
            glNormal3f( 1.0f, 0.0f, 0.0f);
            glVertex3f( particlesize, -particlesize, -particlesize);
            glVertex3f( particlesize,  particlesize, -particlesize);
            glVertex3f( particlesize,  particlesize,  particlesize);
            glVertex3f( particlesize, -particlesize,  particlesize);
        glEnd();

            // Left Face
        glBegin(GL_QUADS);
            glNormal3f(-1.0f, 0.0f, 0.0f);
            glVertex3f(-particlesize, -particlesize, -particlesize);
            glVertex3f(-particlesize, -particlesize,  particlesize);
            glVertex3f(-particlesize,  particlesize,  particlesize);
            glVertex3f(-particlesize,  particlesize, -particlesize);
        glEnd();


        //glPopMatrix();
    

    void glengine::draw()
    
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
        glLoadIdentity();                   // Reset The Current Modelview Matrix

        gluLookAt(0, 5, 20, 0, 0, 0, 0, 1, 0);
        for(int i = 0; i < 500; i++)
            test2(i);
    

    void glengine::update()
    
        for(int i = 0; i < 500; i++)
        
            if(p[i].a <= 0)
                p[i] = particle(5 + rand() % 360, (rand() % 10) * 0.1, Vertex(0.0f, 0.0f, -5.0f), 0, 255, 255, 255);

            else
                p[i].a -= 1;

            p[i].v.x += (sin(p[i].angle * (3.14159265/180)) * p[i].speed);
            p[i].v.y -= (cos(p[i].angle * (3.14159265/180)) * p[i].speed);
        
    

    void glengine::run()
    
        while(processEvents())
        
            update();
            draw();
            SDL_GL_SwapBuffers();
        
    
;

还是不行。在这个问题上我真的束手无策。

【问题讨论】:

我发现如果您可以将源代码减少到绝对最小示例,同时仍然遇到相同的问题,您会得到更好的响应。当您可以将问题简化为 1 页的简单示例时,人们不希望通过查看 4 页源代码来完成这项工作。 将您的程序简化为尽可能简单的绘图程序。设置您的 OpenGL 窗口、视口等并尝试绘制一条线。如果它没有显示在此处发布该代码。然后,当人们看到问题时,您可以将修复程序应用于更大的问题。 【参考方案1】:

我没有检查过你的代码,但是在调试这类问题时我总是做的一件事就是将清晰的颜色设置为像 (1, 0, 1) 左右这样的颜色。

这将帮助您了解问题是您绘制的对象是全黑还是根本没有绘制。

编辑: 正如评论中提到的那样:如果清除操作清除为正确的颜色或保持黑色,它还会显示您是否有正确的 GL 上下文。

【讨论】:

看看你是否创建了一个合适的上下文,至少 glClear 可以工作。【参考方案2】:

好的,我根据您的很多建议以及我已经放置的一些其他源代码设法修复了它。原来问题出在 3 条不同的线路上。

粒度 = 0.01;应该更大:particleize = 1.01;

glColor4i(255, 255, 255, 255) 正在将立方体变成与透明颜色相同的颜色,因为我用错了。我不知道如何正确使用它,所以我改用glColor4f(0.0f,1.0f,1.0f,0.5f),这很有效。

最后gluLookAt(0, 5, 20, 0, 0, 0, 0, 0, 0) 必须是gluLookAt(0, 5, 20, 0, 0, 0, 0, 1, 0)

感谢大家的帮助和时间。

【讨论】:

【参考方案3】:

您没有检查 SDL-GL-SetAttribute() 调用的返回值。

您的显卡是否支持 5/5/5/5 20-bpp 颜色?

【讨论】:

同意,最好在没有工作环境的情况下避免如此具体!【参考方案4】:

检查 OpenGL 的错误状态。使用glslDevilglInterceptgDebugger。检查glGetError 函数。你能测试一下 SDL 是否真的获取了设备上下文吗? Window 是否反映 glClearColor 调用中的变化?不要在 glClearColor 中使用 0.5 作为 alpha 值。 试试这些建议,然后用 Simucal 建议的最小示例进行报告。

【讨论】:

以上是关于为啥我的 OpenGL 不绘制任何东西?的主要内容,如果未能解决你的问题,请参考以下文章

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

OpenGL 3.3 无法绘制任何东西

OpenGL不绘制任何东西

在现有 sdl_opengl 上下文上绘制小部件

Opengl 3.3 不绘制任何东西。使用 GLSL 330 核心

如何在OpenGL中将像素作为纹理绘制到多边形?