Windows OpenGL 学习一(OpenGL 环境搭建)

Windows OpenGL 学习一(OpenGL 环境搭建)

我们使用cmake管理项目

1、cmake配置

1)、使用C++26标准语法

# ✅ 设置 C++ 标准
set(CMAKE_CXX_STANDARD 26)
set(CMAKE_CXX_STANDARD_REQUIRED ON)  # 强制使用指定标准
set(CMAKE_CXX_EXTENSIONS OFF)        # 禁用编译器扩展(使用纯标准)

2)查找源文件

# 查找源文件
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS
        "src/*.cpp"
        "src/*.c"
)

3)包含头文件目录

# 设置头文件包含路径
target_include_directories(${CMAKE_PROJECT_NAME}
    PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/learn01
)

以上设置都和OpenGL没有关系


4) 添加glfw库

# 引入FetchContent模块
include(FetchContent)
# ========== 添加 glfw 库 ==========
FetchContent_Declare(
  glfw
  GIT_REPOSITORY https://github.com/glfw/glfw.git
  GIT_TAG        3.3.8
)
FetchContent_MakeAvailable(glfw)
# ========== 添加 glfw 库 ==========

5)链接 OpenGL 和 glfw 库

# 查找 OpenGL 包
find_package(OpenGL REQUIRED)
# 链接 OpenGL 和 glfw 库
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE OpenGL::GL glfw)

6)引入glad头文件

GLAD 官网生成器生成头文件

#ifndef LEARN01_HPP
#define LEARN01_HPP
extern "C" {
#include <glad/glad.h> // 1
#include <GLFW/glfw3.h> // 2
}  
#endif // LEARN01_HPP

glad头文件必须在glfw头文件之前。因为glfw的头文件包含了glad的头文件

# GLAD 官网生成器生成头文件 https://glad.dav1d.de/
# 设置 glad 头文件包含路径
target_include_directories(${CMAKE_PROJECT_NAME}
    PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/learn01
    PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include // 3
)

因为引入glad头文件是使用的

#include <glad/glad.h>

所有cmake引入头文件使用代码3处的方式。
至此环境配置完成!

另一种方式是使用msys2

$ pacman -S mingw-w64-ucrt-x86_64-glfw

cmake

cmake_minimum_required(VERSION 3.10.0)
project(opengl_learn04 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(opengl_learn04 main.cpp ${SOURCES})

target_include_directories(${CMAKE_PROJECT_NAME}
    PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/learn01
    PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
)

# 查找 OpenGL 包
find_package(OpenGL REQUIRED)
# 查找glfw包
find_package(glfw3 REQUIRED)
# 链接 OpenGL 和 glfw 库
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE OpenGL::GL glfw3)

include(CTest)
enable_testing()

set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)

完成最最简单的显示绿色屏幕的程序

learn01.hpp 头文件

#ifndef LEARN01_HPP
#define LEARN01_HPP
extern "C" {
#include <glad/glad.h>
#include <GLFW/glfw3.h> 
}  
#include <iostream>
void learn01();
void simpleOpenGL();
#endif // LEARN01_HPP

learn01.cpp 源文件

#include "learn01.hpp"

void learn01() {
    std::cout << "Learning C++ is fun!" << std::endl;
}
void simpleOpenGL(){
     // 初始化 GLFW
    int result = glfwInit();
    if (result == GLFW_FALSE) {
        std::cerr << "Failed to initialize GLFW\n";
        return;
    }
    // 创建窗口
    GLFWwindow* window = glfwCreateWindow(640, 480, "OpenGL Hello World", nullptr, nullptr);
    if(window == nullptr) {
        std::cerr << "Failed to create GLFW window\n";
        glfwTerminate();
        return;
    }
    glfwMakeContextCurrent(window); // 设置当前上下文
    result = gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
    if (result == 0) {
        std::cerr << "Failed to initialize GLAD\n";
        glfwDestroyWindow(window);
        glfwTerminate();
        return;
    }
    // 主循环
    while (glfwWindowShouldClose(window) == GLFW_FALSE) {
        // 设置背景色为红色(类似 Hello World 效果)
        glClearColor(1.0F, 0.0F, 0.0F, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        glfwSwapBuffers(window);
        glfwPollEvents();
    }
    glfwDestroyWindow(window);
    glfwTerminate();
}

画一个三角形的三个顶点

void simpleOpenGL1(){
    
    // 初始化 GLFW
    int result = glfwInit();
    if (result == GLFW_FALSE) {
        std::cerr << "Failed to initialize GLFW\n";
        return;
    }
    
    // 创建窗口
    GLFWwindow* window = glfwCreateWindow(640, 480, "OpenGL Hello World", nullptr, nullptr);
    if(window == nullptr) {
        std::cerr << "Failed to create GLFW window\n";
        glfwTerminate();
        return;
    }

    glfwMakeContextCurrent(window); // 设置当前上下文

    result = gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
    if (result == 0) {
        std::cerr << "Failed to initialize GLAD\n";
        glfwDestroyWindow(window);
        glfwTerminate();
        return;
    }

    GLint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    GLint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

    const char* vertexShaderSource = R"(
        #version 330 core
        layout(location = 0) in vec4 aPosition;
        void main() {
            gl_Position = aPosition;
        }
    )";

    const char* fragmentShaderSource = R"(
        #version 330 core
        out vec4 FragColor;
        void main() {
            FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 红色
        }
    )";

    glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
    glCompileShader(vertexShader);

    GLint success;
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if(success == GL_FALSE) {
        char infoLog[512];
        glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
        std::cerr << "Vertex shader compilation failed: " << infoLog << std::endl;
        glDeleteShader(vertexShader);
        glfwDestroyWindow(window);
        glfwTerminate();
        return;
    }

    glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
    glCompileShader(fragmentShader);

    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if(success == GL_FALSE) {
        char infoLog[512];
        glGetShaderInfoLog(fragmentShader, 512, nullptr, infoLog);
        std::cerr << "Fragment shader compilation failed: " << infoLog << std::endl;
        glDeleteShader(fragmentShader);
        glfwDestroyWindow(window);
        glfwTerminate();
        return;
    }

    GLint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);

    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if(success == GL_FALSE) {
        char infoLog[512];
        glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);
        std::cerr << "Shader program linking failed: " << infoLog << std::endl;
        glDeleteProgram(shaderProgram);
        glDeleteShader(vertexShader);
        glDeleteShader(fragmentShader);
        glfwDestroyWindow(window);
        glfwTerminate();
        return;
    }

    glUseProgram(shaderProgram);

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    // 设置顶点数据
    const float vertices[] = {
        0.8f,  -0.8f, 0.0f, // 右下
       -0.8f,  -0.8f, 0.0f, // 左下
        0.0f,   0.8f, 0.0f  // 上
    };

    GLuint location = 0;
    glEnableVertexAttribArray(location);
    glVertexAttribPointer(location, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), vertices);
    glClearColor(1.0F, 1.0F, 1.0F, 1.0f);
    
    // 主循环
    while (glfwWindowShouldClose(window) == GLFW_FALSE) {
        glClear(GL_COLOR_BUFFER_BIT);
        glDrawArrays(GL_TRIANGLES, 0, 3); // 绘制三角形
        glfwSwapBuffers(window);
        glfwPollEvents();
    }
    glfwDestroyWindow(window);
    glfwTerminate();
}

