为啥我的 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 的错误状态。使用glslDevil
、glIntercept
或gDebugger
。检查glGetError
函数。你能测试一下 SDL 是否真的获取了设备上下文吗?
Window 是否反映 glClearColor 调用中的变化?不要在 glClearColor
中使用 0.5 作为 alpha 值。
试试这些建议,然后用 Simucal 建议的最小示例进行报告。
【讨论】:
以上是关于为啥我的 OpenGL 不绘制任何东西?的主要内容,如果未能解决你的问题,请参考以下文章
OpenGL + SDL + glew 初始化成功后不绘制任何东西