OpenGL ES(OpenGL for Embedded Systems)和 OpenGL 是两个紧密相关但用途和设计目标不同的图形API。下面帮你详细梳理它们的区别:
OpenGL ES 与 OpenGL 的区别
方面 | OpenGL | OpenGL ES |
---|---|---|
定位 | 主要面向桌面和工作站平台 | 专为嵌入式系统和移动设备设计 |
目标设备 | PC、工作站、笔记本 | 手机、平板、游戏机、车载系统等 |
功能集 | 功能丰富,支持多种高级特性 | 精简版本,去掉部分复杂功能以适应性能和资源限制 |
版本号 | 最新是 OpenGL 4.x | OpenGL ES 有 1.0、2.0、3.x 等版本,功能逐步增强 |
编程模型 | 支持固定功能管线和可编程管线 | 1.x版本支持固定管线,2.0及以后版本仅支持可编程管线 |
扩展支持 | 支持大量扩展,适合高端图形应用 | 扩展有限,更注重基础性能和兼容性 |
性能与资源需求 | 对硬件要求较高 | 针对低功耗和资源有限设备优化 |
开发难度 | 相对复杂,功能多 | 简化接口,易于学习和使用 |
详细说明
1. 用途和设计目标
- OpenGL 是桌面图形API,设计时考虑了高性能图形渲染和广泛功能支持。
- OpenGL ES 是针对嵌入式设备(如智能手机、平板、嵌入式游戏机)优化,减少复杂功能,提升性能和效率。
2. 功能差异
- OpenGL 有固定功能管线(传统)和可编程管线(Shader)两种模式。
- OpenGL ES 1.x 支持固定管线,2.0+只支持可编程管线,强制使用Shader。
- OpenGL 支持更多纹理格式、多重采样、多渲染目标等高级功能,OpenGL ES 省略或简化这些以降低硬件负担。
3. 性能与硬件需求
- OpenGL 偏向高性能GPU,依赖强大的硬件。
- OpenGL ES 适配移动GPU,注重功耗和带宽限制。
4. 开发环境差异
- OpenGL 主要在 Windows、Linux、macOS 桌面环境开发。
- OpenGL ES 广泛用于 Android、iOS、嵌入式 Linux 等移动和嵌入式系统。
总结
| 你需要桌面级高性能图形渲染,且硬件条件充足 → 选 OpenGL。
| 你开发移动端或嵌入式设备应用,且受限于功耗和性能 → 选 OpenGL ES。
好的!下面我帮你写一组简单的 OpenGL 和 OpenGL ES 的绘制三角形示例代码对比,演示两者的 API 差异和用法差异。示例均为核心代码片段,重点突出不同点。
1. OpenGL (桌面版) 简单绘制三角形
// 顶点着色器 (GLSL)
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 renderTriangle() {
float vertices[] = {
0.0f, 0.5f, 0.0f, // 顶点1
-0.5f, -0.5f, 0.0f, // 顶点2
0.5f, -0.5f, 0.0f // 顶点3
};
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);
// 使用着色器程序 (编译和链接代码略)
glDrawArrays(GL_TRIANGLES, 0, 3);
// 解绑
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
2. OpenGL ES 2.0 (移动嵌入式) 简单绘制三角形
// 顶点着色器 (GLSL ES)
const char* vertexShaderSource = R"(
attribute vec4 aPos;
void main() {
gl_Position = aPos;
}
)";
// 片段着色器
const char* fragmentShaderSource = R"(
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 0.5, 0.2, 1.0);
}
)";
void renderTriangle() {
GLfloat vertices[] = {
0.0f, 0.5f, 0.0f, // 顶点1
-0.5f, -0.5f, 0.0f, // 顶点2
0.5f, -0.5f, 0.0f // 顶点3
};
GLuint VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLint posAttrib = glGetAttribLocation(program, "aPos");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(posAttrib);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
关键区别点总结
项目 | OpenGL | OpenGL ES 2.0 |
---|---|---|
着色器版本 | #version 330 core | 无版本或 #version 100 |
变量限定词 | in , out | attribute (顶点),varying (片段) |
片段颜色输出 | 自定义输出变量 | 只能写入 gl_FragColor |
顶点数组对象(VAO) | 支持 | 部分版本不支持(需手动管理) |
精度限定符 | 不需要 | 需要在片段着色器声明精度 |
API 函数调用 | 支持 VAO 等 | 只能用 VBO 和手动管理顶点属性 |
明白!下面我给你写一个完整的、最简化的 OpenGL ES 2.0 三角形绘制示例(包含着色器编译、链接、绘制),示范基础的流程。代码是用 C 语言和 EGL + GLES2 的风格,适合嵌入式或移动平台开发参考。
OpenGL ES 2.0 简单三角形完整示例(核心代码)
#include <GLES2/gl2.h>
#include <EGL/egl.h>
#include <stdio.h>
#include <stdlib.h>
// 顶点着色器源码
const char* vertexShaderSrc =
"attribute vec4 aPos;\n"
"void main() {\n"
" gl_Position = aPos;\n"
"}";
// 片段着色器源码
const char* fragmentShaderSrc =
"precision mediump float;\n"
"void main() {\n"
" gl_FragColor = vec4(1.0, 0.5, 0.2, 1.0);\n"
"}";
// 编译着色器
GLuint compileShader(GLenum type, const char* src) {
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, &src, NULL);
glCompileShader(shader);
// 检查编译状态
GLint compiled;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled) {
GLint infoLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen) {
char* infoLog = (char*)malloc(infoLen);
glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
printf("Shader compile error: %s\n", infoLog);
free(infoLog);
}
glDeleteShader(shader);
return 0;
}
return shader;
}
// 创建着色器程序
GLuint createProgram(const char* vertSrc, const char* fragSrc) {
GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vertSrc);
GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragSrc);
if (!vertexShader || !fragmentShader) return 0;
GLuint program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glBindAttribLocation(program, 0, "aPos"); // 绑定顶点属性位置0
glLinkProgram(program);
// 检查链接状态
GLint linked;
glGetProgramiv(program, GL_LINK_STATUS, &linked);
if (!linked) {
GLint infoLen = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen) {
char* infoLog = (char*)malloc(infoLen);
glGetProgramInfoLog(program, infoLen, NULL, infoLog);
printf("Program link error: %s\n", infoLog);
free(infoLog);
}
glDeleteProgram(program);
return 0;
}
// 删除着色器对象
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return program;
}
int main(int argc, char** argv) {
// 省略 EGL 初始化上下文的代码(不同平台不同,需先创建 EGLContext 和 EGLSurface)
// 创建程序
GLuint program = createProgram(vertexShaderSrc, fragmentShaderSrc);
if (!program) {
printf("Failed to create program\n");
return -1;
}
// 三角形顶点数据
GLfloat vertices[] = {
0.0f, 0.5f, 0.0f, // 顶点1
-0.5f, -0.5f, 0.0f, // 顶点2
0.5f, -0.5f, 0.0f // 顶点3
};
// 使用程序
glUseProgram(program);
// 传递顶点数据
GLint posAttrib = glGetAttribLocation(program, "aPos");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, vertices);
// 清屏
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
// 绘制三角形
glDrawArrays(GL_TRIANGLES, 0, 3);
// 交换缓冲(平台相关)
// 省略 EGL 清理代码
return 0;
}
说明:
compileShader
:编译顶点或片段着色器,包含错误检测。createProgram
:创建并链接着色器程序。- 使用
glVertexAttribPointer
和glEnableVertexAttribArray
传递顶点数据。 - 省略了 EGL(或其他平台上下文)初始化和交换缓冲,因平台差异较大。
- 这个示例展示了 OpenGL ES 2.0 的核心渲染流程和 API 使用。
明白!这里给你一个基于 Windows + GLFW + OpenGL 3.3 的完整最简绘制三角形示例代码。用 C 语言写,包含窗口创建、OpenGL 上下文初始化、着色器编译和渲染循环。
Windows + GLFW + OpenGL 3.3 三角形示例
#include <GL/glew.h> // GLEW 用于加载 OpenGL 函数
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
// 顶点着色器源码
const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main() {\n"
" gl_Position = vec4(aPos, 1.0);\n"
"}\0";
// 片段着色器源码
const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main() {\n"
" FragColor = vec4(1.0, 0.5, 0.2, 1.0);\n"
"}\0";
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
glViewport(0, 0, width, height);
}
int main() {
// 初始化 GLFW
if (!glfwInit()) {
fprintf(stderr, "Failed to initialize GLFW\n");
return -1;
}
// 设置 OpenGL 版本(3.3核心版)
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // MacOS 需要
#endif
// 创建窗口
GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL 3.3 Triangle", NULL, NULL);
if (!window) {
fprintf(stderr, "Failed to create GLFW window\n");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// 初始化 GLEW
glewExperimental = GL_TRUE; // 使 GLEW 使用现代方法获取函数指针
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
return -1;
}
// 设置视口大小
glViewport(0, 0, 800, 600);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
// 编译顶点着色器
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// 检查编译错误
GLint success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
fprintf(stderr, "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n%s\n", infoLog);
}
// 编译片段着色器
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// 检查编译错误
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
fprintf(stderr, "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n%s\n", infoLog);
}
// 创建着色器程序并链接
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// 检查链接错误
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
fprintf(stderr, "ERROR::PROGRAM::LINKING_FAILED\n%s\n", infoLog);
}
// 删除着色器对象,已链接到程序中
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
// 顶点数据(一个三角形)
float vertices[] = {
0.0f, 0.5f, 0.0f, // 顶点1
-0.5f, -0.5f, 0.0f, // 顶点2
0.5f, -0.5f, 0.0f // 顶点3
};
// 创建 VAO 和 VBO
GLuint VAO, VBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
// 绑定 VAO
glBindVertexArray(VAO);
// 绑定 VBO 并上传数据
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);
// 解绑
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
// 渲染循环
while (!glfwWindowShouldClose(window)) {
// 输入
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, 1);
// 渲染指令
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);
glDeleteProgram(shaderProgram);
glfwTerminate();
return 0;
}
使用说明:
- 需要先安装 GLFW(官网:https://www.glfw.org/ )和 GLEW(官网:http://glew.sourceforge.net/)
- 编译时链接
glfw3.lib
、glew32.lib
和 OpenGL 库(Windows上是opengl32.lib
) - 该示例用现代 OpenGL 3.3 核心版本,使用着色器编程和顶点数组对象(VAO)
发表回复