GLES2添加颜色数组后三角形无法渲染自定义颜色的问题
GLES2中颜色数组不生效的解决方案
核心问题:GLES2是可编程管线,完全移除了旧OpenGL的固定功能管线支持。你没使用着色器的话,GLES2默认不会处理颜色数据,只会输出白色,这就是颜色不生效的根本原因。
解决步骤
1. 编写并编译着色器程序
必须实现顶点着色器和片段着色器,才能让颜色数据被正确处理:
顶点着色器源码
attribute vec3 aPosition; attribute vec4 aColor; varying vec4 vColor; void main() { gl_Position = vec4(aPosition, 1.0); vColor = aColor; }
片段着色器源码
precision mediump float; varying vec4 vColor; void main() { gl_FragColor = vColor; }
着色器编译与链接函数
GLuint create_shader_program(const char* vertex_src, const char* fragment_src) { // 编译顶点着色器 GLuint vs = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vs, 1, &vertex_src, NULL); glCompileShader(vs); // 编译片段着色器 GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fs, 1, &fragment_src, NULL); glCompileShader(fs); // 链接程序 GLuint program = glCreateProgram(); glAttachShader(program, vs); glAttachShader(program, fs); glLinkProgram(program); // 清理临时对象 glDeleteShader(vs); glDeleteShader(fs); return program; }
2. 初始化阶段配置属性与缓冲区
GLuint program; GLuint vbo[2]; // 0:顶点数据, 1:颜色数据 GLint aPositionLoc, aColorLoc; // 初始化着色器程序 const char* vs_src = "填入顶点着色器源码"; const char* fs_src = "填入片段着色器源码"; program = create_shader_program(vs_src, fs_src); // 获取属性位置 aPositionLoc = glGetAttribLocation(program, "aPosition"); aColorLoc = glGetAttribLocation(program, "aColor"); // 创建缓冲区 glGenBuffers(2, vbo); // 绑定顶点缓冲区并初始化数据 float vertices[] = { 0.0f, 0.5f, 0.0f, -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f }; glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW); // 绑定颜色缓冲区并初始化数据 float colors[] = { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f }; glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_DYNAMIC_DRAW);
3. 每帧绘制流程
// 每帧更新顶点和颜色数据 float new_vertices[] = { /* 新的顶点坐标 */ }; float new_colors[] = { /* 新的颜色值 */ }; // 更新顶点缓冲区 glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(new_vertices), new_vertices); // 更新颜色缓冲区 glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(new_colors), new_colors); // 启用着色器程序 glUseProgram(program); // 设置顶点属性指针 glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); glEnableVertexAttribArray(aPositionLoc); glVertexAttribPointer(aPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0); glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); glEnableVertexAttribArray(aColorLoc); glVertexAttribPointer(aColorLoc, 4, GL_FLOAT, GL_FALSE, 0, 0); // 绘制三角形 glDrawArrays(GL_TRIANGLES, 0, 3); // 禁用属性数组(可选,避免后续冲突) glDisableVertexAttribArray(aPositionLoc); glDisableVertexAttribArray(aColorLoc);
关键注意事项
- 必须调用
glUseProgram(program)确保绘制时使用自定义着色器程序 - 每次绘制前要启用对应的顶点属性数组(
glEnableVertexAttribArray) - 使用
glBufferSubData比重复调用glBufferData更高效,适合每帧更新数据 - 可以通过
glGetProgramiv(program, GL_LINK_STATUS, &status)检查链接是否成功,排查错误
内容的提问来源于stack exchange,提问作者Gopikrishnan
相关产品推荐
相关产品推荐

