OpenGL / GLFW 呈现透明

发布于 2024-12-08 16:22:38 字数 2968 浏览 0 评论 0原文

使用 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;
}

While drawing a simple cube using opengl and glfw, the faces of the cube appear to be transparent.
Here's the code. Use the arrow keys to rotate. I've just encapsulated into a class, in my program.
Using 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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

自此以后,行同陌路 2024-12-15 16:22:38

我很遗憾地告诉你,你的代码在几个层面上都被破坏了。让我为您分解一下:

#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() 的调用属于 main 函数,而不是类构造函数。其他函数调用是 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 a member function of class GAME, and除非这是一个静态成员函数,否则您可以不要使用类成员函数作为回调,尤其是对于不认识类的 C 库。它应该如何知道该事件函数属于哪个实例? C++ 没有闭包或委托的概念,而这是必需的(其他语言也有,正是因为这个原因)。

    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;

仅缺少一个细节:您需要在此处设置视口。没什么大不了的: 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 是一个要在modelview 矩阵上执行的函数。模型视图矩阵负责将模型放置在世界空间中并将世界与视图对齐,因此转换是模型→世界,世界→视图,您可以减少中间的世界 步骤,因此它只是模型→视图

    glMatrixMode(GL_MODELVIEW);

在这里你可以调用glLoadIdentity(); gluLookAt(...);。现在应该很明显了,为什么在事件处理程序中进行矩阵操作没有意义。

您实际上应该设置模型视图矩阵,并在此处从头开始完成所有转换。

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

在设置好矩阵、视口等之后调用glClear有点不寻常,但并没有错。你可以就这样。

然而,在开始渲染之前,您实际上必须设置所需的所有 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 类管理所有实例的静态列表并提供一个静态成员函数,将事件传递给列表中的所有实例。或者使用单例(但是我认为单例是一种反模式,应该避免)。

I'm sorry to tell you, but your code is broken on several levels. Let me break it down for you:

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

Here lies the first error: GLFW is a C library, and it needs to be initialized exactly once. The call to glfwInit() belongs into the main function, not a class constructor. The other function calls are OpenGL calls, however they require an active OpenGL context. At this point of the program there is no OpenGL context however, so all the calls you do have not effect at all.

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

Again the nature of GLFW doesn't go along with being used as part of a class. You can have only one window in GLFW and there's only one event loop. This doesn't map so well to classes and objects. You can have of course a class EventLoop or similar, but you wouldn't use it like that.

And then there is this next one line I'm surprised it actually compiled:

    glfwSetKeyCallback(events);

events if a member function of class GAME, and unless this is a static member function, you can not use a class member function as callback, especially not to a C library, which doesn't know classes. How should it know, which instance that event function belongs to? C++ doesn't have the concept of closures or delegates, which was required for this (other languages do, for that very reason).

    running = true;
    while(glfwGetWindowParam(GLFW_OPENED))
    {
        glfwPollEvents();
        loop();
        render();
    }
    return 0;
}

What comes now is a classical newbie misconception:

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

The matrix manipulation calls make only sense withing the drawing code. Calling glRotate here will just mess with the matrix stack, but every sane OpenGL rendering function will initialize all state so some sane values at the beginning.

What you want to do in a event handler is accumulating all input into variables, which you later use in the drawing code to setup and control rendering.

int GAME::loop()
{
    return 0;
}

If this is meant to loop, why is there no loop?

int GAME::render()
{
    int win_width;
    int win_height;
    glfwGetWindowSize(&win_width, &win_height);
    const float win_aspect = (float)win_width / (float)win_height;

Only one detail missing: You need to set the viewport here. No big deal: 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);

Now this is actually good! You do setup the projection matrix in the render function. Way to go, stick to this pattern!

UPDATE However the next line is wrong:

    gluLookAt(0, 0, 3.0, 0, 0, 0, 0.0, 1.0, 0.0);

