OpenGL 蓝书学习(第四版)第三章
OpenGL 蓝书学习(第四版)第三章
欢迎来到第三章!
绘制一个点
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <OpenGL/gl.h>
#include <cstdlib>
#include <iostream>
#include <format>
// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;
void renderScene(){
std::cout << "renderScene..." << "\n";
// 使用紫色 清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(5.0F); // 设置点的大小
glBegin(GL_POINTS);
glVertex2f(0.0F, 0.0F); // 绘制一个点
glEnd();
glutSwapBuffers(); // 交换缓冲区
}
// 首先调用
void setupRc(){
std::cout << "setupRc..." << "\n";
// 使用紫色清除窗口
glClearColor(0.6F, 0.4F, 0.7F, 1.0F);
// 使用红色画笔
glColor3f(1.0F, 0.0F, 0.0F);
}
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case 27: // ESC 键
case 'q':
case 'Q':
std::cout << "keyboard close..." << "\n";
exit(0);
break;
default:
break;
}
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void changeSize(const GLsizei w, const GLsizei h){
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
const GLfloat aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio, 1.0, -1.0);
} else {
glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE, 1.0, -1.0);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv){
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:双缓冲 + RGBA
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutKeyboardFunc(keyboard); // 键盘事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
// 设置 OpenGL 环境
setupRc();
// 获取支持点大小
GLfloat pointSizeRange[2];
glGetFloatv(GL_POINT_SIZE_RANGE, pointSizeRange);
// 获取支持的点大小精度
GLfloat pointSizeGranularity;
glGetFloatv(GL_POINT_SIZE_GRANULARITY, &pointSizeGranularity);
std::cout << std::format("pointSizeRange: [{}, {}], pointSizeGranularity: {}", pointSizeRange[0], pointSizeRange[1], pointSizeGranularity) << "\n";
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}
绘制一个圆
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <OpenGL/gl.h>
#include <cstdlib>
#include <iostream>
#include <format>
#include <numbers>
// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;
void renderScene(){
std::cout << "renderScene..." << "\n";
// 使用紫色 清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(5.0F); // 设置点的大小 // 使用 std::numbers::pi
glBegin(GL_POINTS);
glVertex2f(0.0F, 0.0F); // 绘制一个圆点
// 绘制一个圆
for (GLfloat angle = 0.0F; angle < std::numbers::pi_v<GLfloat> * 2.0F; angle += 0.1F) {
const GLfloat x = 50.0F * std::cos(angle);
const GLfloat y = 50.0F * std::sin(angle);
glVertex2f(x, y);
}
glEnd();
glutSwapBuffers(); // 交换缓冲区
}
// 首先调用
void setupRc(){
std::cout << "setupRc..." << "\n";
// 使用紫色清除窗口
glClearColor(0.6F, 0.4F, 0.7F, 1.0F);
// 使用红色画笔
glColor3f(1.0F, 0.0F, 0.0F);
}
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case 27: // ESC 键
case 'q':
case 'Q':
std::cout << "keyboard close..." << "\n";
exit(0);
break;
default:
break;
}
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void changeSize(const GLsizei w, const GLsizei h){
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
const GLfloat aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio, 1.0, -1.0);
} else {
glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE, 1.0, -1.0);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv){
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:双缓冲 + RGBA
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutKeyboardFunc(keyboard); // 键盘事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
// 设置 OpenGL 环境
setupRc();
// 获取支持点大小
GLfloat pointSizeRange[2];
glGetFloatv(GL_POINT_SIZE_RANGE, pointSizeRange);
// 获取支持的点大小精度
GLfloat pointSizeGranularity;
glGetFloatv(GL_POINT_SIZE_GRANULARITY, &pointSizeGranularity);
std::cout << std::format("pointSizeRange: [{}, {}], pointSizeGranularity: {}", pointSizeRange[0], pointSizeRange[1], pointSizeGranularity) << "\n";
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}
绘制立体弹簧
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <OpenGL/gl.h>
#include <cstdlib>
#include <iostream>
#include <format>
#include <numbers>
// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;
static constexpr GLfloat RADIUS = 50.0F;
// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
static GLfloat zRot = 0.0F; // z旋转角度
void renderScene(){
std::cout << std::format("renderScene xRot={}, yRot={}", xRot, yRot) << "\n";
// 使用紫色 清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(5.0F); // 设置点的大小 // 使用 std::numbers::pi
glPushMatrix();
glRotatef(xRot, 1.0F, 0.0F, 0.0F); // 绕 X 轴倾斜,看到螺旋侧面
glRotatef(yRot, 0.0F, 1.0F, 0.0F); // 绕 Y 轴,顶部朝左
glRotatef(zRot, 0.0F, 0.0F, 1.0F); // 绕 Z 轴旋转
glBegin(GL_POINTS);
glVertex2f(0.0F, 0.0F); // 绘制一个圆点
// 绘制一个圆
for (GLfloat angle = 0.0F, z = -RADIUS; angle < PI * 2.0F * 3.0F; angle += 0.1F) {
const GLfloat x = RADIUS * std::cos(angle);
const GLfloat y = RADIUS * std::sin(angle);
if(angle > PI * 2.0F * 2.0F) {
glColor3f(1.0F, 1.0F, 0.0F); // 黄色
} else {
glColor3f(1.0F, 0.0F, 0.0F); // 红色
}
glVertex3f(x, y, z);
z += 0.5F; // z 轴增加,形成螺旋
}
glEnd();
glPopMatrix();
glutSwapBuffers(); // 交换缓冲区
}
// 首先调用
void setupRc(){
std::cout << "setupRc..." << "\n";
// 使用紫色清除窗口
glClearColor(0.6F, 0.4F, 0.7F, 1.0F);
// 使用红色画笔
glColor3f(1.0F, 0.0F, 0.0F);
}
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case 27: // ESC 键
case 'q':
case 'Q':
std::cout << "keyboard close..." << "\n";
exit(0);
break;
case 'a':
case 'A':
zRot -= 5.0F; // 绕 Z 轴逆时针旋转
glutPostRedisplay();
break;
case 'd':
case 'D':
zRot += 5.0F; // 绕 Z 轴顺时针旋转
glutPostRedisplay();
break;
default:
break;
}
}
void specialKeys(const int key, const int x, const int y) {
std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case GLUT_KEY_UP:
xRot -= 5.0F;
break;
case GLUT_KEY_DOWN:
xRot += 5.0F;
break;
case GLUT_KEY_LEFT:
yRot -= 5.0F;
break;
case GLUT_KEY_RIGHT:
yRot += 5.0F;
break;
default:
break;
}
// Refresh the Window
glutPostRedisplay();
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void changeSize(const GLsizei w, const GLsizei h){
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
const GLfloat aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE, -COORDINATE_SIZE);
} else {
glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv){
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:双缓冲 + RGBA
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutSpecialFunc(specialKeys); // 特殊键事件
glutKeyboardFunc(keyboard); // 普通键事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
// 设置 OpenGL 环境
setupRc();
// 获取支持点大小
GLfloat pointSizeRange[2];
glGetFloatv(GL_POINT_SIZE_RANGE, pointSizeRange);
// 获取支持的点大小精度
GLfloat pointSizeGranularity;
glGetFloatv(GL_POINT_SIZE_GRANULARITY, &pointSizeGranularity);
std::cout << std::format("pointSizeRange: [{}, {}], pointSizeGranularity: {}", pointSizeRange[0], pointSizeRange[1], pointSizeGranularity) << "\n";
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}
绘制立体变粗的弹簧
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <OpenGL/gl.h>
#include <cstdlib>
#include <iostream>
#include <format>
#include <numbers>
// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;
static constexpr GLfloat RADIUS = 50.0F;
// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
void renderScene(){
std::cout << std::format("renderScene xRot={}, yRot={}", xRot, yRot) << "\n";
// 使用紫色 清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT);
// 点大小
GLfloat pointSize = 1.0F;
glPointSize(pointSize);
glPushMatrix();
glRotatef(xRot, 1.0F, 0.0F, 0.0F); // 绕 X 轴倾斜,看到螺旋侧面
glRotatef(yRot, 0.0F, 1.0F, 0.0F); // 绕 Y 轴,顶部朝左
// 原点
glPointSize(5.0F); // glPointSize必须在 glBegin 之前设置,否则无效,但是会影响性能
glBegin(GL_POINTS);
glVertex2f(0.0F, 0.0F);
glEnd();
// 绘制螺旋:每个点单独 begin/end,才能在 glBegin 前设置不同的大小
for (GLfloat angle = 0.0F, z = -RADIUS; angle < PI * 2.0F * 3.0F; angle += 0.1F) {
const GLfloat x = RADIUS * std::cos(angle);
const GLfloat y = RADIUS * std::sin(angle);
if(angle > PI * 2.0F * 2.0F) {
glColor3f(1.0F, 1.0F, 0.0F); // 黄色
} else {
glColor3f(1.0F, 0.0F, 0.0F); // 红色
}
glPointSize(pointSize); // 必须在 glBegin 之前设置
glBegin(GL_POINTS);
glVertex3f(x, y, z);
glEnd();
pointSize += 0.1F;
z += 0.5F;
}
glPopMatrix();
glutSwapBuffers(); // 交换缓冲区
}
// 首先调用
void setupRc(){
std::cout << "setupRc..." << "\n";
// 使用紫色清除窗口
glClearColor(0.6F, 0.4F, 0.7F, 1.0F);
// 使用红色画笔
glColor3f(1.0F, 0.0F, 0.0F);
}
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case 27: // ESC 键
case 'q':
case 'Q':
std::cout << "keyboard close..." << "\n";
exit(0);
break;
default:
break;
}
}
void specialKeys(const int key, const int x, const int y) {
std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case GLUT_KEY_UP:
xRot -= 5.0F;
break;
case GLUT_KEY_DOWN:
xRot += 5.0F;
break;
case GLUT_KEY_LEFT:
yRot -= 5.0F;
break;
case GLUT_KEY_RIGHT:
yRot += 5.0F;
break;
default:
break;
}
// Refresh the Window
glutPostRedisplay();
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void changeSize(const GLsizei w, const GLsizei h){
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
const GLfloat aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE, -COORDINATE_SIZE);
} else {
glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv){
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:双缓冲 + RGBA
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutSpecialFunc(specialKeys); // 特殊键事件
glutKeyboardFunc(keyboard); // 普通键事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
// 设置 OpenGL 环境
setupRc();
// 获取支持点大小
GLfloat pointSizeRange[2];
glGetFloatv(GL_POINT_SIZE_RANGE, pointSizeRange);
// 获取支持的点大小精度
GLfloat pointSizeGranularity;
glGetFloatv(GL_POINT_SIZE_GRANULARITY, &pointSizeGranularity);
std::cout << std::format("pointSizeRange: [{}, {}], pointSizeGranularity: {}", pointSizeRange[0], pointSizeRange[1], pointSizeGranularity) << "\n";
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}
画一条直线
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <OpenGL/gl.h>
#include <cstdlib>
#include <iostream>
#include <format>
// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;
void renderScene(){
std::cout << std::format("renderScene...") << "\n";
// 使用紫色 清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_LINES);
glVertex3f(0.0F, 0.0F, 0.0F);
glVertex3f(50.0F, 50.0F, 0.0F);
glVertex3f(60.0F, 60.0F, 0.0F);
glVertex3f(70.0F, 70.0F, 0.0F);
glEnd();
glutSwapBuffers(); // 交换缓冲区
}
// 首先调用
void setupRc(){
std::cout << "setupRc..." << "\n";
// 使用紫色清除窗口
glClearColor(0.6F, 0.4F, 0.7F, 1.0F);
// 使用红色画笔
glColor3f(1.0F, 0.0F, 0.0F);
}
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case 27: // ESC 键
case 'q':
case 'Q':
std::cout << "keyboard close..." << "\n";
exit(0);
break;
default:
break;
}
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void changeSize(const GLsizei w, const GLsizei h){
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
const GLfloat aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE, -COORDINATE_SIZE);
} else {
glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv){
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:双缓冲 + RGBA
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutKeyboardFunc(keyboard); // 普通键事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
// 设置 OpenGL 环境
setupRc();
// 获取支持点大小
GLfloat pointSizeRange[2];
glGetFloatv(GL_POINT_SIZE_RANGE, pointSizeRange);
// 获取支持的点大小精度
GLfloat pointSizeGranularity;
glGetFloatv(GL_POINT_SIZE_GRANULARITY, &pointSizeGranularity);
std::cout << std::format("pointSizeRange: [{}, {}], pointSizeGranularity: {}", pointSizeRange[0], pointSizeRange[1], pointSizeGranularity) << "\n";
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}
画一个轮毂
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <OpenGL/gl.h>
#include <cstdlib>
#include <iostream>
#include <format>
#include <numbers>
// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;
static constexpr GLfloat RADIUS = 50.0F;
void renderScene(){
std::cout << std::format("renderScene...") << "\n";
// 使用紫色 清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_LINES);
const GLfloat step = PI / 45.0F * 2.0F;
for (GLfloat angle = 0.0F; angle < 2 * PI; angle += step) {
const GLfloat x = RADIUS * std::cos(angle);
const GLfloat y = RADIUS * std::sin(angle);
glVertex2f(0.0F, 0.0F);
glVertex2f(x, y);
}
glEnd();
glutSwapBuffers(); // 交换缓冲区
}
// 首先调用
void setupRc(){
std::cout << "setupRc..." << "\n";
// 使用紫色清除窗口
glClearColor(0.6F, 0.4F, 0.7F, 1.0F);
// 使用红色画笔
glColor3f(1.0F, 0.0F, 0.0F);
}
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case 27: // ESC 键
case 'q':
case 'Q':
std::cout << "keyboard close..." << "\n";
exit(0);
break;
default:
break;
}
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void changeSize(const GLsizei w, const GLsizei h){
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
const GLfloat aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE, -COORDINATE_SIZE);
} else {
glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv){
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:双缓冲 + RGBA
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutKeyboardFunc(keyboard); // 普通键事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
// 设置 OpenGL 环境
setupRc();
// 获取支持点大小
GLfloat pointSizeRange[2];
glGetFloatv(GL_POINT_SIZE_RANGE, pointSizeRange);
// 获取支持的点大小精度
GLfloat pointSizeGranularity;
glGetFloatv(GL_POINT_SIZE_GRANULARITY, &pointSizeGranularity);
std::cout << std::format("pointSizeRange: [{}, {}], pointSizeGranularity: {}", pointSizeRange[0], pointSizeRange[1], pointSizeGranularity) << "\n";
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}
画一个厂
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <OpenGL/gl.h>
#include <cstdlib>
#include <iostream>
#include <format>
#include <numbers>
// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;
static constexpr GLfloat RADIUS = 50.0F;
void renderScene(){
std::cout << std::format("renderScene...") << "\n";
// 使用紫色 清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_LINE_STRIP);
glVertex2f(0.0F, 0.0F);
glVertex2f(50.0F, 50.0F);
glVertex2f(80.0F, 50.0F);
glEnd();
glutSwapBuffers(); // 交换缓冲区
}
// 首先调用
void setupRc(){
std::cout << "setupRc..." << "\n";
// 使用紫色清除窗口
glClearColor(0.6F, 0.4F, 0.7F, 1.0F);
// 使用红色画笔
glColor3f(1.0F, 0.0F, 0.0F);
}
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case 27: // ESC 键
case 'q':
case 'Q':
std::cout << "keyboard close..." << "\n";
exit(0);
break;
default:
break;
}
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void changeSize(const GLsizei w, const GLsizei h){
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
const GLfloat aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE, -COORDINATE_SIZE);
} else {
glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv){
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:双缓冲 + RGBA
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutKeyboardFunc(keyboard); // 普通键事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
// 设置 OpenGL 环境
setupRc();
// 获取支持点大小
GLfloat pointSizeRange[2];
glGetFloatv(GL_POINT_SIZE_RANGE, pointSizeRange);
// 获取支持的点大小精度
GLfloat pointSizeGranularity;
glGetFloatv(GL_POINT_SIZE_GRANULARITY, &pointSizeGranularity);
std::cout << std::format("pointSizeRange: [{}, {}], pointSizeGranularity: {}", pointSizeRange[0], pointSizeRange[1], pointSizeGranularity) << "\n";
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}
GL_LINE_STRIP会绘制经过所有点集的一条线。GL_LINE_LOOP会自闭和。
绘制圆滑弹簧
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <OpenGL/gl.h>
#include <cstdlib>
#include <iostream>
#include <format>
#include <numbers>
// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;
static constexpr GLfloat RADIUS = 50.0F;
// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
void renderScene(){
std::cout << std::format("renderScene xRot={}, yRot={}", xRot, yRot) << "\n";
// 使用紫色 清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(5.0F); // 设置点的大小 // 使用 std::numbers::pi
glPushMatrix();
glRotatef(xRot, 1.0F, 0.0F, 0.0F); // 绕 X 轴倾斜,看到螺旋侧面
glRotatef(yRot, 0.0F, 1.0F, 0.0F); // 绕 Y 轴,顶部朝左
glBegin(GL_POINTS);
glVertex2f(0.0F, 0.0F); // 绘制一个圆点
glEnd();
glBegin(GL_LINE_STRIP);
// 绘制一个圆
for (GLfloat angle = 0.0F, z = -RADIUS; angle < PI * 2.0F * 3.0F; angle += 0.1F) {
const GLfloat x = RADIUS * std::cos(angle);
const GLfloat y = RADIUS * std::sin(angle);
if(angle > PI * 2.0F * 2.0F) {
glColor3f(1.0F, 1.0F, 0.0F); // 黄色
} else {
glColor3f(1.0F, 0.0F, 0.0F); // 红色
}
glVertex3f(x, y, z);
z += 0.5F; // z 轴增加,形成螺旋
}
glEnd();
glPopMatrix();
glutSwapBuffers(); // 交换缓冲区
}
// 首先调用
void setupRc(){
std::cout << "setupRc..." << "\n";
// 使用紫色清除窗口
glClearColor(0.6F, 0.4F, 0.7F, 1.0F);
// 使用红色画笔
glColor3f(1.0F, 0.0F, 0.0F);
}
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case 27: // ESC 键
case 'q':
case 'Q':
std::cout << "keyboard close..." << "\n";
exit(0);
break;
default:
break;
}
}
void specialKeys(const int key, const int x, const int y) {
std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case GLUT_KEY_UP:
xRot -= 5.0F;
break;
case GLUT_KEY_DOWN:
xRot += 5.0F;
break;
case GLUT_KEY_LEFT:
yRot -= 5.0F;
break;
case GLUT_KEY_RIGHT:
yRot += 5.0F;
break;
default:
break;
}
// Refresh the Window
glutPostRedisplay();
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void changeSize(const GLsizei w, const GLsizei h){
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
const GLfloat aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE, -COORDINATE_SIZE);
} else {
glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv){
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:双缓冲 + RGBA
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutSpecialFunc(specialKeys); // 特殊键事件
glutKeyboardFunc(keyboard); // 普通键事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
// 设置 OpenGL 环境
setupRc();
// 获取支持点大小
GLfloat pointSizeRange[2];
glGetFloatv(GL_POINT_SIZE_RANGE, pointSizeRange);
// 获取支持的点大小精度
GLfloat pointSizeGranularity;
glGetFloatv(GL_POINT_SIZE_GRANULARITY, &pointSizeGranularity);
std::cout << std::format("pointSizeRange: [{}, {}], pointSizeGranularity: {}", pointSizeRange[0], pointSizeRange[1], pointSizeGranularity) << "\n";
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}
绘制递增线条宽度的线条
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <OpenGL/gl.h>
#include <cstdlib>
#include <iostream>
#include <format>
#include <numbers>
// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;
static constexpr GLfloat RADIUS = 50.0F;
void renderScene(){
std::cout << "renderScene..." << "\n";
// 使用紫色 清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT);
// 获取支持的线宽范围
GLfloat lineWidthRange[2];
glGetFloatv(GL_LINE_WIDTH_RANGE, lineWidthRange);
for (GLfloat lineWidth = lineWidthRange[0], y = -80.0; lineWidth <= lineWidthRange[1]; lineWidth += 1.0F, y += 10.0F) {
glLineWidth(lineWidth);
glBegin(GL_LINES);
glVertex2f(-80.0F, y);
glVertex2f(80.0F, y);
glEnd();
}
glutSwapBuffers(); // 交换缓冲区
}
// 首先调用
void setupRc(){
std::cout << "setupRc..." << "\n";
// 使用紫色清除窗口
glClearColor(0.6F, 0.4F, 0.7F, 1.0F);
// 使用红色画笔
glColor3f(1.0F, 0.0F, 0.0F);
}
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case 27: // ESC 键
case 'q':
case 'Q':
std::cout << "keyboard close..." << "\n";
exit(0);
break;
default:
break;
}
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void changeSize(const GLsizei w, const GLsizei h){
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
const GLfloat aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE, -COORDINATE_SIZE);
} else {
glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv){
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:双缓冲 + RGBA
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutKeyboardFunc(keyboard); // 普通键事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
// 设置 OpenGL 环境
setupRc();
// 获取支持的线宽范围
GLfloat lineWidthRange[2];
glGetFloatv(GL_LINE_WIDTH_RANGE, lineWidthRange);
// 获取支持的线宽精度
GLfloat lineWidthGranularity;
glGetFloatv(GL_LINE_WIDTH_GRANULARITY, &lineWidthGranularity);
std::cout << std::format("lineWidthRange: [{}, {}], lineWidthGranularity: {}", lineWidthRange[0], lineWidthRange[1], lineWidthGranularity) << "\n";
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}
绘制虚线
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <OpenGL/gl.h>
#include <cstdlib>
#include <iostream>
#include <format>
#include <numbers>
// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;
static constexpr GLfloat RADIUS = 50.0F;
void renderScene(){
std::cout << "renderScene..." << "\n";
// 使用紫色 清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_LINE_SMOOTH); // 开启线条抗锯齿
glEnable(GL_LINE_STIPPLE); // 开启线条虚线
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // 设置抗锯齿质量
// const GLushort pattern = 0x5555; // 线条虚线模式
const GLushort pattern = 0x00FF; // 线条虚线模式
GLint factor = 1; // 线条虚线重复因子
for(GLfloat y = -80.0F; y <= 80.0F; y += 10.0F){
glLineStipple(factor, pattern);
glBegin(GL_LINES);
glVertex2f(-80.0F, y);
glVertex2f(80.0F, y);
glEnd();
factor++;
}
glutSwapBuffers(); // 交换缓冲区
}
// 首先调用
void setupRc(){
std::cout << "setupRc..." << "\n";
// 使用紫色清除窗口
glClearColor(0.6F, 0.4F, 0.7F, 1.0F);
// 使用红色画笔
glColor3f(1.0F, 0.0F, 0.0F);
}
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case 27: // ESC 键
case 'q':
case 'Q':
std::cout << "keyboard close..." << "\n";
exit(0);
break;
default:
break;
}
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void changeSize(const GLsizei w, const GLsizei h){
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
const GLfloat aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE, -COORDINATE_SIZE);
} else {
glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv){
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:双缓冲 + RGBA
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutKeyboardFunc(keyboard); // 普通键事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
// 设置 OpenGL 环境
setupRc();
// 获取支持的线宽范围
GLfloat lineWidthRange[2];
glGetFloatv(GL_LINE_WIDTH_RANGE, lineWidthRange);
// 获取支持的线宽精度
GLfloat lineWidthGranularity;
glGetFloatv(GL_LINE_WIDTH_GRANULARITY, &lineWidthGranularity);
std::cout << std::format("lineWidthRange: [{}, {}], lineWidthGranularity: {}", lineWidthRange[0], lineWidthRange[1], lineWidthGranularity) << "\n";
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}
绘制三角形
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <OpenGL/gl.h>
#include <cstdlib>
#include <iostream>
#include <format>
#include <numbers>
// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;
static constexpr GLfloat RADIUS = 50.0F;
void renderScene(){
std::cout << "renderScene..." << "\n";
// 使用紫色 清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLES);
// 绘制第一个三角形
glVertex2f(0.0F, 0.0F);
glVertex2f(25.0F, 25.0F);
glVertex2f(50.0F, 0.0F);
// 绘制第二个三角形
glVertex2f(-50.0F, 0.0F);
glVertex2f(-75.0F, 50.0F);
glVertex2f(-25.0F, 0.0F);
glEnd();
glutSwapBuffers(); // 交换缓冲区
}
// 首先调用
void setupRc(){
std::cout << "setupRc..." << "\n";
// 使用紫色清除窗口
glClearColor(0.6F, 0.4F, 0.7F, 1.0F);
// 使用红色画笔
glColor3f(1.0F, 0.0F, 0.0F);
}
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case 27: // ESC 键
case 'q':
case 'Q':
std::cout << "keyboard close..." << "\n";
exit(0);
break;
default:
break;
}
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void changeSize(const GLsizei w, const GLsizei h){
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
const GLfloat aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE, -COORDINATE_SIZE);
} else {
glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv){
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:双缓冲 + RGBA
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutKeyboardFunc(keyboard); // 普通键事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
// 设置 OpenGL 环境
setupRc();
// 获取支持的线宽范围
GLfloat lineWidthRange[2];
glGetFloatv(GL_LINE_WIDTH_RANGE, lineWidthRange);
// 获取支持的线宽精度
GLfloat lineWidthGranularity;
glGetFloatv(GL_LINE_WIDTH_GRANULARITY, &lineWidthGranularity);
std::cout << std::format("lineWidthRange: [{}, {}], lineWidthGranularity: {}", lineWidthRange[0], lineWidthRange[1], lineWidthGranularity) << "\n";
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}
绘制三角形并开启背面剔除
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <OpenGL/gl.h>
#include <cstdlib>
#include <iostream>
#include <format>
#include <numbers>
// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;
static constexpr GLfloat RADIUS = 50.0F;
// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
static GLfloat zRot = 0.0F; // z旋转角度
void renderScene(){
std::cout << "renderScene..." << "\n";
// 使用紫色 清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glRotatef(xRot, 1.0F, 0.0F, 0.0F); // 绕 X 轴旋转
glRotatef(yRot, 0.0F, 1.0F, 0.0F); // 绕 Y 轴旋转
glRotatef(zRot, 0.0F, 0.0F, 1.0F); // 绕 Z 轴旋转
glBegin(GL_TRIANGLES);
// 绘制第一个三角形
glVertex2f(0.0F, 0.0F);
glVertex2f(25.0F, 25.0F);
glVertex2f(50.0F, 0.0F);
// 绘制第二个三角形
glVertex2f(-50.0F, 0.0F);
glVertex2f(-75.0F, 50.0F);
glVertex2f(-25.0F, 0.0F);
glEnd();
glPopMatrix();
glutSwapBuffers(); // 交换缓冲区
}
// 首先调用
void setupRc(){
std::cout << "setupRc..." << "\n";
// 使用紫色清除窗口
glClearColor(0.6F, 0.4F, 0.7F, 1.0F);
// 使用红色画笔
glColor3f(1.0F, 0.0F, 0.0F);
glEnable(GL_CULL_FACE); // 开启面剔除
glCullFace(GL_BACK); // 剔除背面(默认就是 BACK)
glFrontFace(GL_CCW); // 逆时针为正面(默认值)
}
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case 27: // ESC 键
case 'q':
case 'Q':
std::cout << "keyboard close..." << "\n";
exit(0);
break;
case 'a':
case 'A':
zRot -= 5.0F; // 绕 Z 轴逆时针旋转
glutPostRedisplay();
break;
case 'd':
case 'D':
zRot += 5.0F; // 绕 Z 轴顺时针旋转
glutPostRedisplay();
break;
default:
break;
}
}
void specialKeys(const int key, const int x, const int y) {
std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case GLUT_KEY_UP:
xRot -= 5.0F;
break;
case GLUT_KEY_DOWN:
xRot += 5.0F;
break;
case GLUT_KEY_LEFT:
yRot -= 5.0F;
break;
case GLUT_KEY_RIGHT:
yRot += 5.0F;
break;
default:
break;
}
// Refresh the Window
glutPostRedisplay();
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void changeSize(const GLsizei w, const GLsizei h){
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
const GLfloat aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE, -COORDINATE_SIZE);
} else {
glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv){
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:双缓冲 + RGBA
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutSpecialFunc(specialKeys); // 特殊键事件
glutKeyboardFunc(keyboard); // 普通键事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
// 设置 OpenGL 环境
setupRc();
// 获取支持的线宽范围
GLfloat lineWidthRange[2];
glGetFloatv(GL_LINE_WIDTH_RANGE, lineWidthRange);
// 获取支持的线宽精度
GLfloat lineWidthGranularity;
glGetFloatv(GL_LINE_WIDTH_GRANULARITY, &lineWidthGranularity);
std::cout << std::format("lineWidthRange: [{}, {}], lineWidthGranularity: {}", lineWidthRange[0], lineWidthRange[1], lineWidthGranularity) << "\n";
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}
默认情况下GL_TRIANGLES、GL_TRIANGLE_FAN使用的是顺时针环绕,满足右手定则,大拇指指定方向为正面,反之为背面。面剔除默认剔除背面。
GL_TRIANGLE_STRIP使用的是逆时针环绕。
使用GL_TRIANGLE_FAN绘制菱形
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <OpenGL/gl.h>
#include <cstdlib>
#include <iostream>
#include <format>
#include <numbers>
// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;
static constexpr GLfloat RADIUS = 50.0F;
// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
static GLfloat zRot = 0.0F; // z旋转角度
void renderScene(){
std::cout << "renderScene..." << "\n";
// 使用紫色 清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glRotatef(xRot, 1.0F, 0.0F, 0.0F); // 绕 X 轴旋转
glRotatef(yRot, 0.0F, 1.0F, 0.0F); // 绕 Y 轴旋转
glRotatef(zRot, 0.0F, 0.0F, 1.0F); // 绕 Z 轴旋转
glBegin(GL_TRIANGLE_FAN); // 绘制三角形扇(菱形)
glVertex2f(0.0F, 0.0F); // 中心点
glVertex2f(0.0F, 50.0F); // 上顶点
glVertex2f(25.0F, 0.0F); // 右顶点
glVertex2f(0.0F, -50.0F); // 下顶点
glVertex2f(-25.0F, 0.0F); // 左顶点
glVertex2f(0.0F, 50.0F); // 闭合回到上顶点
glEnd();
glPopMatrix();
glutSwapBuffers(); // 交换缓冲区
}
// 首先调用
void setupRc(){
std::cout << "setupRc..." << "\n";
// 使用紫色清除窗口
glClearColor(0.6F, 0.4F, 0.7F, 1.0F);
// 使用红色画笔
glColor3f(1.0F, 0.0F, 0.0F);
glEnable(GL_CULL_FACE); // 开启面剔除
}
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case 27: // ESC 键
case 'q':
case 'Q':
std::cout << "keyboard close..." << "\n";
exit(0);
break;
case 'a':
case 'A':
zRot -= 5.0F; // 绕 Z 轴逆时针旋转
glutPostRedisplay();
break;
case 'd':
case 'D':
zRot += 5.0F; // 绕 Z 轴顺时针旋转
glutPostRedisplay();
break;
default:
break;
}
}
void specialKeys(const int key, const int x, const int y) {
std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case GLUT_KEY_UP:
xRot -= 5.0F;
break;
case GLUT_KEY_DOWN:
xRot += 5.0F;
break;
case GLUT_KEY_LEFT:
yRot -= 5.0F;
break;
case GLUT_KEY_RIGHT:
yRot += 5.0F;
break;
default:
break;
}
// Refresh the Window
glutPostRedisplay();
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void changeSize(const GLsizei w, const GLsizei h){
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
const GLfloat aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE, -COORDINATE_SIZE);
} else {
glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv){
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:双缓冲 + RGBA
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutSpecialFunc(specialKeys); // 特殊键事件
glutKeyboardFunc(keyboard); // 普通键事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
// 设置 OpenGL 环境
setupRc();
// 获取支持的线宽范围
GLfloat lineWidthRange[2];
glGetFloatv(GL_LINE_WIDTH_RANGE, lineWidthRange);
// 获取支持的线宽精度
GLfloat lineWidthGranularity;
glGetFloatv(GL_LINE_WIDTH_GRANULARITY, &lineWidthGranularity);
std::cout << std::format("lineWidthRange: [{}, {}], lineWidthGranularity: {}", lineWidthRange[0], lineWidthRange[1], lineWidthGranularity) << "\n";
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}
绘制一个菱形
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <OpenGL/gl.h>
#include <cstdlib>
#include <iostream>
#include <format>
#include <numbers>
// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;
static constexpr GLfloat RADIUS = 50.0F;
// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
static GLfloat zRot = 0.0F; // z旋转角度
void renderScene(){
std::cout << "renderScene..." << "\n";
// 使用紫色 清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glRotatef(xRot, 1.0F, 0.0F, 0.0F); // 绕 X 轴旋转
glRotatef(yRot, 0.0F, 1.0F, 0.0F); // 绕 Y 轴旋转
glRotatef(zRot, 0.0F, 0.0F, 1.0F); // 绕 Z 轴旋转
glBegin(GL_TRIANGLE_STRIP); // 使用三角形条带绘制菱形
// GL_TRIANGLE_STRIP 顶点顺序:
// Triangle 0 (even): v0 → v1 → v2
// Triangle 1 (odd): v2 → v1 → v3 (OpenGL自动交换前两个顶点以保持一致的缠绕)
//
// 菱形四个顶点:
// v0( 0, 50) ← 上
// v1(-25, 0) ← 左
// v2( 25, 0) ← 右
// v3( 0, -50) ← 下
//
// Triangle 0: 上→左→右 (CCW, 上半菱形)
// Triangle 1: 右→左→下 → 经GL交换后: 左→右→下 (CCW, 下半菱形)
std::cout << "v0: top (0, 50)" << "\n";
glVertex2f(0.0F, 50.0F); // v0: 上顶点
std::cout << "v1: left (-25, 0)" << "\n";
glVertex2f(-25.0F, 0.0F); // v1: 左顶点
std::cout << "v2: right (25, 0)" << "\n";
glVertex2f(25.0F, 0.0F); // v2: 右顶点
std::cout << "v3: bottom(0, -50)" << "\n";
glVertex2f(0.0F, -50.0F); // v3: 下顶点
glEnd();
glPopMatrix();
glutSwapBuffers(); // 交换缓冲区
}
// 首先调用
void setupRc(){
std::cout << "setupRc..." << "\n";
// 使用紫色清除窗口
glClearColor(0.6F, 0.4F, 0.7F, 1.0F);
// 使用红色画笔
glColor3f(1.0F, 0.0F, 0.0F);
glEnable(GL_CULL_FACE); // 开启面剔除
}
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case 27: // ESC 键
case 'q':
case 'Q':
std::cout << "keyboard close..." << "\n";
exit(0);
break;
case 'a':
case 'A':
zRot -= 5.0F; // 绕 Z 轴逆时针旋转
glutPostRedisplay();
break;
case 'd':
case 'D':
zRot += 5.0F; // 绕 Z 轴顺时针旋转
glutPostRedisplay();
break;
default:
break;
}
}
void specialKeys(const int key, const int x, const int y) {
std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case GLUT_KEY_UP:
xRot -= 5.0F;
break;
case GLUT_KEY_DOWN:
xRot += 5.0F;
break;
case GLUT_KEY_LEFT:
yRot -= 5.0F;
break;
case GLUT_KEY_RIGHT:
yRot += 5.0F;
break;
default:
break;
}
// Refresh the Window
glutPostRedisplay();
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void changeSize(const GLsizei w, const GLsizei h){
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
const GLfloat aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE, -COORDINATE_SIZE);
} else {
glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv){
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:双缓冲 + RGBA
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutSpecialFunc(specialKeys); // 特殊键事件
glutKeyboardFunc(keyboard); // 普通键事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
// 设置 OpenGL 环境
setupRc();
// 获取支持的线宽范围
GLfloat lineWidthRange[2];
glGetFloatv(GL_LINE_WIDTH_RANGE, lineWidthRange);
// 获取支持的线宽精度
GLfloat lineWidthGranularity;
glGetFloatv(GL_LINE_WIDTH_GRANULARITY, &lineWidthGranularity);
std::cout << std::format("lineWidthRange: [{}, {}], lineWidthGranularity: {}", lineWidthRange[0], lineWidthRange[1], lineWidthGranularity) << "\n";
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}
GL_TRIANGLE_STRIP
画一个圆锥体
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <OpenGL/gl.h>
#include <cstdlib>
#include <iostream>
#include <format>
#include <numbers>
// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;
static constexpr GLfloat RADIUS = 50.0F;
// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
static GLfloat zRot = 0.0F; // z旋转角度
void renderScene(){
std::cout << "renderScene..." << "\n";
// 使用紫色 清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT);
GLboolean isGreen = false;
glPushMatrix();
glRotatef(xRot, 1.0F, 0.0F, 0.0F); // 绕 X 轴旋转
glRotatef(yRot, 0.0F, 1.0F, 0.0F); // 绕 Y 轴旋转
glRotatef(zRot, 0.0F, 0.0F, 1.0F); // 绕 Z 轴旋转
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0F, 0.0F, 80.0F); // 圆锥顶点
for (GLfloat angle = 0.0F, i = 0; angle < 2.0F * PI; angle += PI / 8.0F, ++i) {
glVertex3f(RADIUS * std::cos(angle), RADIUS * std::sin(angle), 0.0F);
if (isGreen) {
glColor3f(0.0F, 1.0F, 0.0F); // 绿色
} else {
glColor3f(1.0F, 0.0F, 0.0F); // 红色
}
isGreen = !isGreen;
}
glVertex3f(RADIUS, 0.0F, 0.0F); // 闭合圆锥底面
glEnd();
// 底盖
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0F, 0.0F, 0.0F); // 圆锥底面中心点
for (GLfloat angle = 0.0F; angle < 2.0F * PI; angle += PI / 8.0F) {
glVertex3f(RADIUS * std::cos(angle), RADIUS * std::sin(angle), 0.0F);
if (isGreen) {
glColor3f(0.0F, 1.0F, 0.0F); // 绿色
} else {
glColor3f(1.0F, 0.0F, 0.0F); // 红色
}
isGreen = !isGreen;
}
glVertex3f(RADIUS, 0.0F, 0.0F); // 闭合圆锥底面
glEnd();
glPopMatrix();
glutSwapBuffers(); // 交换缓冲区
}
// 首先调用
void setupRc(){
std::cout << "setupRc..." << "\n";
// 使用紫色清除窗口
glClearColor(0.6F, 0.4F, 0.7F, 1.0F);
// 使用红色画笔
glColor3f(1.0F, 0.0F, 0.0F);
glShadeModel(GL_FLAT); // 设置为平面着色
}
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case 27: // ESC 键
case 'q':
case 'Q':
std::cout << "keyboard close..." << "\n";
exit(0);
break;
case 'a':
case 'A':
zRot -= 5.0F; // 绕 Z 轴逆时针旋转
glutPostRedisplay();
break;
case 'd':
case 'D':
zRot += 5.0F; // 绕 Z 轴顺时针旋转
glutPostRedisplay();
break;
default:
break;
}
}
void specialKeys(const int key, const int x, const int y) {
std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case GLUT_KEY_UP:
xRot -= 5.0F;
break;
case GLUT_KEY_DOWN:
xRot += 5.0F;
break;
case GLUT_KEY_LEFT:
yRot -= 5.0F;
break;
case GLUT_KEY_RIGHT:
yRot += 5.0F;
break;
default:
break;
}
// Refresh the Window
glutPostRedisplay();
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void changeSize(const GLsizei w, const GLsizei h){
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
const GLfloat aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE, -COORDINATE_SIZE);
} else {
glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv){
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:双缓冲 + RGBA
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutSpecialFunc(specialKeys); // 特殊键事件
glutKeyboardFunc(keyboard); // 普通键事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
// 设置 OpenGL 环境
setupRc();
// 获取支持的线宽范围
GLfloat lineWidthRange[2];
glGetFloatv(GL_LINE_WIDTH_RANGE, lineWidthRange);
// 获取支持的线宽精度
GLfloat lineWidthGranularity;
glGetFloatv(GL_LINE_WIDTH_GRANULARITY, &lineWidthGranularity);
std::cout << std::format("lineWidthRange: [{}, {}], lineWidthGranularity: {}", lineWidthRange[0], lineWidthRange[1], lineWidthGranularity) << "\n";
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}
开启深度测试的圆锥体
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <OpenGL/gl.h>
#include <cstdlib>
#include <iostream>
#include <format>
#include <numbers>
// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;
static constexpr GLfloat RADIUS = 50.0F;
// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
static GLfloat zRot = 0.0F; // z旋转角度
void renderScene(){
std::cout << "renderScene..." << "\n";
// 使用紫色 清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLboolean isGreen = false;
glPushMatrix();
glRotatef(xRot, 1.0F, 0.0F, 0.0F); // 绕 X 轴旋转
glRotatef(yRot, 0.0F, 1.0F, 0.0F); // 绕 Y 轴旋转
glRotatef(zRot, 0.0F, 0.0F, 1.0F); // 绕 Z 轴旋转
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0F, 0.0F, 80.0F); // 圆锥顶点,指向屏幕外
for (GLfloat angle = 0.0F, i = 0; angle < 2.0F * PI; angle += PI / 8.0F, ++i) {
glVertex3f(RADIUS * std::cos(angle), RADIUS * std::sin(angle), 0.0F);
if (isGreen) {
glColor3f(0.0F, 1.0F, 0.0F); // 绿色
} else {
glColor3f(1.0F, 0.0F, 0.0F); // 红色
}
isGreen = !isGreen;
}
glVertex3f(RADIUS, 0.0F, 0.0F); // 闭合圆锥底面
glEnd();
// 底盖
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0F, 0.0F, 0.0F); // 圆锥底面中心点
for (GLfloat angle = 0.0F; angle < 2.0F * PI; angle += PI / 8.0F) {
glVertex3f(RADIUS * std::cos(angle), RADIUS * std::sin(angle), 0.0F);
if (isGreen) {
glColor3f(0.0F, 1.0F, 0.0F); // 绿色
} else {
glColor3f(1.0F, 0.0F, 0.0F); // 红色
}
isGreen = !isGreen;
}
glVertex3f(RADIUS, 0.0F, 0.0F); // 闭合圆锥底面
glEnd();
glPopMatrix();
glutSwapBuffers(); // 交换缓冲区
}
// 首先调用
void setupRc(){
std::cout << "setupRc..." << "\n";
// 使用紫色清除窗口
glClearColor(0.6F, 0.4F, 0.7F, 1.0F);
// 使用红色画笔
glColor3f(1.0F, 0.0F, 0.0F);
glShadeModel(GL_FLAT); // 设置为平面着色
glEnable(GL_DEPTH_TEST); // 启用深度测试
}
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case 27: // ESC 键
case 'q':
case 'Q':
std::cout << "keyboard close..." << "\n";
exit(0);
break;
case 'a':
case 'A':
zRot -= 5.0F; // 绕 Z 轴逆时针旋转
glutPostRedisplay();
break;
case 'd':
case 'D':
zRot += 5.0F; // 绕 Z 轴顺时针旋转
glutPostRedisplay();
break;
default:
break;
}
}
void specialKeys(const int key, const int x, const int y) {
std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case GLUT_KEY_UP:
xRot -= 5.0F;
break;
case GLUT_KEY_DOWN:
xRot += 5.0F;
break;
case GLUT_KEY_LEFT:
yRot -= 5.0F;
break;
case GLUT_KEY_RIGHT:
yRot += 5.0F;
break;
default:
break;
}
// Refresh the Window
glutPostRedisplay();
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void changeSize(const GLsizei w, const GLsizei h){
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
const GLfloat aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE);
} else {
glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE, COORDINATE_SIZE);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv){
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:双缓冲 + RGBA
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutSpecialFunc(specialKeys); // 特殊键事件
glutKeyboardFunc(keyboard); // 普通键事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
// 设置 OpenGL 环境
setupRc();
// 获取支持的线宽范围
GLfloat lineWidthRange[2];
glGetFloatv(GL_LINE_WIDTH_RANGE, lineWidthRange);
// 获取支持的线宽精度
GLfloat lineWidthGranularity;
glGetFloatv(GL_LINE_WIDTH_GRANULARITY, &lineWidthGranularity);
std::cout << std::format("lineWidthRange: [{}, {}], lineWidthGranularity: {}", lineWidthRange[0], lineWidthRange[1], lineWidthGranularity) << "\n";
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}
深度测试+背面剔除
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <OpenGL/gl.h>
#include <cstdlib>
#include <iostream>
#include <format>
#include <numbers>
// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;
static constexpr GLfloat RADIUS = 50.0F;
// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
static GLfloat zRot = 0.0F; // z旋转角度
void renderScene(){
std::cout << "renderScene..." << "\n";
// 使用紫色 清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLboolean isGreen = false;
glPushMatrix();
glRotatef(xRot, 1.0F, 0.0F, 0.0F); // 绕 X 轴旋转
glRotatef(yRot, 0.0F, 1.0F, 0.0F); // 绕 Y 轴旋转
glRotatef(zRot, 0.0F, 0.0F, 1.0F); // 绕 Z 轴旋转
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0F, 0.0F, 80.0F); // 圆锥顶点,指向屏幕外
for (GLfloat angle = 0.0F, i = 0; angle < 2.0F * PI; angle += PI / 8.0F, ++i) {
glVertex3f(RADIUS * std::cos(angle), RADIUS * std::sin(angle), 0.0F);
if (isGreen) {
glColor3f(0.0F, 1.0F, 0.0F); // 绿色
} else {
glColor3f(1.0F, 0.0F, 0.0F); // 红色
}
isGreen = !isGreen;
}
glVertex3f(RADIUS, 0.0F, 0.0F); // 闭合圆锥底面
glEnd();
// 底盖
glFrontFace(GL_CW); // 底面从外部看是顺时针,临时翻转
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0F, 0.0F, 0.0F); // 圆锥底面中心点
for (GLfloat angle = 0.0F; angle < 2.0F * PI; angle += PI / 8.0F) { // 或者顺时针绘制无需 修改 环绕
glVertex3f(RADIUS * std::cos(angle), RADIUS * std::sin(angle), 0.0F);
if (isGreen) {
glColor3f(0.0F, 1.0F, 0.0F); // 绿色
} else {
glColor3f(1.0F, 0.0F, 0.0F); // 红色
}
isGreen = !isGreen;
}
glVertex3f(RADIUS, 0.0F, 0.0F); // 闭合圆锥底面
glEnd();
glFrontFace(GL_CCW); // 恢复默认 为下一帧 渲染恢复默认CCW
glPopMatrix();
glutSwapBuffers(); // 交换缓冲区
}
// 首先调用
void setupRc(){
std::cout << "setupRc..." << "\n";
// 使用紫色清除窗口
glClearColor(0.6F, 0.4F, 0.7F, 1.0F);
// 使用红色画笔
glColor3f(1.0F, 0.0F, 0.0F);
glShadeModel(GL_FLAT); // 设置为平面着色
glEnable(GL_DEPTH_TEST); // 启用深度测试
glEnable(GL_CULL_FACE); // 启用面剔除
}
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case 27: // ESC 键
case 'q':
case 'Q':
std::cout << "keyboard close..." << "\n";
exit(0);
break;
case 'a':
case 'A':
zRot -= 5.0F; // 绕 Z 轴逆时针旋转
glutPostRedisplay();
break;
case 'd':
case 'D':
zRot += 5.0F; // 绕 Z 轴顺时针旋转
glutPostRedisplay();
break;
default:
break;
}
}
void specialKeys(const int key, const int x, const int y) {
std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case GLUT_KEY_UP:
xRot -= 5.0F;
break;
case GLUT_KEY_DOWN:
xRot += 5.0F;
break;
case GLUT_KEY_LEFT:
yRot -= 5.0F;
break;
case GLUT_KEY_RIGHT:
yRot += 5.0F;
break;
default:
break;
}
// Refresh the Window
glutPostRedisplay();
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void changeSize(const GLsizei w, const GLsizei h){
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
const GLfloat aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE);
} else {
glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE, COORDINATE_SIZE);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv){
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:双缓冲 + RGBA
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutSpecialFunc(specialKeys); // 特殊键事件
glutKeyboardFunc(keyboard); // 普通键事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
// 设置 OpenGL 环境
setupRc();
// 获取支持的线宽范围
GLfloat lineWidthRange[2];
glGetFloatv(GL_LINE_WIDTH_RANGE, lineWidthRange);
// 获取支持的线宽精度
GLfloat lineWidthGranularity;
glGetFloatv(GL_LINE_WIDTH_GRANULARITY, &lineWidthGranularity);
std::cout << std::format("lineWidthRange: [{}, {}], lineWidthGranularity: {}", lineWidthRange[0], lineWidthRange[1], lineWidthGranularity) << "\n";
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}
线条形状的圆锥体
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <OpenGL/gl.h>
#include <cstdlib>
#include <iostream>
#include <format>
#include <numbers>
// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;
static constexpr GLfloat RADIUS = 50.0F;
// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
static GLfloat zRot = 0.0F; // z旋转角度
void renderScene(){
std::cout << "renderScene..." << "\n";
// 使用紫色 清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLboolean isGreen = false;
glPushMatrix();
glRotatef(xRot, 1.0F, 0.0F, 0.0F); // 绕 X 轴旋转
glRotatef(yRot, 0.0F, 1.0F, 0.0F); // 绕 Y 轴旋转
glRotatef(zRot, 0.0F, 0.0F, 1.0F); // 绕 Z 轴旋转
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0F, 0.0F, 80.0F); // 圆锥顶点,指向屏幕外
for (GLfloat angle = 0.0F, i = 0; angle < 2.0F * PI; angle += PI / 8.0F, ++i) {
glVertex3f(RADIUS * std::cos(angle), RADIUS * std::sin(angle), 0.0F);
if (isGreen) {
glColor3f(0.0F, 1.0F, 0.0F); // 绿色
} else {
glColor3f(1.0F, 0.0F, 0.0F); // 红色
}
isGreen = !isGreen;
}
glVertex3f(RADIUS, 0.0F, 0.0F); // 闭合圆锥底面
glEnd();
// 底盖
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0F, 0.0F, 0.0F); // 圆锥底面中心点
for (GLfloat angle = 0.0F; angle < 2.0F * PI; angle += PI / 8.0F) {
glVertex3f(RADIUS * std::cos(angle), RADIUS * std::sin(angle), 0.0F);
if (isGreen) {
glColor3f(0.0F, 1.0F, 0.0F); // 绿色
} else {
glColor3f(1.0F, 0.0F, 0.0F); // 红色
}
isGreen = !isGreen;
}
glVertex3f(RADIUS, 0.0F, 0.0F); // 闭合圆锥底面
glEnd();
glPopMatrix();
glutSwapBuffers(); // 交换缓冲区
}
// 首先调用
void setupRc(){
std::cout << "setupRc..." << "\n";
// 使用紫色清除窗口
glClearColor(0.6F, 0.4F, 0.7F, 1.0F);
// 使用红色画笔
glColor3f(1.0F, 0.0F, 0.0F);
glShadeModel(GL_FLAT); // 设置为平面着色
glEnable(GL_DEPTH_TEST); // 启用深度测试
// glEnable(GL_CULL_FACE);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // 设置为线框模式
}
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case 27: // ESC 键
case 'q':
case 'Q':
std::cout << "keyboard close..." << "\n";
exit(0);
break;
case 'a':
case 'A':
zRot -= 5.0F; // 绕 Z 轴逆时针旋转
glutPostRedisplay();
break;
case 'd':
case 'D':
zRot += 5.0F; // 绕 Z 轴顺时针旋转
glutPostRedisplay();
break;
default:
break;
}
}
void specialKeys(const int key, const int x, const int y) {
std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case GLUT_KEY_UP:
xRot -= 5.0F;
break;
case GLUT_KEY_DOWN:
xRot += 5.0F;
break;
case GLUT_KEY_LEFT:
yRot -= 5.0F;
break;
case GLUT_KEY_RIGHT:
yRot += 5.0F;
break;
default:
break;
}
// Refresh the Window
glutPostRedisplay();
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void changeSize(const GLsizei w, const GLsizei h){
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
const GLfloat aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE);
} else {
glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE, COORDINATE_SIZE);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv){
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:双缓冲 + RGBA
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutSpecialFunc(specialKeys); // 特殊键事件
glutKeyboardFunc(keyboard); // 普通键事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
// 设置 OpenGL 环境
setupRc();
// 获取支持的线宽范围
GLfloat lineWidthRange[2];
glGetFloatv(GL_LINE_WIDTH_RANGE, lineWidthRange);
// 获取支持的线宽精度
GLfloat lineWidthGranularity;
glGetFloatv(GL_LINE_WIDTH_GRANULARITY, &lineWidthGranularity);
std::cout << std::format("lineWidthRange: [{}, {}], lineWidthGranularity: {}", lineWidthRange[0], lineWidthRange[1], lineWidthGranularity) << "\n";
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}
绘制四边形
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <OpenGL/gl.h>
#include <cstdlib>
#include <iostream>
#include <format>
#include <numbers>
// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;
static constexpr GLfloat RADIUS = 50.0F;
// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
static GLfloat zRot = 0.0F; // z旋转角度
void renderScene(){
std::cout << "renderScene..." << "\n";
// 使用紫色 清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLboolean isGreen = false;
glPushMatrix();
glRotatef(xRot, 1.0F, 0.0F, 0.0F); // 绕 X 轴旋转
glRotatef(yRot, 0.0F, 1.0F, 0.0F); // 绕 Y 轴旋转
glRotatef(zRot, 0.0F, 0.0F, 1.0F); // 绕 Z 轴旋转
glBegin(GL_QUADS);
glVertex3f(-RADIUS, -RADIUS, 0.0F);
glVertex3f(RADIUS, -RADIUS, 0.0F);
glVertex3f(RADIUS, RADIUS, 0.0F);
glVertex3f(-RADIUS, RADIUS, 0.0F);
glEnd();
glPopMatrix();
glutSwapBuffers(); // 交换缓冲区
}
// 首先调用
void setupRc(){
std::cout << "setupRc..." << "\n";
// 使用紫色清除窗口
glClearColor(0.6F, 0.4F, 0.7F, 1.0F);
// 使用红色画笔
glColor3f(1.0F, 0.0F, 0.0F);
}
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case 27: // ESC 键
case 'q':
case 'Q':
std::cout << "keyboard close..." << "\n";
exit(0);
break;
case 'a':
case 'A':
zRot -= 5.0F; // 绕 Z 轴逆时针旋转
glutPostRedisplay();
break;
case 'd':
case 'D':
zRot += 5.0F; // 绕 Z 轴顺时针旋转
glutPostRedisplay();
break;
default:
break;
}
}
void specialKeys(const int key, const int x, const int y) {
std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case GLUT_KEY_UP:
xRot -= 5.0F;
break;
case GLUT_KEY_DOWN:
xRot += 5.0F;
break;
case GLUT_KEY_LEFT:
yRot -= 5.0F;
break;
case GLUT_KEY_RIGHT:
yRot += 5.0F;
break;
default:
break;
}
// Refresh the Window
glutPostRedisplay();
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void changeSize(const GLsizei w, const GLsizei h){
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
const GLfloat aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE);
} else {
glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE, COORDINATE_SIZE);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv){
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:双缓冲 + RGBA
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutSpecialFunc(specialKeys); // 特殊键事件
glutKeyboardFunc(keyboard); // 普通键事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
// 设置 OpenGL 环境
setupRc();
// 获取支持的线宽范围
GLfloat lineWidthRange[2];
glGetFloatv(GL_LINE_WIDTH_RANGE, lineWidthRange);
// 获取支持的线宽精度
GLfloat lineWidthGranularity;
glGetFloatv(GL_LINE_WIDTH_GRANULARITY, &lineWidthGranularity);
std::cout << std::format("lineWidthRange: [{}, {}], lineWidthGranularity: {}", lineWidthRange[0], lineWidthRange[1], lineWidthGranularity) << "\n";
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}
点画模式
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <OpenGL/gl.h>
#include <cstdlib>
#include <iostream>
#include <format>
#include <numbers>
// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;
static constexpr GLfloat RADIUS = 50.0F;
// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
static GLfloat zRot = 0.0F; // z旋转角度
void renderScene(){
std::cout << "renderScene..." << "\n";
// 使用紫色 清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLboolean isGreen = false;
glPushMatrix();
glRotatef(xRot, 1.0F, 0.0F, 0.0F); // 绕 X 轴旋转
glRotatef(yRot, 0.0F, 1.0F, 0.0F); // 绕 Y 轴旋转
glRotatef(zRot, 0.0F, 0.0F, 1.0F); // 绕 Z 轴旋转
glBegin(GL_QUAD_STRIP);
glVertex3f(-RADIUS, -RADIUS, 0.0F);
glVertex3f(-RADIUS, RADIUS, 0.0F);
glVertex3f(RADIUS, -RADIUS, 0.0F);
glVertex3f(RADIUS, RADIUS, 0.0F);
glEnd();
glPopMatrix();
glutSwapBuffers(); // 交换缓冲区
}
/**
* 首先调用
* 0000 0000 0x00
* 0000 0001 0x01
* 0000 0010 0x02
* 0000 0011 0x03
* 0000 0100 0x04
* 0000 0101 0x05
* 0000 0110 0x06
* 0000 0111 0x07
* 0000 1000 0x08
* 0000 1001 0x09
* 0000 1010 0x0A
* 0000 1011 0x0B
* 0000 1100 0x0C
* 0000 1101 0x0D
* 0000 1110 0x0E
* 0000 1111 0x0F
*/
void setupRc(){
std::cout << "setupRc..." << "\n";
// 使用紫色清除窗口
glClearColor(0.0F, 0.0F, 0.0F, 1.0F);
// 使用红色画笔
glColor3f(1.0F, 0.0F, 0.0F);
glEnable(GL_POLYGON_SMOOTH); // 开启多边形抗锯齿
glEnable(GL_POLYGON_STIPPLE); // 开启多边形点画功能
const GLubyte pattern[] = {
0x00, 0x00, 0x00, 0x00, // 1
0x00, 0x00, 0x00, 0x00, // 2
0x00, 0x00, 0x00, 0x00, // 3
0x00, 0x00, 0x00, 0x00, // 4
0x00, 0x00, 0x00, 0x00, // 5
0x00, 0x00, 0x00, 0x00, // 6
0x00, 0x00, 0x00, 0xC0, // 7
0x00, 0x00, 0x01, 0xF0, // 8
0x00, 0x00, 0x07, 0xF0, // 9
0x00, 0x00, 0x1F, 0xE0, // 10
0x1F, 0x80, 0x1F, 0xC0, // 11
0x0F, 0xC0, 0x3F, 0x80, // 12
0x07, 0xE0, 0x7E, 0x00, // 13
0x03, 0xF0, 0xFF, 0x80, // 14
0x03, 0xF5, 0xFF, 0xE0, // 15
0x1F, 0xFC, 0xFF, 0xE8, // 16
0xE0, 0x03, 0xF0, 0x01, // 17
0xC0, 0x07, 0xE0, 0x03, // 18
0x80, 0x0F, 0xC0, 0x07, // 19
0x00, 0x1F, 0x80, 0x0F, // 20
0x00, 0x3F, 0x00, 0x1F, // 21
0x00, 0x7E, 0x00, 0x3F, // 22
0x55, 0x55, 0x55, 0x55, // 23
0x55, 0x55, 0x55, 0x55, // 24
0x55, 0x55, 0x55, 0x55, // 25
0x55, 0x55, 0x55, 0x55, // 26
0x55, 0x55, 0x55, 0x55, // 27
0x55, 0x55, 0x55, 0x55, // 28
0x55, 0x55, 0x55, 0x55, // 29
0x55, 0x55, 0x55, 0x55, // 30
0x55, 0x55, 0x55, 0x55, // 31
0x55, 0x55, 0x55, 0x55, // 32
};
glPolygonStipple(pattern);
}
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case 27: // ESC 键
case 'q':
case 'Q':
std::cout << "keyboard close..." << "\n";
exit(0);
break;
case 'a':
case 'A':
zRot -= 5.0F; // 绕 Z 轴逆时针旋转
glutPostRedisplay();
break;
case 'd':
case 'D':
zRot += 5.0F; // 绕 Z 轴顺时针旋转
glutPostRedisplay();
break;
default:
break;
}
}
void specialKeys(const int key, const int x, const int y) {
std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case GLUT_KEY_UP:
xRot -= 5.0F;
break;
case GLUT_KEY_DOWN:
xRot += 5.0F;
break;
case GLUT_KEY_LEFT:
yRot -= 5.0F;
break;
case GLUT_KEY_RIGHT:
yRot += 5.0F;
break;
default:
break;
}
// Refresh the Window
glutPostRedisplay();
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void changeSize(const GLsizei w, const GLsizei h){
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
const GLfloat aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE);
} else {
glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE, COORDINATE_SIZE);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv){
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:双缓冲 + RGBA
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutSpecialFunc(specialKeys); // 特殊键事件
glutKeyboardFunc(keyboard); // 普通键事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
// 设置 OpenGL 环境
setupRc();
// 获取支持的线宽范围
GLfloat lineWidthRange[2];
glGetFloatv(GL_LINE_WIDTH_RANGE, lineWidthRange);
// 获取支持的线宽精度
GLfloat lineWidthGranularity;
glGetFloatv(GL_LINE_WIDTH_GRANULARITY, &lineWidthGranularity);
std::cout << std::format("lineWidthRange: [{}, {}], lineWidthGranularity: {}", lineWidthRange[0], lineWidthRange[1], lineWidthGranularity) << "\n";
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}
画一个四角星
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <OpenGL/gl.h>
#include <cstdlib>
#include <format>
#include <iostream>
#include <numbers>
// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;
static constexpr GLfloat RADIUS = 50.0F;
// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
static GLfloat zRot = 0.0F; // z旋转角度
void renderScene() {
std::cout << "renderScene..." << "\n";
// 使用紫色 清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glRotatef(xRot, 1.0F, 0.0F, 0.0F); // 绕 X 轴旋转
glRotatef(yRot, 0.0F, 1.0F, 0.0F); // 绕 Y 轴旋转
glRotatef(zRot, 0.0F, 0.0F, 1.0F); // 绕 Z 轴旋转
// constexpr GLboolean isGreen = false;
// glBegin(GL_LINE_LOOP);
// // 逆时针绘制外轮廓
// glVertex2f(0.0F, 40.0F); // 上顶点
// glVertex2f(20.0F, 0.0F); // 内右
// glVertex2f(60.0F, -20.0F); // 外右
// glVertex2f(20.0F, -40.0F); // 内右下
// glVertex2f(0.0F, -80.0F); // 下顶点
// glVertex2f(-20.0F, -40.0F); // 内左下
// glVertex2f(-60.0F, -20.0F); // 外左
// glVertex2f(-20.0F, 0.0F); // 内左上
// glEnd();
glBegin(GL_TRIANGLES);
// 上三角: v0=(-20,0), v1=(20,0), v2=(0,40)
// v0→v1 内部边(FALSE), v1→v2 外轮廓(TRUE), v2→v0 外轮廓(TRUE)
glEdgeFlag(GL_FALSE); // v0→v1: 内部横线 不画
glVertex2f(-20.0F, 0.0F);
glEdgeFlag(GL_TRUE); // v1→v2: 外轮廓
glVertex2f(20.0F, 0.0F);
// glEdgeFlag(GL_TRUE); // v2→v0: 外轮廓
glVertex2f(0.0F, 40.0F);
// 左三角: v0=(-20,0), v1=(-60,-20), v2=(-20,-40)
// v0→v1 外轮廓(TRUE), v1→v2 外轮廓(TRUE), v2→v0 内部边(FALSE)
glVertex2f(-20.0F, 0.0F);
glVertex2f(-60.0F, -20.0F);
glEdgeFlag(GL_FALSE); // v2→v0: 内部竖线 不画
glVertex2f(-20.0F, -40.0F);
// 下三角: v0=(-20,-40), v1=(0,-80), v2=(20,-40)
// v0→v1 外轮廓(TRUE), v1→v2 外轮廓(TRUE), v2→v0 内部边(FALSE)
glEdgeFlag(GL_TRUE); // v0→v1: 外轮廓
glVertex2f(-20.0F, -40.0F);
glVertex2f(0.0F, -80.0F);
glEdgeFlag(GL_FALSE); // v2→v0: 内部横线 不画
glVertex2f(20.0F, -40.0F);
// 右三角: v0=(20,0), v1=(60,-20), v2=(20,-40)
// v0→v1 外轮廓(TRUE), v1→v2 外轮廓(TRUE), v2→v0 内部边(FALSE)
glEdgeFlag(GL_TRUE); // v0→v1: 外轮廓
glVertex2f(20.0F, 0.0F);
glVertex2f(60.0F, -20.0F);
glEdgeFlag(GL_FALSE); // v2→v0: 内部竖线 不画
glVertex2f(20.0F, -40.0F);
glEdgeFlag(GL_TRUE);
glEnd();
glPopMatrix();
glutSwapBuffers(); // 交换缓冲区
}
/**
* 首先调用
* 0000 0000 0x00
* 0000 0001 0x01
* 0000 0010 0x02
* 0000 0011 0x03
* 0000 0100 0x04
* 0000 0101 0x05
* 0000 0110 0x06
* 0000 0111 0x07
* 0000 1000 0x08
* 0000 1001 0x09
* 0000 1010 0x0A
* 0000 1011 0x0B
* 0000 1100 0x0C
* 0000 1101 0x0D
* 0000 1110 0x0E
* 0000 1111 0x0F
*/
void setupRc() {
std::cout << "setupRc..." << "\n";
// 使用紫色清除窗口
glClearColor(0.0F, 0.0F, 0.0F, 1.0F);
// 使用白色画笔
glColor3f(1.0F, 1.0F, 1.0F);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // 线框模式
}
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case 27: // ESC 键
case 'q':
case 'Q':
std::cout << "keyboard close..." << "\n";
exit(0);
break;
case 'a':
case 'A':
zRot -= 5.0F; // 绕 Z 轴逆时针旋转
glutPostRedisplay();
break;
case 'd':
case 'D':
zRot += 5.0F; // 绕 Z 轴顺时针旋转
glutPostRedisplay();
break;
default:
break;
}
}
void specialKeys(const int key, const int x, const int y) {
std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y)
<< "\n";
switch (key) {
case GLUT_KEY_UP:
xRot -= 5.0F;
break;
case GLUT_KEY_DOWN:
xRot += 5.0F;
break;
case GLUT_KEY_LEFT:
yRot -= 5.0F;
break;
case GLUT_KEY_RIGHT:
yRot += 5.0F;
break;
default:
break;
}
// Refresh the Window
glutPostRedisplay();
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void changeSize(const GLsizei w, const GLsizei h) {
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
const GLfloat aspectRatio =
static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE,
-COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio,
-COORDINATE_SIZE, COORDINATE_SIZE);
} else {
glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio,
-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE,
COORDINATE_SIZE);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char **argv) {
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:双缓冲 + RGBA
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutSpecialFunc(specialKeys); // 特殊键事件
glutKeyboardFunc(keyboard); // 普通键事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
// 设置 OpenGL 环境
setupRc();
// 获取支持的线宽范围
GLfloat lineWidthRange[2];
glGetFloatv(GL_LINE_WIDTH_RANGE, lineWidthRange);
// 获取支持的线宽精度
GLfloat lineWidthGranularity;
glGetFloatv(GL_LINE_WIDTH_GRANULARITY, &lineWidthGranularity);
std::cout << std::format(
"lineWidthRange: [{}, {}], lineWidthGranularity: {}",
lineWidthRange[0], lineWidthRange[1], lineWidthGranularity)
<< "\n";
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}
螺旋丸
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <OpenGL/gl.h>
#include <cstdlib>
#include <format>
#include <iostream>
#include <numbers>
// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;
static constexpr GLfloat RADIUS = 50.0F;
// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
static GLfloat zRot = 0.0F; // z旋转角度
void renderScene() {
std::cout << "renderScene..." << "\n";
static GLdouble radius = 5.0;
static GLdouble angle = 0.0;
if (angle == 0.0) {
glClear(GL_COLOR_BUFFER_BIT); // 清空屏幕
}
glBegin(GL_POINTS);
glVertex2d(radius * std::cos(angle), radius * std::sin(angle));
glEnd();
radius *= 1.01;
angle += 0.1;
if(angle > 30.0){
std::cout << "reset angle and radius..." << std::endl;
angle = 0.0;
radius = 5.0;
}
glFlush(); // 强制执行所有OpenGL命令
}
// 更好看
void renderScene1() {
std::cout << "renderScene..." << "\n";
static GLdouble radius = 1.0;
static GLdouble angle = 0.0;
if (angle == 0.0) {
glClear(GL_COLOR_BUFFER_BIT); // 清空屏幕
}
glBegin(GL_POINTS);
glVertex2d(radius * std::cos(angle), radius * std::sin(angle));
glEnd();
radius += 0.3; // 阿基米德螺线:每圈间距均匀
angle += 0.1;
if(angle > 30.0){
std::cout << "reset angle and radius..." << std::endl;
angle = 0.0;
radius = 1.0;
}
glFlush(); // 强制执行所有OpenGL命令
}
void setupRc() {
std::cout << "setupRc..." << "\n";
// 使用蓝色清除窗口
glClearColor(0.0F, 0.0F, 1.0F, 1.0F);
glColor3f(0.0F, 1.0F, 0.0F);
}
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case 27: // ESC 键
case 'q':
case 'Q':
std::cout << "keyboard close..." << "\n";
exit(0);
break;
case 'a':
case 'A':
zRot -= 5.0F; // 绕 Z 轴逆时针旋转
glutPostRedisplay();
break;
case 'd':
case 'D':
zRot += 5.0F; // 绕 Z 轴顺时针旋转
glutPostRedisplay();
break;
default:
break;
}
}
void specialKeys(const int key, const int x, const int y) {
std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y)
<< "\n";
switch (key) {
case GLUT_KEY_UP:
xRot -= 5.0F;
break;
case GLUT_KEY_DOWN:
xRot += 5.0F;
break;
case GLUT_KEY_LEFT:
yRot -= 5.0F;
break;
case GLUT_KEY_RIGHT:
yRot += 5.0F;
break;
default:
break;
}
// Refresh the Window
glutPostRedisplay();
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void changeSize(const GLsizei w, const GLsizei h) {
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
const GLfloat aspectRatio =
static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE,
-COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio,
-COORDINATE_SIZE, COORDINATE_SIZE);
} else {
glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio,
-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE,
COORDINATE_SIZE);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void timerFunc(int value) {
std::cout << std::format("timerFunc: value={}", value) << "\n";
// 重新绘制窗口
glutPostRedisplay();
// 再次注册定时器
glutTimerFunc(33, timerFunc, 1);
}
int main(int argc, char **argv) {
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:单缓冲 + RGB
glutInitDisplayMode(GLUT_RGB);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutSpecialFunc(specialKeys); // 特殊键事件
glutKeyboardFunc(keyboard); // 普通键事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
glutTimerFunc(33, timerFunc, 1); // 每隔 33 毫秒调用一次,约 30 FPS
// 设置 OpenGL 环境
setupRc();
// 获取支持的线宽范围
GLfloat lineWidthRange[2];
glGetFloatv(GL_LINE_WIDTH_RANGE, lineWidthRange);
// 获取支持的线宽精度
GLfloat lineWidthGranularity;
glGetFloatv(GL_LINE_WIDTH_GRANULARITY, &lineWidthGranularity);
std::cout << std::format(
"lineWidthRange: [{}, {}], lineWidthGranularity: {}",
lineWidthRange[0], lineWidthRange[1], lineWidthGranularity)
<< "\n";
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}
剪刀裁剪
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <OpenGL/gl.h>
#include <cstdlib>
#include <format>
#include <iostream>
#include <numbers>
// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;
static constexpr GLfloat RADIUS = 50.0F;
// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
static GLfloat zRot = 0.0F; // z旋转角度
void renderScene() {
std::cout << "renderScene..." << "\n";
glClearColor(0.0F, 0.0F, 1.0F, 1.0F); // 设置背景色为黑色
glClear(GL_COLOR_BUFFER_BIT); // 清除颜色缓冲区
glClearColor(1.0F, 0.0F, 0.0F, 1.0F); // 设置背景色为黑色
glScissor(100, 100, 600, 400);
glEnable(GL_SCISSOR_TEST);
glClear(GL_COLOR_BUFFER_BIT); // 清除颜色缓冲区
glClearColor(0.0F, 1.0F, 0.0F, 1.0F); // 设置背景色为黑色
glScissor(200, 200, 400, 200);
glClear(GL_COLOR_BUFFER_BIT); // 清除颜色缓冲区
glDisable(GL_SCISSOR_TEST);
glFlush(); // 强制执行所有OpenGL命令
}
void setupRc() {
std::cout << "setupRc..." << "\n";
}
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case 27: // ESC 键
case 'q':
case 'Q':
std::cout << "keyboard close..." << "\n";
exit(0);
break;
case 'a':
case 'A':
zRot -= 5.0F; // 绕 Z 轴逆时针旋转
glutPostRedisplay();
break;
case 'd':
case 'D':
zRot += 5.0F; // 绕 Z 轴顺时针旋转
glutPostRedisplay();
break;
default:
break;
}
}
void specialKeys(const int key, const int x, const int y) {
std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y)
<< "\n";
switch (key) {
case GLUT_KEY_UP:
xRot -= 5.0F;
break;
case GLUT_KEY_DOWN:
xRot += 5.0F;
break;
case GLUT_KEY_LEFT:
yRot -= 5.0F;
break;
case GLUT_KEY_RIGHT:
yRot += 5.0F;
break;
default:
break;
}
// Refresh the Window
glutPostRedisplay();
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void changeSize(const GLsizei w, const GLsizei h) {
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
const GLfloat aspectRatio =
static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE,
-COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio,
-COORDINATE_SIZE, COORDINATE_SIZE);
} else {
glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio,
-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE,
COORDINATE_SIZE);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char **argv) {
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:单缓冲 + RGB
glutInitDisplayMode(GLUT_RGB);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutSpecialFunc(specialKeys); // 特殊键事件
glutKeyboardFunc(keyboard); // 普通键事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
// 设置 OpenGL 环境
setupRc();
// 获取支持的线宽范围
GLfloat lineWidthRange[2];
glGetFloatv(GL_LINE_WIDTH_RANGE, lineWidthRange);
// 获取支持的线宽精度
GLfloat lineWidthGranularity;
glGetFloatv(GL_LINE_WIDTH_GRANULARITY, &lineWidthGranularity);
std::cout << std::format(
"lineWidthRange: [{}, {}], lineWidthGranularity: {}",
lineWidthRange[0], lineWidthRange[1], lineWidthGranularity)
<< "\n";
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}
螺旋模版图案
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <OpenGL/gl.h>
#include <cstdlib>
#include <format>
#include <iostream>
#include <numbers>
// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;
static constexpr GLfloat RADIUS = 50.0F;
// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
static GLfloat zRot = 0.0F; // z旋转角度
// 正方形的大小
static constexpr GLfloat RECT_SIZE = 25.0F;
// 变量
static GLfloat xPos = 0.0F, yPos = 0.0F; // 正方形的初始位置
static GLfloat windowWidthHalf = 0.0F, windowHeightHalf = 0.0F; // 窗口的宽度和高度
// 步进的大小
static GLfloat xStep = 1.0F, yStep = 1.0F;
void renderScene() {
std::cout << "renderScene..." << "\n";
glClearStencil(0x0);
glEnable(GL_STENCIL_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glStencilFunc(GL_NEVER, 0x0, 0x0);
glStencilOp(GL_INCR, GL_INCR, GL_INCR);
GLdouble radius = 0.1;
glBegin(GL_LINE_STRIP);
for (GLfloat angle = 0.0F; angle <= 2 * PI * 65; angle += 0.1F) {
glVertex2f(radius * cos(angle), radius * sin(angle));
radius += 0.1;
}
glEnd();
glStencilFunc(GL_NOTEQUAL, 0x1, 0x1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glColor3f(1.0F, 0.0F, 0.0F);
glRectf(xPos, yPos, xPos + RECT_SIZE, yPos - RECT_SIZE);
glutSwapBuffers();
}
void setupRc() {
std::cout << "setupRc..." << "\n";
glClearColor(0.0F, 0.0F, 1.0F, 1.0F); // 设置背景色为蓝色
glColor3f(1.0F, 1.0F, 1.0F); // 设置绘制颜色为白色
}
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
switch (key) {
case 27: // ESC 键
case 'q':
case 'Q':
std::cout << "keyboard close..." << "\n";
exit(0);
break;
case 'a':
case 'A':
zRot -= 5.0F; // 绕 Z 轴逆时针旋转
glutPostRedisplay();
break;
case 'd':
case 'D':
zRot += 5.0F; // 绕 Z 轴顺时针旋转
glutPostRedisplay();
break;
default:
break;
}
}
void specialKeys(const int key, const int x, const int y) {
std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y)
<< "\n";
switch (key) {
case GLUT_KEY_UP:
xRot -= 5.0F;
break;
case GLUT_KEY_DOWN:
xRot += 5.0F;
break;
case GLUT_KEY_LEFT:
yRot -= 5.0F;
break;
case GLUT_KEY_RIGHT:
yRot += 5.0F;
break;
default:
break;
}
// Refresh the Window
glutPostRedisplay();
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void changeSize(const GLsizei w, const GLsizei h) {
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
const GLfloat aspectRatio =
static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE,
-COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio,
-COORDINATE_SIZE, COORDINATE_SIZE);
windowWidthHalf = 100.0F;
windowHeightHalf = 100.0F / aspectRatio;
} else {
glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio,
-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE,
COORDINATE_SIZE);
windowWidthHalf = 100.0F * aspectRatio;
windowHeightHalf = 100.0F;
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void timerFunc(const int value) {
std::cout << std::format("timerFunc: value={}, windowWidthHalf={}, windowHeightHalf={}", value, windowWidthHalf, windowHeightHalf) << "\n";
if (xPos + RECT_SIZE >= windowWidthHalf || xPos <= -windowWidthHalf) {
xStep = -xStep;
}
if(yPos - RECT_SIZE <= -windowHeightHalf || yPos >= windowHeightHalf){
yStep = -yStep;
}
xPos += xStep;
yPos += yStep;
// 窗口变小了,正方形可能会超出窗口范围,需要重新计算位置
if (xPos + RECT_SIZE > windowWidthHalf) {
xPos = windowWidthHalf - RECT_SIZE;
} else if (xPos < -windowWidthHalf) {
xPos = -windowWidthHalf;
}
if (yPos > windowHeightHalf) {
yPos = windowHeightHalf;
} else if (yPos - RECT_SIZE < -windowHeightHalf) {
yPos = -windowHeightHalf + RECT_SIZE;
}
glutPostRedisplay(); // 重新绘制窗口
glutTimerFunc(33, timerFunc, 1); // 每隔 33 毫秒调用一次,约 30 FPS
}
int main(int argc, char **argv) {
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:单缓冲 + RGB + 模板缓冲区
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_STENCIL);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutSpecialFunc(specialKeys); // 特殊键事件
glutKeyboardFunc(keyboard); // 普通键事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
glutTimerFunc(33, timerFunc, 1); // 每隔 33 毫秒调用一次,约 30 FPS
// 设置 OpenGL 环境
setupRc();
// 获取支持的线宽范围
GLfloat lineWidthRange[2];
glGetFloatv(GL_LINE_WIDTH_RANGE, lineWidthRange);
// 获取支持的线宽精度
GLfloat lineWidthGranularity;
glGetFloatv(GL_LINE_WIDTH_GRANULARITY, &lineWidthGranularity);
std::cout << std::format(
"lineWidthRange: [{}, {}], lineWidthGranularity: {}",
lineWidthRange[0], lineWidthRange[1], lineWidthGranularity)
<< "\n";
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}

浙公网安备 33010602011771号