简单的彩色3D棱镜

时间:2013-10-02 15:39:38

标签: c++ opengl 3d sfml opengl-1.x

我开始学习OpenGL,我正在使用它与SFML 2.1来获取窗口,加载图像等。但我有一个简单的棱镜问题。面部是透明的,看起来很糟糕:/我正在看教程,但我不知道我的代码有什么问题......你能帮助我吗?我读到这是Z-Buffering的问题。如何解决?

这是我的代码:

#include <iostream>
#include <stdio.h>
#include <cmath>
#include <SFML/OpenGL.hpp>
#include <SFML/Graphics.hpp>

using namespace std;

void drawCube (float x, float y, float z, float width, float height, GLuint Texture);

int main()
{
    // Window
    sf::RenderWindow window(sf::VideoMode(800, 600), "OpenGL", sf::Style::Default, sf::ContextSettings(32));

    // Camera
    GLdouble eyex = 0;
    GLdouble eyey = 0;
    GLdouble eyez = 2575;

    GLuint Texture = 0;
    {
        sf::Image Image;
        if (!Image.loadFromFile("background.png"))
            return EXIT_FAILURE;
        glGenTextures(1, &Texture);
        glBindTexture(GL_TEXTURE_2D, Texture);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Image.getSize().x, Image.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, Image.getPixelsPtr());
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    }

    // Main loop
    while (window.isOpen())
    {
        // Checking events
        sf::Event event;
        while (window.pollEvent(event))
        {
            // Close the window
            if (event.type == sf::Event::Closed)
                window.close();

            // Resize the window
            if (event.type == sf::Event::Resized)
                glViewport(0, 0, event.size.width, event.size.height);
        }

        // Close the window
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
            window.close();

        // Clear the window
        window.clear(sf::Color::White);

        // Viewport
        glViewport( 0, 0, window.getSize().x, window.getSize().y );

        // Matrix Mode
        glMatrixMode( GL_PROJECTION );

        // Matrix Load Identity
        glLoadIdentity();

        // Perspective
        gluPerspective(window.getSize().y/45.0, 1.0f*window.getSize().x/window.getSize().y, 0.0f, 100.0f);

        // Clear color buffer
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Set Matrix Mode
        glMatrixMode( GL_MODELVIEW );

        // Matrix Load Identity
        glLoadIdentity();

        // Change camera position
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
            eyey -= 0.1f;
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
            eyey += 0.1f;
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
            eyex -= 0.1f;
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
            eyex += 0.1f;

        printf("%f %f\n", eyex, eyey);

        // Set the camera
        gluLookAt( eyex, -eyey, eyez, eyex, -eyey, 0, 0, 1, 0 );

        // RECTANGLE
        /*
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, Texture);
        glColor4f( 0.0, 1.0, 0.0, 1.0f );
        glScalef(1,-1,1);
        glBegin(GL_QUADS);
            glTexCoord2f(0.0f, 0.0f); glVertex3f(100, 200, 0.0f);
            glTexCoord2f(3.333333f, 0.0f); glVertex3f(200, 200, 0.0f);
            glTexCoord2f(3.333333f, 3.333333f); glVertex3f(200, 300, 0.0f);
            glTexCoord2f(0.0f, 3.333333f); glVertex3f(100, 300, 0.0f);
        glEnd();
        glDisable(GL_TEXTURE_2D);
        */

        // Set color drawing
        glColor3f( 0.0, 0.0, 0.0 );
        glScalef(1,-1,1);

        // Draw cube
        drawCube(0.0f, 0.0f, 1000.0f, 100.0f, 100.0f, Texture);

        // Flush the scene
        glFlush();

        // Update the window
        window.display();
    }
    return 0;
}

void drawCube (float x, float y, float z, float width, float height, GLuint Texture)
{
    width /= 2;
    height /= 2;
    x += width;
    y += height;
    y = -y;
    width = -width;

    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, Texture);
    glBegin(GL_QUADS);
        glColor3f(1.0f, 0.0f, 0.0f);
      // Top face
      glVertex3f( x + width, y + height, 0.0f);
      glVertex3f( x - width, y + height, 0.0f);
      glVertex3f( x - width, y + height, z);
      glVertex3f( x + width, y + height, z);

        glColor3f(1.0f, 1.0f, 0.0f);
      // Left face
      glVertex3f( x - width, y + height, z);
      glVertex3f( x - width, y + height, 0.0f);
      glVertex3f( x - width, y - height, 0.0f);
      glVertex3f( x - width, y - height, z);

        glColor3f(0.0f, 1.0f, 1.0f);
      // Right face
      glVertex3f( x + width, y + height, 0.0f);
      glVertex3f( x + width, y + height, z);
      glVertex3f( x + width, y - height, z);
      glVertex3f( x + width, y - height, 0.0f);

        glColor3f(0.0f, 0.0f, 0.0f);
      // Bottom face
      glVertex3f( x + width, y - height, 0.0f);
      glVertex3f( x - width, y - height, 0.0f);
      glVertex3f( x - width, y - height, z);
      glVertex3f( x + width, y - height, z);

      glColor3f(0.0f, 1.0f, 0.0f);
      // Front face
      glVertex3f( x + width, y + height, z);
      glVertex3f( x - width, y + height, z);
      glVertex3f( x - width, y - height, z);
      glVertex3f( x + width, y - height, z);
   glEnd();
   glDisable(GL_TEXTURE_2D);
}

这是我的结果:

1 个答案:

答案 0 :(得分:6)

你是对的,这个问题与Z-Buffering有关。

我在您的代码中看到了两个问题:

  1. 所有硬件均不支持32位深度缓冲区

    • 24位深度+ 8位模板是一种更兼容的格式,足以满足您的简单应用需求。可以使用sf::ContextSettings (24, 8)请求此操作。

  2. 默认情况下,在OpenGL中禁用深度测试

    • 即使您的硬件支持32位深度缓冲区,单独分配深度缓冲区也是不够的。您必须在创建glEnable (GL_DEPTH_TEST)
    • 后添加对sf::RenderWindow的来电,自行启用它
  3. 更新

    我第一次浏览你的代码时完全错过了这个:

    // Perspective
    gluPerspective(
      window.getSize().y/45.0, 1.0f*window.getSize().x/window.getSize().y,
        0.0f, 100.0f);
        ~~~~
    

    您在透视投影矩阵中使用0.0作为近平面。这是一件非常糟糕的事情,它会彻底搞砸你的深度范围,这可能会影响你在评论中包含的两个截图。

    两个平面必须为正值。如果gluPerspective (...)实际上是OpenGL API的一部分,则在这些情况下会产生GL_INVALID_VALUE错误。另请注意,近平面和远平面之间的距离将决定深度缓冲区的整体精度(这在gluPerspective的文档中有所讨论。)

    要纠正此问题,请使用与近平面非常接近但不完全0.0的值(即0.1)。