我尝试编写了一个使用OpenGL渲染形状的“引擎”。
这个想法是你可以编写“渲染器”,它们只是渲染形状并将它们添加到Engine类中以显示。
所以我添加了一个立方体和一个金字塔(它们的代码我刚从互联网上复制下来) - 然后我让它们旋转。
正如您在问题底部的图片中所看到的那样-形状表现得很奇怪-您可以从前面看到形状的背面等。
现在,我理解OpenGL只是按照我告诉它们要呈现的顺序进行呈现-导致先编写的东西先被呈现-但我使用了glDepthFunc应该使得它呈现的时候按照“深度”而不是书写顺序。
所以我添加了一个立方体和一个金字塔(它们的代码我刚从互联网上复制下来) - 然后我让它们旋转。
正如您在问题底部的图片中所看到的那样-形状表现得很奇怪-您可以从前面看到形状的背面等。
现在,我理解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);
吗? - BDL