├── .gitignore ├── .gitmodules ├── .haxerc ├── LICENSE ├── README.md ├── bin └── index.html ├── build.hxml ├── haxe_libraries ├── asynctools.hxml ├── haxe-loader.hxml └── vector-math.hxml ├── package-lock.json ├── package.json ├── src ├── Main.hx ├── ch02 │ ├── ColorTriangle.hx │ ├── FirstUniform.hx │ └── RedTriangle.hx ├── ch03 │ ├── Brightness.hx │ ├── ColorMath.hx │ ├── Parrot.hx │ ├── Quad.hx │ ├── ScrollingUV.hx │ └── shaders │ │ ├── brightness.frag.glsl │ │ ├── brightness.vert.glsl │ │ ├── color-math.frag.glsl │ │ ├── color-math.vert.glsl │ │ ├── parrot.frag.glsl │ │ ├── parrot.vert.glsl │ │ ├── quad.frag.glsl │ │ ├── quad.vert.glsl │ │ ├── scrolling-uv.frag.glsl │ │ └── scrolling-uv.vert.glsl ├── ch04 │ ├── AlphaBlending.hx │ ├── DepthTest.hx │ ├── GreenMan.hx │ ├── SpriteSheet.hx │ └── shaders │ │ ├── bg.frag.glsl │ │ ├── bg.vert.glsl │ │ ├── cloud.frag.glsl │ │ ├── cloud.vert.glsl │ │ ├── green-man.frag.glsl │ │ ├── green-man.vert.glsl │ │ ├── spriteSheet.vert.glsl │ │ ├── sun.frag.glsl │ │ └── sun.vert.glsl ├── ch05 │ ├── WalkingMan.hx │ └── shaders │ │ ├── bg.frag.glsl │ │ ├── bg.vert.glsl │ │ ├── cloud.frag.glsl │ │ ├── cloud.vert.glsl │ │ ├── green-man.frag.glsl │ │ ├── spriteSheet.vert.glsl │ │ ├── sun.frag.glsl │ │ └── sun.vert.glsl ├── ch06 │ ├── Cameras.hx │ └── shaders │ │ ├── bg.frag.glsl │ │ ├── bg.vert.glsl │ │ ├── cloud.frag.glsl │ │ ├── cloud.vert.glsl │ │ ├── green-man.frag.glsl │ │ ├── spriteSheet.vert.glsl │ │ ├── sun.frag.glsl │ │ └── sun.vert.glsl ├── ch07 │ ├── PerspectiveTorus.hx │ └── shaders │ │ ├── passthrough.vert.glsl │ │ └── uv_vis.frag.glsl ├── ch08 │ ├── DiffuseLighting.hx │ ├── RimLight.hx │ └── shaders │ │ ├── diffuse_light.frag.glsl │ │ ├── diffuse_light.vert.glsl │ │ ├── rim_light.frag.glsl │ │ └── rim_light.vert.glsl ├── ch09 │ ├── BlinnPhongTorus.hx │ ├── BlinnShield.hx │ ├── DiffuseSpecularTorus.hx │ ├── LightModelBase.hx │ ├── PhongTorus.hx │ ├── SpecularTorus.hx │ └── shaders │ │ ├── blinnPhong.frag.glsl │ │ ├── blinnPhong.vert.glsl │ │ ├── blinnShield.frag.glsl │ │ ├── blinnShield.vert.glsl │ │ ├── diffuseSpecular.frag.glsl │ │ ├── diffuseSpecular.vert.glsl │ │ ├── phong.frag.glsl │ │ ├── phong.vert.glsl │ │ ├── specular.frag.glsl │ │ └── specular.vert.glsl ├── ch10 │ ├── NormalMapping.hx │ ├── NormalMappingBase.hx │ ├── Water.hx │ └── shaders │ │ ├── normalMapping.frag.glsl │ │ ├── normalMapping.vert.glsl │ │ ├── water.frag.glsl │ │ └── water.vert.glsl ├── ch11 │ ├── CubeMap.hx │ ├── CubeMapBase.hx │ ├── SkyBox.hx │ └── shaders │ │ ├── cubeMap.frag.glsl │ │ ├── cubeMap.vert.glsl │ │ ├── skyBox.vert.glsl │ │ ├── water.frag.glsl │ │ └── water.vert.glsl ├── ch12 │ ├── LightBase.hx │ ├── MultiPass.hx │ ├── MultipleLights.hx │ ├── PointLightExample.hx │ ├── SpotLights.hx │ ├── lights │ │ ├── PointLight.hx │ │ └── SpotLight.hx │ ├── multipass │ │ ├── DirectionalLight.hx │ │ ├── Light.hx │ │ └── PointLight.hx │ └── shaders │ │ ├── light.glsl │ │ ├── light.vert.glsl │ │ ├── multiplLights.frag.glsl │ │ ├── pointLight.frag.glsl │ │ └── spotLight.frag.glsl ├── externs │ ├── Ogl.hx │ └── Ply.hx ├── types │ └── Types.hx └── utils │ ├── BaseOfApp.hx │ ├── BuildMatrix.hx │ ├── CalculateTangents.hx │ ├── Camera.hx │ ├── CreatePLYGeometry.hx │ ├── Degree.hx │ ├── DirectionalLight.hx │ ├── LoadImage.hx │ ├── LoadTexture.hx │ ├── Material.hx │ ├── Matrix.hx │ ├── Mesh3D.hx │ ├── OglBase.hx │ ├── Texture.hx │ ├── Transformation.hx │ └── ViewMatrix.hx └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | main.js 3 | main.js.map 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "original"] 2 | path = original 3 | url = https://github.com/Apress/practical-shader-dev 4 | -------------------------------------------------------------------------------- /.haxerc: -------------------------------------------------------------------------------- 1 | { 2 | "version": "6dc7876", 3 | "resolveLibs": "scoped" 4 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Uldis Baurovskis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Practical Shader Development HX 2 | Haxe implementation of book: [Practical Shader Development](https://www.apress.com/gp/book/9781484244562) 3 | -------------------------------------------------------------------------------- /bin/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Practical shader development 6 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /build.hxml: -------------------------------------------------------------------------------- 1 | -cp src 2 | -lib vector-math 3 | -lib haxe-loader 4 | --main Main 5 | --js bin/main.js 6 | --debug -------------------------------------------------------------------------------- /haxe_libraries/asynctools.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/asynctools#0.1.0" into asynctools/0.1.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/asynctools/0.1.0/haxelib/ 3 | -D asynctools=0.1.0 -------------------------------------------------------------------------------- /haxe_libraries/haxe-loader.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/haxe-loader#0.9.0" into haxe-loader/0.9.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/haxe-loader/0.9.0/haxelib/haxelib/ 3 | -D haxe-loader=0.9.0 -------------------------------------------------------------------------------- /haxe_libraries/vector-math.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/haxiomic/vector-math#1eb3a944d25cb08a637ef9ecb310eb7fae3a7750" into vector-math/1.4.0/github/1eb3a944d25cb08a637ef9ecb310eb7fae3a7750 2 | -cp ${HAXE_LIBCACHE}/vector-math/1.4.0/github/1eb3a944d25cb08a637ef9ecb310eb7fae3a7750/ 3 | -D vector-math=1.4.0 -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "@webpack-cli/serve": "^1.1.0", 4 | "dts2hx": "^0.15.3", 5 | "file-loader": "^6.2.0", 6 | "haxe-loader": "^0.10.0", 7 | "html-webpack-plugin": "^4.5.0", 8 | "lix": "^15.10.1", 9 | "webpack": "^5.4.0", 10 | "webpack-cli": "^4.2.0", 11 | "webpack-dev-server": "^3.11.0", 12 | "webpack-glsl-loader": "^1.0.1" 13 | }, 14 | "scripts": { 15 | "postinstall": "lix download", 16 | "start": "webpack serve" 17 | }, 18 | "name": "practical-shader-dev-hx", 19 | "dependencies": { 20 | "@loaders.gl/core": "^2.3.6", 21 | "@loaders.gl/ply": "^2.3.6", 22 | "ogl": "^0.0.60" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Main.hx: -------------------------------------------------------------------------------- 1 | package; 2 | 3 | import ch02.RedTriangle; 4 | import ch02.ColorTriangle; 5 | import ch02.FirstUniform; 6 | import ch03.Quad; 7 | import ch03.Parrot; 8 | import ch03.ScrollingUV; 9 | import ch03.Brightness; 10 | import ch03.ColorMath; 11 | import ch04.GreenMan; 12 | import ch04.DepthTest; 13 | import ch04.AlphaBlending; 14 | import ch04.SpriteSheet; 15 | import ch05.WalkingMan; 16 | import ch06.Cameras; 17 | import ch07.PerspectiveTorus; 18 | import ch08.DiffuseLighting; 19 | import ch08.RimLight; 20 | import ch09.SpecularTorus; 21 | import ch09.DiffuseSpecularTorus; 22 | import ch09.PhongTorus; 23 | import ch09.BlinnPhongTorus; 24 | import ch09.BlinnShield; 25 | import ch10.NormalMapping; 26 | import ch10.Water; 27 | import ch11.CubeMap; 28 | import ch11.SkyBox; 29 | import ch12.PointLightExample; 30 | import ch12.SpotLights; 31 | import ch12.MultipleLights; 32 | 33 | class Main { 34 | public function new() { 35 | // new RedTriangle(); 36 | // new ColorTriangle(); 37 | // new FirstUniform(); 38 | // new Quad(); 39 | // new Parrot(); 40 | // new ScrollingUV(); 41 | // new Brightness(); 42 | // new ColorMath(); 43 | // new GreenMan(); 44 | // new DepthTest(); 45 | // new AlphaBlending(); 46 | // new SpriteSheet(); 47 | // new WalkingMan(); 48 | // new Cameras(); 49 | // new PerspectiveTorus(); 50 | // new DiffuseLighting(); 51 | // new RimLight(); 52 | // new SpecularTorus(); 53 | // new DiffuseSpecularTorus(); 54 | // new PhongTorus(); 55 | // new BlinnPhongTorus(); 56 | // new BlinnShield(); 57 | // new NormalMapping(); 58 | // new Water(); 59 | // new CubeMap(); 60 | // new SkyBox(); 61 | // new PointLightExample(); 62 | // new SpotLights(); 63 | new MultipleLights(); 64 | } 65 | 66 | static function main() { 67 | new Main(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/ch02/ColorTriangle.hx: -------------------------------------------------------------------------------- 1 | package ch02; 2 | 3 | import VectorMath.Vec3; 4 | import VectorMath.Vec4; 5 | import js.Browser; 6 | import js.html.KeyboardEvent; 7 | import types.Types.IShader; 8 | import utils.Mesh3D; 9 | import utils.BaseOfApp; 10 | import utils.Material; 11 | import types.Types.Mesh; 12 | 13 | final fragment = '#version 300 es 14 | precision highp float; 15 | 16 | out vec4 outColor; 17 | in vec4 fragColor; 18 | 19 | void main() 20 | { 21 | outColor = fragColor; 22 | }'; 23 | final vertex = '#version 300 es 24 | precision highp float; 25 | 26 | layout (location = 0) in vec3 position; 27 | layout (location = 1) in vec4 color; 28 | 29 | out vec4 fragColor; 30 | 31 | void main() 32 | { 33 | fragColor = color; 34 | gl_Position = vec4(position, 1.0); 35 | }'; 36 | 37 | class ColorTriangle extends BaseOfApp { 38 | private var triangle:Mesh; 39 | private var shader:IShader; 40 | 41 | public function new() { 42 | super(); 43 | } 44 | 45 | override private function setup():Void { 46 | super.setup(); 47 | final width = 2; 48 | final height = 2; 49 | shader = new Material(ctx); 50 | shader.load(vertex, fragment); 51 | triangle = new Mesh3D(ctx, shader.program); 52 | triangle.addVertex(new Vec3(-width * 0.5, height * 0.5, 0)); 53 | triangle.addVertex(new Vec3(height * 0.5, width * 0.5, 0)); 54 | triangle.addVertex(new Vec3(width * 0.5, -height * 0.5, 0)); 55 | 56 | triangle.addColor(new Vec4(1, 0, 0, 1)); 57 | triangle.addColor(new Vec4(0, 1, 0, 1)); 58 | triangle.addColor(new Vec4 (0, 0, 1, 1)); 59 | triangle.build(); 60 | } 61 | 62 | override public function draw(delta:Float):Void { 63 | super.draw(delta); 64 | shader.begin(); 65 | triangle.draw(); 66 | shader.end(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/ch02/FirstUniform.hx: -------------------------------------------------------------------------------- 1 | package ch02; 2 | 3 | import VectorMath.Vec4; 4 | import VectorMath.Vec3; 5 | import js.Browser; 6 | import js.html.KeyboardEvent; 7 | import types.Types.IShader; 8 | import utils.Mesh3D; 9 | import utils.BaseOfApp; 10 | import utils.Material; 11 | import types.Types.Mesh; 12 | 13 | final fragment = '#version 300 es 14 | precision highp float; 15 | 16 | out vec4 outColor; 17 | uniform vec4 fragColor; 18 | 19 | void main() 20 | { 21 | outColor = fragColor; 22 | }'; 23 | final vertex = '#version 300 es 24 | precision highp float; 25 | 26 | layout (location = 0) in vec3 position; 27 | 28 | void main() 29 | { 30 | gl_Position = vec4(position, 1.0); 31 | }'; 32 | 33 | class FirstUniform extends BaseOfApp { 34 | private var triangle:Mesh; 35 | private var shader:IShader; 36 | 37 | public function new() { 38 | super(); 39 | } 40 | 41 | override private function setup():Void { 42 | super.setup(); 43 | final width = 2; 44 | final height = 2; 45 | shader = new Material(ctx); 46 | shader.load(vertex, fragment); 47 | triangle = new Mesh3D(ctx, shader.program); 48 | triangle.addVertex(new Vec3(-width * 0.5, height * 0.5, 0)); 49 | triangle.addVertex(new Vec3(height * 0.5, width * 0.5, 0)); 50 | triangle.addVertex(new Vec3(width * 0.5, -height * 0.5, 0)); 51 | triangle.build(); 52 | } 53 | 54 | override public function draw(delta:Float):Void { 55 | super.draw(delta); 56 | shader.begin(); 57 | shader.setUniform4f("fragColor", new Vec4(1,0,1,1)); 58 | triangle.draw(); 59 | shader.end(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/ch02/RedTriangle.hx: -------------------------------------------------------------------------------- 1 | package ch02; 2 | 3 | import VectorMath.Vec3; 4 | import js.Browser; 5 | import js.html.KeyboardEvent; 6 | import types.Types.IShader; 7 | import utils.Mesh3D; 8 | import utils.BaseOfApp; 9 | import utils.Material; 10 | import types.Types.Mesh; 11 | 12 | final fragment = '#version 300 es 13 | precision highp float; 14 | 15 | out vec4 outColor; 16 | 17 | void main() 18 | { 19 | outColor = vec4(1.0,0.0,0.0,1.0); 20 | }'; 21 | final vertex = '#version 300 es 22 | precision highp float; 23 | 24 | in vec3 position; 25 | 26 | void main() 27 | { 28 | gl_Position = vec4(position, 1.0); 29 | }'; 30 | 31 | class RedTriangle extends BaseOfApp { 32 | private var triangle:Mesh; 33 | private var shader:IShader; 34 | 35 | public function new() { 36 | super(); 37 | Browser.window.addEventListener("keydown", this.onKeyPressed); 38 | } 39 | 40 | override private function setup():Void { 41 | super.setup(); 42 | final width = 2; 43 | final height = 2; 44 | shader = new Material(ctx); 45 | shader.load(vertex, fragment); 46 | triangle = new Mesh3D(ctx, shader.program); 47 | triangle.addVertex(new Vec3(-width * 0.5, height * 0.5, 0)); 48 | triangle.addVertex(new Vec3(height * 0.5, width * 0.5, 0)); 49 | triangle.addVertex(new Vec3(width * 0.5, -height * 0.5, 0)); 50 | triangle.build(); 51 | } 52 | 53 | override public function draw(delta:Float):Void { 54 | super.draw(delta); 55 | shader.begin(); 56 | triangle.draw(); 57 | shader.end(); 58 | } 59 | private function onKeyPressed(e: KeyboardEvent): Void { 60 | final curPos = triangle.getVertex(0); 61 | triangle.setVertex(0, curPos + new Vec3(0, 1, 0)); 62 | triangle.build(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/ch03/Brightness.hx: -------------------------------------------------------------------------------- 1 | package ch03; 2 | 3 | import VectorMath.log; 4 | import VectorMath.Vec2; 5 | import VectorMath.Vec4; 6 | import VectorMath.Vec3; 7 | import types.Types.IShader; 8 | import utils.Mesh3D; 9 | import utils.BaseOfApp; 10 | import utils.Material; 11 | import types.Types.Mesh; 12 | 13 | 14 | class Brightness extends BaseOfApp { 15 | private var quad:Mesh; 16 | private var shader:IShader; 17 | public function new() { 18 | super(); 19 | } 20 | 21 | override private function setup():Void { 22 | super.setup(); 23 | shader = new Material(ctx); 24 | shader.load( 25 | Webpack.require("./shaders/brightness.vert.glsl"), 26 | Webpack.require("./shaders/brightness.frag.glsl") 27 | ); 28 | shader.setUniformTexture("parrotTex", Webpack.require("../../original/ch3/Assets/parrot.png"), 0); 29 | quad = new Mesh3D(ctx, shader.program); 30 | quad.addVertex(new Vec3(-1, -1, 0)); 31 | quad.addVertex(new Vec3(-1, 1, 0)); 32 | quad.addVertex(new Vec3(1, 1, 0)); 33 | quad.addVertex(new Vec3(1, -1, 0)); 34 | 35 | quad.addColor(new Vec4(1, 0, 0, 1)); 36 | quad.addColor(new Vec4(0, 1, 0, 1)); 37 | quad.addColor(new Vec4(0, 0, 1, 1)); 38 | quad.addColor(new Vec4(1, 1, 1, 1)); 39 | 40 | quad.addTexCoord(new Vec2(0, 0)); 41 | quad.addTexCoord(new Vec2(0, 1)); 42 | quad.addTexCoord(new Vec2(1, 1)); 43 | quad.addTexCoord(new Vec2(1, 0)); 44 | 45 | quad.addIndicies([0, 1, 2, 2, 3, 0]); 46 | quad.build(); 47 | } 48 | 49 | override public function draw(delta:Float):Void { 50 | super.draw(delta); 51 | shader.begin(); 52 | shader.setUniform1f("brightness", 0.1); 53 | quad.draw(); 54 | shader.end(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/ch03/ColorMath.hx: -------------------------------------------------------------------------------- 1 | package ch03; 2 | 3 | import VectorMath.log; 4 | import VectorMath.Vec2; 5 | import VectorMath.Vec4; 6 | import VectorMath.Vec3; 7 | import types.Types.IShader; 8 | import utils.Mesh3D; 9 | import utils.BaseOfApp; 10 | import utils.Material; 11 | import types.Types.Mesh; 12 | 13 | 14 | class ColorMath extends BaseOfApp { 15 | private var quad:Mesh; 16 | private var shader:IShader; 17 | public function new() { 18 | super(); 19 | } 20 | 21 | override private function setup():Void { 22 | super.setup(); 23 | shader = new Material(ctx); 24 | shader.load( 25 | Webpack.require("./shaders/color-math.vert.glsl"), 26 | Webpack.require("./shaders/color-math.frag.glsl") 27 | ); 28 | shader.setUniformTexture("parrotTex", Webpack.require("../../original/ch3/Assets/parrot.png"), 0); 29 | quad = new Mesh3D(ctx, shader.program); 30 | quad.addVertex(new Vec3(-1, -1, 0)); 31 | quad.addVertex(new Vec3(-1, 1, 0)); 32 | quad.addVertex(new Vec3(1, 1, 0)); 33 | quad.addVertex(new Vec3(1, -1, 0)); 34 | 35 | quad.addColor(new Vec4(1, 0, 0, 1)); 36 | quad.addColor(new Vec4(0, 1, 0, 1)); 37 | quad.addColor(new Vec4(0, 0, 1, 1)); 38 | quad.addColor(new Vec4(1, 1, 1, 1)); 39 | 40 | quad.addTexCoord(new Vec2(0, 0)); 41 | quad.addTexCoord(new Vec2(0, 1)); 42 | quad.addTexCoord(new Vec2(1, 1)); 43 | quad.addTexCoord(new Vec2(1, 0)); 44 | 45 | quad.addIndicies([0, 1, 2, 2, 3, 0]); 46 | quad.build(); 47 | } 48 | 49 | override public function draw(delta:Float):Void { 50 | super.draw(delta); 51 | shader.begin(); 52 | shader.setUniform4f("multiplay", new Vec4(0.5, 0.5, 0.1, 1.0)); 53 | shader.setUniform4f("add", new Vec4(0.1, 0.1, 0.1, 0.0)); 54 | quad.draw(); 55 | shader.end(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/ch03/Parrot.hx: -------------------------------------------------------------------------------- 1 | package ch03; 2 | 3 | import VectorMath.Vec2; 4 | import VectorMath.Vec4; 5 | import VectorMath.Vec3; 6 | import types.Types.IShader; 7 | import utils.Mesh3D; 8 | import utils.BaseOfApp; 9 | import utils.Material; 10 | import types.Types.Mesh; 11 | 12 | 13 | class Parrot extends BaseOfApp { 14 | private var quad:Mesh; 15 | private var shader:IShader; 16 | 17 | public function new() { 18 | super(); 19 | } 20 | 21 | override private function setup():Void { 22 | super.setup(); 23 | shader = new Material(ctx); 24 | shader.load( 25 | Webpack.require("./shaders/parrot.vert.glsl"), 26 | Webpack.require("./shaders/parrot.frag.glsl") 27 | ); 28 | shader.setUniformTexture("parrotTex", Webpack.require("../../original/ch3/Assets/parrot.png"), 0); 29 | quad = new Mesh3D(ctx, shader.program); 30 | quad.addVertex(new Vec3(-1, -1, 0)); 31 | quad.addVertex(new Vec3(-1, 1, 0)); 32 | quad.addVertex(new Vec3(1, 1, 0)); 33 | quad.addVertex(new Vec3(1, -1, 0)); 34 | 35 | quad.addColor(new Vec4(1, 0, 0, 1)); 36 | quad.addColor(new Vec4(0, 1, 0, 1)); 37 | quad.addColor(new Vec4(0, 0, 1, 1)); 38 | quad.addColor(new Vec4(1, 1, 1, 1)); 39 | 40 | quad.addTexCoord(new Vec2(0, 0)); 41 | quad.addTexCoord(new Vec2(0, 1)); 42 | quad.addTexCoord(new Vec2(1, 1)); 43 | quad.addTexCoord(new Vec2(1, 0)); 44 | 45 | quad.addIndicies([0, 1, 2, 2, 3, 0]); 46 | 47 | quad.build(); 48 | } 49 | 50 | override public function draw(delta:Float):Void { 51 | super.draw(delta); 52 | shader.begin(); 53 | quad.draw(); 54 | shader.end(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/ch03/Quad.hx: -------------------------------------------------------------------------------- 1 | package ch03; 2 | 3 | import VectorMath.Vec2; 4 | import VectorMath.Vec4; 5 | import VectorMath.Vec3; 6 | import types.Types.IShader; 7 | import utils.Mesh3D; 8 | import utils.BaseOfApp; 9 | import utils.Material; 10 | import types.Types.Mesh; 11 | 12 | 13 | class Quad extends BaseOfApp { 14 | private var quad:Mesh; 15 | private var shader:IShader; 16 | 17 | public function new() { 18 | super(); 19 | } 20 | 21 | override private function setup():Void { 22 | super.setup(); 23 | shader = new Material(ctx); 24 | shader.load( 25 | Webpack.require("./shaders/quad.vert.glsl"), 26 | Webpack.require("./shaders/quad.frag.glsl") 27 | ); 28 | quad = new Mesh3D(ctx, shader.program); 29 | quad.addVertex(new Vec3(-1, -1, 0)); 30 | quad.addVertex(new Vec3(-1, 1, 0)); 31 | quad.addVertex(new Vec3(1, 1, 0)); 32 | quad.addVertex(new Vec3(1, -1, 0)); 33 | 34 | quad.addColor(new Vec4(1, 0, 0, 1)); 35 | quad.addColor(new Vec4(0, 1, 0, 1)); 36 | quad.addColor(new Vec4(0, 0, 1, 1)); 37 | quad.addColor(new Vec4(1, 1, 1, 1)); 38 | 39 | quad.addTexCoord(new Vec2(0, 0)); 40 | quad.addTexCoord(new Vec2(0, 1)); 41 | quad.addTexCoord(new Vec2(1, 1)); 42 | quad.addTexCoord(new Vec2(1, 0)); 43 | 44 | quad.addIndicies([0, 1, 2, 2, 3, 0]); 45 | 46 | quad.build(); 47 | } 48 | 49 | override public function draw(delta:Float):Void { 50 | super.draw(delta); 51 | shader.begin(); 52 | quad.draw(); 53 | shader.end(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/ch03/ScrollingUV.hx: -------------------------------------------------------------------------------- 1 | package ch03; 2 | 3 | import VectorMath.log; 4 | import VectorMath.Vec2; 5 | import VectorMath.Vec4; 6 | import VectorMath.Vec3; 7 | import types.Types.IShader; 8 | import utils.Mesh3D; 9 | import utils.BaseOfApp; 10 | import utils.Material; 11 | import types.Types.Mesh; 12 | 13 | 14 | class ScrollingUV extends BaseOfApp { 15 | private var quad:Mesh; 16 | private var shader:IShader; 17 | private var startTime: Float; 18 | public function new() { 19 | super(); 20 | this.startTime = 0; 21 | } 22 | 23 | override private function setup():Void { 24 | super.setup(); 25 | shader = new Material(ctx); 26 | shader.load( 27 | Webpack.require("./shaders/scrolling-uv.vert.glsl"), 28 | Webpack.require("./shaders/scrolling-uv.frag.glsl") 29 | ); 30 | shader.setUniformTexture("parrotTex", Webpack.require("../../original/ch3/Assets/parrot.png"), 0); 31 | quad = new Mesh3D(ctx, shader.program); 32 | quad.addVertex(new Vec3(-1, -1, 0)); 33 | quad.addVertex(new Vec3(-1, 1, 0)); 34 | quad.addVertex(new Vec3(1, 1, 0)); 35 | quad.addVertex(new Vec3(1, -1, 0)); 36 | 37 | quad.addColor(new Vec4(1, 0, 0, 1)); 38 | quad.addColor(new Vec4(0, 1, 0, 1)); 39 | quad.addColor(new Vec4(0, 0, 1, 1)); 40 | quad.addColor(new Vec4(1, 1, 1, 1)); 41 | 42 | quad.addTexCoord(new Vec2(0, 0)); 43 | quad.addTexCoord(new Vec2(0, 1)); 44 | quad.addTexCoord(new Vec2(1, 1)); 45 | quad.addTexCoord(new Vec2(1, 0)); 46 | 47 | quad.addIndicies([0, 1, 2, 2, 3, 0]); 48 | 49 | quad.build(); 50 | } 51 | 52 | override public function draw(delta:Float):Void { 53 | startTime += 0.01; 54 | trace(startTime); 55 | super.draw(delta); 56 | shader.begin(); 57 | shader.setUniform1f("time", startTime); 58 | quad.draw(); 59 | shader.end(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/ch03/shaders/brightness.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | out vec4 outColor; 5 | in vec2 fragUV; 6 | 7 | uniform sampler2D parrotTex; 8 | uniform float brightness; 9 | 10 | void main() { 11 | vec4 tex = texture(parrotTex, fragUV); 12 | tex.rgb *= brightness; 13 | outColor = tex; 14 | } -------------------------------------------------------------------------------- /src/ch03/shaders/brightness.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | layout (location = 0) in vec3 position; 5 | layout (location = 3) in vec2 uv; 6 | 7 | out vec2 fragUV; 8 | 9 | void main() 10 | { 11 | fragUV = uv; 12 | gl_Position = vec4(position, 1.0); 13 | } -------------------------------------------------------------------------------- /src/ch03/shaders/color-math.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | out vec4 outColor; 5 | in vec2 fragUV; 6 | 7 | uniform sampler2D parrotTex; 8 | uniform vec4 multiplay; 9 | uniform vec4 add; 10 | 11 | void main() { 12 | outColor = texture(parrotTex, fragUV) * multiplay + add; 13 | } -------------------------------------------------------------------------------- /src/ch03/shaders/color-math.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | layout (location = 0) in vec3 position; 5 | layout (location = 3) in vec2 uv; 6 | 7 | out vec2 fragUV; 8 | 9 | void main() 10 | { 11 | fragUV = uv; 12 | gl_Position = vec4(position, 1.0); 13 | } -------------------------------------------------------------------------------- /src/ch03/shaders/parrot.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | out vec4 outColor; 5 | in vec2 fragUV; 6 | 7 | uniform sampler2D parrotTex; 8 | 9 | void main() 10 | { 11 | outColor = texture(parrotTex, fragUV); 12 | } -------------------------------------------------------------------------------- /src/ch03/shaders/parrot.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | layout (location = 0) in vec3 position; 5 | layout (location = 3) in vec2 uv; 6 | 7 | out vec2 fragUV; 8 | 9 | void main() 10 | { 11 | fragUV = uv; 12 | gl_Position = vec4(position, 1.0); 13 | } -------------------------------------------------------------------------------- /src/ch03/shaders/quad.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | out vec4 outColor; 5 | in vec4 fragColor; 6 | in vec2 fragUV; 7 | 8 | void main() 9 | { 10 | outColor = vec4(fragUV, 0.0, 1.0); 11 | } -------------------------------------------------------------------------------- /src/ch03/shaders/quad.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | layout (location = 0) in vec3 position; 5 | layout (location = 1) in vec4 color; 6 | layout (location = 3) in vec2 uv; 7 | 8 | out vec4 fragColor; 9 | out vec2 fragUV; 10 | 11 | void main() 12 | { 13 | fragColor = color; 14 | fragUV = uv; 15 | gl_Position = vec4(position, 1.0); 16 | } -------------------------------------------------------------------------------- /src/ch03/shaders/scrolling-uv.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | out vec4 outColor; 5 | in vec2 fragUV; 6 | 7 | uniform sampler2D parrotTex; 8 | 9 | void main() 10 | { 11 | outColor = texture(parrotTex, fragUV); 12 | } -------------------------------------------------------------------------------- /src/ch03/shaders/scrolling-uv.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | layout (location = 0) in vec3 position; 5 | layout (location = 3) in vec2 uv; 6 | 7 | uniform float time; 8 | 9 | out vec2 fragUV; 10 | 11 | void main() 12 | { 13 | fragUV = vec2(uv.x, uv.y) + vec2(1.0, 0.0) * time; 14 | gl_Position = vec4(position, 1.0); 15 | } -------------------------------------------------------------------------------- /src/ch04/AlphaBlending.hx: -------------------------------------------------------------------------------- 1 | package ch04; 2 | 3 | import js.html.webgl.RenderingContext; 4 | import VectorMath.Vec2; 5 | import VectorMath.Vec4; 6 | import VectorMath.Vec3; 7 | import types.Types.IShader; 8 | import utils.Mesh3D; 9 | import utils.BaseOfApp; 10 | import utils.Material; 11 | import types.Types.Mesh; 12 | 13 | 14 | class AlphaBlending extends BaseOfApp { 15 | private var charMesh:Mesh; 16 | private var charShader:IShader; 17 | private var bgMesh:Mesh; 18 | private var bgShader:IShader; 19 | private var cloudMesh:Mesh; 20 | private var cloudShader:IShader; 21 | private var sunMesh:Mesh; 22 | private var sunShader:IShader; 23 | public function new() { 24 | super(); 25 | } 26 | 27 | override private function setup():Void { 28 | super.setup(); 29 | bgShader = new Material(ctx); 30 | bgShader.load( 31 | Webpack.require("./shaders/bg.vert.glsl"), 32 | Webpack.require("./shaders/bg.frag.glsl") 33 | ); 34 | bgShader.setUniformTexture("bg", Webpack.require("../../original/ch4/Assets/forest.png"), 1); 35 | charShader = new Material(ctx); 36 | charShader.load( 37 | Webpack.require("./shaders/green-man.vert.glsl"), 38 | Webpack.require("./shaders/green-man.frag.glsl") 39 | ); 40 | charShader.setUniformTexture("greenMan", Webpack.require("../../original/ch4/Assets/alien.png"), 0); 41 | cloudShader = new Material(ctx); 42 | cloudShader.load( 43 | Webpack.require("./shaders/cloud.vert.glsl"), 44 | Webpack.require("./shaders/cloud.frag.glsl") 45 | ); 46 | cloudShader.setUniformTexture("cloud", Webpack.require("../../original/ch4/Assets/cloud.png"), 2); 47 | sunShader = new Material(ctx); 48 | sunShader.load( 49 | Webpack.require("./shaders/sun.vert.glsl"), 50 | Webpack.require("./shaders/sun.frag.glsl") 51 | ); 52 | sunShader.setUniformTexture("sun", Webpack.require("../../original/ch4/Assets/sun.png"), 3); 53 | charMesh = new Mesh3D(ctx, charShader.program); 54 | buildMesh(charMesh, 0.05, 0.1, new Vec3(0, -0.345, 0)); 55 | charMesh.build(); 56 | bgMesh = new Mesh3D(ctx, bgShader.program); 57 | buildMesh(bgMesh, 1, 1, new Vec3(0, 0, 0.5)); 58 | bgMesh.build(); 59 | cloudMesh = new Mesh3D(ctx, cloudShader.program); 60 | buildMesh(cloudMesh, 0.2, 0.1, new Vec3(-0.55, 0, 0)); 61 | cloudMesh.build(); 62 | sunMesh = new Mesh3D(ctx, sunShader.program); 63 | buildMesh(sunMesh, 1, 1, new Vec3(0, 0, 0.4)); 64 | sunMesh.build(); 65 | } 66 | override public function draw(delta:Float):Void { 67 | super.draw(delta); 68 | enableDepthTest(); 69 | setBlendingMode(RenderingContext.SRC_ALPHA, RenderingContext.ONE_MINUS_SRC_ALPHA); 70 | charShader.begin(); 71 | charMesh.draw(); 72 | charShader.end(); 73 | bgShader.begin(); 74 | bgMesh.draw(); 75 | bgShader.end(); 76 | setBlendingMode(RenderingContext.ONE, RenderingContext.ONE); 77 | sunShader.begin(); 78 | sunMesh.draw(); 79 | sunShader.end(); 80 | setBlendingMode(RenderingContext.SRC_ALPHA, RenderingContext.ONE_MINUS_SRC_ALPHA); 81 | disableDepthTest(); 82 | cloudShader.begin(); 83 | cloudMesh.draw(); 84 | cloudShader.end(); 85 | } 86 | private function buildMesh(mesh: Mesh, width: Float, height: Float, position: Vec3): Void { 87 | final verts: Array = [ 88 | -width + position.x, -height + position.y, position.z, 89 | -width + position.x, height + position.y, position.z, 90 | width + position.x, height + position.y, position.z, 91 | width + position.x, -height + position.y, position.z 92 | ]; 93 | final uv: Array = [ 94 | 0, 0, 95 | 0, 1, 96 | 1, 1, 97 | 1, 0 98 | ]; 99 | 100 | for(i in 0...4) { 101 | final idx = i * 3; 102 | final uvIdx = i * 2; 103 | 104 | mesh.addVertex(new Vec3(verts[idx], verts[idx + 1], verts[idx + 2])); 105 | mesh.addTexCoord(new Vec2(uv[uvIdx], uv[uvIdx + 1])); 106 | } 107 | mesh.addIndicies([ 108 | 0, 1, 2, 2, 3, 0 109 | ]); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/ch04/DepthTest.hx: -------------------------------------------------------------------------------- 1 | package ch04; 2 | 3 | import VectorMath.Vec2; 4 | import VectorMath.Vec4; 5 | import VectorMath.Vec3; 6 | import types.Types.IShader; 7 | import utils.Mesh3D; 8 | import utils.BaseOfApp; 9 | import utils.Material; 10 | import types.Types.Mesh; 11 | 12 | 13 | class DepthTest extends BaseOfApp { 14 | private var charMesh:Mesh; 15 | private var charShader:IShader; 16 | private var bgMesh:Mesh; 17 | private var bgShader:IShader; 18 | public function new() { 19 | super(); 20 | } 21 | 22 | override private function setup():Void { 23 | super.setup(); 24 | bgShader = new Material(ctx); 25 | bgShader.load( 26 | Webpack.require("./shaders/bg.vert.glsl"), 27 | Webpack.require("./shaders/bg.frag.glsl") 28 | ); 29 | bgShader.setUniformTexture("bg", Webpack.require("../../original/ch4/Assets/forest.png"), 1); 30 | charShader = new Material(ctx); 31 | charShader.load( 32 | Webpack.require("./shaders/green-man.vert.glsl"), 33 | Webpack.require("./shaders/green-man.frag.glsl") 34 | ); 35 | charShader.setUniformTexture("greenMan", Webpack.require("../../original/ch4/Assets/alien.png"), 0); 36 | charMesh = new Mesh3D(ctx, charShader.program); 37 | buildMesh(charMesh, 0.05, 0.1, new Vec3(0, 0.15, 0)); 38 | charMesh.build(); 39 | bgMesh = new Mesh3D(ctx, bgShader.program); 40 | buildMesh(bgMesh, 1, 1, new Vec3(0, 0, 0.5)); 41 | bgMesh.build(); 42 | } 43 | override public function draw(delta:Float):Void { 44 | super.draw(delta); 45 | charShader.begin(); 46 | charMesh.draw(); 47 | charShader.end(); 48 | bgShader.begin(); 49 | bgMesh.draw(); 50 | bgShader.end(); 51 | } 52 | private function buildMesh(mesh: Mesh, width: Float, height: Float, position: Vec3): Void { 53 | final verts: Array = [ 54 | -width + position.x, -height + position.y, position.z, 55 | -width + position.x, height + position.y, position.z, 56 | width + position.x, height + position.y, position.z, 57 | width + position.x, -height + position.y, position.z 58 | ]; 59 | final uv: Array = [ 60 | 0, 0, 61 | 0, 1, 62 | 1, 1, 63 | 1, 0 64 | ]; 65 | 66 | for(i in 0...4) { 67 | final idx = i * 3; 68 | final uvIdx = i * 2; 69 | 70 | mesh.addVertex(new Vec3(verts[idx], verts[idx + 1], verts[idx + 2])); 71 | mesh.addTexCoord(new Vec2(uv[uvIdx], uv[uvIdx + 1])); 72 | } 73 | mesh.addIndicies([ 74 | 0, 1, 2, 2, 3, 0 75 | ]); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/ch04/GreenMan.hx: -------------------------------------------------------------------------------- 1 | package ch04; 2 | 3 | import VectorMath.Vec2; 4 | import VectorMath.Vec4; 5 | import VectorMath.Vec3; 6 | import types.Types.IShader; 7 | import utils.Mesh3D; 8 | import utils.BaseOfApp; 9 | import utils.Material; 10 | import types.Types.Mesh; 11 | 12 | 13 | class GreenMan extends BaseOfApp { 14 | private var charMesh:Mesh; 15 | private var shader:IShader; 16 | 17 | public function new() { 18 | super(); 19 | } 20 | 21 | override private function setup():Void { 22 | super.setup(); 23 | shader = new Material(ctx); 24 | shader.load( 25 | Webpack.require("./shaders/green-man.vert.glsl"), 26 | Webpack.require("./shaders/green-man.frag.glsl") 27 | ); 28 | shader.setUniformTexture("greenMan", Webpack.require("../../original/ch4/Assets/alien.png"), 0); 29 | charMesh = new Mesh3D(ctx, shader.program); 30 | buildMesh(charMesh, 0.25, 0.5, new Vec3(0, 0.15, 0)); 31 | charMesh.build(); 32 | } 33 | override public function draw(delta:Float):Void { 34 | super.draw(delta); 35 | shader.begin(); 36 | charMesh.draw(); 37 | shader.end(); 38 | } 39 | private function buildMesh(mesh: Mesh, width: Float, heigh: Float, position: Vec3): Void { 40 | final verts: Array = [ 41 | -width + position.x, -heigh + position.y, position.z, 42 | -width + position.x, heigh + position.y, position.z, 43 | width + position.x, heigh + position.y, position.z, 44 | width + position.x, -heigh + position.y, position.z 45 | ]; 46 | final uv: Array = [ 47 | 0, 0, 0, 48 | 1, 1, 1, 49 | 1, 1, 0 50 | ]; 51 | 52 | final inidicies: Array = [ 53 | 0, 1, 2, 2, 3, 0 54 | ]; 55 | 56 | for(i in 0...4) { 57 | final idx = i * 3; 58 | final uvIdx = i * 2; 59 | 60 | mesh.addVertex(new Vec3(verts[idx], verts[idx + 1], verts[idx +2])); 61 | mesh.addTexCoord(new Vec2(uv[uvIdx], uv[uvIdx + 2])); 62 | } 63 | mesh.addIndicies(inidicies); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/ch04/SpriteSheet.hx: -------------------------------------------------------------------------------- 1 | package ch04; 2 | 3 | import js.html.webgl.RenderingContext; 4 | import VectorMath.Vec2; 5 | import VectorMath.Vec4; 6 | import VectorMath.Vec3; 7 | import types.Types.IShader; 8 | import utils.Mesh3D; 9 | import utils.BaseOfApp; 10 | import utils.Material; 11 | import types.Types.Mesh; 12 | 13 | 14 | class SpriteSheet extends BaseOfApp { 15 | private var charMesh:Mesh; 16 | private var charShader:IShader; 17 | private var bgMesh:Mesh; 18 | private var bgShader:IShader; 19 | private var cloudMesh:Mesh; 20 | private var cloudShader:IShader; 21 | private var sunMesh:Mesh; 22 | private var sunShader:IShader; 23 | private var frame: Float = 0.0; 24 | public function new() { 25 | super(); 26 | } 27 | 28 | override private function setup():Void { 29 | super.setup(); 30 | bgShader = new Material(ctx); 31 | bgShader.load( 32 | Webpack.require("./shaders/bg.vert.glsl"), 33 | Webpack.require("./shaders/bg.frag.glsl") 34 | ); 35 | bgShader.setUniformTexture("bg", Webpack.require("../../original/ch4/Assets/forest.png"), 1); 36 | charShader = new Material(ctx); 37 | charShader.load( 38 | Webpack.require("./shaders/spriteSheet.vert.glsl"), 39 | Webpack.require("./shaders/green-man.frag.glsl") 40 | ); 41 | charShader.setUniformTexture("greenMan", Webpack.require("../../original/ch4/5_SpritesheetAnimation/bin/data/walk_sheet.png"), 0, 0); 42 | cloudShader = new Material(ctx); 43 | cloudShader.load( 44 | Webpack.require("./shaders/cloud.vert.glsl"), 45 | Webpack.require("./shaders/cloud.frag.glsl") 46 | ); 47 | cloudShader.setUniformTexture("cloud", Webpack.require("../../original/ch4/Assets/cloud.png"), 2); 48 | sunShader = new Material(ctx); 49 | sunShader.load( 50 | Webpack.require("./shaders/sun.vert.glsl"), 51 | Webpack.require("./shaders/sun.frag.glsl") 52 | ); 53 | sunShader.setUniformTexture("sun", Webpack.require("../../original/ch4/Assets/sun.png"), 3); 54 | charMesh = new Mesh3D(ctx, charShader.program); 55 | buildMesh(charMesh, 0.05, 0.1, new Vec3(0, -0.345, 0)); 56 | charMesh.build(); 57 | bgMesh = new Mesh3D(ctx, bgShader.program); 58 | buildMesh(bgMesh, 1, 1, new Vec3(0, 0, 0.5)); 59 | bgMesh.build(); 60 | cloudMesh = new Mesh3D(ctx, cloudShader.program); 61 | buildMesh(cloudMesh, 0.2, 0.1, new Vec3(-0.55, 0, 0)); 62 | cloudMesh.build(); 63 | sunMesh = new Mesh3D(ctx, sunShader.program); 64 | buildMesh(sunMesh, 1, 1, new Vec3(0, 0, 0.4)); 65 | sunMesh.build(); 66 | } 67 | override public function draw(delta:Float):Void { 68 | frame = (frame > 10) ? 0.0 : frame += 0.2; 69 | super.draw(delta); 70 | enableDepthTest(); 71 | setBlendingMode(RenderingContext.SRC_ALPHA, RenderingContext.ONE_MINUS_SRC_ALPHA); 72 | charShader.begin(); 73 | charShader.setUniform2f("size", new Vec2(0.28, 0.19)); 74 | charShader.setUniform2f("frame", new Vec2(Std.int(frame % 3), Std.int(frame / 3))); 75 | charMesh.draw(); 76 | charShader.end(); 77 | bgShader.begin(); 78 | bgMesh.draw(); 79 | bgShader.end(); 80 | setBlendingMode(RenderingContext.ONE, RenderingContext.ONE); 81 | sunShader.begin(); 82 | sunMesh.draw(); 83 | sunShader.end(); 84 | setBlendingMode(RenderingContext.SRC_ALPHA, RenderingContext.ONE_MINUS_SRC_ALPHA); 85 | disableDepthTest(); 86 | cloudShader.begin(); 87 | cloudMesh.draw(); 88 | cloudShader.end(); 89 | } 90 | private function buildMesh(mesh: Mesh, width: Float, height: Float, position: Vec3): Void { 91 | final verts: Array = [ 92 | -width + position.x, -height + position.y, position.z, 93 | -width + position.x, height + position.y, position.z, 94 | width + position.x, height + position.y, position.z, 95 | width + position.x, -height + position.y, position.z 96 | ]; 97 | final uv: Array = [ 98 | 0, 0, 99 | 0, 1, 100 | 1, 1, 101 | 1, 0 102 | ]; 103 | 104 | for(i in 0...4) { 105 | final idx = i * 3; 106 | final uvIdx = i * 2; 107 | 108 | mesh.addVertex(new Vec3(verts[idx], verts[idx + 1], verts[idx + 2])); 109 | mesh.addTexCoord(new Vec2(uv[uvIdx], uv[uvIdx + 1])); 110 | } 111 | mesh.addIndicies([ 112 | 0, 1, 2, 2, 3, 0 113 | ]); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/ch04/shaders/bg.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | out vec4 outColor; 5 | in vec2 fragUV; 6 | 7 | uniform sampler2D bg; 8 | 9 | void main() { 10 | vec4 tex = texture(bg, fragUV); 11 | outColor = tex; 12 | } -------------------------------------------------------------------------------- /src/ch04/shaders/bg.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | layout (location = 0) in vec3 position; 5 | layout (location = 3) in vec2 uv; 6 | 7 | out vec2 fragUV; 8 | 9 | void main() 10 | { 11 | fragUV = uv; 12 | gl_Position = vec4(position, 1.0); 13 | } -------------------------------------------------------------------------------- /src/ch04/shaders/cloud.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | out vec4 outColor; 5 | in vec2 fragUV; 6 | 7 | uniform sampler2D cloud; 8 | 9 | void main() { 10 | outColor = texture(cloud, fragUV); 11 | outColor.a = min(outColor.a, 0.8); 12 | } -------------------------------------------------------------------------------- /src/ch04/shaders/cloud.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | layout (location = 0) in vec3 position; 5 | layout (location = 3) in vec2 uv; 6 | 7 | out vec2 fragUV; 8 | 9 | void main() 10 | { 11 | fragUV = uv; 12 | gl_Position = vec4(position, 1.0); 13 | } -------------------------------------------------------------------------------- /src/ch04/shaders/green-man.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | out vec4 outColor; 5 | in vec2 fragUV; 6 | 7 | uniform sampler2D greenMan; 8 | 9 | void main() { 10 | vec4 tex = texture(greenMan, fragUV); 11 | outColor = tex; 12 | 13 | if (outColor.a < 1.0) { 14 | discard; 15 | } 16 | } -------------------------------------------------------------------------------- /src/ch04/shaders/green-man.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | layout (location = 0) in vec3 position; 5 | layout (location = 3) in vec2 uv; 6 | 7 | out vec2 fragUV; 8 | 9 | void main() 10 | { 11 | fragUV = uv; 12 | gl_Position = vec4(position, 1.0); 13 | } -------------------------------------------------------------------------------- /src/ch04/shaders/spriteSheet.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | layout (location = 0) in vec3 position; 5 | layout (location = 3) in vec2 uv; 6 | 7 | out vec2 fragUV; 8 | 9 | uniform vec2 size; 10 | uniform vec2 frame; 11 | 12 | void main() 13 | { 14 | fragUV = vec2(uv.x, 1.0 - uv.y) * size + (frame * size); 15 | gl_Position = vec4(position, 1.0); 16 | } -------------------------------------------------------------------------------- /src/ch04/shaders/sun.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | out vec4 outColor; 5 | in vec2 fragUV; 6 | 7 | uniform sampler2D sun; 8 | 9 | void main() { 10 | outColor = texture(sun, fragUV); 11 | outColor.a = min(outColor.a, 0.8); 12 | } -------------------------------------------------------------------------------- /src/ch04/shaders/sun.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | layout (location = 0) in vec3 position; 5 | layout (location = 3) in vec2 uv; 6 | 7 | out vec2 fragUV; 8 | 9 | void main() 10 | { 11 | fragUV = uv; 12 | gl_Position = vec4(position, 1.0); 13 | } -------------------------------------------------------------------------------- /src/ch05/WalkingMan.hx: -------------------------------------------------------------------------------- 1 | package ch05; 2 | 3 | import VectorMath.Mat4; 4 | import js.lib.Float32Array; 5 | import utils.Transformation.scale; 6 | import utils.Transformation.rotate; 7 | import utils.Transformation.translate; 8 | import VectorMath.log; 9 | import js.html.KeyboardEvent; 10 | import js.Browser; 11 | import js.html.webgl.RenderingContext; 12 | import VectorMath.Vec2; 13 | import VectorMath.Vec4; 14 | import VectorMath.Vec3; 15 | import types.Types.IShader; 16 | import utils.Mesh3D; 17 | import utils.BaseOfApp; 18 | import utils.Material; 19 | import types.Types.Mesh; 20 | 21 | 22 | class WalkingMan extends BaseOfApp { 23 | private var charMesh:Mesh; 24 | private var charShader:IShader; 25 | private var bgMesh:Mesh; 26 | private var bgShader:IShader; 27 | private var cloudMesh:Mesh; 28 | private var cloudShader:IShader; 29 | private var sunMesh:Mesh; 30 | private var sunShader:IShader; 31 | private var frame: Float = 0.0; 32 | private var walkRight: Bool; 33 | private var charPos: Vec3; 34 | public function new() { 35 | super(); 36 | charPos = new Vec3(0, 0, 0); 37 | Browser.window.addEventListener("keydown", onPress); 38 | Browser.window.addEventListener("keyup", onRelease); 39 | } 40 | 41 | override private function setup():Void { 42 | super.setup(); 43 | bgShader = new Material(ctx); 44 | bgShader.load( 45 | Webpack.require("./shaders/bg.vert.glsl"), 46 | Webpack.require("./shaders/bg.frag.glsl") 47 | ); 48 | bgShader.setUniformTexture("bg", Webpack.require("../../original/ch5/Assets/forest.png"), 1); 49 | charShader = new Material(ctx); 50 | charShader.load( 51 | Webpack.require("./shaders/spriteSheet.vert.glsl"), 52 | Webpack.require("./shaders/green-man.frag.glsl") 53 | ); 54 | charShader.setUniformTexture("greenMan", Webpack.require("../../original/ch5/1_WalkingCharacter/bin/data/walk_sheet.png"), 0, 0); 55 | cloudShader = new Material(ctx); 56 | cloudShader.load( 57 | Webpack.require("./shaders/cloud.vert.glsl"), 58 | Webpack.require("./shaders/cloud.frag.glsl") 59 | ); 60 | cloudShader.setUniformTexture("cloud", Webpack.require("../../original/ch5/Assets/cloud.png"), 2); 61 | sunShader = new Material(ctx); 62 | sunShader.load( 63 | Webpack.require("./shaders/sun.vert.glsl"), 64 | Webpack.require("./shaders/sun.frag.glsl") 65 | ); 66 | sunShader.setUniformTexture("sun", Webpack.require("../../original/ch5/Assets/sun.png"), 3); 67 | charMesh = new Mesh3D(ctx, charShader.program); 68 | buildMesh(charMesh, 0.05, 0.1, new Vec3(0, -0.345, 0)); 69 | charMesh.build(); 70 | bgMesh = new Mesh3D(ctx, bgShader.program); 71 | buildMesh(bgMesh, 1, 1, new Vec3(0, 0, 0.5)); 72 | bgMesh.build(); 73 | cloudMesh = new Mesh3D(ctx, cloudShader.program); 74 | buildMesh(cloudMesh, 0.2, 0.1, new Vec3(0, 0, 0)); 75 | cloudMesh.build(); 76 | sunMesh = new Mesh3D(ctx, sunShader.program); 77 | buildMesh(sunMesh, 1, 1, new Vec3(0, 0, 0.4)); 78 | sunMesh.build(); 79 | } 80 | override public function draw(delta:Float):Void { 81 | if (walkRight) { 82 | charPos += new Vec3(0.0004 * delta, 0, 0); 83 | frame = (frame > 10) ? 0.0 : frame += 0.2; 84 | } else { 85 | frame = 0.0; 86 | } 87 | super.draw(delta); 88 | enableDepthTest(); 89 | setBlendingMode(RenderingContext.SRC_ALPHA, RenderingContext.ONE_MINUS_SRC_ALPHA); 90 | charShader.begin(); 91 | charShader.setUniform3f("positionOffset", charPos); 92 | charShader.setUniform2f("size", new Vec2(0.28, 0.19)); 93 | charShader.setUniform2f("frame", new Vec2(Std.int(frame % 3), Std.int(frame / 3))); 94 | charMesh.draw(); 95 | charShader.end(); 96 | bgShader.begin(); 97 | bgMesh.draw(); 98 | bgShader.end(); 99 | setBlendingMode(RenderingContext.ONE, RenderingContext.ONE); 100 | sunShader.begin(); 101 | sunMesh.draw(); 102 | sunShader.end(); 103 | setBlendingMode(RenderingContext.SRC_ALPHA, RenderingContext.ONE_MINUS_SRC_ALPHA); 104 | disableDepthTest(); 105 | cloudShader.begin(); 106 | cloudShader.setUniformMatrix4f("transform", buildMatrix(new Vec3(-0.55, 0, 0), 0, new Vec3(1, 1, 1))); 107 | cloudMesh.draw(); 108 | cloudShader.end(); 109 | } 110 | private function buildMesh(mesh: Mesh, width: Float, height: Float, position: Vec3): Void { 111 | final verts: Array = [ 112 | -width + position.x, -height + position.y, position.z, 113 | -width + position.x, height + position.y, position.z, 114 | width + position.x, height + position.y, position.z, 115 | width + position.x, -height + position.y, position.z 116 | ]; 117 | final uv: Array = [ 118 | 0, 0, 119 | 0, 1, 120 | 1, 1, 121 | 1, 0 122 | ]; 123 | 124 | for(i in 0...4) { 125 | final idx = i * 3; 126 | final uvIdx = i * 2; 127 | 128 | mesh.addVertex(new Vec3(verts[idx], verts[idx + 1], verts[idx + 2])); 129 | mesh.addTexCoord(new Vec2(uv[uvIdx], uv[uvIdx + 1])); 130 | } 131 | mesh.addIndicies([ 132 | 0, 1, 2, 2, 3, 0 133 | ]); 134 | } 135 | private function onPress(e: KeyboardEvent) { 136 | if (e.code == "ArrowRight") { 137 | walkRight = true; 138 | } 139 | } 140 | private function onRelease(e: KeyboardEvent) { 141 | if (e.code == "ArrowRight") { 142 | walkRight = false; 143 | } 144 | } 145 | private function buildMatrix(trans: Vec3, rot: Float, scaling: Vec3): Mat4 { 146 | return translate(trans) * rotate(rot, new Vec3(0, 0, 1)) * scale(scaling); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/ch05/shaders/bg.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | out vec4 outColor; 5 | in vec2 fragUV; 6 | 7 | uniform sampler2D bg; 8 | 9 | void main() { 10 | vec4 tex = texture(bg, fragUV); 11 | outColor = tex; 12 | } -------------------------------------------------------------------------------- /src/ch05/shaders/bg.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | layout (location = 0) in vec3 position; 5 | layout (location = 3) in vec2 uv; 6 | 7 | out vec2 fragUV; 8 | 9 | void main() 10 | { 11 | fragUV = uv; 12 | gl_Position = vec4(position, 1.0); 13 | } -------------------------------------------------------------------------------- /src/ch05/shaders/cloud.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | out vec4 outColor; 5 | in vec2 fragUV; 6 | 7 | uniform sampler2D cloud; 8 | 9 | void main() { 10 | outColor = texture(cloud, fragUV); 11 | outColor.a = min(outColor.a, 0.8); 12 | } -------------------------------------------------------------------------------- /src/ch05/shaders/cloud.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | layout (location = 0) in vec3 position; 5 | layout (location = 3) in vec2 uv; 6 | 7 | uniform mat4 transform; 8 | 9 | out vec2 fragUV; 10 | 11 | void main() 12 | { 13 | fragUV = uv; 14 | gl_Position = transform * vec4(position, 1.0); 15 | } -------------------------------------------------------------------------------- /src/ch05/shaders/green-man.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | out vec4 outColor; 5 | in vec2 fragUV; 6 | 7 | uniform sampler2D greenMan; 8 | 9 | void main() { 10 | vec4 tex = texture(greenMan, fragUV); 11 | outColor = tex; 12 | 13 | if (outColor.a < 1.0) { 14 | discard; 15 | } 16 | } -------------------------------------------------------------------------------- /src/ch05/shaders/spriteSheet.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | layout (location = 0) in vec3 position; 5 | layout (location = 3) in vec2 uv; 6 | 7 | out vec2 fragUV; 8 | 9 | uniform vec2 size; 10 | uniform vec2 frame; 11 | uniform vec3 positionOffset; 12 | 13 | void main() 14 | { 15 | fragUV = vec2(uv.x, 1.0 - uv.y) * size + (frame * size); 16 | gl_Position = vec4(position + positionOffset, 1.0); 17 | } -------------------------------------------------------------------------------- /src/ch05/shaders/sun.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | out vec4 outColor; 5 | in vec2 fragUV; 6 | 7 | uniform sampler2D sun; 8 | 9 | void main() { 10 | outColor = texture(sun, fragUV); 11 | outColor.a = min(outColor.a, 0.8); 12 | } -------------------------------------------------------------------------------- /src/ch05/shaders/sun.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | layout (location = 0) in vec3 position; 5 | layout (location = 3) in vec2 uv; 6 | 7 | out vec2 fragUV; 8 | 9 | void main() 10 | { 11 | fragUV = uv; 12 | gl_Position = vec4(position, 1.0); 13 | } -------------------------------------------------------------------------------- /src/ch06/Cameras.hx: -------------------------------------------------------------------------------- 1 | package ch06; 2 | 3 | import utils.ViewMatrix.buildViewMatrix; 4 | import utils.Camera; 5 | import types.Types.Camera as ICamera; 6 | import js.lib.Float32Array; 7 | import utils.Transformation.scale; 8 | import utils.Transformation.rotate; 9 | import utils.Transformation.translate; 10 | import js.html.KeyboardEvent; 11 | import js.Browser; 12 | import js.html.webgl.RenderingContext; 13 | import VectorMath.Vec2; 14 | import VectorMath.Vec3; 15 | import types.Types.IShader; 16 | import utils.Mesh3D; 17 | import utils.BaseOfApp; 18 | import utils.Material; 19 | import types.Types.Mesh; 20 | 21 | 22 | class Cameras extends BaseOfApp { 23 | private var camera: ICamera; 24 | private var charMesh:Mesh; 25 | private var charShader:IShader; 26 | private var bgMesh:Mesh; 27 | private var bgShader:IShader; 28 | private var cloudMesh:Mesh; 29 | private var cloudShader:IShader; 30 | private var sunMesh:Mesh; 31 | private var sunShader:IShader; 32 | private var frame: Float = 0.0; 33 | private var walkRight: Bool; 34 | private var charPos: Vec3; 35 | public function new() { 36 | super(); 37 | charPos = new Vec3(0, 0, 0); 38 | camera = new Camera(new Vec3(1, 1, 1), 0.0); 39 | Browser.window.addEventListener("keydown", onPress); 40 | Browser.window.addEventListener("keyup", onRelease); 41 | } 42 | 43 | override private function setup():Void { 44 | super.setup(); 45 | bgShader = new Material(ctx); 46 | bgShader.load( 47 | Webpack.require("./shaders/bg.vert.glsl"), 48 | Webpack.require("./shaders/bg.frag.glsl") 49 | ); 50 | bgShader.setUniformTexture("bg", Webpack.require("../../original/ch6/Assets/forest.png"), 1); 51 | charShader = new Material(ctx); 52 | charShader.load( 53 | Webpack.require("./shaders/spriteSheet.vert.glsl"), 54 | Webpack.require("./shaders/green-man.frag.glsl") 55 | ); 56 | charShader.setUniformTexture("greenMan", Webpack.require("../../original/ch6/Assets/walk_sheet.png"), 0, 0); 57 | cloudShader = new Material(ctx); 58 | cloudShader.load( 59 | Webpack.require("./shaders/cloud.vert.glsl"), 60 | Webpack.require("./shaders/cloud.frag.glsl") 61 | ); 62 | cloudShader.setUniformTexture("cloud", Webpack.require("../../original/ch6/Assets/cloud.png"), 2); 63 | sunShader = new Material(ctx); 64 | sunShader.load( 65 | Webpack.require("./shaders/sun.vert.glsl"), 66 | Webpack.require("./shaders/sun.frag.glsl") 67 | ); 68 | sunShader.setUniformTexture("sun", Webpack.require("../../original/ch6/Assets/sun.png"), 3); 69 | charMesh = new Mesh3D(ctx, charShader.program); 70 | buildMesh(charMesh, 0.05, 0.1, new Vec3(0, -0.345, 0)); 71 | charMesh.build(); 72 | bgMesh = new Mesh3D(ctx, bgShader.program); 73 | buildMesh(bgMesh, 1, 1, new Vec3(0, 0, 0.5)); 74 | bgMesh.build(); 75 | cloudMesh = new Mesh3D(ctx, cloudShader.program); 76 | buildMesh(cloudMesh, 0.2, 0.1, new Vec3(0, 0, 0)); 77 | cloudMesh.build(); 78 | sunMesh = new Mesh3D(ctx, sunShader.program); 79 | buildMesh(sunMesh, 1, 1, new Vec3(0, 0, 0.4)); 80 | sunMesh.build(); 81 | } 82 | override public function draw(delta:Float):Void { 83 | if (walkRight) { 84 | charPos += new Vec3(0.0004 * delta, 0, 0); 85 | frame = (frame > 10) ? 0.0 : frame += 0.2; 86 | } else { 87 | frame = 0.0; 88 | } 89 | super.draw(delta); 90 | final view = buildViewMatrix(camera); 91 | enableDepthTest(); 92 | setBlendingMode(RenderingContext.SRC_ALPHA, RenderingContext.ONE_MINUS_SRC_ALPHA); 93 | charShader.begin(); 94 | charShader.setUniformMatrix4f("view", view); 95 | charShader.setUniformMatrix4f("model", translate(charPos)); 96 | charShader.setUniform2f("size", new Vec2(0.28, 0.19)); 97 | charShader.setUniform2f("frame", new Vec2(Std.int(frame % 3), Std.int(frame / 3))); 98 | charMesh.draw(); 99 | charShader.end(); 100 | bgShader.begin(); 101 | bgShader.setUniformMatrix4f("view", view); 102 | bgShader.setUniformMatrix4f("model", translate(new Vec3(0, 0, 0))); 103 | bgMesh.draw(); 104 | bgShader.end(); 105 | setBlendingMode(RenderingContext.ONE, RenderingContext.ONE); 106 | sunShader.begin(); 107 | sunShader.setUniformMatrix4f("view", view); 108 | sunShader.setUniformMatrix4f("model", translate(new Vec3(0, 0, 0))); 109 | sunMesh.draw(); 110 | sunShader.end(); 111 | setBlendingMode(RenderingContext.SRC_ALPHA, RenderingContext.ONE_MINUS_SRC_ALPHA); 112 | disableDepthTest(); 113 | cloudShader.begin(); 114 | cloudShader.setUniformMatrix4f("view", view); 115 | cloudShader.setUniformMatrix4f("model", translate(new Vec3(0, 0, 0))); 116 | cloudMesh.draw(); 117 | cloudShader.end(); 118 | } 119 | private function buildMesh(mesh: Mesh, width: Float, height: Float, position: Vec3): Void { 120 | final verts: Array = [ 121 | -width + position.x, -height + position.y, position.z, 122 | -width + position.x, height + position.y, position.z, 123 | width + position.x, height + position.y, position.z, 124 | width + position.x, -height + position.y, position.z 125 | ]; 126 | final uv: Array = [ 127 | 0, 0, 128 | 0, 1, 129 | 1, 1, 130 | 1, 0 131 | ]; 132 | 133 | for(i in 0...4) { 134 | final idx = i * 3; 135 | final uvIdx = i * 2; 136 | 137 | mesh.addVertex(new Vec3(verts[idx], verts[idx + 1], verts[idx + 2])); 138 | mesh.addTexCoord(new Vec2(uv[uvIdx], uv[uvIdx + 1])); 139 | } 140 | mesh.addIndicies([ 141 | 0, 1, 2, 2, 3, 0 142 | ]); 143 | } 144 | private function onPress(e: KeyboardEvent) { 145 | if (e.code == "ArrowRight") { 146 | walkRight = true; 147 | } 148 | } 149 | private function onRelease(e: KeyboardEvent) { 150 | if (e.code == "ArrowRight") { 151 | walkRight = false; 152 | } 153 | } 154 | private function buildMatrix(trans: Vec3, rot: Float, scaling: Vec3): Float32Array { 155 | final m = translate(trans) * rotate(rot, new Vec3(0, 0, 1)) * scale(scaling); 156 | final result = new Float32Array(16); 157 | result[0] = m[0].x; 158 | result[1] = m[0].y; 159 | result[2] = m[0].z; 160 | result[3] = m[0].w; 161 | 162 | result[4] = m[1].x; 163 | result[5] = m[1].y; 164 | result[6] = m[1].z; 165 | result[7] = m[1].w; 166 | 167 | result[8] = m[2].x; 168 | result[9] = m[2].y; 169 | result[10] = m[2].z; 170 | result[11] = m[2].w; 171 | 172 | result[12] = m[3].x; 173 | result[13] = m[3].y; 174 | result[14] = m[3].z; 175 | result[15] = m[3].w; 176 | return result; 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /src/ch06/shaders/bg.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | out vec4 outColor; 5 | in vec2 fragUV; 6 | 7 | uniform sampler2D bg; 8 | 9 | void main() { 10 | vec4 tex = texture(bg, fragUV); 11 | outColor = tex; 12 | } -------------------------------------------------------------------------------- /src/ch06/shaders/bg.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | layout (location = 0) in vec3 position; 5 | layout (location = 3) in vec2 uv; 6 | 7 | uniform mat4 model; 8 | uniform mat4 view; 9 | 10 | out vec2 fragUV; 11 | 12 | void main() 13 | { 14 | fragUV = uv; 15 | gl_Position = view * model * vec4(position, 1.0); 16 | } -------------------------------------------------------------------------------- /src/ch06/shaders/cloud.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | out vec4 outColor; 5 | in vec2 fragUV; 6 | 7 | uniform sampler2D cloud; 8 | 9 | void main() { 10 | outColor = texture(cloud, fragUV); 11 | outColor.a = min(outColor.a, 0.8); 12 | } -------------------------------------------------------------------------------- /src/ch06/shaders/cloud.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | layout (location = 0) in vec3 position; 5 | layout (location = 3) in vec2 uv; 6 | 7 | uniform mat4 model; 8 | uniform mat4 view; 9 | 10 | out vec2 fragUV; 11 | 12 | void main() 13 | { 14 | fragUV = uv; 15 | gl_Position = view * model * vec4(position, 1.0); 16 | } -------------------------------------------------------------------------------- /src/ch06/shaders/green-man.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | out vec4 outColor; 5 | in vec2 fragUV; 6 | 7 | uniform sampler2D greenMan; 8 | 9 | void main() { 10 | vec4 tex = texture(greenMan, fragUV); 11 | outColor = tex; 12 | 13 | if (outColor.a < 1.0) { 14 | discard; 15 | } 16 | } -------------------------------------------------------------------------------- /src/ch06/shaders/spriteSheet.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | layout (location = 0) in vec3 position; 5 | layout (location = 3) in vec2 uv; 6 | 7 | out vec2 fragUV; 8 | 9 | uniform vec2 size; 10 | uniform vec2 frame; 11 | uniform vec3 positionOffset; 12 | 13 | uniform mat4 model; 14 | uniform mat4 view; 15 | 16 | void main() 17 | { 18 | fragUV = vec2(uv.x, 1.0 - uv.y) * size + (frame * size); 19 | gl_Position = view * model * vec4(position, 1.0); 20 | } -------------------------------------------------------------------------------- /src/ch06/shaders/sun.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | out vec4 outColor; 5 | in vec2 fragUV; 6 | 7 | uniform sampler2D sun; 8 | 9 | void main() { 10 | outColor = texture(sun, fragUV); 11 | outColor.a = min(outColor.a, 0.8); 12 | } -------------------------------------------------------------------------------- /src/ch06/shaders/sun.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | layout (location = 0) in vec3 position; 5 | layout (location = 3) in vec2 uv; 6 | 7 | out vec2 fragUV; 8 | 9 | uniform mat4 model; 10 | uniform mat4 view; 11 | 12 | void main() 13 | { 14 | fragUV = uv; 15 | gl_Position = view * model * vec4(position, 1.0); 16 | } -------------------------------------------------------------------------------- /src/ch07/PerspectiveTorus.hx: -------------------------------------------------------------------------------- 1 | package ch07; 2 | 3 | import externs.Ogl.Program; 4 | import externs.Ogl.Mesh; 5 | import externs.Ogl.Geometry; 6 | import utils.OglBase; 7 | import externs.Ply.Loader; 8 | import externs.Ply.PLYLoader; 9 | import js.Browser; 10 | 11 | class PerspectiveTorus extends OglBase { 12 | private var program: Program; 13 | private var mesh: Mesh; 14 | public function new() { 15 | super(); 16 | } 17 | 18 | override private function setup():Void { 19 | super.setup(); 20 | Loader.load( 21 | Webpack.require("../../original/ch7/Assets/torus.ply"), 22 | PLYLoader, 23 | {} 24 | ).then(r -> { 25 | program = new Program(gl, { 26 | vertex: Webpack.require("./shaders/passthrough.vert.glsl"), 27 | fragment: Webpack.require("./shaders/uv_vis.frag.glsl"), 28 | }); 29 | final geometry = new Geometry(gl, { 30 | position: { size: r.attributes.POSITION.size, data: r.attributes.POSITION.value }, 31 | uv: { size: r.attributes.TEXCOORD_0.size, data: r.attributes.TEXCOORD_0.value }, 32 | normal: { size: r.attributes.NORMAL.size, data: r.attributes.NORMAL.value }, 33 | index: { size: r.indices.size, data: r.indices.value }, 34 | }); 35 | 36 | mesh = new Mesh(gl, { geometry: geometry, program: program }); 37 | 38 | mesh.setParent(scene); 39 | 40 | Browser.window.requestAnimationFrame(onFrame); 41 | }); 42 | } 43 | override public function onFrame(dt: Float): Void { 44 | super.onFrame(dt); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/ch07/shaders/passthrough.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec3 position; 6 | in vec2 uv; 7 | 8 | uniform mat4 modelViewMatrix; 9 | uniform mat4 projectionMatrix; 10 | 11 | out vec2 fragUV; 12 | 13 | void main() { 14 | fragUV = uv; 15 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 16 | } -------------------------------------------------------------------------------- /src/ch07/shaders/uv_vis.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec2 fragUV; 6 | 7 | out vec4 outColor; 8 | void main() { 9 | outColor = vec4(fragUV, 0.0, 1.0); 10 | } -------------------------------------------------------------------------------- /src/ch08/DiffuseLighting.hx: -------------------------------------------------------------------------------- 1 | package ch08; 2 | 3 | import externs.Ogl.Vec3; 4 | import utils.DirectionalLight; 5 | import externs.Ogl.Program; 6 | import externs.Ogl.Mesh; 7 | import externs.Ogl.Geometry; 8 | import utils.OglBase; 9 | import externs.Ply.Loader; 10 | import externs.Ply.PLYLoader; 11 | import js.Browser; 12 | 13 | class DiffuseLighting extends OglBase { 14 | private var program: Program; 15 | private var mesh: Mesh; 16 | private var light: DirectionalLight; 17 | public function new() { 18 | super(); 19 | light = new DirectionalLight(); 20 | light.intensity = 1.0; 21 | light.color = new Vec3(1, 1, 1); 22 | light.direction = new Vec3(0, -1, 0); 23 | } 24 | 25 | override private function setup():Void { 26 | super.setup(); 27 | Loader.load( 28 | Webpack.require("../../original/ch8/Assets/torus.ply"), 29 | PLYLoader, 30 | {} 31 | ).then(r -> { 32 | program = new Program(gl, { 33 | vertex: Webpack.require("./shaders/diffuse_light.vert.glsl"), 34 | fragment: Webpack.require("./shaders/diffuse_light.frag.glsl"), 35 | uniforms: { 36 | lightCol: { value: getLightColor(light) }, 37 | lightDir: { value: getLightDirection(light) }, 38 | meshCol: { value: new Vec3(1, 0, 1) } 39 | }, 40 | }); 41 | final geometry = new Geometry(gl, { 42 | position: { size: r.attributes.POSITION.size, data: r.attributes.POSITION.value }, 43 | uv: { size: r.attributes.TEXCOORD_0.size, data: r.attributes.TEXCOORD_0.value }, 44 | normal: { size: r.attributes.NORMAL.size, data: r.attributes.NORMAL.value }, 45 | index: { size: r.indices.size, data: r.indices.value }, 46 | }); 47 | 48 | mesh = new Mesh(gl, { geometry: geometry, program: program }); 49 | mesh.rotation.x = Math.PI * 0.75; 50 | mesh.setParent(scene); 51 | 52 | Browser.window.requestAnimationFrame(onFrame); 53 | }); 54 | } 55 | override public function onFrame(dt: Float): Void { 56 | super.onFrame(dt); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/ch08/RimLight.hx: -------------------------------------------------------------------------------- 1 | package ch08; 2 | 3 | import externs.Ogl.Vec3; 4 | import utils.DirectionalLight; 5 | import externs.Ogl.Program; 6 | import externs.Ogl.Mesh; 7 | import externs.Ogl.Geometry; 8 | import utils.OglBase; 9 | import externs.Ply.Loader; 10 | import externs.Ply.PLYLoader; 11 | import js.Browser; 12 | 13 | class RimLight extends OglBase { 14 | private var program: Program; 15 | private var mesh: Mesh; 16 | private var light: DirectionalLight; 17 | public function new() { 18 | super(); 19 | light = new DirectionalLight(); 20 | light.intensity = 1.0; 21 | light.color = new Vec3(1, 1, 1); 22 | light.direction = new Vec3(0, -1, 0); 23 | } 24 | 25 | override private function setup():Void { 26 | super.setup(); 27 | Loader.load( 28 | Webpack.require("../../original/ch8/Assets/torus.ply"), 29 | PLYLoader, 30 | {} 31 | ).then(r -> { 32 | program = new Program(gl, { 33 | vertex: Webpack.require("./shaders/rim_light.vert.glsl"), 34 | fragment: Webpack.require("./shaders/rim_light.frag.glsl"), 35 | uniforms: { 36 | lightCol: { value: getLightColor(light) }, 37 | lightDir: { value: getLightDirection(light) }, 38 | meshCol: { value: new Vec3(1, 0, 1) } 39 | }, 40 | }); 41 | final geometry = new Geometry(gl, { 42 | position: { size: r.attributes.POSITION.size, data: r.attributes.POSITION.value }, 43 | uv: { size: r.attributes.TEXCOORD_0.size, data: r.attributes.TEXCOORD_0.value }, 44 | normal: { size: r.attributes.NORMAL.size, data: r.attributes.NORMAL.value }, 45 | index: { size: r.indices.size, data: r.indices.value }, 46 | }); 47 | 48 | mesh = new Mesh(gl, { geometry: geometry, program: program }); 49 | mesh.rotation.x = Math.PI * 0.75; 50 | mesh.setParent(scene); 51 | 52 | Browser.window.requestAnimationFrame(onFrame); 53 | }); 54 | } 55 | override public function onFrame(dt: Float): Void { 56 | super.onFrame(dt); 57 | mesh.rotation.x += 0.01; 58 | mesh.rotation.y += 0.01; 59 | mesh.rotation.z += 0.01; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/ch08/shaders/diffuse_light.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec2 fragUV; 6 | in vec3 fragNormal; 7 | 8 | uniform vec3 lightDir; 9 | uniform vec3 lightCol; 10 | uniform vec3 meshCol; 11 | 12 | out vec4 outColor; 13 | void main() { 14 | vec3 normal = normalize(fragNormal); 15 | float lightAmt = max(0.0, dot(normal, lightDir)); 16 | vec3 fragLight = lightCol * lightAmt; 17 | outColor = vec4(meshCol * fragLight, 1.0); 18 | } -------------------------------------------------------------------------------- /src/ch08/shaders/diffuse_light.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec3 position; 6 | in vec2 uv; 7 | in vec3 normal; 8 | 9 | uniform mat4 modelViewMatrix; 10 | uniform mat4 projectionMatrix; 11 | uniform mat3 normalMatrix; 12 | 13 | out vec2 fragUV; 14 | out vec3 fragNormal; 15 | 16 | void main() { 17 | fragUV = uv; 18 | fragNormal = normalMatrix * normal; 19 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 20 | } -------------------------------------------------------------------------------- /src/ch08/shaders/rim_light.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec3 fragNormal; 6 | in vec3 fragWorldPos; 7 | 8 | uniform vec3 cameraPosition; 9 | uniform vec3 lightDir; 10 | uniform vec3 lightCol; 11 | uniform vec3 meshCol; 12 | 13 | out vec4 outColor; 14 | void main() { 15 | vec3 normal = normalize(fragNormal); 16 | vec3 toCam = normalize(cameraPosition - fragWorldPos); 17 | float rimAmt = 1.0 - max(0.0, dot(normal, toCam)); 18 | rimAmt = pow(rimAmt, 2.0); 19 | float lightAmt = max(0.0, dot(normal, lightDir)); 20 | vec3 fragLight = lightCol * lightAmt; 21 | outColor = vec4(meshCol * fragLight + rimAmt, 1.0); 22 | } -------------------------------------------------------------------------------- /src/ch08/shaders/rim_light.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec3 position; 6 | in vec3 normal; 7 | 8 | uniform mat4 modelViewMatrix; 9 | uniform mat4 projectionMatrix; 10 | uniform mat3 normalMatrix; 11 | 12 | out vec3 fragNormal; 13 | out vec3 fragWorldPos; 14 | 15 | void main() { 16 | fragNormal = normalMatrix * normal; 17 | fragWorldPos = (modelViewMatrix * vec4(position, 1.0)).xyz; 18 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 19 | } -------------------------------------------------------------------------------- /src/ch09/BlinnPhongTorus.hx: -------------------------------------------------------------------------------- 1 | package ch09; 2 | 3 | import externs.Ogl.Program; 4 | import externs.Ogl.Vec3; 5 | import utils.DirectionalLight; 6 | 7 | class BlinnPhongTorus extends LightModelBase { 8 | public function new() { 9 | super(); 10 | } 11 | override private function createShader(): Program { 12 | return new Program(gl, { 13 | vertex: Webpack.require("./shaders/blinnPhong.vert.glsl"), 14 | fragment: Webpack.require("./shaders/blinnPhong.frag.glsl"), 15 | uniforms: { 16 | lightCol: {value: getLightColor(light)}, 17 | lightDir: {value: getLightDirection(light)}, 18 | meshCol: {value: new Vec3(0.0, 0.5, 1)}, 19 | meshSpecCol: {value: new Vec3(1, 1, 1)}, 20 | ambientCol: {value: new Vec3(0.0, 0.3, 0.0)}, 21 | }, 22 | }); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/ch09/BlinnShield.hx: -------------------------------------------------------------------------------- 1 | package ch09; 2 | 3 | import js.html.Image; 4 | import externs.Ogl.Texture; 5 | import externs.Ogl.Program; 6 | import externs.Ogl.Vec3; 7 | import utils.DirectionalLight; 8 | 9 | class BlinnShield extends LightModelBase { 10 | public function new() { 11 | super(); 12 | camera.position.set(0, 0, 3); 13 | } 14 | override private function createShader(): Program { 15 | return new Program(gl, { 16 | vertex: Webpack.require("./shaders/blinnShield.vert.glsl"), 17 | fragment: Webpack.require("./shaders/blinnShield.frag.glsl"), 18 | uniforms: { 19 | lightCol: { value: getLightColor(light) }, 20 | lightDir: { value: getLightDirection(light) }, 21 | ambientCol: { value: new Vec3(0.0, 0.0, 0.0) }, 22 | diffuseTex: { value: loadTexture(Webpack.require("../../original/ch9/Assets/shield_diffuse.png")) }, 23 | specTex: { value: loadTexture(Webpack.require("../../original/ch9/Assets/shield_spec.png")) }, 24 | }, 25 | }); 26 | } 27 | override function getModel() { 28 | return Webpack.require("../../original/ch9/Assets/shield.ply"); 29 | } 30 | private function loadTexture(path: String): Texture { 31 | final texture = new Texture(gl); 32 | final img = new Image(); 33 | img.src = path; 34 | img.onload = () -> texture.image = img; 35 | return texture; 36 | } 37 | override function rotateMesh(dt:Float) { 38 | mesh.rotation.x = -Math.PI * 0.25; 39 | mesh.rotation.y += 0.01; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/ch09/DiffuseSpecularTorus.hx: -------------------------------------------------------------------------------- 1 | package ch09; 2 | 3 | import externs.Ogl.Program; 4 | import externs.Ogl.Vec3; 5 | import utils.DirectionalLight; 6 | 7 | class DiffuseSpecularTorus extends LightModelBase { 8 | public function new() { 9 | super(); 10 | } 11 | override private function createShader(): Program { 12 | return new Program(gl, { 13 | vertex: Webpack.require("./shaders/diffuseSpecular.vert.glsl"), 14 | fragment: Webpack.require("./shaders/diffuseSpecular.frag.glsl"), 15 | uniforms: { 16 | lightCol: {value: getLightColor(light)}, 17 | lightDir: {value: getLightDirection(light)}, 18 | meshCol: {value: new Vec3(1, 0, 1)}, 19 | meshSpecCol: {value: new Vec3(1, 1, 1)}, 20 | }, 21 | }); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/ch09/LightModelBase.hx: -------------------------------------------------------------------------------- 1 | package ch09; 2 | 3 | import externs.Ply.PLYLoader; 4 | import externs.Ply.Loader; 5 | import externs.Ogl.Geometry; 6 | import externs.Ogl.Program; 7 | import externs.Ogl.Vec3; 8 | import utils.DirectionalLight; 9 | import externs.Ogl.Mesh; 10 | import utils.OglBase; 11 | import js.Browser; 12 | 13 | abstract class LightModelBase extends OglBase { 14 | private var program:Program; 15 | private var mesh:Mesh; 16 | private var light:DirectionalLight; 17 | 18 | public function new() { 19 | super(); 20 | light = new DirectionalLight(); 21 | light.intensity = 1.0; 22 | light.color = new Vec3(1, 1, 1); 23 | light.direction = new Vec3(0, -1, 0); 24 | } 25 | 26 | override private function setup():Void { 27 | super.setup(); 28 | Loader.load(getModel(), PLYLoader, {}).then(r -> { 29 | program = createShader(); 30 | final geometry = new Geometry(gl, { 31 | position: {size: r.attributes.POSITION.size, data: r.attributes.POSITION.value}, 32 | uv: {size: r.attributes.TEXCOORD_0.size, data: r.attributes.TEXCOORD_0.value}, 33 | normal: {size: r.attributes.NORMAL.size, data: r.attributes.NORMAL.value}, 34 | index: {size: r.indices.size, data: r.indices.value}, 35 | }); 36 | 37 | mesh = new Mesh(gl, {geometry: geometry, program: program}); 38 | mesh.rotation.x = Math.PI * 0.75; 39 | mesh.setParent(scene); 40 | 41 | Browser.window.requestAnimationFrame(onFrame); 42 | }); 43 | } 44 | 45 | override public function onFrame(dt:Float):Void { 46 | super.onFrame(dt); 47 | rotateMesh(dt); 48 | } 49 | 50 | abstract private function createShader(): Program; 51 | private function getModel() { 52 | return Webpack.require("../../original/ch9/Assets/torus.ply"); 53 | } 54 | private function rotateMesh(dt:Float) { 55 | mesh.rotation.x += 0.01; 56 | mesh.rotation.y += 0.01; 57 | mesh.rotation.z += 0.01; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/ch09/PhongTorus.hx: -------------------------------------------------------------------------------- 1 | package ch09; 2 | 3 | import externs.Ogl.Program; 4 | import externs.Ogl.Vec3; 5 | import utils.DirectionalLight; 6 | 7 | class PhongTorus extends LightModelBase { 8 | public function new() { 9 | super(); 10 | } 11 | override private function createShader(): Program { 12 | return new Program(gl, { 13 | vertex: Webpack.require("./shaders/phong.vert.glsl"), 14 | fragment: Webpack.require("./shaders/phong.frag.glsl"), 15 | uniforms: { 16 | lightCol: {value: getLightColor(light)}, 17 | lightDir: {value: getLightDirection(light)}, 18 | meshCol: {value: new Vec3(0.0, 0.5, 1)}, 19 | meshSpecCol: {value: new Vec3(1, 1, 1)}, 20 | ambientCol: {value: new Vec3(0.0, 0.3, 0.0)}, 21 | }, 22 | }); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/ch09/SpecularTorus.hx: -------------------------------------------------------------------------------- 1 | package ch09; 2 | 3 | import externs.Ogl.Program; 4 | import externs.Ogl.Vec3; 5 | import utils.DirectionalLight; 6 | 7 | class SpecularTorus extends LightModelBase { 8 | public function new() { 9 | super(); 10 | } 11 | override private function createShader(): Program { 12 | return new Program(gl, { 13 | vertex: Webpack.require("./shaders/specular.vert.glsl"), 14 | fragment: Webpack.require("./shaders/specular.frag.glsl"), 15 | uniforms: { 16 | lightCol: {value: getLightColor(light)}, 17 | lightDir: {value: getLightDirection(light)}, 18 | meshCol: {value: new Vec3(1, 0, 1)}, 19 | meshSpecCol: {value: new Vec3(1, 1, 1)}, 20 | }, 21 | }); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/ch09/shaders/blinnPhong.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec3 fragNormal; 6 | in vec3 fragWorldPos; 7 | 8 | uniform vec3 lightDir; 9 | uniform vec3 lightCol; 10 | uniform vec3 meshCol; 11 | uniform vec3 meshSpecCol; 12 | uniform vec3 ambientCol; 13 | uniform vec3 cameraPosition; 14 | 15 | out vec4 outColor; 16 | 17 | void main() { 18 | vec3 normal = normalize(fragNormal); 19 | vec3 viewDir = normalize(cameraPosition - fragWorldPos); 20 | vec3 halfVec = normalize(viewDir + lightDir); 21 | 22 | float diffuseAmount = max(0.0, dot(normal, lightDir)); 23 | vec3 diffuseColor = meshCol * lightCol * diffuseAmount; 24 | 25 | float specularAmount = max(0.0, dot(halfVec, normal)); 26 | float specularBrightnes = pow(specularAmount, 64.0); 27 | vec3 specularColor = meshSpecCol * lightCol * specularBrightnes; 28 | 29 | vec3 ambient = ambientCol * meshCol; 30 | 31 | outColor = vec4(diffuseColor + specularColor + ambient, 1.0); 32 | } -------------------------------------------------------------------------------- /src/ch09/shaders/blinnPhong.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec3 position; 6 | in vec3 normal; 7 | 8 | uniform mat4 modelViewMatrix; 9 | uniform mat4 projectionMatrix; 10 | uniform mat3 normalMatrix; 11 | 12 | out vec3 fragNormal; 13 | out vec3 fragWorldPos; 14 | 15 | void main() { 16 | fragNormal = normalMatrix * normal; 17 | fragWorldPos = (modelViewMatrix * vec4(position, 1.0)).xyz; 18 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 19 | } -------------------------------------------------------------------------------- /src/ch09/shaders/blinnShield.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec3 fragNormal; 6 | in vec3 fragWorldPos; 7 | in vec2 fragUV; 8 | 9 | uniform vec3 lightDir; 10 | uniform vec3 lightCol; 11 | uniform vec3 ambientCol; 12 | uniform vec3 cameraPosition; 13 | uniform sampler2D diffuseTex; 14 | uniform sampler2D specTex; 15 | 16 | out vec4 outColor; 17 | 18 | void main() { 19 | vec3 normal = normalize(fragNormal); 20 | vec3 viewDir = normalize(cameraPosition - fragWorldPos); 21 | vec3 halfVec = normalize(viewDir + lightDir); 22 | 23 | vec3 meshCol = texture(diffuseTex, fragUV).xyz; 24 | vec3 meshSpecCol = texture(specTex, fragUV).xyz; 25 | 26 | float diffuseAmount = max(0.0, dot(normal, lightDir)); 27 | vec3 diffuseColor = meshCol * lightCol * diffuseAmount; 28 | 29 | float specularAmount = max(0.0, dot(halfVec, normal)); 30 | float specularBrightnes = pow(specularAmount, 64.0); 31 | vec3 specularColor = meshSpecCol.x * lightCol * specularBrightnes; 32 | 33 | vec3 ambient = ambientCol * meshCol; 34 | 35 | outColor = vec4(diffuseColor + specularColor + ambient, 1.0); 36 | } -------------------------------------------------------------------------------- /src/ch09/shaders/blinnShield.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec3 position; 6 | in vec3 normal; 7 | in vec2 uv; 8 | 9 | uniform mat4 modelViewMatrix; 10 | uniform mat4 projectionMatrix; 11 | uniform mat3 normalMatrix; 12 | 13 | out vec3 fragNormal; 14 | out vec3 fragWorldPos; 15 | out vec2 fragUV; 16 | 17 | void main() { 18 | fragUV = uv; 19 | fragNormal = normalMatrix * normal; 20 | fragWorldPos = (modelViewMatrix * vec4(position, 1.0)).xyz; 21 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 22 | } -------------------------------------------------------------------------------- /src/ch09/shaders/diffuseSpecular.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec3 fragNormal; 6 | in vec3 fragWorldPos; 7 | 8 | uniform vec3 lightDir; 9 | uniform vec3 lightCol; 10 | uniform vec3 meshCol; 11 | uniform vec3 meshSpecCol; 12 | uniform vec3 cameraPosition; 13 | 14 | out vec4 outColor; 15 | 16 | void main() { 17 | vec3 normal = normalize(fragNormal); 18 | vec3 reflection = reflect(-lightDir, normal); 19 | vec3 viewDir = normalize(cameraPosition - fragWorldPos); 20 | 21 | float diffuseAmount = max(0.0, dot(normal, lightDir)); 22 | vec3 diffuseColor = meshCol * lightCol * diffuseAmount; 23 | 24 | float specularAmount = max(0.0, dot(reflection, viewDir)); 25 | float specularBrightnes = pow(specularAmount, 16.0); 26 | vec3 specularColor = meshSpecCol * lightCol * specularBrightnes; 27 | 28 | outColor = vec4(diffuseColor + specularColor, 1.0); 29 | } -------------------------------------------------------------------------------- /src/ch09/shaders/diffuseSpecular.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec3 position; 6 | in vec3 normal; 7 | 8 | uniform mat4 modelViewMatrix; 9 | uniform mat4 projectionMatrix; 10 | uniform mat3 normalMatrix; 11 | 12 | out vec3 fragNormal; 13 | out vec3 fragWorldPos; 14 | 15 | void main() { 16 | fragNormal = normalMatrix * normal; 17 | fragWorldPos = (modelViewMatrix * vec4(position, 1.0)).xyz; 18 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 19 | } -------------------------------------------------------------------------------- /src/ch09/shaders/phong.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec3 fragNormal; 6 | in vec3 fragWorldPos; 7 | 8 | uniform vec3 lightDir; 9 | uniform vec3 lightCol; 10 | uniform vec3 meshCol; 11 | uniform vec3 meshSpecCol; 12 | uniform vec3 ambientCol; 13 | uniform vec3 cameraPosition; 14 | 15 | out vec4 outColor; 16 | 17 | void main() { 18 | vec3 normal = normalize(fragNormal); 19 | vec3 reflection = reflect(-lightDir, normal); 20 | vec3 viewDir = normalize(cameraPosition - fragWorldPos); 21 | 22 | float diffuseAmount = max(0.0, dot(normal, lightDir)); 23 | vec3 diffuseColor = meshCol * lightCol * diffuseAmount; 24 | 25 | float specularAmount = max(0.0, dot(reflection, viewDir)); 26 | float specularBrightnes = pow(specularAmount, 16.0); 27 | vec3 specularColor = meshSpecCol * lightCol * specularBrightnes; 28 | 29 | vec3 ambient = ambientCol * meshCol; 30 | 31 | outColor = vec4(diffuseColor + specularColor + ambient, 1.0); 32 | } -------------------------------------------------------------------------------- /src/ch09/shaders/phong.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec3 position; 6 | in vec3 normal; 7 | 8 | uniform mat4 modelViewMatrix; 9 | uniform mat4 projectionMatrix; 10 | uniform mat3 normalMatrix; 11 | 12 | out vec3 fragNormal; 13 | out vec3 fragWorldPos; 14 | 15 | void main() { 16 | fragNormal = normalMatrix * normal; 17 | fragWorldPos = (modelViewMatrix * vec4(position, 1.0)).xyz; 18 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 19 | } -------------------------------------------------------------------------------- /src/ch09/shaders/specular.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec3 fragNormal; 6 | in vec3 fragWorldPos; 7 | 8 | uniform vec3 lightDir; 9 | uniform vec3 lightCol; 10 | uniform vec3 meshCol; 11 | uniform vec3 meshSpecCol; 12 | uniform vec3 cameraPosition; 13 | 14 | out vec4 outColor; 15 | void main() { 16 | vec3 normal = normalize(fragNormal); 17 | vec3 reflection = reflect(-lightDir, normal); 18 | vec3 viewDir = normalize(cameraPosition - fragWorldPos); 19 | 20 | float specularAmount = max(0.0, dot(reflection, viewDir)); 21 | float specularBrightnes = pow(specularAmount, 16.0); 22 | 23 | outColor = vec4(lightCol * meshSpecCol * specularBrightnes, 1.0); 24 | } -------------------------------------------------------------------------------- /src/ch09/shaders/specular.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec3 position; 6 | in vec3 normal; 7 | 8 | uniform mat4 modelViewMatrix; 9 | uniform mat4 projectionMatrix; 10 | uniform mat3 normalMatrix; 11 | 12 | out vec3 fragNormal; 13 | out vec3 fragWorldPos; 14 | 15 | void main() { 16 | fragNormal = normalMatrix * normal; 17 | fragWorldPos = (modelViewMatrix * vec4(position, 1.0)).xyz; 18 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 19 | } -------------------------------------------------------------------------------- /src/ch10/NormalMapping.hx: -------------------------------------------------------------------------------- 1 | package ch10; 2 | 3 | import utils.LoadTexture.loadTexture; 4 | import externs.Ogl.Program; 5 | import externs.Ogl.Vec3; 6 | import utils.DirectionalLight; 7 | 8 | class NormalMapping extends NormalMappingBase { 9 | public function new() { 10 | super(); 11 | } 12 | override private function createShader():Program { 13 | return new Program(gl, { 14 | vertex: Webpack.require("./shaders/normalMapping.vert.glsl"), 15 | fragment: Webpack.require("./shaders/normalMapping.frag.glsl"), 16 | uniforms: { 17 | lightCol: {value: getLightColor(light)}, 18 | lightDir: {value: getLightDirection(light)}, 19 | ambientCol: {value: new Vec3(0.0, 0.0, 0.0)}, 20 | diffuseTex: {value: loadTexture(Webpack.require("../../original/ch10/Assets/shield_diffuse.png"), gl)}, 21 | specTex: {value: loadTexture(Webpack.require("../../original/ch10/Assets/shield_spec.png"), gl)}, 22 | normalTex: {value: loadTexture(Webpack.require("../../original/ch10/Assets/shield_normal.png"), gl)}, 23 | }, 24 | }); 25 | } 26 | 27 | override private function getModel() { 28 | return Webpack.require("../../original/ch10/Assets/shield.ply"); 29 | } 30 | 31 | override public function onFrame(dt:Float):Void { 32 | super.onFrame(dt); 33 | rotateMesh(dt); 34 | } 35 | 36 | function rotateMesh(dt:Float) { 37 | mesh.rotation.x = -Math.PI * 0.25; 38 | mesh.rotation.y += 0.01; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/ch10/NormalMappingBase.hx: -------------------------------------------------------------------------------- 1 | package ch10; 2 | 3 | import js.Browser; 4 | import externs.Ply.PLYLoader; 5 | import externs.Ply.Loader; 6 | import externs.Ogl.Mesh; 7 | import utils.OglBase; 8 | import externs.Ogl.Program; 9 | import externs.Ogl.Vec3; 10 | import utils.DirectionalLight; 11 | import utils.CreatePLYGeometry.createPLYGeometry; 12 | 13 | abstract class NormalMappingBase extends OglBase { 14 | private var program:Program; 15 | private var mesh:Mesh; 16 | private var light:DirectionalLight; 17 | 18 | public function new() { 19 | super(); 20 | light = new DirectionalLight(); 21 | light.intensity = 1.0; 22 | light.color = new Vec3(1, 1, 1); 23 | light.direction = new Vec3(0, -1, 0); 24 | camera.position.set(0, 0, 3); 25 | } 26 | 27 | override private function setup():Void { 28 | super.setup(); 29 | Loader.load(getModel(), PLYLoader, {}).then(r -> { 30 | program = createShader(); 31 | final geometry = createPLYGeometry(gl, r); 32 | 33 | mesh = new Mesh(gl, {geometry: geometry, program: program}); 34 | mesh.rotation.x = Math.PI * 0.75; 35 | mesh.setParent(scene); 36 | 37 | Browser.window.requestAnimationFrame(onFrame); 38 | }); 39 | } 40 | 41 | abstract private function createShader():Program; 42 | 43 | abstract function getModel(): String; 44 | } 45 | -------------------------------------------------------------------------------- /src/ch10/Water.hx: -------------------------------------------------------------------------------- 1 | package ch10; 2 | 3 | import utils.LoadTexture.loadTexture; 4 | import js.html.webgl.WebGL2RenderingContext; 5 | import externs.Ogl.Program; 6 | import externs.Ogl.Vec3; 7 | import utils.DirectionalLight; 8 | 9 | class Water extends NormalMappingBase { 10 | public function new() { 11 | super(); 12 | light.direction = new Vec3(0.5, -1, -1); 13 | } 14 | override private function createShader():Program { 15 | return new Program(gl, { 16 | vertex: Webpack.require("./shaders/water.vert.glsl"), 17 | fragment: Webpack.require("./shaders/water.frag.glsl"), 18 | uniforms: { 19 | time: { value: 0 }, 20 | lightCol: {value: getLightColor(light)}, 21 | lightDir: {value: getLightDirection(light)}, 22 | normalTex: {value: loadTexture( 23 | Webpack.require("../../original/ch10/Assets/water_nrm.png"), 24 | gl, 25 | { 26 | wrapS: WebGL2RenderingContext.REPEAT, 27 | wrapT: WebGL2RenderingContext.REPEAT, 28 | flipY: false, 29 | } 30 | )}, 31 | }, 32 | cullFace: null, 33 | }); 34 | } 35 | 36 | override private function getModel() { 37 | return Webpack.require("../../original/ch10/Assets/plane.ply"); 38 | } 39 | override public function onFrame(dt:Float):Void { 40 | super.onFrame(dt); 41 | program.uniforms.time.value = dt * 0.001; 42 | mesh.rotation.x = Math.PI * 1.3; 43 | mesh.rotation.y = Math.PI; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/ch10/shaders/normalMapping.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec3 fragWorldPos; 6 | in vec2 fragUV; 7 | in mat3 TBN; 8 | 9 | uniform vec3 lightDir; 10 | uniform vec3 lightCol; 11 | uniform vec3 ambientCol; 12 | uniform vec3 cameraPosition; 13 | uniform sampler2D diffuseTex; 14 | uniform sampler2D specTex; 15 | uniform sampler2D normalTex; 16 | 17 | out vec4 outColor; 18 | 19 | void main() { 20 | vec3 normal = texture(normalTex, fragUV).rgb; 21 | normal = normalize(normal * 2.0 - 1.0); 22 | normal = normalize(TBN * normal); 23 | 24 | vec3 viewDir = normalize(cameraPosition - fragWorldPos); 25 | vec3 halfVec = normalize(viewDir + lightDir); 26 | 27 | vec3 meshCol = texture(diffuseTex, fragUV).xyz; 28 | vec3 meshSpecCol = texture(specTex, fragUV).xyz; 29 | 30 | float diffuseAmount = max(0.0, dot(normal, lightDir)); 31 | vec3 diffuseColor = lightCol * diffuseAmount; 32 | 33 | float specularAmount = max(0.0, dot(halfVec, normal)); 34 | float specularBrightnes = pow(specularAmount, 64.0); 35 | vec3 specularColor = meshSpecCol.x * lightCol * specularBrightnes; 36 | 37 | vec3 ambient = ambientCol * meshCol; 38 | 39 | outColor = vec4(diffuseColor + specularColor + ambient, 1.0); 40 | } -------------------------------------------------------------------------------- /src/ch10/shaders/normalMapping.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec3 position; 6 | in vec3 normal; 7 | in vec2 uv; 8 | in vec3 tangent; 9 | 10 | uniform mat4 modelViewMatrix; 11 | uniform mat4 projectionMatrix; 12 | uniform mat3 normalMatrix; 13 | 14 | out vec3 fragWorldPos; 15 | out vec2 fragUV; 16 | out mat3 TBN; 17 | 18 | void main() { 19 | vec3 T = normalize(normalMatrix * tangent.xyz); 20 | vec3 B = normalize(normal * cross(tangent.xyz, normal.xyz)); 21 | vec3 N = normalize(normalMatrix * normal); 22 | 23 | TBN = mat3(T, B, N); 24 | 25 | fragUV = uv; 26 | fragWorldPos = (modelViewMatrix * vec4(position, 1.0)).xyz; 27 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 28 | } -------------------------------------------------------------------------------- /src/ch10/shaders/water.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec3 fragWorldPos; 6 | in vec2 fragUV; 7 | in vec2 fragUV2; 8 | in mat3 TBN; 9 | 10 | uniform vec3 lightDir; 11 | uniform vec3 lightCol; 12 | uniform vec3 cameraPosition; 13 | uniform sampler2D normalTex; 14 | 15 | out vec4 outColor; 16 | 17 | void main() { 18 | vec3 normal = texture(normalTex, fragUV).rgb; 19 | normal = normalize(normal * 2.0 - 1.0); 20 | 21 | vec3 normal2 = texture(normalTex, fragUV2).rgb; 22 | normal2 = normalize(normal2 * 2.0 - 1.0); 23 | 24 | normal = normalize((normal + normal2)); 25 | 26 | vec3 viewDir = normalize(cameraPosition - fragWorldPos); 27 | vec3 halfVec = normalize(viewDir + lightDir); 28 | 29 | float diffuseAmount = max(0.0, dot(normal, lightDir)); 30 | vec3 diffuseColor = vec3(0.3, 0.3, 0.4) * lightCol * diffuseAmount; 31 | 32 | float specularAmount = max(0.0, dot(halfVec, normal)); 33 | float specularBrightnes = pow(specularAmount, 512.0); 34 | vec3 specularColor = lightCol * specularBrightnes; 35 | 36 | outColor = vec4(diffuseColor + specularColor, 1.0); 37 | } -------------------------------------------------------------------------------- /src/ch10/shaders/water.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec3 position; 6 | in vec3 normal; 7 | in vec2 uv; 8 | in vec3 tangent; 9 | 10 | uniform mat4 modelViewMatrix; 11 | uniform mat4 projectionMatrix; 12 | uniform mat3 normalMatrix; 13 | uniform float time; 14 | 15 | out vec3 fragWorldPos; 16 | out vec2 fragUV; 17 | out vec2 fragUV2; 18 | out mat3 TBN; 19 | 20 | void main() { 21 | vec3 T = normalize(normalMatrix * tangent.xyz); 22 | vec3 B = normalize(normalMatrix * cross(tangent.xyz, normal.xyz)); 23 | vec3 N = normalize(normalMatrix * normal); 24 | 25 | TBN = mat3(T, B, N); 26 | 27 | float t = time * 0.05; 28 | float t2 = time * 0.02; 29 | fragUV = vec2(uv.x + t, uv.y) * 3.0; 30 | fragUV2= vec2(uv.x + t2, uv.y - t2) * 2.0; 31 | fragWorldPos = (modelViewMatrix * vec4(position, 1.0)).xyz; 32 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 33 | } -------------------------------------------------------------------------------- /src/ch11/CubeMap.hx: -------------------------------------------------------------------------------- 1 | package ch11; 2 | 3 | import externs.Ogl.Program; 4 | import externs.Ogl.Mesh; 5 | import ch11.CubeMapBase; 6 | 7 | class CubeMap extends CubeMapBase { 8 | private var mesh: Null = null; 9 | public function new() { 10 | super(); 11 | } 12 | override private function setup():Void { 13 | super.setup(); 14 | loadModel( 15 | Webpack.require("../../original/ch11/1_DrawCube/bin/data/cube.ply"), 16 | new Program(gl, { 17 | vertex: Webpack.require("./shaders/cubeMap.vert.glsl"), 18 | fragment: Webpack.require("./shaders/cubeMap.frag.glsl"), 19 | uniforms: { 20 | cubeTexture: {value: createCubeMapTexture(gl, [ 21 | Webpack.require('../../original/ch11/1_DrawCube/bin/data/cube_left.jpg'), 22 | Webpack.require('../../original/ch11/1_DrawCube/bin/data/cube_right.jpg'), 23 | Webpack.require('../../original/ch11/1_DrawCube/bin/data/cube_top.jpg'), 24 | Webpack.require('../../original/ch11/1_DrawCube/bin/data/cube_bottom.jpg'), 25 | Webpack.require('../../original/ch11/1_DrawCube/bin/data/cube_back.jpg'), 26 | Webpack.require('../../original/ch11/1_DrawCube/bin/data/cube_front.jpg'), 27 | ])}, 28 | }, 29 | }), 30 | mesh -> { 31 | this.mesh = mesh; 32 | } 33 | ); 34 | } 35 | override public function onFrame(dt:Float):Void { 36 | super.onFrame(dt); 37 | if (mesh != null) { 38 | mesh.rotation.y += 0.01; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/ch11/CubeMapBase.hx: -------------------------------------------------------------------------------- 1 | package ch11; 2 | 3 | import js.html.Image; 4 | import js.lib.Promise; 5 | import utils.LoadImage.loadImage; 6 | import externs.Ogl.Texture; 7 | import js.html.webgl.WebGL2RenderingContext; 8 | import externs.Ogl.GL; 9 | import js.Browser; 10 | import externs.Ply.PLYLoader; 11 | import externs.Ply.Loader; 12 | import externs.Ogl.Mesh; 13 | import utils.OglBase; 14 | import externs.Ogl.Program; 15 | import externs.Ogl.Vec3; 16 | import utils.DirectionalLight; 17 | import utils.CreatePLYGeometry.createPLYGeometry; 18 | 19 | abstract class CubeMapBase extends OglBase { 20 | private var light:DirectionalLight; 21 | public function new() { 22 | super(); 23 | } 24 | 25 | override private function setup():Void { 26 | super.setup(); 27 | light = new DirectionalLight(); 28 | light.intensity = 1.0; 29 | light.color = new Vec3(1, 1, 1); 30 | light.direction = new Vec3(0, -1, 0); 31 | camera.position.set(0, 0, 3); 32 | Browser.window.requestAnimationFrame(onFrame); 33 | } 34 | 35 | private function loadModel(path: String, shader: Program, ?onLoaded: (mesh: Mesh) -> Void) { 36 | Loader.load(path, PLYLoader, {}).then(r -> { 37 | final geometry = createPLYGeometry(gl, r); 38 | final mesh = new Mesh(gl, {geometry: geometry, program: shader}); 39 | mesh.setParent(scene); 40 | if (onLoaded != null) { 41 | onLoaded(mesh); 42 | } 43 | }); 44 | } 45 | private function createCubeMapTexture(gl: GL, images: Array): Texture { 46 | final texture = new Texture(gl, { 47 | target: WebGL2RenderingContext.TEXTURE_CUBE_MAP, 48 | }); 49 | final imagesToLoad: Array> = []; 50 | for(path in images) { 51 | imagesToLoad.push(loadImage(path)); 52 | } 53 | Promise.all(imagesToLoad).then((images: Array) -> { 54 | texture.image = images; 55 | }); 56 | return texture; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/ch11/SkyBox.hx: -------------------------------------------------------------------------------- 1 | package ch11; 2 | 3 | import externs.Ogl.Vec3; 4 | import utils.LoadTexture.loadTexture; 5 | import utils.DirectionalLight.getLightDirection; 6 | import utils.DirectionalLight.getLightColor; 7 | import js.html.webgl.WebGL2RenderingContext; 8 | import externs.Ogl.Program; 9 | import externs.Ogl.Mesh; 10 | import ch11.CubeMapBase; 11 | 12 | class SkyBox extends CubeMapBase { 13 | private var water: Null; 14 | public function new() { 15 | super(); 16 | } 17 | override private function setup():Void { 18 | super.setup(); 19 | light.direction = new Vec3(0.5, -1, -1); 20 | final cubeTexture = createCubeMapTexture(gl, [ 21 | Webpack.require('../../original/ch11/1_DrawCube/bin/data/cube_left.jpg'), 22 | Webpack.require('../../original/ch11/1_DrawCube/bin/data/cube_right.jpg'), 23 | Webpack.require('../../original/ch11/1_DrawCube/bin/data/cube_top.jpg'), 24 | Webpack.require('../../original/ch11/1_DrawCube/bin/data/cube_bottom.jpg'), 25 | Webpack.require('../../original/ch11/1_DrawCube/bin/data/cube_back.jpg'), 26 | Webpack.require('../../original/ch11/1_DrawCube/bin/data/cube_front.jpg'), 27 | ]); 28 | loadModel( 29 | Webpack.require("../../original/ch11/1_DrawCube/bin/data/cube.ply"), 30 | new Program(gl, { 31 | vertex: Webpack.require("./shaders/skyBox.vert.glsl"), 32 | fragment: Webpack.require("./shaders/cubeMap.frag.glsl"), 33 | uniforms: { 34 | cubeTexture: {value: cubeTexture}, 35 | }, 36 | depthFunc: WebGL2RenderingContext.LEQUAL, 37 | frontFace: WebGL2RenderingContext.CW, 38 | }), 39 | mesh -> { 40 | mesh.scale.set(4,4,4); 41 | } 42 | ); 43 | loadModel( 44 | Webpack.require("../../original/ch11/Assets/plane.ply"), 45 | new Program(gl, { 46 | vertex: Webpack.require("./shaders/water.vert.glsl"), 47 | fragment: Webpack.require("./shaders/water.frag.glsl"), 48 | uniforms: { 49 | cubeTexture: {value: cubeTexture}, 50 | time: { value: 0 }, 51 | lightCol: {value: getLightColor(light)}, 52 | lightDir: {value: getLightDirection(light)}, 53 | normalTex: {value: loadTexture( 54 | Webpack.require("../../original/ch10/Assets/water_nrm.png"), 55 | gl, 56 | { 57 | wrapS: WebGL2RenderingContext.REPEAT, 58 | wrapT: WebGL2RenderingContext.REPEAT, 59 | } 60 | )}, 61 | }, 62 | }), 63 | mesh -> { 64 | mesh.scale.set(10,10,1); 65 | mesh.rotation.x = Math.PI * 1.45; 66 | mesh.rotation.y = Math.PI; 67 | mesh.position.y -= 4; 68 | mesh.position.z -= 8; 69 | water = mesh; 70 | } 71 | ); 72 | } 73 | override public function onFrame(dt:Float):Void { 74 | super.onFrame(dt); 75 | if (water != null) { 76 | water.program.uniforms.time.value = dt * 0.001; 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/ch11/shaders/cubeMap.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec3 fragPos; 6 | 7 | uniform samplerCube cubeTexture; 8 | 9 | out vec4 outColor; 10 | 11 | void main() { 12 | 13 | outColor = texture(cubeTexture, fragPos); 14 | } -------------------------------------------------------------------------------- /src/ch11/shaders/cubeMap.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec3 position; 6 | 7 | uniform mat4 modelViewMatrix; 8 | uniform mat4 projectionMatrix; 9 | 10 | out vec3 fragPos; 11 | 12 | void main() { 13 | fragPos = position; 14 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 15 | } -------------------------------------------------------------------------------- /src/ch11/shaders/skyBox.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec3 position; 6 | 7 | uniform mat4 modelViewMatrix; 8 | uniform mat4 projectionMatrix; 9 | 10 | out vec3 fragPos; 11 | 12 | void main() { 13 | fragPos = position; 14 | gl_Position = (projectionMatrix * modelViewMatrix * vec4(position, 1.0)).xyww; 15 | } -------------------------------------------------------------------------------- /src/ch11/shaders/water.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec3 fragWorldPos; 6 | in vec2 fragUV; 7 | in vec2 fragUV2; 8 | in mat3 TBN; 9 | 10 | uniform vec3 lightDir; 11 | uniform vec3 lightCol; 12 | uniform vec3 cameraPosition; 13 | uniform sampler2D normalTex; 14 | uniform samplerCube cubeTexture; 15 | 16 | out vec4 outColor; 17 | 18 | void main() { 19 | vec3 normal = texture(normalTex, fragUV).rgb; 20 | normal = normalize(normal * 2.0 - 1.0); 21 | 22 | vec3 normal2 = texture(normalTex, fragUV2).rgb; 23 | normal2 = normalize(normal2 * 2.0 - 1.0); 24 | 25 | normal = normalize((normal + normal2)); 26 | 27 | vec3 viewDir = normalize(cameraPosition - fragWorldPos); 28 | vec3 halfVec = normalize(viewDir + lightDir); 29 | 30 | float diffuseAmount = max(0.0, dot(normal, lightDir)); 31 | vec3 diffuseColor = texture(cubeTexture, reflect(-viewDir, normal)).xyz * lightCol * diffuseAmount; 32 | 33 | float specularAmount = max(0.0, dot(halfVec, normal)); 34 | float specularBrightnes = pow(specularAmount, 512.0); 35 | vec3 specularColor = lightCol * specularBrightnes; 36 | 37 | outColor = vec4(diffuseColor + specularColor, 1.0); 38 | } -------------------------------------------------------------------------------- /src/ch11/shaders/water.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec3 position; 6 | in vec3 normal; 7 | in vec2 uv; 8 | in vec3 tangent; 9 | 10 | uniform mat4 modelViewMatrix; 11 | uniform mat4 projectionMatrix; 12 | uniform mat3 normalMatrix; 13 | uniform float time; 14 | 15 | out vec3 fragWorldPos; 16 | out vec2 fragUV; 17 | out vec2 fragUV2; 18 | out mat3 TBN; 19 | 20 | void main() { 21 | vec3 T = normalize(normalMatrix * tangent.xyz); 22 | vec3 B = normalize(normalMatrix * cross(tangent.xyz, normal.xyz)); 23 | vec3 N = normalize(normalMatrix * normal); 24 | 25 | TBN = mat3(T, B, N); 26 | 27 | float t = time * 0.05; 28 | float t2 = time * 0.02; 29 | fragUV = vec2(uv.x + t, uv.y) * 3.0; 30 | fragUV2= vec2(uv.x + t2, uv.y - t2) * 2.0; 31 | fragWorldPos = (modelViewMatrix * vec4(position, 1.0)).xyz; 32 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 33 | } -------------------------------------------------------------------------------- /src/ch12/LightBase.hx: -------------------------------------------------------------------------------- 1 | package ch12; 2 | 3 | import js.html.Image; 4 | import js.lib.Promise; 5 | import utils.LoadImage.loadImage; 6 | import externs.Ogl.Texture; 7 | import js.html.webgl.WebGL2RenderingContext; 8 | import externs.Ogl.GL; 9 | import js.Browser; 10 | import externs.Ply.PLYLoader; 11 | import externs.Ply.Loader; 12 | import externs.Ogl.Mesh; 13 | import utils.OglBase; 14 | import externs.Ogl.Program; 15 | import utils.CreatePLYGeometry.createPLYGeometry; 16 | 17 | abstract class LightBase extends OglBase { 18 | public function new() { 19 | super(); 20 | } 21 | 22 | override private function setup():Void { 23 | super.setup(); 24 | Browser.window.requestAnimationFrame(onFrame); 25 | } 26 | 27 | private function loadModel(path: String, shader: Program, ?onLoaded: (mesh: Mesh) -> Void) { 28 | Loader.load(path, PLYLoader, {}).then(r -> { 29 | final geometry = createPLYGeometry(gl, r); 30 | final mesh = new Mesh(gl, {geometry: geometry, program: shader}); 31 | mesh.setParent(scene); 32 | if (onLoaded != null) { 33 | onLoaded(mesh); 34 | } 35 | }); 36 | } 37 | private function createCubeMapTexture(gl: GL, images: Array): Texture { 38 | final texture = new Texture(gl, { 39 | target: WebGL2RenderingContext.TEXTURE_CUBE_MAP, 40 | }); 41 | final imagesToLoad: Array> = []; 42 | for(path in images) { 43 | imagesToLoad.push(loadImage(path)); 44 | } 45 | Promise.all(imagesToLoad).then((images: Array) -> { 46 | texture.image = images; 47 | }); 48 | return texture; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/ch12/MultiPass.hx: -------------------------------------------------------------------------------- 1 | package ch12; 2 | 3 | import ch12.multipass.PointLight; 4 | import ch12.multipass.DirectionalLight; 5 | import utils.LoadTexture.loadTexture; 6 | import ch12.LightBase; 7 | import externs.Ogl.Mesh; 8 | import externs.Ogl.Program; 9 | import externs.Ogl.Vec3; 10 | 11 | class MultiPass extends LightBase { 12 | private var mesh: Null = null; 13 | private var directionalLightShader: Null = null; 14 | private var pointLightShader: Null = null; 15 | private var shieldShader: Null = null; 16 | private var directionalLight: Null = null; 17 | private var pointLights: Null> = null; 18 | public function new() { 19 | super(); 20 | camera.position.set(0, 0, 6); 21 | } 22 | 23 | override private function setup():Void { 24 | super.setup(); 25 | pointLights = []; 26 | directionalLight = new DirectionalLight( 27 | new Vec3(0, -1, 0), 28 | new Vec3(1, 1, 1), 29 | 2 30 | ); 31 | pointLights.push(new PointLight( 32 | new Vec3(0, 0.5, 0.75), 33 | new Vec3(1, 0, 1), 34 | 4, 35 | 1 36 | )); 37 | pointLights.push(new PointLight( 38 | new Vec3(0.5, 0.5, 0.75), 39 | new Vec3(0, 1, 1), 40 | 4, 41 | 1 42 | )); 43 | 44 | directionalLightShader = new Program(gl, { 45 | vertex: Webpack.require("./shaders/light.vert.glsl"), 46 | fragment: Webpack.require("./shaders/pointLight.frag.glsl"), 47 | uniforms: {}, 48 | }); 49 | 50 | pointLightShader = new Program(gl, { 51 | vertex: Webpack.require("./shaders/light.vert.glsl"), 52 | fragment: Webpack.require("./shaders/pointLight.frag.glsl"), 53 | uniforms: {}, 54 | }); 55 | 56 | shieldShader = new Program(gl, { 57 | vertex: Webpack.require("./shaders/light.vert.glsl"), 58 | fragment: Webpack.require("./shaders/multiplLights.frag.glsl"), 59 | uniforms: { 60 | diffuseTex: { value: loadTexture(Webpack.require("../../original/ch12/Assets/shield_diffuse.png"), gl) }, 61 | specTex: { value: loadTexture(Webpack.require("../../original/ch12/Assets/shield_spec.png"), gl)}, 62 | normalTex: { value: loadTexture(Webpack.require("../../original/ch12/Assets/shield_normal.png"), gl)} , 63 | cubeTexture: {value: createCubeMapTexture(gl, [ 64 | Webpack.require('../../original/ch12/Assets/night_left.jpg'), 65 | Webpack.require('../../original/ch12/Assets/night_right.jpg'), 66 | Webpack.require('../../original/ch12/Assets/night_top.jpg'), 67 | Webpack.require('../../original/ch12/Assets/night_bottom.jpg'), 68 | Webpack.require('../../original/ch12/Assets/night_back.jpg'), 69 | Webpack.require('../../original/ch12/Assets/night_front.jpg'), 70 | ])}, 71 | }, 72 | }); 73 | 74 | loadModel( 75 | Webpack.require("../../original/ch12/Assets/shield.ply"), 76 | shieldShader, 77 | mesh -> { 78 | this.mesh = mesh; 79 | } 80 | ); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/ch12/MultipleLights.hx: -------------------------------------------------------------------------------- 1 | package ch12; 2 | 3 | import ch12.lights.PointLight; 4 | import utils.DirectionalLight; 5 | import utils.Degree.toRadians; 6 | import utils.LoadTexture.loadTexture; 7 | import ch12.LightBase; 8 | import ch12.lights.SpotLight; 9 | import externs.Ogl.Mesh; 10 | import externs.Ogl.Program; 11 | import externs.Ogl.Vec3; 12 | 13 | class MultipleLights extends LightBase { 14 | private var mesh: Null = null; 15 | public function new() { 16 | super(); 17 | camera.position.set(0, 0, 6); 18 | } 19 | 20 | override private function setup():Void { 21 | super.setup(); 22 | final directionalLights: Array = []; 23 | final pointLights: Array = []; 24 | final spotLights: Array = []; 25 | directionalLights.push(new DirectionalLight( 26 | new Vec3(0, -1, 0), 27 | new Vec3(1, 1, 1), 28 | 2 29 | )); 30 | pointLights.push(new PointLight( 31 | new Vec3(0, 0.5, 0.75), 32 | new Vec3(1, 0, 1), 33 | 4, 34 | 1 35 | )); 36 | pointLights.push(new PointLight( 37 | new Vec3(0.5, 0.5, 0.75), 38 | new Vec3(0, 1, 1), 39 | 4, 40 | 1 41 | )); 42 | spotLights.push(new SpotLight( 43 | new Vec3(0.5, 0 ,6), 44 | new Vec3(0, 0, -1), 45 | new Vec3(1, 0, 0), 46 | 1.0, 47 | Math.cos(toRadians(4.5)) 48 | )); 49 | spotLights.push(new SpotLight( 50 | new Vec3(-0.5, 0 ,6), 51 | new Vec3(0, 0, -1), 52 | new Vec3(0, 1, 0), 53 | 1.0, 54 | Math.cos(toRadians(4.5)) 55 | )); 56 | 57 | final program = new Program(gl, { 58 | vertex: Webpack.require("./shaders/light.vert.glsl"), 59 | fragment: Webpack.require("./shaders/multiplLights.frag.glsl"), 60 | uniforms: { 61 | "directionalLights": directionalLights, 62 | "spotLights": spotLights, 63 | "pointLights": pointLights, 64 | diffuseTex: { value: loadTexture(Webpack.require("../../original/ch12/Assets/shield_diffuse.png"), gl) }, 65 | specTex: { value: loadTexture(Webpack.require("../../original/ch12/Assets/shield_spec.png"), gl)}, 66 | normalTex: { value: loadTexture(Webpack.require("../../original/ch12/Assets/shield_normal.png"), gl)} , 67 | cubeTexture: {value: createCubeMapTexture(gl, [ 68 | Webpack.require('../../original/ch12/Assets/night_left.jpg'), 69 | Webpack.require('../../original/ch12/Assets/night_right.jpg'), 70 | Webpack.require('../../original/ch12/Assets/night_top.jpg'), 71 | Webpack.require('../../original/ch12/Assets/night_bottom.jpg'), 72 | Webpack.require('../../original/ch12/Assets/night_back.jpg'), 73 | Webpack.require('../../original/ch12/Assets/night_front.jpg'), 74 | ])}, 75 | }, 76 | }); 77 | 78 | loadModel( 79 | Webpack.require("../../original/ch12/Assets/shield.ply"), 80 | program, 81 | mesh -> { 82 | this.mesh = mesh; 83 | } 84 | ); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/ch12/PointLightExample.hx: -------------------------------------------------------------------------------- 1 | package ch12; 2 | 3 | import utils.LoadTexture.loadTexture; 4 | import ch12.LightBase; 5 | import ch12.lights.PointLight; 6 | import externs.Ogl.Mesh; 7 | import externs.Ogl.Program; 8 | import externs.Ogl.Vec3; 9 | 10 | class PointLightExample extends LightBase { 11 | private var mesh: Null = null; 12 | private var light: PointLight; 13 | private var time: Float = 0.0; 14 | public function new() { 15 | super(); 16 | camera.position.set(0, 0, 6); 17 | } 18 | 19 | override private function setup():Void { 20 | super.setup(); 21 | light = new PointLight(); 22 | light.intensity = 3.0; 23 | light.radius = 1; 24 | light.color = new Vec3(1, 1, 1); 25 | light.position.set(0, 0.5, 0.75); 26 | 27 | loadModel( 28 | Webpack.require("../../original/ch12/1_PointLights/bin/shield.ply"), 29 | new Program(gl, { 30 | vertex: Webpack.require("./shaders/light.vert.glsl"), 31 | fragment: Webpack.require("./shaders/pointLight.frag.glsl"), 32 | uniforms: { 33 | lightCol: { value: getLightColor(light) }, 34 | lightRadius: { value: light.radius }, 35 | lightPos: { value: light.position }, 36 | diffuseTex: { value: loadTexture(Webpack.require("../../original/ch12/Assets/shield_diffuse.png"), gl) }, 37 | specTex: { value: loadTexture(Webpack.require("../../original/ch12/Assets/shield_spec.png"), gl)}, 38 | normalTex: { value: loadTexture(Webpack.require("../../original/ch12/Assets/shield_normal.png"), gl)} , 39 | cubeTexture: {value: createCubeMapTexture(gl, [ 40 | Webpack.require('../../original/ch12/1_PointLights/bin/cube_left.jpg'), 41 | Webpack.require('../../original/ch12/1_PointLights/bin/cube_right.jpg'), 42 | Webpack.require('../../original/ch12/1_PointLights/bin/cube_top.jpg'), 43 | Webpack.require('../../original/ch12/1_PointLights/bin/cube_bottom.jpg'), 44 | Webpack.require('../../original/ch12/1_PointLights/bin/cube_back.jpg'), 45 | Webpack.require('../../original/ch12/1_PointLights/bin/cube_front.jpg'), 46 | ])}, 47 | }, 48 | }), 49 | mesh -> { 50 | this.mesh = mesh; 51 | } 52 | ); 53 | } 54 | override public function onFrame(dt:Float):Void { 55 | super.onFrame(dt); 56 | if (light != null) { 57 | time += 0.01; 58 | light.position = new Vec3(Math.sin(time), 0.5, 0.75); 59 | if (mesh != null) { 60 | mesh.program.uniforms.lightPos.value = light.position; 61 | mesh.rotation.x += 0.01; 62 | mesh.rotation.y += 0.01; 63 | mesh.rotation.z += 0.01; 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/ch12/SpotLights.hx: -------------------------------------------------------------------------------- 1 | package ch12; 2 | 3 | import utils.Degree.toRadians; 4 | import utils.LoadTexture.loadTexture; 5 | import ch12.LightBase; 6 | import ch12.lights.SpotLight; 7 | import externs.Ogl.Mesh; 8 | import externs.Ogl.Program; 9 | import externs.Ogl.Vec3; 10 | 11 | class SpotLights extends LightBase { 12 | private var mesh: Null = null; 13 | private var light: SpotLight; 14 | public function new() { 15 | super(); 16 | camera.position.set(0, 0, 6); 17 | } 18 | 19 | override private function setup():Void { 20 | super.setup(); 21 | light = new SpotLight(); 22 | light.intensity = 1.0; 23 | light.color = new Vec3(1, 1, 1); 24 | light.direction = new Vec3(0, 0, -1); 25 | light.position.set(0.5,0, 6); 26 | light.cutoff = Math.cos(toRadians(4.5)); 27 | 28 | loadModel( 29 | Webpack.require("../../original/ch12/2_SpotLights/bin/shield.ply"), 30 | new Program(gl, { 31 | vertex: Webpack.require("./shaders/light.vert.glsl"), 32 | fragment: Webpack.require("./shaders/spotLight.frag.glsl"), 33 | uniforms: { 34 | lightCol: { value: getLightColor(light) }, 35 | lightCutoff: { value: light.cutoff }, 36 | lightPos: { value: light.position }, 37 | lightConeDir: { value: light.direction }, 38 | diffuseTex: { value: loadTexture(Webpack.require("../../original/ch12/Assets/shield_diffuse.png"), gl) }, 39 | specTex: { value: loadTexture(Webpack.require("../../original/ch12/Assets/shield_spec.png"), gl)}, 40 | normalTex: { value: loadTexture(Webpack.require("../../original/ch12/Assets/shield_normal.png"), gl)} , 41 | cubeTexture: {value: createCubeMapTexture(gl, [ 42 | Webpack.require('../../original/ch12/Assets/night_left.jpg'), 43 | Webpack.require('../../original/ch12/Assets/night_right.jpg'), 44 | Webpack.require('../../original/ch12/Assets/night_top.jpg'), 45 | Webpack.require('../../original/ch12/Assets/night_bottom.jpg'), 46 | Webpack.require('../../original/ch12/Assets/night_back.jpg'), 47 | Webpack.require('../../original/ch12/Assets/night_front.jpg'), 48 | ])}, 49 | }, 50 | }), 51 | mesh -> { 52 | this.mesh = mesh; 53 | } 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/ch12/lights/PointLight.hx: -------------------------------------------------------------------------------- 1 | package ch12.lights; 2 | 3 | import externs.Ogl.Vec3; 4 | 5 | class PointLight { 6 | public var position: Vec3; 7 | public var color: Vec3; 8 | public var intensity: Float; 9 | public var radius: Float; 10 | public function new(?position: Vec3, ?color: Vec3, ?intensity: Float, ?radius: Float) { 11 | this.position = (position != null) ? position : new Vec3(); 12 | this.color = (color != null) ? color : new Vec3(1, 1, 1); 13 | this.intensity = (intensity != null) ? intensity : 1; 14 | this.radius = (radius != null) ? radius : std.Math.POSITIVE_INFINITY; 15 | } 16 | } 17 | function getLightColor(light: PointLight): Vec3 { 18 | return light.color.clone().multiply(light.intensity); 19 | } -------------------------------------------------------------------------------- /src/ch12/lights/SpotLight.hx: -------------------------------------------------------------------------------- 1 | package ch12.lights; 2 | 3 | import externs.Ogl.Vec3; 4 | 5 | class SpotLight { 6 | public var position: Vec3; 7 | public var direction: Vec3; 8 | public var color: Vec3; 9 | public var intensity: Float; 10 | public var cutoff: Float; 11 | public function new(?position: Vec3, ?direction: Vec3, ?color: Vec3, ?intensity: Float, ?cutoff: Float) { 12 | this.position = (position != null) ? position : new Vec3(); 13 | this.direction = (direction != null) ? direction : new Vec3(); 14 | this.color = (color != null) ? color : new Vec3(1, 1, 1); 15 | this.intensity = (intensity != null) ? intensity : 1; 16 | this.cutoff = (cutoff != null) ? cutoff : Math.PI; 17 | } 18 | } 19 | function getLightColor(light: SpotLight): Vec3 { 20 | return light.color.clone().multiply(light.intensity); 21 | } -------------------------------------------------------------------------------- /src/ch12/multipass/DirectionalLight.hx: -------------------------------------------------------------------------------- 1 | package ch12.multipass; 2 | 3 | import externs.Ogl.Program; 4 | import externs.Ogl.Vec3; 5 | 6 | class DirectionalLight extends Light { 7 | public var direction: Vec3; 8 | public var color: Vec3; 9 | public var intensity: Float; 10 | 11 | public function new(?direction: Vec3, ?color: Vec3, ?intensity: Float) { 12 | this.direction = (direction != null) ? direction : new Vec3(); 13 | this.color = (color != null) ? color : new Vec3(1, 1, 1); 14 | this.intensity = (intensity != null) ? intensity : 1; 15 | } 16 | 17 | override public function apply(shader: Program): Void { 18 | shader.uniforms.lightDir.value = direction.clone().negate().normalize(); 19 | shader.uniforms.lightCol.value = color.clone().multiply(intensity); 20 | } 21 | } -------------------------------------------------------------------------------- /src/ch12/multipass/Light.hx: -------------------------------------------------------------------------------- 1 | package ch12.multipass; 2 | 3 | import externs.Ogl.Program; 4 | 5 | abstract class Light { 6 | public function isPointLight(): Bool { 7 | return false; 8 | } 9 | abstract public function apply(shader: Program): Void; 10 | } -------------------------------------------------------------------------------- /src/ch12/multipass/PointLight.hx: -------------------------------------------------------------------------------- 1 | package ch12.multipass; 2 | 3 | import externs.Ogl.Program; 4 | import externs.Ogl.Vec3; 5 | 6 | class PointLight extends Light { 7 | public var position: Vec3; 8 | public var intensity: Float; 9 | public var radius: Float; 10 | public var color: Vec3; 11 | 12 | public function new(?position: Vec3, ?color: Vec3, ?intensity: Float, ?radius: Float) { 13 | this.position = (position != null) ? position : new Vec3(); 14 | this.color = (color != null) ? color : new Vec3(1, 1, 1); 15 | this.intensity = (intensity != null) ? intensity : 1; 16 | this.radius = (radius != null) ? radius : std.Math.POSITIVE_INFINITY; 17 | } 18 | 19 | override public function isPointLight(): Bool { 20 | return true; 21 | } 22 | 23 | override public function apply(shader: Program): Void { 24 | shader.uniforms.lightPos.value = position; 25 | shader.uniforms.lightCol.value = color.clone().multiply(intensity); 26 | shader.uniforms.lightRadius.value = radius; 27 | } 28 | } -------------------------------------------------------------------------------- /src/ch12/shaders/light.glsl: -------------------------------------------------------------------------------- 1 | float diffuse(vec3 lightDir, vec3 normal) { 2 | return max(0.0, dot(normal, lightDir)); 3 | } 4 | float specular(vec3 lightDir, vec3 viewDir, vec3 normal, float shininess) { 5 | vec3 halfVec = normalize(viewDir + lightDir); 6 | float specAmt = max(0.0, dot(halfVec, normal)); 7 | return pow(specAmt, shininess); 8 | } -------------------------------------------------------------------------------- /src/ch12/shaders/light.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | in vec3 position; 6 | in vec3 normal; 7 | in vec2 uv; 8 | in vec3 tangent; 9 | 10 | uniform mat4 modelViewMatrix; 11 | uniform mat4 modelMatrix; 12 | uniform mat4 projectionMatrix; 13 | uniform mat3 normalMatrix; 14 | 15 | out vec3 fragWorldPos; 16 | out vec2 fragUV; 17 | out mat3 TBN; 18 | 19 | void main() { 20 | vec3 T = normalize(normalMatrix * tangent.xyz); 21 | vec3 B = normalize(normalMatrix * cross(tangent.xyz, normal.xyz)); 22 | vec3 N = normalize(normalMatrix * normal); 23 | 24 | TBN = mat3(T, B, N); 25 | 26 | fragUV = uv; 27 | fragWorldPos = (modelMatrix * vec4(position, 1.0)).xyz; 28 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 29 | } -------------------------------------------------------------------------------- /src/ch12/shaders/multiplLights.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | struct DirectionalLight { 6 | vec3 direction; 7 | vec3 color; 8 | }; 9 | struct PointLight { 10 | vec3 position; 11 | vec3 color; 12 | float radius; 13 | }; 14 | struct SpotLight { 15 | vec3 position; 16 | vec3 direction; 17 | vec3 color; 18 | float cutoff; 19 | }; 20 | 21 | #define NUM_DIR_LIGHTS 1 22 | #define NUM_POINTS_LIGHT 2 23 | #define NUM_SPOT_LIGHTS 2 24 | 25 | uniform DirectionalLight directionalLights[NUM_DIR_LIGHTS]; 26 | uniform SpotLight spotLights[NUM_SPOT_LIGHTS]; 27 | uniform PointLight pointLights[NUM_POINTS_LIGHT]; 28 | 29 | uniform sampler2D normalTex; 30 | uniform sampler2D diffuseTex; 31 | uniform sampler2D specTex; 32 | uniform samplerCube cubeTexture; 33 | 34 | uniform vec3 cameraPosition; 35 | 36 | in vec3 fragNormal; 37 | in vec3 fragWorldPos; 38 | in vec2 fragUV; 39 | in mat3 TBN; 40 | 41 | @import ./light; 42 | 43 | out vec4 outColor; 44 | 45 | void main() { 46 | vec3 normal = texture(normalTex, fragUV).rgb; 47 | normal = normalize(normal * 2.0 - 1.0); 48 | normal = normalize(TBN * normal); 49 | vec3 viewDir = normalize(cameraPosition - fragWorldPos); 50 | 51 | vec3 diffuseColor = texture(diffuseTex, fragUV).rgb; 52 | float specMask = texture(specTex, fragUV).x; 53 | vec3 envReflection = texture(cubeTexture, reflect(-viewDir, normal)).xyz; 54 | 55 | vec3 finalColor = vec3(0.0, 0.0, 0.0); 56 | 57 | for (int i = 0; i < NUM_DIR_LIGHTS; i++) { 58 | DirectionalLight light = directionalLights[i]; 59 | vec3 sceneLight = mix(light.color, envReflection + light.color * 0.5, 0.5); 60 | 61 | float diffAmt = diffuse(light.direction, normal); 62 | float specAmt = specular(light.direction, viewDir, normal, 4.0) * specMask; 63 | 64 | vec3 envLighting = envReflection * specMask * diffAmt; 65 | 66 | vec3 specColor = specMask * sceneLight * specAmt; 67 | 68 | finalColor += diffuseColor * diffAmt * light.color; 69 | finalColor += specColor * sceneLight; 70 | } 71 | 72 | for (int i = 0; i < NUM_POINTS_LIGHT; i++) { 73 | PointLight light = pointLights[i]; 74 | vec3 sceneLight = mix(light.color, envReflection + light.color * 0.5, 0.5); 75 | 76 | vec3 toLight = light.position - fragWorldPos; 77 | vec3 lightDir = normalize(toLight); 78 | float distToLight = length(toLight); 79 | float falloff = 1.0 - distToLight / light.radius; 80 | 81 | float diffAmt = diffuse(lightDir, normal) * falloff; 82 | float specAmt = specular(lightDir, viewDir, normal, 4.0) * specMask * falloff; 83 | 84 | vec3 envLighting = envReflection * specMask * diffAmt; 85 | vec3 specColor = specMask * sceneLight * specAmt; 86 | 87 | finalColor += diffAmt * sceneLight * diffuseColor; 88 | finalColor += specColor; 89 | } 90 | 91 | for (int i = 0; i < NUM_SPOT_LIGHTS; i++) { 92 | SpotLight light = spotLights[i]; 93 | vec3 sceneLight = mix(light.color, envReflection + light.color * 0.5, 0.5); 94 | 95 | vec3 toLight = light.position - fragWorldPos; 96 | vec3 lightDir = normalize(toLight); 97 | float angle = dot(light.direction, -lightDir); 98 | 99 | float falloff = step(light.cutoff, angle); 100 | 101 | float diffAmt = diffuse(lightDir, normal) * falloff; 102 | float specAmt = specular(lightDir, viewDir, normal, 4.0) * specMask * falloff; 103 | 104 | vec3 envLighting = envReflection * specMask * diffAmt; 105 | vec3 specColor = specMask * sceneLight * specAmt; 106 | 107 | finalColor += diffAmt * sceneLight * diffuseColor; 108 | finalColor += specColor; 109 | } 110 | 111 | outColor = vec4(finalColor, 1.0); 112 | } -------------------------------------------------------------------------------- /src/ch12/shaders/pointLight.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | uniform vec3 lightCol; 6 | 7 | uniform float lightRadius; 8 | uniform vec3 lightPos; 9 | 10 | uniform sampler2D normalTex; 11 | uniform sampler2D diffuseTex; 12 | uniform sampler2D specTex; 13 | uniform samplerCube cubeTexture; 14 | 15 | uniform vec3 cameraPosition; 16 | 17 | in vec3 fragWorldPos; 18 | in vec2 fragUV; 19 | in mat3 TBN; 20 | 21 | out vec4 outColor; 22 | 23 | @import ./light; 24 | 25 | void main() { 26 | vec3 normal = texture(normalTex, fragUV).rgb; 27 | normal = normalize(normal * 2.0 - 1.0); 28 | normal = normalize(TBN * normal); 29 | vec3 viewDir = normalize(cameraPosition - fragWorldPos); 30 | 31 | vec3 envSample = texture(cubeTexture, reflect(-viewDir, normal)).xyz; 32 | vec3 sceneLight = mix(lightCol, envSample + lightCol * 0.5, 0.5); 33 | 34 | vec3 toLight = lightPos - fragWorldPos; 35 | vec3 lightDir = normalize(toLight); 36 | float distToLight = length(toLight); 37 | float falloff = max(0.0, 1.0 - distToLight / lightRadius); 38 | float specMask = texture(specTex, fragUV).x; 39 | 40 | float diffAmt = diffuse(lightDir, normal) * falloff; 41 | float specAmt = specular(lightDir, viewDir, normal, 4.0) * specMask * falloff; 42 | 43 | vec3 diffCol = texture(diffuseTex, fragUV).rgb * sceneLight * diffAmt; 44 | 45 | 46 | vec3 specCol = specMask * sceneLight * specAmt; 47 | 48 | 49 | outColor = vec4(diffCol + specCol, 1.0); 50 | } -------------------------------------------------------------------------------- /src/ch12/shaders/spotLight.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp int; 3 | precision highp float; 4 | 5 | uniform vec3 lightCol; 6 | 7 | uniform float lightCutoff; 8 | uniform vec3 lightPos; 9 | 10 | uniform sampler2D normalTex; 11 | uniform sampler2D diffuseTex; 12 | uniform sampler2D specTex; 13 | uniform samplerCube cubeTexture; 14 | 15 | uniform vec3 cameraPosition; 16 | uniform vec3 lightConeDir; 17 | 18 | in vec3 fragWorldPos; 19 | in vec2 fragUV; 20 | in mat3 TBN; 21 | 22 | out vec4 outColor; 23 | 24 | @import ./light; 25 | 26 | void main() { 27 | vec3 normal = texture(normalTex, fragUV).rgb; 28 | normal = normalize(normal * 2.0 - 1.0); 29 | normal = normalize(TBN * normal); 30 | vec3 viewDir = normalize(cameraPosition - fragWorldPos); 31 | 32 | vec3 envSample = texture(cubeTexture, reflect(-viewDir, normal)).xyz; 33 | vec3 sceneLight = mix(lightCol, envSample + lightCol * 0.5, 0.5); 34 | 35 | vec3 toLight = lightPos - fragWorldPos; 36 | vec3 lightDir = normalize(toLight); 37 | float angle = dot(lightConeDir, -lightDir); 38 | 39 | float falloff = step(lightCutoff, angle); 40 | 41 | float diffAmt = diffuse(lightDir, normal) * falloff; 42 | float specAmt = specular(lightDir, viewDir, normal, 4.0) * specMask * falloff; 43 | 44 | vec3 diffCol = texture(diffuseTex, fragUV).rgb * sceneLight * diffAmt; 45 | 46 | float specMask = texture(specTex, fragUV).x; 47 | vec3 specCol = specMask * sceneLight * specAmt; 48 | 49 | vec3 envLighting = envSample * specMask * diffAmt; 50 | specCol = mix(envLighting, specCol, min(1.0, specAmt)); 51 | 52 | outColor = vec4(diffCol + specCol, 1.0); 53 | } -------------------------------------------------------------------------------- /src/externs/Ogl.hx: -------------------------------------------------------------------------------- 1 | package externs; 2 | 3 | import haxe.extern.EitherType; 4 | import js.html.Image; 5 | import js.html.webgl.PowerPreference; 6 | import js.lib.Float32Array; 7 | import js.lib.Uint32Array; 8 | import js.html.webgl.RenderingContext; 9 | 10 | 11 | typedef RendererOptions = { 12 | var ?dpr: Float; 13 | var ?antialias: Bool; 14 | var ?powerPreference: PowerPreference; 15 | }; 16 | 17 | @:jsRequire("ogl", "GL") 18 | class GL extends RenderingContext { 19 | var renderer: Renderer; 20 | } 21 | 22 | typedef RenderProps = { 23 | var scene: Transform; 24 | var camera: Camera; 25 | } 26 | 27 | @:jsRequire("ogl", "Renderer") 28 | extern class Renderer { 29 | public function new(options: RendererOptions): Void; 30 | public var gl: GL; 31 | public function setSize(width: Float, height: Float): Void; 32 | public function render(props: RenderProps): Void; 33 | 34 | } 35 | @:jsRequire("ogl", "Vec3") 36 | extern class Vec3 { 37 | public function new(?x: Float, ?y: Float, ?z: Float): Void; 38 | var x: Float; 39 | var y: Float; 40 | var z: Float; 41 | public function set(x: Float, y: Float, z: Float): Void; 42 | public function multiply(v: Float): Vec3; 43 | public function negate(?v: Vec3): Vec3; 44 | public function normalize(): Vec3; 45 | public function clone(): Vec3; 46 | public function copy(v: Vec3): Vec3; 47 | public function sub(v: Vec3, ?v2: Vec3): Vec3; 48 | } 49 | @:jsRequire("ogl", "Vec2") 50 | extern class Vec2 { 51 | public function new(?x: Float, ?y: Float): Void; 52 | var x: Float; 53 | var y: Float; 54 | public function set(x: Float, y: Float): Void; 55 | public function multiply(v: Float): Vec2; 56 | public function normalize(): Vec2; 57 | public function clone(): Vec2; 58 | public function sub(v: Vec2, ?v2: Vec2): Vec2; 59 | } 60 | @:jsRequire("ogl", "Eulor") 61 | extern class Euler { 62 | public function new(?x: Float, ?y: Float, ?z: Float): Void; 63 | var x: Float; 64 | var y: Float; 65 | var z: Float; 66 | public function set(x: Float, y: Float, z: Float): Void; 67 | } 68 | @:jsRequire("ogl", "Transform") 69 | extern class Transform { 70 | var position: Vec3; 71 | var rotation: Euler; 72 | public function new(): Void; 73 | public function lookAt(target: Vec3, ?inverse: Bool): Void; 74 | public function setParent(node: Null): Void; 75 | } 76 | 77 | typedef CreateCameraProps = { 78 | var ?fov: Int; 79 | } 80 | typedef CameraPerspectiveProps = { 81 | var aspect: Float; 82 | } 83 | @:jsRequire("ogl", "Camera") 84 | extern class Camera extends Transform { 85 | public function new(gl: GL, options: CreateCameraProps): Void; 86 | public function perspective(props: CameraPerspectiveProps): Void; 87 | } 88 | 89 | typedef CreateProgramProps = { 90 | var vertex: String; 91 | var fragment: String; 92 | var ?uniforms: Dynamic; 93 | var ?cullFace: Null; 94 | var ?depthTest: Bool; 95 | var ?depthFunc: Int; 96 | var ?frontFace: Int; 97 | } 98 | typedef Uniform = { 99 | var value: T; 100 | } 101 | @:jsRequire("ogl", "Program") 102 | extern class Program { 103 | public var uniforms: Dynamic; 104 | public function new(gl: GL, options: CreateProgramProps): Void; 105 | } 106 | 107 | typedef TextureProps = { 108 | var ?wrapS: Int; 109 | var ?wrapT: Int; 110 | var ?flipY: Bool; 111 | var ?target: Int; 112 | }; 113 | @:jsRequire("ogl", "Texture") 114 | extern class Texture { 115 | public var image: EitherType>; 116 | public function new(gl: GL, ?options: TextureProps): Void; 117 | } 118 | 119 | typedef GeometryData = { 120 | var size: Int; 121 | var data: T; 122 | }; 123 | 124 | typedef CreateGeometryProps = { 125 | var position: GeometryData; 126 | var ?uv: GeometryData; 127 | var ?normal: GeometryData; 128 | var ?index: GeometryData; 129 | var ?tangent: GeometryData; 130 | } 131 | @:jsRequire("ogl", "Geometry") 132 | extern class Geometry { 133 | public function new(gl: GL, options: CreateGeometryProps): Void; 134 | public function setDrawRange(start: Int, count: Int): Void; 135 | } 136 | 137 | typedef CreateMeshProps = { 138 | var program: Program; 139 | var geometry: Geometry; 140 | }; 141 | @:jsRequire("ogl", "Mesh") 142 | extern class Mesh extends Transform { 143 | var scale: Vec3; 144 | var program: Program; 145 | public function new(gl: GL, options: CreateMeshProps): Void; 146 | } -------------------------------------------------------------------------------- /src/externs/Ply.hx: -------------------------------------------------------------------------------- 1 | package externs; 2 | 3 | import js.lib.Float32Array; 4 | import js.lib.Uint32Array; 5 | import js.lib.Promise; 6 | 7 | @:jsRequire("@loaders.gl/ply", "PLYLoader") 8 | extern class PLYLoader { 9 | 10 | } 11 | 12 | interface Attribute { 13 | var size: Int; 14 | var value: Float32Array; 15 | } 16 | 17 | interface Indicies { 18 | var size: Int; 19 | var value: Uint32Array; 20 | } 21 | 22 | interface Attributes { 23 | var NORMAL: Attribute; 24 | var POSITION: Attribute; 25 | var TEXCOORD_0: Attribute; 26 | } 27 | 28 | interface PlyModel { 29 | var attributes: Attributes; 30 | var indices: Indicies; 31 | } 32 | 33 | @:jsRequire("@loaders.gl/core") 34 | extern class Loader { 35 | public static function load(urls: String, loader: Dynamic, options: Dynamic): Promise; 36 | } -------------------------------------------------------------------------------- /src/types/Types.hx: -------------------------------------------------------------------------------- 1 | package types; 2 | 3 | import VectorMath.Mat4; 4 | import VectorMath.Vec2; 5 | import VectorMath.Vec4; 6 | import VectorMath.Vec3; 7 | import js.html.webgl.Program; 8 | import js.lib.Float32Array; 9 | 10 | interface BaseApp { 11 | // public function update():Void; 12 | public function draw(delta:Float):Void; 13 | public function setBlendingMode(source: Int, destination: Int): Void; 14 | public function enableDepthTest(): Void; 15 | public function disableDepthTest(): Void; 16 | } 17 | 18 | interface Mesh { 19 | public function build():Void; 20 | public function draw():Void; 21 | public function addVertex(vertex: Vec3):Void; 22 | public function getVertex(index: Int): Vec3; 23 | public function setVertex(index: Int, v: Vec3): Void; 24 | public function addColor(color: Vec4): Void; 25 | public function addIndicies(indicies: Array): Void; 26 | public function addTexCoord(c: Vec2): Void; 27 | } 28 | 29 | interface IShader { 30 | public var program:Program; 31 | public function load(vert:String, frag:String):Void; 32 | public function begin():Void; 33 | public function end():Void; 34 | public function setUniform4f(name: String, v: Vec4): Void; 35 | public function setUniform3f(name: String, v: Vec3): Void; 36 | public function setUniform2f(name: String, v: Vec2): Void; 37 | public function setUniform1f(name: String, f: Float): Void; 38 | public function setUniformMatrix4f(name: String, m: Mat4): Void; 39 | public function setUniformTexture(name: String, src: String, slot: Int, ?flipY: Int): Void; 40 | } 41 | 42 | interface Camera { 43 | public var position: Vec3; 44 | public var rotation: Float; 45 | } 46 | -------------------------------------------------------------------------------- /src/utils/BaseOfApp.hx: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import VectorMath.log; 4 | import js.html.KeyboardEvent; 5 | import js.Browser; 6 | import js.html.webgl.RenderingContext; 7 | import types.Types.BaseApp; 8 | import js.html.webgl.PowerPreference; 9 | 10 | class BaseOfApp implements BaseApp { 11 | private var ctx:RenderingContext; 12 | private var blendSource = RenderingContext.SRC_ALPHA; 13 | private var blendDestination = RenderingContext.ONE_MINUS_SRC_ALPHA; 14 | private var previousFrameTime: Float = -1; 15 | public function new() { 16 | setup(); 17 | } 18 | 19 | private function setup():Void { 20 | final canvas = Browser.document.createCanvasElement(); 21 | canvas.width = 1024; 22 | canvas.height = 768; 23 | canvas.id = "canvas"; 24 | ctx = canvas.getContextWebGL2({ 25 | powerPreference: PowerPreference.HIGH_PERFORMANCE, 26 | premultipliedAlpha: true, 27 | antialias: true, 28 | alpha: false 29 | }); 30 | ctx.viewport(0, 0, canvas.width, canvas.height); 31 | Browser.document.body.appendChild(canvas); 32 | Browser.window.requestAnimationFrame(onFrame); 33 | } 34 | public function setBlendingMode(source: Int, destination: Int): Void { 35 | blendSource = source; 36 | blendDestination = destination; 37 | ctx.blendFunc(blendSource, blendDestination); 38 | } 39 | public function onFrame(time: Float) { 40 | var delta = 0.0; 41 | if (previousFrameTime == -1) { 42 | delta = 16; 43 | } else { 44 | delta = time - previousFrameTime; 45 | } 46 | previousFrameTime = time; 47 | draw(delta); 48 | Browser.window.requestAnimationFrame(onFrame); 49 | } 50 | public function draw(delta:Float) { 51 | ctx.viewport(0, 0, ctx.canvas.width, ctx.canvas.height); 52 | ctx.enable(RenderingContext.BLEND); 53 | ctx.enable(RenderingContext.DEPTH_TEST); 54 | ctx.blendFunc(blendSource, blendDestination); 55 | ctx.clearColor(0.2, 0.2, 0.2, 1.0); 56 | ctx.clear(RenderingContext.COLOR_BUFFER_BIT | RenderingContext.DEPTH_BUFFER_BIT); 57 | 58 | } 59 | public function enableDepthTest(): Void { 60 | ctx.enable(RenderingContext.DEPTH_TEST); 61 | } 62 | public function disableDepthTest(): Void { 63 | ctx.disable(RenderingContext.DEPTH_TEST); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/utils/BuildMatrix.hx: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import utils.Transformation.scale; 4 | import utils.Transformation.rotate; 5 | import utils.Transformation.translate; 6 | import VectorMath.Mat4; 7 | import VectorMath.Vec3; 8 | 9 | function buildMatrix(trans: Vec3, rot: Float, scaling: Vec3): Mat4 { 10 | return translate(trans) * rotate(rot, new Vec3(0, 0, 1)) * scale(scaling); 11 | } -------------------------------------------------------------------------------- /src/utils/CalculateTangents.hx: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import externs.Ogl.Vec2; 4 | import externs.Ogl.Vec3; 5 | import js.lib.Float32Array; 6 | import externs.Ply.PlyModel; 7 | 8 | function calculateTangents(model:PlyModel):Float32Array { 9 | final tangents:Array = []; 10 | final indexCount:Int = Std.int(model.indices.value.length / model.indices.size); 11 | final uvs = model.attributes.TEXCOORD_0.value; 12 | final vertices = model.attributes.POSITION.value; 13 | final indices = model.indices.value; 14 | for (i in 0...indexCount - 2) { 15 | if (i % 3 == 0) { 16 | final v0:Vec3 = new Vec3(vertices[indices[i]], vertices[indices[i + 1]], vertices[indices[i + 2]]); 17 | final v1:Vec3 = new Vec3(vertices[indices[i + 3]], vertices[indices[i + 4]], vertices[indices[i + 5]]); 18 | final v2:Vec3 = new Vec3(vertices[indices[i + 6]], vertices[indices[i + 7]], vertices[indices[i + 8]]); 19 | 20 | final uv0:Vec2 = new Vec2(uvs[indices[i]], uvs[indices[i + 1]]); 21 | final uv1:Vec2 = new Vec2(uvs[indices[i + 2]], uvs[indices[i + 3]]); 22 | final uv2:Vec2 = new Vec2(uvs[indices[i + 4]], uvs[indices[i + 5]]); 23 | 24 | final edge1 = v1.clone().sub(v0); 25 | final edge2 = v2.clone().sub(v0); 26 | final dUV1 = uv1.clone().sub(uv0); 27 | final dUV2 = uv2.clone().sub(uv0); 28 | 29 | final f = 1.0 / (dUV1.x * dUV2.y - dUV2.x * dUV1.y); 30 | 31 | final tan:Vec3 = new Vec3(); 32 | tan.x = f * (dUV2.y * edge1.x - dUV1.y * edge2.x); 33 | tan.y = f * (dUV2.y * edge1.y - dUV1.y * edge2.y); 34 | tan.z = f * (dUV2.y * edge1.z - dUV1.y * edge2.z); 35 | tan.normalize(); 36 | 37 | tangents[indices[i]] = tan.clone(); 38 | tangents[indices[i + 1]] = tan.clone(); 39 | tangents[indices[i + 2]] = tan.clone(); 40 | } 41 | } 42 | final result = new Float32Array(tangents.length * 3); 43 | for (i in 0...tangents.length) { 44 | final t = tangents[i]; 45 | result[i] = t.x; 46 | result[i + 1] = t.y; 47 | result[i + 2] = t.z; 48 | } 49 | return result; 50 | } -------------------------------------------------------------------------------- /src/utils/Camera.hx: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import VectorMath.Vec3; 4 | import types.Types.Camera as ICamera; 5 | 6 | class Camera implements ICamera { 7 | public var position: Vec3; 8 | public var rotation: Float; 9 | public function new(position: Vec3, rotation: Float) { 10 | this.position = position; 11 | this.rotation = rotation; 12 | } 13 | } -------------------------------------------------------------------------------- /src/utils/CreatePLYGeometry.hx: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import utils.CalculateTangents.calculateTangents; 4 | import externs.Ogl.CreateGeometryProps; 5 | import externs.Ogl.GL; 6 | import externs.Ply.PlyModel; 7 | import externs.Ogl.Geometry; 8 | 9 | function createPLYGeometry(gl: GL, model: PlyModel): Geometry { 10 | final props: CreateGeometryProps = { 11 | position: { size: model.attributes.POSITION.size, data: model.attributes.POSITION.value }, 12 | }; 13 | if (model.attributes.NORMAL != null) { 14 | props.normal = { size: model.attributes.NORMAL.size, data: model.attributes.NORMAL.value }; 15 | if (model.attributes.TEXCOORD_0 != null && model.indices != null) { 16 | props.tangent = { size: model.attributes.NORMAL.size, data: calculateTangents(model) }; 17 | } 18 | } 19 | if (model.attributes.TEXCOORD_0 != null) { 20 | props.uv = { size: model.attributes.TEXCOORD_0.size, data: model.attributes.TEXCOORD_0.value }; 21 | } 22 | if (model.indices != null) { 23 | props.index = { size: model.indices.size, data: model.indices.value }; 24 | } 25 | return new Geometry(gl, props); 26 | } -------------------------------------------------------------------------------- /src/utils/Degree.hx: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | function toRadians(degree: Float): Float { 4 | return degree * Math.PI / 180; 5 | } -------------------------------------------------------------------------------- /src/utils/DirectionalLight.hx: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import externs.Ogl.Vec3; 4 | 5 | class DirectionalLight { 6 | public var direction: Vec3; 7 | public var color: Vec3; 8 | public var intensity: Float; 9 | public function new(?direction: Vec3, ?color: Vec3, ?intensity: Float) { 10 | this.direction = (direction != null) ? direction : new Vec3(); 11 | this.color = (color != null) ? color : new Vec3(1, 1, 1); 12 | this.intensity = (intensity != null) ? intensity : 1; 13 | } 14 | } 15 | 16 | function getLightDirection(light: DirectionalLight): Vec3 { 17 | return light.direction.clone().negate().normalize(); 18 | } 19 | function getLightColor(light: DirectionalLight): Vec3 { 20 | return light.color.clone().multiply(light.intensity); 21 | } -------------------------------------------------------------------------------- /src/utils/LoadImage.hx: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import js.html.Image; 4 | import js.lib.Promise; 5 | 6 | function loadImage(src: String): Promise { 7 | return new Promise((success, reject) -> { 8 | final img = new Image(); 9 | img.onload = () -> success(img); 10 | img.src = src; 11 | }); 12 | } -------------------------------------------------------------------------------- /src/utils/LoadTexture.hx: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import utils.LoadImage.loadImage; 4 | import externs.Ogl.GL; 5 | import externs.Ogl.TextureProps; 6 | import externs.Ogl.Texture; 7 | 8 | function loadTexture(path:String, gl: GL, ?props: TextureProps):Texture { 9 | final texture = new Texture(gl, props); 10 | loadImage(path).then(img -> { 11 | texture.image = img; 12 | }); 13 | return texture; 14 | } -------------------------------------------------------------------------------- /src/utils/Material.hx: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import js.lib.Float32Array; 4 | import VectorMath.Mat4; 5 | import VectorMath.Vec3; 6 | import VectorMath.Vec2; 7 | import js.html.webgl.UniformLocation; 8 | import VectorMath.Vec4; 9 | import types.Types.IShader; 10 | import js.html.webgl.Program; 11 | import js.html.webgl.RenderingContext; 12 | import js.html.webgl.Shader; 13 | 14 | class Material implements IShader { 15 | private var ctx:RenderingContext; 16 | private var textures: Array = []; 17 | 18 | public var program:Program; 19 | 20 | private var slot = 0; 21 | 22 | public function new(ctx:RenderingContext) { 23 | this.ctx = ctx; 24 | } 25 | 26 | public function load(vert:String, frag:String) { 27 | program = createProgram(ctx, vert, frag); 28 | ctx.linkProgram(program); 29 | } 30 | 31 | public function begin() { 32 | ctx.useProgram(program); 33 | if (textures.length > 0) { 34 | ctx.texParameteri(RenderingContext.TEXTURE_2D, RenderingContext.TEXTURE_WRAP_S, RenderingContext.CLAMP_TO_EDGE); 35 | ctx.texParameteri(RenderingContext.TEXTURE_2D, RenderingContext.TEXTURE_WRAP_T, RenderingContext.CLAMP_TO_EDGE); 36 | ctx.uniform1i(textures[0], slot); 37 | } 38 | } 39 | 40 | public function end() {} 41 | 42 | public function setUniform4f(name: String, v: Vec4): Void { 43 | final location = ctx.getUniformLocation(program, name); 44 | ctx.uniform4f(location, v.x, v.y, v.z, v.w); 45 | } 46 | public function setUniform3f(name: String, v: Vec3): Void { 47 | final location = ctx.getUniformLocation(program, name); 48 | ctx.uniform3f(location, v.x, v.y, v.z); 49 | } 50 | public function setUniform2f(name: String, v: Vec2): Void { 51 | final location = ctx.getUniformLocation(program, name); 52 | ctx.uniform2f(location, v.x, v.y); 53 | } 54 | public function setUniform1f(name: String, f: Float): Void { 55 | final location = ctx.getUniformLocation(program, name); 56 | if (location != null) { 57 | ctx.uniform1f(location, f); 58 | } 59 | } 60 | public function setUniformTexture(name: String, src: String, slot: Int, ?flipY = 1): Void { 61 | this.slot = slot; 62 | new Texture(src, ctx, slot, flipY); 63 | final textureLocation = ctx.getUniformLocation(program, name); 64 | if (textureLocation != null) { 65 | textures.push(textureLocation); 66 | } 67 | } 68 | public function setUniformMatrix4f(name: String, m: Mat4): Void { 69 | final convertedM = new Float32Array(16); 70 | convertedM[0] = m[0].x; 71 | convertedM[1] = m[0].y; 72 | convertedM[2] = m[0].z; 73 | convertedM[3] = m[0].w; 74 | 75 | convertedM[4] = m[1].x; 76 | convertedM[5] = m[1].y; 77 | convertedM[6] = m[1].z; 78 | convertedM[7] = m[1].w; 79 | 80 | convertedM[8] = m[2].x; 81 | convertedM[9] = m[2].y; 82 | convertedM[10] = m[2].z; 83 | convertedM[11] = m[2].w; 84 | 85 | convertedM[12] = m[3].x; 86 | convertedM[13] = m[3].y; 87 | convertedM[14] = m[3].z; 88 | convertedM[15] = m[3].w; 89 | final location = ctx.getUniformLocation(program, name); 90 | if (location != null) { 91 | ctx.uniformMatrix4fv(location, false, convertedM); 92 | } 93 | } 94 | } 95 | 96 | private function createProgram(ctx:RenderingContext, vert:String, frag:String):Program { 97 | final program = ctx.createProgram(); 98 | ctx.attachShader(program, createShader(ctx, RenderingContext.VERTEX_SHADER, vert)); 99 | ctx.attachShader(program, createShader(ctx, RenderingContext.FRAGMENT_SHADER, frag)); 100 | return program; 101 | } 102 | 103 | private function createShader(ctx:RenderingContext, type:Int, source:String):Shader { 104 | final shader = ctx.createShader(type); 105 | ctx.shaderSource(shader, source); 106 | ctx.compileShader(shader); 107 | return shader; 108 | } 109 | -------------------------------------------------------------------------------- /src/utils/Matrix.hx: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import VectorMath.Mat4; 4 | 5 | function inverse(m:Mat4):Mat4 { 6 | final out = new Mat4( 7 | 1,0,0,0, 8 | 0,1,0,0, 9 | 0,0,1,0, 10 | 0,0,0,1 11 | ); 12 | final det = determinant(m, 4); 13 | for (row in 0...4) { 14 | for (column in 0...4) { 15 | out[column][row] = cofactor(m, row, column, 4) / det; 16 | } 17 | } 18 | return out; 19 | } 20 | 21 | function determinant(m:Mat4, length: Int):Float { 22 | var det:Float = 0; 23 | if (length == 2) { 24 | det = m[0][0] * m[1][1] - m[0][1] * m[1][0]; 25 | } else { 26 | for (column in 0...length) { 27 | det += m[0][column] * cofactor(m, 0, column, length); 28 | } 29 | } 30 | return det; 31 | } 32 | 33 | function cofactor(m:Mat4, row:UInt, column:UInt, length: Int):Float { 34 | final minorValue = minor(m, row, column, length); 35 | 36 | return (row + column) % 2 == 0 ? minorValue : minorValue * -1; 37 | } 38 | 39 | function minor(m:Mat4, row:UInt, column:UInt, length: Int):Float { 40 | return determinant(submatrix(m, row, column, length - 1), length - 1); 41 | } 42 | 43 | function submatrix(m:Mat4, rowToRemove:UInt, columnToRemove:UInt, length: Int):Mat4 { 44 | final out = new Mat4( 45 | 1,0,0,0, 46 | 0,1,0,0, 47 | 0,0,1,0, 48 | 0,0,0,1 49 | ); 50 | var rows: Int; 51 | var columns: Int; 52 | if (length == 4) { 53 | rows = 3; 54 | columns = 3; 55 | } else { 56 | rows = 2; 57 | columns = 2; 58 | } 59 | var currentRow = 0; 60 | var currentColumn = 0; 61 | for (row in 0...rows) { 62 | if (row != rowToRemove) { 63 | currentColumn = 0; 64 | for (column in 0...columns) { 65 | if (column != columnToRemove) { 66 | out[currentRow][currentColumn] = m[row][column]; 67 | currentColumn++; 68 | } 69 | } 70 | currentRow++; 71 | } 72 | } 73 | return out; 74 | } -------------------------------------------------------------------------------- /src/utils/Mesh3D.hx: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import js.html.webgl.Buffer; 4 | import VectorMath.Vec2; 5 | import VectorMath.Vec4; 6 | import VectorMath.Vec3; 7 | import js.html.webgl.Program; 8 | import js.lib.Float32Array; 9 | import js.lib.Uint16Array; 10 | import js.html.webgl.RenderingContext; 11 | import types.Types.Mesh; 12 | 13 | class Mesh3D implements Mesh { 14 | private var ctx:RenderingContext; 15 | private var vertices:Array; 16 | private var indicies:Array; 17 | private var uv:Array; 18 | private var colors:Array; 19 | private var shader:Program; 20 | private var indiciesBuffer: Null; 21 | private var vertexPositionBuffer: Null; 22 | private var vertexColorBuffer: Null; 23 | private var uvBuffer: Null; 24 | 25 | public function new(ctx:RenderingContext, shader:Program) { 26 | this.ctx = ctx; 27 | this.shader = shader; 28 | vertices = []; 29 | colors = []; 30 | indicies = []; 31 | uv = []; 32 | }; 33 | 34 | public function addVertex(vertex: Vec3):Void { 35 | vertices.push(vertex.x); 36 | vertices.push(vertex.y); 37 | vertices.push(vertex.z); 38 | } 39 | public function setVertex(index: Int, v:Vec3):Void { 40 | vertices[index] = v.x; 41 | vertices[index + 1] = v.y; 42 | vertices[index + 2] = v.z; 43 | } 44 | public function getVertex(index: Int):Vec3 { 45 | return new Vec3( 46 | vertices[index], 47 | vertices[index + 1], 48 | vertices[index + 2] 49 | ); 50 | } 51 | public function addColor(color: Vec4): Void { 52 | colors.push(color.x); 53 | colors.push(color.y); 54 | colors.push(color.z); 55 | colors.push(color.w); 56 | } 57 | public function addIndicies(indicies: Array): Void { 58 | this.indicies = this.indicies.concat(indicies); 59 | } 60 | public function addTexCoord(c: Vec2): Void { 61 | uv.push(c.x); 62 | uv.push(c.y); 63 | } 64 | public function build():Void { 65 | final positionAttriuteLocation = ctx.getAttribLocation(shader, "position"); 66 | vertexPositionBuffer = ctx.createBuffer(); 67 | ctx.enableVertexAttribArray(positionAttriuteLocation); 68 | ctx.bindBuffer(RenderingContext.ARRAY_BUFFER, vertexPositionBuffer); 69 | ctx.vertexAttribPointer(positionAttriuteLocation, 3, RenderingContext.FLOAT, false, 0, 0); 70 | ctx.bufferData(RenderingContext.ARRAY_BUFFER, new Float32Array(vertices), RenderingContext.STATIC_DRAW); 71 | 72 | final colorAttriuteLocation = ctx.getAttribLocation(shader, "color"); 73 | if (colorAttriuteLocation >= 0) { 74 | vertexColorBuffer = ctx.createBuffer(); 75 | ctx.enableVertexAttribArray(colorAttriuteLocation); 76 | ctx.bindBuffer(RenderingContext.ARRAY_BUFFER, vertexColorBuffer); 77 | ctx.vertexAttribPointer(colorAttriuteLocation, 4, RenderingContext.FLOAT, false, 0, 0); 78 | ctx.bufferData(RenderingContext.ARRAY_BUFFER, new Float32Array(colors), RenderingContext.STATIC_DRAW); 79 | } 80 | final uvAttriuteLocation = ctx.getAttribLocation(shader, "uv"); 81 | if (uvAttriuteLocation >= 0) { 82 | uvBuffer = ctx.createBuffer(); 83 | ctx.enableVertexAttribArray(uvAttriuteLocation); 84 | ctx.bindBuffer(RenderingContext.ARRAY_BUFFER, uvBuffer); 85 | ctx.vertexAttribPointer(uvAttriuteLocation, 2, RenderingContext.FLOAT, false, 0, 0); 86 | ctx.bufferData(RenderingContext.ARRAY_BUFFER, new Float32Array(uv), RenderingContext.STATIC_DRAW); 87 | } 88 | if (indicies.length > 0) { 89 | indiciesBuffer = ctx.createBuffer(); 90 | ctx.bindBuffer(RenderingContext.ELEMENT_ARRAY_BUFFER, indiciesBuffer); 91 | ctx.bufferData(RenderingContext.ELEMENT_ARRAY_BUFFER, new Uint16Array(indicies), RenderingContext.STATIC_DRAW); 92 | } 93 | } 94 | 95 | public function draw():Void { 96 | if (vertexPositionBuffer != null) { 97 | ctx.enableVertexAttribArray(ctx.getAttribLocation(shader, "position")); 98 | ctx.bindBuffer(RenderingContext.ARRAY_BUFFER, vertexPositionBuffer); 99 | ctx.vertexAttribPointer(ctx.getAttribLocation(shader, "position"), 3, RenderingContext.FLOAT, false, 0, 0); 100 | ctx.bufferData(RenderingContext.ARRAY_BUFFER, new Float32Array(vertices), RenderingContext.STATIC_DRAW); 101 | } 102 | if (vertexColorBuffer != null) { 103 | ctx.bindBuffer(RenderingContext.ARRAY_BUFFER, vertexColorBuffer); 104 | ctx.bufferData(RenderingContext.ARRAY_BUFFER, new Float32Array(colors), RenderingContext.STATIC_DRAW); 105 | } 106 | if (uvBuffer != null) { 107 | ctx.enableVertexAttribArray(ctx.getAttribLocation(shader, "uv")); 108 | ctx.bindBuffer(RenderingContext.ARRAY_BUFFER, uvBuffer); 109 | ctx.vertexAttribPointer(ctx.getAttribLocation(shader, "uv"), 2, RenderingContext.FLOAT, false, 0, 0); 110 | ctx.bufferData(RenderingContext.ARRAY_BUFFER, new Float32Array(uv), RenderingContext.STATIC_DRAW); 111 | } 112 | if (indiciesBuffer != null) { 113 | ctx.bindBuffer(RenderingContext.ELEMENT_ARRAY_BUFFER, indiciesBuffer); 114 | ctx.bufferData(RenderingContext.ELEMENT_ARRAY_BUFFER, new Uint16Array(indicies), RenderingContext.STATIC_DRAW); 115 | ctx.drawElements(RenderingContext.TRIANGLES, indicies.length, RenderingContext.UNSIGNED_SHORT, 0); 116 | } else { 117 | ctx.drawArrays(RenderingContext.TRIANGLES, 0, Std.int(vertices.length / 3)); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/utils/OglBase.hx: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import js.html.webgl.PowerPreference; 4 | import externs.Ogl.Renderer; 5 | import externs.Ogl.Camera; 6 | import externs.Ogl.GL; 7 | import externs.Ogl.Transform; 8 | import externs.Ogl.Vec3; 9 | import js.Browser; 10 | 11 | class OglBase { 12 | private var renderer: Renderer; 13 | private var gl: GL; 14 | private var camera: Camera; 15 | private var scene: Transform; 16 | public function new() { 17 | createEngine(); 18 | setup(); 19 | } 20 | private function createEngine(): Void { 21 | renderer = new Renderer({ 22 | dpr: 2, 23 | antialias: true, 24 | powerPreference: PowerPreference.HIGH_PERFORMANCE 25 | }); 26 | gl = renderer.gl; 27 | Browser.document.body.appendChild(gl.canvas); 28 | 29 | gl.clearColor(1, 1, 1, 1); 30 | 31 | camera = new Camera(gl, { fov: 35 }); 32 | camera.position.set(0, 0, 15); 33 | camera.lookAt(new Vec3(0, 0, 0)); 34 | 35 | Browser.window.addEventListener("resize", resize, false); 36 | 37 | scene = new Transform(); 38 | 39 | resize(); 40 | } 41 | private function resize(): Void { 42 | renderer.setSize(Browser.window.innerWidth, Browser.window.innerHeight); 43 | camera.perspective({ aspect: gl.canvas.width / gl.canvas.height }); 44 | } 45 | private function onFrame(dt: Float): Void { 46 | renderer.render({ scene: scene , camera: camera }); 47 | Browser.window.requestAnimationFrame(onFrame); 48 | } 49 | private function setup():Void { 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/utils/Texture.hx: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import js.lib.Uint8Array; 4 | import js.Browser; 5 | import js.html.webgl.RenderingContext; 6 | 7 | class Texture { 8 | public function new(src: String, ctx: RenderingContext, index: Int, flipY: Int) { 9 | final texture = ctx.createTexture(); 10 | ctx.activeTexture(RenderingContext.TEXTURE0 + index); 11 | ctx.bindTexture(RenderingContext.TEXTURE_2D, texture); 12 | ctx.pixelStorei(RenderingContext.UNPACK_FLIP_Y_WEBGL, flipY); 13 | ctx.texImage2D(RenderingContext.TEXTURE_2D, 0, RenderingContext.RGBA, 1, 1, 0, RenderingContext.RGBA, RenderingContext.UNSIGNED_BYTE, 14 | new Uint8Array([0, 0, 0, 255])); 15 | final img = Browser.document.createImageElement(); 16 | img.src = src; 17 | img.addEventListener("load", () -> { 18 | ctx.activeTexture(RenderingContext.TEXTURE0 + index); 19 | ctx.bindTexture(RenderingContext.TEXTURE_2D, texture); 20 | ctx.pixelStorei(RenderingContext.UNPACK_FLIP_Y_WEBGL, flipY); 21 | ctx.texImage2D(RenderingContext.TEXTURE_2D, 0, RenderingContext.RGBA, RenderingContext.RGBA, RenderingContext.UNSIGNED_BYTE, img); 22 | ctx.generateMipmap(RenderingContext.TEXTURE_2D); 23 | }); 24 | } 25 | } -------------------------------------------------------------------------------- /src/utils/Transformation.hx: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import VectorMath.Vec3; 4 | import VectorMath.Mat4; 5 | 6 | function translate(v: Vec3): Mat4 { 7 | return new Mat4( 8 | 1, 0, 0, v.x, 9 | 0, 1, 0, v.y, 10 | 0, 0, 1, v.z, 11 | 0, 0, 0, 1 12 | ); 13 | } 14 | 15 | function scale(v: Vec3): Mat4 { 16 | return new Mat4( 17 | v.x, 0, 0, 0, 18 | 0, v.y, 0, 0, 19 | 0, 0, v.z, 0, 20 | 0, 0, 0, 1 21 | ); 22 | } 23 | 24 | function rotate(radians: Float, axis: Vec3): Mat4 { 25 | var m = new Mat4( 26 | 1, 0, 0, 0, 27 | 0, 1, 0, 0, 28 | 0, 0, 1, 0, 29 | 0, 0, 0, 1 30 | ); 31 | if (axis.x > 0) { 32 | m = m * rotateX(radians); 33 | } 34 | if (axis.y > 0) { 35 | m = m * rotateY(radians); 36 | } 37 | if (axis.z > 0) { 38 | m = m * rotateZ(radians); 39 | } 40 | return m; 41 | } 42 | 43 | private function rotateX(radians: Float): Mat4 { 44 | return new Mat4( 45 | 1, 0, 0, 0, 46 | 0, Math.cos(radians), -Math.sin(radians), 0, 47 | 0, Math.sin(radians), Math.cos(radians), 0, 48 | 0, 0, 0, 1 49 | ); 50 | } 51 | private function rotateY(radians: Float): Mat4 { 52 | return new Mat4( 53 | Math.cos(radians), 0, Math.sin(radians), 0, 54 | 0, 1, 0, 0, 55 | -Math.sin(radians), 0, Math.cos(radians), 0, 56 | 0, 0, 0, 1 57 | ); 58 | } 59 | private function rotateZ(radians: Float): Mat4 { 60 | return new Mat4( 61 | Math.cos(radians), -Math.sin(radians), 0, 0, 62 | Math.sin(radians), Math.cos(radians), 0, 0, 63 | 0, 0, 1, 0, 64 | 0, 0, 0, 1 65 | ); 66 | } -------------------------------------------------------------------------------- /src/utils/ViewMatrix.hx: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import VectorMath.Vec3; 4 | import utils.BuildMatrix.buildMatrix; 5 | import utils.Matrix.inverse; 6 | import types.Types.Camera; 7 | import VectorMath.Mat4; 8 | 9 | function buildViewMatrix(camera: Camera): Mat4 { 10 | return inverse(buildMatrix(camera.position, camera.rotation, new Vec3(1, 1, 1))); 11 | } -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | 4 | module.exports = { 5 | mode: 'development', 6 | devtool: 'source-map', 7 | entry: './build.hxml', 8 | output: { 9 | filename: 'main.js', 10 | path: path.resolve(__dirname, 'bin'), 11 | }, 12 | module: { 13 | rules: [ 14 | { 15 | test: /\.hxml$/, 16 | loader: 'haxe-loader', 17 | options: { 18 | debug: true 19 | } 20 | }, 21 | { 22 | test: /\.glsl$/, 23 | loader: 'webpack-glsl-loader' 24 | }, 25 | { 26 | test: /\.(png|jpe?g|gif|ply)$/i, 27 | use: [ 28 | { 29 | loader: 'file-loader', 30 | options: { 31 | esModule: false, 32 | }, 33 | }, 34 | ], 35 | }, 36 | ] 37 | }, 38 | plugins: [ 39 | new HtmlWebpackPlugin({ 40 | template: './bin/index.html' 41 | }) 42 | ], 43 | devServer: { 44 | compress: true, 45 | port: 4444, 46 | overlay: true, 47 | hot: true, 48 | disableHostCheck: true 49 | } 50 | } --------------------------------------------------------------------------------