下面是一个简单的在Linux上使用OpenGL实现着色器的例子。这个示例展示了如何创建一个窗口,初始化OpenGL,并使用顶点和片段着色器渲染一个三角形。
准备工作
- 确保你已经安装了OpenGL、GLM(用于数学计算)和GLEW(用于管理OpenGL扩展)库。如果没有,请使用包管理器进行安装,例如在Ubuntu中可以运行:
sudo apt-get install libglfw3-dev libglew-dev libglm-dev
- 创建一个新的C++源文件,比如
main.cpp
。
示例代码
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <iostream>
// 顶点着色器源码
const char* vertexShaderSource = R"(
#version 330 core
layout(location = 0) in vec3 aPos;
void main() {
gl_Position = vec4(aPos, 1.0);
}
)";
// 片段着色器源码
const char* fragmentShaderSource = R"(
#version 330 core
out vec4 FragColor;
void main() {
FragColor = vec4(1.0, 0.5, 0.2, 1.0); // 设置颜色为橙色
}
)";
void checkCompileErrors(GLuint shader, std::string type) {
int success;
char infoLog[512];
if (type != "PROGRAM") {
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(shader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n"
<< infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
}
} else {
glGetProgramiv(shader, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shader, 512, NULL, infoLog);
std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n"
<< infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
}
}
}
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(800, 600, "Learn OpenGL", nullptr, nullptr);
if (window == nullptr) {
std::cerr << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// 初始化 GLEW
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK) {
std::cerr << "Failed to initialize GLEW" << std::endl;
return -1;
}
// 定义三角形的顶点数据
float vertices[] = {
0.5f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
-0.5f , 0.5f , 0.0f
};
unsigned int indices[] = {
// 第一部分组成三角形的索引顺序
1 ,2 ,3 ,
// 第二部分组成三角形的索引顺序
// 从上到下,逆时针方向,表示第一个三角形由A B C构成第二个由C A D 构成。
// A -> 第三个点 B -> 第四个点 C -> 第一点 D -> 第二个点
};
GLuint VBO;
GLuint VAO;
GLuint EBO;
glGenVertexArrays(1,&VAO);
glGenBuffers(1,&VBO);
glGenBuffers(1,&EBO);
// 把数组绑定到VAO上面进行操作
//首先我们要告诉OpenGL我们即将做什么。
// bind the Vertex Array Object first, 然后再设置我们的缓冲并给它们链接。
glBindVertexArray(VAO);
//把顶点数据传输给缓冲对象,将其存储在VBO中。
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);
//
// 告诉OpenGL如何解释顶点数据,将位置属性链接到 VBO中的每个属性,
// 对应于 shader 中的位置输入变量aPos。
glVertexAttribPointer(0 ,3 , GL_FLOAT , GL_FALSE ,3 * sizeof(float),(void*)nullptr );
///启用这个属性,以便能够使用它。
glEnableVertexAttribArray(0);
// 分别编译我们的顶点和片段着色器。
GLuint vertexShader;
GLuint fragmentShader;
GLuint shaderProgram;
// 顶点着色器调用相应函数来完成其编译任务。并检查错误。
vertexShader=glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader ,1 ,&vertexShaderSource,NULL );
glCompileShader(vertexShader );
checkCompileErrors(vertexShader ,"VERTEX");
// 分别对片段着色器调用相应函数来完成其编译任务。同样需检查错误。
fragmentShader=glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader ,1,&fragmentShaderSource,NULL );
glCompileShader(fragmentShader );
checkCompileErrors(fragmentShader ,"FRAGMENT");
// 将两者链接到同一个程序当中去。
shaderProgram=glCreateProgram();
glAttachShader(shaderProgram ,vertexShader );
glAttachShader(shaderProgram ,fragmentShader );
glLinkProgram(shaderProgram );
// 删除不再需要的各单独部件代码(这并不会影响已连接程序)。
glDeleteShader(vertexShader );
glDeleteShader(fragmentShader );
// 主循环,直到用户关闭窗口:
while (!glfwWindowShouldClose(window)) {
// 渲染指令:每次渲染之前清空屏幕内容与颜色信息,使之透明黑黑的状态,然后绘制图像。
glClearColor(0.2f,.3f,.3f,.9f );
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// 使用创建好的程序:
glUseProgram(shaderProgram);
// 绘制三角形:
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES,sizeof(indices)/sizeof(unsigned int),GL_UNSIGNED_INT,(void*)nullptr );
// swap前后缓冲,并查询IO事件,触发回调函数:
glfwSwapBuffers(window);
glfwPollEvents();
}
// 清理资源:
glDeleteVertexArrays(1,&VAO);
glDeleteBuffers(1,&VBO);
// 最后终止 GLFW:
glfwTerminate();
return 0;
}
编译与运行
使用以下命令编译该代码:
g++ main.cpp -o opengl_example -lGLEW -lGLFW -lGL
然后运行生成的可执行文件:
./opengl_example
总结
以上代码创建了一个基本的OpenGL应用程序,通过使用顶点和片段着色器来绘制一个橙色的三角形。你可以根据需要修改顶点数据或着色器代码以进行更多实验。确保你的环境中有合适版本的OpenGL驱动程序,并且库正确安装。在开发过程中,可以通过打印日志或添加调试信息来帮助解决可能出现的问题。
内容由零声教学AI助手提供,问题来源于学员提问