FFmpeg4.3系列之52:Android OpenGL实现3D画图及抛骰子案例实战
获取ZY↑↑方打开链接↑↑
OpenGL着色器绘制三角形的代码细节
在OpenGL中使用着色器绘制三角形涉及顶点着色器和片段着色器的编写,以及相关的OpenGL API调用。以下是一个简单的示例,展示了如何使用GLSL(OpenGL Shading Language)编写着色器并绘制一个三角形。
1. 顶点着色器 (vertex shader)
顶点着色器负责处理顶点数据,通常用于顶点变换和光照计算。以下是一个简单的顶点着色器示例,它仅将顶点位置传递给片段着色器:
Glsl
#version 330 corelayout (location = 0) in vec3 aPos; // 顶点位置属性void main(){ gl_Position = vec4(aPos, 1.0); // 将顶点位置传递给片段着色器}
2. 片段着色器 (fragment shader)
片段着色器负责处理每个片段(像素)的颜色。以下是一个简单的片段着色器示例,它将所有片段设置为红色:
Glsl
#version 330 coreout vec4 FragColor;void main(){ FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 设置片段颜色为红色}
3. OpenGL代码 (C++)
接下来是C++中的OpenGL代码,用于设置OpenGL环境、编译着色器、创建VAO/VBO并绘制三角形。
Cpp
#include <GL/glew.h>#include <GLFW/glfw3.h>#include <iostream>// 顶点着色器源码const char* vertexShaderSource = R"(#version 330 corelayout (location = 0) in vec3 aPos;void main(){ gl_Position = vec4(aPos, 1.0);})";// 片段着色器源码const char* fragmentShaderSource = R"(#version 330 coreout vec4 FragColor;void main(){ FragColor = vec4(1.0, 0.0, 0.0, 1.0);})";// 编译着色器unsigned int compileShader(unsigned int type, const char* source) { unsigned int shader = glCreateShader(type); glShaderSource(shader, 1, &source, nullptr); glCompileShader(shader); int success; glGetShaderiv(shader, GL_COMPILE_STATUS, &success); if (!success) { char infoLog[512]; glGetShaderInfoLog(shader, 512, nullptr, infoLog); std::cerr << "ERROR::SHADER::COMPILATION_FAILED\n" << infoLog << std::endl; } return shader;}// 创建着色器程序unsigned int createShaderProgram(const char* vertexShaderSource, const char* fragmentShaderSource) { unsigned int vertexShader = compileShader(GL_VERTEX_SHADER, vertexShaderSource); unsigned int fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSource); unsigned int shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertexShader); glAttachShader(shaderProgram, fragmentShader); glLinkProgram(shaderProgram); int success; glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); if (!success) { char infoLog[512]; glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog); std::cerr << "ERROR::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl; } glDeleteShader(vertexShader); glDeleteShader(fragmentShader); return shaderProgram;}int main() { // 初始化GLFW if (!glfwInit()) { std::cerr << "Failed to initialize GLFW" << std::endl; return -1; } // 创建窗口 GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Window", nullptr, nullptr); if (!window) { 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; } // 构建和编译我们的着色器程序 unsigned int shaderProgram = createShaderProgram(vertexShaderSource, fragmentShaderSource); // 设置顶点数据,并配置顶点属性 float vertices[] = { -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f }; unsigned int VBO, VAO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); // 渲染循环 while (!glfwWindowShouldClose(window)) { // 输入 if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); // 渲染指令 glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // 绘制我们的第一个三角形 glUseProgram(shaderProgram); glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES, 0, 3); // 交换缓冲区 glfwSwapBuffers(window); glfwPollEvents(); } // 清理资源 glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glfwTerminate(); return 0;}
代码说明
- 顶点着色器和片段着色器:使用GLSL语言编写,定义了顶点位置和片段颜色的计算方式。
- 编译着色器:
compileShader函数用于编译顶点着色器和片段着色器。 - 创建着色器程序:
createShaderProgram函数将编译后的顶点着色器和片段着色器链接成一个着色器程序。 - 初始化GLFW和GLEW:设置OpenGL上下文。
- 设置顶点数据:定义三角形的顶点位置,并使用VBO和VAO进行顶点数据的存储和配置。
- 渲染循环:在渲染循环中,清空颜色缓冲区,使用着色器程序绘制三角形,并交换前后缓冲区以显示内容。
确保你已经安装了GLFW和GLEW库,并且正确配置了开发环境以编译和运行此代码。