使用 opengl 和 glfw 绘制一个简单的立方体时,立方体的面看起来是透明的。
这是代码。使用箭头键旋转。我刚刚在我的程序中封装了一个类。
使用 Visual C++ Ultimate 2010。
#include "GAME.h"
using namespace std;
GAME::GAME()
{
glfwInit();
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_NORMALIZE);
}
int GAME::execute()
{
glfwOpenWindow(640, 320, 16, 16, 16, 16, 16, 16, GLFW_WINDOW);
glfwSetWindowTitle("Viraj");
glClearColor(1.0, 1.0, 1.0, 1.0);
glfwSetKeyCallback(events);
running = true;
while(glfwGetWindowParam(GLFW_OPENED))
{
glfwPollEvents();
loop();
render();
}
return 0;
}
void GAME::events(int key, int action)
{
switch(key)
{
case GLFW_KEY_UP:
glRotatef(10, 1, 0, 0);
break;
case GLFW_KEY_DOWN:
glRotatef(-10, 1, 0, 0);
break;
case GLFW_KEY_RIGHT:
glRotatef(10, 0, 1, 0);
break;
case GLFW_KEY_LEFT:
glRotatef(-10, 0, 1, 0);
break;
}
}
int GAME::loop()
{
return 0;
}
int GAME::render()
{
int win_width;
int win_height;
glfwGetWindowSize(&win_width, &win_height);
const float win_aspect = (float)win_width / (float)win_height;
glViewport(0, 0, win_width, win_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//glOrtho(-win_aspect, win_aspect, -1., 1., -1., 1.);
gluPerspective(90, win_aspect, 1, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, 3.0, 0, 0, 0, 0.0, 1.0, 0.0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_NORMALIZE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_QUADS);
glRotatef(-1, 0, 1, 0);
glColor3f(0.0f, 0.0f, 0.0f);
//Front
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(1.0, 0.0, 0.0);
glVertex3f(1.0, 1.0, 0.0);
glVertex3f(0.0, 1.0, 0.0);
glColor3f(1.0f, 0.0f, 0.0f);
//Left
glVertex3f(1.0, 0.0, 0.0);
glVertex3f(1.0, 0.0, -1.0);
glVertex3f(1.0, 1.0, -1.0);
glVertex3f(1.0, 1.0, 0.0);
glColor3f(0.0f, 1.0f, 0.0f);
//Back
glVertex3f(1.0, 0.0, -1.0);
glVertex3f(1.0, 1.0, -1.0);
glVertex3f(0.0, 1.0, -1.0);
glVertex3f(0.0, 0.0, -1.0);
glColor3f(0.0f, 0.0f, 1.0f);
//Right
glVertex3f(0.0, 0.0, -1.0);
glVertex3f(0.0, 1.0, -1.0);
glVertex3f(0.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glColor3f(1.0f, 0.0f, 1.0f);
//Top
glVertex3f(0.0, 1.0, -0.0);
glVertex3f(0.0, 1.0, -1.0);
glVertex3f(1.0, 1.0, -1.0);
glVertex3f(1.0, 1.0, 0.0);
glColor3f(1.0f, 1.0f, 0.0f);
//Bottom
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(1.0, 0.0, 0.0);
glVertex3f(1.0, 0.0, -1.0);
glVertex3f(0.0, 0.0, -1.0);
glEnd();
glfwSwapBuffers();
return 0;
}
最佳答案
很遗憾地告诉你,你的代码在几个层面上都被破坏了。让我为你分解一下:
#include "GAME.h"
using namespace std;
GAME::GAME()
{
glfwInit();
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_NORMALIZE);
}
这是第一个错误:GLFW 是一个 C 库,需要精确初始化 一次 .调用
glfwInit()
属于主函数,而不是类构造函数。其他函数调用是 OpenGL 调用,但是它们需要一个事件的 OpenGL 上下文。但是,此时程序没有 OpenGL 上下文,因此您所做的所有调用都没有效果。int GAME::execute()
{
glfwOpenWindow(640, 320, 16, 16, 16, 16, 16, 16, GLFW_WINDOW);
glfwSetWindowTitle("Viraj");
glClearColor(1.0, 1.0, 1.0, 1.0);
同样,GLFW 的性质与被用作类的一部分不符。 GLFW 中只能有一个窗口,并且只有一个事件循环。这不能很好地映射到类和对象。你当然可以上课
EventLoop
或类似的,但你不会那样使用它。然后是下一行,我很惊讶它实际上编译了:
glfwSetKeyCallback(events);
events
if 类的成员函数 GAME
, 除非这是一个静态成员函数,否则你不能使用类成员函数作为回调,尤其是对于不知道类的 C 库。它应该如何知道该事件函数属于哪个实例? C++ 没有闭包或委托(delegate)的概念,这是必需的(出于这个原因,其他语言有)。 running = true;
while(glfwGetWindowParam(GLFW_OPENED))
{
glfwPollEvents();
loop();
render();
}
return 0;
}
现在出现的是一个经典的新手误解:
void GAME::events(int key, int action)
{
switch(key)
{
case GLFW_KEY_UP:
glRotatef(10, 1, 0, 0);
break;
case GLFW_KEY_DOWN:
glRotatef(-10, 1, 0, 0);
break;
case GLFW_KEY_RIGHT:
glRotatef(10, 0, 1, 0);
break;
case GLFW_KEY_LEFT:
glRotatef(-10, 0, 1, 0);
break;
}
}
矩阵操作调用仅对绘图代码有意义。在这里调用 glRotate 只会弄乱矩阵堆栈,但是每个理智的 OpenGL 渲染函数都会初始化所有状态,因此在开始时会有一些理智的值。
您想要在事件处理程序中执行的操作是将所有输入累积到变量中,稍后您将在绘图代码中使用这些变量来设置和控制渲染。
int GAME::loop()
{
return 0;
}
如果这是为了循环,为什么没有循环?
int GAME::render()
{
int win_width;
int win_height;
glfwGetWindowSize(&win_width, &win_height);
const float win_aspect = (float)win_width / (float)win_height;
仅缺少一个细节:您需要在此处设置视口(viewport)。没什么大不了的:
glViewport(0, 0, win_width, win_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//glOrtho(-win_aspect, win_aspect, -1., 1., -1., 1.);
gluPerspective(90, win_aspect, 1, 100.0);
现在这实际上很好!您确实在渲染函数中设置了投影矩阵。一路走好,坚持这个模式!
更新 但是下一行是错误的:
gluLookAt(0, 0, 3.0, 0, 0, 0, 0.0, 1.0, 0.0);
gluLookAt
是要在 上执行的功能模型 View 矩阵。模型 View 矩阵负责将模型放置在世界空间中并将世界与 View 对齐,因此转换为 model→world, world→view
其中你可以减少临时world
步骤所以它只是model→view
. glMatrixMode(GL_MODELVIEW);
在这里您可以调用
glLoadIdentity(); gluLookAt(...);
.现在应该很明显了,为什么在事件处理程序中进行矩阵操作是没有意义的。您实际上应该设置模型 View 矩阵,并在此处从头开始完成所有转换。
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
调用
glClear
有点不寻常设置好矩阵、视口(viewport)等之后,还不错。你可以这样离开它。然而,在你开始渲染之前,你应该,acutually必须设置所有需要的OpenGL状态。请记住构造函数中的那些“初始化”OpenGL 调用。他们属于 这里 .
glBegin(GL_QUADS);
glColor3f(0.0f, 0.0f, 0.0f);
//Front
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(1.0, 0.0, 0.0);
glVertex3f(1.0, 1.0, 0.0);
glVertex3f(0.0, 1.0, 0.0);
glColor3f(1.0f, 0.0f, 0.0f);
//Left
glVertex3f(1.0, 0.0, 0.0);
glVertex3f(1.0, 0.0, -1.0);
glVertex3f(1.0, 1.0, -1.0);
glVertex3f(1.0, 1.0, 0.0);
glColor3f(0.0f, 1.0f, 0.0f);
//Back
glVertex3f(1.0, 0.0, -1.0);
glVertex3f(1.0, 1.0, -1.0);
glVertex3f(0.0, 1.0, -1.0);
glVertex3f(0.0, 0.0, -1.0);
glColor3f(0.0f, 0.0f, 1.0f);
//Right
glVertex3f(0.0, 0.0, -1.0);
glVertex3f(0.0, 1.0, -1.0);
glVertex3f(0.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glColor3f(1.0f, 0.0f, 1.0f);
//Top
glVertex3f(0.0, 0.0, -0.0);
glVertex3f(0.0, 0.0, -1.0);
glVertex3f(1.0, 0.0, -1.0);
glVertex3f(1.0, 0.0, 0.0);
glColor3f(1.0f, 1.0f, 0.0f);
//Bottom
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(1.0, 0.0, 0.0);
glVertex3f(1.0, 0.0, -1.0);
glVertex3f(0.0, 0.0, -1.0);
glEnd();
如果你想要照明,你需要提供法线。但我不会费心添加一大堆
glNormal
在那里调用:立即模式(glBegin,glEnd)已过时,我强烈建议您了解顶点数组和顶点缓冲区对象。 glfwSwapBuffers();
return 0;
}
总结:将 GLFW 调用从类中取出。 GLFW 不是面向对象的。只需从
main
全局使用它功能。将事件传递给类是有序的,但您不能将类成员函数用作 GLFW 的回调。你需要写一些辅助函数extern GAME *pGame;
void eventhandler(int key, int action)
{
pGame->event(key, action);
}
您可能还拥有
GAME
类管理所有实例的静态列表并提供静态成员函数,将事件传递给列表中的所有实例。或者使用单例(但是我认为单例是一种反模式,应该避免)。
关于c++ - OpenGL/GLFW 显得透明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7678531/