OpenGL学习(二)
三种变换
- 模型变换:改变物体自身的位置、旋转、缩放(比如让立方体向左移动、旋转)。
- 视图变换:改变观察角度(相机位置和朝向),不改变物体本身,只改变 “从哪里看”。
- 投影变换:定义画面的透视效果(比如近大远小),而视图变换只决定观察方向。
代码解释
一、主函数
// 主函数
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(800, 600);
glutCreateWindow("OpenGL 矩阵变换示例");
init();
// 注册回调函数
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutTimerFunc(0, timer, 0);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
对比上节代码,区别在于
1、glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
开启深度缓存的作用在于:每当绘制新像素时,OpenGL 会自动比较新像素与已有像素的深度值,如果新像素更近(深度值更小),则更新颜色缓冲区和深度缓冲区(显示新像素);如果新像素更远,则忽略该像素(不覆盖已有像素)。
2、glutReshapeFunc(reshape);
当窗口被拉伸、缩放或首次创建时,FreeGLUT 会自动调用这个函数。
由于我们将在该节中使用透视投影,代码如下,透视投影与窗口的宽高比密切相关,若窗口大小改变而不及时去更改width和height的值,可能导致图像投影后失真。
gluPerspective(45.0f, (float)width / (float)height, 0.1f, 100.0f);
可是,问题是,为什么窗口会改变呢?我们并不会在代码中去更改窗口大小,但是用户可以通过拉伸窗口更改其宽高。为了防止图像失真,需要主动调用。
3、glutTimerFunc(0, timer, 0);
如果不注册 glutTimerFunc(0, timer, 0);,就无法自动更新场景状态和触发重绘,动画会静止不动(除非通过用户交互手动触发)。
二、display函数
// 显示回调函数
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除颜色和深度缓冲区
// 重置模型视图矩阵
glLoadIdentity();
// -------------------------- 视图变换 --------------------------
// 参数:相机位置(x,y,z)、目标点(x,y,z)、上方向向量(x,y,z)
gluLookAt(0.0f, 1.0f, cameraZ, // 相机位置(可以通过按键调整z值)
0.0f, 0.0f, 0.0f, // 目标点(看向原点)
0.0f, 1.0f, 0.0f); // 上方向(Y轴为上)
// -------------------------- 模型变换 --------------------------
glRotatef(rotationAngle, 1.0f, 1.0f, 0.0f); // 绕(1,1,0)轴旋转
glTranslatef(1.0f, 0.0f, 0.0f); // 沿X轴平移
// 绘制第一个立方体
drawCube();
// 对第二个立方体应用不同的模型变换
glPushMatrix(); // 保存当前矩阵状态
glRotatef(rotationAngle, 0.0f, 1.0f, 0.0f); // 绕Y轴旋转
glTranslatef(-2.0f, 0.0f, 0.0f); // 沿X轴负方向平移
glScalef(0.5f, 0.5f, 0.5f); // 缩小一半
drawCube(); // 绘制第二个立方体
glPopMatrix(); // 恢复矩阵状态
glutSwapBuffers(); // 交换缓冲区
}
这里主要介绍三点:
1、glLoadIdentity()
用于矩阵初始化的核心函数,作用是将「当前活跃的矩阵」重置为单位矩阵。
为什么需要重置为单位矩阵:
OpenGL 是一个 “状态机”,矩阵运算具有累积性—— 每次调用变换函数(如 glRotate、glTranslate、glScale),都是将当前矩阵与新的变换矩阵相乘,并将结果作为新的当前矩阵。如果不重置矩阵,新的变换会叠加在之前的变换上,导致结果不可控。
2、 gluLookAt(0.0f, 1.0f, cameraZ, // 相机位置(可以通过按键调整z值)
0.0f, 0.0f, 0.0f, // 目标点(看向原点)
0.0f, 1.0f, 0.0f); // 上方向(Y轴为上)
为什么需要定义上方向:
想象你手里拿着一个相机,镜头对准前方的一棵树(目标点):
- 当你水平握持相机时(镜头朝前,相机顶部朝上),拍出来的照片是正的(地平线水平,树干垂直);
- 当你倾斜握持相机时(镜头仍对准树,但相机顶部朝左或朝右),拍出来的照片会是歪的(地平线倾斜,树干歪斜)。
这里的 “相机顶部朝向” 就是现实中的 “上方向”—— 即使镜头对准同一个目标,上方向不同,最终画面的 “正立状态” 也会不同。
3、glutSwapBuffers()
核心作用是交换双缓冲模式下的前后缓冲区,让后台缓冲区中绘制完成的完整画面显示到屏幕上,从而避免绘制过程中的闪烁。当 display 函数中的所有绘制操作(画点、线、立方体等)完成后,glutSwapBuffers() 会执行一次 “缓冲区交换”:
- 原本的后台缓冲区(已完成当前帧绘制)变成前台缓冲区,直接显示到屏幕上;
- 原本的前台缓冲区变成新的后台缓冲区,为下一帧绘制做准备。
这个过程瞬间完成,用户看不到中间绘制步骤,只会看到完整的画面,从而消除闪烁。
三、reshape函数
// 窗口大小变化回调函数
void reshape(int width, int height) {
glViewport(0, 0, width, height); // 设置视口,占满整个窗口
// 切换到投影矩阵模式
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // 重置投影矩阵
// -------------------------- 投影变换 --------------------------
// 使用透视投影
// 参数:视野角度、宽高比、近平面距离、远平面距离
float aspectRatio = (float)width / (float)height;
gluPerspective(45.0f, aspectRatio, 0.1f, 100.0f);
// 切换回模型视图矩阵模式
glMatrixMode(GL_MODELVIEW);
}
矩阵模式切换:
-
投影矩阵(
GL_PROJECTION):专门负责 “投影变换”—— 决定 3D 场景如何被 “投影” 到 2D 屏幕上(如透视投影的 “近大远小” 效果)。在reshape函数中,我们需要设置透视投影参数(gluPerspective),因此必须先切换到GL_PROJECTION模式,否则这些参数会错误地应用到其他矩阵上。 -
模型视图矩阵(
GL_MODELVIEW):专门负责 “模型变换”(物体的旋转、平移、缩放)和 “视图变换”(相机的位置和朝向)。绝大多数绘制逻辑(如display函数中的旋转、gluLookAt视图变换)都需要在这个模式下进行,因此设置完投影矩阵后,必须切换回GL_MODELVIEW模式,确保后续的模型 / 视图变换正确生效。
透视投影:
核心作用是让 3D 场景在 2D 屏幕上呈现出符合人类视觉习惯的真实效果,通过近大远小的规律模拟深度感,完成 3D 到 2D 的坐标转换,限定可见区域优化效率,同时保证画面比例正确。
三、timer函数
// 定时器回调函数,用于动画效果
void timer(int value) {
rotationAngle += 1.0f; // 增加旋转角度
if (rotationAngle >= 360.0f) {
rotationAngle = 0.0f;
}
glutPostRedisplay(); // 标记窗口需要重绘
glutTimerFunc(16, timer, 0); // 约60fps
}
四、键盘回调函数
// 键盘回调函数
void keyboard(unsigned char key, int x, int y) {
switch (key) {
case 27: // ESC键退出
exit(0);
break;
case '+': // 相机靠近
cameraZ -= 0.5f;
if (cameraZ < 1.0f) cameraZ = 1.0f;
break;
case '-': // 相机远离
cameraZ += 0.5f;
break;
}
glutPostRedisplay(); // 重绘
}
代码汇总
#include <GL/glut.h>
#include <GL/glu.h>
#include <math.h>
// 全局变量
float rotationAngle = 0.0f; // 旋转角度
float cameraZ = 5.0f; // 相机Z轴位置
// 初始化函数
void init() {
glClearColor(0.1f, 0.1f, 0.1f, 1.0f); // 背景色:深灰色
glEnable(GL_DEPTH_TEST); // 启用深度测试,处理遮挡关系
glEnable(GL_COLOR_MATERIAL); // 启用颜色材质,使颜色生效
}
// 绘制彩色立方体
void drawCube() {
glBegin(GL_QUADS); // 使用四边形绘制立方体的6个面
// 前面(红色)
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(-0.5f, -0.5f, 0.5f);
glVertex3f(0.5f, -0.5f, 0.5f);
glVertex3f(0.5f, 0.5f, 0.5f);
glVertex3f(-0.5f, 0.5f, 0.5f);
// 后面(绿色)
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(-0.5f, -0.5f, -0.5f);
glVertex3f(-0.5f, 0.5f, -0.5f);
glVertex3f(0.5f, 0.5f, -0.5f);
glVertex3f(0.5f, -0.5f, -0.5f);
// 右面(蓝色)
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.5f, -0.5f, -0.5f);
glVertex3f(0.5f, 0.5f, -0.5f);
glVertex3f(0.5f, 0.5f, 0.5f);
glVertex3f(0.5f, -0.5f, 0.5f);
// 左面(黄色)
glColor3f(1.0f, 1.0f, 0.0f);
glVertex3f(-0.5f, -0.5f, -0.5f);
glVertex3f(-0.5f, -0.5f, 0.5f);
glVertex3f(-0.5f, 0.5f, 0.5f);
glVertex3f(-0.5f, 0.5f, -0.5f);
// 上面(青色)
glColor3f(0.0f, 1.0f, 1.0f);
glVertex3f(-0.5f, 0.5f, -0.5f);
glVertex3f(-0.5f, 0.5f, 0.5f);
glVertex3f(0.5f, 0.5f, 0.5f);
glVertex3f(0.5f, 0.5f, -0.5f);
// 下面(紫色)
glColor3f(1.0f, 0.0f, 1.0f);
glVertex3f(-0.5f, -0.5f, -0.5f);
glVertex3f(0.5f, -0.5f, -0.5f);
glVertex3f(0.5f, -0.5f, 0.5f);
glVertex3f(-0.5f, -0.5f, 0.5f);
glEnd();
}
// 显示回调函数
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除颜色和深度缓冲区
// 重置模型视图矩阵
glLoadIdentity();
// -------------------------- 视图变换 --------------------------
// 参数:相机位置(x,y,z)、目标点(x,y,z)、上方向向量(x,y,z)
gluLookAt(0.0f, 1.0f, cameraZ, // 相机位置(可以通过按键调整z值)
0.0f, 0.0f, 0.0f, // 目标点(看向原点)
0.0f, 1.0f, 0.0f); // 上方向(Y轴为上)
// -------------------------- 模型变换 --------------------------
glRotatef(rotationAngle, 1.0f, 1.0f, 0.0f); // 绕(1,1,0)轴旋转
glTranslatef(1.0f, 0.0f, 0.0f); // 沿X轴平移
// 绘制第一个立方体
drawCube();
// 对第二个立方体应用不同的模型变换
glPushMatrix(); // 保存当前矩阵状态
glRotatef(rotationAngle, 0.0f, 1.0f, 0.0f); // 绕Y轴旋转
glTranslatef(-2.0f, 0.0f, 0.0f); // 沿X轴负方向平移
glScalef(0.5f, 0.5f, 0.5f); // 缩小一半
drawCube(); // 绘制第二个立方体
glPopMatrix(); // 恢复矩阵状态
glutSwapBuffers(); // 交换缓冲区
}
// 窗口大小变化回调函数
void reshape(int width, int height) {
glViewport(0, 0, width, height); // 设置视口,占满整个窗口
// 切换到投影矩阵模式
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // 重置投影矩阵
// -------------------------- 投影变换 --------------------------
// 使用透视投影
// 参数:视野角度、宽高比、近平面距离、远平面距离
float aspectRatio = (float)width / (float)height;
gluPerspective(45.0f, aspectRatio, 0.1f, 100.0f);
// 切换回模型视图矩阵模式
glMatrixMode(GL_MODELVIEW);
}
// 定时器回调函数,用于动画效果
void timer(int value) {
rotationAngle += 1.0f; // 增加旋转角度
if (rotationAngle >= 360.0f) {
rotationAngle = 0.0f;
}
glutPostRedisplay(); // 标记窗口需要重绘
glutTimerFunc(16, timer, 0); // 约60fps
}
// 键盘回调函数
void keyboard(unsigned char key, int x, int y) {
switch (key) {
case 27: // ESC键退出
exit(0);
break;
case '+': // 相机靠近
cameraZ -= 0.5f;
if (cameraZ < 1.0f) cameraZ = 1.0f;
break;
case '-': // 相机远离
cameraZ += 0.5f;
break;
}
glutPostRedisplay(); // 重绘
}
// 主函数
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(800, 600);
glutCreateWindow("OpenGL 矩阵变换示例");
init();
// 注册回调函数
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutTimerFunc(0, timer, 0);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}

