【问题标题】:Why are my 3D shapes in opengl acting weird?为什么我在 opengl 中的 3D 形状表现得很奇怪?
【发布时间】:2019-07-16 15:29:57
【问题描述】:

我尝试编写一个“引擎”来使用 OpenGL 渲染形状。 这个想法是您可以编写“渲染器”,它们只是渲染形状并将它们添加到引擎类要显示的列表的函数。

所以我添加了一个立方体和一个金字塔(我刚刚从互联网上复制的代码)- 我让它们旋转。

正如您在问题底部的图片中看到的那样 - 形状表现得很奇怪 - 您可以从前面看到形状的背面,等等。

现在,我知道 OpenGL 只是按照我告诉它渲染它们的顺序渲染东西 - 导致首先渲染的东西首先被渲染 - 但我使用了 glDepthFunc 这应该使它的东西呈现为“深度”而不是写作顺序。

#include <GL/glut.h>
#include <iostream>
#include <list>

namespace Graphics
{
    class Engine
    {
    public:
        static void Init();
        static void Display();
        static void Reshape(GLsizei width, GLsizei height);
        static void Timer(int value);
        static bool Run(int argc, char** argv);

        // A renderer is just a method that does stuff and return a boolean
        using renderer_t = bool(*)();

        static void AddRenderer(renderer_t renderer);

    private:
        static std::list<renderer_t> renderers;
    };
}

namespace Graphics
{
    std::list<Engine::renderer_t> Engine::renderers;

    void Engine::Init()
    {
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color to black and opaque
        glClearDepth(1.0f);                   // Set background depth to farthest
        glEnable(GL_DEPTH_TEST);   // Enable depth testing for z-culling
        glDepthFunc(GL_LEQUAL);    // Set the type of depth-test
        glShadeModel(GL_SMOOTH);   // Enable smooth shading
        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  // Nice perspective corrections
    }

    void Engine::Display()
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear color and depth buffers
        glMatrixMode(GL_MODELVIEW);     // To operate on model-view matrix

        for (auto renderer : Engine::renderers)
        {
            if (!renderer())
            {
                std::cout << "A renderer has failed rendering something... :(" << std::endl;
            }
        }

        glutSwapBuffers();  // Swap the front and back frame buffers (double buffering)
    }

    void Engine::Reshape(GLsizei width, GLsizei height)
    {  // GLsizei for non-negative integer
        // Compute aspect ratio of the new window
        if (height == 0) height = 1;                // To prevent divide by 0
        GLfloat aspect = (GLfloat)width / (GLfloat)height;

        // Set the viewport to cover the new window
        glViewport(0, 0, width, height);

        // Set the aspect ratio of the clipping volume to match the viewport
        glMatrixMode(GL_PROJECTION);  // To operate on the Projection matrix
        glLoadIdentity();             // Reset
        // Enable perspective projection with fovy, aspect, zNear and zFar
        gluPerspective(45.0f, aspect, 0.1f, 100.0f);
    }

    void Engine::Timer(int value)
    {
        glutPostRedisplay();      // Post re-paint request to activate display()
        glutTimerFunc(15, Engine::Timer, 0); // next timer call milliseconds later
    }

    bool Engine::Run(int argc, char** argv)
    {
        glutInit(&argc, argv);            // Initialize GLUT
        glutInitDisplayMode(GLUT_DOUBLE); // Enable double buffered mode
        glutInitWindowSize(640, 480);   // Set the window's initial width & height
        glutInitWindowPosition(50, 50); // Position the window's initial top-left corner
        glutCreateWindow("FML");          // Create window with the given title
        glutDisplayFunc(Engine::Display);       // Register callback handler for window re-paint event
        glutReshapeFunc(Engine::Reshape);       // Register callback handler for window re-size event
        Engine::Init();                       // Our own OpenGL initialization
        glutTimerFunc(0, Engine::Timer, 0);     // Call the next display immediately
        glutMainLoop();                 // Enter the infinite event-processing loop
        return true;
    }

    void Engine::AddRenderer(renderer_t renderer)
    {
        Engine::renderers.push_back(renderer);
    }
}

using namespace Graphics;