gluLookAt is a function meant to be performed on the modelview matrix. The modelview matrix is responsible for both placing models in world space and aligning the world to the view, hence the transformation are model→world, world→view of which you can reduce away the interim world step so it's only model→view.

    glMatrixMode(GL_MODELVIEW);

Here you would call glLoadIdentity(); gluLookAt(...);. It should become obvious now, why doing matrix manipulations in event handlers makes no sense.

You should actually set the modelview matrix, with all transformations done from scratch here.

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

It's a bit unusual to call glClear after setting up the matrices, viewport, etc., but not wrong. You may leave it that way.

However before you begin rendering, you should, acutually must set all OpenGL state required. Remember those "initializing" OpenGL calls in the constructor. They belong here.

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

If you want lighting you need to supply normals. But I'd not bother adding a large bunch of glNormal calls up there: The Immediate Mode (glBegin, glEnd) is outdated, I strongly recommend you learn about Vertex Arrays and Vertex Buffer Objects.

    glfwSwapBuffers();
    return 0;
}

Summarizing: Get the GLFW calls out of the class. GLFW is not object oriented. Just use it globally from the main function. Passing events to classes is in order, but you can't use class member functions as callbacks to GLFW. You need to write some helper function

extern GAME *pGame;
void eventhandler(int key, int action)
{
    pGame->event(key, action);
}

You may also have the GAME class manage a static list of all instances and provide a static member function, that passes the event to all instances in the list. Or use a singleton (however I think singletons are an anti pattern, and should be avoided).

旧伤慢歌 2024-12-15 16:22:38

虽然我不确定问题是什么(它们真的看起来透明吗?),但代码中明显的第一个点是,您启用了照明,但没有为顶点指定任何法线向量。这些需要告诉 OpenGL 向量面向什么方向(对象的实际表面如何定向,但在每个离散顶点)。

但在立方体的情况下,每个面(四边形)应该有一个法线向量(意味着四边形的每个顶点应该具有相同的法线)。因此,只需在绘制面的四个顶点之前指定适当的法线向量(类似于指定颜色的方式)。在你的情况下,这些应该是(0,0,1)前面,(1,0,0)左边,(0,0,-1)后面,(-1,0,0)右边,( 0,1,0) 为顶部,(0,-1,0) 为底部。

其次,您没有绘制顶面,而是有两个底面(您忘记为顶部设置 y=1)。

第三,最好的做法是对对象的面的顶点进行一致的排序,以便从外部观察时所有面都是逆时针或顺时针方向(实际上您通过这个方向定义外部是什么),但是不是有些是这样,有些是那样。尽管在您当前的配置中这不会造成任何损害,但一旦启用背面剔除(一种非常常见且易于使用的优化技术)或尝试自动计算面法线,您就会遇到问题。

如果这对您来说都是疯狂的谈话,那么请更深入地研究 OpenGL 和计算机图形学。

Although I'm not sure what the question is (do they really appear transparent?), the obvious first spot in your code is, that you enable lighting, but you don't specify any normal vectors for your vertices. These are needed to tell OpenGL what direction a vector faces (how the actual surface of the object is oriented, but at each discrete vertex).

But in your case of a cube, each face (quad) should have a normal vector (meaning each vertex of a quad should have the same normal). So just specify an appropriate normal vector before drawing the four vertices of a face (similar to how you specify the colors). In your case these should be (0,0,1) for the front, (1,0,0) for left, (0,0,-1) for back, (-1,0,0) for right, (0,1,0) for top and (0,-1,0) for bottom.

Second, you don't draw a top face, you have two bottom faces (you forgot to set y=1 for the top).

Third, it is good practice to order the vertices of the faces of an object consistently, so that all faces are oriented all counter-clockwise or all clockwise when viewed from the outside (actually you define what the outside is by this orientation), but not some this way and others that way. Allthough in your current configuration this doesn't do any harm, you will get problems once you enable backface-culling (a very common and easy to use optimization technique) or try to compute the face normals automatically.

If this is all crazy talk for you, then delve a little deeper into OpenGL and computer graphics in general.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文