OpenGL 蓝书学习(第四版)第二章

OpenGL 蓝书学习(第四版)第二章

买了OpenGL蓝书第四版和OpenGL蓝书第七版,先看第四版在看第七版。

环境搭建

环境配置
vscodemacbook proclangdcmake, 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";
posted @ 2026-07-26 11:41  爱情丶眨眼而去  阅读(3)  评论(0)    收藏  举报