OpenGL 蓝书学习(第四版)第二章
OpenGL 蓝书学习(第四版)第二章
买了OpenGL蓝书第四版和OpenGL蓝书第七版,先看第四版在看第七版。
环境搭建
环境配置
vscode、macbook pro、clangd、cmake, clang++
cmake配置
CmakeList.txt
cmake_minimum_required(VERSION 3.10.0)
project(opengl2_learn01 VERSION 0.1.0 LANGUAGES C CXX)
# ✅ 设置 C++ 标准
set(CMAKE_CXX_STANDARD 26)
set(CMAKE_CXX_STANDARD_REQUIRED ON) # 强制使用指定标准
set(CMAKE_CXX_EXTENSIONS OFF) # 禁用编译器扩展(使用纯标准)
# 查找源文件
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS
"src/*.cpp"
"src/*.c"
)
add_executable(${CMAKE_PROJECT_NAME} main.cpp ${SOURCES})
# 设置头文件包含路径
target_include_directories(${CMAKE_PROJECT_NAME}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include/learn01
)
# 抑制警告
if(APPLE)
target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE GL_SILENCE_DEPRECATION GLUT_SILENCE_DEPRECATION)
endif()
# 查找 OpenGL、GLUT 包
find_package(OpenGL REQUIRED)
find_package(GLUT REQUIRED)
# 链接 OpenGL 和 glfw 库
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE OpenGL::GL GLUT::GLUT)
include(CTest)
enable_testing()
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)
最简单的OpenGL程序
// mac 特有的头文件
#include <GLUT/glut.h>
// exit
#include <cstdlib>
#include <iostream>
#include <format>
void renderScene(){
std::cout << "renderScene..." << "\n";
// 使用紫色 清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT);
// 立即执行所有 OpenGL 命令 glClearColor 和 glClear
glFlush();
}
// 首先调用
void setupRc(){
std::cout << "setupRc..." << "\n";
// 使用紫色清除窗口
glClearColor(0.6F, 0.4F, 0.7F, 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;
default:
break;
}
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
int main(int argc, char** argv){
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:单缓冲 + RGBA
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutKeyboardFunc(keyboard); // 键盘事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
// 设置 OpenGL 环境
setupRc();
// 进入 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>
void renderScene(){
std::cout << "renderScene..." << "\n";
// 使用紫色 清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0F, 0.0F, 0.0F); // 红色
glRectf(-25.0F, 25.0F, 25.0F, -25.0F); // 绘制矩形
glFlush();
}
// 首先调用
void setupRc(){
std::cout << "setupRc..." << "\n";
// 使用紫色清除窗口
glClearColor(0.6F, 0.4F, 0.7F, 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;
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";
GLfloat aspectRatio;
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-100.0, 100.0, -100.0 / aspectRatio, 100.0 / aspectRatio, 1.0, -1.0);
} else {
glOrtho(-100.0 * aspectRatio, 100.0 * aspectRatio, -100.0, 100.0, 1.0, -1.0);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv){
// 初始化 glut 必须在 main() 中调用,且必须在创建窗口之前调用
glutInit(&argc, argv);
// 设置显示模式:单缓冲 + RGB
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
// 设置窗口大小
glutInitWindowSize(800, 600);
glutCreateWindow("Hello World");
// 注册 窗口变化 回调
glutDisplayFunc(renderScene);
// 注册 键盘事件 回调
glutKeyboardFunc(keyboard); // 键盘事件
// 注册 窗口关闭 回调(mac已经移除对其支持)
glutWMCloseFunc(onClose);
glutReshapeFunc(changeSize); // 窗口变化事件
// 设置 OpenGL 环境
setupRc();
// 进入 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 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";
// 使用紫色 清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT);
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.6F, 0.4F, 0.7F, 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;
default:
break;
}
}
// 窗口关闭回调(点击红色关闭按钮)
void onClose() {
std::cout << "window close..." << "\n";
exit(0);
}
void timerFunc(const int value) {
std::cout << std::format("timerFunc: value={}", value) << "\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
}
void changeSize(const GLsizei w, const GLsizei h){
std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
GLfloat aspectRatio;
// 防止除以 0
if (h == 0) {
throw std::runtime_error("h == 0");
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // 投影
glLoadIdentity();
aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
if (w < h) {
glOrtho(-100.0, 100.0, -100.0 / aspectRatio, 100.0 / aspectRatio, 1.0, -1.0);
windowWidthHalf = 100.0F;
windowHeightHalf = 100.0F / aspectRatio;
} else {
glOrtho(-100.0 * aspectRatio, 100.0 * aspectRatio, -100.0, 100.0, 1.0, -1.0);
windowWidthHalf = 100.0F * aspectRatio;
windowHeightHalf = 100.0F;
}
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); // 窗口变化事件
glutTimerFunc(33, timerFunc, 1); // 每隔 33 毫秒调用一次,约 30 FPS
// 设置 OpenGL 环境
setupRc();
// 进入 GLUT 事件处理循环
glutMainLoop();
std::cout << "hello world\n";
return 0;
}
常用方法
// 常见方法
const auto error = glGetError();
std::cout << "error: " << error << "\n";
const auto errorStr = gluErrorString(error);
std::cout << "errorStr: " << errorStr << "\n";
GLint maxTextureSize;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
std::cout << "maxTextureSize: " << maxTextureSize << "\n";
const auto version = glGetString(GL_VERSION);
std::cout << "version: " << version << "\n";
const auto vendor = glGetString(GL_VENDOR);
std::cout << "vendor: " << vendor << "\n";
const auto renderer = glGetString(GL_RENDERER);
std::cout << "renderer: " << renderer << "\n";
const auto shadingLanguageVersion = glGetString(GL_SHADING_LANGUAGE_VERSION);
std::cout << "shadingLanguageVersion: " << shadingLanguageVersion << "\n";
const auto extensions = glGetString(GL_EXTENSIONS);
std::cout << "extensions: " << extensions << "\n";

浙公网安备 33010602011771号