欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 幼教 > OpenGL ES 入门指南

OpenGL ES 入门指南

2025/9/20 14:17:51 来源:https://blog.csdn.net/byxdaz/article/details/148739034  浏览:    关键词:OpenGL ES 入门指南

一、OpenGL ES 简介

OpenGL ES (OpenGL for Embedded Systems) 是OpenGL的子集,专为移动设备和嵌入式系统设计。它是智能手机、平板电脑、游戏主机等设备上2D/3D图形渲染的标准API。

二、OpenGL ES版本

  • OpenGL ES 1.x: 固定功能管线

  • OpenGL ES 2.0: 可编程着色器管线,移除了固定功能

  • OpenGL ES 3.0/3.1/3.2: 扩展功能,更多特性

三、基础概念

1. 渲染管线

OpenGL ES 2.0+的可编程管线主要包含:

  1. 顶点着色器 - 处理每个顶点

  2. 图元装配 - 组成点、线、三角形

  3. 光栅化 - 将图元转换为片段

  4. 片段着色器 - 处理每个片段(像素)

  5. 逐片段操作 - 深度测试、混合等

2. 着色器(Shaders)

(1) 着色器类型
着色器类型作用
顶点着色器处理每个顶点的位置、法线、UV坐标等属性
片段着色器计算每个像素(片段)的最终颜色
计算着色器(ES 3.1+)通用计算,用于非图形任务(如物理模拟、粒子系统)
(2) 着色器编写流程
  1. 编写 GLSL ES 代码(顶点/片段着色器)。

  2. 编译着色器glCreateShader + glCompileShader)。

  3. 链接着色器程序glCreateProgram + glLinkProgram)。

  4. 在渲染时使用该程序glUseProgram)。

(3) 语法
(3.1) 语法版本声明

OpenGL ES 着色器需指定版本:

glsl

// OpenGL ES 2.0(WebGL 1.0)
#version 100// OpenGL ES 3.0(WebGL 2.0)
#version 300 es
  • ES 2.0 使用较旧的语法(如 attribute / varying)。

  • ES 3.0+ 使用现代语法(如 in / out / layout)。

(3.2) 变量限定符
顶点着色器输入(Vertex Shader Input)
限定符ES 2.0ES 3.0+说明
顶点属性attributein + layout每个顶点独有的数据(如位置)
统一变量uniformuniform全局常量(如变换矩阵)
顶点→片段着色器传递数据
限定符ES 2.0ES 3.0+说明
插值变量varyingout (VS) → in (FS)光栅化阶段插值(如UV坐标)
片段着色器输出
限定符ES 2.0ES 3.0+说明
最终颜色gl_FragColorout vec4 fragColor片段着色器的输出颜色
(3.3) 精度限定符(Precision Qualifiers)

OpenGL ES 要求显式指定浮点数/整数精度(尤其是片段着色器):

glsl

// 设置默认浮点精度(ES 2.0 片段着色器必须声明)
precision mediump float;// 声明变量时指定精度
highp vec3 position;   // 高精度(32-bit,适合位置)
mediump vec2 uv;       // 中等精度(16-bit,适合UV坐标)
lowp vec4 color;       // 低精度(10-bit,适合颜色)
 (4) OpenGL ES 2.0 着色器示例
(4.1) 顶点着色器(Vertex Shader)

glsl

#version 100
attribute vec3 aPosition;    // 顶点位置
attribute vec2 aTexCoord;    // 纹理坐标
varying vec2 vTexCoord;      // 传递给片段着色器的UVuniform mat4 uMVPMatrix;     // 模型-视图-投影矩阵void main() {gl_Position = uMVPMatrix * vec4(aPosition, 1.0);vTexCoord = aTexCoord;   // 传递UV坐标
}
(4.2) 片段着色器(Fragment Shader)

glsl

#version 100
precision mediump float;     // 必须声明默认精度varying vec2 vTexCoord;      // 来自顶点着色器的UV
uniform sampler2D uTexture;  // 纹理采样器void main() {gl_FragColor = texture2D(uTexture, vTexCoord);
}
 (5) OpenGL ES 3.0 着色器示例
(5.1) 顶点着色器(Vertex Shader)

glsl

#version 300 es
layout(location = 0) in vec3 aPosition;  // 使用 layout 指定属性位置
layout(location = 1) in vec2 aTexCoord;
out vec2 vTexCoord;                      // 输出到片段着色器uniform mat4 uMVPMatrix;void main() {gl_Position = uMVPMatrix * vec4(aPosition, 1.0);vTexCoord = aTexCoord;
}
(5.2) 片段着色器(Fragment Shader)

glsl

#version 300 es
precision mediump float;
in vec2 vTexCoord;           // 来自顶点着色器的输入
uniform sampler2D uTexture;
out vec4 fragColor;          // 输出颜色(替代 gl_FragColor)void main() {fragColor = texture(uTexture, vTexCoord);
}

3. 坐标系统

  • 模型坐标 → 世界坐标 → 视图坐标 → 裁剪坐标 → 屏幕坐标

  • 通过模型(Model)、视图(View)、投影(Projection)矩阵变换

四、环境搭建

4.1 Android 开发环境

  1. 安装 Android Studio

  2. 配置 NDK (Native Development Kit)

  3. 在 CMakeLists.txt 中添加 OpenGL ES 依赖:

cmake

find_library( # Sets the name of the path variable.log-liblog )find_library( gles-libGLESv2 )target_link_libraries( # Specifies the target library.native-lib${log-lib}${gles-lib} )

4.2 iOS 开发环境

  1. 在 Xcode 项目中添加 OpenGLES.framework

  2. 包含头文件:

#import <OpenGLES/ES2/gl.h>
#import <OpenGLES/ES2/glext.h>

五、OpenGL ES 程序示例

初始化 OpenGL ES 上下文

// Android 示例
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, nullptr, nullptr);const EGLint attribs[] = {EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,EGL_SURFACE_TYPE, EGL_WINDOW_BIT,EGL_BLUE_SIZE, 8,EGL_GREEN_SIZE, 8,EGL_RED_SIZE, 8,EGL_DEPTH_SIZE, 16,EGL_NONE
};EGLConfig config;
EGLint numConfigs;
eglChooseConfig(display, attribs, &config, 1, &numConfigs);EGLSurface surface = eglCreateWindowSurface(display, config, window, nullptr);const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2,EGL_NONE
};EGLContext context = eglCreateContext(display, config, nullptr, contextAttribs);
eglMakeCurrent(display, surface, surface, context);

简单的三角形绘制

