惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

B
Blog
V
Vulnerabilities – Threatpost
Apple Machine Learning Research
Apple Machine Learning Research
V
V2EX
博客园 - 叶小钗
阮一峰的网络日志
阮一峰的网络日志
人人都是产品经理
人人都是产品经理
Latest news
Latest news
博客园 - 三生石上(FineUI控件)
美团技术团队
aimingoo的专栏
aimingoo的专栏
Google Online Security Blog
Google Online Security Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
T
Threatpost
Y
Y Combinator Blog
T
Tailwind CSS Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
A
Arctic Wolf
C
Cyber Attacks, Cyber Crime and Cyber Security
小众软件
小众软件
Recent Commits to openclaw:main
Recent Commits to openclaw:main
T
Tenable Blog
W
WeLiveSecurity
L
LINUX DO - 热门话题
D
Docker
Cyberwarzone
Cyberwarzone
量子位
A
About on SuperTechFans
The Last Watchdog
The Last Watchdog
雷峰网
雷峰网
C
CERT Recently Published Vulnerability Notes
P
Palo Alto Networks Blog
The Hacker News
The Hacker News
Blog — PlanetScale
Blog — PlanetScale
P
Proofpoint News Feed
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
F
Full Disclosure
The Cloudflare Blog
T
The Blog of Author Tim Ferriss
T
The Exploit Database - CXSecurity.com
Engineering at Meta
Engineering at Meta
O
OpenAI News
Hacker News - Newest:
Hacker News - Newest: "LLM"
Scott Helme
Scott Helme
IT之家
IT之家
S
Secure Thoughts
MongoDB | Blog
MongoDB | Blog
L
Lohrmann on Cybersecurity
博客园 - 司徒正美
Google DeepMind News
Google DeepMind News

博客园 - 华腾智算

smart-water 融合多端协同总体架构设计方案 现代前端架构的核心思想 极简设计框架 跨平台弹性栅格理念设计 多端统一设计理念 一套规则,多端伸缩的UI设计理念 现代栅格设计之一 设计中的栅格系统 智慧水利顶层设计之何为“水利矩阵”与“数字孪生” 从古典Web到AI原生超级应用:团队学习路线与未来架构蓝图 最新架构设计 前端代码规范 v1.0 树型菜单全功能代码 最终最佳实践操作文档:统信UOS VSCode 全栈开发环境配置(基于 Chromium 浏览器) vscode-setting.json配置 VSCode 全栈开发环境初始化设置与跨平台配置指南(Windows/macOS 通用) VScode完整的跨平台适配方案 完整的跨平台 settings.json(飞雪飘鸿优化版) 数字孪生破局之道 雏形 程序方向 web三维 第一步,第一行,开始 绘制三角形 明确目标 从文本文件加载指令到模拟内存中,并显示前11个内存单元的内容 使用Python的pydub库播放音乐并打印二进制数据 python的音频处理 python加密与解密 mainwindows.cpp 十进制数213转换为二进制数的完整过程,使用除2取余法(也称为“重复除法法”) 二进制数 \((-1101.101)_2\) 转换为十进制数 - 华腾智算
完整的GLFW应用程序示例
华腾智算 · 2025-09-28 · via 博客园 - 华腾智算
/*
 * 完整的GLFW应用程序示例
 * 包含窗口创建、输入处理、渲染循环等所有主要功能
 * 每行代码都有详细注释,便于学习GLFW的使用
 */

#include <GLFW/glfw3.h>  // GLFW主头文件
#include <iostream>      // 用于控制台输出
#include <cmath>         // 用于数学计算

// 全局变量定义
GLFWwindow* g_window = nullptr;  // 全局窗口指针
int g_windowWidth = 800;         // 窗口宽度
int g_windowHeight = 600;        // 窗口高度
float g_backgroundColor[3] = {0.2f, 0.3f, 0.3f};  // 背景颜色(RGB)
bool g_wireframeMode = false;    // 线框模式标志

/*
 * 错误回调函数
 * 当GLFW发生错误时自动调用
 */
void errorCallback(int error, const char* description) {
    std::cerr << "GLFW错误 " << error << ": " << description << std::endl;
}

/*
 * 窗口大小改变回调函数
 * 当用户调整窗口大小时自动调用
 */
void framebufferSizeCallback(GLFWwindow* window, int width, int height) {
    g_windowWidth = width;
    g_windowHeight = height;
    
    // 设置视口大小,匹配窗口大小
    glViewport(0, 0, width, height);
    
    std::cout << "窗口大小改变: " << width << " x " << height << std::endl;
}

/*
 * 键盘按键回调函数
 * 当用户按下或释放键盘按键时调用
 */