static bool RenderCube()
{
    static auto angleCube = 0.0f;

    // Render a color-cube consisting of 6 quads with different colors
    glLoadIdentity();                 // Reset the model-view matrix
    glTranslatef(1.5f, 0.0f, -7.0f);  // Move right and into the screen
    glRotatef(angleCube, 1.0f, 1.0f, 1.0f);

    glBegin(GL_QUADS);                // Begin drawing the color cube with 6 quads
    // Top face (y = 1.0f)
    // Define vertices in counter-clockwise (CCW) order with normal pointing out
    glColor3f(0.0f, 1.0f, 0.0f);     // Green
    glVertex3f( 1.0f, 1.0f, -1.0f);
    glVertex3f(-1.0f, 1.0f, -1.0f);
    glVertex3f(-1.0f, 1.0f,  1.0f);
    glVertex3f( 1.0f, 1.0f,  1.0f);

    // Bottom face (y = -1.0f)
    glColor3f(1.0f, 0.5f, 0.0f);     // Orange
    glVertex3f( 1.0f, -1.0f,  1.0f);
    glVertex3f(-1.0f, -1.0f,  1.0f);
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glVertex3f( 1.0f, -1.0f, -1.0f);

    // Front face  (z = 1.0f)
    glColor3f(1.0f, 0.0f, 0.0f);     // Red
    glVertex3f( 1.0f,  1.0f, 1.0f);
    glVertex3f(-1.0f,  1.0f, 1.0f);
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glVertex3f( 1.0f, -1.0f, 1.0f);

    // Back face (z = -1.0f)
    glColor3f(1.0f, 1.0f, 0.0f);     // Yellow
    glVertex3f( 1.0f, -1.0f, -1.0f);
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glVertex3f(-1.0f,  1.0f, -1.0f);
    glVertex3f( 1.0f,  1.0f, -1.0f);

    // Left face (x = -1.0f)
    glColor3f(0.0f, 0.0f, 1.0f);     // Blue
    glVertex3f(-1.0f,  1.0f,  1.0f);
    glVertex3f(-1.0f,  1.0f, -1.0f);
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glVertex3f(-1.0f, -1.0f,  1.0f);

    // Right face (x = 1.0f)
    glColor3f(1.0f, 0.0f, 1.0f);     // Magenta
    glVertex3f(1.0f,  1.0f, -1.0f);
    glVertex3f(1.0f,  1.0f,  1.0f);
    glVertex3f(1.0f, -1.0f,  1.0f);
    glVertex3f(1.0f, -1.0f, -1.0f);
    glEnd();

    angleCube += 0.2f;

    return true;
}

static bool RenderPyramid()
{
    static auto anglePyramid = 0.0f;

    // Render a pyramid consists of 4 triangles
    glLoadIdentity();                  // Reset the model-view matrix
    glTranslatef(-1.5f, 0.0f, -6.0f);  // Move left and into the screen
    glRotatef(anglePyramid, 1.0f, 1.0f, 1.0f);

    glBegin(GL_TRIANGLES);           // Begin drawing the pyramid with 4 triangles
    // Front
    glColor3f(1.0f, 0.0f, 0.0f);     // Red
    glVertex3f( 0.0f, 1.0f, 0.0f);
    glColor3f(0.0f, 1.0f, 0.0f);     // Green
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glColor3f(0.0f, 0.0f, 1.0f);     // Blue
    glVertex3f(1.0f, -1.0f, 1.0f);

    // Right
    glColor3f(1.0f, 0.0f, 0.0f);     // Red
    glVertex3f(0.0f, 1.0f, 0.0f);
    glColor3f(0.0f, 0.0f, 1.0f);     // Blue
    glVertex3f(1.0f, -1.0f, 1.0f);
    glColor3f(0.0f, 1.0f, 0.0f);     // Green
    glVertex3f(1.0f, -1.0f, -1.0f);

    // Back
    glColor3f(1.0f, 0.0f, 0.0f);     // Red
    glVertex3f(0.0f, 1.0f, 0.0f);
    glColor3f(0.0f, 1.0f, 0.0f);     // Green
    glVertex3f(1.0f, -1.0f, -1.0f);
    glColor3f(0.0f, 0.0f, 1.0f);     // Blue
    glVertex3f(-1.0f, -1.0f, -1.0f);

    // Left
    glColor3f(1.0f,0.0f,0.0f);       // Red
    glVertex3f( 0.0f, 1.0f, 0.0f);
    glColor3f(0.0f,0.0f,1.0f);       // Blue
    glVertex3f(-1.0f,-1.0f,-1.0f);
    glColor3f(0.0f,1.0f,0.0f);       // Green
    glVertex3f(-1.0f,-1.0f, 1.0f);
    glEnd();   // Done drawing the pyramid

    anglePyramid += 0.25f;

    return true;
}

int main(int argc, char** argv)
{
    Engine::AddRenderer(RenderCube);
    Engine::AddRenderer(RenderPyramid);
    return Engine::Run(argc, argv);
}

生成的旋转形状的图像

正如您所看到的,这些形状表现得很奇怪 - 即使我使用了 glDepthFunc,您也可以看到它们的背面。

【问题讨论】:

  • 您的窗口或帧缓冲区是否有深度缓冲区?更好的说法是:你试过glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);
  • 刚刚用 VS 2017 编译,看起来很完美,和你的不一样。使用 freeglut 3.0.0-rc2 和 NVIDIA Quadro 显卡。
  • @Trantor:如果您不请求深度缓冲区,并非所有操作系统/驱动程序都会为您提供深度缓冲区; Windows 10 w/AMD 给了我一个深度缓冲区,Linux 和 Mesa 的软件渲染器没有。
  • 是的,他绝对应该使用正确的 GLUT 标志。
  • 是的,我忘了添加那个标志——我的错。感谢您的帮助:)

标签: c++ opengl 3d glut freeglut


【解决方案1】:

除非您特别要求,否则操作系统/驱动程序没有义务向您提供任何深度缓冲区位;零位,无深度缓冲。

正如@BDL 指出的那样,对于 GLUT,这意味着将 GLUT_DEPTH 与您的 glutInitDisplayMode() 参数进行 ORing。

【讨论】:

    猜你喜欢
    • 2012-06-29
    • 2021-10-11
    • 2018-09-09
    • 2014-07-03
    • 1970-01-01
    • 2014-02-05
    • 2020-05-30
    • 2023-01-07
    • 2015-09-14
    相关资源
    最近更新 更多