├── Geometry and Appearances.html ├── Web.config ├── _lib ├── matrix.js ├── polygon.js ├── util.js └── webgl-util.js ├── images ├── awesomeface.png ├── back(1).jpg ├── back.jpg ├── bottom(1).jpg ├── bottom.jpg ├── brick-diffuse.png ├── brick-normals.png ├── brickwall.jpg ├── brickwall_normal.jpg ├── camera.jpg ├── container2.png ├── container2_specular.png ├── front(1).jpg ├── front.jpg ├── grass.png ├── left(1).jpg ├── left.jpg ├── lena.png ├── marble.jpg ├── metal.png ├── normal_mapping.png ├── right (2).jpg ├── right.jpg ├── sky_cloud.jpg ├── stone.png ├── stone_normal.png ├── top(1).jpg ├── top.jpg ├── wall.jpg ├── window.png ├── wood.png └── 阴影示例.png ├── lib ├── cuon-matrix.js ├── cuon-utils.js ├── gl-matrix.js ├── jquery-1.9.1.min.js ├── webgl-debug.js ├── webgl-obj-loader.min.js └── webgl-utils.js ├── models ├── CesiumMan │ ├── CesiumMan.gltf │ ├── CesiumMan.jpg │ └── CesiumMan0.bin └── female02 │ ├── .htaccess │ ├── 01_-_Default1noCulling.JPG │ ├── 02_-_Default1noCulling.JPG │ ├── 03_-_Default1noCulling.JPG │ ├── Female02_bin.bin │ ├── Female02_bin.js │ ├── Female02_slim.js │ ├── female02.mtl │ ├── female02.obj │ ├── female02_vertex_colors.obj │ └── readme.txt ├── resources ├── gl-matrix.js ├── m4.js ├── models │ ├── CesiumMan │ │ ├── CesiumMan.gltf │ │ ├── CesiumMan.jpg │ │ └── CesiumMan0.bin │ ├── killer_whale │ │ ├── whale.CYCLES.bin │ │ └── whale.CYCLES.gltf │ └── simpleSkin.gltf ├── webgl-lessons-ui.js ├── webgl-tutorials.css └── webgl-utils.js ├── rtsp.html ├── sample ├── index.html └── textures │ ├── grass.jpg │ ├── misc.jpg │ └── tree.png ├── webgl-skinning-3d-gltf-skinned.html ├── webgl-skinning-3d-gltf.html ├── webgl-skinning.html ├── 一些比较炫的例子 └── 星系 │ ├── css │ └── style.css │ ├── index.html │ └── js │ ├── TweenMax.min.js │ ├── index.js │ ├── stat.js │ └── three.min.js ├── 代码库 └── 生成cube.html ├── 学习webgl ├── 你好三角形.html └── 纹理.html ├── 新建文本文档.html ├── 第一章 ├── camera.html ├── coordinateSystem.html ├── texture.html ├── transform.html └── triangle.html ├── 第三章 ├── FaceCulling.html ├── FrameBuffer_cube.html ├── FrameBuffer_cube.js ├── StencilTest.html ├── blending.html ├── blending2.html ├── cubemaps.html ├── depthTest.html ├── discard.html ├── wireframe.html ├── 天空盒-反射效果.html ├── 天空盒-折射效果.html ├── 实例化.html ├── 模板测试.html ├── 深度测试.html ├── 混合-半透明纹理.html ├── 混合-片段丢弃.html └── 面剔除.html ├── 第二章 ├── BaseLighting.html ├── LightingMaps-copy.html ├── LightingMaps.html ├── LoadModel.html ├── MirrorReflect.html ├── SpecularMaps.html ├── color.html ├── material.html ├── 光照贴图-漫反射贴图.html ├── 光照贴图-镜面光贴图.html ├── 基础光照.html ├── 多光源.html ├── 定向光.html ├── 材质.html ├── 点光源的衰减.html ├── 聚光.html └── 聚光柔和.html ├── 第五章-动画 ├── film-grain.html └── 骨骼动画.html ├── 第四章-高级光照 ├── Blinn-Phong.html ├── Gamma校正.html ├── HDR(高动态范围).html ├── PCF阴影消除锯齿.html ├── 多物体高精度PCF-副本.html ├── 多物体高精度PCF.html ├── 法线贴图.html ├── 泛光.html ├── 深度贴图.html ├── 视差贴图.html ├── 阴影映射.html └── 高级光照.html └── 视频纹理 ├── index.html ├── test.mp4 └── webgl-demo.js /Web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /_lib/polygon.js: -------------------------------------------------------------------------------- 1 | // var va = vec4(0.0, 0.0, -1.0,1); 2 | // var vb = vec4(0.0, 0.942809, 0.333333, 1); 3 | // var vc = vec4(-0.816497, -0.471405, 0.333333, 1); 4 | // var vd = vec4(0.816497, -0.471405, 0.333333,1); 5 | 6 | function Polygon(position,normal,color,indices){ 7 | this.position=position; 8 | this.normal=normal; 9 | this.color=color; 10 | this.indices=indices; 11 | } 12 | /** 13 | * 平面(2*0*2) 14 | */ 15 | function Plane(color){ 16 | // v0------v1 17 | // | | 18 | // | | 19 | // | | 20 | // v3------v2 21 | color=color||[1,1,1,1]; 22 | var positions = [-1,0,-1, 1,0,-1, 1,0,1, -1,0,1], 23 | normals = [0,1,0, 0,1,0, 0,1,0, 0,1,0], 24 | colors = [], 25 | indices = new Uint8Array([0,2,3,0,1,2]); 26 | for(var i=0;i<4;i++){ 27 | colors=colors.concat(color); 28 | } 29 | 30 | return new Polygon(positions,normals,colors,indices); 31 | } 32 | 33 | /** 34 | * 立方体(1*1*1) 35 | */ 36 | function Cube(color){ 37 | // v4----- v7 38 | // /| /| 39 | // v0------v1| 40 | // | | | | 41 | // | |v5---|-|v6 42 | // |/ |/ 43 | // v3------v2 44 | // 45 | color=color||[1,1,1,1]; 46 | var colors=[]; 47 | for(var i=0;i<24;i++){ 48 | colors.push(...color); 49 | } 50 | 51 | // 顶点 52 | var positions = [ 53 | -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, // v0-v1-v2-v3 front 54 | 1, 1, 1, 1, 1, -1, 1, -1,-1, 1, -1, 1, // v1-v7-v6-v2 right 55 | -1,1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, // v4-v7-v1-v0 up 56 | -1, 1, 1, -1,1, -1, -1,-1,-1, -1, -1, 1, // v0-v4-v5-v3 left 57 | -1,-1,-1, -1, -1, 1, 1, -1, 1, 1, -1,-1, // v5-v3-v2-v6 down 58 | -1,1, -1, -1,-1,-1, 1, -1,-1, 1, 1, -1 // v4-v5-v6-v7 back 59 | ]; 60 | 61 | // 法向量 62 | var normals = [ 63 | 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, // v0-v1-v2-v3 front 64 | 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // v1-v7-v6-v2 right 65 | 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, // v4-v7-v1-v0 up 66 | -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, // v0-v4-v5-v3 left 67 | 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0,  // v5-v3-v2-v6 down 68 | 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1 // v4-v5-v6-v7 back 69 | ]; 70 | 71 | // 顶点索引 72 | var indices = new Uint8Array([ 73 | 0, 1, 2, 0, 2, 3, // front 74 | 4, 5, 6, 4, 6, 7, // right 75 | 8, 9,10, 8,10,11, // up 76 | 12,13,14, 12,14,15, // left 77 | 16,17,18, 16,18,19, // down 78 | 20,21,22, 20,22,23 // back 79 | ]); 80 | 81 | return new Polygon(positions,normals,colors,indices); 82 | } 83 | 84 | /** 85 | * 圆球(1*1*1) 86 | */ 87 | function Sphere(len, color) { 88 | len = len || 15; 89 | color=color||[1,1,1,1]; 90 | 91 | var i, ai, si, ci; 92 | var j, aj, sj, cj; 93 | var p1, p2; 94 | var pos = [],nor=[]; 95 | 96 | var positions = [], 97 | normals = [], 98 | colors = [], 99 | indices = []; 100 | 101 | // 创建顶点坐标 102 | for (j = 0; j <= len; j++) { 103 | aj = j * Math.PI / len; 104 | sj = Math.sin(aj); 105 | cj = Math.cos(aj); 106 | for (i = 0; i <= len; i++) { 107 | ai = i * 2 * Math.PI / len; 108 | si = Math.sin(ai); 109 | ci = Math.cos(ai); 110 | 111 | pos = [si * sj, cj, ci * sj];// x y z 112 | positions.push(...pos); 113 | 114 | nor=normalize(pos);// 归一化后的顶点坐标就是法向量 115 | normals.push(...nor); 116 | 117 | colors.push(...color);// 颜色 118 | } 119 | } 120 | // 创建顶点索引 121 | for (j = 0; j < len; j++) { 122 | for (i = 0; i < len; i++) { 123 | p1 = j * (len + 1) + i; 124 | p2 = p1 + (len + 1); 125 | 126 | indices.push(p1); 127 | indices.push(p2); 128 | indices.push(p1 + 1); 129 | 130 | indices.push(p1 + 1); 131 | indices.push(p2); 132 | indices.push(p2 + 1); 133 | } 134 | } 135 | 136 | return new Polygon(positions,normals,colors,indices); 137 | } 138 | 139 | /** 140 | * 圆柱体 141 | */ 142 | function Cylinder(r,h,l,color){ 143 | // 8 144 | 145 | // 1 5 146 | // 0 4 147 | 148 | // 2 6 149 | // 3 7 150 | 151 | // 9 152 | var angle=Math.PI*2/l, 153 | x=0, z=0, 154 | color=color||[1,1,1,1], 155 | colors=[], 156 | positions=[], 157 | normals=[], 158 | indices=[]; 159 | 160 | for(var i=0;i element 99 | * @param opt_debug flag to initialize the context for debugging 100 | * @return the rendering context for WebGL 101 | */ 102 | function getWebGLContext(canvas, opt_debug) { 103 | // Get the rendering context for WebGL 104 | var gl = WebGLUtils.setupWebGL(canvas); 105 | if (!gl) return null; 106 | 107 | // if opt_debug is explicitly false, create the context for debugging 108 | if (arguments.length < 2 || opt_debug) { 109 | gl = WebGLDebugUtils.makeDebugContext(gl); 110 | } 111 | 112 | return gl; 113 | } 114 | -------------------------------------------------------------------------------- /lib/webgl-utils.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010, Google Inc. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above 12 | * copyright notice, this list of conditions and the following disclaimer 13 | * in the documentation and/or other materials provided with the 14 | * distribution. 15 | * * Neither the name of Google Inc. nor the names of its 16 | * contributors may be used to endorse or promote products derived from 17 | * this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | 33 | /** 34 | * @fileoverview This file contains functions every webgl program will need 35 | * a version of one way or another. 36 | * 37 | * Instead of setting up a context manually it is recommended to 38 | * use. This will check for success or failure. On failure it 39 | * will attempt to present an approriate message to the user. 40 | * 41 | * gl = WebGLUtils.setupWebGL(canvas); 42 | * 43 | * For animated WebGL apps use of setTimeout or setInterval are 44 | * discouraged. It is recommended you structure your rendering 45 | * loop like this. 46 | * 47 | * function render() { 48 | * window.requestAnimationFrame(render, canvas); 49 | * 50 | * // do rendering 51 | * ... 52 | * } 53 | * render(); 54 | * 55 | * This will call your rendering function up to the refresh rate 56 | * of your display but will stop rendering if your app is not 57 | * visible. 58 | */ 59 | 60 | WebGLUtils = function() { 61 | 62 | /** 63 | * Creates the HTLM for a failure message 64 | * @param {string} canvasContainerId id of container of th 65 | * canvas. 66 | * @return {string} The html. 67 | */ 68 | var makeFailHTML = function(msg) { 69 | return '' + 70 | '
' + msg + '
'; 71 | return '' + 72 | '' + 73 | '
' + 74 | '
' + 75 | '
' + msg + '
' + 76 | '
' + 77 | '
'; 78 | }; 79 | 80 | /** 81 | * Mesasge for getting a webgl browser 82 | * @type {string} 83 | */ 84 | var GET_A_WEBGL_BROWSER = '' + 85 | 'This page requires a browser that supports WebGL.
' + 86 | 'Click here to upgrade your browser.'; 87 | 88 | /** 89 | * Mesasge for need better hardware 90 | * @type {string} 91 | */ 92 | var OTHER_PROBLEM = '' + 93 | "It doesn't appear your computer can support WebGL.
" + 94 | 'Click here for more information.'; 95 | 96 | /** 97 | * Creates a webgl context. If creation fails it will 98 | * change the contents of the container of the 99 | * tag to an error message with the correct links for WebGL. 100 | * @param {Element} canvas. The canvas element to create a 101 | * context from. 102 | * @param {WebGLContextCreationAttirbutes} opt_attribs Any 103 | * creation attributes you want to pass in. 104 | * @param {function:(msg)} opt_onError An function to call 105 | * if there is an error during creation. 106 | * @return {WebGLRenderingContext} The created context. 107 | */ 108 | var setupWebGL = function(canvas, opt_attribs, opt_onError) { 109 | function handleCreationError(msg) { 110 | var container = document.getElementsByTagName("body")[0]; 111 | //var container = canvas.parentNode; 112 | if (container) { 113 | var str = window.WebGLRenderingContext ? 114 | OTHER_PROBLEM : 115 | GET_A_WEBGL_BROWSER; 116 | if (msg) { 117 | str += "