void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {
    // 只处理按键按下事件,忽略重复和释放事件
    if (action == GLFW_PRESS) {
        switch (key) {
            case GLFW_KEY_ESCAPE:
                // ESC键:关闭窗口
                std::cout << "ESC键按下,关闭窗口" << std::endl;
                glfwSetWindowShouldClose(window, true);
                break;
                
            case GLFW_KEY_SPACE:
                // 空格键:切换背景颜色
                g_backgroundColor[0] = static_cast<float>(rand()) / RAND_MAX;
                g_backgroundColor[1] = static_cast<float>(rand()) / RAND_MAX;
                g_backgroundColor[2] = static_cast<float>(rand()) / RAND_MAX;
                std::cout << "空格键按下,切换背景颜色" << std::endl;
                break;
                
            case GLFW_KEY_W:
                // W键:切换线框模式
                g_wireframeMode = !g_wireframeMode;
                if (g_wireframeMode) {
                    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
                    std::cout << "线框模式: 开启" << std::endl;
                } else {
                    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
                    std::cout << "线框模式: 关闭" << std::endl;
                }
                break;
                
            case GLFW_KEY_F:
                // F键:切换全屏/窗口模式
                static bool fullscreen = false;
                fullscreen = !fullscreen;
                
                if (fullscreen) {
                    // 获取主显示器模式
                    GLFWmonitor* monitor = glfwGetPrimaryMonitor();
                    const GLFWvidmode* mode = glfwGetVideoMode(monitor);
                    
                    // 切换到全屏模式
                    glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
                    std::cout << "切换到全屏模式" << std::endl;
                } else {
                    // 切换到窗口模式
                    glfwSetWindowMonitor(window, nullptr, 100, 100, g_windowWidth, g_windowHeight, 0);
                    std::cout << "切换到窗口模式" << std::endl;
                }
                break;
                
            case GLFW_KEY_P:
                // P键:打印窗口信息
                int x, y;
                glfwGetWindowPos(window, &x, &y);
                std::cout << "窗口位置: (" << x << ", " << y << ")" << std::endl;
                std::cout << "窗口大小: " << g_windowWidth << " x " << g_windowHeight << std::endl;
                break;
        }
    }
}

/*
 * 鼠标移动回调函数
 * 当鼠标移动时调用
 */
void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) {
    // 可以在这里处理鼠标移动逻辑
    // 示例:每100次调用打印一次位置(避免过于频繁的输出)
    static int callCount = 0;
    if (callCount++ % 100 == 0) {
        std::cout << "鼠标位置: (" << xpos << ", " << ypos << ")" << std::endl;
    }
}

/*
 * 鼠标按钮回调函数
 * 当鼠标按钮按下或释放时调用
 */
void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods) {
    if (action == GLFW_PRESS) {
        double xpos, ypos;
        glfwGetCursorPos(window, &xpos, &ypos);
        
        switch (button) {
            case GLFW_MOUSE_BUTTON_LEFT:
                std::cout << "左键点击位置: (" << xpos << ", " << ypos << ")" << std::endl;
                break;
                
            case GLFW_MOUSE_BUTTON_RIGHT:
                std::cout << "右键点击位置: (" << xpos << ", " << ypos << ")" << std::endl;
                break;
                
            case GLFW_MOUSE_BUTTON_MIDDLE:
                std::cout << "中键点击位置: (" << xpos << ", " << ypos << ")" << std::endl;
                break;
        }
    }
}

/*
 * 鼠标滚轮回调函数
 * 当鼠标滚轮滚动时调用
 */
void scrollCallback(GLFWwindow* window, double xoffset, double yoffset) {
    std::cout << "鼠标滚轮: X=" << xoffset << ", Y=" << yoffset << std::endl;
}

/*
 * 窗口焦点回调函数
 * 当窗口获得或失去焦点时调用
 */
void windowFocusCallback(GLFWwindow* window, int focused) {
    if (focused) {
        std::cout << "窗口获得焦点" << std::endl;
    } else {
        std::cout << "窗口失去焦点" << std::endl;
    }
}

/*
 * 窗口图标化回调函数
 * 当窗口被最小化或恢复时调用
 */
void windowIconifyCallback(GLFWwindow* window, int iconified) {
    if (iconified) {
        std::cout << "窗口被最小化" << std::endl;
    } else {
        std::cout << "窗口恢复" << std::endl;
    }
}

/*
 * 初始化GLFW和创建窗口
 * 返回true表示成功,false表示失败
 */
bool initializeGLFW() {
    // 设置错误回调函数
    glfwSetErrorCallback(errorCallback);
    
    // 初始化GLFW库
    if (!glfwInit()) {
        std::cerr << "GLFW初始化失败!" << std::endl;
        return false;
    }
    
    // 配置GLFW窗口属性
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);  // OpenGL主版本号
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);  // OpenGL次版本号
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);  // 使用核心模式
    glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);      // 窗口可调整大小
    glfwWindowHint(GLFW_SAMPLES, 4);                // 4倍多重采样抗锯齿
    