第一个任务完成,我们接下来看看第二个任务:利用函数指定颜色模式。
首先我们先定义三种颜色模式。
typedef enum {
COLOR_MODE_COLORFUL, // 彩色模式(默认)
COLOR_MODE_GRAYSCALE, // 灰度模式(无彩色,仅黑白灰)
COLOR_MODE_MONO // 单色模式(所有面用同一种颜色)
} ColorMode;
对具体颜色模式进行处理。
ColorMode currentColorMode = COLOR_MODE_COLORFUL; // 当前激活的颜色模式
float monoColor[3] = { 1.0f, 0.5f, 0.0f }; // 单色模式的预设颜色(初始为橙色)
void setCurrentColor(float r, float g, float b) {
float gray = 0.0f; // 提前初始化,避免case跳过问题
switch (currentColorMode) {
case COLOR_MODE_COLORFUL:
// 彩色模式:直接使用原始颜色
glColor3f(r, g, b);
break;
case COLOR_MODE_GRAYSCALE:
// 灰度模式:计算并使用灰度值
gray = 0.299f * r + 0.587f * g + 0.114f * b;
glColor3f(gray, gray, gray);
break;
case COLOR_MODE_MONO:
// 单色模式:使用统一预设颜色
glColor3f(monoColor[0], monoColor[1], monoColor[2]);
break;
}
}
对键盘函数进行改进,加入颜色按键选择。
// -------------------------- 新增:颜色模式切换 --------------------------
case '1': // 1键:切换到彩色模式
currentColorMode = COLOR_MODE_COLORFUL;
glutSetWindowTitle("OpenGL 矩阵变换示例 - 彩色模式");
printf("当前颜色模式:彩色模式\n");
break;
case '2': // 2键:切换到灰度模式
currentColorMode = COLOR_MODE_GRAYSCALE;
glutSetWindowTitle("OpenGL 矩阵变换示例 - 灰度模式");
printf("当前颜色模式:灰度模式\n");
break;
case '3': // 3键:切换到单色模式
currentColorMode = COLOR_MODE_MONO;
glutSetWindowTitle("OpenGL 矩阵变换示例 - 单色模式(橙色)");
printf("当前颜色模式:单色模式(可按4/5/6调整颜色)\n");
break;
// 单色模式下调整颜色(4=加红,5=加绿,6=加蓝)
case '4':
if (currentColorMode == COLOR_MODE_MONO) {
monoColor[0] = (monoColor[0] + 0.1f) > 1.0f ? 1.0f : monoColor[0] + 0.1f;
glutSetWindowTitle("OpenGL 矩阵变换示例 - 单色模式(红+)");
printf("单色模式:红色分量=%.1f\n", monoColor[0]);
}
break;
case '5':
if (currentColorMode == COLOR_MODE_MONO) {
monoColor[1] = (monoColor[1] + 0.1f) > 1.0f ? 1.0f : monoColor[1] + 0.1f;
glutSetWindowTitle("OpenGL 矩阵变换示例 - 单色模式(绿+)");
printf("单色模式:绿色分量=%.1f\n", monoColor[1]);
}
break;
case '6':
if (currentColorMode == COLOR_MODE_MONO) {
monoColor[2] = (monoColor[2] + 0.1f) > 1.0f ? 1.0f : monoColor[2] + 0.1f;
glutSetWindowTitle("OpenGL 矩阵变换示例 - 单色模式(蓝+)");
printf("单色模式:蓝色分量=%.1f\n", monoColor[2]);
}
break;
}
glutMainLoop()调用后, 启动了一个 “无限事件循环”,不断触发回调函数(如 display、timer、keyboard)重复执行。
代码汇总为
#include <GL/glut.h>
#include <GL/glu.h>
#include <math.h>
#include <stdio.h>
// 全局变量
float rotationAngle = 0.0f; // 旋转角度
float cameraZ = 5.0f; // 相机Z轴位置
// -------------------------- 新增:颜色模式相关定义 --------------------------
// 1. 颜色模式枚举(定义可支持的颜色模式)
typedef enum {
COLOR_MODE_COLORFUL, // 彩色模式(默认)
COLOR_MODE_GRAYSCALE, // 灰度模式(无彩色,仅黑白灰)
COLOR_MODE_MONO // 单色模式(所有面用同一种颜色)
} ColorMode;
ColorMode currentColorMode = COLOR_MODE_COLORFUL; // 当前激活的颜色模式
float monoColor[3] = { 1.0f, 0.5f, 0.0f }; // 单色模式的预设颜色(初始为橙色)
// 2. 统一颜色处理函数(根据当前颜色模式,处理原始颜色并设置)
// 参数:r/g/b - 物体面的原始颜色;返回:根据模式处理后的颜色
void setCurrentColor(float r, float g, float b) {
float gray = 0.0f; // 提前初始化,避免case跳过问题
switch (currentColorMode) {
case COLOR_MODE_COLORFUL:
// 彩色模式:直接使用原始颜色
glColor3f(r, g, b);
break;
case COLOR_MODE_GRAYSCALE:
// 灰度模式:计算并使用灰度值
gray = 0.299f * r + 0.587f * g + 0.114f * b;
glColor3f(gray, gray, gray);
break;
case COLOR_MODE_MONO:
// 单色模式:使用统一预设颜色
glColor3f(monoColor[0], monoColor[1], monoColor[2]);
break;
}
}
// 初始化函数(原有逻辑不变,新增颜色模式默认提示)
void init() {
glClearColor(0.1f, 0.1f, 0.1f, 1.0f); // 背景色:深灰色
glEnable(GL_DEPTH_TEST); // 启用深度测试,处理遮挡关系
glEnable(GL_COLOR_MATERIAL); // 启用颜色材质,使颜色生效
printf("初始化完成!当前颜色模式:彩色模式\n");
printf("操作提示:1=彩色 2=灰度 3=单色 4=单色+红 5=单色+绿 6=单色+蓝 ESC=退出\n");
}
// 绘制立方体(修改:用setCurrentColor替代直接glColor3f)
void drawCube() {
glBegin(GL_QUADS); // 使用四边形绘制立方体的6个面
// 前面(原始红色)
setCurrentColor(1.0f, 0.0f, 0.0f);
glVertex3f(-0.5f, -0.5f, 0.5f);
glVertex3f(0.5f, -0.5f, 0.5f);
glVertex3f(0.5f, 0.5f, 0.5f);
glVertex3f(-0.5f, 0.5f, 0.5f);
// 后面(原始绿色)
setCurrentColor(0.0f, 1.0f, 0.0f);
glVertex3f(-0.5f, -0.5f, -0.5f);
glVertex3f(-0.5f, 0.5f, -0.5f);
glVertex3f(0.5f, 0.5f, -0.5f);
glVertex3f(0.5f, -0.5f, -0.5f);
// 右面(原始蓝色)
setCurrentColor(0.0f, 0.0f, 1.0f);
glVertex3f(0.5f, -0.5f, -0.5f);
glVertex3f(0.5f, 0.5f, -0.5f);
glVertex3f(0.5f, 0.5f, 0.5f);
glVertex3f(0.5f, -0.5f, 0.5f);
// 左面(原始黄色)
setCurrentColor(1.0f, 1.0f, 0.0f);
glVertex3f(-0.5f, -0.5f, -0.5f);
glVertex3f(-0.5f, -0.5f, 0.5f);
glVertex3f(-0.5f, 0.5f, 0.5f);
glVertex3f(-0.5f, 0.5f, -0.5f);
// 上面(原始青色)
setCurrentColor(0.0f, 1.0f, 1.0f);
glVertex3f(-0.5f, 0.5f, -0.5f);
glVertex3f(-0.5f, 0.5f, 0.5f);
glVertex3f(0.5f, 0.5f, 0.5f);
glVertex3f(0.5f, 0.5f, -0.5f);
// 下面(原始紫色)
setCurrentColor(1.0f, 0.0f, 1.0f);
glVertex3f(-0.5f, -0.5f, -0.5f);
glVertex3f(0.5f, -0.5f, -0.5f);
glVertex3f(0.5f, -0.5f, 0.5f);
glVertex3f(-0.5f, -0.5f, 0.5f);
glEnd();
}
// 显示回调函数(原有逻辑不变)
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除颜色和深度缓冲区
// 重置模型视图矩阵
glLoadIdentity();
// -------------------------- 视图变换 --------------------------
gluLookAt(0.0f, 1.0f, cameraZ, // 相机位置(可通过+/-调整)
0.0f, 0.0f, 0.0f, // 目标点(看向原点)
0.0f, 1.0f, 0.0f); // 上方向(Y轴为上)
// -------------------------- 模型变换 --------------------------
glRotatef(rotationAngle, 1.0f, 1.0f, 0.0f); // 绕(1,1,0)轴旋转
glTranslatef(1.0f, 0.0f, 0.0f); // 沿X轴平移
// 绘制第一个立方体
drawCube();
// 对第二个立方体应用不同的模型变换
glPushMatrix(); // 保存当前矩阵状态
glRotatef(rotationAngle, 0.0f, 1.0f, 0.0f); // 绕Y轴旋转
glTranslatef(-2.0f, 0.0f, 0.0f); // 沿X轴负方向平移
glScalef(0.5f, 0.5f, 0.5f); // 缩小一半
drawCube(); // 绘制第二个立方体
glPopMatrix(); // 恢复矩阵状态
glutSwapBuffers(); // 交换缓冲区
}
// 窗口大小变化回调函数(原有逻辑不变)
void reshape(int width, int height) {
glViewport(0, 0, width, height); // 设置视口,占满整个窗口
// 切换到投影矩阵模式
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // 重置投影矩阵
// -------------------------- 投影变换 --------------------------
float aspectRatio = (float)width / (float)height;
gluPerspective(45.0f, aspectRatio, 0.1f, 100.0f); // 透视投影
// 切换回模型视图矩阵模式
glMatrixMode(GL_MODELVIEW);
}
// 定时器回调函数(原有逻辑不变)
void timer(int value) {
rotationAngle += 1.0f; // 增加旋转角度
if (rotationAngle >= 360.0f) {
rotationAngle = 0.0f;
}
glutPostRedisplay(); // 标记窗口需要重绘
glutTimerFunc(16, timer, 0); // 约60fps
}
// 键盘回调函数(修改:新增颜色模式切换逻辑)
void keyboard(unsigned char key, int x, int y) {
switch (key) {
case 27: // ESC键:退出程序
exit(0);
break;
case '+': // 相机靠近
cameraZ -= 0.5f;
if (cameraZ < 1.0f) cameraZ = 1.0f;
break;
case '-': // 相机远离
cameraZ += 0.5f;
break;
// -------------------------- 新增:颜色模式切换 --------------------------
case '1': // 1键:切换到彩色模式
currentColorMode = COLOR_MODE_COLORFUL;
glutSetWindowTitle("OpenGL 矩阵变换示例 - 彩色模式");
printf("当前颜色模式:彩色模式\n");
break;
case '2': // 2键:切换到灰度模式
currentColorMode = COLOR_MODE_GRAYSCALE;
glutSetWindowTitle("OpenGL 矩阵变换示例 - 灰度模式");
printf("当前颜色模式:灰度模式\n");
break;
case '3': // 3键:切换到单色模式
currentColorMode = COLOR_MODE_MONO;
glutSetWindowTitle("OpenGL 矩阵变换示例 - 单色模式(橙色)");
printf("当前颜色模式:单色模式(可按4/5/6调整颜色)\n");
break;
// 单色模式下调整颜色(4=加红,5=加绿,6=加蓝)
case '4':
if (currentColorMode == COLOR_MODE_MONO) {
monoColor[0] = (monoColor[0] + 0.1f) > 1.0f ? 1.0f : monoColor[0] + 0.1f;
glutSetWindowTitle("OpenGL 矩阵变换示例 - 单色模式(红+)");
printf("单色模式:红色分量=%.1f\n", monoColor[0]);
}
break;
case '5':
if (currentColorMode == COLOR_MODE_MONO) {
monoColor[1] = (monoColor[1] + 0.1f) > 1.0f ? 1.0f : monoColor[1] + 0.1f;
glutSetWindowTitle("OpenGL 矩阵变换示例 - 单色模式(绿+)");
printf("单色模式:绿色分量=%.1f\n", monoColor[1]);
}
break;
case '6':
if (currentColorMode == COLOR_MODE_MONO) {
monoColor[2] = (monoColor[2] + 0.1f) > 1.0f ? 1.0f : monoColor[2] + 0.1f;
glutSetWindowTitle("OpenGL 矩阵变换示例 - 单色模式(蓝+)");
printf("单色模式:蓝色分量=%.1f\n", monoColor[2]);
}
break;
}
glutPostRedisplay(); // 切换后触发重绘
}
// 主函数(原有逻辑不变)
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(800, 600);
glutCreateWindow("OpenGL 矩阵变换示例 - 彩色模式");
init();
// 注册回调函数
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutTimerFunc(0, timer, 0);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
结果为:




AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)