// 顶点着色器
const char* vertexShaderSource = "attribute vec4 vPosition;""void main() {""   gl_Position = vPosition;""}";// 片段着色器
const char* fragmentShaderSource = "precision mediump float;""void main() {""   gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);""}";// 编译着色器
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
glCompileShader(vertexShader);GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
glCompileShader(fragmentShader);// 创建程序
GLuint program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
glUseProgram(program);// 顶点数据
GLfloat vertices[] = {0.0f,  0.5f, 0.0f,-0.5f, -0.5f, 0.0f,0.5f, -0.5f, 0.0f
};// 创建VBO
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);// 获取顶点属性位置
GLint positionLoc = glGetAttribLocation(program, "vPosition");
glEnableVertexAttribArray(positionLoc);
glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);// 绘制
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);

六、纹理映射

// 加载纹理
GLuint loadTexture(const char* data, int width, int height) {GLuint textureId;glGenTextures(1, &textureId);glBindTexture(GL_TEXTURE_2D, textureId);// 设置纹理参数glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);// 加载纹理数据glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);return textureId;
}// 在着色器中使用纹理
const char* fragmentShaderSource = "precision mediump float;""uniform sampler2D uTexture;""varying vec2 vTexCoord;""void main() {""   gl_FragColor = texture2D(uTexture, vTexCoord);""}";

七、3D 变换

// 在顶点着色器中添加变换矩阵
const char* vertexShaderSource = "uniform mat4 uMVPMatrix;""attribute vec4 vPosition;""attribute vec2 aTexCoord;""varying vec2 vTexCoord;""void main() {""   gl_Position = uMVPMatrix * vPosition;""   vTexCoord = aTexCoord;""}";// C++ 代码中设置矩阵
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>glm::mat4 model = glm::mat4(1.0f);
glm::mat4 view = glm::lookAt(glm::vec3(0.0f, 0.0f, 3.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float)width/(float)height, 0.1f, 100.0f);
glm::mat4 mvp = projection * view * model;GLint mvpLoc = glGetUniformLocation(program, "uMVPMatrix");
glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, glm::value_ptr(mvp));

八、最佳实践

  1. 避免频繁的状态切换: 尽量一次性设置好所有状态

  2. 使用顶点缓冲对象(VBO): 减少CPU-GPU数据传输

  3. 批处理绘制调用: 合并多个小绘制调用

  4. 纹理压缩: 使用ETC/PVRTC等压缩格式

  5. 着色器优化: 减少分支和复杂计算

  6. 帧率控制: 使用垂直同步(VSync)避免过度绘制

九、调试技巧

  1. 使用 glGetError() 检查错误

  2. 在着色器编译后检查日志:

    GLint success;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
    if (!success) {GLchar infoLog[512];glGetShaderInfoLog(shader, 512, nullptr, infoLog);// 输出错误信息
    }
  3. 使用图形调试工具如 RenderDoc 或 Xcode OpenGL ES Debugger