#ifdef __APPLE__
    // macOS需要额外的配置
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
    
    // 创建窗口和OpenGL上下文
    g_window = glfwCreateWindow(g_windowWidth, g_windowHeight, "GLFW完整示例 - 学习OpenGL", nullptr, nullptr);
    if (!g_window) {
        std::cerr << "创建GLFW窗口失败!" << std::endl;
        glfwTerminate();
        return false;
    }
    
    // 将窗口的上下文设置为当前线程的主上下文
    glfwMakeContextCurrent(g_window);
    
    // 设置垂直同步(1表示开启,0表示关闭)
    glfwSwapInterval(1);
    
    // 设置各种回调函数
    glfwSetFramebufferSizeCallback(g_window, framebufferSizeCallback);
    glfwSetKeyCallback(g_window, keyCallback);
    glfwSetCursorPosCallback(g_window, cursorPosCallback);
    glfwSetMouseButtonCallback(g_window, mouseButtonCallback);
    glfwSetScrollCallback(g_window, scrollCallback);
    glfwSetWindowFocusCallback(g_window, windowFocusCallback);
    glfwSetWindowIconifyCallback(g_window, windowIconifyCallback);
    
    // 设置输入模式
    glfwSetInputMode(g_window, GLFW_STICKY_KEYS, GLFW_TRUE);  // 启用粘性键
    glfwSetInputMode(g_window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);  // 正常光标模式
    
    std::cout << "GLFW初始化成功!" << std::endl;
    std::cout << "控制说明:" << std::endl;
    std::cout << "  ESC - 退出程序" << std::endl;
    std::cout << "  空格 - 随机改变背景颜色" << std::endl;
    std::cout << "  W - 切换线框模式" << std::endl;
    std::cout << "  F - 切换全屏/窗口模式" << std::endl;
    std::cout << "  P - 打印窗口信息" << std::endl;
    
    return true;
}

/*
 * 渲染一个简单的旋转三角形
 */
void renderTriangle(float time) {
    // 开始绘制三角形
    glBegin(GL_TRIANGLES);
    
    // 计算旋转角度(随时间变化)
    float angle = time * 50.0f;  // 每秒旋转50度
    
    // 第一个顶点(红色)
    glColor3f(1.0f, 0.0f, 0.0f);  // 红色
    glVertex2f(0.0f * cos(angle) - 0.5f * sin(angle), 
               0.0f * sin(angle) + 0.5f * cos(angle));
    
    // 第二个顶点(绿色)
    glColor3f(0.0f, 1.0f, 0.0f);  // 绿色
    glVertex2f(-0.5f * cos(angle) - (-0.5f) * sin(angle), 
               -0.5f * sin(angle) + (-0.5f) * cos(angle));
    
    // 第三个顶点(蓝色)
    glColor3f(0.0f, 0.0f, 1.0f);  // 蓝色
    glVertex2f(0.5f * cos(angle) - (-0.5f) * sin(angle), 
               0.5f * sin(angle) + (-0.5f) * cos(angle));
    
    glEnd();
}

/*
 * 渲染场景
 */
void renderScene(float time) {
    // 清除颜色缓冲区
    glClear(GL_COLOR_BUFFER_BIT);
    
    // 设置投影矩阵为正交投影
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
    
    // 设置模型视图矩阵
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    
    // 渲染旋转三角形
    renderTriangle(time);
}

/*
 * 主函数 - 程序入口点
 */
int main() {
    std::cout << "启动GLFW应用程序..." << std::endl;
    
    // 初始化GLFW
    if (!initializeGLFW()) {
        return -1;
    }
    
    // 设置初始视口
    glViewport(0, 0, g_windowWidth, g_windowHeight);
    
    // 获取时间基准
    double lastTime = glfwGetTime();
    int frameCount = 0;
    
    // 主渲染循环
    while (!glfwWindowShouldClose(g_window)) {
        // 计算帧率
        double currentTime = glfwGetTime();
        frameCount++;
        
        // 每秒更新一次帧率显示
        if (currentTime - lastTime >= 1.0) {
            std::string title = "GLFW示例 - FPS: " + std::to_string(frameCount);
            glfwSetWindowTitle(g_window, title.c_str());
            frameCount = 0;
            lastTime = currentTime;
        }
        
        // 设置清除颜色(背景色)
        glClearColor(g_backgroundColor[0], g_backgroundColor[1], g_backgroundColor[2], 1.0f);
        
        // 渲染场景
        renderScene(static_cast<float>(currentTime));
        
        // 交换前后缓冲区(双缓冲技术)
        glfwSwapBuffers(g_window);
        
        // 处理事件(输入、窗口事件等)
        glfwPollEvents();
        
        // 检查某些特定按键状态(持续按下的处理)
        if (glfwGetKey(g_window, GLFW_KEY_R) == GLFW_PRESS) {
            // R键持续按下时重置背景颜色
            g_backgroundColor[0] = 0.2f;
            g_backgroundColor[1] = 0.3f;
            g_backgroundColor[2] = 0.3f;
        }
    }
    
    // 清理资源
    glfwDestroyWindow(g_window);
    glfwTerminate();
    
    std::cout << "程序正常退出" << std::endl;
    return 0;
}