要在Linux系统下使用OpenGL显示图像,需要完成几个关键步骤:初始化窗口、创建上下文、加载纹理以及渲染纹理到屏幕上。以下是一个完整的示例流程和代码。
### 环境准备
在开始之前,确保系统中安装了必要的开发库:
```bash
sudo apt-get install libgl1-mesa-dev libglfw3-dev libpng-dev
```
这里用到了 GLFW 和 GLAD 来管理窗口和 OpenGL 函数指针,并使用 stb_image.h 来加载图片。
### 示例代码
#### 1. 初始化GLFW和GLAD
```c
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#include "stb_image.h"
// 窗口大小
const int WIDTH = 800;
const int HEIGHT = 600;
// 顶点着色器源码
const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec2 aTexCoord;\n"
"out vec2 TexCoord;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos, 1.0);\n"
" TexCoord = aTexCoord;\n"
"}\0";
// 片段着色器源码
const char* fragmentShaderSource = "#version 330 core\n"
"in vec2 TexCoord;\n"
"out vec4 FragColor;\n"
"uniform sampler2D ourTexture;\n"
"void main()\n"
"{\n"
" FragColor = texture(ourTexture, TexCoord);\n"
"}\n\0";
unsigned int loadTexture(char const * path)
{
unsigned int textureID;
glGenTextures(1, &textureID);
int width, height, nrChannels;
unsigned char *data = stbi_load(path, &width, &height, &nrChannels, 0);
if (data)
{
GLenum format;
if (nrChannels == 1)
format = GL_RED;
else if (nrChannels == 3)
format = GL_RGB;
else if (nrChannels == 4)
format = GL_RGBA;
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
stbi_image_free(data);
}
else
{
printf("Failed to load texture %s\n", path);
stbi_image_free(data);
}
return textureID;
}
int main()
{
// 初始化GLFW
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "OpenGL Image Display", NULL, NULL);
if (!window)
{
printf("Failed to create GLFW window\n");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// 加载GLAD
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
printf("Failed to initialize GLAD\n");
return -1;
}
// 设置视口
glViewport(0, 0, WIDTH, HEIGHT);
// 创建并编译着色器程序
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
unsigned int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
// 定义顶点数据
float vertices[] = {
// 位置 // 纹理坐标
1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // 右上角
1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // 右下角
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, // 左下角
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f // 左上角
};
unsigned int indices[] = {
0, 1, 2,
2, 3, 0
};
unsigned int VBO, VAO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// 位置属性
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// 纹理坐标属性
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
// 加载纹理
unsigned int texture = loadTexture("your_image.png"); // 替换为你的图片路径
while (!glfwWindowShouldClose(window))
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// 激活着色器程序
glUseProgram(shaderProgram);
// 绑定纹理
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(glGetUniformLocation(shaderProgram, "ourTexture"), 0);
// 绘制矩形
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
glDeleteProgram(shaderProgram);
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
```
### 编译与运行
确保你已经下载了 `stb_image.h` 并将其放置在项目目录中,然后使用如下命令编译:
```bash
gcc main.c -o display -lglfw -lGL -lm -ldl
./display
```
### 解释说明
- **GLFW** 用于创建窗口并处理输入事件。
- **GLAD** 负责加载 OpenGL 函数指针。
- **纹理加载** 使用 `stb_image.h` 库来读取图像文件。
- **着色器** 分为顶点着色器和片段着色器,负责将纹理映射到几何体上。
- **绘制过程** 将纹理应用到一个四边形上,并通过 OpenGL 渲染出来。
此示例展示了如何在 Linux 系统下使用 OpenGL 显示图像的基本方法,适用于入门级开发者学习和实践[^1]。
---