Status: " + msg; 118 | } 119 | container.innerHTML = makeFailHTML(str); 120 | } 121 | }; 122 | 123 | opt_onError = opt_onError || handleCreationError; 124 | 125 | if (canvas.addEventListener) { 126 | canvas.addEventListener("webglcontextcreationerror", function(event) { 127 | opt_onError(event.statusMessage); 128 | }, false); 129 | } 130 | var context = create3DContext(canvas, opt_attribs); 131 | if (!context) { 132 | if (!window.WebGLRenderingContext) { 133 | opt_onError(""); 134 | } else { 135 | opt_onError(""); 136 | } 137 | } 138 | 139 | return context; 140 | }; 141 | 142 | /** 143 | * Creates a webgl context. 144 | * @param {!Canvas} canvas The canvas tag to get context 145 | * from. If one is not passed in one will be created. 146 | * @return {!WebGLContext} The created context. 147 | */ 148 | var create3DContext = function(canvas, opt_attribs) { 149 | var names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"]; 150 | var context = null; 151 | for (var ii = 0; ii < names.length; ++ii) { 152 | try { 153 | context = canvas.getContext(names[ii], opt_attribs); 154 | } catch(e) {} 155 | if (context) { 156 | break; 157 | } 158 | } 159 | return context; 160 | } 161 | 162 | return { 163 | create3DContext: create3DContext, 164 | setupWebGL: setupWebGL 165 | }; 166 | }(); 167 | 168 | /** 169 | * Provides requestAnimationFrame in a cross browser 170 | * way. 171 | */ 172 | if (!window.requestAnimationFrame) { 173 | window.requestAnimationFrame = (function() { 174 | return window.requestAnimationFrame || 175 | window.webkitRequestAnimationFrame || 176 | window.mozRequestAnimationFrame || 177 | window.oRequestAnimationFrame || 178 | window.msRequestAnimationFrame || 179 | function(/* function FrameRequestCallback */ callback, /* DOMElement Element */ element) { 180 | window.setTimeout(callback, 1000/60); 181 | }; 182 | })(); 183 | } 184 | 185 | /** * ERRATA: 'cancelRequestAnimationFrame' renamed to 'cancelAnimationFrame' to reflect an update to the W3C Animation-Timing Spec. 186 | * 187 | * Cancels an animation frame request. 188 | * Checks for cross-browser support, falls back to clearTimeout. 189 | * @param {number} Animation frame request. */ 190 | if (!window.cancelAnimationFrame) { 191 | window.cancelAnimationFrame = (window.cancelRequestAnimationFrame || 192 | window.webkitCancelAnimationFrame || window.webkitCancelRequestAnimationFrame || 193 | window.mozCancelAnimationFrame || window.mozCancelRequestAnimationFrame || 194 | window.msCancelAnimationFrame || window.msCancelRequestAnimationFrame || 195 | window.oCancelAnimationFrame || window.oCancelRequestAnimationFrame || 196 | window.clearTimeout); 197 | } -------------------------------------------------------------------------------- /models/CesiumMan/CesiumMan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubgithub/learnopengl/64f9b1d3addd43dcb12e91ffe0c0f75ca58828c1/models/CesiumMan/CesiumMan.jpg -------------------------------------------------------------------------------- /models/CesiumMan/CesiumMan0.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubgithub/learnopengl/64f9b1d3addd43dcb12e91ffe0c0f75ca58828c1/models/CesiumMan/CesiumMan0.bin -------------------------------------------------------------------------------- /models/female02/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | SetOutputFilter DEFLATE 3 | 4 | -------------------------------------------------------------------------------- /models/female02/01_-_Default1noCulling.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubgithub/learnopengl/64f9b1d3addd43dcb12e91ffe0c0f75ca58828c1/models/female02/01_-_Default1noCulling.JPG -------------------------------------------------------------------------------- /models/female02/02_-_Default1noCulling.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubgithub/learnopengl/64f9b1d3addd43dcb12e91ffe0c0f75ca58828c1/models/female02/02_-_Default1noCulling.JPG -------------------------------------------------------------------------------- /models/female02/03_-_Default1noCulling.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubgithub/learnopengl/64f9b1d3addd43dcb12e91ffe0c0f75ca58828c1/models/female02/03_-_Default1noCulling.JPG -------------------------------------------------------------------------------- /models/female02/Female02_bin.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubgithub/learnopengl/64f9b1d3addd43dcb12e91ffe0c0f75ca58828c1/models/female02/Female02_bin.bin -------------------------------------------------------------------------------- /models/female02/Female02_bin.js: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "metadata" : 4 | { 5 | "formatVersion" : 3.1, 6 | "sourceFile" : "female02.obj", 7 | "generatedBy" : "OBJConverter", 8 | "vertices" : 3274, 9 | "faces" : 6233, 10 | "normals" : 3292, 11 | "uvs" : 4935, 12 | "materials" : 6 13 | }, 14 | 15 | "materials": [ { 16 | "DbgColor" : 15658734, 17 | "DbgIndex" : 0, 18 | "DbgName" : "_03_-_Default1noCulli__03_-_Default1noCulli", 19 | "colorDiffuse" : [0.64, 0.64, 0.64], 20 | "colorSpecular" : [0.165, 0.165, 0.165], 21 | "illumination" : 2, 22 | "mapDiffuse" : "03_-_Default1noCulling.JPG", 23 | "opticalDensity" : 1.0, 24 | "specularCoef" : 154.901961, 25 | "opacity" : 1.0 26 | }, 27 | 28 | { 29 | "DbgColor" : 15597568, 30 | "DbgIndex" : 1, 31 | "DbgName" : "_02_-_Default1noCulli__02_-_Default1noCulli", 32 | "colorDiffuse" : [0.64, 0.64, 0.64], 33 | "colorSpecular" : [0.165, 0.165, 0.165], 34 | "illumination" : 2, 35 | "mapDiffuse" : "02_-_Default1noCulling.JPG", 36 | "opticalDensity" : 1.0, 37 | "specularCoef" : 154.901961, 38 | "opacity" : 1.0 39 | }, 40 | 41 | { 42 | "DbgColor" : 60928, 43 | "DbgIndex" : 2, 44 | "DbgName" : "FrontColorNoCullingID__02_-_Default1noCulli", 45 | "colorDiffuse" : [0.8, 0.8, 0.8], 46 | "colorSpecular" : [0.165, 0.165, 0.165], 47 | "illumination" : 2, 48 | "mapDiffuse" : "02_-_Default1noCulling.JPG", 49 | "opticalDensity" : 1.0, 50 | "specularCoef" : 154.901961, 51 | "opacity" : 1.0 52 | }, 53 | 54 | { 55 | "DbgColor" : 238, 56 | "DbgIndex" : 3, 57 | "DbgName" : "FrontColorNoCullingID__03_-_Default1noCulli", 58 | "colorDiffuse" : [0.8, 0.8, 0.8], 59 | "colorSpecular" : [0.165, 0.165, 0.165], 60 | "illumination" : 2, 61 | "mapDiffuse" : "03_-_Default1noCulling.JPG", 62 | "opticalDensity" : 1.0, 63 | "specularCoef" : 154.901961, 64 | "opacity" : 1.0 65 | }, 66 | 67 | { 68 | "DbgColor" : 15658496, 69 | "DbgIndex" : 4, 70 | "DbgName" : "_01_-_Default1noCulli__01_-_Default1noCulli", 71 | "colorDiffuse" : [0.64, 0.64, 0.64], 72 | "colorSpecular" : [0.165, 0.165, 0.165], 73 | "illumination" : 2, 74 | "mapDiffuse" : "01_-_Default1noCulling.JPG", 75 | "opticalDensity" : 1.0, 76 | "specularCoef" : 154.901961, 77 | "opacity" : 1.0 78 | }, 79 | 80 | { 81 | "DbgColor" : 61166, 82 | "DbgIndex" : 5, 83 | "DbgName" : "FrontColorNoCullingID__01_-_Default1noCulli", 84 | "colorDiffuse" : [0.8, 0.8, 0.8], 85 | "colorSpecular" : [0.165, 0.165, 0.165], 86 | "illumination" : 2, 87 | "mapDiffuse" : "01_-_Default1noCulling.JPG", 88 | "opticalDensity" : 1.0, 89 | "specularCoef" : 154.901961, 90 | "opacity" : 1.0 91 | }], 92 | 93 | "buffers": "Female02_bin.bin" 94 | 95 | } 96 | -------------------------------------------------------------------------------- /models/female02/female02.mtl: -------------------------------------------------------------------------------- 1 | # Material Count: 6 2 | newmtl FrontColorNoCullingID__01_-_Default1noCulli 3 | Ns 154.901961 4 | Ka 0.000000 0.000000 0.000000 5 | Kd 0.800000 0.800000 0.800000 6 | Ks 0.165000 0.165000 0.165000 7 | Ni 1.000000 8 | d 1.000000 9 | illum 2 10 | map_Kd 01_-_Default1noCulling.JPG 11 | 12 | 13 | newmtl _02_-_Default1noCulli__02_-_Default1noCulli 14 | Ns 154.901961 15 | Ka 0.000000 0.000000 0.000000 16 | Kd 0.640000 0.640000 0.640000 17 | Ks 0.165000 0.165000 0.165000 18 | Ni 1.000000 19 | d 1.000000 20 | illum 2 21 | map_Kd 02_-_Default1noCulling.JPG 22 | 23 | 24 | newmtl _01_-_Default1noCulli__01_-_Default1noCulli 25 | Ns 154.901961 26 | Ka 0.000000 0.000000 0.000000 27 | Kd 0.640000 0.640000 0.640000 28 | Ks 0.165000 0.165000 0.165000 29 | Ni 1.000000 30 | d 1.000000 31 | illum 2 32 | map_Kd 01_-_Default1noCulling.JPG 33 | 34 | 35 | newmtl FrontColorNoCullingID__03_-_Default1noCulli 36 | Ns 154.901961 37 | Ka 0.000000 0.000000 0.000000 38 | Kd 0.800000 0.800000 0.800000 39 | Ks 0.165000 0.165000 0.165000 40 | Ni 1.000000 41 | d 1.000000 42 | illum 2 43 | map_Kd 03_-_Default1noCulling.JPG 44 | 45 | 46 | newmtl _03_-_Default1noCulli__03_-_Default1noCulli 47 | Ns 154.901961 48 | Ka 0.000000 0.000000 0.000000 49 | Kd 0.640000 0.640000 0.640000 50 | Ks 0.165000 0.165000 0.165000 51 | Ni 1.000000 52 | d 1.000000 53 | illum 2 54 | map_Kd 03_-_Default1noCulling.JPG 55 | 56 | 57 | newmtl FrontColorNoCullingID__02_-_Default1noCulli 58 | Ns 154.901961 59 | Ka 0.000000 0.000000 0.000000 60 | Kd 0.800000 0.800000 0.800000 61 | Ks 0.165000 0.165000 0.165000 62 | Ni 1.000000 63 | d 1.000000 64 | illum 2 65 | map_Kd 02_-_Default1noCulling.JPG 66 | 67 | 68 | -------------------------------------------------------------------------------- /models/female02/readme.txt: -------------------------------------------------------------------------------- 1 | Model by Reallusion iClone from Google 3d Warehouse: 2 | 3 | http://sketchup.google.com/3dwarehouse/details?mid=2c6fd128fca34052adc5f5b98d513da1 -------------------------------------------------------------------------------- /resources/models/CesiumMan/CesiumMan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubgithub/learnopengl/64f9b1d3addd43dcb12e91ffe0c0f75ca58828c1/resources/models/CesiumMan/CesiumMan.jpg -------------------------------------------------------------------------------- /resources/models/CesiumMan/CesiumMan0.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubgithub/learnopengl/64f9b1d3addd43dcb12e91ffe0c0f75ca58828c1/resources/models/CesiumMan/CesiumMan0.bin -------------------------------------------------------------------------------- /resources/models/killer_whale/whale.CYCLES.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubgithub/learnopengl/64f9b1d3addd43dcb12e91ffe0c0f75ca58828c1/resources/models/killer_whale/whale.CYCLES.bin -------------------------------------------------------------------------------- /resources/models/simpleSkin.gltf: -------------------------------------------------------------------------------- 1 | { 2 | "scenes" : [ { 3 | "nodes" : [ 0 ] 4 | } ], 5 | 6 | "nodes" : [ { 7 | "skin" : 0, 8 | "mesh" : 0, 9 | "children" : [ 1 ] 10 | }, { 11 | "children" : [ 2 ], 12 | "translation" : [ 0.0, 1.0, 0.0 ] 13 | }, { 14 | "rotation" : [ 0.0, 0.0, 0.0, 1.0 ] 15 | } ], 16 | 17 | "meshes" : [ { 18 | "primitives" : [ { 19 | "attributes" : { 20 | "POSITION" : 1, 21 | "JOINTS_0" : 2, 22 | "WEIGHTS_0" : 3 23 | }, 24 | "indices" : 0 25 | } ] 26 | } ], 27 | 28 | "skins" : [ { 29 | "inverseBindMatrices" : 4, 30 | "joints" : [ 1, 2 ] 31 | } ], 32 | 33 | "animations" : [ { 34 | "channels" : [ { 35 | "sampler" : 0, 36 | "target" : { 37 | "node" : 2, 38 | "path" : "rotation" 39 | } 40 | } ], 41 | "samplers" : [ { 42 | "input" : 5, 43 | "interpolation" : "LINEAR", 44 | "output" : 6 45 | } ] 46 | } ], 47 | 48 | "buffers" : [ { 49 | "uri" : "data:application/gltf-buffer;base64,AAABAAMAAAADAAIAAgADAAUAAgAFAAQABAAFAAcABAAHAAYABgAHAAkABgAJAAgAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAD8AAAAAAACAPwAAAD8AAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAwD8AAAAAAACAPwAAwD8AAAAAAAAAAAAAAEAAAAAAAACAPwAAAEAAAAAA", 50 | "byteLength" : 168 51 | }, { 52 | "uri" : "data:application/gltf-buffer;base64,AAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAABAPwAAgD4AAAAAAAAAAAAAQD8AAIA+AAAAAAAAAAAAAAA/AAAAPwAAAAAAAAAAAAAAPwAAAD8AAAAAAAAAAAAAgD4AAEA/AAAAAAAAAAAAAIA+AABAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAA=", 53 | "byteLength" : 320 54 | }, { 55 | "uri" : "data:application/gltf-buffer;base64,AACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAvwAAgL8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAL8AAIC/AAAAAAAAgD8=", 56 | "byteLength" : 128 57 | }, { 58 | "uri" : "data:application/gltf-buffer;base64,AAAAAAAAAD8AAIA/AADAPwAAAEAAACBAAABAQAAAYEAAAIBAAACQQAAAoEAAALBAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAkxjEPkSLbD8AAAAAAAAAAPT9ND/0/TQ/AAAAAAAAAAD0/TQ/9P00PwAAAAAAAAAAkxjEPkSLbD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAkxjEvkSLbD8AAAAAAAAAAPT9NL/0/TQ/AAAAAAAAAAD0/TS/9P00PwAAAAAAAAAAkxjEvkSLbD8AAAAAAAAAAAAAAAAAAIA/", 59 | "byteLength" : 240 60 | } ], 61 | 62 | "bufferViews" : [ { 63 | "buffer" : 0, 64 | "byteOffset" : 0, 65 | "byteLength" : 48, 66 | "target" : 34963 67 | }, { 68 | "buffer" : 0, 69 | "byteOffset" : 48, 70 | "byteLength" : 120, 71 | "target" : 34962 72 | }, { 73 | "buffer" : 1, 74 | "byteOffset" : 0, 75 | "byteLength" : 320, 76 | "byteStride" : 16 77 | }, { 78 | "buffer" : 2, 79 | "byteOffset" : 0, 80 | "byteLength" : 128 81 | }, { 82 | "buffer" : 3, 83 | "byteOffset" : 0, 84 | "byteLength" : 240 85 | } ], 86 | 87 | "accessors" : [ { 88 | "bufferView" : 0, 89 | "byteOffset" : 0, 90 | "componentType" : 5123, 91 | "count" : 24, 92 | "type" : "SCALAR", 93 | "max" : [ 9 ], 94 | "min" : [ 0 ] 95 | }, { 96 | "bufferView" : 1, 97 | "byteOffset" : 0, 98 | "componentType" : 5126, 99 | "count" : 10, 100 | "type" : "VEC3", 101 | "max" : [ 1.0, 2.0, 0.0 ], 102 | "min" : [ 0.0, 0.0, 0.0 ] 103 | }, { 104 | "bufferView" : 2, 105 | "byteOffset" : 0, 106 | "componentType" : 5123, 107 | "count" : 10, 108 | "type" : "VEC4", 109 | "max" : [ 0, 1, 0, 0 ], 110 | "min" : [ 0, 1, 0, 0 ] 111 | }, { 112 | "bufferView" : 2, 113 | "byteOffset" : 160, 114 | "componentType" : 5126, 115 | "count" : 10, 116 | "type" : "VEC4", 117 | "max" : [ 1.0, 1.0, 0.0, 0.0 ], 118 | "min" : [ 0.0, 0.0, 0.0, 0.0 ] 119 | }, { 120 | "bufferView" : 3, 121 | "byteOffset" : 0, 122 | "componentType" : 5126, 123 | "count" : 2, 124 | "type" : "MAT4", 125 | "max" : [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -0.5, -1.0, 0.0, 1.0 ], 126 | "min" : [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -0.5, -1.0, 0.0, 1.0 ] 127 | }, { 128 | "bufferView" : 4, 129 | "byteOffset" : 0, 130 | "componentType" : 5126, 131 | "count" : 12, 132 | "type" : "SCALAR", 133 | "max" : [ 5.5 ], 134 | "min" : [ 0.0 ] 135 | }, { 136 | "bufferView" : 4, 137 | "byteOffset" : 48, 138 | "componentType" : 5126, 139 | "count" : 12, 140 | "type" : "VEC4", 141 | "max" : [ 0.0, 0.0, 0.707, 1.0 ], 142 | "min" : [ 0.0, 0.0, -0.707, 0.707 ] 143 | } ], 144 | 145 | "asset" : { 146 | "version" : "2.0" 147 | } 148 | } -------------------------------------------------------------------------------- /resources/webgl-lessons-ui.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016, Gregg Tavares. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above 12 | * copyright notice, this list of conditions and the following disclaimer 13 | * in the documentation and/or other materials provided with the 14 | * distribution. 15 | * * Neither the name of Gregg Tavares. nor the names of his 16 | * contributors may be used to endorse or promote products derived from 17 | * this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | 33 | (function(root, factory) { // eslint-disable-line 34 | if (typeof define === 'function' && define.amd) { 35 | // AMD. Register as an anonymous module. 36 | define([], function() { 37 | return factory.call(root); 38 | }); 39 | } else { 40 | // Browser globals 41 | root.webglLessonsUI = factory.call(root); 42 | } 43 | }(this, function() { 44 | 45 | const gopt = getQueryParams(); 46 | 47 | function setupSlider(selector, options) { 48 | var parent = document.querySelector(selector); 49 | if (!parent) { 50 | return; // like jquery don't fail on a bad selector 51 | } 52 | if (!options.name) { 53 | options.name = selector.substring(1); 54 | } 55 | return createSlider(parent, options); 56 | } 57 | 58 | function createSlider(parent, options) { 59 | var precision = options.precision || 0; 60 | var min = options.min || 0; 61 | var step = options.step || 1; 62 | var value = options.value || 0; 63 | var max = options.max || 1; 64 | var fn = options.slide; 65 | var name = gopt["ui-" + options.name] || options.name; 66 | var uiPrecision = options.uiPrecision === undefined ? precision : options.uiPrecision; 67 | var uiMult = options.uiMult || 1; 68 | 69 | min /= step; 70 | max /= step; 71 | value /= step; 72 | 73 | parent.innerHTML = ` 74 |
75 |
${name}
76 |
77 | 78 |
79 | `; 80 | var valueElem = parent.querySelector(".gman-widget-value"); 81 | var sliderElem = parent.querySelector(".gman-widget-slider"); 82 | 83 | function updateValue(value) { 84 | valueElem.textContent = (value * step * uiMult).toFixed(uiPrecision); 85 | } 86 | 87 | updateValue(value); 88 | 89 | function handleChange(event) { 90 | var value = parseInt(event.target.value); 91 | updateValue(value); 92 | fn(event, { value: value * step }); 93 | } 94 | 95 | sliderElem.addEventListener('input', handleChange); 96 | sliderElem.addEventListener('change', handleChange); 97 | 98 | return { 99 | elem: parent, 100 | updateValue: (v) => { 101 | v /= step; 102 | sliderElem.value = v; 103 | updateValue(v); 104 | }, 105 | }; 106 | } 107 | 108 | function makeSlider(options) { 109 | const div = document.createElement("div"); 110 | return createSlider(div, options); 111 | } 112 | 113 | var widgetId = 0; 114 | function getWidgetId() { 115 | return "__widget_" + widgetId++; 116 | } 117 | 118 | function makeCheckbox(options) { 119 | const div = document.createElement("div"); 120 | div.className = "gman-widget-outer"; 121 | const label = document.createElement("label"); 122 | const id = getWidgetId(); 123 | label.setAttribute('for', id); 124 | label.textContent = gopt["ui-" + options.name] || options.name; 125 | label.className = "gman-checkbox-label"; 126 | const input = document.createElement("input"); 127 | input.type = "checkbox"; 128 | input.checked = options.value; 129 | input.id = id; 130 | input.className = "gman-widget-checkbox"; 131 | div.appendChild(label); 132 | div.appendChild(input); 133 | input.addEventListener('change', function(e) { 134 | options.change(e, { 135 | value: e.target.checked, 136 | }); 137 | }); 138 | 139 | return { 140 | elem: div, 141 | updateValue: function(v) { 142 | input.checked = !!v; 143 | }, 144 | }; 145 | } 146 | 147 | function makeOption(options) { 148 | const div = document.createElement("div"); 149 | div.className = "gman-widget-outer"; 150 | const label = document.createElement("label"); 151 | const id = getWidgetId(); 152 | label.setAttribute('for', id); 153 | label.textContent = gopt["ui-" + options.name] || options.name; 154 | label.className = "gman-widget-label"; 155 | const selectElem = document.createElement("select"); 156 | options.options.forEach((name, ndx) => { 157 | const opt = document.createElement("option"); 158 | opt.textContent = gopt["ui-" + name] || name; 159 | opt.value = ndx; 160 | opt.selected = ndx === options.value 161 | selectElem.appendChild(opt); 162 | }); 163 | selectElem.className = "gman-widget-select"; 164 | div.appendChild(label); 165 | div.appendChild(selectElem); 166 | selectElem.addEventListener('change', function(e) { 167 | options.change(e, { 168 | value: selectElem.selectedIndex, 169 | }); 170 | }); 171 | 172 | return { 173 | elem: div, 174 | updateValue: function(v) { 175 | selectedElem.selectedIndex = v; 176 | }, 177 | }; 178 | } 179 | 180 | function noop() { 181 | } 182 | 183 | function genSlider(object, ui) { 184 | const changeFn = ui.change || noop; 185 | ui.name = ui.name || ui.key; 186 | ui.value = object[ui.key]; 187 | ui.slide = ui.slide || function(event, uiInfo) { 188 | object[ui.key] = uiInfo.value; 189 | changeFn(); 190 | }; 191 | return makeSlider(ui); 192 | } 193 | 194 | function genCheckbox(object, ui) { 195 | const changeFn = ui.change || noop; 196 | ui.value = object[ui.key]; 197 | ui.name = ui.name || ui.key; 198 | ui.change = function(event, uiInfo) { 199 | object[ui.key] = uiInfo.value; 200 | changeFn(); 201 | }; 202 | return makeCheckbox(ui); 203 | } 204 | 205 | function genOption(object, ui) { 206 | const changeFn = ui.change || noop; 207 | ui.value = object[ui.key]; 208 | ui.name = ui.name || ui.key; 209 | ui.change = function(event, uiInfo) { 210 | object[ui.key] = uiInfo.value; 211 | changeFn(); 212 | }; 213 | return makeOption(ui); 214 | } 215 | 216 | const uiFuncs = { 217 | slider: genSlider, 218 | checkbox: genCheckbox, 219 | option: genOption, 220 | }; 221 | 222 | function setupUI(parent, object, uiInfos) { 223 | const widgets = {}; 224 | uiInfos.forEach(function(ui) { 225 | const widget = uiFuncs[ui.type](object, ui); 226 | parent.appendChild(widget.elem); 227 | widgets[ui.key] = widget; 228 | }); 229 | return widgets; 230 | } 231 | 232 | function updateUI(widgets, data) { 233 | Object.keys(widgets).forEach(key => { 234 | const widget = widgets[key]; 235 | widget.updateValue(data[key]); 236 | }); 237 | } 238 | 239 | function getQueryParams() { 240 | var params = {}; 241 | if (window.hackedParams) { 242 | Object.keys(window.hackedParams).forEach(function(key) { 243 | params[key] = window.hackedParams[key]; 244 | }); 245 | } 246 | if (window.location.search) { 247 | window.location.search.substring(1).split("&").forEach(function(pair) { 248 | var keyValue = pair.split("=").map(function (kv) { 249 | return decodeURIComponent(kv); 250 | }); 251 | params[keyValue[0]] = keyValue[1]; 252 | }); 253 | } 254 | return params; 255 | } 256 | 257 | return { 258 | setupUI: setupUI, 259 | updateUI: updateUI, 260 | setupSlider: setupSlider, 261 | makeSlider: makeSlider, 262 | makeCheckbox: makeCheckbox, 263 | }; 264 | 265 | })); 266 | 267 | -------------------------------------------------------------------------------- /resources/webgl-tutorials.css: -------------------------------------------------------------------------------- 1 | /* Licensed under a BSD license. See ../license.html for license */ 2 | 3 | html { 4 | box-sizing: border-box; 5 | } 6 | *, *:before, *:after { 7 | box-sizing: inherit; 8 | user-select: none; 9 | } 10 | 11 | body { 12 | background-color: #aaa; 13 | font-family: Sans-Serif; 14 | } 15 | 16 | canvas { 17 | background-color: #fff; 18 | border: 1px solid black; 19 | /* NOTE: This size is changed if in iframe - see below '.iframe canvas' */ 20 | width: 800px; 21 | height: 600px; 22 | display: block; 23 | } 24 | 25 | #uiContainer { 26 | position: absolute; 27 | top: 10px; 28 | right: 10px; 29 | z-index: 3; 30 | font-family: monospace; 31 | pointer-events: none; 32 | 33 | text-shadow: 34 | -1px -1px 0 #FFF, 35 | 1px -1px 0 #FFF, 36 | -1px 1px 0 #FFF, 37 | 1px 1px 0 #FFF; 38 | } 39 | #ui { 40 | opacity: 0.8; 41 | } 42 | #ui>div { 43 | pointer-events: none; 44 | } 45 | #ui input, #ui select, #ui option, #ui canvas { 46 | pointer-events: auto; 47 | } 48 | 49 | .gman-slider-label, .gman-widget-label, .gman-checkbox-label { 50 | font-size: small; 51 | min-width: 10em; 52 | text-align: right; 53 | } 54 | .gman-checkbox-label { 55 | pointer-events: auto; 56 | } 57 | .gman-widget-value { 58 | float: right; 59 | font-size: small; 60 | order: 1; 61 | min-width: 3em; 62 | } 63 | 64 | .gman-slider-upper { 65 | height: 1.5em; 66 | } 67 | .gman-slider-outer, .gman-widget-outer { 68 | float: right; 69 | display: flex; 70 | align-items: center; 71 | height: 1.7em; 72 | } 73 | .gman-widget-slider, .gman-widget-checkbox, .gman-widget-select { 74 | opacity: 0.5; 75 | font-size: large; 76 | margin-left: .3em; 77 | margin-right: .3em; 78 | } 79 | .gman-widget-select { 80 | font-size: small; 81 | } 82 | .gman-widget-slider { 83 | min-width: 120px; 84 | } 85 | 86 | 87 | /* styles to apply if in an iframe */ 88 | 89 | html.iframe { 90 | height: 100vh; 91 | } 92 | body.iframe { 93 | width: 100vw; 94 | height: 100vh; 95 | margin: 0; 96 | overflow: hidden; 97 | } 98 | 99 | .iframe>.description { 100 | display: none; 101 | } 102 | .iframe .divcavnas { 103 | width: 100vw; 104 | height: 100vh; 105 | } 106 | .iframe canvas { 107 | width: 100vw; 108 | height: 100vh; 109 | max-width: 100vw; 110 | border: none; 111 | } 112 | 113 | .iframe>#example { 114 | width: 100%; 115 | height: 100%; 116 | } 117 | #ui #rotation>canvas { 118 | background-color: rgba(255, 255, 255, 0.6); 119 | } 120 | #ui { 121 | width: 200px; 122 | } 123 | 124 | .console { 125 | font-family: monospace; 126 | max-height: 50%; 127 | position: fixed; 128 | bottom: 0; 129 | left: 0; 130 | width: 100%; 131 | overflow: auto; 132 | background: #DDD; 133 | } 134 | .console>div { 135 | white-space: pre-wrap; 136 | border-top: 1px solid black; 137 | padding-left: 0.2em; 138 | padding-right: 0.2em; 139 | } 140 | .console>.error { 141 | background: red; 142 | color: white; 143 | } 144 | 145 | .contextlost { 146 | display: flex; 147 | justify-content: center; 148 | align-items: center; 149 | width: 100vw; 150 | height: 100vh; 151 | position: absolute; 152 | left: 0; 153 | top: 0; 154 | background-color: rgba(0, 0, 0, 0.8); 155 | color: white; 156 | z-index: 10000; 157 | } 158 | .contextlost>div { 159 | padding: 1em; 160 | border-radius: 0.5em; 161 | background: red; 162 | color: white; 163 | } 164 | 165 | @media (max-width: 390px) { 166 | pre { 167 | font-size: xx-small !important; 168 | max-width: 300px !important; 169 | } 170 | canvas { 171 | width: 100vw; 172 | } 173 | .iframe canvas { 174 | width: 100vw; 175 | height: 100vh; 176 | border: none; 177 | } 178 | #uiContainer { 179 | top: 120px; 180 | } 181 | .iframe #uiContainer { 182 | top: 10px; 183 | } 184 | } 185 | 186 | 187 | 188 | -------------------------------------------------------------------------------- /rtsp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | WebGL - Skinning 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /sample/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Babylon.js sample code 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 40 | 41 | 42 | 43 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /sample/textures/grass.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubgithub/learnopengl/64f9b1d3addd43dcb12e91ffe0c0f75ca58828c1/sample/textures/grass.jpg -------------------------------------------------------------------------------- /sample/textures/misc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubgithub/learnopengl/64f9b1d3addd43dcb12e91ffe0c0f75ca58828c1/sample/textures/misc.jpg -------------------------------------------------------------------------------- /sample/textures/tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubgithub/learnopengl/64f9b1d3addd43dcb12e91ffe0c0f75ca58828c1/sample/textures/tree.png -------------------------------------------------------------------------------- /webgl-skinning.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | WebGL - Skinning 8 | 9 | 10 | 11 | 12 | 13 | 14 | 33 | 40 | 51 | 58 | 59 | 60 | 61 | 261 | 262 | -------------------------------------------------------------------------------- /一些比较炫的例子/星系/css/style.css: -------------------------------------------------------------------------------- 1 | body{ 2 | margin:0; 3 | background-color:#000; 4 | } 5 | canvas{ 6 | cursor:grab; 7 | cursor:-webkit-grab; 8 | cursor:-moz-grab; 9 | } 10 | canvas:active{ 11 | cursor:grabbing; 12 | cursor:-webkit-grabbing; 13 | cursor:-moz-grabbing; 14 | } 15 | a.twitter, a.more{ 16 | position:absolute; 17 | bottom:40px; 18 | right:10px; 19 | font-family:Arial; 20 | color:#33c; 21 | margin-right:-500px; 22 | transition:margin-right 500ms ease; 23 | } 24 | p{ 25 | margin:3px; 26 | position:relative; 27 | font:normal 15px Arial; 28 | } 29 | p.shadow{ 30 | text-shadow:1px 1px 2px #000 ; 31 | } 32 | div.layout{ 33 | top:-250px; 34 | width:100%; 35 | position:absolute; 36 | transition:top 500ms ease; 37 | } 38 | #instruction{ 39 | z-index:1; 40 | color:#f90; 41 | font-family:Arial; 42 | padding:9px 0 5px 0; 43 | background-color:darkslategrey; 44 | top:100%; 45 | width:50%; 46 | position:absolute; 47 | left:25%; 48 | opacity:.8; 49 | border-radius:0px 0px 100px 100px; 50 | text-align:center; 51 | transition:all 500ms ease; 52 | } 53 | #good-person{ 54 | cursor:pointer; 55 | color:#f90; 56 | font-family:Arial; 57 | padding:9px 0 5px 0; 58 | background-color:darkslategrey; 59 | bottom:-50px; 60 | box-shadow:0px -2px 4px black inset; 61 | width:50%; 62 | position:absolute; 63 | left:25%; 64 | opacity:.8; 65 | border-radius:100px 100px 0px 0px ; 66 | text-align:center; 67 | transition:all 500ms ease; 68 | } 69 | #info{ 70 | border:solid 4px #444; 71 | border-top:none; 72 | border-radius:0px 0px 10px 10px; 73 | z-index:2; 74 | box-shadow:0px 5px 5px black ; 75 | color:#aaa; 76 | font-family:Arial; 77 | position:relative; 78 | text-align:center; 79 | padding:1px; 80 | top:0px; 81 | width:50%; 82 | min-width:500px; 83 | margin:auto; 84 | background:linear-gradient(-78deg ,#222 23%, #446 39%, #222 45%,#222 52%, #334 55%, #222 57%); 85 | } 86 | span.black{ 87 | width:3%; 88 | height:7%; 89 | background:black; 90 | position:absolute; 91 | left:-1%; 92 | box-shadow:-2px 0px 5px #222 inset; 93 | } 94 | span.right{ 95 | position:absolute; 96 | left:98%; 97 | box-shadow:2px 0px 5px #222 inset; 98 | } 99 | span.one{top:10%} 100 | span.two{top:19%} 101 | span.three{top:28%} 102 | span.four{top:37%} 103 | p.positionning{ 104 | width:50%; 105 | background:#000; 106 | height:2px; 107 | text-align:left; 108 | margin:10px auto; 109 | } 110 | #timeline{ 111 | height:2px; 112 | width:0%; 113 | position:absolute; 114 | top:0%; 115 | } 116 | .scanning{ 117 | background:#f90; 118 | /*animation:scan 8s linear;*/ /* way faster on mobile without that*/ 119 | } 120 | @keyframes scan{ 121 | 0%{ 122 | width:0%; 123 | box-shadow:0px 0px 20px 5px #f90; 124 | } 125 | 100%{ 126 | width:100%; 127 | box-shadow:0px 0px 20px 5px #f90; 128 | } 129 | } 130 | .waiting{ 131 | background:#3c4; 132 | /*animation:wait 4s infinite;*/ /*same*/ 133 | } 134 | @keyframes wait{ 135 | 0%{ 136 | width:100%; 137 | box-shadow:0px 0px 20px 3px #3c4; 138 | } 139 | 50%{ 140 | width:100%; 141 | box-shadow:0px 0px 0px 0px #3c4; 142 | } 143 | 100%{ 144 | width:100%; 145 | box-shadow:0px 0px 20px 3px #3c4; 146 | } 147 | } 148 | .warning{ 149 | background:#f50; 150 | animation:warn 1s infinite; 151 | } 152 | @keyframes warn{ 153 | 0%{ 154 | width:100%; 155 | box-shadow:0px 0px 0px 0px #f50; 156 | } 157 | 50%{ 158 | width:100%; 159 | box-shadow:0px 0px 20px 3px #f50; 160 | } 161 | 100%{ 162 | width:100%; 163 | box-shadow:0px 0px 0px 0px #f50; 164 | } 165 | } 166 | span.eye{ 167 | width:40px; 168 | height:40px; 169 | background:-webkit-radial-gradient(orange 0% , red 20%, black 60%, #555 61%); 170 | background:-moz-radial-gradient(orange 0% , red 20%, black 60%, #555 61%); 171 | background:-ms-radial-gradient(orange 0% , red 20%, black 60%, #555 61%); 172 | background:-o-radial-gradient(orange 0% , red 20%, black 60%, #555 61%); 173 | border-radius:50%; 174 | position:absolute; 175 | left:47px; 176 | top:7px; 177 | } 178 | span.metal{ 179 | font:bold 10px Arial; 180 | width:40px; 181 | height:40px; 182 | background:-webkit-radial-gradient(#777 15%,#888 35%, #666 50%,#888 55%,#555 65%); 183 | background:-moz-radial-gradient(#666 0% , #777 15%,#888 35%, #666 50%,#888 55%,#555 65%); 184 | background:-ms-radial-gradient(#666 0% , #777 15%,#888 35%, #666 50%,#888 55%,#555 65%); 185 | background:-o-radial-gradient(#666 0% , #777 15%,#888 35%, #666 50%,#888 55%,#555 65%); 186 | border-radius:50%; 187 | box-shadow:0px 0px 15px 3px black; 188 | position:absolute; 189 | right:47px; 190 | top:7px; 191 | color:#222; 192 | } 193 | .clic{ 194 | animation:clic .2s linear 2 alternate; 195 | } 196 | @keyframes clic{ 197 | 0%{box-shadow:0px 0px 15px 3px black} 198 | 100%{box-shadow:0px 0px 15px 3px green} 199 | } 200 | span.metal:after{ 201 | position:relative; 202 | content:'ABORT'; 203 | text-align:center; 204 | width:100%; 205 | top:14px 206 | } 207 | .abort{ 208 | animation:aborting .4s linear infinite alternate; 209 | } 210 | @keyframes aborting{ 211 | 0%{color:#222;} 212 | 100%{color:red;} 213 | } 214 | #log{ 215 | font:normal 15px Courier; 216 | border-radius:10px; 217 | height:36px; 218 | padding:3px 15px; 219 | background:black; 220 | } 221 | #howmuch { 222 | top:20%; 223 | height:71%; 224 | width:58px; 225 | position:absolute; 226 | text-align:center; 227 | border:solid 4px #444; 228 | border-left:none; 229 | border-radius:0px 10px 10px 0px; 230 | background:#222; 231 | padding:2px; 232 | left:-100px; 233 | transition:left 500ms ease; 234 | } 235 | #good{ 236 | top:15%; 237 | color:#590; 238 | font:bold 15px Arial; 239 | left:1px; 240 | } 241 | #bad{ 242 | font:bold 15px Arial; 243 | color:#a11; 244 | position:absolute; 245 | bottom:22%; 246 | left:4px; 247 | } 248 | #gauge { 249 | position:absolute; 250 | top:50%; 251 | left:11px; 252 | border-top: 4px solid transparent; 253 | border-bottom: 4px solid transparent; 254 | border-left: 19px solid #444; 255 | border-right: 19px solid #444; 256 | width:2px; 257 | transition:top 2s ease; 258 | } 259 | #bg{ 260 | width:40px; 261 | height:40%; 262 | background:black; 263 | position:absolute; 264 | top:30%; 265 | left:11px; 266 | } 267 | p.counter-title{ 268 | color:#aaa; 269 | font:normal 10px Arial; 270 | } 271 | #destroyed{ 272 | position:absolute; 273 | bottom:0; 274 | left:-2px; 275 | } 276 | p.counter{ 277 | width:40px; 278 | height:40px; 279 | left:7px; 280 | border-radius:50%; 281 | border:solid 1px #555; 282 | position:absolute; 283 | font:bold 37px Arial; 284 | color:#aaa; 285 | background:#222; 286 | } 287 | #destroyedresult{ 288 | bottom:30px; 289 | } 290 | p.change{ 291 | animation:changing 2s linear; 292 | } 293 | @keyframes changing{ 294 | 0%{ 295 | background:#ccc; 296 | } 297 | 100%{ 298 | background:#222; 299 | } 300 | } -------------------------------------------------------------------------------- /一些比较炫的例子/星系/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 基于HTML5 WebGL的3D星云动画特效DEMO演示 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 45 | 69 | 70 | 71 | 72 | 73 | 74 |
75 | 76 | 77 |
78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /代码库/生成cube.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 坐标系统 6 | 7 | 8 | 9 | 10 | 273 | 274 | 275 | 276 | Please use a browser that supports "canvas" 277 | 278 | 279 | -------------------------------------------------------------------------------- /学习webgl/你好三角形.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 你好三角形 6 | 7 | 8 | 9 | 70 | 71 | 72 | 73 | Please use a browser that supports "canvas" 74 | 75 | 76 | -------------------------------------------------------------------------------- /学习webgl/纹理.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 你好三角形 6 | 7 | 8 | 9 | 109 | 110 | 111 | 112 | Please use a browser that supports "canvas" 113 | 114 | 115 | -------------------------------------------------------------------------------- /新建文本文档.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 24 | 25 | 26 |
27 |
28 | 29 | 30 | -------------------------------------------------------------------------------- /第一章/coordinateSystem.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 坐标系统 6 | 7 | 8 | 9 | 10 | 269 | 270 | 271 | 272 | Please use a browser that supports "canvas" 273 | 274 | 275 | -------------------------------------------------------------------------------- /第一章/texture.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 纹理 6 | 7 | 8 | 9 | 165 | 166 | 167 | 168 | Please use a browser that supports "canvas" 169 | 170 | 171 | -------------------------------------------------------------------------------- /第一章/transform.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 变换 6 | 7 | 8 | 9 | 10 | 198 | 199 | 200 | 201 | 202 | Please use a browser that supports "canvas" 203 | 204 | 205 | -------------------------------------------------------------------------------- /第一章/triangle.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 你好三角形 6 | 7 | 8 | 9 | 70 | 71 | 72 | 73 | Please use a browser that supports "canvas" 74 | 75 | 76 | -------------------------------------------------------------------------------- /第三章/FrameBuffer_cube.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Frame Buffer Object 6 | 7 | 8 | 9 | 10 | Please use a browser that supports "canvas" 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /第三章/depthTest.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 深度缓冲 6 | 7 | 8 | 9 | 10 | 265 | 266 | 267 | 268 | Please use a browser that supports "canvas" 269 | 270 |
271 |

深度值与深度缓冲进行数值比较,按照less比较规则,深度值较小的绘制,大的舍弃不绘制,从而保证在实现方向上,离观察者近的片元绘制,离观察者远的片元被遮盖。

272 |

当深度测试(Depth Testing)被启用的时候,OpenGL会将一个片段的的深度值与深度缓冲的内容进行对比。OpenGL会执行一个深度测试,如果这个测试通过了的话,深度缓冲将会更新为新的深度值。

273 |

世界坐标系中的z值与深度值理论上应该是一个线性关系,但实际并不是,是一个拱形的非线性关系,越远的z值,深度值越接近1,近的则比较精确的呈线性关系。

274 |
275 | 276 | -------------------------------------------------------------------------------- /第三章/wireframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 你好三角形 6 | 7 | 8 | 9 | 94 | 95 | 96 | 97 | Please use a browser that supports "canvas" 98 | 99 | 100 | -------------------------------------------------------------------------------- /第三章/实例化.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 你好三角形 6 | 7 | 8 | 9 | 103 | 104 | 105 |
106 | 107 | Please use a browser that supports "canvas" 108 | 109 |
110 | 111 | -------------------------------------------------------------------------------- /第二章/BaseLighting.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 相机 6 | 7 | 8 | 9 | 10 | 249 | 250 | 251 | 252 | Please use a browser that supports "canvas" 253 | 254 | 255 | -------------------------------------------------------------------------------- /第二章/LightingMaps.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 光照贴图 6 | 7 | 8 | 9 | 10 | 188 | 189 | 190 | 191 | Please use a browser that supports "canvas" 192 | 193 | 194 | -------------------------------------------------------------------------------- /第二章/LoadModel.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 载入模型 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 27 | 28 | 29 | 30 | Please use a browser that supports "canvas" 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /第二章/MirrorReflect.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 镜面高光 6 | 7 | 8 | 9 | 10 | 257 | 258 | 259 | 260 | Please use a browser that supports "canvas" 261 | 262 | 263 | -------------------------------------------------------------------------------- /第二章/color.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 相机 6 | 7 | 8 | 9 | 10 | 227 | 228 | 229 | 230 | Please use a browser that supports "canvas" 231 | 232 | 233 | -------------------------------------------------------------------------------- /第二章/光照贴图-镜面光贴图.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 光照贴图 6 | 7 | 8 | 9 | 10 | 250 | 251 | 252 | 253 | Please use a browser that supports "canvas" 254 | 255 | 256 | -------------------------------------------------------------------------------- /第二章/基础光照.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 基础光照 6 | 7 | 8 | 9 | 10 | 224 | 225 | 226 | 227 | Please use a browser that supports "canvas" 228 | 229 | 230 | -------------------------------------------------------------------------------- /第四章-高级光照/视差贴图.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /视频纹理/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | WebGL Demo 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /视频纹理/test.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubgithub/learnopengl/64f9b1d3addd43dcb12e91ffe0c0f75ca58828c1/视频纹理/test.mp4 --------------------------------------------------------------------------------