{"id":17988213,"url":"https://github.com/program-spiritual/learnopengles","last_synced_at":"2026-05-09T04:32:48.801Z","repository":{"id":112520970,"uuid":"325760129","full_name":"program-spiritual/learnOpenGLES","owner":"program-spiritual","description":"learn OpenGL ES","archived":false,"fork":false,"pushed_at":"2021-02-09T05:51:10.000Z","size":590,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-04T03:27:18.407Z","etag":null,"topics":["cplusplus","cpp14","js","opengl","opengl-es","opengl-tutorial"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/program-spiritual.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2020-12-31T09:04:27.000Z","updated_at":"2021-02-09T05:51:13.000Z","dependencies_parsed_at":"2023-05-15T14:00:38.037Z","dependency_job_id":null,"html_url":"https://github.com/program-spiritual/learnOpenGLES","commit_stats":null,"previous_names":["yiyandaoren/learnopengles","program-spiritual/learnopengles"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/program-spiritual/learnOpenGLES","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/program-spiritual%2FlearnOpenGLES","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/program-spiritual%2FlearnOpenGLES/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/program-spiritual%2FlearnOpenGLES/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/program-spiritual%2FlearnOpenGLES/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/program-spiritual","download_url":"https://codeload.github.com/program-spiritual/learnOpenGLES/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/program-spiritual%2FlearnOpenGLES/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32807211,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-08T08:22:46.396Z","status":"online","status_checked_at":"2026-05-09T02:00:06.633Z","response_time":123,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cplusplus","cpp14","js","opengl","opengl-es","opengl-tutorial"],"created_at":"2024-10-29T19:11:01.396Z","updated_at":"2026-05-09T04:32:48.787Z","avatar_url":"https://github.com/program-spiritual.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# learn OpenGL ES （Web 版本）\n\n这里我将使用 `MDN` 的资源进行简明的示例编写，以便于你能够快速读懂。\n\n\n## 基本原理\n\n- 第一步\n\n  - 基于 `canvas` 对象\n  - 利用 OpenGL ES 2.0 的 API   \n\n- 第二步\n  - 用 `JavaScript` 写的控制代码\n  - 执行的着色代码（`GLSL` ，注：`GLSL` 为 `OpenGL` 着色语言）  \n\n\n## 准备点火\n\n下面我们基于一个 `html` 文件结合  `Canvas` 初始化一个 `WEBGL` 上下文。\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\n\u003chead\u003e\n  \u003cmeta charset=\"UTF-8\"\u003e\n  \u003ctitle\u003eprepare\u003c/title\u003e\n\u003c/head\u003e\n\u003cbody onload=\"OnDOMLoaded()\"\u003e\n  \u003ccanvas id=\"glcanvas\" class=\"box\"\u003e\n    你的浏览器似乎不支持或者禁用了HTML5 \u003ccode\u003e\u0026lt;canvas\u0026gt;\u003c/code\u003e 元素.\n  \u003c/canvas\u003e\n\u003c/body\u003e\n\u003cscript\u003e\n  function OnDOMLoaded(){\n    const CANVAS = document.getElementById('glcanvas')\n    const GL_CONTEXT = CANVAS.getContext('webgl')\n    if (!GL_CONTEXT){\n      alert('无法初始化WEBGL，你的浏览器或OS不支持')\n      return\n    }\n\n    // 使用不透明全黑抹掉一切\n    GL_CONTEXT.clearColor(0, 0, 0, 1)\n    // 清除缓冲区\n    GL_CONTEXT.clear(GL_CONTEXT.COLOR_BUFFER_BIT)\n  }\n\u003c/script\u003e\n\u003c/html\u003e\n\n```\n\n屏幕截图如下所示：\n\n![prepare](learnOpenGLES-prepare-html-1612674402226.png)\n\n## 渲染\n\n- 着色器\n  - 本质\n    - 使用着色语言编写的程序\n      - [着色语言](GLSL_ES_Specification_1.00.pdf)\n  - 需要的信息\n    - 绘制形状的顶点信息\n    - 构造绘制在屏幕上像素的所需数据\n    \n  - 一句话\n    - 着色器负责记录像素点位置、颜色\n  - 使用的函数\n    - 顶点着色器\n    - 片段着色器\n    - 顶点着色器和片段着色器的集合我们通常称之为着色器程序。\n  \n### 顶点着色器\n\n一句话可以概括：\n\n将原始坐标系转换为WEBGL的特定坐标系\n\n细节：\n\n- 每个轴的坐标范围是　`－１`　到　`１`\n- 不考虑纵横比，实际尺寸或任何其他因素\n- 经过各种转换后，将变量保存至名为 `gl_Position`的特殊变量中并返回\n\n他能干的活：\n\n- 决定哪个包含 `texel` 面部纹理的坐标，可以应用于顶点；\n- 通过法线来确定应用到顶点的光照因子等\n- 存储的变量\n  - `varyings`\n  - `attributes`\n  - 目的\n    - 以便与片段着色器共享\n  \n#### 示例\n\n定义一个顶点位置\n\n```js\n  const vsSource = `\n    attribute vec4 aVertexPosition; // 顶点位置值\n\n    uniform mat4 uModelViewMatrix;  // 4x4 矩阵\n    uniform mat4 uProjectionMatrix; // 4x4 矩阵\n\n    void main() {\n    // 乘积赋值给gl_Position\n      gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;\n    }\n  `;\n```\n\n### 片段着色器\n\n定点处理完了，每个要被绘制的像素点调用一次它\n\n职责：\n\n确定像素的颜色\n\n方式：\n\n通过指定应用到像素的纹理元素（也就是图形纹理中的像素），获取纹理元素的颜色，然后将适当的光照应用于颜色。\n\n变量存储？\n\n存储在特殊变量 `gl_FragColor` 中，返回到 `WebGL` 层\n\n最终渲染：\n\n该颜色将最终绘制到屏幕上图形对应像素的对应位置。\n\n\n```js\nconst fsSource = `\n    void main() {\n    // 获取纹理元素的颜色\n      gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n    }\n  `;\n```\n\n## 初始化着色器\n\n着色器 -\u003e WEBGL -\u003e 编译 -\u003e 检查是否编译成功 -\u003e 返回编译的着色器\n\n\n```html\n\u003cscript\u003e\n  const vsSource = `\n    attribute vec4 aVertexPosition;\n\n    uniform mat4 uModelViewMatrix;\n    uniform mat4 uProjectionMatrix;\n\n    void main() {\n      gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;\n    }\n  `;\n\n  const fsSource = `\n    void main() {\n      gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n    }\n  `;\n\n\n  function OnDOMLoaded() {\n    const CANVAS = document.getElementById('glcanvas')\n    const GL_CONTEXT = CANVAS.getContext('webgl')\n    if (!GL_CONTEXT) {\n      alert('无法初始化WEBGL，你的浏览器或OS不支持')\n      return\n    }\n\n    // 使用不透明全黑抹掉一切\n    GL_CONTEXT.clearColor(0, 0, 0, 1)\n    // 清除缓冲区\n    GL_CONTEXT.clear(GL_CONTEXT.COLOR_BUFFER_BIT)\n\n    // 调用代码\n    const shaderProgram = initShaderProgram(GL_CONTEXT, vsSource, fsSource);\n\n  }\n\n  // 创建指定类型的着色器，上传 source 源码并编译\n  function loadShader(glContext, type, source) {\n    // 创建着色器\n    const shader = glContext.createShader(type);\n    // 将源发送到着色器对象\n    glContext.shaderSource(shader, source);\n    // 编译着色器程序\n    glContext.compileShader(shader);\n    // 查看是否成功编译\n    if (!glContext.getShaderParameter(shader,glContext.COMPILE_STATUS)) {\n      alert('编译着色器时发生错误: ' + glContext.getShaderInfoLog(shader));\n      glContext.deleteShader(shader);\n      return null;\n    }\n    return shader;\n  }\n\n  // 初始化着色器程序，让WebGL知道如何绘制我们的数据\n  function initShaderProgram(glContext, vsSource, fsSource) {\n    const vertexShader = loadShader(glContext, glContext.VERTEX_SHADER, vsSource);\n    const fragmentShader = loadShader(glContext, glContext.FRAGMENT_SHADER, fsSource);\n    // 创建着色器程序\n    const shaderProgram = glContext.createProgram();\n    glContext.attachShader(shaderProgram, vertexShader);\n    glContext.attachShader(shaderProgram, fragmentShader);\n    glContext.linkProgram(shaderProgram);\n    // 如果创建失败，那么提示\n    if (!glContext.getProgramParameter(shaderProgram,glContext.LINK_STATUS)) {\n      alert('无法初始化着色器程序: ' + glContext.getProgramInfoLog(shaderProgram));\n      return null;\n    }\n    return shaderProgram;\n  }\n  \n\u003c/script\u003e\n```\n\n### 查找WebGL返回分配的输入位置\n\nuniform:\n\n- 类似于JavaScript全局变量\n- 着色器迭代不会影响\n\nattribute:\n\n- 属性从缓冲区接收值\n- 顶点着色器的每次迭代都从分配给该属性的缓冲区接收下一个值\n\n\n我们会用到名字为 `initBuffers()` 的函数。\n\n- 调用 `gl` 的成员函数 `createBuffer()` 得到了缓冲对象并存储在顶点缓冲器\n- 调用 `bindBuffer()` 函数绑定上下文\n- 转化为 `WebGL` 浮点型类型的数组\n- 传到 `gl` 对象的  `bufferData()` 方法来建立对象的顶点\n- 当着色器和物体都创建好后，我们可以开始渲染这个场景\n\n\n[正方形绘制](square.html)\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprogram-spiritual%2Flearnopengles","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprogram-spiritual%2Flearnopengles","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprogram-spiritual%2Flearnopengles/lists"}