使用对象缓冲区画三角形

void simpleOpenGL(){

     // 初始化 GLFW
    int result = glfwInit();
    if (result == GLFW_FALSE) {
        std::cerr << "Failed to initialize GLFW\n";
        return;
    }
    
    // 创建窗口
    GLFWwindow* window = glfwCreateWindow(640, 480, "OpenGL Hello World", nullptr, nullptr);
    if(window == nullptr) {
        std::cerr << "Failed to create GLFW window\n";
        glfwTerminate();
        return;
    }
    
    glfwMakeContextCurrent(window); // 设置当前上下文
    
    result = gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
    if (result == 0) {
        std::cerr << "Failed to initialize GLAD\n";
        glfwDestroyWindow(window);
        glfwTerminate();
        return;
    }

    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

    const char* vertexShaderSource = R"(
        #version 330 core
        layout(location = 0) in vec4 aPosition;
        void main() {
            gl_Position = aPosition;
            gl_PointSize = 50.0;
        }
    )";

    const char* fragmentShaderSource = R"(
        #version 330 core
        out vec4 FragColor;
        void main() {
            FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 红色
        }
    )";

    glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
    glCompileShader(vertexShader);

    GLint success;
    
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if(success == GL_FALSE) {
        char infoLog[512];
        glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
        std::cerr << "Vertex shader compilation failed: " << infoLog << std::endl;
        glDeleteShader(vertexShader);
        glfwDestroyWindow(window);
        glfwTerminate();
        return;
    }

    glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
    glCompileShader(fragmentShader);
    
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if(success == GL_FALSE) {
        char infoLog[512];
        glGetShaderInfoLog(fragmentShader, 512, nullptr, infoLog);
        std::cerr << "Fragment shader compilation failed: " << infoLog << std::endl;
        glDeleteShader(fragmentShader);
        glfwDestroyWindow(window);
        glfwTerminate();
        return;
    }

    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);

    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if(success == GL_FALSE) {
        char infoLog[512];
        glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);
        std::cerr << "Shader program linking failed: " << infoLog << std::endl;
        glDeleteProgram(shaderProgram);
        glDeleteShader(vertexShader);
        glDeleteShader(fragmentShader);
        glfwDestroyWindow(window);
        glfwTerminate();
        return;
    }
    
    glUseProgram(shaderProgram);
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    // 设置顶点数据
    const float vertices[] = {
        0.8f,  -0.8f, 0.0f, // 右下
       -0.8f,  -0.8f, 0.0f, // 左下
        0.0f,   0.8f, 0.0f  // 上
    };

    GLuint VBO;
    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    GLuint VAO;
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);

    // 设置顶点属性指针
    GLuint location = 0;
    glVertexAttribPointer(location, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr);
    glEnableVertexAttribArray(location);

    // 清理状态
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    glClearColor(1.0F, 1.0F, 1.0F, 1.0F); // 设置清屏颜色为白色
    // 启用点大小
    glEnable(GL_PROGRAM_POINT_SIZE);

    // 主循环
    while (glfwWindowShouldClose(window) == GLFW_FALSE) {
        glClear(GL_COLOR_BUFFER_BIT);
        glBindVertexArray(VAO);
        glDrawArrays(GL_POINTS, 0, 3); // 绘制三角形
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glfwDestroyWindow(window);
    glfwTerminate();
}

最简单的 hello world 结束了,有什么不足还请大家指正

posted @ 2025-08-06 21:15  爱情丶眨眼而去  阅读(39)  评论(0)    收藏  举报