十、高级示例代码

  1. 帧缓冲对象(FBO)离屏渲染

    // OpenGL ES 2.0 FBO 离屏渲染完整示例
    #include <GLES2/gl2.h>
    #include <EGL/egl.h>
    #include <iostream>// 全局变量
    GLuint fbo;                     // 帧缓冲对象
    GLuint colorTexture;            // 颜色附件纹理
    GLuint depthStencilRBO;         // 深度和模板渲染缓冲对象
    GLuint quadVAO;                 // 全屏四边形VAO
    GLuint quadVBO;                 // 全屏四边形VBO
    GLuint sceneProgram;            // 场景着色器程序
    GLuint postProcessProgram;      // 后期处理着色器程序
    int width = 800, height = 600;  // 渲染尺寸// 编译着色器工具函数
    GLuint compileShader(GLenum type, const char* source) {GLuint shader = glCreateShader(type);glShaderSource(shader, 1, &source, NULL);glCompileShader(shader);// 检查编译错误GLint success;glGetShaderiv(shader, GL_COMPILE_STATUS, &success);if (!success) {char infoLog[512];glGetShaderInfoLog(shader, 512, NULL, infoLog);std::cerr << "Shader compilation failed:\n" << infoLog << std::endl;}return shader;
    }// 创建着色器程序工具函数
    GLuint createShaderProgram(const char* vertSource, const char* fragSource) {GLuint vertShader = compileShader(GL_VERTEX_SHADER, vertSource);GLuint fragShader = compileShader(GL_FRAGMENT_SHADER, fragSource);GLuint program = glCreateProgram();glAttachShader(program, vertShader);glAttachShader(program, fragShader);glLinkProgram(program);// 检查链接错误GLint success;glGetProgramiv(program, GL_LINK_STATUS, &success);if (!success) {char infoLog[512];glGetProgramInfoLog(program, 512, NULL, infoLog);std::cerr << "Program linking failed:\n" << infoLog << std::endl;}glDeleteShader(vertShader);glDeleteShader(fragShader);return program;
    }// 初始化FBO和渲染资源
    void initResources() {// ============================================// 1. 创建帧缓冲对象(FBO)// ============================================glGenFramebuffers(1, &fbo);glBindFramebuffer(GL_FRAMEBUFFER, fbo);// ============================================// 2. 创建颜色附件纹理// ============================================glGenTextures(1, &colorTexture);glBindTexture(GL_TEXTURE_2D, colorTexture);// 创建空的纹理(数据传NULL,因为我们要渲染到它)glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);// 设置纹理参数glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);// 将纹理附加到FBO的颜色附件glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);// ============================================// 3. 创建深度和模板渲染缓冲对象(RBO)// ============================================glGenRenderbuffers(1, &depthStencilRBO);glBindRenderbuffer(GL_RENDERBUFFER, depthStencilRBO);// 分配存储空间(24位深度 + 8位模板)glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);// 将RBO附加到FBO的深度和模板附件glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRBO);glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRBO);// ============================================// 4. 检查FBO完整性// ============================================if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {std::cerr << "Framebuffer is not complete!" << std::endl;}// 解绑FBO,回到默认帧缓冲glBindFramebuffer(GL_FRAMEBUFFER, 0);// ============================================// 5. 设置全屏四边形(用于后期处理)// ============================================float quadVertices[] = {// 位置(x,y)   // 纹理坐标(s,t)-1.0f,  1.0f,  0.0f, 1.0f,  // 左上-1.0f, -1.0f,  0.0f, 0.0f,  // 左下1.0f, -1.0f,  1.0f, 0.0f,  // 右下-1.0f,  1.0f,  0.0f, 1.0f,  // 左上1.0f, -1.0f,  1.0f, 0.0f,  // 右下1.0f,  1.0f,  1.0f, 1.0f   // 右上};glGenVertexArrays(1, &quadVAO);glGenBuffers(1, &quadVBO);glBindVertexArray(quadVAO);glBindBuffer(GL_ARRAY_BUFFER, quadVBO);glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), quadVertices, GL_STATIC_DRAW);// 位置属性glEnableVertexAttribArray(0);glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);// 纹理坐标属性glEnableVertexAttribArray(1);glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));// ============================================// 6. 创建场景着色器程序(渲染一个旋转的彩色三角形)// ============================================const char* sceneVertexShader = "attribute vec4 vPosition;""uniform mat4 uMVPMatrix;""varying vec4 vColor;""void main() {""   gl_Position = uMVPMatrix * vPosition;"// 根据位置生成颜色(简单示例)"   vColor = vec4(vPosition.x + 0.5, vPosition.y + 0.5, 0.5, 1.0);""}";const char* sceneFragmentShader = "precision mediump float;""varying vec4 vColor;""void main() {""   gl_FragColor = vColor;""}";sceneProgram = createShaderProgram(sceneVertexShader, sceneFragmentShader);// ============================================// 7. 创建后期处理着色器程序(边缘检测效果)// ============================================const char* postProcessVertexShader = "attribute vec2 aPos;""attribute vec2 aTexCoord;""varying vec2 vTexCoord;""void main() {""   gl_Position = vec4(aPos, 0.0, 1.0);""   vTexCoord = aTexCoord;""}";const char* postProcessFragmentShader = "precision mediump float;""varying vec2 vTexCoord;""uniform sampler2D uTexture;""uniform vec2 uTexelSize;""void main() {"// Sobel边缘检测算子"   vec3 topLeft = texture2D(uTexture, vTexCoord + vec2(-uTexelSize.x, uTexelSize.y)).rgb;""   vec3 top = texture2D(uTexture, vTexCoord + vec2(0.0, uTexelSize.y)).rgb;""   vec3 topRight = texture2D(uTexture, vTexCoord + vec2(uTexelSize.x, uTexelSize.y)).rgb;""   vec3 left = texture2D(uTexture, vTexCoord + vec2(-uTexelSize.x, 0.0)).rgb;""   vec3 center = texture2D(uTexture, vTexCoord).rgb;""   vec3 right = texture2D(uTexture, vTexCoord + vec2(uTexelSize.x, 0.0)).rgb;""   vec3 bottomLeft = texture2D(uTexture, vTexCoord + vec2(-uTexelSize.x, -uTexelSize.y)).rgb;""   vec3 bottom = texture2D(uTexture, vTexCoord + vec2(0.0, -uTexelSize.y)).rgb;""   vec3 bottomRight = texture2D(uTexture, vTexCoord + vec2(uTexelSize.x, -uTexelSize.y)).rgb;"// 计算水平和垂直梯度"   vec3 gx = -topLeft - 2.0 * left - bottomLeft + topRight + 2.0 * right + bottomRight;""   vec3 gy = -topLeft - 2.0 * top - topRight + bottomLeft + 2.0 * bottom + bottomRight;"// 计算梯度幅度"   vec3 edge = sqrt(gx * gx + gy * gy);""   float edgeIntensity = length(edge);"// 输出边缘检测结果(黑色背景+白色边缘)"   gl_FragColor = vec4(vec3(1.0 - edgeIntensity), 1.0);""}";postProcessProgram = createShaderProgram(postProcessVertexShader, postProcessFragmentShader);
    }// 渲染场景到FBO
    void renderSceneToFBO(float angle) {// ============================================// 1. 绑定自定义FBO// ============================================glBindFramebuffer(GL_FRAMEBUFFER, fbo);glViewport(0, 0, width, height);// ============================================// 2. 清除颜色和深度缓冲// ============================================glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// ============================================// 3. 绘制场景(这里是一个旋转的彩色三角形)// ============================================glUseProgram(sceneProgram);// 定义三角形顶点float vertices[] = {0.0f,  0.5f, 0.0f,  // 上顶点-0.5f, -0.5f, 0.0f, // 左下0.5f, -0.5f, 0.0f    // 右下};// 创建旋转矩阵float s = sin(angle), c = cos(angle);float mvpMatrix[] = {c, -s, 0.0f, 0.0f,s,  c, 0.0f, 0.0f,0.0f, 0.0f, 1.0f, 0.0f,0.0f, 0.0f, 0.0f, 1.0f};// 传递矩阵到着色器GLint mvpLoc = glGetUniformLocation(sceneProgram, "uMVPMatrix");glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, mvpMatrix);// 绘制三角形GLuint vbo;glGenBuffers(1, &vbo);glBindBuffer(GL_ARRAY_BUFFER, vbo);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);GLint posLoc = glGetUniformLocation(sceneProgram, "vPosition");glEnableVertexAttribArray(posLoc);glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);glDrawArrays(GL_TRIANGLES, 0, 3);// 清理glDeleteBuffers(1, &vbo);
    }// 渲染后期处理效果
    void renderPostProcessing() {// ============================================// 1. 绑定回默认帧缓冲(屏幕)// ============================================glBindFramebuffer(GL_FRAMEBUFFER, 0);glViewport(0, 0, width, height);glClear(GL_COLOR_BUFFER_BIT);// ============================================// 2. 使用后期处理着色器渲染全屏四边形// ============================================glUseProgram(postProcessProgram);// 绑定FBO的颜色纹理glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, colorTexture);glUniform1i(glGetUniformLocation(postProcessProgram, "uTexture"), 0);// 设置纹理像素大小(用于边缘检测)glUniform2f(glGetUniformLocation(postProcessProgram, "uTexelSize"), 1.0f/width, 1.0f/height);// 绘制全屏四边形glBindVertexArray(quadVAO);glDrawArrays(GL_TRIANGLES, 0, 6);
    }// 主渲染函数
    void renderFrame(float angle) {// 1. 渲染场景到FBOrenderSceneToFBO(angle);// 2. 渲染后期处理效果到屏幕renderPostProcessing();
    }// 清理资源
    void cleanup() {glDeleteFramebuffers(1, &fbo);glDeleteTextures(1, &colorTexture);glDeleteRenderbuffers(1, &depthStencilRBO);glDeleteVertexArrays(1, &quadVAO);glDeleteBuffers(1, &quadVBO);glDeleteProgram(sceneProgram);glDeleteProgram(postProcessProgram);
    }// 示例主循环(伪代码)
    int main() {// 初始化OpenGL ES和EGL(平台相关代码略)initEGLAndOpenGLES();// 初始化资源initResources();// 主循环float angle = 0.0f;while (!shouldClose) {angle += 0.01f;  // 更新旋转角度// 渲染帧renderFrame(angle);// 交换缓冲eglSwapBuffers(eglDisplay, eglSurface);}// 清理资源cleanup();return 0;
    }
  2. 多重采样抗锯齿(MSAA)

    EGL配置设置 (启用MSAA)
    // 选择EGL配置时请求MSAA
    const EGLint attribs[] = {EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,EGL_SURFACE_TYPE, EGL_WINDOW_BIT,EGL_BLUE_SIZE, 8,EGL_GREEN_SIZE, 8,EGL_RED_SIZE, 8,EGL_ALPHA_SIZE, 8,EGL_DEPTH_SIZE, 24,EGL_STENCIL_SIZE, 8,EGL_SAMPLE_BUFFERS, 1,  // 启用多重采样EGL_SAMPLES, 4,         // 4x MSAAEGL_NONE
    };完整代码
    #include <GLES3/gl3.h>
    #include <EGL/egl.h>
    #include <vector>
    #include <cmath>
    #include <iostream>
    #include <glm/glm.hpp>
    #include <glm/gtc/matrix_transform.hpp>
    #include <glm/gtc/type_ptr.hpp>// 顶点着色器
    const char* vertexShaderSource = R"(
    #version 300 es
    precision mediump float;
    layout(location = 0) in vec3 aPos;
    layout(location = 1) in vec3 aColor;out vec3 ourColor;uniform mat4 model;
    uniform mat4 view;
    uniform mat4 projection;void main() {gl_Position = projection * view * model * vec4(aPos, 1.0);ourColor = aColor;
    }
    )";// 片段着色器
    const char* fragmentShaderSource = R"(
    #version 300 es
    precision mediump float;in vec3 ourColor;
    out vec4 FragColor;void main() {FragColor = vec4(ourColor, 1.0);
    }
    )";// 立方体顶点数据
    float vertices[] = {// 位置              // 颜色-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,0.5f,  0.5f, -0.5f, 1.0f, 0.0f, 0.0f,0.5f,  0.5f, -0.5f, 1.0f, 0.0f, 0.0f,-0.5f,  0.5f, -0.5f, 1.0f, 0.0f, 0.0f,-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,// 其他面数据...// 为简洁起见省略,实际使用时需要完整立方体数据
    };GLuint CompileShader(GLenum type, const char* source) {GLuint shader = glCreateShader(type);glShaderSource(shader, 1, &source, nullptr);glCompileShader(shader);GLint success;glGetShaderiv(shader, GL_COMPILE_STATUS, &success);if (!success) {char infoLog[512];glGetShaderInfoLog(shader, 512, nullptr, infoLog);std::cerr << "Shader compilation failed:\n" << infoLog << std::endl;}return shader;
    }GLuint CreateShaderProgram(const char* vertexSource, const char* fragmentSource) {GLuint vertexShader = CompileShader(GL_VERTEX_SHADER, vertexSource);GLuint fragmentShader = CompileShader(GL_FRAGMENT_SHADER, fragmentSource);GLuint program = glCreateProgram();glAttachShader(program, vertexShader);glAttachShader(program, fragmentShader);glLinkProgram(program);GLint success;glGetProgramiv(program, GL_LINK_STATUS, &success);if (!success) {char infoLog[512];glGetProgramInfoLog(program, 512, nullptr, infoLog);std::cerr << "Program linking failed:\n" << infoLog << std::endl;}glDeleteShader(vertexShader);glDeleteShader(fragmentShader);return program;
    }int main() {// 初始化EGLEGLDisplay eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);eglInitialize(eglDisplay, nullptr, nullptr);// 配置MSAAconst EGLint attribs[] = {EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,EGL_SURFACE_TYPE, EGL_WINDOW_BIT,EGL_BLUE_SIZE, 8,EGL_GREEN_SIZE, 8,EGL_RED_SIZE, 8,EGL_ALPHA_SIZE, 8,EGL_DEPTH_SIZE, 24,EGL_STENCIL_SIZE, 8,EGL_SAMPLE_BUFFERS, 1,  // 启用多重采样EGL_SAMPLES, 4,         // 4x MSAAEGL_NONE};EGLint numConfigs;EGLConfig eglConfig;eglChooseConfig(eglDisplay, attribs, &eglConfig, 1, &numConfigs);// 创建窗口表面 (具体平台相关代码省略)EGLSurface eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, nativeWindow, nullptr);// 创建上下文const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3,EGL_NONE};EGLContext eglContext = eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, contextAttribs);eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);// 加载着色器GLuint shaderProgram = CreateShaderProgram(vertexShaderSource, fragmentShaderSource);// 设置顶点缓冲区和属性GLuint 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, 6 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);// 颜色属性glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));glEnableVertexAttribArray(1);// 启用多重采样 (通常默认启用)glEnable(GL_MULTISAMPLE);// 渲染循环while (!shouldClose) {// 清除颜色和深度缓冲glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// 启用深度测试glEnable(GL_DEPTH_TEST);// 使用着色器程序glUseProgram(shaderProgram);// 创建变换矩阵glm::mat4 model = glm::rotate(glm::mat4(1.0f), (float)glfwGetTime(), glm::vec3(0.5f, 1.0f, 0.0f));glm::mat4 view = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -3.0f));glm::mat4 projection = glm::perspective(glm::radians(45.0f), 800.0f / 600.0f, 0.1f, 100.0f);// 传递矩阵到着色器GLint modelLoc = glGetUniformLocation(shaderProgram, "model");GLint viewLoc = glGetUniformLocation(shaderProgram, "view");GLint projLoc = glGetUniformLocation(shaderProgram, "projection");glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));// 渲染立方体glBindVertexArray(VAO);glDrawArrays(GL_TRIANGLES, 0, 36);// 交换缓冲区eglSwapBuffers(eglDisplay, eglSurface);}// 清理资源glDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);glDeleteProgram(shaderProgram);// 清理EGLeglDestroyContext(eglDisplay, eglContext);eglDestroySurface(eglDisplay, eglSurface);eglTerminate(eglDisplay);return 0;
    }
  3. 实例化渲染

    顶点着色器 (instancing.vert)
    #version 300 es
    precision mediump float;// 标准顶点属性
    layout(location = 0) in vec3 aPosition;
    layout(location = 1) in vec3 aNormal;
    layout(location = 2) in vec2 aTexCoord;// 实例化属性 - 每个实例不同
    layout(location = 3) in vec3 aInstancePosition;
    layout(location = 4) in vec3 aInstanceColor;
    layout(location = 5) in float aInstanceScale;// 输出到片段着色器
    out vec3 vNormal;
    out vec2 vTexCoord;
    out vec3 vColor;// 统一变量
    uniform mat4 uViewProjection;void main() {// 应用实例缩放和平移vec3 position = aPosition * aInstanceScale + aInstancePosition;gl_Position = uViewProjection * vec4(position, 1.0);vNormal = aNormal;vTexCoord = aTexCoord;vColor = aInstanceColor;
    }片段着色器 (instancing.frag)
    #version 300 es
    precision mediump float;// 从顶点着色器输入
    in vec3 vNormal;
    in vec2 vTexCoord;
    in vec3 vColor;// 输出颜色
    out vec4 fragColor;void main() {// 简单的光照计算vec3 lightDir = normalize(vec3(0.5, 1.0, 0.7));float diff = max(dot(normalize(vNormal), lightDir), 0.2);vec3 lighting = vColor * (diff + 0.2); // 环境光+漫反射fragColor = vec4(lighting, 1.0);
    }C++ 主程序 (main.cpp)
    #include <GLES3/gl3.h>
    #include <EGL/egl.h>
    #include <vector>
    #include <cmath>
    #include <iostream>// 简单的立方体顶点数据
    const float cubeVertices[] = {// 位置              // 法线           // 纹理坐标-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f,0.5f,  0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,0.5f,  0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,-0.5f,  0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,// 其他面的数据...// 为简洁起见省略,实际使用时需要完整立方体数据
    };// 编译着色器
    GLuint CompileShader(GLenum type, const char* source) {GLuint shader = glCreateShader(type);glShaderSource(shader, 1, &source, nullptr);glCompileShader(shader);// 检查编译错误GLint success;glGetShaderiv(shader, GL_COMPILE_STATUS, &success);if (!success) {char infoLog[512];glGetShaderInfoLog(shader, 512, nullptr, infoLog);std::cerr << "Shader compilation failed:\n" << infoLog << std::endl;}return shader;
    }// 创建着色器程序
    GLuint CreateShaderProgram(const char* vertexSource, const char* fragmentSource) {GLuint vertexShader = CompileShader(GL_VERTEX_SHADER, vertexSource);GLuint fragmentShader = CompileShader(GL_FRAGMENT_SHADER, fragmentSource);GLuint program = glCreateProgram();glAttachShader(program, vertexShader);glAttachShader(program, fragmentShader);glLinkProgram(program);// 检查链接错误GLint success;glGetProgramiv(program, GL_LINK_STATUS, &success);if (!success) {char infoLog[512];glGetProgramInfoLog(program, 512, nullptr, infoLog);std::cerr << "Program linking failed:\n" << infoLog << std::endl;}glDeleteShader(vertexShader);glDeleteShader(fragmentShader);return program;
    }int main() {// 初始化EGL和OpenGL ES (平台相关代码省略)// 假设已经创建了有效的EGL上下文// 加载着色器const char* vertexShaderSource = "..."; // 上面顶点着色器代码const char* fragmentShaderSource = "..."; // 上面片段着色器代码GLuint shaderProgram = CreateShaderProgram(vertexShaderSource, fragmentShaderSource);// 设置立方体VAOGLuint cubeVAO, cubeVBO;glGenVertexArrays(1, &cubeVAO);glGenBuffers(1, &cubeVBO);glBindVertexArray(cubeVAO);glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), cubeVertices, GL_STATIC_DRAW);// 顶点属性// 位置glEnableVertexAttribArray(0);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);// 法线glEnableVertexAttribArray(1);glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));// 纹理坐标glEnableVertexAttribArray(2);glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));// 实例化数据const int instanceCount = 1000;std::vector<glm::vec3> instancePositions;std::vector<glm::vec3> instanceColors;std::vector<float> instanceScales;// 生成随机实例数据for (int i = 0; i < instanceCount; ++i) {// 在球面上随机分布float radius = 5.0f;float theta = static_cast<float>(rand()) / RAND_MAX * 2.0f * M_PI;float phi = static_cast<float>(rand()) / RAND_MAX * M_PI;instancePositions.emplace_back(radius * sin(phi) * cos(theta),radius * sin(phi) * sin(theta),radius * cos(phi));instanceColors.emplace_back(static_cast<float>(rand()) / RAND_MAX,static_cast<float>(rand()) / RAND_MAX,static_cast<float>(rand()) / RAND_MAX);instanceScales.push_back(0.1f + static_cast<float>(rand()) / RAND_MAX * 0.2f);}// 实例化VBOGLuint instanceVBOs[3];glGenBuffers(3, instanceVBOs);// 位置glBindBuffer(GL_ARRAY_BUFFER, instanceVBOs[0]);glBufferData(GL_ARRAY_BUFFER, instanceCount * sizeof(glm::vec3), instancePositions.data(), GL_STATIC_DRAW);glEnableVertexAttribArray(3);glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), (void*)0);glVertexAttribDivisor(3, 1); // 告诉OpenGL这是每实例数据// 颜色glBindBuffer(GL_ARRAY_BUFFER, instanceVBOs[1]);glBufferData(GL_ARRAY_BUFFER, instanceCount * sizeof(glm::vec3), instanceColors.data(), GL_STATIC_DRAW);glEnableVertexAttribArray(4);glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), (void*)0);glVertexAttribDivisor(4, 1);// 缩放glBindBuffer(GL_ARRAY_BUFFER, instanceVBOs[2]);glBufferData(GL_ARRAY_BUFFER, instanceCount * sizeof(float), instanceScales.data(), GL_STATIC_DRAW);glEnableVertexAttribArray(5);glVertexAttribPointer(5, 1, GL_FLOAT, GL_FALSE, sizeof(float), (void*)0);glVertexAttribDivisor(5, 1);glBindVertexArray(0);// 设置视口glViewport(0, 0, 800, 600);// 简单的视图投影矩阵glm::mat4 view = glm::lookAt(glm::vec3(0.0f, 0.0f, 10.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));glm::mat4 projection = glm::perspective(glm::radians(45.0f), 800.0f / 600.0f, 0.1f, 100.0f);glm::mat4 viewProjection = projection * view;// 渲染循环while (!shouldClose) { // shouldClose由平台代码控制glClearColor(0.1f, 0.1f, 0.1f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// 启用深度测试glEnable(GL_DEPTH_TEST);// 使用着色器glUseProgram(shaderProgram);// 上传视图投影矩阵GLuint viewProjLoc = glGetUniformLocation(shaderProgram, "uViewProjection");glUniformMatrix4fv(viewProjLoc, 1, GL_FALSE, glm::value_ptr(viewProjection));// 绘制实例化立方体glBindVertexArray(cubeVAO);glDrawArraysInstanced(GL_TRIANGLES, 0, 36, instanceCount); // 假设完整立方体有36个顶点glBindVertexArray(0);// 交换缓冲区eglSwapBuffers(eglDisplay, eglSurface);}// 清理glDeleteVertexArrays(1, &cubeVAO);glDeleteBuffers(1, &cubeVBO);glDeleteBuffers(3, instanceVBOs);glDeleteProgram(shaderProgram);return 0;
    }
  4. 计算着色器(OpenGL ES 3.1+)

    #include <GLES3/gl31.h>
    #include <EGL/egl.h>
    #include <iostream>
    #include <vector>// 计算着色器源码 - 简单数组相加
    const char* computeShaderSource = R"(
    #version 310 es
    layout(local_size_x = 1) in;  // 定义工作组大小layout(binding = 0) buffer InputA {float a[];
    };layout(binding = 1) buffer InputB {float b[];
    };layout(binding = 2) buffer Output {float result[];
    };void main() {uint index = gl_GlobalInvocationID.x;result[index] = a[index] + b[index];
    }
    )";// 顶点着色器源码 (用于渲染结果)
    const char* vertexShaderSource = R"(
    #version 310 es
    precision highp float;
    layout (location = 0) in vec2 aPos;
    layout (location = 1) in float aValue;out float vValue;void main() {gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0);vValue = aValue;
    }
    )";// 片段着色器源码 (用于渲染结果)
    const char* fragmentShaderSource = R"(
    #version 310 es
    precision highp float;
    in float vValue;
    out vec4 FragColor;void main() {// 根据值的大小着色 (0-1映射到蓝-红)FragColor = vec4(vValue, 0.0, 1.0 - vValue, 1.0);
    }
    )";GLuint compileShader(GLenum type, const char* source) {GLuint shader = glCreateShader(type);glShaderSource(shader, 1, &source, nullptr);glCompileShader(shader);GLint success;glGetShaderiv(shader, GL_COMPILE_STATUS, &success);if (!success) {char infoLog[512];glGetShaderInfoLog(shader, 512, nullptr, infoLog);std::cerr << "Shader compilation error:\n" << infoLog << std::endl;}return shader;
    }GLuint createComputeProgram() {GLuint computeShader = compileShader(GL_COMPUTE_SHADER, computeShaderSource);GLuint program = glCreateProgram();glAttachShader(program, computeShader);glLinkProgram(program);GLint success;glGetProgramiv(program, GL_LINK_STATUS, &success);if (!success) {char infoLog[512];glGetProgramInfoLog(program, 512, nullptr, infoLog);std::cerr << "Compute program linking error:\n" << infoLog << std::endl;}glDeleteShader(computeShader);return program;
    }GLuint createRenderProgram() {GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vertexShaderSource);GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSource);GLuint program = glCreateProgram();glAttachShader(program, vertexShader);glAttachShader(program, fragmentShader);glLinkProgram(program);GLint success;glGetProgramiv(program, GL_LINK_STATUS, &success);if (!success) {char infoLog[512];glGetProgramInfoLog(program, 512, nullptr, infoLog);std::cerr << "Render program linking error:\n" << infoLog << std::endl;}glDeleteShader(vertexShader);glDeleteShader(fragmentShader);return program;
    }int main() {// 初始化EGL和OpenGL ES上下文 (这里简化了)// 实际应用中需要根据平台正确初始化const int dataSize = 64; // 数据元素数量// 准备输入数据std::vector<float> inputA(dataSize);std::vector<float> inputB(dataSize);std::vector<float> output(dataSize);for (int i = 0; i < dataSize; ++i) {inputA[i] = (float)i / dataSize;inputB[i] = (float)(dataSize - i) / dataSize;}// 创建SSBO (着色器存储缓冲对象)GLuint ssboA, ssboB, ssboOutput;glGenBuffers(1, &ssboA);glGenBuffers(1, &ssboB);glGenBuffers(1, &ssboOutput);// 绑定并填充SSBOglBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboA);glBufferData(GL_SHADER_STORAGE_BUFFER, dataSize * sizeof(float), inputA.data(), GL_STATIC_DRAW);glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboB);glBufferData(GL_SHADER_STORAGE_BUFFER, dataSize * sizeof(float), inputB.data(), GL_STATIC_DRAW);glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboOutput);glBufferData(GL_SHADER_STORAGE_BUFFER, dataSize * sizeof(float), nullptr, GL_STATIC_DRAW);// 创建计算着色器程序GLuint computeProgram = createComputeProgram();// 运行计算着色器glUseProgram(computeProgram);// 绑定SSBO到指定绑定点glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssboA);glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssboB);glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, ssboOutput);// 分派计算着色器glDispatchCompute(dataSize, 1, 1); // 每个工作组处理一个元素// 确保计算完成glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);// 读取结果glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboOutput);float* result = (float*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, dataSize * sizeof(float), GL_MAP_READ_BIT);// 打印部分结果std::cout << "Compute shader results (first 10 elements):\n";for (int i = 0; i < 10; ++i) {std::cout << inputA[i] << " + " << inputB[i] << " = " << result[i] << "\n";}glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);// 创建渲染数据 (可视化结果)std::vector<float> positions(dataSize * 2);for (int i = 0; i < dataSize; ++i) {positions[i*2] = -1.0f + 2.0f * i / dataSize;positions[i*2+1] = 0.0f;}// 创建渲染VAO和VBOGLuint VAO, posVBO, valueVBO;glGenVertexArrays(1, &VAO);glGenBuffers(1, &posVBO);glGenBuffers(1, &valueVBO);glBindVertexArray(VAO);// 位置数据glBindBuffer(GL_ARRAY_BUFFER, posVBO);glBufferData(GL_ARRAY_BUFFER, positions.size() * sizeof(float), positions.data(), GL_STATIC_DRAW);glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);// 值数据 (来自计算结果)glBindBuffer(GL_ARRAY_BUFFER, valueVBO);glBufferData(GL_ARRAY_BUFFER, output.size() * sizeof(float), result, GL_STATIC_DRAW);glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, sizeof(float), (void*)0);glEnableVertexAttribArray(1);// 创建渲染程序GLuint renderProgram = createRenderProgram();// 渲染循环while (true) { // 实际应用中应该有终止条件glClearColor(0.1f, 0.1f, 0.1f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);glUseProgram(renderProgram);glBindVertexArray(VAO);glDrawArrays(GL_POINTS, 0, dataSize);// 实际应用中应该交换缓冲区// eglSwapBuffers(...);}// 清理资源glDeleteBuffers(1, &ssboA);glDeleteBuffers(1, &ssboB);glDeleteBuffers(1, &ssboOutput);glDeleteBuffers(1, &posVBO);glDeleteBuffers(1, &valueVBO);glDeleteVertexArrays(1, &VAO);glDeleteProgram(computeProgram);glDeleteProgram(renderProgram);return 0;
    }
  5. 几何着色器(OpenGL ES 3.2+)。几何着色器可以用于:动态生成几何图形、点精灵扩展、几何细分、法线可视化等。

    #include <GLES3/gl32.h>
    #include <EGL/egl.h>
    #include <iostream>
    #include <vector>
    #include <cmath>// 顶点着色器源码
    const char* vertexShaderSource = R"(
    #version 320 es
    precision highp float;
    layout (location = 0) in vec2 aPos;void main()
    {gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0);
    }
    )";// 几何着色器源码 - 将点扩展为三角形
    const char* geometryShaderSource = R"(
    #version 320 es
    precision highp float;
    layout (points) in;
    layout (triangle_strip, max_vertices = 3) out;void main()
    {// 第一个顶点gl_Position = gl_in[0].gl_Position + vec4(-0.1, -0.1, 0.0, 0.0);EmitVertex();// 第二个顶点gl_Position = gl_in[0].gl_Position + vec4(0.1, -0.1, 0.0, 0.0);EmitVertex();// 第三个顶点gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.1, 0.0, 0.0);EmitVertex();EndPrimitive();
    }
    )";// 片段着色器源码
    const char* fragmentShaderSource = R"(
    #version 320 es
    precision highp float;
    out vec4 FragColor;void main()
    {FragColor = vec4(1.0, 0.5, 0.2, 1.0);
    }
    )";// 编译着色器
    GLuint compileShader(GLenum type, const char* source) {GLuint shader = glCreateShader(type);glShaderSource(shader, 1, &source, nullptr);glCompileShader(shader);// 检查编译错误GLint success;glGetShaderiv(shader, GL_COMPILE_STATUS, &success);if (!success) {char infoLog[512];glGetShaderInfoLog(shader, 512, nullptr, infoLog);std::cerr << "Shader compilation error:\n" << infoLog << std::endl;}return shader;
    }// 创建着色器程序
    GLuint createShaderProgram() {GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vertexShaderSource);GLuint geometryShader = compileShader(GL_GEOMETRY_SHADER, geometryShaderSource);GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSource);GLuint program = glCreateProgram();glAttachShader(program, vertexShader);glAttachShader(program, geometryShader);glAttachShader(program, fragmentShader);glLinkProgram(program);// 检查链接错误GLint success;glGetProgramiv(program, GL_LINK_STATUS, &success);if (!success) {char infoLog[512];glGetProgramInfoLog(program, 512, nullptr, infoLog);std::cerr << "Program linking error:\n" << infoLog << std::endl;}glDeleteShader(vertexShader);glDeleteShader(geometryShader);glDeleteShader(fragmentShader);return program;
    }int main() {// 初始化EGL和OpenGL ES (这里简化了EGL初始化过程)// 实际应用中需要根据平台正确初始化EGL// 顶点数据 - 一些点std::vector<float> vertices = {-0.5f,  0.5f,0.0f,  0.0f,0.5f, -0.5f};// 创建VAO和VBOGLuint VAO, VBO;glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), vertices.data(), GL_STATIC_DRAW);glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);// 创建着色器程序GLuint shaderProgram = createShaderProgram();// 渲染循环while (true) { // 实际应用中应该有终止条件glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);glUseProgram(shaderProgram);glBindVertexArray(VAO);glDrawArrays(GL_POINTS, 0, 3); // 绘制3个点// 实际应用中应该交换缓冲区// eglSwapBuffers(...);}// 清理资源glDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);glDeleteProgram(shaderProgram);return 0;
    }
  6. 基于物理的渲染(PBR)

    #include <GLES3/gl3.h>
    #include <EGL/egl.h>
    #include <vector>
    #include <cmath>
    #include <string>// PBR 顶点着色器
    const char* pbrVertexShader = R"(
    #version 300 es
    precision highp float;
    layout (location = 0) in vec3 aPos;
    layout (location = 1) in vec3 aNormal;
    layout (location = 2) in vec2 aTexCoords;out vec3 WorldPos;
    out vec3 Normal;
    out vec2 TexCoords;uniform mat4 projection;
    uniform mat4 view;
    uniform mat4 model;void main()
    {WorldPos = vec3(model * vec4(aPos, 1.0));Normal = mat3(transpose(inverse(model))) * aNormal;TexCoords = aTexCoords;gl_Position = projection * view * vec4(WorldPos, 1.0);
    }
    )";// PBR 片段着色器
    const char* pbrFragmentShader = R"(
    #version 300 es
    precision highp float;in vec3 WorldPos;
    in vec3 Normal;
    in vec2 TexCoords;uniform vec3 albedo;
    uniform float metallic;
    uniform float roughness;
    uniform float ao;uniform vec3 lightPositions[4];
    uniform vec3 lightColors[4];uniform vec3 camPos;const float PI = 3.14159265359;out vec4 FragColor;// 法线分布函数 (Trowbridge-Reitz GGX)
    float DistributionGGX(vec3 N, vec3 H, float roughness)
    {float a = roughness * roughness;float a2 = a * a;float NdotH = max(dot(N, H), 0.0);float NdotH2 = NdotH * NdotH;float nom = a2;float denom = (NdotH2 * (a2 - 1.0) + 1.0);denom = PI * denom * denom;return nom / denom;
    }// 几何函数 (Schlick GGX)
    float GeometrySchlickGGX(float NdotV, float roughness)
    {float r = (roughness + 1.0);float k = (r * r) / 8.0;float nom = NdotV;float denom = NdotV * (1.0 - k) + k;return nom / denom;
    }// 几何函数 (Smith)
    float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
    {float NdotV = max(dot(N, V), 0.0);float NdotL = max(dot(N, L), 0.0);float ggx2 = GeometrySchlickGGX(NdotV, roughness);float ggx1 = GeometrySchlickGGX(NdotL, roughness);return ggx1 * ggx2;
    }// Fresnel-Schlick近似
    vec3 fresnelSchlick(float cosTheta, vec3 F0)
    {return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
    }void main()
    {vec3 N = normalize(Normal);vec3 V = normalize(camPos - WorldPos);// 计算反射率vec3 F0 = vec3(0.04); F0 = mix(F0, albedo, metallic);// 反射方程vec3 Lo = vec3(0.0);for(int i = 0; i < 4; ++i){// 计算每个光源的辐射vec3 L = normalize(lightPositions[i] - WorldPos);vec3 H = normalize(V + L);float distance = length(lightPositions[i] - WorldPos);float attenuation = 1.0 / (distance * distance);vec3 radiance = lightColors[i] * attenuation;// Cook-Torrance BRDFfloat NDF = DistributionGGX(N, H, roughness);   float G = GeometrySmith(N, V, L, roughness);    vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);        vec3 nominator = NDF * G * F;float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.001;vec3 specular = nominator / denominator;vec3 kS = F;vec3 kD = vec3(1.0) - kS;kD *= 1.0 - metallic;	  float NdotL = max(dot(N, L), 0.0);        Lo += (kD * albedo / PI + specular) * radiance * NdotL;}   // 环境光照 (简化版)vec3 ambient = vec3(0.03) * albedo * ao;vec3 color = ambient + Lo;// HDR色调映射color = color / (color + vec3(1.0));// gamma校正color = pow(color, vec3(1.0/2.2)); FragColor = vec4(color, 1.0);
    }
    )";// 球体网格生成
    void createSphere(std::vector<float>& vertices, std::vector<unsigned int>& indices, unsigned int X_SEGMENTS = 64, unsigned int Y_SEGMENTS = 64)
    {const float PI = 3.14159265359f;for (unsigned int y = 0; y <= Y_SEGMENTS; ++y){for (unsigned int x = 0; x <= X_SEGMENTS; ++x){float xSegment = (float)x / (float)X_SEGMENTS;float ySegment = (float)y / (float)Y_SEGMENTS;float xPos = std::cos(xSegment * 2.0f * PI) * std::sin(ySegment * PI);float yPos = std::cos(ySegment * PI);float zPos = std::sin(xSegment * 2.0f * PI) * std::sin(ySegment * PI);vertices.push_back(xPos);vertices.push_back(yPos);vertices.push_back(zPos);// 法线就是位置向量vertices.push_back(xPos);vertices.push_back(yPos);vertices.push_back(zPos);// 纹理坐标vertices.push_back(xSegment);vertices.push_back(ySegment);}}for (unsigned int y = 0; y < Y_SEGMENTS; ++y){for (unsigned int x = 0; x < X_SEGMENTS; ++x){indices.push_back((y + 1) * (X_SEGMENTS + 1) + x);indices.push_back(y * (X_SEGMENTS + 1) + x);indices.push_back(y * (X_SEGMENTS + 1) + x + 1);indices.push_back((y + 1) * (X_SEGMENTS + 1) + x);indices.push_back(y * (X_SEGMENTS + 1) + x + 1);indices.push_back((y + 1) * (X_SEGMENTS + 1) + x + 1);}}
    }GLuint compileShader(GLenum type, const char* source) {GLuint shader = glCreateShader(type);glShaderSource(shader, 1, &source, nullptr);glCompileShader(shader);GLint success;glGetShaderiv(shader, GL_COMPILE_STATUS, &success);if (!success) {char infoLog[512];glGetShaderInfoLog(shader, 512, nullptr, infoLog);std::cerr << "Shader compilation error:\n" << infoLog << std::endl;}return shader;
    }GLuint createShaderProgram(const char* vsSource, const char* fsSource) {GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vsSource);GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, fsSource);GLuint program = glCreateProgram();glAttachShader(program, vertexShader);glAttachShader(program, fragmentShader);glLinkProgram(program);GLint success;glGetProgramiv(program, GL_LINK_STATUS, &success);if (!success) {char infoLog[512];glGetProgramInfoLog(program, 512, nullptr, infoLog);std::cerr << "Program linking error:\n" << infoLog << std::endl;}glDeleteShader(vertexShader);glDeleteShader(fragmentShader);return program;
    }int main() {// 初始化EGL和OpenGL ES上下文 (这里简化了)// 创建球体网格std::vector<float> sphereVertices;std::vector<unsigned int> sphereIndices;createSphere(sphereVertices, sphereIndices);// 创建VAO和VBOGLuint sphereVAO, sphereVBO, sphereEBO;glGenVertexArrays(1, &sphereVAO);glGenBuffers(1, &sphereVBO);glGenBuffers(1, &sphereEBO);glBindVertexArray(sphereVAO);glBindBuffer(GL_ARRAY_BUFFER, sphereVBO);glBufferData(GL_ARRAY_BUFFER, sphereVertices.size() * sizeof(float), sphereVertices.data(), GL_STATIC_DRAW);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, sphereEBO);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sphereIndices.size() * sizeof(unsigned int), sphereIndices.data(), GL_STATIC_DRAW);// 位置属性glEnableVertexAttribArray(0);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);// 法线属性glEnableVertexAttribArray(1);glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));// 纹理坐标属性glEnableVertexAttribArray(2);glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));// 创建PBR着色器程序GLuint pbrShader = createShaderProgram(pbrVertexShader, pbrFragmentShader);// 光源设置glm::vec3 lightPositions[] = {glm::vec3(-10.0f,  10.0f, 10.0f),glm::vec3( 10.0f,  10.0f, 10.0f),glm::vec3(-10.0f, -10.0f, 10.0f),glm::vec3( 10.0f, -10.0f, 10.0f)};glm::vec3 lightColors[] = {glm::vec3(300.0f, 300.0f, 300.0f),glm::vec3(300.0f, 300.0f, 300.0f),glm::vec3(300.0f, 300.0f, 300.0f),glm::vec3(300.0f, 300.0f, 300.0f)};// 相机位置glm::vec3 cameraPos(0.0f, 0.0f, 5.0f);// 投影矩阵glm::mat4 projection = glm::perspective(glm::radians(45.0f), 800.0f / 600.0f, 0.1f, 100.0f);// 渲染循环while (true) {// 清除颜色和深度缓冲glClearColor(0.1f, 0.1f, 0.1f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// 视图矩阵glm::mat4 view = glm::lookAt(cameraPos, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));// 激活PBR着色器glUseProgram(pbrShader);// 传递矩阵glUniformMatrix4fv(glGetUniformLocation(pbrShader, "projection"), 1, GL_FALSE, &projection[0][0]);glUniformMatrix4fv(glGetUniformLocation(pbrShader, "view"), 1, GL_FALSE, &view[0][0]);// 传递光源信息for (int i = 0; i < 4; ++i) {glUniform3fv(glGetUniformLocation(pbrShader, ("lightPositions[" + std::to_string(i) + "]").c_str()), 1, &lightPositions[i][0]);glUniform3fv(glGetUniformLocation(pbrShader, ("lightColors[" + std::to_string(i) + "]").c_str()), 1, &lightColors[i][0]);}// 传递相机位置glUniform3fv(glGetUniformLocation(pbrShader, "camPos"), 1, &cameraPos[0]);// 渲染多个球体,每个球体有不同的金属度和粗糙度int nrRows = 7;int nrColumns = 7;float spacing = 2.5;glm::mat4 model = glm::mat4(1.0f);for (int row = 0; row < nrRows; ++row) {for (int col = 0; col < nrColumns; ++col) {model = glm::mat4(1.0f);model = glm::translate(model, glm::vec3((col - (nrColumns / 2)) * spacing,(row - (nrRows / 2)) * spacing,0.0f));glUniformMatrix4fv(glGetUniformLocation(pbrShader, "model"), 1, GL_FALSE, &model[0][0]);// 设置材质属性glm::vec3 albedo = glm::vec3(0.5f, 0.0f, 0.0f);float metallic = (float)row / (float)nrRows;float roughness = glm::clamp((float)col / (float)nrColumns, 0.05f, 1.0f);float ao = 1.0f;glUniform3fv(glGetUniformLocation(pbrShader, "albedo"), 1, &albedo[0]);glUniform1f(glGetUniformLocation(pbrShader, "metallic"), metallic);glUniform1f(glGetUniformLocation(pbrShader, "roughness"), roughness);glUniform1f(glGetUniformLocation(pbrShader, "ao"), ao);// 渲染球体glBindVertexArray(sphereVAO);glDrawElements(GL_TRIANGLES, sphereIndices.size(), GL_UNSIGNED_INT, 0);}}// 实际应用中应该交换缓冲区// eglSwapBuffers(...);}// 清理资源glDeleteVertexArrays(1, &sphereVAO);glDeleteBuffers(1, &sphereVBO);glDeleteBuffers(1, &sphereEBO);glDeleteProgram(pbrShader);return 0;
    }

十一、 学习资源

  1. OpenGL ES 官方参考

  2. LearnOpenGL ES

  3. Google Android OpenGL ES 教程

  4. Apple OpenGL ES 指南

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词