返回

OpenGL--渲染图形实战

IOS



写在前面

本文将介绍如何将固定位置上的顶点数据以6种不同的图元展示,并用键盘控制视图变换。具体代码详见:https://github.com/cjf564558856/OpenGLDemo

1. 渲染

在OpenGL中,渲染是一个将对象从模型空间变换到屏幕的过程。它包含几个步骤:

  1. 模型变换 :将模型从模型空间变换到世界空间。
  2. 视图变换 :将世界空间中的对象变换到相机空间。
  3. 投影变换 :将相机空间中的对象变换到裁剪空间。
  4. 视口变换 :将裁剪空间中的对象变换到屏幕空间。

这四个变换都由矩阵表示,这些矩阵可以通过OpenGL函数glMatrixMode()glLoadIdentity()glTranslatef()glRotatef()glScalef()等来设置。

// 设置模型变换矩阵
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -10.0f); // 将模型向后平移10个单位

// 设置视图变换矩阵
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (float)width / (float)height, 0.1f, 100.0f); // 设置透视投影

// 设置视口变换矩阵
glViewport(0, 0, width, height); // 设置视口大小

2. 图元

图元是OpenGL用来表示几何形状的基本单位。OpenGL支持多种不同的图元,包括:

  • 线
  • 三角形
  • 四边形
  • 多边形

图元可以使用OpenGL函数glBegin()glVertex3f()glEnd()等来绘制。

// 绘制一个三角形
glBegin(GL_TRIANGLES);
glVertex3f(-1.0f, -1.0f, 0.0f); // 三角形的第一个顶点
glVertex3f(1.0f, -1.0f, 0.0f); // 三角形的第二个顶点
glVertex3f(0.0f, 1.0f, 0.0f); // 三角形的第三个顶点
glEnd();

3. 键盘控制

键盘控制是OpenGL中控制视图变换的常用方法。OpenGL提供了几个函数来处理键盘输入,包括:

  • glutKeyboardFunc():注册键盘回调函数。
  • glutSpecialFunc():注册特殊键回调函数。
  • glutMainLoop():进入OpenGL主循环。

在键盘回调函数中,我们可以根据键盘输入来更新视图变换矩阵,从而改变观察者的视角。

void keyboard(unsigned char key, int x, int y)
{
    switch (key)
    {
    case 'w':
        glTranslatef(0.0f, 0.1f, 0.0f); // 向上平移
        break;
    case 's':
        glTranslatef(0.0f, -0.1f, 0.0f); // 向下平移
        break;
    case 'a':
        glTranslatef(-0.1f, 0.0f, 0.0f); // 向左平移
        break;
    case 'd':
        glTranslatef(0.1f, 0.0f, 0.0f); // 向右平移
        break;
    case 'q':
        glRotatef(1.0f, 1.0f, 0.0f, 0.0f); // 绕X轴旋转
        break;
    case 'e':
        glRotatef(-1.0f, 1.0f, 0.0f, 0.0f); // 绕X轴旋转
        break;
    }

    glutPostRedisplay(); // 重新绘制场景
}

4. 完整代码

#include <GL/glut.h>

// 定义窗口宽高
const int width = 800;
const int height = 600;

// 定义键盘回调函数
void keyboard(unsigned char key, int x, int y)
{
    switch (key)
    {
    case 'w':
        glTranslatef(0.0f, 0.1f, 0.0f); // 向上平移
        break;
    case 's':
        glTranslatef(0.0f, -0.1f, 0.0f); // 向下平移
        break;
    case 'a':
        glTranslatef(-0.1f, 0.0f, 0.0f); // 向左平移
        break;
    case 'd':
        glTranslatef(0.1f, 0.0f, 0.0f); // 向右平移
        break;
    case 'q':
        glRotatef(1.0f, 1.0f, 0.0f, 0.0f); // 绕X轴旋转
        break;
    case 'e':
        glRotatef(-1.0f, 1.0f, 0.0f, 0.0f); // 绕X轴旋转
        break;
    }

    glutPostRedisplay(); // 重新绘制场景
}

// 定义显示函数
void display()
{
    // 清除颜色缓冲区
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // 设置模型变换矩阵
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0.0f, 0.0f, -10.0f); // 将模型向后平移10个单位

    // 设置视图变换矩阵
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0f, (float)width / (float)height, 0.1f, 100.0f); // 设置透视投影

    // 设置视口变换矩阵
    glViewport(0, 0, width, height); // 设置视口大小

    // 绘制一个三角形
    glBegin(GL_TRIANGLES);
    glVertex3f(-1.0f, -1.0f, 0.0f); // 三角形的第一个顶点
    glVertex3f(1.0f, -1.0f, 0.0f); // 三角形的第二个顶点
    glVertex3f(0.0f, 1.0f, 0.0f); // 三角形的第三个顶点
    glEnd();

    // 交换前后缓冲区
    glutSwapBuffers();
}

// 定义主函数
int main(int argc, char** argv)
{
    // 初始化GLUT
    glutInit(&argc, argv);

    // 设置显示模式
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);

    // 设置窗口大小和位置
    glutInitWindowSize(width, height);
    glutInitWindowPosition(100, 100);

    // 创建窗口
    glutCreateWindow("OpenGL Demo");

    // 注册键盘回调函数
    glutKeyboardFunc(keyboard);

    // 注册显示函数
    glutDisplayFunc(display);

    // 进入GLUT主循环
    glutMainLoop();

    return 0;
}