Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ OpenGL/GLFW看起来是透明的_C++_Opengl_Graphics_3d_Glfw - Fatal编程技术网

C++ OpenGL/GLFW看起来是透明的

C++ OpenGL/GLFW看起来是透明的,c++,opengl,graphics,3d,glfw,C++,Opengl,Graphics,3d,Glfw,使用opengl和glfw绘制简单立方体时,立方体的面看起来是透明的。 这是密码。使用箭头键旋转。我刚刚在我的程序中封装到一个类中。 使用Visual C++ 2010版.< /P> #include "GAME.h" using namespace std; GAME::GAME() { glfwInit(); glEnable(GL_DEPTH_TEST); glEnable(GL_COLOR_MATERIAL); glEnable(GL_LIGHTING)

使用opengl和glfw绘制简单立方体时,立方体的面看起来是透明的。 这是密码。使用箭头键旋转。我刚刚在我的程序中封装到一个类中。 使用Visual C++ 2010版.< /P>
#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;
}

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

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

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

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


如果这对你来说都是疯狂的话题,那就深入研究一下OpenGL和计算机图形学吧。

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

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

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

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


如果这对你来说都是些疯狂的话题,那就深入研究一下OpenGL和计算机图形学吧。

我很抱歉地告诉你,你的代码在几个层次上都有漏洞。让我为您详细介绍一下:

#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
如果是类
GAME
的成员函数,并且除非这是静态成员函数,否则不能将类成员函数用作回调函数,尤其是对不知道类的C库。它如何知道事件函数属于哪个实例?C++没有闭包或委托的概念,这是需要的(其他语言也是如此)。

现在出现的是一个典型的新手误解:

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只会弄乱矩阵堆栈,但每个sane OpenGL渲染函数都会初始化所有状态,因此在开始时会有一些sane值

在事件处理程序中要做的是将所有输入累积到变量中,稍后在图形代码中使用这些变量来设置和控制渲染

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\u宽度,win\u高度)

现在这真的很好!在渲染函数中设置投影矩阵。干得好,坚持这个模式

更新但下一行错误:

    gluLookAt(0, 0, 3.0, 0, 0, 0, 0.0, 1.0, 0.0);
gluLookAt
是一个在modelview矩阵上执行的功能。modelview矩阵负责在世界空间中放置模型,并将世界与视图对齐,因此转换为
模型→世界,世界→查看
,您可以减少中间的
世界
步骤,使其成为唯一的
模型→查看

    glMatrixMode(GL_MODELVIEW);
这里您将调用
glLoadIdentity();gluLookAt(…)。现在应该很明显了,为什么要做矩阵m
    gluLookAt(0, 0, 3.0, 0, 0, 0, 0.0, 1.0, 0.0);
    glMatrixMode(GL_MODELVIEW);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    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();
    glfwSwapBuffers();
    return 0;
}
extern GAME *pGame;
void eventhandler(int key, int action)
{
    pGame->event(key, action);
}