├── .gitignore ├── .gitmodules ├── .vscode └── launch.json ├── Assets ├── BasicGeometry │ ├── arrow.obj │ ├── cube.obj │ ├── quad_nouv.obj │ ├── sphere.obj │ ├── suzanne.obj │ └── torus.obj ├── Bones │ ├── CharacterRunning.dae │ ├── CharacterRunning.ogex │ └── CharacterTexture.png ├── Common │ ├── KenPixel.ttf │ └── index.html ├── FlowField │ ├── flowField.frag.glsl │ └── noise.frag.glsl ├── GameAssets │ └── SimpleCarGame │ │ ├── carSedan.mtl │ │ ├── carSedan.obj │ │ ├── tree.mtl │ │ └── tree.obj ├── GameOfLife │ ├── gameOfLife.frag.glsl │ ├── gameOfLifeMathOnly.frag.glsl │ └── gameOfLifeNoBranches.frag.glsl ├── ImageSlideshow │ ├── Images │ │ ├── TestImage001.png │ │ └── TestImage002.png │ └── Shaders │ │ └── imageFade.frag.glsl ├── Images │ ├── Lenna.png │ └── Test.png ├── Models │ ├── carFormula.mtl │ └── carFormula.obj ├── PostProcessingShaders │ ├── postBlackAndWhite.frag.glsl │ ├── postBlur.frag.glsl │ ├── postColorCorrection.frag.glsl │ ├── postColorQuantization.frag.glsl │ ├── postFXAA.frag.glsl │ ├── postGaussianBlur.frag.glsl │ └── postPixelate.frag.glsl ├── Shaders │ ├── colored.frag.glsl │ ├── colored.vert.glsl │ ├── coloredBones.vert.glsl │ ├── directionalLighting.frag.glsl │ ├── directionalLighting.vert.glsl │ ├── normals.frag.glsl │ ├── normals.vert.glsl │ ├── simple.frag.glsl │ ├── simple.vert.glsl │ ├── striped.frag.glsl │ ├── testColored.vert.glsl │ ├── textureCutoffMesh.frag.glsl │ ├── textured.frag.glsl │ ├── textured.vert.glsl │ ├── texturedBillboard.frag.glsl │ ├── texturedBillboard.vert.glsl │ ├── texturedBones.vert.glsl │ ├── tinted.frag.glsl │ ├── tinted.vert.glsl │ └── transition.frag.glsl └── Transitions │ ├── FadeTextureBottomTop.png │ ├── FadeTextureCenterCircular.png │ ├── FadeTextureCounterClockwise.png │ ├── FadeTextureMiddleHorizontal.png │ └── FadeTextureMiddleVertical.png ├── README.md ├── Source ├── Main.hx ├── MeshType.hx ├── gameChallenges │ └── SimpleCarGame.hx ├── replicationChallenges │ ├── LeParcNoodles.hx │ ├── OpArtCircles01.hx │ └── SineCubesState.hx ├── shaderChallenges │ ├── FlowFieldShader.hx │ ├── GameOfLifeShader.hx │ ├── PostProcessingShader.hx │ ├── TextureCutoffMeshShader.hx │ └── TransitionShaders.hx ├── simpleChallenges │ ├── SimpleBones.hx │ ├── SimpleImageSlideshow.hx │ └── SimpleLighting.hx └── utils │ ├── DemoMeshes.hx │ └── ZUIUtils.hx ├── build.bat ├── buildAndroid.bat ├── buildAndroidNative.bat ├── buildHTML5.bat ├── buildKrom.bat ├── buildWindows.bat ├── initKha.bat ├── initLibraries.bat ├── khafile.js ├── korefile.js └── updateKha.bat /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | /npm-debug.log -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Kha"] 2 | path = Kha 3 | url = https://github.com/Kode/Kha 4 | [submodule "Libraries/zui"] 5 | path = Libraries/zui 6 | url = https://github.com/armory3d/zui.git 7 | [submodule "Libraries/kext"] 8 | path = Libraries/kext 9 | url = https://github.com/JuanRinaudo/kext.git 10 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "type": "electron", 5 | "request": "launch", 6 | "name": "Kha: HTML5", 7 | "appDir": "${workspaceFolder}/build/debug-html5", 8 | "cwd": "${workspaceFolder}/build/debug-html5", 9 | "sourceMaps": true, 10 | "preLaunchTask": "Kha: Build for Debug HTML5", 11 | "internalConsoleOptions": "openOnSessionStart" 12 | }, 13 | { 14 | "type": "krom", 15 | "request": "launch", 16 | "name": "Kha: Krom", 17 | "preLaunchTask": "Kha: Build for Krom", 18 | "internalConsoleOptions": "openOnSessionStart" 19 | } 20 | ], 21 | "compounds": [], 22 | "version": "0.2.0" 23 | } -------------------------------------------------------------------------------- /Assets/BasicGeometry/arrow.obj: -------------------------------------------------------------------------------- 1 | # Blender v2.79 (sub 0) OBJ File: 'Arrow.blend' 2 | # www.blender.org 3 | mtllib arrowsmartfixed.mtl 4 | o Cube 5 | v 0.500000 -1.000000 -1.000000 6 | v 0.500000 -1.000000 1.000000 7 | v -0.500000 -1.000000 1.000000 8 | v -0.500000 -1.000000 -1.000000 9 | v 0.500000 1.000000 -0.999999 10 | v 0.500000 1.000000 1.000001 11 | v -0.500000 1.000000 1.000000 12 | v -0.500000 1.000000 -1.000000 13 | v 0.500000 2.500000 0.000001 14 | v -0.500000 2.500000 0.000000 15 | v 0.499999 1.000000 2.000000 16 | v -0.500000 1.000000 2.000000 17 | v 0.500000 1.000000 -2.000000 18 | v -0.500000 1.000000 -2.000000 19 | vt 0.422535 0.507042 20 | vt 0.281690 0.788732 21 | vt 0.281690 0.507042 22 | vt 0.422535 0.788733 23 | vt 0.563380 0.929577 24 | vt 0.422535 0.929578 25 | vt 0.859375 0.445312 26 | vt 0.578125 0.164062 27 | vt 0.859375 0.164062 28 | vt 0.140845 0.507042 29 | vt 0.140845 0.788732 30 | vt 0.421875 0.281250 31 | vt 0.140625 0.000000 32 | vt 0.421875 0.000000 33 | vt 0.281690 0.788732 34 | vt 0.422535 0.957747 35 | vt 0.281690 0.957747 36 | vt 0.578125 0.445312 37 | vt 0.718750 0.656250 38 | vt 0.140625 0.281250 39 | vt 0.281250 0.492188 40 | vt 0.000000 0.281250 41 | vt 0.562500 0.281250 42 | vt 0.437500 0.445312 43 | vt 0.140845 0.788733 44 | vt 0.281690 1.000000 45 | vt 0.140845 1.000000 46 | vt 0.140845 0.507042 47 | vt 0.000000 0.859155 48 | vt 0.000000 0.507042 49 | vt 0.563380 0.647887 50 | vt 0.422535 0.788732 51 | vt 0.422535 0.647887 52 | vt 1.000000 0.445312 53 | vt 0.422535 0.788732 54 | vt 0.563380 0.788732 55 | vt 0.281690 0.507042 56 | vt 0.422535 0.788732 57 | vt 0.281690 0.788732 58 | vt 0.140845 0.859155 59 | vt 0.563380 0.788732 60 | vn 0.0000 -1.0000 0.0000 61 | vn 1.0000 -0.0000 0.0000 62 | vn 0.0000 -0.0000 1.0000 63 | vn -1.0000 -0.0000 -0.0000 64 | vn 0.0000 0.0000 -1.0000 65 | vn -0.0000 0.8000 0.6000 66 | vn 0.0000 0.8000 -0.6000 67 | usemtl Material 68 | s off 69 | f 1/1/1 3/2/1 4/3/1 70 | f 6/4/1 12/5/1 7/6/1 71 | f 5/7/2 2/8/2 1/9/2 72 | f 6/10/3 3/2/3 2/11/3 73 | f 7/12/4 4/13/4 3/14/4 74 | f 1/15/5 8/16/5 5/17/5 75 | f 6/18/2 5/7/2 9/19/2 76 | f 8/20/4 7/12/4 10/21/4 77 | f 8/20/4 10/21/4 14/22/4 78 | f 10/21/4 7/12/4 12/23/4 79 | f 6/18/2 9/19/2 11/24/2 80 | f 9/25/6 12/26/6 11/27/6 81 | f 9/28/7 14/29/7 10/30/7 82 | f 8/31/1 13/32/1 5/33/1 83 | f 9/19/2 5/7/2 13/34/2 84 | f 1/1/1 2/35/1 3/2/1 85 | f 6/4/1 11/36/1 12/5/1 86 | f 5/7/2 6/18/2 2/8/2 87 | f 6/10/3 7/37/3 3/2/3 88 | f 7/12/4 8/20/4 4/13/4 89 | f 1/15/5 4/38/5 8/16/5 90 | f 9/25/6 10/39/6 12/26/6 91 | f 9/28/7 13/40/7 14/29/7 92 | f 8/31/1 14/41/1 13/32/1 93 | -------------------------------------------------------------------------------- /Assets/BasicGeometry/cube.obj: -------------------------------------------------------------------------------- 1 | # Blender v2.79 (sub 0) OBJ File: '' 2 | # www.blender.org 3 | mtllib cube.mtl 4 | o Cube_Cube.002 5 | v -1.000000 -1.000000 1.000000 6 | v -1.000000 1.000000 1.000000 7 | v -1.000000 -1.000000 -1.000000 8 | v -1.000000 1.000000 -1.000000 9 | v 1.000000 -1.000000 1.000000 10 | v 1.000000 1.000000 1.000000 11 | v 1.000000 -1.000000 -1.000000 12 | v 1.000000 1.000000 -1.000000 13 | vt 0.625000 0.000000 14 | vt 0.375000 0.250000 15 | vt 0.375000 0.000000 16 | vt 0.625000 0.250000 17 | vt 0.375000 0.500000 18 | vt 0.625000 0.500000 19 | vt 0.375000 0.750000 20 | vt 0.625000 0.750000 21 | vt 0.375000 1.000000 22 | vt 0.125000 0.750000 23 | vt 0.125000 0.500000 24 | vt 0.875000 0.500000 25 | vt 0.625000 1.000000 26 | vt 0.875000 0.750000 27 | vn -0.5773 0.5773 0.5773 28 | vn -0.5773 -0.5773 -0.5773 29 | vn -0.5773 -0.5773 0.5773 30 | vn -0.5773 0.5773 -0.5773 31 | vn 0.5773 -0.5773 -0.5773 32 | vn 0.5773 0.5773 -0.5773 33 | vn 0.5773 -0.5773 0.5773 34 | vn 0.5773 0.5773 0.5773 35 | usemtl None 36 | s 1 37 | f 2/1/1 3/2/2 1/3/3 38 | f 4/4/4 7/5/5 3/2/2 39 | f 8/6/6 5/7/7 7/5/5 40 | f 6/8/8 1/9/3 5/7/7 41 | f 7/5/5 1/10/3 3/11/2 42 | f 4/12/4 6/8/8 8/6/6 43 | f 2/1/1 4/4/4 3/2/2 44 | f 4/4/4 8/6/6 7/5/5 45 | f 8/6/6 6/8/8 5/7/7 46 | f 6/8/8 2/13/1 1/9/3 47 | f 7/5/5 5/7/7 1/10/3 48 | f 4/12/4 2/14/1 6/8/8 49 | -------------------------------------------------------------------------------- /Assets/BasicGeometry/quad_nouv.obj: -------------------------------------------------------------------------------- 1 | # Blender v2.79 (sub 0) OBJ File: '' 2 | # www.blender.org 3 | mtllib quad_nouv.mtl 4 | o Plane_Plane.004 5 | v -1.000000 0.000000 1.000000 6 | v 1.000000 0.000000 1.000000 7 | v -1.000000 0.000000 -1.000000 8 | v 1.000000 0.000000 -1.000000 9 | vn 0.0000 1.0000 0.0000 10 | usemtl None 11 | s 1 12 | f 2//1 3//1 1//1 13 | f 2//1 4//1 3//1 14 | -------------------------------------------------------------------------------- /Assets/BasicGeometry/sphere.obj: -------------------------------------------------------------------------------- 1 | # Blender v2.79 (sub 0) OBJ File: '' 2 | # www.blender.org 3 | mtllib sphere.mtl 4 | o Sphere_Sphere.002 5 | v 0.000000 0.980785 -0.195090 6 | v 0.000000 0.923880 -0.382683 7 | v 0.000000 0.831470 -0.555570 8 | v 0.000000 0.555570 -0.831470 9 | v 0.000000 0.382683 -0.923880 10 | v 0.000000 0.000000 -1.000000 11 | v 0.000000 -0.382683 -0.923880 12 | v 0.000000 -0.555570 -0.831470 13 | v 0.000000 -0.831470 -0.555570 14 | v 0.000000 -0.923880 -0.382683 15 | v 0.000000 -0.980785 -0.195090 16 | v 0.000000 -1.000000 0.000000 17 | v 0.074658 0.980785 -0.180240 18 | v 0.146447 0.923880 -0.353553 19 | v 0.212608 0.831470 -0.513280 20 | v 0.270598 0.707107 -0.653281 21 | v 0.318190 0.555570 -0.768178 22 | v 0.353554 0.382683 -0.853553 23 | v 0.375330 0.195090 -0.906127 24 | v 0.382684 0.000000 -0.923880 25 | v 0.375330 -0.195090 -0.906127 26 | v 0.353554 -0.382683 -0.853553 27 | v 0.318190 -0.555570 -0.768178 28 | v 0.270598 -0.707107 -0.653281 29 | v 0.212608 -0.831470 -0.513280 30 | v 0.146447 -0.923880 -0.353553 31 | v 0.074658 -0.980785 -0.180240 32 | v 0.137950 0.980785 -0.137950 33 | v 0.270598 0.923880 -0.270598 34 | v 0.392848 0.831470 -0.392847 35 | v 0.500000 0.707107 -0.500000 36 | v 0.587938 0.555570 -0.587938 37 | v 0.653282 0.382683 -0.653281 38 | v 0.693520 0.195090 -0.693520 39 | v 0.707107 0.000000 -0.707107 40 | v 0.693520 -0.195090 -0.693520 41 | v 0.653282 -0.382683 -0.653281 42 | v 0.587938 -0.555570 -0.587938 43 | v 0.500000 -0.707107 -0.500000 44 | v 0.392848 -0.831470 -0.392847 45 | v 0.270598 -0.923880 -0.270598 46 | v 0.137950 -0.980785 -0.137949 47 | v 0.180240 0.980785 -0.074658 48 | v 0.353554 0.923880 -0.146446 49 | v 0.513280 0.831470 -0.212607 50 | v 0.653282 0.707107 -0.270598 51 | v 0.768178 0.555570 -0.318189 52 | v 0.853554 0.382683 -0.353553 53 | v 0.906128 0.195090 -0.375330 54 | v 0.923880 0.000000 -0.382683 55 | v 0.906128 -0.195090 -0.375330 56 | v 0.853554 -0.382683 -0.353553 57 | v 0.768178 -0.555570 -0.318189 58 | v 0.653282 -0.707107 -0.270598 59 | v 0.513280 -0.831470 -0.212607 60 | v 0.353554 -0.923880 -0.146446 61 | v 0.180240 -0.980785 -0.074658 62 | v 0.195091 0.980785 0.000000 63 | v 0.382684 0.923880 0.000000 64 | v 0.555571 0.831470 0.000000 65 | v 0.707107 0.707107 0.000000 66 | v 0.831470 0.555570 0.000000 67 | v 0.923880 0.382683 0.000000 68 | v 0.980786 0.195090 0.000000 69 | v 1.000000 0.000000 0.000000 70 | v 0.980786 -0.195090 0.000000 71 | v 0.923880 -0.382683 0.000000 72 | v 0.831470 -0.555570 0.000000 73 | v 0.707107 -0.707107 0.000000 74 | v 0.555570 -0.831470 0.000000 75 | v 0.382684 -0.923880 0.000000 76 | v 0.195090 -0.980785 0.000000 77 | v 0.180240 0.980785 0.074658 78 | v 0.353554 0.923880 0.146447 79 | v 0.513280 0.831470 0.212608 80 | v 0.653282 0.707107 0.270599 81 | v 0.768178 0.555570 0.318190 82 | v 0.853554 0.382683 0.353554 83 | v 0.906128 0.195090 0.375331 84 | v 0.923880 0.000000 0.382684 85 | v 0.906128 -0.195090 0.375331 86 | v 0.853554 -0.382683 0.353554 87 | v 0.768178 -0.555570 0.318190 88 | v 0.653282 -0.707107 0.270599 89 | v 0.513280 -0.831470 0.212608 90 | v 0.353553 -0.923880 0.146447 91 | v 0.180240 -0.980785 0.074658 92 | v 0.137950 0.980785 0.137950 93 | v 0.270598 0.923880 0.270599 94 | v 0.392848 0.831470 0.392848 95 | v 0.500000 0.707107 0.500000 96 | v 0.587938 0.555570 0.587938 97 | v 0.653282 0.382683 0.653282 98 | v 0.693520 0.195090 0.693520 99 | v 0.707107 0.000000 0.707107 100 | v 0.693520 -0.195090 0.693520 101 | v 0.653282 -0.382683 0.653282 102 | v 0.587938 -0.555570 0.587938 103 | v 0.500000 -0.707107 0.500000 104 | v 0.392848 -0.831470 0.392848 105 | v 0.270598 -0.923880 0.270599 106 | v 0.137950 -0.980785 0.137950 107 | v 0.074658 0.980785 0.180241 108 | v 0.146447 0.923880 0.353554 109 | v 0.212608 0.831470 0.513281 110 | v 0.270598 0.707107 0.653282 111 | v 0.318190 0.555570 0.768178 112 | v 0.353553 0.382683 0.853554 113 | v 0.375330 0.195090 0.906128 114 | v 0.382683 0.000000 0.923880 115 | v 0.375330 -0.195090 0.906128 116 | v 0.353553 -0.382683 0.853554 117 | v 0.318190 -0.555570 0.768178 118 | v 0.270598 -0.707107 0.653282 119 | v 0.212607 -0.831470 0.513281 120 | v 0.146447 -0.923880 0.353554 121 | v 0.074658 -0.980785 0.180240 122 | v -0.000000 0.980785 0.195091 123 | v -0.000000 0.923880 0.382684 124 | v -0.000000 0.831470 0.555571 125 | v -0.000000 0.707107 0.707107 126 | v -0.000000 0.555570 0.831470 127 | v -0.000000 0.382683 0.923880 128 | v -0.000000 0.195090 0.980786 129 | v -0.000000 0.000000 1.000000 130 | v -0.000000 -0.195090 0.980786 131 | v -0.000000 -0.382683 0.923880 132 | v -0.000000 -0.555570 0.831470 133 | v -0.000000 -0.707107 0.707107 134 | v -0.000000 -0.831470 0.555571 135 | v -0.000000 -0.923880 0.382684 136 | v -0.000000 -0.980785 0.195091 137 | v -0.000000 1.000000 0.000001 138 | v -0.074658 0.980785 0.180241 139 | v -0.146447 0.923880 0.353554 140 | v -0.212608 0.831470 0.513280 141 | v -0.270598 0.707107 0.653282 142 | v -0.318190 0.555570 0.768178 143 | v -0.353554 0.382683 0.853554 144 | v -0.375330 0.195090 0.906128 145 | v -0.382684 0.000000 0.923880 146 | v -0.375330 -0.195090 0.906128 147 | v -0.353554 -0.382683 0.853554 148 | v -0.318190 -0.555570 0.768178 149 | v -0.270598 -0.707107 0.653282 150 | v -0.212608 -0.831470 0.513280 151 | v -0.146447 -0.923880 0.353554 152 | v -0.074658 -0.980785 0.180240 153 | v -0.137950 0.980785 0.137950 154 | v -0.270598 0.923880 0.270598 155 | v -0.392848 0.831470 0.392848 156 | v -0.500000 0.707107 0.500000 157 | v -0.587938 0.555570 0.587938 158 | v -0.653282 0.382683 0.653282 159 | v -0.693520 0.195090 0.693520 160 | v -0.707107 0.000000 0.707107 161 | v -0.693520 -0.195090 0.693520 162 | v -0.653282 -0.382683 0.653282 163 | v -0.587938 -0.555570 0.587938 164 | v -0.500000 -0.707107 0.500000 165 | v -0.392848 -0.831470 0.392848 166 | v -0.270598 -0.923880 0.270598 167 | v -0.137950 -0.980785 0.137950 168 | v -0.180240 0.980785 0.074658 169 | v -0.353554 0.923880 0.146447 170 | v -0.513280 0.831470 0.212608 171 | v -0.653282 0.707107 0.270598 172 | v -0.768178 0.555570 0.318190 173 | v -0.853554 0.382683 0.353553 174 | v -0.906127 0.195090 0.375330 175 | v -0.923880 0.000000 0.382683 176 | v -0.906127 -0.195090 0.375330 177 | v -0.853554 -0.382683 0.353553 178 | v -0.768178 -0.555570 0.318190 179 | v -0.653282 -0.707107 0.270598 180 | v -0.513280 -0.831470 0.212608 181 | v -0.353554 -0.923880 0.146447 182 | v -0.180240 -0.980785 0.074658 183 | v -0.195091 0.980785 0.000000 184 | v -0.382684 0.923880 0.000000 185 | v -0.555570 0.831470 0.000000 186 | v -0.707107 0.707107 0.000000 187 | v -0.831470 0.555570 -0.000000 188 | v -0.923880 0.382683 -0.000000 189 | v -0.980785 0.195090 0.000000 190 | v -1.000000 0.000000 -0.000000 191 | v -0.980785 -0.195090 0.000000 192 | v -0.923880 -0.382683 -0.000000 193 | v -0.831470 -0.555570 -0.000000 194 | v -0.707107 -0.707107 0.000000 195 | v -0.555570 -0.831470 0.000000 196 | v -0.382684 -0.923880 0.000000 197 | v -0.195090 -0.980785 0.000000 198 | v -0.180240 0.980785 -0.074658 199 | v -0.353554 0.923880 -0.146446 200 | v -0.513280 0.831470 -0.212608 201 | v -0.653281 0.707107 -0.270598 202 | v -0.768178 0.555570 -0.318190 203 | v -0.853553 0.382683 -0.353553 204 | v -0.906127 0.195090 -0.375330 205 | v -0.923880 0.000000 -0.382684 206 | v -0.906127 -0.195090 -0.375330 207 | v -0.853553 -0.382683 -0.353553 208 | v -0.768178 -0.555570 -0.318190 209 | v -0.653281 -0.707107 -0.270598 210 | v -0.513280 -0.831470 -0.212608 211 | v -0.353553 -0.923880 -0.146447 212 | v -0.180240 -0.980785 -0.074658 213 | v -0.137950 0.980785 -0.137950 214 | v -0.270598 0.923880 -0.270598 215 | v -0.392847 0.831470 -0.392847 216 | v -0.500000 0.707107 -0.500000 217 | v -0.587937 0.555570 -0.587938 218 | v -0.653281 0.382683 -0.653282 219 | v -0.693520 0.195090 -0.693520 220 | v -0.707107 0.000000 -0.707107 221 | v -0.693520 -0.195090 -0.693520 222 | v -0.653281 -0.382683 -0.653282 223 | v -0.587937 -0.555570 -0.587938 224 | v -0.500000 -0.707107 -0.500000 225 | v -0.392847 -0.831470 -0.392847 226 | v -0.270598 -0.923880 -0.270598 227 | v -0.137950 -0.980785 -0.137949 228 | v -0.074658 0.980785 -0.180240 229 | v -0.146447 0.923880 -0.353553 230 | v -0.212607 0.831470 -0.513280 231 | v -0.270598 0.707107 -0.653281 232 | v -0.318189 0.555570 -0.768178 233 | v -0.353553 0.382683 -0.853553 234 | v -0.375330 0.195090 -0.906127 235 | v -0.382683 0.000000 -0.923880 236 | v -0.375330 -0.195090 -0.906127 237 | v -0.353553 -0.382683 -0.853553 238 | v -0.318189 -0.555570 -0.768178 239 | v -0.270598 -0.707107 -0.653281 240 | v -0.212607 -0.831470 -0.513280 241 | v -0.146446 -0.923880 -0.353553 242 | v -0.074658 -0.980785 -0.180240 243 | v 0.000000 0.707107 -0.707106 244 | v 0.000000 0.195090 -0.980785 245 | v 0.000000 -0.195090 -0.980785 246 | v 0.000000 -0.707107 -0.707106 247 | vt 0.750000 0.250000 248 | vt 0.687500 0.187500 249 | vt 0.750000 0.187500 250 | vt 0.750000 0.687500 251 | vt 0.687500 0.625000 252 | vt 0.750000 0.625000 253 | vt 0.687500 0.125000 254 | vt 0.750000 0.125000 255 | vt 0.750000 0.562500 256 | vt 0.687500 0.562500 257 | vt 0.687500 0.062500 258 | vt 0.750000 0.062500 259 | vt 0.687500 0.500000 260 | vt 0.750000 0.500000 261 | vt 0.750000 0.937500 262 | vt 0.718750 1.000000 263 | vt 0.687500 0.937500 264 | vt 0.718750 0.000000 265 | vt 0.750000 0.437500 266 | vt 0.687500 0.437500 267 | vt 0.687500 0.875000 268 | vt 0.750000 0.875000 269 | vt 0.687500 0.375000 270 | vt 0.750000 0.375000 271 | vt 0.750000 0.812500 272 | vt 0.687500 0.812500 273 | vt 0.687500 0.312500 274 | vt 0.750000 0.312500 275 | vt 0.750000 0.750000 276 | vt 0.687500 0.750000 277 | vt 0.687500 0.250000 278 | vt 0.687500 0.687500 279 | vt 0.625000 0.750000 280 | vt 0.625000 0.250000 281 | vt 0.625000 0.687500 282 | vt 0.625000 0.187500 283 | vt 0.625000 0.625000 284 | vt 0.625000 0.125000 285 | vt 0.625000 0.562500 286 | vt 0.625000 0.062500 287 | vt 0.625000 0.500000 288 | vt 0.656250 1.000000 289 | vt 0.625000 0.937500 290 | vt 0.656250 0.000000 291 | vt 0.625000 0.437500 292 | vt 0.625000 0.875000 293 | vt 0.625000 0.375000 294 | vt 0.625000 0.812500 295 | vt 0.625000 0.312500 296 | vt 0.562500 0.562500 297 | vt 0.562500 0.500000 298 | vt 0.593750 1.000000 299 | vt 0.562500 0.937500 300 | vt 0.593750 0.000000 301 | vt 0.562500 0.062500 302 | vt 0.562500 0.437500 303 | vt 0.562500 0.875000 304 | vt 0.562500 0.375000 305 | vt 0.562500 0.812500 306 | vt 0.562500 0.312500 307 | vt 0.562500 0.750000 308 | vt 0.562500 0.250000 309 | vt 0.562500 0.687500 310 | vt 0.562500 0.187500 311 | vt 0.562500 0.625000 312 | vt 0.562500 0.125000 313 | vt 0.500000 0.250000 314 | vt 0.500000 0.687500 315 | vt 0.500000 0.187500 316 | vt 0.500000 0.625000 317 | vt 0.500000 0.125000 318 | vt 0.500000 0.562500 319 | vt 0.500000 0.062500 320 | vt 0.500000 0.500000 321 | vt 0.531249 1.000000 322 | vt 0.500000 0.937500 323 | vt 0.531250 0.000000 324 | vt 0.500000 0.437500 325 | vt 0.500000 0.875000 326 | vt 0.500000 0.375000 327 | vt 0.500000 0.812500 328 | vt 0.500000 0.312500 329 | vt 0.500000 0.750000 330 | vt 0.468750 0.000000 331 | vt 0.437500 0.062500 332 | vt 0.437500 0.437500 333 | vt 0.437500 0.875000 334 | vt 0.437500 0.375000 335 | vt 0.437500 0.812500 336 | vt 0.437500 0.312500 337 | vt 0.437500 0.750000 338 | vt 0.437500 0.250000 339 | vt 0.437500 0.687500 340 | vt 0.437500 0.187500 341 | vt 0.437500 0.625000 342 | vt 0.437500 0.125000 343 | vt 0.437500 0.562500 344 | vt 0.437500 0.500000 345 | vt 0.468749 1.000000 346 | vt 0.437500 0.937500 347 | vt 0.375000 0.250000 348 | vt 0.375000 0.187500 349 | vt 0.375000 0.625000 350 | vt 0.375000 0.125000 351 | vt 0.375000 0.562500 352 | vt 0.375000 0.062500 353 | vt 0.375000 0.500000 354 | vt 0.406249 1.000000 355 | vt 0.375000 0.937500 356 | vt 0.406250 0.000000 357 | vt 0.375000 0.437500 358 | vt 0.375000 0.875000 359 | vt 0.375000 0.375000 360 | vt 0.375000 0.812500 361 | vt 0.375000 0.312500 362 | vt 0.375000 0.750000 363 | vt 0.375000 0.687500 364 | vt 0.312500 0.937500 365 | vt 0.312500 0.875000 366 | vt 0.312500 0.437500 367 | vt 0.312500 0.375000 368 | vt 0.312500 0.812500 369 | vt 0.312500 0.312500 370 | vt 0.312500 0.750000 371 | vt 0.312500 0.250000 372 | vt 0.312500 0.687500 373 | vt 0.312500 0.187500 374 | vt 0.312500 0.625000 375 | vt 0.312500 0.125000 376 | vt 0.312500 0.562500 377 | vt 0.312500 0.062500 378 | vt 0.312500 0.500000 379 | vt 0.343750 1.000000 380 | vt 0.343750 0.000000 381 | vt 0.250000 0.625000 382 | vt 0.250000 0.187500 383 | vt 0.250000 0.125000 384 | vt 0.250000 0.562500 385 | vt 0.250000 0.062500 386 | vt 0.250000 0.500000 387 | vt 0.281250 1.000000 388 | vt 0.250000 0.937500 389 | vt 0.281250 0.000000 390 | vt 0.250000 0.437500 391 | vt 0.250000 0.875000 392 | vt 0.250000 0.375000 393 | vt 0.250000 0.812500 394 | vt 0.250000 0.312500 395 | vt 0.250000 0.750000 396 | vt 0.250000 0.250000 397 | vt 0.250000 0.687500 398 | vt 0.187500 0.437500 399 | vt 0.187500 0.375000 400 | vt 0.187500 0.812500 401 | vt 0.187500 0.312500 402 | vt 0.187500 0.750000 403 | vt 0.187500 0.250000 404 | vt 0.187500 0.687500 405 | vt 0.187500 0.187500 406 | vt 0.187500 0.625000 407 | vt 0.187500 0.125000 408 | vt 0.187500 0.562500 409 | vt 0.187500 0.062500 410 | vt 0.187500 0.500000 411 | vt 0.218750 1.000000 412 | vt 0.187500 0.937500 413 | vt 0.218750 0.000000 414 | vt 0.187500 0.875000 415 | vt 0.125000 0.125000 416 | vt 0.125000 0.562500 417 | vt 0.125000 0.062500 418 | vt 0.125000 0.500000 419 | vt 0.156250 1.000000 420 | vt 0.125000 0.937500 421 | vt 0.156250 0.000000 422 | vt 0.125000 0.437500 423 | vt 0.125000 0.875000 424 | vt 0.125000 0.375000 425 | vt 0.125000 0.812500 426 | vt 0.125000 0.312500 427 | vt 0.125000 0.750000 428 | vt 0.125000 0.250000 429 | vt 0.125000 0.687500 430 | vt 0.125000 0.187500 431 | vt 0.125000 0.625000 432 | vt 0.062500 0.812500 433 | vt 0.062500 0.375000 434 | vt 0.062500 0.312500 435 | vt 0.062500 0.750000 436 | vt 0.062500 0.250000 437 | vt 0.062500 0.687500 438 | vt 0.062500 0.187500 439 | vt 0.062500 0.625000 440 | vt 0.062500 0.125000 441 | vt 0.062500 0.562500 442 | vt 0.062500 0.062500 443 | vt 0.062500 0.500000 444 | vt 0.093750 1.000000 445 | vt 0.062500 0.937500 446 | vt 0.093750 0.000000 447 | vt 0.062500 0.437500 448 | vt 0.062500 0.875000 449 | vt 0.000000 0.562500 450 | vt 0.000000 0.062500 451 | vt 0.000000 0.500000 452 | vt 0.031250 1.000000 453 | vt 0.000000 0.937500 454 | vt 0.031250 0.000000 455 | vt 0.000000 0.437500 456 | vt 0.000000 0.875000 457 | vt 0.000000 0.375000 458 | vt 0.000000 0.812500 459 | vt 0.000000 0.312500 460 | vt 0.000000 0.750000 461 | vt 0.000000 0.250000 462 | vt 0.000000 0.687500 463 | vt 0.000000 0.187500 464 | vt 0.000000 0.625000 465 | vt 0.000000 0.125000 466 | vt 1.000000 0.312500 467 | vt 0.937500 0.375000 468 | vt 0.937500 0.312500 469 | vt 1.000000 0.812500 470 | vt 0.937500 0.750000 471 | vt 1.000000 0.750000 472 | vt 0.937500 0.250000 473 | vt 1.000000 0.250000 474 | vt 1.000000 0.687500 475 | vt 0.937500 0.687500 476 | vt 1.000000 0.187500 477 | vt 0.937500 0.187500 478 | vt 0.937500 0.625000 479 | vt 1.000000 0.625000 480 | vt 1.000000 0.125000 481 | vt 0.937500 0.125000 482 | vt 0.937500 0.562500 483 | vt 1.000000 0.562500 484 | vt 0.937500 0.062500 485 | vt 1.000000 0.062500 486 | vt 1.000000 0.500000 487 | vt 0.937500 0.500000 488 | vt 1.000000 0.937500 489 | vt 0.968750 1.000000 490 | vt 0.937500 0.937500 491 | vt 0.968750 0.000000 492 | vt 0.937500 0.437500 493 | vt 1.000000 0.437500 494 | vt 1.000000 0.875000 495 | vt 0.937500 0.875000 496 | vt 1.000000 0.375000 497 | vt 0.937500 0.812500 498 | vt 0.875000 0.062500 499 | vt 0.875000 0.562500 500 | vt 0.875000 0.500000 501 | vt 0.906250 1.000000 502 | vt 0.875000 0.937500 503 | vt 0.906250 0.000000 504 | vt 0.875000 0.437500 505 | vt 0.875000 0.875000 506 | vt 0.875000 0.375000 507 | vt 0.875000 0.812500 508 | vt 0.875000 0.312500 509 | vt 0.875000 0.750000 510 | vt 0.875000 0.250000 511 | vt 0.875000 0.687500 512 | vt 0.875000 0.187500 513 | vt 0.875000 0.625000 514 | vt 0.875000 0.125000 515 | vt 0.812500 0.250000 516 | vt 0.812500 0.750000 517 | vt 0.812500 0.687500 518 | vt 0.812500 0.187500 519 | vt 0.812500 0.625000 520 | vt 0.812500 0.125000 521 | vt 0.812500 0.562500 522 | vt 0.812500 0.062500 523 | vt 0.812500 0.500000 524 | vt 0.843750 1.000000 525 | vt 0.812500 0.937500 526 | vt 0.843750 0.000000 527 | vt 0.812500 0.437500 528 | vt 0.812500 0.875000 529 | vt 0.812500 0.375000 530 | vt 0.812500 0.812500 531 | vt 0.812500 0.312500 532 | vt 0.781250 1.000000 533 | vt 0.781250 0.000000 534 | vn 0.0000 -0.7010 -0.7131 535 | vn 0.2158 -0.8258 -0.5210 536 | vn 0.0000 -0.8258 -0.5639 537 | vn 0.0000 0.5500 -0.8351 538 | vn 0.3542 0.3784 -0.8552 539 | vn 0.0000 0.3784 -0.9256 540 | vn 0.1504 -0.9195 -0.3631 541 | vn 0.0000 -0.9195 -0.3930 542 | vn 0.0000 0.1928 -0.9812 543 | vn 0.3755 0.1928 -0.9065 544 | vn 0.0791 -0.9784 -0.1910 545 | vn 0.0000 -0.9784 -0.2068 546 | vn 0.3827 0.0000 -0.9239 547 | vn 0.0000 0.0000 -1.0000 548 | vn 0.0000 0.9784 -0.2068 549 | vn 0.0000 1.0000 0.0000 550 | vn 0.0791 0.9784 -0.1910 551 | vn 0.0000 -1.0000 0.0000 552 | vn 0.0000 -0.1928 -0.9812 553 | vn 0.3755 -0.1928 -0.9065 554 | vn 0.1504 0.9195 -0.3631 555 | vn 0.0000 0.9195 -0.3930 556 | vn 0.3542 -0.3784 -0.8552 557 | vn 0.0000 -0.3784 -0.9256 558 | vn 0.0000 0.8258 -0.5639 559 | vn 0.2158 0.8258 -0.5210 560 | vn 0.3196 -0.5500 -0.7716 561 | vn 0.0000 -0.5500 -0.8351 562 | vn 0.0000 0.7010 -0.7131 563 | vn 0.2729 0.7010 -0.6588 564 | vn 0.2729 -0.7010 -0.6588 565 | vn 0.3196 0.5500 -0.7716 566 | vn 0.5042 0.7010 -0.5042 567 | vn 0.5042 -0.7010 -0.5042 568 | vn 0.5905 0.5500 -0.5905 569 | vn 0.3987 -0.8258 -0.3987 570 | vn 0.6545 0.3784 -0.6545 571 | vn 0.2779 -0.9195 -0.2779 572 | vn 0.6938 0.1928 -0.6938 573 | vn 0.1462 -0.9784 -0.1462 574 | vn 0.7071 0.0000 -0.7071 575 | vn 0.1462 0.9784 -0.1462 576 | vn 0.6938 -0.1928 -0.6938 577 | vn 0.2779 0.9195 -0.2779 578 | vn 0.6545 -0.3784 -0.6545 579 | vn 0.3987 0.8258 -0.3987 580 | vn 0.5905 -0.5500 -0.5905 581 | vn 0.9065 0.1928 -0.3755 582 | vn 0.9239 0.0000 -0.3827 583 | vn 0.1910 0.9784 -0.0791 584 | vn 0.1910 -0.9784 -0.0791 585 | vn 0.9065 -0.1928 -0.3755 586 | vn 0.3631 0.9195 -0.1504 587 | vn 0.8552 -0.3784 -0.3542 588 | vn 0.5210 0.8258 -0.2158 589 | vn 0.7716 -0.5500 -0.3196 590 | vn 0.6588 0.7010 -0.2729 591 | vn 0.6588 -0.7010 -0.2729 592 | vn 0.7716 0.5500 -0.3196 593 | vn 0.5210 -0.8258 -0.2158 594 | vn 0.8552 0.3784 -0.3542 595 | vn 0.3631 -0.9195 -0.1504 596 | vn 0.7131 -0.7010 0.0000 597 | vn 0.8351 0.5500 0.0000 598 | vn 0.5639 -0.8258 0.0000 599 | vn 0.9256 0.3784 0.0000 600 | vn 0.3930 -0.9195 0.0000 601 | vn 0.9812 0.1928 0.0000 602 | vn 0.2068 -0.9784 0.0000 603 | vn 1.0000 0.0000 0.0000 604 | vn 0.2068 0.9784 0.0000 605 | vn 0.9812 -0.1928 0.0000 606 | vn 0.3930 0.9195 0.0000 607 | vn 0.9256 -0.3784 0.0000 608 | vn 0.5639 0.8258 0.0000 609 | vn 0.8351 -0.5500 0.0000 610 | vn 0.7131 0.7010 0.0000 611 | vn 0.1910 -0.9784 0.0791 612 | vn 0.9065 -0.1928 0.3755 613 | vn 0.3631 0.9195 0.1504 614 | vn 0.8552 -0.3784 0.3542 615 | vn 0.5210 0.8258 0.2158 616 | vn 0.7716 -0.5500 0.3196 617 | vn 0.6588 0.7010 0.2729 618 | vn 0.6588 -0.7010 0.2729 619 | vn 0.7716 0.5500 0.3196 620 | vn 0.5210 -0.8258 0.2158 621 | vn 0.8552 0.3784 0.3542 622 | vn 0.3631 -0.9195 0.1504 623 | vn 0.9065 0.1928 0.3755 624 | vn 0.9239 0.0000 0.3827 625 | vn 0.1910 0.9784 0.0791 626 | vn 0.5042 -0.7010 0.5042 627 | vn 0.3987 -0.8258 0.3987 628 | vn 0.6545 0.3784 0.6545 629 | vn 0.2779 -0.9195 0.2779 630 | vn 0.6938 0.1928 0.6938 631 | vn 0.1462 -0.9784 0.1462 632 | vn 0.7071 0.0000 0.7071 633 | vn 0.1462 0.9784 0.1462 634 | vn 0.6938 -0.1928 0.6938 635 | vn 0.2779 0.9195 0.2779 636 | vn 0.6545 -0.3784 0.6545 637 | vn 0.3987 0.8258 0.3987 638 | vn 0.5905 -0.5500 0.5905 639 | vn 0.5042 0.7010 0.5042 640 | vn 0.5905 0.5500 0.5905 641 | vn 0.0791 0.9784 0.1910 642 | vn 0.1504 0.9195 0.3631 643 | vn 0.3755 -0.1928 0.9065 644 | vn 0.3542 -0.3784 0.8552 645 | vn 0.2158 0.8258 0.5210 646 | vn 0.3196 -0.5500 0.7716 647 | vn 0.2729 0.7010 0.6588 648 | vn 0.2729 -0.7010 0.6588 649 | vn 0.3196 0.5500 0.7716 650 | vn 0.2158 -0.8258 0.5210 651 | vn 0.3542 0.3784 0.8552 652 | vn 0.1504 -0.9195 0.3631 653 | vn 0.3755 0.1928 0.9065 654 | vn 0.0791 -0.9784 0.1910 655 | vn 0.3827 0.0000 0.9239 656 | vn 0.0000 0.3784 0.9256 657 | vn 0.0000 -0.8258 0.5639 658 | vn 0.0000 -0.9195 0.3930 659 | vn 0.0000 0.1928 0.9812 660 | vn 0.0000 -0.9784 0.2068 661 | vn 0.0000 0.0000 1.0000 662 | vn 0.0000 0.9784 0.2068 663 | vn 0.0000 -0.1928 0.9812 664 | vn 0.0000 0.9195 0.3930 665 | vn 0.0000 -0.3784 0.9256 666 | vn 0.0000 0.8258 0.5639 667 | vn 0.0000 -0.5500 0.8351 668 | vn 0.0000 0.7010 0.7131 669 | vn 0.0000 -0.7010 0.7131 670 | vn 0.0000 0.5500 0.8351 671 | vn -0.3755 -0.1928 0.9065 672 | vn -0.3542 -0.3784 0.8552 673 | vn -0.2158 0.8258 0.5210 674 | vn -0.3196 -0.5500 0.7716 675 | vn -0.2729 0.7010 0.6588 676 | vn -0.2729 -0.7010 0.6588 677 | vn -0.3196 0.5500 0.7716 678 | vn -0.2158 -0.8258 0.5210 679 | vn -0.3542 0.3784 0.8552 680 | vn -0.1504 -0.9195 0.3631 681 | vn -0.3755 0.1928 0.9065 682 | vn -0.0791 -0.9784 0.1910 683 | vn -0.3827 0.0000 0.9239 684 | vn -0.0791 0.9784 0.1910 685 | vn -0.1504 0.9195 0.3631 686 | vn -0.2779 -0.9195 0.2779 687 | vn -0.6938 0.1928 0.6938 688 | vn -0.1462 -0.9784 0.1462 689 | vn -0.7071 0.0000 0.7071 690 | vn -0.1462 0.9784 0.1462 691 | vn -0.6938 -0.1928 0.6938 692 | vn -0.2779 0.9195 0.2779 693 | vn -0.6545 -0.3784 0.6545 694 | vn -0.3987 0.8258 0.3987 695 | vn -0.5905 -0.5500 0.5905 696 | vn -0.5042 0.7010 0.5042 697 | vn -0.5042 -0.7010 0.5042 698 | vn -0.5905 0.5500 0.5905 699 | vn -0.3987 -0.8258 0.3987 700 | vn -0.6545 0.3784 0.6545 701 | vn -0.5210 0.8258 0.2158 702 | vn -0.8552 -0.3784 0.3542 703 | vn -0.7716 -0.5500 0.3196 704 | vn -0.6588 0.7010 0.2729 705 | vn -0.6588 -0.7010 0.2729 706 | vn -0.7716 0.5500 0.3196 707 | vn -0.5210 -0.8258 0.2158 708 | vn -0.8552 0.3784 0.3542 709 | vn -0.3631 -0.9195 0.1504 710 | vn -0.9065 0.1928 0.3755 711 | vn -0.1910 -0.9784 0.0791 712 | vn -0.9239 0.0000 0.3827 713 | vn -0.1910 0.9784 0.0791 714 | vn -0.9065 -0.1928 0.3755 715 | vn -0.3631 0.9195 0.1504 716 | vn -0.9812 0.1928 0.0000 717 | vn -0.2068 -0.9784 0.0000 718 | vn -1.0000 0.0000 0.0000 719 | vn -0.2068 0.9784 0.0000 720 | vn -0.9812 -0.1928 0.0000 721 | vn -0.3930 0.9195 0.0000 722 | vn -0.9256 -0.3784 0.0000 723 | vn -0.5639 0.8258 0.0000 724 | vn -0.8351 -0.5500 0.0000 725 | vn -0.7131 0.7010 0.0000 726 | vn -0.7131 -0.7010 0.0000 727 | vn -0.8351 0.5500 0.0000 728 | vn -0.5639 -0.8258 0.0000 729 | vn -0.9256 0.3784 0.0000 730 | vn -0.3930 -0.9195 0.0000 731 | vn -0.8552 -0.3784 -0.3542 732 | vn -0.7716 -0.5500 -0.3196 733 | vn -0.6588 0.7010 -0.2729 734 | vn -0.6588 -0.7010 -0.2729 735 | vn -0.7716 0.5500 -0.3196 736 | vn -0.5210 -0.8258 -0.2158 737 | vn -0.8552 0.3784 -0.3542 738 | vn -0.3631 -0.9195 -0.1504 739 | vn -0.9065 0.1928 -0.3755 740 | vn -0.1910 -0.9784 -0.0791 741 | vn -0.9239 0.0000 -0.3827 742 | vn -0.1910 0.9784 -0.0791 743 | vn -0.9065 -0.1928 -0.3755 744 | vn -0.3631 0.9195 -0.1504 745 | vn -0.5210 0.8258 -0.2158 746 | vn -0.1462 -0.9784 -0.1462 747 | vn -0.6938 0.1928 -0.6938 748 | vn -0.7071 0.0000 -0.7071 749 | vn -0.1462 0.9784 -0.1462 750 | vn -0.6938 -0.1928 -0.6938 751 | vn -0.2779 0.9195 -0.2779 752 | vn -0.6545 -0.3784 -0.6545 753 | vn -0.3987 0.8258 -0.3987 754 | vn -0.5905 -0.5500 -0.5905 755 | vn -0.5042 0.7010 -0.5042 756 | vn -0.5042 -0.7010 -0.5042 757 | vn -0.5905 0.5500 -0.5905 758 | vn -0.3987 -0.8258 -0.3987 759 | vn -0.6545 0.3784 -0.6545 760 | vn -0.2779 -0.9195 -0.2779 761 | vn -0.2729 -0.7010 -0.6588 762 | vn -0.2729 0.7010 -0.6588 763 | vn -0.3196 0.5500 -0.7716 764 | vn -0.2158 -0.8258 -0.5210 765 | vn -0.3542 0.3784 -0.8552 766 | vn -0.1504 -0.9195 -0.3631 767 | vn -0.3755 0.1928 -0.9065 768 | vn -0.0791 -0.9784 -0.1910 769 | vn -0.3827 0.0000 -0.9239 770 | vn -0.0791 0.9784 -0.1910 771 | vn -0.3755 -0.1928 -0.9065 772 | vn -0.1504 0.9195 -0.3631 773 | vn -0.3542 -0.3784 -0.8552 774 | vn -0.2158 0.8258 -0.5210 775 | vn -0.3196 -0.5500 -0.7716 776 | usemtl None 777 | s 1 778 | f 242/1/1 25/2/2 9/3/3 779 | f 4/4/4 18/5/5 5/6/6 780 | f 9/3/3 26/7/7 10/8/8 781 | f 240/9/9 18/5/5 19/10/10 782 | f 10/8/8 27/11/11 11/12/12 783 | f 240/9/9 20/13/13 6/14/14 784 | f 1/15/15 133/16/16 13/17/17 785 | f 12/18/18 11/12/12 27/11/11 786 | f 241/19/19 20/13/13 21/20/20 787 | f 1/15/15 14/21/21 2/22/22 788 | f 241/19/19 22/23/23 7/24/24 789 | f 3/25/25 14/21/21 15/26/26 790 | f 7/24/24 23/27/27 8/28/28 791 | f 239/29/29 15/26/26 16/30/30 792 | f 242/1/1 23/27/27 24/31/31 793 | f 239/29/29 17/32/32 4/4/4 794 | f 15/26/26 31/33/33 16/30/30 795 | f 23/27/27 39/34/34 24/31/31 796 | f 16/30/30 32/35/35 17/32/32 797 | f 24/31/31 40/36/36 25/2/2 798 | f 17/32/32 33/37/37 18/5/5 799 | f 25/2/2 41/38/38 26/7/7 800 | f 18/5/5 34/39/39 19/10/10 801 | f 27/11/11 41/38/38 42/40/40 802 | f 20/13/13 34/39/39 35/41/41 803 | f 13/17/17 133/42/16 28/43/42 804 | f 12/44/18 27/11/11 42/40/40 805 | f 20/13/13 36/45/43 21/20/20 806 | f 13/17/17 29/46/44 14/21/21 807 | f 21/20/20 37/47/45 22/23/23 808 | f 14/21/21 30/48/46 15/26/26 809 | f 22/23/23 38/49/47 23/27/27 810 | f 35/41/41 49/50/48 50/51/49 811 | f 28/43/42 133/52/16 43/53/50 812 | f 12/54/18 42/40/40 57/55/51 813 | f 35/41/41 51/56/52 36/45/43 814 | f 28/43/42 44/57/53 29/46/44 815 | f 37/47/45 51/56/52 52/58/54 816 | f 29/46/44 45/59/55 30/48/46 817 | f 37/47/45 53/60/56 38/49/47 818 | f 30/48/46 46/61/57 31/33/33 819 | f 38/49/47 54/62/58 39/34/34 820 | f 31/33/33 47/63/59 32/35/35 821 | f 39/34/34 55/64/60 40/36/36 822 | f 33/37/37 47/63/59 48/65/61 823 | f 41/38/38 55/64/60 56/66/62 824 | f 33/37/37 49/50/48 34/39/39 825 | f 41/38/38 57/55/51 42/40/40 826 | f 53/60/56 69/67/63 54/62/58 827 | f 46/61/57 62/68/64 47/63/59 828 | f 54/62/58 70/69/65 55/64/60 829 | f 47/63/59 63/70/66 48/65/61 830 | f 55/64/60 71/71/67 56/66/62 831 | f 48/65/61 64/72/68 49/50/48 832 | f 56/66/62 72/73/69 57/55/51 833 | f 50/51/49 64/72/68 65/74/70 834 | f 43/53/50 133/75/16 58/76/71 835 | f 12/77/18 57/55/51 72/73/69 836 | f 50/51/49 66/78/72 51/56/52 837 | f 43/53/50 59/79/73 44/57/53 838 | f 51/56/52 67/80/74 52/58/54 839 | f 44/57/53 60/81/75 45/59/55 840 | f 52/58/54 68/82/76 53/60/56 841 | f 45/59/55 61/83/77 46/61/57 842 | f 12/84/18 72/73/69 87/85/78 843 | f 65/74/70 81/86/79 66/78/72 844 | f 58/76/71 74/87/80 59/79/73 845 | f 66/78/72 82/88/81 67/80/74 846 | f 59/79/73 75/89/82 60/81/75 847 | f 68/82/76 82/88/81 83/90/83 848 | f 60/81/75 76/91/84 61/83/77 849 | f 68/82/76 84/92/85 69/67/63 850 | f 61/83/77 77/93/86 62/68/64 851 | f 69/67/63 85/94/87 70/69/65 852 | f 62/68/64 78/95/88 63/70/66 853 | f 71/71/67 85/94/87 86/96/89 854 | f 63/70/66 79/97/90 64/72/68 855 | f 71/71/67 87/85/78 72/73/69 856 | f 65/74/70 79/97/90 80/98/91 857 | f 58/76/71 133/99/16 73/100/92 858 | f 85/94/87 99/101/93 100/102/94 859 | f 77/93/86 93/103/95 78/95/88 860 | f 86/96/89 100/102/94 101/104/96 861 | f 78/95/88 94/105/97 79/97/90 862 | f 86/96/89 102/106/98 87/85/78 863 | f 80/98/91 94/105/97 95/107/99 864 | f 73/100/92 133/108/16 88/109/100 865 | f 12/110/18 87/85/78 102/106/98 866 | f 80/98/91 96/111/101 81/86/79 867 | f 73/100/92 89/112/102 74/87/80 868 | f 82/88/81 96/111/101 97/113/103 869 | f 74/87/80 90/114/104 75/89/82 870 | f 82/88/81 98/115/105 83/90/83 871 | f 75/89/82 91/116/106 76/91/84 872 | f 83/90/83 99/101/93 84/92/85 873 | f 76/91/84 92/117/107 77/93/86 874 | f 89/112/102 103/118/108 104/119/109 875 | f 97/113/103 111/120/110 112/121/111 876 | f 89/112/102 105/122/112 90/114/104 877 | f 97/113/103 113/123/113 98/115/105 878 | f 90/114/104 106/124/114 91/116/106 879 | f 98/115/105 114/125/115 99/101/93 880 | f 92/117/107 106/124/114 107/126/116 881 | f 100/102/94 114/125/115 115/127/117 882 | f 92/117/107 108/128/118 93/103/95 883 | f 101/104/96 115/127/117 116/129/119 884 | f 93/103/95 109/130/120 94/105/97 885 | f 101/104/96 117/131/121 102/106/98 886 | f 95/107/99 109/130/120 110/132/122 887 | f 88/109/100 133/133/16 103/118/108 888 | f 12/134/18 102/106/98 117/131/121 889 | f 95/107/99 111/120/110 96/111/101 890 | f 107/126/116 123/135/123 108/128/118 891 | f 116/129/119 130/136/124 131/137/125 892 | f 108/128/118 124/138/126 109/130/120 893 | f 116/129/119 132/139/127 117/131/121 894 | f 110/132/122 124/138/126 125/140/128 895 | f 103/118/108 133/141/16 118/142/129 896 | f 12/143/18 117/131/121 132/139/127 897 | f 110/132/122 126/144/130 111/120/110 898 | f 103/118/108 119/145/131 104/119/109 899 | f 112/121/111 126/144/130 127/146/132 900 | f 104/119/109 120/147/133 105/122/112 901 | f 112/121/111 128/148/134 113/123/113 902 | f 105/122/112 121/149/135 106/124/114 903 | f 113/123/113 129/150/136 114/125/115 904 | f 107/126/116 121/149/135 122/151/137 905 | f 115/127/117 129/150/136 130/136/124 906 | f 127/146/132 142/152/138 143/153/139 907 | f 119/145/131 136/154/140 120/147/133 908 | f 127/146/132 144/155/141 128/148/134 909 | f 120/147/133 137/156/142 121/149/135 910 | f 128/148/134 145/157/143 129/150/136 911 | f 121/149/135 138/158/144 122/151/137 912 | f 130/136/124 145/157/143 146/159/145 913 | f 122/151/137 139/160/146 123/135/123 914 | f 131/137/125 146/159/145 147/161/147 915 | f 123/135/123 140/162/148 124/138/126 916 | f 131/137/125 148/163/149 132/139/127 917 | f 125/140/128 140/162/148 141/164/150 918 | f 118/142/129 133/165/16 134/166/151 919 | f 12/167/18 132/139/127 148/163/149 920 | f 125/140/128 142/152/138 126/144/130 921 | f 118/142/129 135/168/152 119/145/131 922 | f 146/159/145 162/169/153 147/161/147 923 | f 139/160/146 155/170/154 140/162/148 924 | f 147/161/147 163/171/155 148/163/149 925 | f 140/162/148 156/172/156 141/164/150 926 | f 134/166/151 133/173/16 149/174/157 927 | f 12/175/18 148/163/149 163/171/155 928 | f 141/164/150 157/176/158 142/152/138 929 | f 134/166/151 150/177/159 135/168/152 930 | f 143/153/139 157/176/158 158/178/160 931 | f 135/168/152 151/179/161 136/154/140 932 | f 143/153/139 159/180/162 144/155/141 933 | f 136/154/140 152/181/163 137/156/142 934 | f 144/155/141 160/182/164 145/157/143 935 | f 137/156/142 153/183/165 138/158/144 936 | f 146/159/145 160/182/164 161/184/166 937 | f 138/158/144 154/185/167 139/160/146 938 | f 150/177/159 166/186/168 151/179/161 939 | f 159/180/162 173/187/169 174/188/170 940 | f 151/179/161 167/189/171 152/181/163 941 | f 159/180/162 175/190/172 160/182/164 942 | f 153/183/165 167/189/171 168/191/173 943 | f 161/184/166 175/190/172 176/192/174 944 | f 153/183/165 169/193/175 154/185/167 945 | f 162/169/153 176/192/174 177/194/176 946 | f 154/185/167 170/195/177 155/170/154 947 | f 162/169/153 178/196/178 163/171/155 948 | f 155/170/154 171/197/179 156/172/156 949 | f 149/174/157 133/198/16 164/199/180 950 | f 12/200/18 163/171/155 178/196/178 951 | f 156/172/156 172/201/181 157/176/158 952 | f 149/174/157 165/202/182 150/177/159 953 | f 158/178/160 172/201/181 173/187/169 954 | f 169/193/175 185/203/183 170/195/177 955 | f 177/194/176 193/204/184 178/196/178 956 | f 171/197/179 185/203/183 186/205/185 957 | f 164/199/180 133/206/16 179/207/186 958 | f 12/208/18 178/196/178 193/204/184 959 | f 171/197/179 187/209/187 172/201/181 960 | f 165/202/182 179/207/186 180/210/188 961 | f 173/187/169 187/209/187 188/211/189 962 | f 165/202/182 181/212/190 166/186/168 963 | f 174/188/170 188/211/189 189/213/191 964 | f 166/186/168 182/214/192 167/189/171 965 | f 174/188/170 190/215/193 175/190/172 966 | f 168/191/173 182/214/192 183/216/194 967 | f 176/192/174 190/215/193 191/217/195 968 | f 168/191/173 184/218/196 169/193/175 969 | f 177/194/176 191/217/195 192/219/197 970 | f 189/220/191 203/221/198 204/222/199 971 | f 181/223/190 197/224/200 182/225/192 972 | f 189/220/191 205/226/201 190/227/193 973 | f 183/228/194 197/224/200 198/229/202 974 | f 191/230/195 205/226/201 206/231/203 975 | f 183/228/194 199/232/204 184/233/196 976 | f 192/234/197 206/231/203 207/235/205 977 | f 184/233/196 200/236/206 185/237/183 978 | f 192/234/197 208/238/207 193/239/184 979 | f 186/240/185 200/236/206 201/241/208 980 | f 179/242/186 133/243/16 194/244/209 981 | f 12/245/18 193/239/184 208/238/207 982 | f 186/240/185 202/246/210 187/247/187 983 | f 180/248/188 194/244/209 195/249/211 984 | f 188/250/189 202/246/210 203/221/198 985 | f 180/248/188 196/251/212 181/223/190 986 | f 207/235/205 223/252/213 208/238/207 987 | f 201/241/208 215/253/214 216/254/215 988 | f 194/244/209 133/255/16 209/256/216 989 | f 12/257/18 208/238/207 223/252/213 990 | f 201/241/208 217/258/217 202/246/210 991 | f 194/244/209 210/259/218 195/249/211 992 | f 203/221/198 217/258/217 218/260/219 993 | f 196/251/212 210/259/218 211/261/220 994 | f 204/222/199 218/260/219 219/262/221 995 | f 196/251/212 212/263/222 197/224/200 996 | f 204/222/199 220/264/223 205/226/201 997 | f 198/229/202 212/263/222 213/265/224 998 | f 206/231/203 220/264/223 221/266/225 999 | f 198/229/202 214/267/226 199/232/204 1000 | f 207/235/205 221/266/225 222/268/227 1001 | f 199/232/204 215/253/214 200/236/206 1002 | f 219/262/221 235/269/228 220/264/223 1003 | f 213/265/224 227/270/229 228/271/230 1004 | f 221/266/225 235/269/228 236/272/231 1005 | f 213/265/224 229/273/232 214/267/226 1006 | f 221/266/225 237/274/233 222/268/227 1007 | f 214/267/226 230/275/234 215/253/214 1008 | f 222/268/227 238/276/235 223/252/213 1009 | f 216/254/215 230/275/234 231/277/236 1010 | f 209/256/216 133/278/16 224/279/237 1011 | f 12/280/18 223/252/213 238/276/235 1012 | f 216/254/215 232/281/238 217/258/217 1013 | f 209/256/216 225/282/239 210/259/218 1014 | f 218/260/219 232/281/238 233/283/240 1015 | f 211/261/220 225/282/239 226/284/241 1016 | f 219/262/221 233/283/240 234/285/242 1017 | f 211/261/220 227/270/229 212/263/222 1018 | f 224/279/237 133/286/16 1/15/15 1019 | f 12/287/18 238/276/235 11/12/12 1020 | f 232/281/238 6/14/14 241/19/19 1021 | f 225/282/239 1/15/15 2/22/22 1022 | f 232/281/238 7/24/24 233/283/240 1023 | f 226/284/241 2/22/22 3/25/25 1024 | f 233/283/240 8/28/28 234/285/242 1025 | f 227/270/229 3/25/25 239/29/29 1026 | f 235/269/228 8/28/28 242/1/1 1027 | f 227/270/229 4/4/4 228/271/230 1028 | f 235/269/228 9/3/3 236/272/231 1029 | f 228/271/230 5/6/6 229/273/232 1030 | f 236/272/231 10/8/8 237/274/233 1031 | f 230/275/234 5/6/6 240/9/9 1032 | f 237/274/233 11/12/12 238/276/235 1033 | f 230/275/234 6/14/14 231/277/236 1034 | f 242/1/1 24/31/31 25/2/2 1035 | f 4/4/4 17/32/32 18/5/5 1036 | f 9/3/3 25/2/2 26/7/7 1037 | f 240/9/9 5/6/6 18/5/5 1038 | f 10/8/8 26/7/7 27/11/11 1039 | f 240/9/9 19/10/10 20/13/13 1040 | f 241/19/19 6/14/14 20/13/13 1041 | f 1/15/15 13/17/17 14/21/21 1042 | f 241/19/19 21/20/20 22/23/23 1043 | f 3/25/25 2/22/22 14/21/21 1044 | f 7/24/24 22/23/23 23/27/27 1045 | f 239/29/29 3/25/25 15/26/26 1046 | f 242/1/1 8/28/28 23/27/27 1047 | f 239/29/29 16/30/30 17/32/32 1048 | f 15/26/26 30/48/46 31/33/33 1049 | f 23/27/27 38/49/47 39/34/34 1050 | f 16/30/30 31/33/33 32/35/35 1051 | f 24/31/31 39/34/34 40/36/36 1052 | f 17/32/32 32/35/35 33/37/37 1053 | f 25/2/2 40/36/36 41/38/38 1054 | f 18/5/5 33/37/37 34/39/39 1055 | f 27/11/11 26/7/7 41/38/38 1056 | f 20/13/13 19/10/10 34/39/39 1057 | f 20/13/13 35/41/41 36/45/43 1058 | f 13/17/17 28/43/42 29/46/44 1059 | f 21/20/20 36/45/43 37/47/45 1060 | f 14/21/21 29/46/44 30/48/46 1061 | f 22/23/23 37/47/45 38/49/47 1062 | f 35/41/41 34/39/39 49/50/48 1063 | f 35/41/41 50/51/49 51/56/52 1064 | f 28/43/42 43/53/50 44/57/53 1065 | f 37/47/45 36/45/43 51/56/52 1066 | f 29/46/44 44/57/53 45/59/55 1067 | f 37/47/45 52/58/54 53/60/56 1068 | f 30/48/46 45/59/55 46/61/57 1069 | f 38/49/47 53/60/56 54/62/58 1070 | f 31/33/33 46/61/57 47/63/59 1071 | f 39/34/34 54/62/58 55/64/60 1072 | f 33/37/37 32/35/35 47/63/59 1073 | f 41/38/38 40/36/36 55/64/60 1074 | f 33/37/37 48/65/61 49/50/48 1075 | f 41/38/38 56/66/62 57/55/51 1076 | f 53/60/56 68/82/76 69/67/63 1077 | f 46/61/57 61/83/77 62/68/64 1078 | f 54/62/58 69/67/63 70/69/65 1079 | f 47/63/59 62/68/64 63/70/66 1080 | f 55/64/60 70/69/65 71/71/67 1081 | f 48/65/61 63/70/66 64/72/68 1082 | f 56/66/62 71/71/67 72/73/69 1083 | f 50/51/49 49/50/48 64/72/68 1084 | f 50/51/49 65/74/70 66/78/72 1085 | f 43/53/50 58/76/71 59/79/73 1086 | f 51/56/52 66/78/72 67/80/74 1087 | f 44/57/53 59/79/73 60/81/75 1088 | f 52/58/54 67/80/74 68/82/76 1089 | f 45/59/55 60/81/75 61/83/77 1090 | f 65/74/70 80/98/91 81/86/79 1091 | f 58/76/71 73/100/92 74/87/80 1092 | f 66/78/72 81/86/79 82/88/81 1093 | f 59/79/73 74/87/80 75/89/82 1094 | f 68/82/76 67/80/74 82/88/81 1095 | f 60/81/75 75/89/82 76/91/84 1096 | f 68/82/76 83/90/83 84/92/85 1097 | f 61/83/77 76/91/84 77/93/86 1098 | f 69/67/63 84/92/85 85/94/87 1099 | f 62/68/64 77/93/86 78/95/88 1100 | f 71/71/67 70/69/65 85/94/87 1101 | f 63/70/66 78/95/88 79/97/90 1102 | f 71/71/67 86/96/89 87/85/78 1103 | f 65/74/70 64/72/68 79/97/90 1104 | f 85/94/87 84/92/85 99/101/93 1105 | f 77/93/86 92/117/107 93/103/95 1106 | f 86/96/89 85/94/87 100/102/94 1107 | f 78/95/88 93/103/95 94/105/97 1108 | f 86/96/89 101/104/96 102/106/98 1109 | f 80/98/91 79/97/90 94/105/97 1110 | f 80/98/91 95/107/99 96/111/101 1111 | f 73/100/92 88/109/100 89/112/102 1112 | f 82/88/81 81/86/79 96/111/101 1113 | f 74/87/80 89/112/102 90/114/104 1114 | f 82/88/81 97/113/103 98/115/105 1115 | f 75/89/82 90/114/104 91/116/106 1116 | f 83/90/83 98/115/105 99/101/93 1117 | f 76/91/84 91/116/106 92/117/107 1118 | f 89/112/102 88/109/100 103/118/108 1119 | f 97/113/103 96/111/101 111/120/110 1120 | f 89/112/102 104/119/109 105/122/112 1121 | f 97/113/103 112/121/111 113/123/113 1122 | f 90/114/104 105/122/112 106/124/114 1123 | f 98/115/105 113/123/113 114/125/115 1124 | f 92/117/107 91/116/106 106/124/114 1125 | f 100/102/94 99/101/93 114/125/115 1126 | f 92/117/107 107/126/116 108/128/118 1127 | f 101/104/96 100/102/94 115/127/117 1128 | f 93/103/95 108/128/118 109/130/120 1129 | f 101/104/96 116/129/119 117/131/121 1130 | f 95/107/99 94/105/97 109/130/120 1131 | f 95/107/99 110/132/122 111/120/110 1132 | f 107/126/116 122/151/137 123/135/123 1133 | f 116/129/119 115/127/117 130/136/124 1134 | f 108/128/118 123/135/123 124/138/126 1135 | f 116/129/119 131/137/125 132/139/127 1136 | f 110/132/122 109/130/120 124/138/126 1137 | f 110/132/122 125/140/128 126/144/130 1138 | f 103/118/108 118/142/129 119/145/131 1139 | f 112/121/111 111/120/110 126/144/130 1140 | f 104/119/109 119/145/131 120/147/133 1141 | f 112/121/111 127/146/132 128/148/134 1142 | f 105/122/112 120/147/133 121/149/135 1143 | f 113/123/113 128/148/134 129/150/136 1144 | f 107/126/116 106/124/114 121/149/135 1145 | f 115/127/117 114/125/115 129/150/136 1146 | f 127/146/132 126/144/130 142/152/138 1147 | f 119/145/131 135/168/152 136/154/140 1148 | f 127/146/132 143/153/139 144/155/141 1149 | f 120/147/133 136/154/140 137/156/142 1150 | f 128/148/134 144/155/141 145/157/143 1151 | f 121/149/135 137/156/142 138/158/144 1152 | f 130/136/124 129/150/136 145/157/143 1153 | f 122/151/137 138/158/144 139/160/146 1154 | f 131/137/125 130/136/124 146/159/145 1155 | f 123/135/123 139/160/146 140/162/148 1156 | f 131/137/125 147/161/147 148/163/149 1157 | f 125/140/128 124/138/126 140/162/148 1158 | f 125/140/128 141/164/150 142/152/138 1159 | f 118/142/129 134/166/151 135/168/152 1160 | f 146/159/145 161/184/166 162/169/153 1161 | f 139/160/146 154/185/167 155/170/154 1162 | f 147/161/147 162/169/153 163/171/155 1163 | f 140/162/148 155/170/154 156/172/156 1164 | f 141/164/150 156/172/156 157/176/158 1165 | f 134/166/151 149/174/157 150/177/159 1166 | f 143/153/139 142/152/138 157/176/158 1167 | f 135/168/152 150/177/159 151/179/161 1168 | f 143/153/139 158/178/160 159/180/162 1169 | f 136/154/140 151/179/161 152/181/163 1170 | f 144/155/141 159/180/162 160/182/164 1171 | f 137/156/142 152/181/163 153/183/165 1172 | f 146/159/145 145/157/143 160/182/164 1173 | f 138/158/144 153/183/165 154/185/167 1174 | f 150/177/159 165/202/182 166/186/168 1175 | f 159/180/162 158/178/160 173/187/169 1176 | f 151/179/161 166/186/168 167/189/171 1177 | f 159/180/162 174/188/170 175/190/172 1178 | f 153/183/165 152/181/163 167/189/171 1179 | f 161/184/166 160/182/164 175/190/172 1180 | f 153/183/165 168/191/173 169/193/175 1181 | f 162/169/153 161/184/166 176/192/174 1182 | f 154/185/167 169/193/175 170/195/177 1183 | f 162/169/153 177/194/176 178/196/178 1184 | f 155/170/154 170/195/177 171/197/179 1185 | f 156/172/156 171/197/179 172/201/181 1186 | f 149/174/157 164/199/180 165/202/182 1187 | f 158/178/160 157/176/158 172/201/181 1188 | f 169/193/175 184/218/196 185/203/183 1189 | f 177/194/176 192/219/197 193/204/184 1190 | f 171/197/179 170/195/177 185/203/183 1191 | f 171/197/179 186/205/185 187/209/187 1192 | f 165/202/182 164/199/180 179/207/186 1193 | f 173/187/169 172/201/181 187/209/187 1194 | f 165/202/182 180/210/188 181/212/190 1195 | f 174/188/170 173/187/169 188/211/189 1196 | f 166/186/168 181/212/190 182/214/192 1197 | f 174/188/170 189/213/191 190/215/193 1198 | f 168/191/173 167/189/171 182/214/192 1199 | f 176/192/174 175/190/172 190/215/193 1200 | f 168/191/173 183/216/194 184/218/196 1201 | f 177/194/176 176/192/174 191/217/195 1202 | f 189/220/191 188/250/189 203/221/198 1203 | f 181/223/190 196/251/212 197/224/200 1204 | f 189/220/191 204/222/199 205/226/201 1205 | f 183/228/194 182/225/192 197/224/200 1206 | f 191/230/195 190/227/193 205/226/201 1207 | f 183/228/194 198/229/202 199/232/204 1208 | f 192/234/197 191/230/195 206/231/203 1209 | f 184/233/196 199/232/204 200/236/206 1210 | f 192/234/197 207/235/205 208/238/207 1211 | f 186/240/185 185/237/183 200/236/206 1212 | f 186/240/185 201/241/208 202/246/210 1213 | f 180/248/188 179/242/186 194/244/209 1214 | f 188/250/189 187/247/187 202/246/210 1215 | f 180/248/188 195/249/211 196/251/212 1216 | f 207/235/205 222/268/227 223/252/213 1217 | f 201/241/208 200/236/206 215/253/214 1218 | f 201/241/208 216/254/215 217/258/217 1219 | f 194/244/209 209/256/216 210/259/218 1220 | f 203/221/198 202/246/210 217/258/217 1221 | f 196/251/212 195/249/211 210/259/218 1222 | f 204/222/199 203/221/198 218/260/219 1223 | f 196/251/212 211/261/220 212/263/222 1224 | f 204/222/199 219/262/221 220/264/223 1225 | f 198/229/202 197/224/200 212/263/222 1226 | f 206/231/203 205/226/201 220/264/223 1227 | f 198/229/202 213/265/224 214/267/226 1228 | f 207/235/205 206/231/203 221/266/225 1229 | f 199/232/204 214/267/226 215/253/214 1230 | f 219/262/221 234/285/242 235/269/228 1231 | f 213/265/224 212/263/222 227/270/229 1232 | f 221/266/225 220/264/223 235/269/228 1233 | f 213/265/224 228/271/230 229/273/232 1234 | f 221/266/225 236/272/231 237/274/233 1235 | f 214/267/226 229/273/232 230/275/234 1236 | f 222/268/227 237/274/233 238/276/235 1237 | f 216/254/215 215/253/214 230/275/234 1238 | f 216/254/215 231/277/236 232/281/238 1239 | f 209/256/216 224/279/237 225/282/239 1240 | f 218/260/219 217/258/217 232/281/238 1241 | f 211/261/220 210/259/218 225/282/239 1242 | f 219/262/221 218/260/219 233/283/240 1243 | f 211/261/220 226/284/241 227/270/229 1244 | f 232/281/238 231/277/236 6/14/14 1245 | f 225/282/239 224/279/237 1/15/15 1246 | f 232/281/238 241/19/19 7/24/24 1247 | f 226/284/241 225/282/239 2/22/22 1248 | f 233/283/240 7/24/24 8/28/28 1249 | f 227/270/229 226/284/241 3/25/25 1250 | f 235/269/228 234/285/242 8/28/28 1251 | f 227/270/229 239/29/29 4/4/4 1252 | f 235/269/228 242/1/1 9/3/3 1253 | f 228/271/230 4/4/4 5/6/6 1254 | f 236/272/231 9/3/3 10/8/8 1255 | f 230/275/234 229/273/232 5/6/6 1256 | f 237/274/233 10/8/8 11/12/12 1257 | f 230/275/234 240/9/9 6/14/14 1258 | -------------------------------------------------------------------------------- /Assets/Bones/CharacterTexture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JuanRinaudo/CodingChallengesKha/82c1ba66426b0b13f8fa2ff92c7b5470266f8eb5/Assets/Bones/CharacterTexture.png -------------------------------------------------------------------------------- /Assets/Common/KenPixel.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JuanRinaudo/CodingChallengesKha/82c1ba66426b0b13f8fa2ff92c7b5470266f8eb5/Assets/Common/KenPixel.ttf -------------------------------------------------------------------------------- /Assets/Common/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Coding Challenges Kha 6 | 7 | 8 | 42 | 43 |
44 | 45 |
46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /Assets/FlowField/flowField.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec4 fragmentColor; 4 | in vec2 texCoord; 5 | out vec4 fragColor; 6 | 7 | uniform sampler2D TEXTURE; 8 | uniform sampler2D FLOW_TEXTURE; 9 | 10 | uniform highp float DELTA_WIDTH; 11 | uniform highp float DELTA_HEIGHT; 12 | 13 | uniform highp float COLOR_MULTIPLY; 14 | uniform highp float SPEED; 15 | 16 | void main() { 17 | highp vec4 flowField = texture(TEXTURE, texCoord); 18 | highp vec4 targetColor = texture(FLOW_TEXTURE, texCoord + vec2((flowField.x - 0.5) * SPEED * DELTA_WIDTH, (flowField.y - 0.5) * SPEED * DELTA_HEIGHT)); 19 | highp vec4 currentColor = texture(FLOW_TEXTURE, texCoord); 20 | highp vec4 color = currentColor * (1 - COLOR_MULTIPLY) + targetColor * COLOR_MULTIPLY; 21 | 22 | fragColor = color; 23 | } -------------------------------------------------------------------------------- /Assets/FlowField/noise.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec4 fragmentColor; 4 | in vec2 texCoord; 5 | out vec4 fragColor; 6 | 7 | uniform highp float TIME; 8 | 9 | uniform highp float DELTA_WIDTH; 10 | uniform highp float DELTA_HEIGHT; 11 | 12 | #define M_PI 3.14159265358979323846 13 | 14 | float rand(vec2 co){return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);} 15 | float rand (vec2 co, float l) {return rand(vec2(rand(co), l));} 16 | float rand (vec2 co, float l, float t) {return rand(vec2(rand(co, l), t));} 17 | 18 | float perlin(vec2 p, float dim, float time) { 19 | vec2 pos = floor(p * dim); 20 | vec2 posx = pos + vec2(1.0, 0.0); 21 | vec2 posy = pos + vec2(0.0, 1.0); 22 | vec2 posxy = pos + vec2(1.0); 23 | 24 | float c = rand(pos, dim, time); 25 | float cx = rand(posx, dim, time); 26 | float cy = rand(posy, dim, time); 27 | float cxy = rand(posxy, dim, time); 28 | 29 | vec2 d = fract(p * dim); 30 | d = -0.5 * cos(d * M_PI) + 0.5; 31 | 32 | float ccx = mix(c, cx, d.x); 33 | float cycxy = mix(cy, cxy, d.x); 34 | float center = mix(ccx, cycxy, d.y); 35 | 36 | return center; 37 | } 38 | 39 | void main() { 40 | fragColor = vec4( 41 | perlin(vec2(texCoord.x, texCoord.y) * (1 / DELTA_WIDTH), 1, TIME), 42 | perlin(vec2(texCoord.y, texCoord.x) * (1 / DELTA_HEIGHT), 1, TIME), 0.0, 1.0 43 | ); 44 | } -------------------------------------------------------------------------------- /Assets/GameAssets/SimpleCarGame/carSedan.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'None' 2 | # Material Count: 7 3 | 4 | newmtl backLight.004 5 | Ns 92.156863 6 | Ka 0.000000 0.000000 0.000000 7 | Kd 1.000000 0.349020 0.227451 8 | Ks 0.330000 0.330000 0.330000 9 | Ke 0.000000 0.000000 0.000000 10 | Ni 1.000000 11 | d 1.000000 12 | illum 2 13 | 14 | newmtl carTire.000 15 | Ns 92.156863 16 | Ka 0.000000 0.000000 0.000000 17 | Kd 0.411765 0.411765 0.411765 18 | Ks 0.330000 0.330000 0.330000 19 | Ke 0.000000 0.000000 0.000000 20 | Ni 1.000000 21 | d 1.000000 22 | illum 2 23 | 24 | newmtl frontLight.004 25 | Ns 92.156863 26 | Ka 0.000000 0.000000 0.000000 27 | Kd 0.956863 1.000000 0.819608 28 | Ks 0.330000 0.330000 0.330000 29 | Ke 0.000000 0.000000 0.000000 30 | Ni 1.000000 31 | d 1.000000 32 | illum 2 33 | 34 | newmtl glass.004 35 | Ns 92.156863 36 | Ka 0.000000 0.000000 0.000000 37 | Kd 0.298039 0.376471 0.466667 38 | Ks 0.330000 0.330000 0.330000 39 | Ke 0.000000 0.000000 0.000000 40 | Ni 1.000000 41 | d 1.000000 42 | illum 2 43 | 44 | newmtl paintRed.004 45 | Ns 92.156863 46 | Ka 0.000000 0.000000 0.000000 47 | Kd 0.909804 0.333333 0.325490 48 | Ks 0.330000 0.330000 0.330000 49 | Ke 0.000000 0.000000 0.000000 50 | Ni 1.000000 51 | d 1.000000 52 | illum 2 53 | 54 | newmtl plastic.004 55 | Ns 92.156863 56 | Ka 0.000000 0.000000 0.000000 57 | Kd 0.376471 0.376471 0.376471 58 | Ks 0.330000 0.330000 0.330000 59 | Ke 0.000000 0.000000 0.000000 60 | Ni 1.000000 61 | d 1.000000 62 | illum 2 63 | 64 | newmtl wheelCover.000 65 | Ns 92.156863 66 | Ka 0.000000 0.000000 0.000000 67 | Kd 0.827451 0.827451 0.827451 68 | Ks 0.330000 0.330000 0.330000 69 | Ke 0.000000 0.000000 0.000000 70 | Ni 1.000000 71 | d 1.000000 72 | illum 2 73 | -------------------------------------------------------------------------------- /Assets/GameAssets/SimpleCarGame/tree.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'None' 2 | # Material Count: 2 3 | 4 | newmtl Leafs 5 | Ns 96.078431 6 | Ka 0.000000 0.000000 0.000000 7 | Kd 0.270588 0.407843 0.400000 8 | Ks 0.330000 0.330000 0.330000 9 | Ke 0.000000 0.000000 0.000000 10 | Ni 1.000000 11 | d 1.000000 12 | illum 2 13 | 14 | newmtl Wood 15 | Ns 96.078431 16 | Ka 0.000000 0.000000 0.000000 17 | Kd 0.666667 0.545098 0.356863 18 | Ks 0.330000 0.330000 0.330000 19 | Ke 0.000000 0.000000 0.000000 20 | Ni 1.000000 21 | d 1.000000 22 | illum 2 23 | -------------------------------------------------------------------------------- /Assets/GameAssets/SimpleCarGame/tree.obj: -------------------------------------------------------------------------------- 1 | # Blender v2.79 (sub 0) OBJ File: '' 2 | # www.blender.org 3 | mtllib tree.mtl 4 | o Mesh1_Oak_Dark_Model 5 | v -0.000000 2.819248 -0.910000 6 | v 0.788086 1.535748 -0.455000 7 | v -0.000000 1.535748 -0.910000 8 | v 0.788086 2.819248 -0.455000 9 | v -0.000000 4.510748 -0.527800 10 | v 0.457087 4.510748 -0.263899 11 | v -0.000000 4.935748 0.000001 12 | v -0.457089 4.510748 -0.263899 13 | v -0.788083 2.819248 -0.455000 14 | v -0.788083 1.535748 -0.455000 15 | v -0.441326 1.272248 -0.254800 16 | v -0.000000 1.272248 -0.509600 17 | v 0.441327 1.272248 -0.254800 18 | v 0.441327 1.272248 0.254800 19 | v 0.788086 1.535748 0.455000 20 | v 0.788086 2.819248 0.455000 21 | v 0.457087 4.510748 0.263901 22 | v -0.000000 4.510748 0.527801 23 | v -0.457089 4.510748 0.263901 24 | v -0.788083 2.819248 0.455000 25 | v -0.788083 1.535748 0.455000 26 | v -0.441326 1.272248 0.254800 27 | v -0.114257 1.272248 -0.114260 28 | v 0.114255 1.272248 -0.114260 29 | v 0.114255 1.272248 0.114256 30 | v -0.000000 1.272248 0.509600 31 | v -0.114257 1.272248 0.114256 32 | v -0.179931 0.002248 -0.179930 33 | v -0.179931 0.002248 0.179930 34 | v 0.179931 0.002248 -0.179930 35 | v 0.179931 0.002248 0.179930 36 | v -0.000000 1.535748 0.910000 37 | v -0.000000 2.819248 0.910000 38 | vt -42.910599 1.236500 39 | vt -31.328501 51.303299 40 | vt -40.325001 51.303299 41 | vt -28.742901 1.236500 42 | vt -38.110802 42.910599 43 | vt -23.943001 28.742901 44 | vt -23.943001 42.910599 45 | vt -38.110802 28.742901 46 | vt 42.910599 -1.968170 47 | vt 31.328501 48.098598 48 | vt 28.742901 -1.968170 49 | vt 40.325001 48.098598 50 | vt -38.110802 -2.216050 51 | vt -26.528601 47.850800 52 | vt -35.525200 47.850800 53 | vt -23.943001 -2.216050 54 | vt 35.525200 51.551201 55 | vt 23.943001 1.484380 56 | vt 38.110802 1.484380 57 | vt 26.528601 51.551201 58 | vt 8.956690 110.905998 59 | vt -26.870100 60.374001 60 | vt 8.956690 60.374001 61 | vt -26.870100 110.905998 62 | vt 1.433070 161.802994 63 | vt -26.870100 93.945297 64 | vt 8.956690 93.945297 65 | vt -19.346500 161.802994 66 | vt -19.346500 73.603104 67 | vt 1.433070 73.603104 68 | vt -8.956690 98.175697 69 | vt -55.173199 96.325500 70 | vt -34.393700 96.325500 71 | vt -44.783501 120.898003 72 | vt -62.696899 99.903702 73 | vt -34.393700 167.761002 74 | vt -55.173199 167.761002 75 | vt -26.870100 99.903702 76 | vt -62.696899 60.374001 77 | vt -26.870100 110.905998 78 | vt -62.696899 110.905998 79 | vt -26.870100 60.374001 80 | vt -62.696899 73.583702 81 | vt -34.751999 56.437500 82 | vt -26.870100 73.583702 83 | vt -54.814999 56.437500 84 | vt 8.956690 98.287300 85 | vt -18.988199 81.141098 86 | vt 1.074800 81.141098 87 | vt -26.870100 98.287300 88 | vt 53.740200 85.935501 89 | vt 25.795300 68.789299 90 | vt 45.858299 68.789299 91 | vt 17.913401 85.935501 92 | vt 53.740200 60.374001 93 | vt 17.913401 110.905998 94 | vt 17.913401 60.374001 95 | vt 53.740200 110.905998 96 | vt 53.740200 96.924500 97 | vt 25.437000 164.781998 98 | vt 17.913401 96.924500 99 | vt 46.216499 164.781998 100 | vt 46.216499 84.964302 101 | vt 35.826801 109.537003 102 | vt 25.437000 84.964302 103 | vt 55.173199 119.047997 104 | vt 44.783501 143.619995 105 | vt 34.393700 119.047997 106 | vt 19.346500 141.770004 107 | vt 8.956690 166.343002 108 | vt -1.433070 141.770004 109 | vt -35.826801 154.981995 110 | vt -46.216499 130.408997 111 | vt -25.437000 130.408997 112 | vt -53.740200 108.841003 113 | vt -25.437000 176.699005 114 | vt -46.216499 176.699005 115 | vt -17.913401 108.841003 116 | vt -53.740200 110.905998 117 | vt -17.913401 60.374001 118 | vt -17.913401 110.905998 119 | vt -53.740200 60.374001 120 | vt -53.740200 36.528198 121 | vt -25.795300 19.382000 122 | vt -17.913401 36.528198 123 | vt -45.858299 19.382000 124 | vt -31.026899 55.889801 125 | vt -13.651800 25.795300 126 | vt -13.651800 45.858299 127 | vt -26.528601 40.325001 128 | vt -35.525200 40.325001 129 | vt -48.402000 45.858299 130 | vt -35.525200 31.328501 131 | vt -48.402000 25.795300 132 | vt -31.026899 15.763800 133 | vt -26.528601 31.328501 134 | vt 26.870100 24.176399 135 | vt -1.074800 7.030190 136 | vt 18.988199 7.030190 137 | vt -8.956690 24.176399 138 | vt 26.870100 110.905998 139 | vt -8.956690 60.374001 140 | vt 26.870100 60.374001 141 | vt -8.956690 110.905998 142 | vt 19.346500 179.677994 143 | vt -8.956690 111.820000 144 | vt 26.870100 111.820000 145 | vt -1.433070 179.677994 146 | vt 26.870100 105.862000 147 | vt 55.173199 173.720001 148 | vt 34.393700 173.720001 149 | vt 62.696899 105.862000 150 | vt 62.696899 110.905998 151 | vt 62.696899 60.374001 152 | vt 26.870100 48.880100 153 | vt 54.814999 31.733801 154 | vt 62.696899 48.880100 155 | vt 34.751999 31.733801 156 | vn -0.9987 0.0516 0.0000 157 | vn 0.0000 -1.0000 0.0000 158 | vn 0.9987 0.0516 0.0000 159 | vn 0.0000 0.0516 -0.9987 160 | vn 0.0000 0.0516 0.9987 161 | vn 0.4977 0.0964 -0.8620 162 | vn 0.5000 0.0000 -0.8660 163 | vn 0.4907 0.1920 -0.8499 164 | vn 0.3405 0.7323 -0.5897 165 | vn -0.3405 0.7323 -0.5897 166 | vn -0.4977 0.0964 -0.8620 167 | vn -0.4907 0.1920 -0.8499 168 | vn -0.5000 0.0000 -0.8660 169 | vn -0.3025 -0.7962 -0.5240 170 | vn 0.3025 -0.7962 -0.5240 171 | vn 0.6050 -0.7962 0.0000 172 | vn 1.0000 -0.0000 0.0000 173 | vn 0.9953 0.0964 0.0000 174 | vn 0.9814 0.1920 0.0000 175 | vn 0.6809 0.7323 0.0000 176 | vn 0.3405 0.7323 0.5897 177 | vn -0.3405 0.7323 0.5897 178 | vn -0.6809 0.7323 0.0000 179 | vn -0.9953 0.0964 -0.0000 180 | vn -0.9814 0.1920 0.0000 181 | vn -0.9953 0.0965 0.0000 182 | vn -1.0000 -0.0000 0.0000 183 | vn -0.6050 -0.7962 0.0000 184 | vn -0.3025 -0.7962 0.5240 185 | vn -0.4977 0.0964 0.8620 186 | vn -0.5000 -0.0000 0.8660 187 | vn -0.4907 0.1920 0.8499 188 | vn 0.4977 0.0964 0.8620 189 | vn 0.4907 0.1920 0.8499 190 | vn 0.4977 0.0965 0.8620 191 | vn 0.5000 -0.0000 0.8660 192 | vn 0.3025 -0.7962 0.5240 193 | usemtl Wood 194 | s 1 195 | f 28/1/1 27/2/1 23/3/1 196 | f 27/2/1 28/1/1 29/4/1 197 | f 30/5/2 29/6/2 28/7/2 198 | f 29/6/2 30/5/2 31/8/2 199 | f 30/9/3 25/10/3 31/11/3 200 | f 25/10/3 30/9/3 24/12/3 201 | f 30/13/4 23/14/4 24/15/4 202 | f 23/14/4 30/13/4 28/16/4 203 | f 25/17/5 29/18/5 31/19/5 204 | f 29/18/5 25/17/5 27/20/5 205 | usemtl Leafs 206 | f 1/21/6 2/22/7 3/23/7 207 | f 2/22/7 1/21/6 4/24/6 208 | f 5/25/8 4/26/6 1/27/6 209 | f 4/26/6 5/25/8 6/28/8 210 | f 6/29/9 5/30/9 7/31/9 211 | f 5/32/10 8/33/10 7/34/10 212 | f 1/35/11 8/36/12 5/37/12 213 | f 8/36/12 1/35/11 9/38/11 214 | f 3/39/13 9/40/11 1/41/11 215 | f 9/40/11 3/39/13 10/42/13 216 | f 3/43/14 11/44/14 10/45/14 217 | f 11/44/14 3/43/14 12/46/14 218 | f 3/47/15 13/48/15 12/49/15 219 | f 13/48/15 3/47/15 2/50/15 220 | f 2/51/16 14/52/16 13/53/16 221 | f 14/52/16 2/51/16 15/54/16 222 | f 2/55/17 16/56/18 15/57/17 223 | f 16/56/18 2/55/17 4/58/18 224 | f 4/59/18 17/60/19 16/61/18 225 | f 17/60/19 4/59/18 6/62/19 226 | f 6/63/20 7/64/20 17/65/20 227 | f 17/66/21 7/67/21 18/68/21 228 | f 18/69/22 7/70/22 19/71/22 229 | f 7/72/23 8/73/23 19/74/23 230 | f 9/75/24 19/76/25 8/77/25 231 | f 19/76/25 9/75/24 20/78/26 232 | f 9/79/24 21/80/27 20/81/26 233 | f 21/80/27 9/79/24 10/82/27 234 | f 10/83/28 22/84/28 21/85/28 235 | f 22/84/28 10/83/28 11/86/28 236 | f 12/87/2 22/88/2 11/89/2 237 | f 22/88/2 12/87/2 23/90/2 238 | f 23/90/2 12/87/2 24/91/2 239 | f 24/91/2 12/87/2 13/92/2 240 | f 24/91/2 13/92/2 25/93/2 241 | f 14/94/2 25/93/2 13/92/2 242 | f 26/95/2 25/93/2 14/94/2 243 | f 26/95/2 27/96/2 25/93/2 244 | f 22/88/2 27/96/2 26/95/2 245 | f 27/96/2 22/88/2 23/90/2 246 | f 32/97/29 22/98/29 26/99/29 247 | f 22/98/29 32/97/29 21/100/29 248 | f 33/101/30 21/102/31 32/103/31 249 | f 21/102/31 33/101/30 20/104/30 250 | f 18/105/32 20/106/30 33/107/30 251 | f 20/106/30 18/105/32 19/108/32 252 | f 33/109/33 17/110/34 18/111/34 253 | f 17/110/34 33/109/33 16/112/35 254 | f 32/103/36 16/113/35 33/101/33 255 | f 16/113/35 32/103/36 15/114/36 256 | f 32/115/37 14/116/37 15/117/37 257 | f 14/116/37 32/115/37 26/118/37 258 | -------------------------------------------------------------------------------- /Assets/GameOfLife/gameOfLife.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec4 fragmentColor; 4 | in vec2 texCoord; 5 | out vec4 fragColor; 6 | 7 | uniform sampler2D TEXTURE; 8 | uniform float DELTA_WIDTH; 9 | uniform float DELTA_HEIGHT; 10 | 11 | uniform int SOLITUDE; 12 | uniform int OVERPOPULATION; 13 | uniform int POPULATE; 14 | 15 | void main() { 16 | int neighbors = 17 | int(texture(TEXTURE, texCoord + vec2(-DELTA_WIDTH, -DELTA_HEIGHT)).r) + 18 | int(texture(TEXTURE, texCoord + vec2(-DELTA_WIDTH, 0)).r) + 19 | int(texture(TEXTURE, texCoord + vec2(-DELTA_WIDTH, DELTA_HEIGHT)).r) + 20 | int(texture(TEXTURE, texCoord + vec2(0, -DELTA_HEIGHT)).r) + 21 | int(texture(TEXTURE, texCoord + vec2(0, DELTA_HEIGHT)).r) + 22 | int(texture(TEXTURE, texCoord + vec2(DELTA_WIDTH, -DELTA_HEIGHT)).r) + 23 | int(texture(TEXTURE, texCoord + vec2(DELTA_WIDTH, 0)).r) + 24 | int(texture(TEXTURE, texCoord + vec2(DELTA_WIDTH, DELTA_HEIGHT)).r); 25 | 26 | vec4 color = texture(TEXTURE, texCoord); 27 | if(color.r > 0) { 28 | if(neighbors <= SOLITUDE || neighbors >= OVERPOPULATION) { 29 | color = vec4(0, 0, 0, 1); 30 | } 31 | } else { 32 | if(neighbors == POPULATE) { 33 | color = vec4(1, 1, 1, 1); 34 | } 35 | } 36 | 37 | fragColor = color; 38 | } -------------------------------------------------------------------------------- /Assets/GameOfLife/gameOfLifeMathOnly.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec4 fragmentColor; 4 | in vec2 texCoord; 5 | out vec4 fragColor; 6 | 7 | uniform sampler2D TEXTURE; 8 | uniform lowp float DELTA_WIDTH; 9 | uniform lowp float DELTA_HEIGHT; 10 | 11 | uniform int SOLITUDE; 12 | uniform int OVERPOPULATION; 13 | uniform int POPULATE; 14 | 15 | void main() { 16 | int neighbors = int( 17 | (texture(TEXTURE, texCoord + vec2(-DELTA_WIDTH, -DELTA_HEIGHT)) + 18 | texture(TEXTURE, texCoord + vec2(0, -DELTA_HEIGHT)) + 19 | texture(TEXTURE, texCoord + vec2(-DELTA_WIDTH, 0)) + 20 | texture(TEXTURE, texCoord + vec2(DELTA_WIDTH, -DELTA_HEIGHT)) + 21 | texture(TEXTURE, texCoord + vec2(DELTA_WIDTH, 0)) + 22 | texture(TEXTURE, texCoord + vec2(-DELTA_WIDTH, DELTA_HEIGHT)) + 23 | texture(TEXTURE, texCoord + vec2(0, DELTA_HEIGHT)) + 24 | texture(TEXTURE, texCoord + vec2(DELTA_WIDTH, DELTA_HEIGHT))).r 25 | ); 26 | 27 | lowp vec4 color = texture(TEXTURE, texCoord); 28 | lowp float life = color.r; 29 | lowp float solitude = clamp(SOLITUDE - neighbors + 1, 0, life); 30 | lowp float overpulated = clamp(neighbors - OVERPOPULATION + 1, 0, life); 31 | lowp float populate = clamp(clamp(1 - abs(neighbors - POPULATE), 0, 1) - life, 0, 1); 32 | life = clamp(life - solitude - overpulated + populate, 0, 1); 33 | 34 | fragColor = vec4(life, life, life, 1.0); 35 | } -------------------------------------------------------------------------------- /Assets/GameOfLife/gameOfLifeNoBranches.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec4 fragmentColor; 4 | in vec2 texCoord; 5 | out vec4 fragColor; 6 | 7 | uniform sampler2D TEXTURE; 8 | uniform lowp float DELTA_WIDTH; 9 | uniform lowp float DELTA_HEIGHT; 10 | 11 | uniform int SOLITUDE; 12 | uniform int OVERPOPULATION; 13 | uniform int POPULATE; 14 | 15 | void main() { 16 | int neighbors = int( 17 | (texture(TEXTURE, texCoord + vec2(-DELTA_WIDTH, -DELTA_HEIGHT)) + 18 | texture(TEXTURE, texCoord + vec2(-DELTA_WIDTH, 0)) + 19 | texture(TEXTURE, texCoord + vec2(-DELTA_WIDTH, DELTA_HEIGHT)) + 20 | texture(TEXTURE, texCoord + vec2(0, -DELTA_HEIGHT)) + 21 | texture(TEXTURE, texCoord + vec2(0, DELTA_HEIGHT)) + 22 | texture(TEXTURE, texCoord + vec2(DELTA_WIDTH, -DELTA_HEIGHT)) + 23 | texture(TEXTURE, texCoord + vec2(DELTA_WIDTH, 0)) + 24 | texture(TEXTURE, texCoord + vec2(DELTA_WIDTH, DELTA_HEIGHT))).r 25 | ); 26 | 27 | lowp vec4 color = texture(TEXTURE, texCoord); 28 | lowp float life = color.r; 29 | lowp float solitude = float(life > 0 && neighbors <= SOLITUDE); 30 | lowp float overpulated = float(life > 0 && neighbors >= OVERPOPULATION); 31 | lowp float populate = float(life == 0 && neighbors == POPULATE); 32 | life = clamp(life - solitude - overpulated + populate, 0, 1); 33 | 34 | fragColor = vec4(life, life, life, 1.0); 35 | } -------------------------------------------------------------------------------- /Assets/ImageSlideshow/Images/TestImage001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JuanRinaudo/CodingChallengesKha/82c1ba66426b0b13f8fa2ff92c7b5470266f8eb5/Assets/ImageSlideshow/Images/TestImage001.png -------------------------------------------------------------------------------- /Assets/ImageSlideshow/Images/TestImage002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JuanRinaudo/CodingChallengesKha/82c1ba66426b0b13f8fa2ff92c7b5470266f8eb5/Assets/ImageSlideshow/Images/TestImage002.png -------------------------------------------------------------------------------- /Assets/ImageSlideshow/Shaders/imageFade.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec4 fragmentColor; 4 | in vec2 texCoord; 5 | out vec4 fragColor; 6 | 7 | uniform sampler2D IMAGE; 8 | uniform sampler2D NEXT_IMAGE; 9 | uniform float TIME; 10 | 11 | void main() { 12 | vec4 texcolor = texture(IMAGE, texCoord); 13 | vec4 color = texcolor * fragmentColor; 14 | color.rgb *= color.a; 15 | fragColor = color; 16 | } -------------------------------------------------------------------------------- /Assets/Images/Lenna.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JuanRinaudo/CodingChallengesKha/82c1ba66426b0b13f8fa2ff92c7b5470266f8eb5/Assets/Images/Lenna.png -------------------------------------------------------------------------------- /Assets/Images/Test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JuanRinaudo/CodingChallengesKha/82c1ba66426b0b13f8fa2ff92c7b5470266f8eb5/Assets/Images/Test.png -------------------------------------------------------------------------------- /Assets/Models/carFormula.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'None' 2 | # Material Count: 6 3 | 4 | newmtl carTire 5 | Ns 94.117647 6 | Ka 0.000000 0.000000 0.000000 7 | Kd 0.411765 0.411765 0.411765 8 | Ks 0.330000 0.330000 0.330000 9 | Ke 0.000000 0.000000 0.000000 10 | Ni 1.000000 11 | d 1.000000 12 | illum 2 13 | 14 | newmtl glass 15 | Ns 94.117647 16 | Ka 0.000000 0.000000 0.000000 17 | Kd 0.298039 0.376471 0.466667 18 | Ks 0.330000 0.330000 0.330000 19 | Ke 0.000000 0.000000 0.000000 20 | Ni 1.000000 21 | d 1.000000 22 | illum 2 23 | 24 | newmtl paintRed 25 | Ns 94.117647 26 | Ka 0.000000 0.000000 0.000000 27 | Kd 0.909804 0.333333 0.325490 28 | Ks 0.330000 0.330000 0.330000 29 | Ke 0.000000 0.000000 0.000000 30 | Ni 1.000000 31 | d 1.000000 32 | illum 2 33 | 34 | newmtl paintWhite 35 | Ns 94.117647 36 | Ka 0.000000 0.000000 0.000000 37 | Kd 0.952941 0.976471 0.960784 38 | Ks 0.330000 0.330000 0.330000 39 | Ke 0.000000 0.000000 0.000000 40 | Ni 1.000000 41 | d 1.000000 42 | illum 2 43 | 44 | newmtl plastic 45 | Ns 94.117647 46 | Ka 0.000000 0.000000 0.000000 47 | Kd 0.376471 0.376471 0.376471 48 | Ks 0.330000 0.330000 0.330000 49 | Ke 0.000000 0.000000 0.000000 50 | Ni 1.000000 51 | d 1.000000 52 | illum 2 53 | 54 | newmtl wheelCover 55 | Ns 94.117647 56 | Ka 0.000000 0.000000 0.000000 57 | Kd 0.827451 0.827451 0.827451 58 | Ks 0.330000 0.330000 0.330000 59 | Ke 0.000000 0.000000 0.000000 60 | Ni 1.000000 61 | d 1.000000 62 | illum 2 63 | -------------------------------------------------------------------------------- /Assets/PostProcessingShaders/postBlackAndWhite.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec2 texCoord; 4 | out vec4 FragColor; 5 | 6 | uniform sampler2D tex; 7 | 8 | void main() { 9 | vec4 texcolor = texture(tex, texCoord); 10 | texcolor.rgb = vec3(texcolor.r + texcolor.g + texcolor.b) / 3.0; 11 | FragColor = vec4(texcolor.rgb, 1.0); 12 | } -------------------------------------------------------------------------------- /Assets/PostProcessingShaders/postBlur.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec2 texCoord; 4 | out vec4 FragColor; 5 | 6 | uniform sampler2D tex; 7 | uniform int BLUR_VALUE; 8 | uniform vec2 RENDER_SIZE; 9 | 10 | void main() { 11 | vec4 texcolor = vec4(0.0); 12 | vec2 textureSizeInv = vec2(1.0, 1.0) / RENDER_SIZE; 13 | vec2 delta = vec2(BLUR_VALUE / 2.0, BLUR_VALUE / 2.0) * textureSizeInv; 14 | for(int i = 0; i < BLUR_VALUE; i++) { 15 | for(int j = 0; j < BLUR_VALUE; j++) { 16 | texcolor += texture(tex, texCoord + vec2(i, j) * textureSizeInv - delta); 17 | } 18 | } 19 | texcolor /= BLUR_VALUE * BLUR_VALUE; 20 | FragColor = texcolor; 21 | } -------------------------------------------------------------------------------- /Assets/PostProcessingShaders/postColorCorrection.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec2 texCoord; 4 | out vec4 FragColor; 5 | 6 | uniform sampler2D tex; 7 | uniform float RED; 8 | uniform float GREEN; 9 | uniform float BLUE; 10 | uniform float CONTRAST; 11 | uniform float BRIGHTNESS; 12 | uniform float TEMPERATURE; 13 | uniform float TINT; 14 | uniform float GAMMA; 15 | uniform float HUE; 16 | uniform float SATURATION; 17 | uniform float LUMINATION; 18 | 19 | vec4 rgbToHsl(vec4 col) 20 | { 21 | float maxComponent = max(col.r, max(col.g,col.b)); 22 | float minComponent = min(col.r, min(col.g,col.b)); 23 | float dif = maxComponent - minComponent; 24 | float add = maxComponent + minComponent; 25 | vec4 outColor = vec4(0.0, 0.0, 0.0, col.a); 26 | 27 | if (minComponent == maxComponent) { 28 | outColor.r = 0.0; 29 | } else if (col.r == maxComponent) { 30 | outColor.r = mod(((60.0 * (col.g - col.b) / dif) + 360.0), 360.0); 31 | } else if (col.g == maxComponent) { 32 | outColor.r = (60.0 * (col.b - col.r) / dif) + 120.0; 33 | } else { 34 | outColor.r = (60.0 * (col.r - col.g) / dif) + 240.0; 35 | } 36 | 37 | outColor.b = 0.5 * add; 38 | 39 | if (outColor.b == 0.0) { 40 | outColor.g = 0.0; 41 | } else if (outColor.b <= 0.5) { 42 | outColor.g = dif / add; 43 | } else { 44 | outColor.g = dif / (2.0 - add); 45 | } 46 | 47 | outColor.r /= 360.0; 48 | 49 | return outColor; 50 | } 51 | 52 | float hueToRgb(float p, float q, float h) 53 | { 54 | if (h < 0.0) { 55 | h += 1.0; 56 | } else if (h > 1.0) { 57 | h -= 1.0; 58 | } 59 | 60 | if ((h * 6.0) < 1.0) { 61 | return p + (q - p) * h * 6.0; 62 | } else if ((h * 2.0) < 1.0) { 63 | return q; 64 | } else if ((h * 3.0) < 2.0) { 65 | return p + (q - p) * ((2.0 / 3.0) - h) * 6.0; 66 | } else { 67 | return p; 68 | } 69 | } 70 | 71 | vec4 hslToRgb(vec4 col) 72 | { 73 | vec4 outColor = vec4(0.0, 0.0, 0.0, col.a); 74 | float p, q, tr, tg, tb; 75 | if (col.b <= 0.5) { 76 | q = col.b * (1.0 + col.g); 77 | } else { 78 | q = col.b + col.g - (col.b * col.g); 79 | } 80 | 81 | p = 2.0 * col.b - q; 82 | tr = col.r + (1.0 / 3.0); 83 | tg = col.r; 84 | tb = col.r - (1.0 / 3.0); 85 | 86 | outColor.r = hueToRgb(p, q, tr); 87 | outColor.g = hueToRgb(p, q, tg); 88 | outColor.b = hueToRgb(p, q, tb); 89 | 90 | return outColor; 91 | } 92 | 93 | void main() { 94 | vec4 texcolor = texture(tex, texCoord); 95 | 96 | vec4 hsl = rgbToHsl(texcolor); 97 | hsl.x = mod(hsl.x + HUE, 1.0); 98 | hsl.y = clamp(hsl.y + SATURATION, 0.0, 1.0); 99 | hsl.z = clamp(hsl.z + LUMINATION, 0.0, 1.0); 100 | 101 | texcolor = hslToRgb(hsl); 102 | 103 | texcolor = (texcolor - 0.5) * CONTRAST + 0.5 + BRIGHTNESS; 104 | texcolor = vec4(pow(abs(texcolor.r), GAMMA), pow(abs(texcolor.g), GAMMA), pow(abs(texcolor.b), GAMMA), 1.0); 105 | 106 | texcolor.r = texcolor.r * RED - TEMPERATURE; 107 | texcolor.g = texcolor.g * GREEN + TINT; 108 | texcolor.b = texcolor.b * BLUE + TEMPERATURE; 109 | 110 | FragColor = texcolor; 111 | } -------------------------------------------------------------------------------- /Assets/PostProcessingShaders/postColorQuantization.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec2 texCoord; 4 | out vec4 FragColor; 5 | 6 | uniform sampler2D tex; 7 | uniform int COLOR_QUANTIZATION; 8 | 9 | void main() { 10 | vec4 texcolor = texture(tex, texCoord); 11 | FragColor = round(texcolor * COLOR_QUANTIZATION) / COLOR_QUANTIZATION; 12 | } -------------------------------------------------------------------------------- /Assets/PostProcessingShaders/postFXAA.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec2 texCoord; 4 | out vec4 FragColor; 5 | 6 | uniform sampler2D tex; 7 | uniform float FXAA_SPAN_MAX = 10; 8 | uniform float FXAA_REDUCE_MIN = 0.03; 9 | uniform float FXAA_REDUCE_MUL = 0.1; 10 | uniform vec2 RENDER_SIZE; 11 | 12 | vec4 FXAA() { 13 | vec4 color; 14 | mediump vec2 inverseVP = vec2(1.0 / RENDER_SIZE.x, 1.0 / RENDER_SIZE.y); 15 | vec3 rgbNW = texture(tex, texCoord + vec2(-1.0, -1.0) * inverseVP).xyz; 16 | vec3 rgbNE = texture(tex, texCoord + vec2(1.0, -1.0) * inverseVP).xyz; 17 | vec3 rgbSW = texture(tex, texCoord + vec2(-1.0, 1.0) * inverseVP).xyz; 18 | vec3 rgbSE = texture(tex, texCoord + vec2(1.0, 1.0) * inverseVP).xyz; 19 | vec4 texColor = texture(tex, texCoord); 20 | vec3 rgbM = texColor.xyz; 21 | vec3 luma = vec3(0.299, 0.587, 0.114); 22 | float lumaNW = dot(rgbNW, luma); 23 | float lumaNE = dot(rgbNE, luma); 24 | float lumaSW = dot(rgbSW, luma); 25 | float lumaSE = dot(rgbSE, luma); 26 | float lumaM = dot(rgbM, luma); 27 | float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); 28 | float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); 29 | 30 | mediump vec2 dir; 31 | dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); 32 | dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); 33 | 34 | float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * 35 | (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); 36 | 37 | float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce); 38 | dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), 39 | max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), 40 | dir * rcpDirMin)) * inverseVP; 41 | 42 | vec3 rgbA = 0.5 * ( 43 | texture(tex, gl_FragCoord.xy * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz + 44 | texture(tex, gl_FragCoord.xy * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz); 45 | vec3 rgbB = rgbA * 0.5 + 0.25 * ( 46 | texture(tex, gl_FragCoord.xy * inverseVP + dir * -0.5).xyz + 47 | texture(tex, gl_FragCoord.xy * inverseVP + dir * 0.5).xyz); 48 | 49 | float lumaB = dot(rgbB, luma); 50 | if ((lumaB < lumaMin) || (lumaB > lumaMax)) 51 | color = vec4(rgbA, texColor.a); 52 | else 53 | color = vec4(rgbB, texColor.a); 54 | return color; 55 | } 56 | 57 | void main() { 58 | FragColor = FXAA(); 59 | } 60 | -------------------------------------------------------------------------------- /Assets/PostProcessingShaders/postGaussianBlur.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec2 texCoord; 4 | out vec4 FragColor; 5 | 6 | uniform sampler2D tex; 7 | uniform int BLUR_SIZE; 8 | uniform float SIGMA; 9 | uniform vec2 DIRECTION; 10 | uniform vec2 RENDER_SIZE; 11 | 12 | const float PI = 3.14159265; 13 | 14 | void main() { 15 | vec3 incrementalGaussian; 16 | incrementalGaussian.x = 1.0 / (sqrt(2.0 * PI) * SIGMA); 17 | incrementalGaussian.y = exp(-0.5 / (SIGMA * SIGMA)); 18 | incrementalGaussian.z = incrementalGaussian.y * incrementalGaussian.y; 19 | 20 | vec4 avgValue = vec4(0.0); 21 | float coefficientSum = 0.0; 22 | 23 | avgValue += texture(tex, texCoord) * incrementalGaussian.x; 24 | coefficientSum += incrementalGaussian.x; 25 | incrementalGaussian.xy *= incrementalGaussian.yz; 26 | 27 | vec2 texSizeInverted = vec2(1.0, 1.0) / RENDER_SIZE; 28 | for (float i = 1.0; i <= BLUR_SIZE; i++) { 29 | avgValue += texture(tex, texCoord - i * texSizeInverted * 30 | DIRECTION) * incrementalGaussian.x; 31 | avgValue += texture(tex, texCoord + i * texSizeInverted * 32 | DIRECTION) * incrementalGaussian.x; 33 | coefficientSum += 2.0 * incrementalGaussian.x; 34 | incrementalGaussian.xy *= incrementalGaussian.yz; 35 | } 36 | 37 | FragColor = avgValue / coefficientSum; 38 | } -------------------------------------------------------------------------------- /Assets/PostProcessingShaders/postPixelate.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec2 texCoord; 4 | out vec4 FragColor; 5 | 6 | uniform sampler2D tex; 7 | uniform vec2 CELL_SIZE; 8 | uniform vec2 RENDER_SIZE; 9 | 10 | void main() { 11 | vec4 texcolor = vec4(0.0); 12 | vec2 texSizeInverted = vec2(1.0, 1.0) / RENDER_SIZE; 13 | vec2 cellPosition = floor(texCoord * (RENDER_SIZE / CELL_SIZE)) / (RENDER_SIZE / CELL_SIZE); 14 | 15 | texcolor += texture(tex, vec2(cellPosition.x, cellPosition.y)) * 0.2; 16 | texcolor += texture(tex, vec2(cellPosition.x + CELL_SIZE.x * 0.5 * texSizeInverted.x, cellPosition.y + CELL_SIZE.y * 0.5 * texSizeInverted.y)) * 0.2; 17 | texcolor += texture(tex, vec2(cellPosition.x + CELL_SIZE.x * texSizeInverted.x, cellPosition.y)) * 0.2; 18 | texcolor += texture(tex, vec2(cellPosition.x, cellPosition.y + CELL_SIZE.y * texSizeInverted.y)) * 0.2; 19 | texcolor += texture(tex, vec2(cellPosition.x + CELL_SIZE.x * texSizeInverted.x, cellPosition.y + CELL_SIZE.y * texSizeInverted.y)) * 0.2; 20 | 21 | FragColor = texcolor; 22 | } -------------------------------------------------------------------------------- /Assets/Shaders/colored.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec4 fragmentColor; 4 | out vec4 fragColor; 5 | 6 | void main() { 7 | vec4 color = fragmentColor; 8 | color.rgb *= color.a; 9 | fragColor = color; 10 | } -------------------------------------------------------------------------------- /Assets/Shaders/colored.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec3 position; 4 | in vec4 color; 5 | 6 | out vec4 fragmentColor; 7 | 8 | uniform mat4 MVP_MATRIX; 9 | 10 | void main() { 11 | gl_Position = MVP_MATRIX * vec4(position, 1.0); 12 | fragmentColor = color; 13 | } -------------------------------------------------------------------------------- /Assets/Shaders/coloredBones.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | const int MAX_JOINTS = 50;//max joints allowed in a skeleton 4 | const int MAX_WEIGHTS = 3;//max number of joints that can affect a vertex 5 | 6 | in vec3 position; 7 | in vec3 normal; 8 | in vec2 texuv; 9 | in vec4 color; 10 | in vec4 jointIndex; 11 | in vec4 jointWeight; 12 | 13 | out vec4 fragmentColor; 14 | 15 | uniform mat4 JOINT_TRANSFORMS[MAX_JOINTS]; 16 | uniform mat4 MVP_MATRIX; 17 | 18 | void main() { 19 | vec4 newVertex; 20 | vec4 newNormal; 21 | int index; 22 | 23 | index = int(jointIndex.x); 24 | newVertex = (JOINT_TRANSFORMS[index] * vec4(position, 1.0)) * jointWeight.x; 25 | newNormal = (JOINT_TRANSFORMS[index] * vec4(normal, 0.0)) * jointWeight.x; 26 | index = int(jointIndex.y); 27 | newVertex = (JOINT_TRANSFORMS[index] * vec4(position, 1.0)) * jointWeight.y + newVertex; 28 | newNormal = (JOINT_TRANSFORMS[index] * vec4(normal, 0.0)) * jointWeight.y + newNormal; 29 | index = int(jointIndex.z); 30 | newVertex = (JOINT_TRANSFORMS[index] * vec4(position, 1.0)) * jointWeight.z + newVertex; 31 | newNormal = (JOINT_TRANSFORMS[index] * vec4(normal, 0.0)) * jointWeight.z + newNormal; 32 | index = int(jointIndex.w); 33 | newVertex = (JOINT_TRANSFORMS[index] * vec4(position, 1.0)) * jointWeight.w + newVertex; 34 | newNormal = (JOINT_TRANSFORMS[index] * vec4(normal, 0.0)) * jointWeight.w + newNormal; 35 | 36 | gl_Position = MVP_MATRIX * vec4(newVertex.xyz, 1.0); 37 | fragmentColor = color; 38 | } -------------------------------------------------------------------------------- /Assets/Shaders/directionalLighting.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec3 fragmentPosition; 4 | in vec4 fragmentColor; 5 | in vec3 fragmentNormal; 6 | out vec4 fragColor; 7 | 8 | uniform vec4 LIGHT_DIRECTION; 9 | uniform vec4 LIGHT_COLOR; 10 | uniform vec4 AMBIENT_COLOR; 11 | 12 | void main() { 13 | vec3 ambient = AMBIENT_COLOR.rgb; 14 | ambient.rgb *= AMBIENT_COLOR.a; 15 | 16 | float diff = max(dot(fragmentNormal, LIGHT_DIRECTION.xyz), 0.0); 17 | vec3 diffuse = diff * LIGHT_COLOR.rgb; 18 | diffuse.rgb *= LIGHT_COLOR.a; 19 | 20 | // vec3 lightDirection = normalize(LIGHT_POSITION.xyz - fragmentPosition.xyz); //For point lights 21 | 22 | // float specularStrength = 0.1; //For specular 23 | // vec3 viewDir = normalize(VIEW_POSITION - fragmentPosition); 24 | // vec3 reflectDir = reflect(-LIGHT_DIRECTION, fragmentNormal); 25 | // float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32); 26 | // vec3 specular = specularStrength * spec * LIGHT_COLOR; 27 | 28 | vec4 color = vec4((ambient + diffuse) * fragmentColor.rgb, fragmentColor.a); 29 | color.rgb *= color.a; 30 | fragColor = color; 31 | } -------------------------------------------------------------------------------- /Assets/Shaders/directionalLighting.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec3 position; 4 | in vec3 normal; 5 | in vec2 texuv; 6 | in vec4 color; 7 | 8 | out vec3 fragmentPosition; 9 | out vec4 fragmentColor; 10 | out vec3 fragmentNormal; 11 | out vec2 texCoord; 12 | 13 | uniform mat4 MVP_MATRIX; 14 | uniform mat4 MODEL_MATRIX; 15 | uniform mat3 NORMAL_MATRIX; 16 | 17 | void main() { 18 | gl_Position = MVP_MATRIX * vec4(position, 1.0); 19 | fragmentColor = color; 20 | fragmentPosition = vec3(MODEL_MATRIX * vec4(position, 1.0)); 21 | fragmentNormal = normalize(NORMAL_MATRIX * normal); 22 | texCoord = texuv; 23 | } -------------------------------------------------------------------------------- /Assets/Shaders/normals.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec4 fragmentColor; 4 | in vec3 fragmentNormal; 5 | 6 | out vec4 fragColor; 7 | 8 | void main() { 9 | vec4 color = vec4(abs(fragmentNormal), 1.0); 10 | color.rgb *= color.a; 11 | fragColor = color; 12 | } -------------------------------------------------------------------------------- /Assets/Shaders/normals.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec3 position; 4 | in vec3 normal; 5 | in vec4 color; 6 | 7 | out vec4 fragmentColor; 8 | out vec3 fragmentNormal; 9 | 10 | uniform mat4 MVP_MATRIX; 11 | 12 | void main() { 13 | gl_Position = MVP_MATRIX * vec4(position, 1.0); 14 | fragmentNormal = normalize(normal); 15 | fragmentColor = color; 16 | } -------------------------------------------------------------------------------- /Assets/Shaders/simple.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | out vec4 fragColor; 4 | 5 | void main() { 6 | fragColor = vec4(1.0, 0.0, 0.0, 1.0); 7 | } -------------------------------------------------------------------------------- /Assets/Shaders/simple.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec3 pos; 4 | 5 | uniform mat4 MVP_MATRIX; 6 | 7 | void main() { 8 | gl_Position = MVP_MATRIX * vec4(pos, 1.0); 9 | } -------------------------------------------------------------------------------- /Assets/Shaders/striped.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec4 fragmentColor; 4 | in vec2 texCoord; 5 | out vec4 fragColor; 6 | 7 | float rand(vec2 v2){ 8 | return fract(sin(dot(v2.xy, vec2(12.9898, 78.233))) * 43758.5453); 9 | } 10 | 11 | void main() { 12 | vec2 t = floor(texCoord * 10); 13 | vec4 color = (rand(t) * 0.5 + 0.5) * fragmentColor; 14 | color.rgb *= color.a; 15 | fragColor = color; 16 | } -------------------------------------------------------------------------------- /Assets/Shaders/testColored.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec3 position; 4 | in vec4 color; 5 | 6 | out vec4 fragmentColor; 7 | 8 | uniform mat4 MVP_MATRIX; 9 | 10 | void main() { 11 | gl_Position = MVP_MATRIX * vec4(position, 1.0); 12 | fragmentColor = vec4(position, 1.0); 13 | } -------------------------------------------------------------------------------- /Assets/Shaders/textureCutoffMesh.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec4 fragmentColor; 4 | in vec3 fragmentNormal; 5 | in vec2 texCoord; 6 | out vec4 fragColor; 7 | 8 | uniform float CUTOFF_VALUE; 9 | uniform sampler2D TEXTURE; 10 | 11 | uniform vec4 LIGHT_DIRECTION; 12 | uniform vec4 LIGHT_COLOR; 13 | uniform vec4 AMBIENT_COLOR; 14 | 15 | void main() { 16 | vec4 texcolor = texture(TEXTURE, texCoord); 17 | if(texcolor.x > CUTOFF_VALUE) { 18 | discard; 19 | } 20 | vec3 lightDirection = normalize(LIGHT_DIRECTION).xyz; 21 | vec4 color = max(fragmentColor * LIGHT_COLOR * dot(fragmentNormal, lightDirection), AMBIENT_COLOR); 22 | color.rgb *= color.a; 23 | fragColor = color; 24 | } -------------------------------------------------------------------------------- /Assets/Shaders/textured.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec4 fragmentColor; 4 | in vec2 texCoord; 5 | out vec4 fragColor; 6 | 7 | uniform sampler2D TEXTURE; 8 | 9 | void main() { 10 | vec4 texcolor = texture(TEXTURE, texCoord); 11 | vec4 color = texcolor * fragmentColor; 12 | color.rgb *= color.a; 13 | fragColor = color; 14 | } -------------------------------------------------------------------------------- /Assets/Shaders/textured.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec3 position; 4 | in vec2 texuv; 5 | in vec4 color; 6 | 7 | out vec4 fragmentColor; 8 | out vec2 texCoord; 9 | 10 | uniform mat4 MVP_MATRIX; 11 | 12 | void main() { 13 | gl_Position = MVP_MATRIX * vec4(position, 1.0); 14 | fragmentColor = color; 15 | texCoord = texuv; 16 | } -------------------------------------------------------------------------------- /Assets/Shaders/texturedBillboard.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec4 fragmentColor; 4 | in vec2 texCoord; 5 | out vec4 fragColor; 6 | 7 | uniform sampler2D TEXTURE; 8 | 9 | void main() { 10 | vec4 texcolor = texture(TEXTURE, texCoord); 11 | if(texcolor.a < 1) { 12 | discard; 13 | } 14 | vec4 color = texcolor * fragmentColor; 15 | color.rgb *= color.a; 16 | fragColor = color; 17 | } -------------------------------------------------------------------------------- /Assets/Shaders/texturedBillboard.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec3 position; 4 | in vec2 texuv; 5 | in vec4 color; 6 | 7 | out vec4 fragmentColor; 8 | out vec2 texCoord; 9 | 10 | uniform mat4 MV_MATRIX; 11 | uniform mat4 PROJECTION; 12 | 13 | void main() { 14 | gl_Position = PROJECTION * (MV_MATRIX * vec4(.0, .0, .0, 1.0) + vec4(position.xy, .0, .0)); 15 | fragmentColor = color; 16 | texCoord = texuv; 17 | } -------------------------------------------------------------------------------- /Assets/Shaders/texturedBones.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | const int MAX_JOINTS = 50;//max joints allowed in a skeleton 4 | 5 | in vec3 position; 6 | in vec3 normal; 7 | in vec2 texuv; 8 | in vec4 color; 9 | in vec4 jointIndex; 10 | in vec4 jointWeight; 11 | 12 | out vec4 fragmentColor; 13 | out vec2 texCoord; 14 | 15 | uniform mat4 JOINT_TRANSFORMS[MAX_JOINTS]; 16 | 17 | uniform mat4 MVP_MATRIX; 18 | 19 | void main() { 20 | vec4 newVertex; 21 | vec4 newNormal; 22 | int index; 23 | 24 | index = int(jointIndex.x); 25 | newVertex = (JOINT_TRANSFORMS[index] * vec4(position, 1.0)) * jointWeight.x; 26 | newNormal = (JOINT_TRANSFORMS[index] * vec4(normal, 0.0)) * jointWeight.x; 27 | index = int(jointIndex.y); 28 | newVertex = (JOINT_TRANSFORMS[index] * vec4(position, 1.0)) * jointWeight.y + newVertex; 29 | newNormal = (JOINT_TRANSFORMS[index] * vec4(normal, 0.0)) * jointWeight.y + newNormal; 30 | index = int(jointIndex.z); 31 | newVertex = (JOINT_TRANSFORMS[index] * vec4(position, 1.0)) * jointWeight.z + newVertex; 32 | newNormal = (JOINT_TRANSFORMS[index] * vec4(normal, 0.0)) * jointWeight.z + newNormal; 33 | index = int(jointIndex.w); 34 | newVertex = (JOINT_TRANSFORMS[index] * vec4(position, 1.0)) * jointWeight.w + newVertex; 35 | newNormal = (JOINT_TRANSFORMS[index] * vec4(normal, 0.0)) * jointWeight.w + newNormal; 36 | 37 | gl_Position = MVP_MATRIX * vec4(newVertex.xyz, 1.0); 38 | fragmentColor = color; 39 | texCoord = texuv; 40 | } -------------------------------------------------------------------------------- /Assets/Shaders/tinted.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | out vec4 fragColor; 4 | 5 | uniform vec4 TINT_COLOR; 6 | 7 | void main() { 8 | vec4 color = TINT_COLOR; 9 | color.rgb *= TINT_COLOR.a; 10 | fragColor = color; 11 | } -------------------------------------------------------------------------------- /Assets/Shaders/tinted.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec3 position; 4 | 5 | uniform mat4 MVP_MATRIX; 6 | 7 | void main() { 8 | gl_Position = MVP_MATRIX * vec4(position, 1.0); 9 | } -------------------------------------------------------------------------------- /Assets/Shaders/transition.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec4 fragmentColor; 4 | in vec2 texCoord; 5 | out vec4 fragColor; 6 | 7 | uniform sampler2D TEXTURE; 8 | uniform float TRANSITION; 9 | uniform int TILES_X; 10 | uniform int TILES_Y; 11 | 12 | void main() { 13 | vec4 texColor = texture(TEXTURE, vec2(texCoord.x * TILES_X, texCoord.y * TILES_Y)); 14 | vec4 color = vec4(fragmentColor.xyz, ceil(texColor.w - TRANSITION)); 15 | color.rgb *= color.a; 16 | fragColor = color; 17 | } -------------------------------------------------------------------------------- /Assets/Transitions/FadeTextureBottomTop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JuanRinaudo/CodingChallengesKha/82c1ba66426b0b13f8fa2ff92c7b5470266f8eb5/Assets/Transitions/FadeTextureBottomTop.png -------------------------------------------------------------------------------- /Assets/Transitions/FadeTextureCenterCircular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JuanRinaudo/CodingChallengesKha/82c1ba66426b0b13f8fa2ff92c7b5470266f8eb5/Assets/Transitions/FadeTextureCenterCircular.png -------------------------------------------------------------------------------- /Assets/Transitions/FadeTextureCounterClockwise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JuanRinaudo/CodingChallengesKha/82c1ba66426b0b13f8fa2ff92c7b5470266f8eb5/Assets/Transitions/FadeTextureCounterClockwise.png -------------------------------------------------------------------------------- /Assets/Transitions/FadeTextureMiddleHorizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JuanRinaudo/CodingChallengesKha/82c1ba66426b0b13f8fa2ff92c7b5470266f8eb5/Assets/Transitions/FadeTextureMiddleHorizontal.png -------------------------------------------------------------------------------- /Assets/Transitions/FadeTextureMiddleVertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JuanRinaudo/CodingChallengesKha/82c1ba66426b0b13f8fa2ff92c7b5470266f8eb5/Assets/Transitions/FadeTextureMiddleVertical.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CodingChallengesKha 2 | 3 | Github repository for personal challenges made to learn the bases of 3D Rendering using the Kha library. -------------------------------------------------------------------------------- /Source/Main.hx: -------------------------------------------------------------------------------- 1 | package; 2 | 3 | import kext.g4basics.G4Constants; 4 | import kha.graphics4.ConstantLocation; 5 | import kext.Application; 6 | // import replicationChallenges.SineCubesState; 7 | // import simpleChallenges.SimpleLighting; 8 | // import shaderChallenges.TransitionShaders; 9 | // import shaderChallenges.TextureCutoffMeshShader; 10 | // import shaderChallenges.PostProcessingShader; 11 | // import gameChallenges.SimpleCarGame; 12 | // import simpleChallenges.SimpleBones; 13 | // import shaderChallenges.GameOfLifeShader; 14 | // import shaderChallenges.FlowFieldShader; 15 | // import replicationChallenges.LeParcNoodles; 16 | import replicationChallenges.OpArtCircles01; 17 | 18 | class Main { 19 | private static var application:Application; 20 | 21 | public static function main() { 22 | // application = SineCubesState.initApplication(); //Challenge 001 23 | // application = SimpleLighting.initApplication(); //Challenge 002 24 | // application = TransitionShaders.initApplication(); //Challenge 003 25 | // application = TextureCutoffMeshShader.initApplication(); //Challenge 004 26 | // application = PostProcessingShader.initApplication(); //Challenge 005 27 | // application = SimpleCarGame.initApplication(); //Challenge 006 28 | // application = SimpleBones.initApplication(); //Challenge 007 29 | // application = GameOfLifeShader.initApplication(); //Challenge 008 30 | // application = LeParcNoodles.initApplication(); //Challenge 009 31 | application = OpArtCircles01.initApplication(); //Challenge 010 32 | // application = FlowFieldShader.initApplication(); //Challenge 0XX 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /Source/MeshType.hx: -------------------------------------------------------------------------------- 1 | enum MeshType { 2 | CUBE_OBJ; 3 | SPHERE_OBJ; 4 | TORUS_OBJ; 5 | SUZANNE_OBJ; 6 | CAR_FORMULA_OBJ; 7 | CUBE_STL; 8 | SPHERE_STL; 9 | TORUS_STL; 10 | SUZANNE_STL; 11 | CAR_FORMULA_STL; 12 | } -------------------------------------------------------------------------------- /Source/gameChallenges/SimpleCarGame.hx: -------------------------------------------------------------------------------- 1 | package gameChallenges; 2 | 3 | import kha.Assets; 4 | import kha.Color; 5 | import kha.Image; 6 | import kha.Framebuffer; 7 | import kha.Shaders; 8 | 9 | import kha.math.Vector2; 10 | import kha.math.Vector3; 11 | import kha.math.FastVector4; 12 | 13 | import kha.input.KeyCode; 14 | 15 | import kext.Application; 16 | import kext.AppState; 17 | 18 | import kext.g4basics.BasicPipeline; 19 | import kext.g4basics.BasicMesh; 20 | 21 | import kha.graphics4.ConstantLocation; 22 | 23 | import kext.math.MathExt; 24 | import kext.math.BoundingCube; 25 | 26 | import kext.utils.Counter; 27 | 28 | import kext.debug.Debug; 29 | 30 | import zui.Id; 31 | import utils.ZUIUtils; 32 | 33 | typedef AICar = { 34 | alive:Bool, 35 | lane:Int, 36 | moveSpeed:Vector2, 37 | model:Int, 38 | position:Vector3 39 | } 40 | 41 | typedef SideDecoration = { 42 | alive:Bool, 43 | model:Int, 44 | position:Vector3, 45 | rotation:Vector3, 46 | scale:Vector3, 47 | } 48 | 49 | class SimpleCarGame extends AppState { 50 | private static inline var CANVAS_WIDTH:Int = 768; 51 | private static inline var CANVAS_HEIGHT:Int = 1024; 52 | private static inline var NAME:String = "Simple Car Game"; 53 | 54 | private var pipeline:BasicPipeline; 55 | private var meshRacingCar:BasicMesh; 56 | private var meshGrass:BasicMesh; 57 | private var meshRoad:BasicMesh; 58 | private var meshSedanCar:BasicMesh; 59 | private var meshTree:BasicMesh; 60 | 61 | private var drawBounds:Bool; 62 | private var boundsRacingCar:BoundingCube; 63 | private var boundsSedanCar:BoundingCube; 64 | 65 | private var aiCars:Array; 66 | private var aiCreationCounter:Counter; 67 | private var decorationCreationCounter:Counter; 68 | 69 | private var sideDecorations:Array; 70 | 71 | private var locationDirectionalLight:ConstantLocation; 72 | private var locationDirectionalColor:ConstantLocation; 73 | private var locationAmbientLight:ConstantLocation; 74 | 75 | private var worldSizeY:Float = 20; 76 | private var laneCount:Int = 3; 77 | private var laneWidth:Float = 1.6; 78 | 79 | private var playerSpeed:Vector2 = new Vector2(5, 5); 80 | private var playerWidth:Float = 0.7; 81 | private var playerTargetZ:Float = 0; 82 | private var playerMaxZ:Float = 10; 83 | private var playerTargetLane:Int = 0; 84 | 85 | private var boundsScale:Vector3 = new Vector3(0.9, 1, 0.9); 86 | 87 | private var cameraFrom:Vector3 = new Vector3(-9, -13, -15); 88 | private var cameraTo:Vector3 = new Vector3(0, 0, -6); 89 | private var orthogonalOrPerspective:Bool = true; 90 | private var cameraSize:Float = 8; 91 | private var cameraFov:Float = 28; 92 | 93 | private var lightDirection:FastVector4 = new FastVector4(0.5, 1, -1, 1); 94 | private var lightColor:FastVector4 = new FastVector4(1, 1, 1, 1); 95 | private var ambientColor:FastVector4 = new FastVector4(0.05, 0.05, 0.05, 1); 96 | 97 | private var fxaaOn:Bool = true; 98 | 99 | public static function initApplication() { 100 | return new Application( 101 | {title: SimpleCarGame.NAME, width: SimpleCarGame.CANVAS_WIDTH, height: SimpleCarGame.CANVAS_HEIGHT}, 102 | {initState: SimpleCarGame, defaultFontName: "KenPixel"} 103 | ); 104 | } 105 | 106 | public function new() { 107 | super(); 108 | 109 | pipeline = new BasicPipeline(Shaders.directionalLighting_vert, Shaders.directionalLighting_frag); 110 | pipeline.orthogonal(cameraSize, CANVAS_WIDTH / CANVAS_HEIGHT); 111 | pipeline.cameraLookAtXYZ(0, -2, -1, 0, 0, -3); 112 | pipeline.compile(); 113 | 114 | locationDirectionalLight = pipeline.getConstantLocation("LIGHT_DIRECTION"); 115 | locationDirectionalColor = pipeline.getConstantLocation("LIGHT_COLOR"); 116 | locationAmbientLight = pipeline.getConstantLocation("AMBIENT_COLOR"); 117 | 118 | meshRacingCar = BasicMesh.getOBJMesh(Assets.blobs.carFormula_obj, pipeline.vertexStructure, Color.fromFloats(0, 0, 0.8, 1)); 119 | boundsRacingCar = BoundingCube.fromBasicMesh(meshRacingCar); 120 | 121 | meshGrass = BasicMesh.getOBJMesh(Assets.blobs.quad_obj, pipeline.vertexStructure, Color.fromFloats(0, 0.7, 0, 1)); 122 | meshGrass.scale(new Vector3(15, 1, worldSizeY)); 123 | meshRoad = BasicMesh.getOBJMesh(Assets.blobs.quad_obj, pipeline.vertexStructure, Color.fromFloats(0.4, 0.4, 0.4, 1)); 124 | meshRoad.translate(new Vector3(0, 0.01, 0)); 125 | 126 | meshSedanCar = BasicMesh.getOBJMesh(Assets.blobs.carSedan_obj, pipeline.vertexStructure, Color.fromFloats(0.8, 0, 0, 1)); 127 | meshSedanCar.rotate(new Vector3(Math.PI, 0, 0)); 128 | boundsSedanCar = BoundingCube.fromBasicMesh(meshSedanCar); 129 | 130 | meshTree = BasicMesh.getOBJMesh(Assets.blobs.tree_obj, pipeline.vertexStructure, Color.fromFloats(0.2, 0.6, 0, 1)); 131 | 132 | aiCars = []; 133 | for(i in 0...10) { 134 | createAICar(); 135 | } 136 | aiCreationCounter = new Counter(2, Application.deltaTime, tryCreateAICar, true); 137 | 138 | sideDecorations = []; 139 | for(i in 0...10) { 140 | createSideDecoration(); 141 | } 142 | decorationCreationCounter = new Counter(0.1, Application.deltaTime, tryCreateSideDecoration, true); 143 | 144 | Application.setPostProcessingShader(Shaders.postFXAA_frag); 145 | Application.setPostProcesingConstantLocation(Shaders.postFXAA_frag, FLOAT, "FXAA_SPAN_MAX", 10); 146 | Application.setPostProcesingConstantLocation(Shaders.postFXAA_frag, FLOAT, "FXAA_REDUCE_MIN", 0.03); 147 | Application.setPostProcesingConstantLocation(Shaders.postFXAA_frag, FLOAT, "FXAA_REDUCE_MUL", 0.1); 148 | } 149 | 150 | override public function render(backbuffer:Image) { 151 | beginAndClear(backbuffer); 152 | 153 | if(orthogonalOrPerspective) { pipeline.orthogonal(cameraSize, CANVAS_WIDTH / CANVAS_HEIGHT); } 154 | else { pipeline.perspective(cameraFov * (Math.PI / 180), CANVAS_WIDTH / CANVAS_HEIGHT); } 155 | pipeline.cameraLookAtXYZ(cameraFrom.x, cameraFrom.y, cameraFrom.z, cameraTo.x, cameraTo.y, cameraTo.z); 156 | 157 | backbuffer.g4.setPipeline(pipeline); 158 | backbuffer.g4.setVector4(locationDirectionalLight, lightDirection); 159 | backbuffer.g4.setVector4(locationDirectionalColor, lightColor); 160 | backbuffer.g4.setVector4(locationAmbientLight, ambientColor); 161 | meshRacingCar.drawMesh(backbuffer, pipeline, false); 162 | 163 | meshGrass.drawMesh(backbuffer, pipeline, false); 164 | meshRoad.setSize(new Vector3(laneWidth * Math.floor(laneCount * .5) + playerWidth, 1, 20)); 165 | meshRoad.drawMesh(backbuffer, pipeline, false); 166 | 167 | if(boundsRacingCar.size.x != boundsScale.x || boundsRacingCar.size.y != boundsScale.y || boundsRacingCar.size.z != boundsScale.z) 168 | { boundsRacingCar.setScale(boundsScale); } 169 | 170 | var collision:AICar = null; 171 | for(car in aiCars) { 172 | if(car.alive) { 173 | meshSedanCar.setPosition(car.position); 174 | boundsSedanCar.setPosition(car.position); 175 | meshSedanCar.drawMesh(backbuffer, pipeline, false); 176 | 177 | if(boundsSedanCar.size.x != boundsRacingCar.size.x || boundsSedanCar.size.y != boundsRacingCar.size.y || boundsSedanCar.size.z != boundsRacingCar.size.z) 178 | { boundsSedanCar.setScale(boundsScale); } 179 | 180 | if(drawBounds) { Debug.drawDebugBoundingCube(backbuffer, pipeline, boundsSedanCar); } 181 | if(boundsRacingCar.checkCubeOverlap(boundsSedanCar)) { 182 | collision = car; 183 | } 184 | } 185 | } 186 | 187 | for(decoration in sideDecorations) { 188 | if(decoration.alive) { 189 | meshTree.setTransform(new Vector3((laneWidth * laneCount + playerWidth) * decoration.position.x, decoration.position.y, decoration.position.z), 190 | decoration.rotation, 191 | decoration.scale); 192 | meshTree.drawMesh(backbuffer, pipeline, false); 193 | } 194 | } 195 | 196 | if(collision != null) { 197 | restart(); 198 | } else { 199 | if(drawBounds) { Debug.drawDebugBoundingCube(backbuffer, pipeline, boundsRacingCar); } 200 | } 201 | 202 | backbuffer.g4.end(); 203 | 204 | backbuffer.g2.begin(false); 205 | backbuffer.g2.end(); 206 | } 207 | 208 | override public function update(delta:Float) { 209 | getPlayerInput(delta); 210 | movePlayerCar(delta); 211 | 212 | aiCreationCounter.tick(); 213 | moveAICars(delta); 214 | 215 | decorationCreationCounter.tick(); 216 | moveDecorations(delta); 217 | } 218 | 219 | private inline function restart() { 220 | Application.reset(); 221 | } 222 | 223 | private function getPlayerInput(delta:Float) { 224 | if(Application.keyboard.keyPressed(KeyCode.D) && playerTargetLane < Math.floor(laneCount * .5)) { 225 | playerTargetLane++; 226 | } else if(Application.keyboard.keyPressed(KeyCode.A) && playerTargetLane > -Math.floor(laneCount * .5)) { 227 | playerTargetLane--; 228 | } 229 | 230 | playerTargetZ += delta; 231 | if(Application.keyboard.keyDown(KeyCode.W)) { 232 | playerTargetZ -= delta * playerSpeed.y; 233 | } else if(Application.keyboard.keyDown(KeyCode.S)) { 234 | playerTargetZ += delta * playerSpeed.y; 235 | } 236 | playerTargetZ = MathExt.clamp(playerTargetZ, -playerMaxZ, 0); 237 | } 238 | 239 | private inline function movePlayerCar(delta:Float) { 240 | var carDeltaX = playerTargetLane * laneWidth - meshRacingCar.position.x; 241 | var translation:Vector3 = new Vector3(0, 0, 0); 242 | if(Math.abs(carDeltaX) > 0.05) { 243 | translation.x = delta * playerSpeed.x * MathExt.clamp(carDeltaX, -1, 1); 244 | } 245 | 246 | if(playerTargetZ != 1) { 247 | var carDeltaZ = playerTargetZ - meshRacingCar.position.z; 248 | translation.z = delta * playerSpeed.y * MathExt.clamp(carDeltaZ, -1, 1); 249 | } 250 | 251 | meshRacingCar.translate(translation); 252 | boundsRacingCar.translate(translation); 253 | } 254 | 255 | private inline function tryCreateAICar() { 256 | var car:AICar = null; 257 | for(c in aiCars) { 258 | if(!c.alive) { car = c; break; } 259 | } 260 | if(car == null) { car = createAICar(); } 261 | car.alive = true; 262 | car.lane = Math.floor(Math.random() * laneCount) - Math.floor(laneCount * .5); 263 | car.position.x = laneWidth * car.lane; 264 | car.position.z = -worldSizeY; 265 | } 266 | 267 | private inline function tryCreateSideDecoration() { 268 | var decoration:SideDecoration = null; 269 | for(d in sideDecorations) { 270 | if(!d.alive) { decoration = d; break; } 271 | } 272 | if(decoration == null) { decoration = createSideDecoration(); } 273 | decoration.alive = true; 274 | decoration.rotation.x = Math.random() * Math.PI * 2; 275 | decoration.scale.x = decoration.scale.y = decoration.scale.z = Math.random() * 0.1 + 1; 276 | decoration.position.x = (Math.random() + 1) * (Math.random() > 0.5 ? -1 : 1); 277 | decoration.position.z = -worldSizeY; 278 | } 279 | 280 | private inline function createAICar():AICar { 281 | var car:AICar = { 282 | alive: false, 283 | lane: 0, 284 | moveSpeed: new Vector2(0, 1 + Math.random()), 285 | model: 0, 286 | position: new Vector3(0, 0, 0) 287 | }; 288 | aiCars.push(car); 289 | return car; 290 | } 291 | 292 | private inline function createSideDecoration():SideDecoration { 293 | var decoration:SideDecoration = { 294 | alive: false, 295 | model: 0, 296 | position: new Vector3(1, 0, -worldSizeY), 297 | rotation: new Vector3(0, 0, 0), 298 | scale: new Vector3(1, 1, 1) 299 | }; 300 | sideDecorations.push(decoration); 301 | return decoration; 302 | } 303 | 304 | private inline function moveAICars(delta:Float) { 305 | for(car in aiCars) { 306 | if(car.alive) { 307 | var deltaZ:Float = delta * (playerSpeed.y + car.moveSpeed.y); 308 | car.position.z += deltaZ; 309 | if(car.position.z > worldSizeY) { 310 | car.alive = false; 311 | } 312 | } 313 | } 314 | } 315 | 316 | private inline function moveDecorations(delta:Float) { 317 | for(decoration in sideDecorations) { 318 | decoration.position.z += delta * playerSpeed.y; 319 | if(decoration.position.z > worldSizeY) { 320 | decoration.alive = false; 321 | } 322 | } 323 | } 324 | 325 | override public function renderFramebuffer(framebuffer:Framebuffer) { 326 | var fxaaStatus:Bool = fxaaOn; 327 | 328 | ui.begin(framebuffer.g2); 329 | if(ui.window(Id.handle(), 0, 0, 400, 800)) { 330 | uiToggle = ui.check(Id.handle({selected: false}), "UI On/Off"); 331 | if(uiToggle) { 332 | if(ui.panel(Id.handle({selected: false}), "General")) { 333 | worldSizeY = ui.slider(Id.handle({value: worldSizeY}), "World Wrap Y", 0, 100, true, 1); 334 | laneWidth = ui.slider(Id.handle({value: laneWidth}), "Lane Width", 0, 3, true, 10); 335 | laneCount = Math.floor(ui.slider(Id.handle({value: laneCount}), "Lane Count", 0, 10, true, 1)); 336 | decorationCreationCounter.targetValue = ui.slider(Id.handle({value: decorationCreationCounter.targetValue}), "Decoration Creation Time", 0.01, 10, true, 100); 337 | } 338 | if(ui.panel(Id.handle({selected: false}), "Camera")) { 339 | ZUIUtils.vector3Sliders(ui, Id.handle(), cameraFrom, "Camera From", -worldSizeY, worldSizeY, 10); 340 | ZUIUtils.vector3Sliders(ui, Id.handle(), cameraTo, "Camera To", -worldSizeY, worldSizeY, 10); 341 | orthogonalOrPerspective = ui.check(Id.handle({selected: orthogonalOrPerspective}), "Orthogonal / Perspective Camera"); 342 | cameraSize = ui.slider(Id.handle({value: cameraSize}), "Camera Size", 0, 20, true, 10); 343 | cameraFov = ui.slider(Id.handle({value: cameraFov}), "Camera FOV", 0, 180, true, 100); 344 | } 345 | if(ui.panel(Id.handle({selected: false}), "Car Movement")) { 346 | ui.text('Car target Lane: $playerTargetLane'); 347 | ui.text("Racing Car Mesh Position: " + meshRacingCar.position); 348 | ZUIUtils.vector2Sliders(ui, Id.handle(), playerSpeed, "Car Speed", 0, 30, 10); 349 | ui.text('Car target Z: $playerTargetZ'); 350 | playerMaxZ = ui.slider(Id.handle({value: playerMaxZ}), "Car Max Z", 0, worldSizeY, true, 10); 351 | playerWidth = ui.slider(Id.handle({value: playerWidth}), "Car Width", 0, 3, true, 10); 352 | } 353 | if(ui.panel(Id.handle({selected: false}), "Collisions")) { 354 | drawBounds = ui.check(Id.handle(), "Draw Collision Bounds"); 355 | ZUIUtils.vector3Sliders(ui, Id.handle(), boundsScale, "Car Bounds Scale", 0, 2, 100); 356 | } 357 | ZUIUtils.lightingParameters(ui, Id.handle(), lightDirection, lightColor, ambientColor, false); 358 | if(ui.panel(Id.handle({selected: false}), "AI Cars")) { 359 | aiCreationCounter.targetValue = ui.slider(Id.handle({value: aiCreationCounter.targetValue}), "AI Creation Time", 0.1, 10, true, 10); 360 | } 361 | if(ui.panel(Id.handle({selected: false}), "Post Processing")) { 362 | fxaaOn = ui.check(Id.handle({selected: fxaaOn}), "FXAA"); 363 | } 364 | } 365 | } 366 | ui.end(); 367 | 368 | if(fxaaStatus != fxaaOn) { 369 | if(fxaaOn) { 370 | Application.setPostProcessingShader(Shaders.postFXAA_frag); 371 | } else { 372 | Application.removePostProcessingShader(Shaders.postFXAA_frag); 373 | } 374 | } 375 | } 376 | 377 | } -------------------------------------------------------------------------------- /Source/replicationChallenges/LeParcNoodles.hx: -------------------------------------------------------------------------------- 1 | package replicationChallenges; 2 | 3 | import kext.g4basics.Camera3D; 4 | import kext.Application; 5 | import kext.AppState; 6 | import kext.g4basics.BasicPipeline; 7 | 8 | import kha.graphics2.ImageScaleQuality; 9 | import kha.graphics4.ConstantLocation; 10 | import kha.graphics4.VertexData; 11 | import kha.graphics4.VertexStructure; 12 | import kha.graphics4.IndexBuffer; 13 | import kha.graphics4.VertexBuffer; 14 | import kha.graphics4.Usage; 15 | import kha.Image; 16 | import kha.Shaders; 17 | import kha.Framebuffer; 18 | import kha.Color; 19 | import kha.math.Vector2i; 20 | import kha.math.Vector2; 21 | import kha.math.FastMatrix4; 22 | import kha.math.FastVector3; 23 | import kha.math.FastVector4; 24 | 25 | import zui.Id; 26 | 27 | class LeParcNoodles extends AppState { 28 | private static inline var CANVAS_WIDTH:Int = 1080; 29 | private static inline var CANVAS_HEIGHT:Int = 1080; 30 | private static inline var NAME:String = "Le Parc Noodles"; 31 | 32 | private var pipeline:BasicPipeline; 33 | 34 | private var projectionMatrix:FastMatrix4; 35 | private var viewMatrix:FastMatrix4; 36 | private var modelMatrix:FastMatrix4; 37 | private var projectionViewMatrix:FastMatrix4; 38 | 39 | private var locationMVPMatrix:ConstantLocation; 40 | private var locationTintColor:ConstantLocation; 41 | 42 | private var mainColors:Array; 43 | private var secondaryColors:Array; 44 | 45 | private var noodles:Vector2i = new Vector2i(7, 6); 46 | private var padding:Vector2 = new Vector2(0.2, 0.24); 47 | 48 | private var noodleSize:Float = 30; 49 | private var movementDelta:Vector2 = new Vector2(40, 0.01); 50 | 51 | private var minColor:Float = 0.15; 52 | private var maxColor:Float = 1.0; 53 | 54 | private var offsetDelta:Float = 3.14; 55 | private var rowOffsetX:Float = 10; 56 | private var offsetByRow:Bool = true; 57 | 58 | private var topCircleResolution:Int = 20; 59 | 60 | private var vertexBuffer:VertexBuffer; 61 | private var indexBuffer:IndexBuffer; 62 | 63 | private var circleVertexBuffer:VertexBuffer; 64 | private var circleIndexBuffer:IndexBuffer; 65 | 66 | private var trailYDelta:Int = 20; 67 | 68 | public static function initApplication() { 69 | return new Application( 70 | {title: LeParcNoodles.NAME, width: LeParcNoodles.CANVAS_WIDTH, height: LeParcNoodles.CANVAS_HEIGHT}, 71 | {initState: LeParcNoodles, defaultFontName: "KenPixel", imgScaleQuality: ImageScaleQuality.High} 72 | ); 73 | } 74 | 75 | public function new() { 76 | super(); 77 | 78 | var camera:Camera3D = new Camera3D(); 79 | camera.orthogonal(Application.height * 0.5, Application.width / Application.height); 80 | camera.transform.setPositionXYZ(Application.width * 0.5, Application.height * 0.5, 10); 81 | camera.lookAt(new FastVector3(Application.width * 0.5, Application.height * 0.5, 0)); 82 | Application.mainCamera = camera; 83 | 84 | setupPipeline(); 85 | 86 | generateNoodleBuffer(); 87 | generateCircleBuffer(); 88 | 89 | mainColors = []; 90 | secondaryColors = []; 91 | } 92 | 93 | private inline function setupPipeline() { 94 | var vertexStructure:VertexStructure = new VertexStructure(); 95 | vertexStructure.add(name, VertexData.Float3); 96 | pipeline = new BasicPipeline(Shaders.tinted_vert, Shaders.tinted_frag, null, vertexStructure); 97 | pipeline.compile(); 98 | 99 | locationMVPMatrix = pipeline.getConstantLocation("MVP_MATRIX"); 100 | locationTintColor = pipeline.getConstantLocation("TINT_COLOR"); 101 | } 102 | 103 | private function generateNoodleBuffer() 104 | { 105 | var steps = Math.ceil(Application.height / trailYDelta * 2); 106 | vertexBuffer = new VertexBuffer(steps * 6, pipeline.vertexStructure, Usage.StaticUsage); 107 | indexBuffer = new IndexBuffer(steps * 6 - 6, Usage.StaticUsage); 108 | } 109 | 110 | private function generateCircleBuffer() { 111 | circleVertexBuffer = new VertexBuffer(topCircleResolution * 3 + 3, pipeline.vertexStructure, Usage.StaticUsage); 112 | circleIndexBuffer = new IndexBuffer(topCircleResolution * 3 + 3, Usage.StaticUsage); 113 | 114 | var circleIndex = 0; 115 | var vertexIndex = 0; 116 | 117 | var vertexes = circleVertexBuffer.lock(); 118 | 119 | vertexes.set(0, -noodleSize * 0.5 + noodleSize); 120 | vertexes.set(1, trailYDelta - noodleSize); 121 | vertexes.set(2, 0); 122 | vertexIndex += 3; 123 | 124 | while(circleIndex < topCircleResolution) { 125 | var angle = Math.PI * 2 * (circleIndex / topCircleResolution); 126 | vertexes.set(vertexIndex + 0, -noodleSize * 0.5 + noodleSize + Math.cos(angle) * noodleSize); 127 | vertexes.set(vertexIndex + 1, noodleSize * 0.5 - noodleSize + Math.sin(angle) * noodleSize); 128 | vertexes.set(vertexIndex + 2, 0); 129 | vertexIndex += 3; 130 | circleIndex++; 131 | } 132 | circleVertexBuffer.unlock(); 133 | 134 | var indexes = circleIndexBuffer.lock(); 135 | var index = 0; 136 | var indexVertexIndex = 1; 137 | while(indexVertexIndex < topCircleResolution) { 138 | indexes.set(index + 0, 0); 139 | indexes.set(index + 1, indexVertexIndex + 0); 140 | indexes.set(index + 2, indexVertexIndex + 1); 141 | index += 3; 142 | indexVertexIndex++; 143 | } 144 | indexes.set(index + 0, 0); 145 | indexes.set(index + 1, topCircleResolution); 146 | indexes.set(index + 2, 1); 147 | circleIndexBuffer.unlock(); 148 | } 149 | 150 | override public function render(backbuffer:Image) { 151 | beginAndClear3D(backbuffer, Color.fromBytes(85, 85, 85)); 152 | 153 | if(vertexBuffer != null && circleVertexBuffer != null) { 154 | var containerSize:Vector2 = new Vector2(Application.width * (1 - padding.x * 2), Application.height * (1 - padding.y * 2)); 155 | var delta:Vector2 = new Vector2(containerSize.x / (noodles.x - 1), containerSize.y / (noodles.y - 1)); 156 | var position:Vector2 = new Vector2(0, Application.height * padding.x); 157 | 158 | if(noodles.y == 1) { position.y = Application.height * 0.5; } 159 | 160 | var noodleCount:Int = 0; 161 | var rowCount:Int = 0; 162 | for(y in 0...noodles.y) { 163 | if(noodles.x == 1) { position.x = Application.width * 0.5; } 164 | else { position.x = Application.width * padding.x; } 165 | 166 | for(x in 0...noodles.x) { 167 | if(mainColors.length < noodleCount) { 168 | var mainColor:Color = Color.fromFloats(Math.random() * (maxColor - minColor) + minColor, 169 | Math.random() * (maxColor - minColor) + minColor, 170 | Math.random() * (maxColor - minColor) + minColor); 171 | mainColors.push(mainColor); 172 | secondaryColors.push(Color.fromFloats(mainColor.R * 0.75, mainColor.G * 0.75, mainColor.B * 0.75)); 173 | } 174 | 175 | drawNoodle(backbuffer, position.x - rowOffsetX * (rowCount % 2 == 0 ? -1 : 1), position.y, noodleSize, movementDelta, mainColors[noodleCount], secondaryColors[noodleCount], Application.time + (offsetByRow ? rowCount : noodleCount) * offsetDelta); 176 | position.x += delta.x; 177 | 178 | noodleCount++; 179 | } 180 | rowCount++; 181 | position.y += delta.y; 182 | } 183 | } 184 | 185 | end3D(backbuffer); 186 | } 187 | 188 | private function drawNoodle(backbuffer:Image, startX:Float, startY:Float, radius:Float, moveDelta:Vector2, topColor:Color, bottomColor:Color, offsetY:Float) 189 | { 190 | backbuffer.g4.setPipeline(pipeline); 191 | var modelMatrix:FastMatrix4 = FastMatrix4.identity().multmat(FastMatrix4.translation(0, 0, 0)); 192 | backbuffer.g4.setMatrix(locationMVPMatrix, pipeline.getMVPMatrix(modelMatrix)); 193 | 194 | var stepIndex = 0; 195 | var vertexIndex = 0; 196 | 197 | var steps = Math.ceil(Application.height / trailYDelta * 2); 198 | var vertexes = vertexBuffer.lock(); 199 | while(stepIndex < steps) { 200 | vertexes.set(vertexIndex + 0, startX + Math.sin(stepIndex * trailYDelta * moveDelta.y + offsetY) * moveDelta.x - radius * 0.5); 201 | vertexes.set(vertexIndex + 1, startY + stepIndex * trailYDelta - radius * 0.5); 202 | vertexes.set(vertexIndex + 2, 0); 203 | vertexes.set(vertexIndex + 3, startX + Math.sin(stepIndex * trailYDelta * moveDelta.y + offsetY) * moveDelta.x - radius * 0.5 + noodleSize * 2); 204 | vertexes.set(vertexIndex + 4, startY + stepIndex * trailYDelta - radius * 0.5); 205 | vertexes.set(vertexIndex + 5, 0); 206 | 207 | vertexIndex += 6; 208 | stepIndex++; 209 | } 210 | vertexBuffer.unlock(); 211 | 212 | var indexes = indexBuffer.lock(); 213 | var index = 0; 214 | var indexVertexIndex = 0; 215 | while(indexVertexIndex < vertexIndex) { 216 | indexes.set(index + 0, indexVertexIndex + 0); 217 | indexes.set(index + 1, indexVertexIndex + 1); 218 | indexes.set(index + 2, indexVertexIndex + 2); 219 | indexes.set(index + 3, indexVertexIndex + 2); 220 | indexes.set(index + 4, indexVertexIndex + 1); 221 | indexes.set(index + 5, indexVertexIndex + 3); 222 | index += 6; 223 | indexVertexIndex += 2; 224 | } 225 | indexBuffer.unlock(); 226 | 227 | backbuffer.g4.setVector4(locationTintColor, new FastVector4(bottomColor.R, bottomColor.G, bottomColor.B, bottomColor.A)); 228 | backbuffer.g4.setVertexBuffer(vertexBuffer); 229 | backbuffer.g4.setIndexBuffer(indexBuffer); 230 | backbuffer.g4.drawIndexedVertices(); 231 | 232 | var modelMatrix:FastMatrix4 = FastMatrix4.identity().multmat(FastMatrix4.translation(startX + Math.sin(offsetY) * moveDelta.x, startY, 0)); 233 | backbuffer.g4.setMatrix(locationMVPMatrix, pipeline.getMVPMatrix(modelMatrix)); 234 | 235 | backbuffer.g4.setVector4(locationTintColor, new FastVector4(topColor.R, topColor.G, topColor.B, topColor.A)); 236 | backbuffer.g4.setVertexBuffer(circleVertexBuffer); 237 | backbuffer.g4.setIndexBuffer(circleIndexBuffer); 238 | backbuffer.g4.drawIndexedVertices(); 239 | } 240 | 241 | override public function renderFramebuffer(framebuffer:Framebuffer) { 242 | var lastNoodleSize = noodleSize; 243 | var lastTrailYDelta = trailYDelta; 244 | 245 | ui.begin(framebuffer.g2); 246 | if(ui.window(Id.handle(), 0, 0, 400, 800)) { 247 | uiToggle = ui.check(Id.handle({selected: true}), "UI On/Off"); 248 | if(uiToggle) { 249 | if(ui.panel(Id.handle({selected: true}), "General")) { 250 | noodleSize = Math.floor(ui.slider(Id.handle({value: noodleSize}), "Noodle Size", 1, 100, true, 1)); 251 | 252 | noodles.x = Math.floor(ui.slider(Id.handle({value: noodles.x}), "Noodles X", 1, 50, true, 1)); 253 | noodles.y = Math.floor(ui.slider(Id.handle({value: noodles.y}), "Noodles Y", 1, 50, true, 1)); 254 | 255 | padding.x = ui.slider(Id.handle({value: padding.x}), "Padding X", 0, .45, true, 100); 256 | padding.y = ui.slider(Id.handle({value: padding.y}), "Padding Y", 0, .45, true, 100); 257 | 258 | trailYDelta = Math.floor(ui.slider(Id.handle({value: trailYDelta}), "Trail Y Delta", 1, 100, true, 1)); 259 | movementDelta.x = ui.slider(Id.handle({value: movementDelta.x}), "Movement Delta X", 0, 100, true, 1); 260 | movementDelta.y = ui.slider(Id.handle({value: movementDelta.y}), "Movement Delta Y", 0, 0.05, true, 1000); 261 | 262 | minColor = ui.slider(Id.handle({value: minColor}), "Min Color", 0, 1, true, 100); 263 | maxColor = ui.slider(Id.handle({value: maxColor}), "Max Color", 0, 1, true, 100); 264 | 265 | offsetDelta = ui.slider(Id.handle({value: offsetDelta}), "Offset Delta", 0, 3.14*2, true, 100); 266 | rowOffsetX = ui.slider(Id.handle({value: rowOffsetX}), "Row offset X", 0, 100, true, 1); 267 | offsetByRow = ui.check(Id.handle({selected: offsetByRow}), "Offset By Row"); 268 | 269 | if(ui.button("Reset Colors")) { 270 | mainColors = []; 271 | secondaryColors = []; 272 | } 273 | } 274 | } 275 | } 276 | ui.end(); 277 | 278 | if(lastTrailYDelta != trailYDelta) { 279 | generateNoodleBuffer(); 280 | } 281 | 282 | if(lastNoodleSize != noodleSize) { 283 | generateCircleBuffer(); 284 | } 285 | } 286 | 287 | } -------------------------------------------------------------------------------- /Source/replicationChallenges/OpArtCircles01.hx: -------------------------------------------------------------------------------- 1 | package replicationChallenges; 2 | 3 | import zui.Zui.Align; 4 | import kext.g4basics.Camera3D; 5 | import kext.Application; 6 | import kext.AppState; 7 | import kext.g4basics.BasicPipeline; 8 | import kext.extensions.ColorExt; 9 | 10 | import kha.graphics2.ImageScaleQuality; 11 | import kha.graphics4.ConstantLocation; 12 | import kha.graphics4.VertexData; 13 | import kha.graphics4.VertexStructure; 14 | import kha.graphics4.IndexBuffer; 15 | import kha.graphics4.VertexBuffer; 16 | import kha.graphics4.Usage; 17 | import kha.Image; 18 | import kha.Shaders; 19 | import kha.Framebuffer; 20 | import kha.Color; 21 | import kha.math.Vector2; 22 | import kha.math.FastMatrix4; 23 | import kha.math.FastVector3; 24 | import kha.math.FastVector4; 25 | 26 | import zui.Ext; 27 | import zui.Id; 28 | import utils.ZUIUtils; 29 | 30 | using tweenxcore.Tools; 31 | 32 | class OpArtCircles01 extends AppState { 33 | private static inline var CANVAS_WIDTH:Int = 1080; 34 | private static inline var CANVAS_HEIGHT:Int = 1080; 35 | private static inline var NAME:String = "Op Art Circles 01"; 36 | 37 | private var pipeline:BasicPipeline; 38 | 39 | private var projectionMatrix:FastMatrix4; 40 | private var viewMatrix:FastMatrix4; 41 | private var modelMatrix:FastMatrix4; 42 | private var projectionViewMatrix:FastMatrix4; 43 | 44 | private var locationMVPMatrix:ConstantLocation; 45 | private var locationTintColor:ConstantLocation; 46 | 47 | private var mainColor:Color; 48 | private var secondaryColor:Color; 49 | 50 | private var radius:Float = CANVAS_WIDTH; 51 | private var circleCount:Int = 35; 52 | private var circleResolution:Int = 20; 53 | private var colorIndexOffset:Float = 0.05; 54 | private var colorAnimateTime:Float = 3; 55 | private var rotationSpeed:Float = 0.03; 56 | private var rotationAnimateTime:Float = 3; 57 | 58 | private var rotationIndexEasing:Int = 35; 59 | private var colorIndexEasing:Int = 20; 60 | private var mainEasing:Int = 18; 61 | private var secondEasing:Int = 20; 62 | 63 | private var loop = true; 64 | private var running:Bool = true; 65 | private var time:Float = 0; 66 | private var timeSpeed:Float = 1; 67 | 68 | private var vertexBuffer:VertexBuffer; 69 | private var indexBufferMain:IndexBuffer; 70 | private var indexBufferSecond:IndexBuffer; 71 | 72 | public static function initApplication() { 73 | return new Application( 74 | {title: OpArtCircles01.NAME, width: OpArtCircles01.CANVAS_WIDTH, height: OpArtCircles01.CANVAS_HEIGHT}, 75 | {initState: OpArtCircles01, defaultFontName: "KenPixel", imgScaleQuality: ImageScaleQuality.High} 76 | ); 77 | } 78 | 79 | public function new() { 80 | super(); 81 | 82 | var camera:Camera3D = new Camera3D(); 83 | camera.orthogonal(Application.height, Application.ratio); 84 | camera.transform.setPositionXYZ(0, 0, 10); 85 | camera.lookAt(new FastVector3(0, 0, 0)); 86 | Application.mainCamera = camera; 87 | 88 | radius = Application.width * 1.5 * Application.ratio; 89 | 90 | setupPipeline(); 91 | 92 | generateBuffer(); 93 | 94 | mainColor = Color.White; 95 | secondaryColor = Color.Black; 96 | } 97 | 98 | private function generateBuffer() { 99 | var bufferSize = circleResolution * 3 + 3; 100 | vertexBuffer = new VertexBuffer(bufferSize, pipeline.vertexStructure, Usage.StaticUsage); 101 | indexBufferMain = new IndexBuffer(bufferSize, Usage.StaticUsage); 102 | indexBufferSecond = new IndexBuffer(bufferSize, Usage.StaticUsage); 103 | 104 | var vertexes = vertexBuffer.lock(); 105 | var vertexIndex = 0; 106 | 107 | vertexes.set(0, 0); 108 | vertexes.set(1, 0); 109 | vertexes.set(2, 0); 110 | vertexIndex += 3; 111 | 112 | var circleIndex = 0; 113 | while(circleIndex < circleResolution) { 114 | var angle = Math.PI * 2 * (circleIndex / circleResolution); 115 | vertexes.set(vertexIndex + 0, Math.cos(angle)); 116 | vertexes.set(vertexIndex + 1, Math.sin(angle)); 117 | vertexes.set(vertexIndex + 2, 0); 118 | vertexIndex += 3; 119 | circleIndex++; 120 | } 121 | vertexBuffer.unlock(); 122 | 123 | var indexes = indexBufferMain.lock(); 124 | var index = 0; 125 | var indexVertexIndex = 1; 126 | while(indexVertexIndex < circleResolution) { 127 | indexes.set(index + 0, 0); 128 | indexes.set(index + 1, indexVertexIndex + 0); 129 | indexes.set(index + 2, indexVertexIndex + 1); 130 | index += 3; 131 | indexVertexIndex+=2; 132 | } 133 | if(indexVertexIndex % 2 == 0) { 134 | indexes.set(index + 0, 0); 135 | indexes.set(index + 1, circleResolution); 136 | indexes.set(index + 2, 1); 137 | } 138 | indexBufferMain.unlock(); 139 | 140 | var indexes = indexBufferSecond.lock(); 141 | var index = 0; 142 | var indexVertexIndex = 2; 143 | while(indexVertexIndex < circleResolution) { 144 | indexes.set(index + 0, 0); 145 | indexes.set(index + 1, indexVertexIndex + 0); 146 | indexes.set(index + 2, indexVertexIndex + 1); 147 | index += 3; 148 | indexVertexIndex+=2; 149 | } 150 | if(indexVertexIndex % 2 == 0) { 151 | indexes.set(index + 0, 0); 152 | indexes.set(index + 1, circleResolution); 153 | indexes.set(index + 2, 1); 154 | } 155 | indexBufferSecond.unlock(); 156 | } 157 | 158 | private inline function setupPipeline() { 159 | var vertexStructure:VertexStructure = new VertexStructure(); 160 | vertexStructure.add(name, VertexData.Float3); 161 | pipeline = new BasicPipeline(Shaders.tinted_vert, Shaders.tinted_frag, null, vertexStructure); 162 | pipeline.compile(); 163 | 164 | locationMVPMatrix = pipeline.getConstantLocation("MVP_MATRIX"); 165 | locationTintColor = pipeline.getConstantLocation("TINT_COLOR"); 166 | } 167 | 168 | override function update(delta:Float) { 169 | super.update(delta); 170 | 171 | if(running) { 172 | time += delta * timeSpeed; 173 | } 174 | } 175 | 176 | override public function render(backbuffer:Image) { 177 | beginAndClear3D(backbuffer, Color.fromBytes(85, 85, 85)); 178 | 179 | var position:Vector2 = new Vector2(0, 0); 180 | 181 | for(i in 0...circleCount) { 182 | drawSplitedCircle(backbuffer, position, radius - i * (radius / circleCount), 183 | mainColor, secondaryColor, i); 184 | } 185 | 186 | end3D(backbuffer); 187 | } 188 | 189 | private function drawSplitedCircle(backbuffer:Image, position:Vector2, radius:Float, mainColor:Color, secondaryColor:Color, circleIndex:Int) 190 | { 191 | var rotationIndexOffset = ZUIUtils.callEasingByIndex(rotationIndexEasing, (circleIndex / circleCount)).lerp(0, circleCount); 192 | var colorIndexOffset = ZUIUtils.callEasingByIndex(colorIndexEasing, (circleIndex / circleCount)).lerp(0, circleCount); 193 | 194 | var finalTime = loop ? Math.sin(time) : time; 195 | 196 | var rotationOffsetTime = rotationAnimateTime > 0 ? 197 | finalTime * rotationSpeed * rotationIndexOffset * rotationAnimateTime : 198 | 1; 199 | var colorOffsetTime = colorAnimateTime > 0 ? 200 | ((finalTime + colorIndexOffset) % colorAnimateTime) / colorAnimateTime : 201 | 1; 202 | 203 | backbuffer.g4.setPipeline(pipeline); 204 | var modelMatrix:FastMatrix4 = FastMatrix4.identity() 205 | .multmat(FastMatrix4.translation(position.x, position.y, 0)) 206 | .multmat(FastMatrix4.scale(radius, radius, radius)) 207 | .multmat(FastMatrix4.rotation(0, rotationOffsetTime, 0)); 208 | backbuffer.g4.setMatrix(locationMVPMatrix, pipeline.getMVPMatrix(modelMatrix)); 209 | 210 | backbuffer.g4.setVertexBuffer(vertexBuffer); 211 | 212 | var mainOffsetTime = ZUIUtils.callEasingByIndex(mainEasing, colorOffsetTime); 213 | 214 | var mainColorLerped:Color = ColorExt.lerp(mainColor, secondaryColor, mainOffsetTime); 215 | backbuffer.g4.setVector4(locationTintColor, new FastVector4(mainColorLerped.R, mainColorLerped.G, mainColorLerped.B, mainColorLerped.A)); 216 | backbuffer.g4.setIndexBuffer(indexBufferMain); 217 | backbuffer.g4.drawIndexedVertices(); 218 | 219 | var secondOffsetTime = ZUIUtils.callEasingByIndex(secondEasing, colorOffsetTime); 220 | 221 | var secondColorLerped:Color = ColorExt.lerp(secondaryColor, mainColor, secondOffsetTime); 222 | backbuffer.g4.setVector4(locationTintColor, new FastVector4(secondColorLerped.R, secondColorLerped.G, secondColorLerped.B, secondColorLerped.A)); 223 | backbuffer.g4.setIndexBuffer(indexBufferSecond); 224 | backbuffer.g4.drawIndexedVertices(); 225 | } 226 | 227 | override public function renderFramebuffer(framebuffer:Framebuffer) { 228 | var lastCircleResolution = circleResolution; 229 | 230 | ui.begin(framebuffer.g2); 231 | if(ui.window(Id.handle(), 0, 0, 400, 800)) { 232 | uiToggle = ui.check(Id.handle({selected: true}), "UI On/Off"); 233 | if(uiToggle) { 234 | if(ui.panel(Id.handle({selected: true}), "Control")) { 235 | if(ui.button(running ? "Pause" : "Play")) { 236 | running = !running; 237 | } 238 | if(ui.button("Reset")) { 239 | time = 0; 240 | } 241 | if(ui.button("Next Frame")) { 242 | running = false; 243 | time += Application.deltaTime; 244 | } 245 | loop = ui.check(Id.handle({selected: loop}), "Loop"); 246 | timeSpeed = ui.slider(Id.handle({value: timeSpeed}), "Time Speed", 0, 2, true, 100); 247 | } 248 | if(ui.panel(Id.handle({selected: true}), "General")) { 249 | radius = ui.slider(Id.handle({value: radius}), "Radius", 1, Application.width * 1.5 * Application.ratio, true, 1); 250 | circleCount = Math.floor(ui.slider(Id.handle({value: circleCount}), "Circle Count", 1, 250, true, 1)); 251 | circleResolution = Math.floor(ui.slider(Id.handle({value: circleResolution}), "Circle Resolution", 3, 250, true, .5)); 252 | 253 | ui.separator(); 254 | 255 | ui.text("Rotation", Align.Center); 256 | rotationAnimateTime = ui.slider(Id.handle({value: rotationAnimateTime}), "Rotation Animate Time", 0, 100, true, 10); 257 | rotationSpeed = ui.slider(Id.handle({value: rotationSpeed}), "Rotation Speed", 0, 1, true, 100); 258 | rotationIndexEasing = ZUIUtils.tweenEasing(ui, Id.handle({value: rotationIndexEasing}), "Index Rotation Offset Easing"); 259 | 260 | ui.text("Color", Align.Center); 261 | colorAnimateTime = ui.slider(Id.handle({value: colorAnimateTime}), "Color animate Time", 0, 60, true, 10); 262 | // colorIndexOffset = ui.slider(Id.handle({value: colorIndexOffset}), "Color Index Offset", 0.01, 1, true, 100); 263 | colorIndexEasing = ZUIUtils.tweenEasing(ui, Id.handle({value: colorIndexEasing}), "Index Color Offset Easing"); 264 | 265 | ui.separator(); 266 | 267 | ui.text("Main Color", Align.Center); 268 | mainColor = Ext.colorPicker(ui, Id.handle({color: mainColor}), false); 269 | ui.text("Secondary Color", Align.Center); 270 | secondaryColor = Ext.colorPicker(ui, Id.handle({color: secondaryColor}), false); 271 | 272 | mainEasing = ZUIUtils.tweenEasing(ui, Id.handle({value: mainEasing}), "Main Easing"); 273 | secondEasing = ZUIUtils.tweenEasing(ui, Id.handle({value: secondEasing}), "Second Easing"); 274 | } 275 | } 276 | } 277 | ui.end(); 278 | 279 | if(lastCircleResolution != circleResolution) { 280 | generateBuffer(); 281 | } 282 | } 283 | 284 | } -------------------------------------------------------------------------------- /Source/replicationChallenges/SineCubesState.hx: -------------------------------------------------------------------------------- 1 | package replicationChallenges; 2 | 3 | import kha.Assets; 4 | import kha.Color; 5 | import kha.Shaders; 6 | import kha.Image; 7 | import kha.Framebuffer; 8 | import kha.graphics4.ConstantLocation; 9 | import kha.math.FastMatrix3; 10 | import kha.math.FastMatrix4; 11 | import kha.math.FastVector3; 12 | import kha.math.FastVector4; 13 | 14 | import kext.Application; 15 | import kext.AppState; 16 | import kext.g4basics.BasicMesh; 17 | import kext.g4basics.BasicPipeline; 18 | 19 | import zui.Ext; 20 | import zui.Id; 21 | 22 | class SineCubesState extends AppState { 23 | private static inline var CANVAS_WIDTH:Int = 800; 24 | private static inline var CANVAS_HEIGHT:Int = 800; 25 | private static inline var NAME:String = "Beesandbombs Sine Cubes"; 26 | 27 | private var cubesPipeline:BasicPipeline; 28 | 29 | private var projectionMatrix:FastMatrix4; 30 | private var viewMatrix:FastMatrix4; 31 | private var modelMatrix:FastMatrix4; 32 | private var projectionViewMatrix:FastMatrix4; 33 | private var normalMatrix:FastMatrix3; 34 | 35 | private var locationMVPMatrix:ConstantLocation; 36 | private var locationNormalMatrix:ConstantLocation; 37 | private var locationDirectionalLight:ConstantLocation; 38 | private var locationDirectionalColor:ConstantLocation; 39 | private var locationAmbientLight:ConstantLocation; 40 | 41 | private var cubeMesh:BasicMesh; 42 | 43 | private var time:Float = 0; 44 | private var cubesX:Int = 20; 45 | private var cubesZ:Int = 20; 46 | private var timeMultiplier:Float = 1.8; 47 | private var distanceMultiplier:Float = -0.35; 48 | private var minValue:Float = 5; 49 | private var maxValue:Float = 15; 50 | private var lastColor:Int = Color.White.value; 51 | private var cubeColor:Int = Color.White.value; 52 | 53 | private var lightRotation:Bool = false; 54 | private var lightRotationSpeed:Float = 1; 55 | private var lightDirection:FastVector4 = new FastVector4(0, -.3, -.5, 0); 56 | private var ambientLight:Color = Color.Black; 57 | 58 | private var cameraSize:Float = 18; 59 | 60 | public static function initApplication() { 61 | return new Application( 62 | {title: SineCubesState.NAME, width: SineCubesState.CANVAS_WIDTH, height: SineCubesState.CANVAS_HEIGHT}, 63 | {initState: SineCubesState, defaultFontName: "KenPixel"} 64 | ); 65 | } 66 | 67 | public function new() { 68 | super(); 69 | 70 | setupPipeline(); 71 | setupCube(); 72 | 73 | locationMVPMatrix = cubesPipeline.getConstantLocation("MVP_MATRIX"); 74 | locationNormalMatrix = cubesPipeline.getConstantLocation("NORMAL_MATRIX"); 75 | locationDirectionalLight = cubesPipeline.getConstantLocation("LIGHT_DIRECTION"); 76 | locationDirectionalColor = cubesPipeline.getConstantLocation("LIGHT_COLOR"); 77 | locationAmbientLight = cubesPipeline.getConstantLocation("AMBIENT_COLOR"); 78 | } 79 | 80 | private inline function setupPipeline() { 81 | cubesPipeline = new BasicPipeline(Shaders.directionalLighting_vert, Shaders.directionalLighting_frag); 82 | cubesPipeline.compile(); 83 | } 84 | 85 | private inline function setupMVP() { 86 | var size:Float = cameraSize; 87 | projectionMatrix = FastMatrix4.orthogonalProjection(-size, size, -size, size, .1, 300); 88 | viewMatrix = FastMatrix4.lookAt( 89 | new FastVector3(-100, -100, -100), 90 | new FastVector3(0, 0, 0), 91 | new FastVector3(0, 1, 0) 92 | ); 93 | modelMatrix = FastMatrix4.identity(); 94 | projectionViewMatrix = projectionMatrix.multmat(viewMatrix); 95 | } 96 | 97 | private inline function setupCube() { 98 | cubeMesh = BasicMesh.getSTLMesh(Assets.blobs.cube_obj, cubesPipeline, Color.White); 99 | } 100 | 101 | override public function render(backbuffer:Image) { 102 | setupMVP(); 103 | 104 | backbuffer.g4.begin(); 105 | backbuffer.g4.clear(Color.Black, Math.POSITIVE_INFINITY); 106 | 107 | renderCubes(backbuffer); 108 | 109 | backbuffer.g4.end(); 110 | } 111 | 112 | private inline function renderCubes(backbuffer:Image) { 113 | backbuffer.g4.setPipeline(cubesPipeline); 114 | 115 | cubeMesh.setBufferMesh(backbuffer); 116 | 117 | if(lightRotation) { 118 | lightDirection = new FastVector4(Math.sin(time * lightRotationSpeed), lightDirection.y, Math.cos(time * lightRotationSpeed), 0); 119 | } 120 | lightDirection.normalize(); 121 | backbuffer.g4.setVector4(locationDirectionalLight, viewMatrix.multvec(lightDirection)); 122 | backbuffer.g4.setVector4(locationDirectionalColor, new FastVector4(1, 1, 1, 1)); 123 | backbuffer.g4.setVector4(locationAmbientLight, new FastVector4(0, 0, 0, 1)); 124 | 125 | if(cubeColor != lastColor) { 126 | BasicMesh.setAllVertexesColor(cubeMesh.vertexBuffer, cubesPipeline.vertexStructure, cubeColor); 127 | } 128 | 129 | var modelMatrix:FastMatrix4; 130 | var mvpMatrix:FastMatrix4; 131 | 132 | var x:Float = 0; 133 | var z:Float = 0; 134 | var distance:Float = 0; 135 | for(i in 0...cubesX) { 136 | for(j in 0...cubesZ) { 137 | x = i - cubesX / 2; 138 | z = j - cubesZ / 2; 139 | distance = Math.sqrt(x * x + z * z); 140 | modelMatrix = FastMatrix4.identity() 141 | .multmat(FastMatrix4.translation(x, 0, z)) 142 | .multmat(FastMatrix4.scale(.5, (Math.abs(Math.sin(time * timeMultiplier + distance * distanceMultiplier) * (maxValue - minValue)) + minValue) * .5, .5)); 143 | 144 | mvpMatrix = projectionViewMatrix.multmat(modelMatrix); 145 | backbuffer.g4.setMatrix(locationMVPMatrix, mvpMatrix); 146 | 147 | var modelViewMatrix:FastMatrix4 = viewMatrix.multmat(modelMatrix); 148 | normalMatrix = new FastMatrix3(modelViewMatrix._00, modelViewMatrix._10, modelViewMatrix._20, 149 | modelViewMatrix._01, modelViewMatrix._11, modelViewMatrix._21, 150 | modelViewMatrix._02, modelViewMatrix._12, modelViewMatrix._22).inverse().transpose(); 151 | backbuffer.g4.setMatrix3(locationNormalMatrix, normalMatrix); 152 | 153 | backbuffer.g4.drawIndexedVertices(); 154 | } 155 | } 156 | } 157 | 158 | override public function renderFramebuffer(framebuffer:Framebuffer) { 159 | ui.begin(framebuffer.g2); 160 | if(ui.window(Id.handle(), 0, 0, 400, 800)) { 161 | uiToggle = ui.check(Id.handle({selected: true}), "UI On/Off"); 162 | if(uiToggle) { 163 | if(ui.panel(Id.handle({selected: true}), "General")) { 164 | cubesX = Math.floor(ui.slider(Id.handle({value: cubesX}), "Cubes X", 1, 100, true, 1)); 165 | cubesZ = Math.floor(ui.slider(Id.handle({value: cubesZ}), "Cubes Z", 1, 100, true, 1)); 166 | timeMultiplier = ui.slider(Id.handle({value: timeMultiplier}), "Time Multiplier", -5, 5, true, 10); 167 | distanceMultiplier = ui.slider(Id.handle({value: distanceMultiplier}), "Distance Multiplier", -5, 5, true, 100); 168 | minValue = ui.slider(Id.handle({value: minValue}), "Min Value", 0, 100, true, 10); 169 | maxValue = ui.slider(Id.handle({value: maxValue}), "Max Value", 0, 100, true, 10); 170 | if(ui.panel(Id.handle({selected: true}), "Cube Color")) { 171 | cubeColor = Ext.colorPicker(ui, Id.handle({color: cubeColor}), false); 172 | } 173 | } 174 | if(ui.panel(Id.handle({selected: true}), "Lighting")) { 175 | lightRotation = ui.check(Id.handle(), "Rotate Light"); 176 | if(!lightRotation) { 177 | lightDirection.x = ui.slider(Id.handle({value: lightDirection.x}), "Light Direction X", -1, 1, true, 100, true); 178 | lightDirection.y = ui.slider(Id.handle({value: lightDirection.y}), "Light Direction Y", -1, 1, true, 100, true); 179 | lightDirection.z = ui.slider(Id.handle({value: lightDirection.z}), "Light Direction Z", -1, 1, true, 100, true); 180 | } else { 181 | lightRotationSpeed = ui.slider(Id.handle({value: lightRotationSpeed}), "Light Rotation Speed", -10, 10, true, 10, true); 182 | lightDirection.y = ui.slider(Id.handle({value: lightDirection.y}), "Light Direction Y", -1, 1, true, 100, true); 183 | } 184 | } 185 | if(ui.panel(Id.handle({selected: true}), "Camera")) { 186 | cameraSize = ui.slider(Id.handle({value: cameraSize}), "Camera Size", 0, 50, true, 10, true); 187 | } 188 | } 189 | } 190 | ui.end(); 191 | } 192 | 193 | override public function update(delta:Float) { 194 | time += delta; 195 | } 196 | 197 | } -------------------------------------------------------------------------------- /Source/shaderChallenges/FlowFieldShader.hx: -------------------------------------------------------------------------------- 1 | package shaderChallenges; 2 | 3 | import js.html.FileReader; 4 | import zui.Ext; 5 | import kha.graphics4.ConstantLocation; 6 | import zui.Zui.Handle; 7 | import kha.graphics2.GraphicsExtension; 8 | import kha.math.Vector2; 9 | import kha.Color; 10 | import kha.Shaders; 11 | import kha.math.FastVector3; 12 | import kha.math.Vector3; 13 | import kext.g4basics.Camera3D; 14 | import kext.g4basics.BasicMesh; 15 | import kext.g4basics.G4Constants; 16 | import kext.g4basics.Texture; 17 | import kext.g4basics.BasicPipeline; 18 | import kha.graphics4.FragmentShader; 19 | import kha.Framebuffer; 20 | import zui.Id; 21 | import kha.Image; 22 | import kext.Application; 23 | import kext.AppState; 24 | 25 | typedef Creature = { 26 | var position:Vector2; 27 | var velocity:Vector2; 28 | } 29 | 30 | class FlowFieldShader extends AppState { 31 | private static inline var CANVAS_WIDTH:Int = 640; 32 | private static inline var CANVAS_HEIGHT:Int = 640; 33 | private static inline var NAME:String = "Flow Field Shader"; 34 | 35 | private var texture:Texture; 36 | private var flowTexture:Texture; 37 | private var buffer:Image; 38 | private var textureBuffer:Image; 39 | private var flowBuffer:Image; 40 | private var camera:Camera3D; 41 | private var pipeline:BasicPipeline; 42 | private var noisePipeline:BasicPipeline; 43 | private var pausedPipeline:BasicPipeline; 44 | private var screenQuad:BasicMesh; 45 | 46 | private var deltaWidthLocation:ConstantLocation; 47 | private var deltaHeightLocation:ConstantLocation; 48 | private var colorMultiplyLocation:ConstantLocation; 49 | private var speedLocation:ConstantLocation; 50 | 51 | private var colorMultiply:Float = 0.995; 52 | private var speed:Float = 0.9; 53 | 54 | private var spawnSize:Float = 2; 55 | private var spawnColor:Color = Color.Red; 56 | 57 | private var drawNoiseField:Bool = false; 58 | private var drawNoiseFieldHandle:Handle; 59 | private var drawFlowField:Bool = false; 60 | private var drawFlowFieldHandle:Handle; 61 | 62 | private var noiseResolution:Float = 1; 63 | private var noiseCounter:Float = 0; 64 | private var noiseRefreshTime:Float = -0.01; 65 | 66 | private var creatures:Array; 67 | private var creatureCount:Int = 100; 68 | private var flowField:Array>; 69 | private var flowFieldWidth:Int = 32; 70 | private var flowFieldHeight:Int = 32; 71 | 72 | private var renderTargetWidth:Int = 256; 73 | private var renderTargetHeight:Int = 256; 74 | 75 | private static var width:Int = 256; 76 | private static var height:Int = 256; 77 | 78 | public static function initApplication():Application { 79 | return new Application( 80 | {title: NAME, width: CANVAS_WIDTH, height: CANVAS_HEIGHT}, 81 | {initState: FlowFieldShader, defaultFontName: "KenPixel", bufferWidth: width, bufferHeight: height} 82 | ); 83 | } 84 | 85 | public function new() { 86 | super(); 87 | 88 | ui.alwaysRedraw = true; 89 | drawNoiseFieldHandle = Id.handle({selected: drawNoiseField}); 90 | drawFlowFieldHandle = Id.handle({selected: drawFlowField}); 91 | 92 | camera = new Camera3D(); 93 | camera.transform.setPosition(new Vector3(0, 0, -10)); 94 | camera.lookAt(new FastVector3(0, 0, 0)); 95 | camera.orthogonal(1, CANVAS_WIDTH / CANVAS_HEIGHT); 96 | Application.mainCamera = camera; 97 | createPipeline(Shaders.flowField_frag); 98 | 99 | pausedPipeline = new BasicPipeline(Shaders.textured_vert, Shaders.textured_frag, camera); 100 | pausedPipeline.compile(); 101 | 102 | screenQuad = BasicMesh.createQuadMesh(new Vector3(1, -1, 0), new Vector3(-1, 1, 0), pipeline, Color.White); 103 | screenQuad.setPipeline = false; 104 | 105 | flowField = []; 106 | for(i in 0...flowFieldWidth) { 107 | var temp = []; 108 | for(j in 0...flowFieldHeight) { 109 | temp.push(new Vector2(Math.random() * 2 - 1, Math.random() * 2 - 1)); 110 | } 111 | flowField[i] = temp; 112 | } 113 | 114 | creatures = []; 115 | initBuffers(); 116 | } 117 | 118 | private function createPipeline(shader:FragmentShader) { 119 | pipeline = new BasicPipeline(Shaders.textured_vert, shader, camera); 120 | pipeline.compile(); 121 | 122 | noisePipeline = new BasicPipeline(Shaders.textured_vert, Shaders.noise_frag, camera); 123 | noisePipeline.compile(); 124 | 125 | deltaWidthLocation = pipeline.getConstantLocation("DELTA_WIDTH"); 126 | deltaHeightLocation = pipeline.getConstantLocation("DELTA_HEIGHT"); 127 | colorMultiplyLocation = pipeline.getConstantLocation("COLOR_MULTIPLY"); 128 | speedLocation = pipeline.getConstantLocation("SPEED"); 129 | } 130 | 131 | private function initBuffers() { 132 | initCreatures(); 133 | 134 | width = renderTargetWidth; 135 | height = renderTargetHeight; 136 | 137 | Application.instance.resizeBuffers(width, height); 138 | buffer = Image.createRenderTarget(width, height, RGBA32, NoDepthAndStencil, 1); 139 | textureBuffer = Image.createRenderTarget(width, height, RGBA32, NoDepthAndStencil, 1); 140 | flowBuffer = Image.createRenderTarget(width, height, RGBA32, NoDepthAndStencil, 1); 141 | 142 | texture = new Texture(textureBuffer, "FLOW_TEXTURE"); 143 | texture.minificationFilter = AnisotropicFilter; 144 | texture.magnificationFilter = AnisotropicFilter; 145 | flowTexture = new Texture(flowBuffer, G4Constants.TEXTURE); 146 | flowTexture.minificationFilter = AnisotropicFilter; 147 | flowTexture.magnificationFilter = AnisotropicFilter; 148 | screenQuad.textures = [texture, flowTexture]; 149 | 150 | clearBuffers(); 151 | drawNoise(); 152 | } 153 | 154 | private function initCreatures() { 155 | var initialSize = creatures.length; 156 | creatures.resize(creatureCount); 157 | if(creatureCount > initialSize) { 158 | for(i in initialSize...creatureCount) { 159 | creatures[i] = { 160 | position: new Vector2(Math.random() * width, Math.random() * height), 161 | velocity: new Vector2(Math.random() * width, Math.random() * height) 162 | }; 163 | } 164 | } 165 | 166 | for(i in 0...creatures.length) { 167 | creatures[i].position.x = (creatures[i].position.x / width) * renderTargetWidth; 168 | creatures[i].position.y = (creatures[i].position.y / height) * renderTargetHeight; 169 | } 170 | } 171 | 172 | private function clearBuffers() { 173 | buffer.g4.begin(); 174 | buffer.g4.clear(Color.Black); 175 | buffer.g4.end(); 176 | textureBuffer.g4.begin(); 177 | textureBuffer.g4.clear(Color.Black); 178 | textureBuffer.g4.end(); 179 | flowBuffer.g4.begin(); 180 | flowBuffer.g4.clear(Color.fromFloats(.5, .5, 0, 1)); 181 | flowBuffer.g4.end(); 182 | } 183 | 184 | override function update(delta:Float) { 185 | super.update(delta); 186 | 187 | if(Application.keyboard.keyPressed(Escape)) { 188 | uiToggle = !uiToggle; 189 | } 190 | 191 | if(Application.mouse.buttonDown(0)) { 192 | 193 | } 194 | 195 | textureBuffer.g2.begin(false); 196 | textureBuffer.g2.color = spawnColor; 197 | for(i in 0...creatures.length) { 198 | var flowFieldX:Int = Math.floor((creatures[i].position.x / width) * flowFieldWidth); 199 | var flowFieldY:Int = Math.floor((creatures[i].position.y / height) * flowFieldHeight); 200 | 201 | creatures[i].velocity.x = Math.min(Math.max(creatures[i].velocity.x + flowField[flowFieldX][flowFieldY].x * delta * 10, -10), 10); 202 | creatures[i].velocity.y = Math.min(Math.max(creatures[i].velocity.y + flowField[flowFieldX][flowFieldY].y * delta * 10, -10), 10); 203 | 204 | creatures[i].position.x = (creatures[i].position.x + creatures[i].velocity.x * delta + width) % width; 205 | creatures[i].position.y = (creatures[i].position.y + creatures[i].velocity.y * delta + height) % height; 206 | GraphicsExtension.fillCircle(textureBuffer.g2, creatures[i].position.x, creatures[i].position.y, spawnSize); 207 | } 208 | textureBuffer.g2.end(); 209 | 210 | if(Application.mouse.buttonDown(1)) { 211 | var mousePosition:Vector2 = Application.mouse.position; 212 | textureBuffer.g2.begin(false); 213 | textureBuffer.g2.color = spawnColor; 214 | GraphicsExtension.fillCircle(textureBuffer.g2, mousePosition.x, mousePosition.y, spawnSize); 215 | textureBuffer.g2.end(); 216 | } 217 | 218 | noiseCounter += delta; 219 | if(Application.keyboard.keyPressed(N) || (noiseRefreshTime > 0 && noiseCounter > noiseRefreshTime)) { 220 | noiseCounter = 0; 221 | drawNoise(); 222 | } 223 | 224 | if(Application.keyboard.keyPressed(C)) { 225 | clearBuffers(); 226 | } 227 | } 228 | 229 | private function drawNoise() { 230 | beginAndClear3D(flowBuffer, Color.Black); 231 | flowBuffer.g4.setPipeline(noisePipeline); 232 | trace(1.0 / flowBuffer.width); 233 | flowBuffer.g4.setFloat(noisePipeline.getConstantLocation("DELTA_WIDTH"), 1 / (flowBuffer.width * noiseResolution)); 234 | flowBuffer.g4.setFloat(noisePipeline.getConstantLocation("DELTA_HEIGHT"), 1 / (flowBuffer.height * noiseResolution)); 235 | flowBuffer.g4.setFloat(noisePipeline.getConstantLocation("TIME"), Math.random() + 1); 236 | screenQuad.pipeline = noisePipeline; 237 | screenQuad.render(flowBuffer); 238 | end3D(flowBuffer); 239 | } 240 | 241 | override function render(backbuffer:Image) { 242 | super.render(backbuffer); 243 | 244 | beginAndClear3D(buffer, Color.Black); 245 | buffer.g4.setPipeline(pipeline); 246 | screenQuad.pipeline = pipeline; 247 | buffer.g4.setFloat(deltaWidthLocation, 1 / buffer.width); 248 | buffer.g4.setFloat(deltaHeightLocation, 1 / buffer.height); 249 | buffer.g4.setFloat(colorMultiplyLocation, colorMultiply); 250 | buffer.g4.setFloat(speedLocation, speed); 251 | screenQuad.render(buffer); 252 | end3D(buffer); 253 | 254 | textureBuffer.g2.begin(true, Color.Black); 255 | textureBuffer.g2.color = Color.fromFloats(1, 1, 1, 1); 256 | textureBuffer.g2.drawImage(buffer, 0, 0); 257 | textureBuffer.g2.end(); 258 | 259 | backbuffer.g2.begin(true, Color.Black); 260 | backbuffer.g2.color = Color.fromFloats(1, 1, 1, 1); 261 | backbuffer.g2.drawImage(drawNoiseField ? buffer : flowBuffer, 0, 0); 262 | backbuffer.g2.end(); 263 | } 264 | 265 | override public function renderFramebuffer(framebuffer:Framebuffer) { 266 | var reinitBuffers:Bool = false; 267 | var reinitCreatures:Bool = false; 268 | 269 | if(uiToggle) { 270 | ui.begin(framebuffer.g2); 271 | if(ui.window(Id.handle(), 0, 0, 400, 800)) { 272 | uiToggle = ui.check(Id.handle({selected: true}), "UI On/Off"); 273 | 274 | ui.separator(); 275 | ui.text("Flow Field"); 276 | drawNoiseField = ui.check(drawNoiseFieldHandle, "Draw Noise Field"); 277 | drawFlowField = ui.check(drawFlowFieldHandle, "Draw Flow Field"); 278 | 279 | ui.separator(); 280 | ui.text("Color"); 281 | colorMultiply = ui.slider(Id.handle({value: colorMultiply}), "Color Multiply", 0, 1, true, 1000, true, Right, true); 282 | speed = ui.slider(Id.handle({value: speed}), "Speed", 0, 10, true, 10, true, Right, true); 283 | 284 | spawnSize = ui.slider(Id.handle({value: spawnSize}), "Spawn Size", 0, 32, true, 10, true, Right, true); 285 | spawnColor = Ext.colorPicker(ui, Id.handle({color: spawnColor}), true); 286 | 287 | noiseResolution = ui.slider(Id.handle({value: noiseResolution}), "Noise Resolution", 0, 1, true, 100, true, Right, true); 288 | noiseRefreshTime = ui.slider(Id.handle({value: noiseRefreshTime}), "Noise Refresh Time", -0.01, 1, true, 100, true, Right, true); 289 | 290 | renderTargetWidth = Math.floor(ui.slider(Id.handle({value: renderTargetWidth}), "World Width", 0, 4096, true, 1)); 291 | renderTargetHeight = Math.floor(ui.slider(Id.handle({value: renderTargetHeight}), "World Height", 0, 4096, true, 1)); 292 | if(ui.button("Reinitialize")) { 293 | reinitBuffers = true; 294 | } 295 | 296 | ui.separator(); 297 | ui.text("Paint Creatures"); 298 | creatureCount = Math.floor(ui.slider(Id.handle({value: creatureCount}), "Creature Count", 0, 1000, true, 1, true, Right, true)); 299 | if(ui.button("Reinitialize")) { 300 | reinitCreatures = true; 301 | } 302 | } 303 | ui.end(); 304 | } 305 | 306 | if(reinitBuffers) { 307 | initBuffers(); 308 | } 309 | if(reinitCreatures) { 310 | initCreatures(); 311 | } 312 | } 313 | 314 | } -------------------------------------------------------------------------------- /Source/shaderChallenges/GameOfLifeShader.hx: -------------------------------------------------------------------------------- 1 | package shaderChallenges; 2 | 3 | import kha.graphics4.TextureFormat; 4 | import zui.Zui; 5 | import zui.Zui.Handle; 6 | import kha.graphics4.FragmentShader; 7 | import kha.graphics4.VertexShader; 8 | import utils.ZUIUtils; 9 | import kha.graphics4.TextureAddressing; 10 | import zui.Ext; 11 | import kext.g4basics.Texture; 12 | import kext.g4basics.G4Constants; 13 | import zui.Id; 14 | import kha.Framebuffer; 15 | import kha.graphics2.GraphicsExtension; 16 | import kha.math.Vector2; 17 | import kha.math.FastVector3; 18 | import kha.Color; 19 | import kha.math.Vector3; 20 | import kext.g4basics.BasicMesh; 21 | import kext.g4basics.Camera3D; 22 | import kha.Shaders; 23 | import kext.g4basics.BasicPipeline; 24 | import kha.Image; 25 | import kext.Application; 26 | import kext.AppState; 27 | import kha.graphics4.ConstantLocation; 28 | 29 | enum Pattern { 30 | Blinker; 31 | Grin; 32 | Pole4; 33 | Beacon; 34 | Glider; 35 | GliderGun; 36 | } 37 | 38 | class GameOfLifeShader extends AppState { 39 | private static inline var CANVAS_WIDTH:Int = 640; 40 | private static inline var CANVAS_HEIGHT:Int = 640; 41 | private static inline var NAME:String = "Game Of Life Shader"; 42 | 43 | private var texture:Texture; 44 | private var textureBuffer:Image; 45 | private var camera:Camera3D; 46 | private var pipeline:BasicPipeline; 47 | private var pausedPipeline:BasicPipeline; 48 | private var screenQuad:BasicMesh; 49 | 50 | private var deltaWidthLocation:ConstantLocation; 51 | private var deltaHeightLocation:ConstantLocation; 52 | private var solitudeLocation:ConstantLocation; 53 | private var overpopulationLocation:ConstantLocation; 54 | private var populateLocation:ConstantLocation; 55 | 56 | private var addOrRemove:Bool = true; 57 | private var running:Bool = false; 58 | private var checkHandle:Handle; 59 | private var addOrRemoveHandle:Handle; 60 | 61 | private var pattern:Pattern; 62 | 63 | private var updateCounter:Float = 0; 64 | private var updateTime:Float = 0.01; 65 | private var stepsPerUpdate:Int = 1; 66 | 67 | private var solitude:Int = 1; 68 | private var overpopulation:Int = 4; 69 | private var populate:Int = 3; 70 | 71 | private var samplingDelta:Int = 1; 72 | private var brushSize:Float = 3; 73 | 74 | private static var width:Int = 128; 75 | private static var height:Int = 128; 76 | 77 | public static function initApplication():Application { 78 | return new Application( 79 | {title: NAME, width: CANVAS_WIDTH, height: CANVAS_HEIGHT}, 80 | {initState: GameOfLifeShader, defaultFontName: "KenPixel", bufferWidth: width, bufferHeight: height} 81 | ); 82 | } 83 | 84 | public function new() { 85 | super(); 86 | 87 | ui.alwaysRedraw = true; 88 | checkHandle = Id.handle({selected: running}); 89 | addOrRemoveHandle = Id.handle({selected: addOrRemove}); 90 | 91 | pattern = Glider; 92 | 93 | camera = new Camera3D(); 94 | camera.transform.setPosition(new Vector3(0, 0, -10)); 95 | camera.lookAt(new FastVector3(0, 0, 0)); 96 | camera.orthogonal(1, CANVAS_WIDTH / CANVAS_HEIGHT); 97 | Application.mainCamera = camera; 98 | createPipeline(Shaders.gameOfLifeMathOnly_frag); 99 | 100 | pausedPipeline = new BasicPipeline(Shaders.textured_vert, Shaders.textured_frag, camera); 101 | pausedPipeline.compile(); 102 | 103 | screenQuad = BasicMesh.createQuadMesh(new Vector3(1, -1, 0), new Vector3(-1, 1, 0), pipeline, Color.White); 104 | screenQuad.setPipeline = false; 105 | 106 | setupBuffers(); 107 | } 108 | 109 | private function createPipeline(shader:FragmentShader) { 110 | pipeline = new BasicPipeline(Shaders.textured_vert, shader, camera); 111 | pipeline.compile(); 112 | 113 | deltaWidthLocation = pipeline.getConstantLocation("DELTA_WIDTH"); 114 | deltaHeightLocation = pipeline.getConstantLocation("DELTA_HEIGHT"); 115 | solitudeLocation = pipeline.getConstantLocation("SOLITUDE"); 116 | overpopulationLocation = pipeline.getConstantLocation("OVERPOPULATION"); 117 | populateLocation = pipeline.getConstantLocation("POPULATE"); 118 | } 119 | 120 | private function setupBuffers() { 121 | Application.instance.resizeBuffers(width, height); 122 | textureBuffer = Image.createRenderTarget(width, height, L8, NoDepthAndStencil, 0); 123 | texture = new Texture(textureBuffer, G4Constants.TEXTURE); 124 | screenQuad.textures = [texture]; 125 | } 126 | 127 | private function clearBuffers() { 128 | textureBuffer.g2.begin(true); 129 | textureBuffer.g2.end(); 130 | } 131 | 132 | override function update(delta:Float) { 133 | super.update(delta); 134 | 135 | updateCounter += delta; 136 | 137 | if(Application.keyboard.keyPressed(Space)) { 138 | running = !running; 139 | checkHandle.selected = running; 140 | } 141 | 142 | if(Application.keyboard.keyPressed(C)) { 143 | clearBuffers(); 144 | } 145 | 146 | if(Application.keyboard.keyPressed(One)) { 147 | pattern = Blinker; 148 | } else if(Application.keyboard.keyPressed(Two)) { 149 | pattern = Grin; 150 | } else if(Application.keyboard.keyPressed(Three)) { 151 | pattern = Pole4; 152 | } else if(Application.keyboard.keyPressed(Four)) { 153 | pattern = Beacon; 154 | } else if(Application.keyboard.keyPressed(Five)) { 155 | pattern = Glider; 156 | } else if(Application.keyboard.keyPressed(Six)) { 157 | pattern = GliderGun; 158 | } 159 | 160 | if(Application.mouse.buttonPressed(0)) { 161 | var mousePosition:Vector2 = Application.mouse.position; 162 | textureBuffer.g2.begin(false); 163 | textureBuffer.g2.color = addOrRemove ? Color.White : Color.Black; 164 | switch(pattern) { 165 | case Blinker: 166 | textureBuffer.g2.fillRect(mousePosition.x, mousePosition.y, 1, 3); 167 | case Grin: 168 | textureBuffer.g2.fillRect(mousePosition.x + 1, mousePosition.y, 1, 1); 169 | textureBuffer.g2.fillRect(mousePosition.x, mousePosition.y + 1, 1, 2); 170 | textureBuffer.g2.fillRect(mousePosition.x + 1, mousePosition.y + 3, 1, 1); 171 | case Pole4: 172 | textureBuffer.g2.fillRect(mousePosition.x, mousePosition.y, 1, 1); 173 | textureBuffer.g2.fillRect(mousePosition.x + 2, mousePosition.y, 1, 1); 174 | textureBuffer.g2.fillRect(mousePosition.x + 2, mousePosition.y + 2, 1, 1); 175 | textureBuffer.g2.fillRect(mousePosition.x + 4, mousePosition.y + 2, 1, 1); 176 | case Beacon: 177 | textureBuffer.g2.fillRect(mousePosition.x, mousePosition.y, 1, 2); 178 | textureBuffer.g2.fillRect(mousePosition.x + 1, mousePosition.y, 1, 1); 179 | textureBuffer.g2.fillRect(mousePosition.x + 3, mousePosition.y + 2, 1, 2); 180 | textureBuffer.g2.fillRect(mousePosition.x + 2, mousePosition.y + 3, 1, 1); 181 | case Glider: 182 | textureBuffer.g2.fillRect(mousePosition.x, mousePosition.y, 1, 1); 183 | textureBuffer.g2.fillRect(mousePosition.x + 1, mousePosition.y + 1, 1, 1); 184 | textureBuffer.g2.fillRect(mousePosition.x - 1, mousePosition.y + 2, 3, 1); 185 | case GliderGun: 186 | textureBuffer.g2.fillRect(mousePosition.x , mousePosition.y + 4, 2, 2); 187 | textureBuffer.g2.fillRect(mousePosition.x + 34, mousePosition.y + 2, 2, 2); 188 | 189 | textureBuffer.g2.fillRect(mousePosition.x + 12, mousePosition.y + 2, 2, 1); 190 | textureBuffer.g2.fillRect(mousePosition.x + 11, mousePosition.y + 3, 1, 1); 191 | textureBuffer.g2.fillRect(mousePosition.x + 10, mousePosition.y + 4, 1, 3); 192 | textureBuffer.g2.fillRect(mousePosition.x + 14, mousePosition.y + 5, 1, 1); 193 | textureBuffer.g2.fillRect(mousePosition.x + 11, mousePosition.y + 7, 1, 1); 194 | textureBuffer.g2.fillRect(mousePosition.x + 12, mousePosition.y + 8, 2, 1); 195 | 196 | textureBuffer.g2.fillRect(mousePosition.x + 15, mousePosition.y + 3, 1, 1); 197 | textureBuffer.g2.fillRect(mousePosition.x + 16, mousePosition.y + 4, 1, 3); 198 | textureBuffer.g2.fillRect(mousePosition.x + 17, mousePosition.y + 5, 1, 1); 199 | textureBuffer.g2.fillRect(mousePosition.x + 15, mousePosition.y + 7, 1, 1); 200 | 201 | textureBuffer.g2.fillRect(mousePosition.x + 24, mousePosition.y , 1, 2); 202 | textureBuffer.g2.fillRect(mousePosition.x + 22, mousePosition.y + 1, 1, 1); 203 | textureBuffer.g2.fillRect(mousePosition.x + 20, mousePosition.y + 2, 2, 3); 204 | textureBuffer.g2.fillRect(mousePosition.x + 22, mousePosition.y + 5, 1, 1); 205 | textureBuffer.g2.fillRect(mousePosition.x + 24, mousePosition.y + 5, 1, 2); 206 | } 207 | textureBuffer.g2.end(); 208 | } 209 | if(Application.mouse.buttonDown(1)) { 210 | var mousePosition:Vector2 = Application.mouse.position; 211 | textureBuffer.g2.begin(false); 212 | textureBuffer.g2.color = addOrRemove ? Color.White : Color.Black; 213 | GraphicsExtension.fillCircle(textureBuffer.g2, mousePosition.x, mousePosition.y, brushSize); 214 | textureBuffer.g2.end(); 215 | } 216 | } 217 | 218 | override function render(backbuffer:Image) { 219 | super.render(backbuffer); 220 | 221 | if(running && updateCounter > updateTime) { 222 | screenQuad.pipeline = pipeline; 223 | 224 | textureBuffer.g2.color = Color.White; 225 | for(i in 0...stepsPerUpdate) { 226 | beginAndClear3D(backbuffer); 227 | backbuffer.g4.setPipeline(pipeline); 228 | backbuffer.g4.setFloat(deltaWidthLocation, samplingDelta / textureBuffer.width); 229 | backbuffer.g4.setFloat(deltaHeightLocation, samplingDelta / textureBuffer.height); 230 | backbuffer.g4.setInt(solitudeLocation, solitude); 231 | backbuffer.g4.setInt(overpopulationLocation, overpopulation); 232 | backbuffer.g4.setInt(populateLocation, populate); 233 | screenQuad.render(backbuffer); 234 | end3D(backbuffer); 235 | 236 | textureBuffer.g2.begin(true); 237 | textureBuffer.g2.drawImage(backbuffer, 0, 0); 238 | textureBuffer.g2.end(); 239 | } 240 | 241 | updateCounter = 0; 242 | } else { 243 | beginAndClear3D(backbuffer); 244 | backbuffer.g4.setPipeline(pausedPipeline); 245 | screenQuad.pipeline = pausedPipeline; 246 | screenQuad.render(backbuffer); 247 | end3D(backbuffer); 248 | } 249 | } 250 | 251 | override public function renderFramebuffer(framebuffer:Framebuffer) { 252 | ui.begin(framebuffer.g2); 253 | if(ui.window(Id.handle(), 0, 0, 400, 800)) { 254 | uiToggle = ui.check(Id.handle({selected: true}), "UI On/Off"); 255 | if(uiToggle) { 256 | updateTime = ui.slider(Id.handle({value: updateTime}), "Step Time", 0.001, 1, true, 1000); 257 | stepsPerUpdate = Math.floor(ui.slider(Id.handle({value: stepsPerUpdate}), "Steps Per Update", 1, 50, true, 1)); 258 | solitude = Math.floor(ui.slider(Id.handle({value: solitude}), "Solitude Threshold", 0, 8, true, 1)); 259 | overpopulation = Math.floor(ui.slider(Id.handle({value: overpopulation}), "Overpopulation Threshold", 0, 8, true, 1)); 260 | populate = Math.floor(ui.slider(Id.handle({value: populate}), "Populate Threshold", 0, 8, true, 1)); 261 | if(ui.button("Clear")) { 262 | clearBuffers(); 263 | } 264 | brushSize = ui.slider(Id.handle({value: brushSize}), "Brush Size", 0, 100, true, 10); 265 | samplingDelta = Math.floor(ui.slider(Id.handle({value: samplingDelta}), "Sampling Delta", 0, 100, true, 1)); 266 | width = Math.floor(ui.slider(Id.handle({value: width}), "World Width", 0, 4096, true, 1)); 267 | height = Math.floor(ui.slider(Id.handle({value: height}), "World Height", 0, 4096, true, 1)); 268 | texture.verticalAddresing = ZUIUtils.textureAddresing(ui, Id.handle(), texture.verticalAddresing, "Vertical Addresing"); 269 | texture.horizontalAddresing = ZUIUtils.textureAddresing(ui, Id.handle(), texture.horizontalAddresing, "Horizontal Addresing"); 270 | if(ui.button("Resize")) { 271 | setupBuffers(); 272 | } 273 | running = ui.check(checkHandle, "Running"); 274 | addOrRemove = ui.check(addOrRemoveHandle, "Add/Remove cells"); 275 | if(ui.panel(Id.handle(), "Spawn Pattern")) { 276 | if(ui.button("Blinker")) { 277 | pattern = Blinker; 278 | } 279 | if(ui.button("Grin")) { 280 | pattern = Grin; 281 | } 282 | if(ui.button("Pole4")) { 283 | pattern = Pole4; 284 | } 285 | if(ui.button("Beacon")) { 286 | pattern = Beacon; 287 | } 288 | if(ui.button("Glider")) { 289 | pattern = Glider; 290 | } 291 | if(ui.button("GliderGun")) { 292 | pattern = GliderGun; 293 | } 294 | } 295 | if(ui.panel(Id.handle(), "Shader")) { 296 | if(ui.button("Game Of Life Normal")) { 297 | createPipeline(Shaders.gameOfLife_frag); 298 | } 299 | if(ui.button("Game Of Life No Branches")) { 300 | createPipeline(Shaders.gameOfLifeNoBranches_frag); 301 | } 302 | if(ui.button("Game Of Life Math Only")) { 303 | createPipeline(Shaders.gameOfLifeMathOnly_frag); 304 | } 305 | } 306 | } 307 | } 308 | ui.end(); 309 | } 310 | 311 | } -------------------------------------------------------------------------------- /Source/shaderChallenges/PostProcessingShader.hx: -------------------------------------------------------------------------------- 1 | package shaderChallenges; 2 | 3 | import kext.g4basics.Camera3D; 4 | import kha.Assets; 5 | import kha.Color; 6 | import kha.Image; 7 | import kha.Framebuffer; 8 | import kha.Shaders; 9 | 10 | import kha.math.Vector2; 11 | import kha.math.Vector3; 12 | import kha.math.FastVector3; 13 | 14 | import kha.graphics4.FragmentShader; 15 | 16 | import kext.Application; 17 | import kext.AppState; 18 | 19 | import kext.g4basics.BasicMesh; 20 | import kext.g4basics.BasicPipeline; 21 | 22 | import utils.DemoMeshes; 23 | import utils.ZUIUtils; 24 | 25 | import zui.Zui; 26 | import zui.Id; 27 | 28 | using kext.UniformType; 29 | 30 | enum PostProcessingEfect { 31 | BLUR; 32 | GAUSSIANBLUR; 33 | COLORQUANTIZATION; 34 | BLACKANDWHITE; 35 | PIXELATE; 36 | COLORCORRECTION; 37 | FXAA; 38 | } 39 | 40 | class PostProcessingShader extends AppState { 41 | private static inline var CANVAS_WIDTH:Int = 1200; 42 | private static inline var CANVAS_HEIGHT:Int = 800; 43 | private static inline var NAME:String = "Post Processing Shader"; 44 | 45 | private var camera:Camera3D; 46 | 47 | private var pipeline:BasicPipeline; 48 | private var mesh:BasicMesh; 49 | 50 | private var texture:Image; 51 | private var effectList:Array = []; 52 | 53 | //Blur 54 | private var blurValue:Int = 1; 55 | //Gaussian Blur 56 | private var blursize:Int = 1; 57 | private var sigma:Float = 5; 58 | private var direction:Vector2 = new Vector2(1, 0); 59 | //Color Quantization 60 | private var colorQuantization:Int = 1; 61 | //Pixelate 62 | private var cellSize:Vector2 = new Vector2(2, 2); 63 | //Color correction 64 | private var red:Float = 1; 65 | private var green:Float = 1; 66 | private var blue:Float = 1; 67 | private var contrast:Float = 1; 68 | private var brightness:Float = 0; 69 | private var temperature:Float = 0; 70 | private var tint:Float = 0; 71 | private var gamma:Float = 1; 72 | private var hue:Float = 0; 73 | private var saturation:Float = 0; 74 | private var lumination:Float = 0; 75 | //FXAA 76 | private var fxaaSpanMax:Float = 10; 77 | private var fxaaReduceMin:Float = 0.03; 78 | private var fxaaReduceMul:Float = 0.1; 79 | 80 | public static function initApplication():Application { 81 | return new Application( 82 | {title: PostProcessingShader.NAME, width: PostProcessingShader.CANVAS_WIDTH, height: PostProcessingShader.CANVAS_HEIGHT}, 83 | {initState: PostProcessingShader, defaultFontName: "KenPixel"} 84 | ); 85 | } 86 | 87 | public function new() { 88 | super(); 89 | 90 | camera = new Camera3D(); 91 | camera.transform.setPosition(new Vector3(0, 0, 10)); 92 | camera.orthogonal(5, CANVAS_WIDTH / CANVAS_HEIGHT); 93 | camera.lookAt(new FastVector3(0, 0, 0)); 94 | 95 | pipeline = new BasicPipeline(Shaders.textured_vert, Shaders.textured_frag, camera); 96 | pipeline.compile(); 97 | 98 | DemoMeshes.init(pipeline, Color.White); 99 | DemoMeshes.QUAD.transform.setScale(new Vector3(4, 4, 4)); 100 | DemoMeshes.QUAD.transform.rotate(new Vector3(Math.PI, 0, 0)); 101 | DemoMeshes.CUBE.transform.setScale(new Vector3(3, 3, 3)); 102 | 103 | mesh = DemoMeshes.CUBE; 104 | texture = Assets.images.Lenna; 105 | } 106 | 107 | override public function render(backbuffer:Image) { 108 | DemoMeshes.CUBE.transform.rotate(new Vector3(Application.deltaTime, 0, 0)); 109 | 110 | beginAndClear3D(backbuffer); 111 | backbuffer.g4.setPipeline(pipeline); 112 | // backbuffer.g4.setMatrix(pipeline.locationMVPMatrix, pipeline.getMVPMatrix(mesh.modelMatrix)); 113 | backbuffer.g4.setTexture(pipeline.textureUnit, texture); 114 | pipeline.setDefaultTextureUnitParameters(backbuffer, pipeline.textureUnit); 115 | // if(mesh == DemoMeshes.CUBE) { 116 | 117 | // } else { 118 | 119 | // } 120 | mesh.render(backbuffer); 121 | end3D(backbuffer); 122 | } 123 | 124 | override public function renderFramebuffer(framebuffer:Framebuffer) { 125 | ui.begin(framebuffer.g2); 126 | if(ui.window(Id.handle(), 0, 0, 400, 800)) { 127 | uiToggle = ui.check(Id.handle({selected: true}), "UI On/Off"); 128 | if(uiToggle) { 129 | if(ui.panel(Id.handle({selected: true}), "General")) { 130 | if(ui.button("Test Cube")) { mesh = DemoMeshes.CUBE; } 131 | if(ui.button("Lena Image")) { mesh = DemoMeshes.QUAD; texture = Assets.images.Lenna; } 132 | if(ui.button("Test Image")) { mesh = DemoMeshes.QUAD; texture = Assets.images.Test; } 133 | } 134 | for(effect in effectList) { 135 | switch(effect) { 136 | case BLUR: 137 | if(ui.panel(Id.handle({selected: true}), "Post Processing Parameters Blur")) { 138 | blurValue = Math.floor(ui.slider(Id.handle({value: blurValue}), "Blur Value", 1, 16, true, 1)); 139 | } 140 | case GAUSSIANBLUR: 141 | if(ui.panel(Id.handle({selected: true}), "Post Processing Parameters Gaussian Blur")) { 142 | blursize = Math.floor(ui.slider(Id.handle({value: blursize}), "Blur Size", 1, 32, true, 1)); 143 | sigma = ui.slider(Id.handle({value: sigma}), "Sigma", 0.01, 100, true, 100); 144 | ZUIUtils.vector2Sliders(ui, Id.handle(), direction, "Direction", -1, 1, 100); 145 | } 146 | case COLORQUANTIZATION: 147 | if(ui.panel(Id.handle({selected: true}), "Post Processing Parameters Color Quantization")) { 148 | colorQuantization = Math.floor(ui.slider(Id.handle({value: colorQuantization}), "Color quantization", 1, 255, true, 1)); 149 | } 150 | case PIXELATE: 151 | if(ui.panel(Id.handle({selected: true}), "Post Processing Parameters Pixelate")) { 152 | ZUIUtils.vector2Sliders(ui, Id.handle(), cellSize, "Pixel Size", 2, 64, 1); 153 | } 154 | case COLORCORRECTION: 155 | if(ui.panel(Id.handle({selected: true}), "Post Processing Parameters Color Correction")) { 156 | red = ui.slider(Id.handle({value: red}), "Red", -2, 2, true, 100); 157 | green = ui.slider(Id.handle({value: green}), "Green", -2, 2, true, 100); 158 | blue = ui.slider(Id.handle({value: blue}), "Blue", -2, 2, true, 100); 159 | contrast = ui.slider(Id.handle({value: contrast}), "Contrast", -5, 5, true, 100); 160 | brightness = ui.slider(Id.handle({value: brightness}), "Brightness", -5, 5, true, 100); 161 | temperature = ui.slider(Id.handle({value: brightness}), "Temperature", -3, 3, true, 100); 162 | tint = ui.slider(Id.handle({value: brightness}), "Tint", -5, 5, true, 100); 163 | gamma = ui.slider(Id.handle({value: gamma}), "Gamma", 0, 10, true, 100); 164 | hue = ui.slider(Id.handle({value: hue}), "Hue", 0, 1, true, 100); 165 | saturation = ui.slider(Id.handle({value: saturation}), "Saturation", -1, 1, true, 100); 166 | lumination = ui.slider(Id.handle({value: lumination}), "Lumination", -1, 1, true, 100); 167 | } 168 | case FXAA: 169 | if(ui.panel(Id.handle({selected: true}), "Post Processing Parameters FXAA")) { 170 | fxaaSpanMax = ui.slider(Id.handle({value: fxaaSpanMax}), "FXAA Span Max", 0, 20, true, 100); 171 | fxaaReduceMin = ui.slider(Id.handle({value: fxaaReduceMin}), "FXAA Reduce Min", 0, 1, true, 100); 172 | fxaaReduceMul = ui.slider(Id.handle({value: fxaaReduceMul}), "FXAA Reduce Mul", 0, 1, true, 100); 173 | } 174 | default: 175 | } 176 | } 177 | if(ui.panel(Id.handle({selected: true}), "Post Processing Effect")) { 178 | postProcessingCheck(ui.check(Id.handle(), "Blur"), PostProcessingEfect.BLUR, Shaders.postBlur_frag); 179 | postProcessingCheck(ui.check(Id.handle(), "Gaussian Blur"), PostProcessingEfect.GAUSSIANBLUR, Shaders.postGaussianBlur_frag); 180 | postProcessingCheck(ui.check(Id.handle(), "Color Quantization"), PostProcessingEfect.COLORQUANTIZATION, Shaders.postColorQuantization_frag); 181 | postProcessingCheck(ui.check(Id.handle(), "Black And White"), PostProcessingEfect.BLACKANDWHITE, Shaders.postBlackAndWhite_frag); 182 | postProcessingCheck(ui.check(Id.handle(), "Pixelate"), PostProcessingEfect.PIXELATE, Shaders.postPixelate_frag); 183 | postProcessingCheck(ui.check(Id.handle(), "Color Correction"), PostProcessingEfect.COLORCORRECTION, Shaders.postColorCorrection_frag); 184 | postProcessingCheck(ui.check(Id.handle(), "FXAA"), PostProcessingEfect.FXAA, Shaders.postFXAA_frag); 185 | } 186 | } 187 | } 188 | ui.end(); 189 | 190 | for(effect in effectList) { 191 | switch(effect) { 192 | case BLUR: 193 | Application.setPostProcesingConstantLocation(Shaders.postBlur_frag, INT, "BLUR_VALUE", blurValue); 194 | case GAUSSIANBLUR: 195 | Application.setPostProcesingConstantLocation(Shaders.postGaussianBlur_frag, INT, "BLUR_SIZE", blursize); 196 | Application.setPostProcesingConstantLocation(Shaders.postGaussianBlur_frag, FLOAT, "SIGMA", sigma); 197 | Application.setPostProcesingConstantLocation(Shaders.postGaussianBlur_frag, VECTOR2, "DIRECTION", direction); 198 | case COLORQUANTIZATION: 199 | Application.setPostProcesingConstantLocation(Shaders.postColorQuantization_frag, INT, "COLOR_QUANTIZATION", colorQuantization); 200 | case PIXELATE: 201 | Application.setPostProcesingConstantLocation(Shaders.postPixelate_frag, VECTOR2, "CELL_SIZE", cellSize); 202 | case COLORCORRECTION: 203 | Application.setPostProcesingConstantLocation(Shaders.postColorCorrection_frag, FLOAT, "RED", red); 204 | Application.setPostProcesingConstantLocation(Shaders.postColorCorrection_frag, FLOAT, "GREEN", green); 205 | Application.setPostProcesingConstantLocation(Shaders.postColorCorrection_frag, FLOAT, "BLUE", blue); 206 | Application.setPostProcesingConstantLocation(Shaders.postColorCorrection_frag, FLOAT, "CONTRAST", contrast); 207 | Application.setPostProcesingConstantLocation(Shaders.postColorCorrection_frag, FLOAT, "BRIGHTNESS", brightness); 208 | Application.setPostProcesingConstantLocation(Shaders.postColorCorrection_frag, FLOAT, "TEMPERATURE", temperature); 209 | Application.setPostProcesingConstantLocation(Shaders.postColorCorrection_frag, FLOAT, "TINT", tint); 210 | Application.setPostProcesingConstantLocation(Shaders.postColorCorrection_frag, FLOAT, "GAMMA", gamma); 211 | Application.setPostProcesingConstantLocation(Shaders.postColorCorrection_frag, FLOAT, "HUE", hue); 212 | Application.setPostProcesingConstantLocation(Shaders.postColorCorrection_frag, FLOAT, "SATURATION", saturation); 213 | Application.setPostProcesingConstantLocation(Shaders.postColorCorrection_frag, FLOAT, "LUMINATION", lumination); 214 | case FXAA: 215 | Application.setPostProcesingConstantLocation(Shaders.postFXAA_frag, FLOAT, "FXAA_SPAN_MAX", fxaaSpanMax); 216 | Application.setPostProcesingConstantLocation(Shaders.postFXAA_frag, FLOAT, "FXAA_REDUCE_MIN", fxaaReduceMin); 217 | Application.setPostProcesingConstantLocation(Shaders.postFXAA_frag, FLOAT, "FXAA_REDUCE_MUL", fxaaReduceMul); 218 | default: 219 | } 220 | } 221 | } 222 | 223 | private inline function postProcessingCheck(check:Bool, effect:PostProcessingEfect, shader:FragmentShader) { 224 | if(check && effectList.indexOf(effect) == -1) { 225 | effectList.push(effect); Application.setPostProcessingShader(shader); 226 | } else if(!check && effectList.indexOf(effect) != -1) { 227 | effectList.remove(effect); Application.removePostProcessingShader(shader); 228 | } 229 | } 230 | 231 | } -------------------------------------------------------------------------------- /Source/shaderChallenges/TextureCutoffMeshShader.hx: -------------------------------------------------------------------------------- 1 | package shaderChallenges; 2 | 3 | import kha.Image; 4 | import kha.Framebuffer; 5 | import kha.Color; 6 | import kha.Shaders; 7 | 8 | import kext.AppState; 9 | import kext.Application; 10 | 11 | import kext.g4basics.BasicMesh; 12 | import kext.g4basics.BasicPipeline; 13 | 14 | import kha.graphics4.ConstantLocation; 15 | import kha.graphics4.TextureAddressing; 16 | import kha.graphics4.TextureFilter; 17 | import kha.graphics4.MipMapFilter; 18 | 19 | import kha.math.Vector3; 20 | import kha.math.FastVector4; 21 | 22 | import utils.DemoMeshes; 23 | import utils.ZUIUtils; 24 | 25 | import zui.Id; 26 | 27 | class TextureCutoffMeshShader extends AppState { 28 | private static inline var CANVAS_WIDTH:Int = 1200; 29 | private static inline var CANVAS_HEIGHT:Int = 800; 30 | private static inline var NAME:String = "Texture Cutoff Mesh Shader"; 31 | 32 | private var pipeline:BasicPipeline; 33 | private var mesh:BasicMesh; 34 | private var fadeTexture:Image; 35 | private var textureSize:Int = 8; 36 | 37 | private var timeAnimation:Bool = true; 38 | private var timeMultiplier:Float = 1; 39 | private var cuttoffValue:Float = 0; 40 | private var filter:TextureFilter = TextureFilter.LinearFilter; 41 | 42 | private var meshRotation:Vector3; 43 | private var meshScale:Vector3; 44 | 45 | private var lightDirection:FastVector4; 46 | private var lightColor:FastVector4; 47 | private var ambientColor:FastVector4; 48 | 49 | private var locationCutoffValue:ConstantLocation; 50 | private var locationLightDirection:ConstantLocation; 51 | private var locationLightColor:ConstantLocation; 52 | private var locationAmbientColor:ConstantLocation; 53 | 54 | public static function initApplication():Application { 55 | return new Application( 56 | {title: TextureCutoffMeshShader.NAME, width: TextureCutoffMeshShader.CANVAS_WIDTH, height: TextureCutoffMeshShader.CANVAS_HEIGHT}, 57 | {initState: TextureCutoffMeshShader, defaultFontName: "KenPixel"} 58 | ); 59 | } 60 | 61 | public function new() { 62 | super(); 63 | 64 | pipeline = new BasicPipeline(Shaders.directionalLighting_vert, Shaders.textureCutoffMesh_frag); 65 | pipeline.orthogonal(5, CANVAS_WIDTH / CANVAS_HEIGHT); 66 | pipeline.compile(); 67 | 68 | locationCutoffValue = pipeline.getConstantLocation("CUTOFF_VALUE"); 69 | locationLightDirection = pipeline.getConstantLocation("LIGHT_DIRECTION"); 70 | locationLightColor = pipeline.getConstantLocation("LIGHT_COLOR"); 71 | locationAmbientColor = pipeline.getConstantLocation("AMBIENT_COLOR"); 72 | 73 | DemoMeshes.init(pipeline.vertexStructure, Color.White); 74 | mesh = DemoMeshes.CUBE_OBJ; 75 | 76 | meshScale = new Vector3(1, 1, 1); 77 | meshRotation = new Vector3(0, 0, 0); 78 | 79 | lightDirection = new FastVector4(1, 1, 0.5, 0); 80 | lightColor = new FastVector4(1, 1, 1, 1); 81 | ambientColor = new FastVector4(.2, .2, .2, 1); 82 | 83 | createTexture(); 84 | } 85 | 86 | override public function update(delta:Float) { 87 | mesh.setRotation(meshRotation); 88 | mesh.setSize(meshScale); 89 | 90 | if(timeAnimation) { 91 | cuttoffValue = Math.abs(Math.sin(Application.time * timeMultiplier)); 92 | } 93 | } 94 | 95 | override public function render(backbuffer:Image) { 96 | renderMesh(backbuffer); 97 | } 98 | 99 | private inline function renderMesh(backbuffer:Image) { 100 | beginAndClear(backbuffer, Color.Black); 101 | 102 | backbuffer.g4.setPipeline(pipeline); 103 | backbuffer.g4.setMatrix(pipeline.locationMVPMatrix, pipeline.getMVPMatrix(mesh.modelMatrix)); 104 | backbuffer.g4.setMatrix3(pipeline.locationNormalMatrix, pipeline.getNormalMatrix(mesh.modelMatrix)); 105 | backbuffer.g4.setFloat(locationCutoffValue, cuttoffValue); 106 | backbuffer.g4.setVector4(locationLightDirection, pipeline.camera.viewMatrix.multvec(lightDirection)); 107 | backbuffer.g4.setVector4(locationLightColor, lightColor); 108 | backbuffer.g4.setVector4(locationAmbientColor, ambientColor); 109 | 110 | backbuffer.g4.setTexture(pipeline.textureUnit, fadeTexture); 111 | backbuffer.g4.setTextureParameters(pipeline.textureUnit, TextureAddressing.Repeat, TextureAddressing.Repeat, 112 | filter, filter, MipMapFilter.NoMipFilter); 113 | 114 | mesh.setBufferMesh(backbuffer); 115 | backbuffer.g4.drawIndexedVertices(); 116 | 117 | backbuffer.g4.end(); 118 | } 119 | 120 | var initialSeedValue:Int = 123456789; 121 | var seed:Int = 123456789; 122 | private inline static var a = 1103515245; 123 | private inline static var c = 12345; 124 | private inline static var m = 4294967296; 125 | private function random():Float 126 | { 127 | seed = Math.floor((a * seed + c) % m); 128 | return seed / m; 129 | } 130 | 131 | private function createTexture() { 132 | fadeTexture = Image.createRenderTarget(textureSize, textureSize, null, null, 1); 133 | fadeTexture.g2.begin(true, Color.Black); 134 | for(x in 0...textureSize) { 135 | for(y in 0...textureSize) { 136 | var value:Float = Math.min(random() + .0, 1); 137 | fadeTexture.g2.color = Color.fromFloats(value, 0, 0, 1); 138 | fadeTexture.g2.fillRect(x, y, 1, 1); 139 | } 140 | } 141 | fadeTexture.g2.end(); 142 | } 143 | 144 | override public function renderFramebuffer(framebuffer:Framebuffer) { 145 | var createTextureClicked:Bool = false; 146 | ui.begin(framebuffer.g2); 147 | if(ui.window(Id.handle(), 0, 0, 400, 800)) { 148 | uiToggle = ui.check(Id.handle({selected: true}), "UI On/Off"); 149 | if(uiToggle) { 150 | if(ui.panel(Id.handle({selected: true}), "General")) { 151 | ZUIUtils.vector3Sliders(ui, Id.handle(), meshScale, "Mesh Scale", 0.1, 5, 10); 152 | ZUIUtils.vector3Sliders(ui, Id.handle(), meshRotation, "Mesh Rotation", 0, Math.PI * 2, 100); 153 | } 154 | if(ui.panel(Id.handle({selected: true}), "Cuttoff Parameters")) { 155 | textureSize = Math.floor(ui.slider(Id.handle({value: textureSize}), "Texture Size", 0, 256, true, 1, true)); 156 | if(ui.button("Create Texture")) { createTextureClicked = true; } 157 | ui.text('Random seed $initialSeedValue'); 158 | if(ui.button("Randomize Seed")) { initialSeedValue = Math.floor(Math.random() * m); createTextureClicked = true; } 159 | timeAnimation = ui.check(Id.handle({selected: true}), "Time / Manual"); 160 | if(timeAnimation) { 161 | ui.text('Cuffout value: $cuttoffValue'); 162 | timeMultiplier = ui.slider(Id.handle({value: timeMultiplier}), "Time Multiplier", -3, 3, true, 100, true); 163 | } else { 164 | cuttoffValue = ui.slider(Id.handle({value: cuttoffValue}), "Cuttoff Value", 0, 1, true, 100, true); 165 | } 166 | ui.text("Filters"); 167 | if(ui.button("Point Filter")) { filter = TextureFilter.PointFilter; createTextureClicked = true; } 168 | if(ui.button("Linear Filter")) { filter = TextureFilter.LinearFilter; createTextureClicked = true; } 169 | if(ui.button("Anisotropic Filter")) { filter = TextureFilter.AnisotropicFilter; createTextureClicked = true; } 170 | } 171 | mesh = ZUIUtils.meshSelector(ui, Id.handle(), mesh); 172 | ZUIUtils.lightingParameters(ui, Id.handle(), lightDirection, lightColor, ambientColor, false); 173 | } 174 | } 175 | ui.end(); 176 | 177 | if(createTextureClicked) { 178 | seed = initialSeedValue; 179 | createTexture(); 180 | } 181 | } 182 | 183 | } -------------------------------------------------------------------------------- /Source/shaderChallenges/TransitionShaders.hx: -------------------------------------------------------------------------------- 1 | package shaderChallenges; 2 | 3 | import kha.Assets; 4 | import kha.Shaders; 5 | import kha.Image; 6 | import kha.Framebuffer; 7 | import kha.Color; 8 | 9 | import kha.graphics4.ConstantLocation; 10 | import kha.graphics4.TextureUnit; 11 | import kha.graphics4.TextureAddressing; 12 | import kha.graphics4.TextureFilter; 13 | import kha.graphics4.MipMapFilter; 14 | 15 | import kext.Application; 16 | import kext.AppState; 17 | 18 | import kext.g4basics.BasicMesh; 19 | import kext.g4basics.BasicPipeline; 20 | import kext.loaders.OBJMeshLoader; 21 | 22 | import kha.math.FastMatrix4; 23 | 24 | import zui.Zui; 25 | import zui.Zui.Handle; 26 | import zui.Id; 27 | 28 | class TransitionShaders extends AppState { 29 | private static inline var CANVAS_WIDTH:Int = 800; 30 | private static inline var CANVAS_HEIGHT:Int = 800; 31 | private static inline var NAME:String = "Transition Shaders"; 32 | 33 | private var pipeline:BasicPipeline; 34 | private var quad:BasicMesh; 35 | 36 | private var locationTransition:ConstantLocation; 37 | private var locationTilesX:ConstantLocation; 38 | private var locationTilesY:ConstantLocation; 39 | 40 | private var fadeTexture:Image; 41 | 42 | private var screenMatrix:FastMatrix4; 43 | 44 | private var time:Float = 0; 45 | private var transition:Float = 0; 46 | private var tilesX:Int = 1; 47 | private var tilesY:Int = 1; 48 | private var transitionDelta:Float = 0.5; 49 | 50 | public static function initApplication():Application { 51 | return new Application( 52 | {title: TransitionShaders.NAME, width: TransitionShaders.CANVAS_WIDTH, height: TransitionShaders.CANVAS_HEIGHT}, 53 | {initState: TransitionShaders, defaultFontName: "KenPixel"} 54 | ); 55 | } 56 | 57 | public function new() { 58 | super(); 59 | 60 | pipeline = new BasicPipeline(Shaders.textured_vert, Shaders.transition_frag); 61 | pipeline.compile(); 62 | 63 | locationTransition = pipeline.getConstantLocation("TRANSITION"); 64 | locationTilesX = pipeline.getConstantLocation("TILES_X"); 65 | locationTilesY = pipeline.getConstantLocation("TILES_Y"); 66 | 67 | quad = BasicMesh.getOBJMesh(Assets.blobs.quad_obj, pipeline.vertexStructure, Color.Black); 68 | quad.modelMatrix = FastMatrix4.identity().multmat(FastMatrix4.rotation(0, 0, Math.PI * 0.5)); 69 | 70 | fadeTexture = Assets.images.FadeTextureBottomTop; 71 | 72 | screenMatrix = FastMatrix4.orthogonalProjection(-1, 1, -1, 1, 0, 1000); 73 | } 74 | 75 | override public function render(backbuffer:Image) { 76 | beginAndClear(backbuffer, Color.White); 77 | 78 | backbuffer.g4.setTexture(pipeline.textureUnit, fadeTexture); 79 | backbuffer.g4.setTextureParameters(pipeline.textureUnit, TextureAddressing.Repeat, TextureAddressing.Repeat, 80 | TextureFilter.PointFilter, TextureFilter.PointFilter, MipMapFilter.NoMipFilter); 81 | 82 | backbuffer.g4.setPipeline(pipeline); 83 | 84 | backbuffer.g4.setFloat(locationTransition, transition); 85 | backbuffer.g4.setInt(locationTilesX, tilesX); 86 | backbuffer.g4.setInt(locationTilesY, tilesY); 87 | backbuffer.g4.setMatrix(pipeline.locationMVPMatrix, screenMatrix.multmat(quad.modelMatrix)); 88 | 89 | quad.setBufferMesh(backbuffer); 90 | 91 | backbuffer.g4.drawIndexedVertices(); 92 | 93 | backbuffer.g4.end(); 94 | } 95 | 96 | override public function update(delta:Float) { 97 | time += Application.deltaTime * transitionDelta; 98 | transition = Math.abs(time % 2 - 1); 99 | } 100 | 101 | override public function renderFramebuffer(framebuffer:Framebuffer) { 102 | ui.begin(framebuffer.g2); 103 | if(ui.window(Id.handle(), 0, 0, 400, 800)) { 104 | uiToggle = ui.check(Id.handle({selected: true}), "UI On/Off"); 105 | if(uiToggle) { 106 | if(ui.panel(Id.handle({selected: true}), "General")) { 107 | ui.text('Transition: $transition'); 108 | if(ui.button("Reset")) { transition = 0; } 109 | transitionDelta = ui.slider(Id.handle({value: transitionDelta}), "Transition Delta", -1, 1, true, 100); 110 | tilesX = Math.floor(ui.slider(Id.handle({value: tilesX}), "Tiles X", 0, 100, true, 1)); 111 | tilesY = Math.floor(ui.slider(Id.handle({value: tilesY}), "Tiles Y", 0, 100, true, 1)); 112 | } 113 | if(ui.panel(Id.handle({selected: true}), "Fade Effect")) { 114 | ui.text("Texture"); 115 | ui.image(fadeTexture); 116 | if(ui.button("BottomTop")) { fadeTexture = Assets.images.FadeTextureBottomTop; } 117 | if(ui.button("Counterclockwise")) { fadeTexture = Assets.images.FadeTextureCounterClockwise; } 118 | if(ui.button("Center Circular")) { fadeTexture = Assets.images.FadeTextureCenterCircular; } 119 | if(ui.button("Middle Horizontal")) { fadeTexture = Assets.images.FadeTextureMiddleHorizontal; } 120 | if(ui.button("Middle Vertical")) { fadeTexture = Assets.images.FadeTextureMiddleVertical; } 121 | } 122 | if(ui.panel(Id.handle({selected: true}), "Camera")) { 123 | 124 | } 125 | } 126 | } 127 | ui.end(); 128 | } 129 | 130 | } -------------------------------------------------------------------------------- /Source/simpleChallenges/SimpleBones.hx: -------------------------------------------------------------------------------- 1 | package simpleChallenges; 2 | 3 | import utils.ZUIUtils; 4 | import kext.g4basics.Camera3D; 5 | import kha.Assets; 6 | import kha.Color; 7 | import kha.Image; 8 | import kha.Framebuffer; 9 | import kha.Shaders; 10 | import kha.graphics4.VertexData; 11 | import kha.math.Vector3; 12 | import kha.math.FastVector3; 13 | 14 | import kext.Application; 15 | import kext.AppState; 16 | import kext.g4basics.BasicMesh; 17 | import kext.g4basics.SkeletalMesh; 18 | import kext.g4basics.BasicPipeline; 19 | import kext.g4basics.G4Constants; 20 | 21 | import zui.Zui; 22 | import zui.Id; 23 | 24 | class SimpleBones extends AppState { 25 | private static inline var CANVAS_WIDTH:Int = 800; 26 | private static inline var CANVAS_HEIGHT:Int = 800; 27 | private static inline var NAME:String = "Simple Bones"; 28 | 29 | private var basicPipeline:BasicPipeline; 30 | private var animatedPipeline:BasicPipeline; 31 | private var floor:BasicMesh; 32 | private var animatedMesh:SkeletalMesh; 33 | 34 | private var characterSpeed:Float = 10; 35 | private var characterPosition:Vector3; 36 | 37 | private var lookAtCharacter:Bool = true; 38 | private var cameraPosition:Vector3; 39 | private var cameraAngle:Float = 0; 40 | 41 | private var rotateArroundChacter:Bool = false; 42 | private var cameraRotationSpeed:Float = 0.2; 43 | private var cameraRotationRadius:Float = 10; 44 | 45 | private var camera:Camera3D; 46 | 47 | public static function initApplication() { 48 | return new Application( 49 | {title: SimpleBones.NAME, width: SimpleBones.CANVAS_WIDTH, height: SimpleBones.CANVAS_HEIGHT}, 50 | {initState: SimpleBones, defaultFontName: "KenPixel"} 51 | ); 52 | } 53 | 54 | public function new() { 55 | super(); 56 | 57 | camera = new Camera3D(); 58 | Application.mainCamera = camera; 59 | cameraPosition = new Vector3(0, -10, 10); 60 | characterPosition = new Vector3(0, 0, 0); 61 | 62 | basicPipeline = new BasicPipeline(Shaders.textured_vert, Shaders.striped_frag); 63 | basicPipeline.compile(); 64 | 65 | animatedPipeline = new BasicPipeline(Shaders.texturedBones_vert, Shaders.textured_frag); 66 | animatedPipeline.addVertexData(G4Constants.VERTEX_DATA_JOINT_INDEX, VertexData.Float4); 67 | animatedPipeline.addVertexData(G4Constants.VERTEX_DATA_JOINT_WEIGHT, VertexData.Float4); 68 | animatedPipeline.compile(); 69 | 70 | floor = BasicMesh.createQuadMesh(new Vector3(-1, -1, 0), new Vector3(1, 1, 0), basicPipeline, Color.Green); 71 | floor.transform.setScale(new Vector3(10, 10, 1)); 72 | 73 | animatedMesh = SkeletalMesh.getOGEXAnimatedMesh(Assets.blobs.CharacterRunning_ogex, animatedPipeline, Color.White); 74 | animatedMesh.texture = Assets.images.CharacterTexture; 75 | animatedMesh.transform.scaleTransform(new Vector3(.7, .7, .7)); 76 | } 77 | 78 | override public function update(delta:Float) { 79 | handleCharacterMovement(delta); 80 | if(rotateArroundChacter) { 81 | rotateCamera(delta); 82 | } 83 | 84 | animatedMesh.update(delta); 85 | } 86 | 87 | private function handleCharacterMovement(delta:Float) { 88 | if(Application.keyboard.keyDown(kha.input.KeyCode.A)) { 89 | characterPosition.x += delta * characterSpeed; 90 | animatedMesh.transform.rotationY = Math.PI * 0.5; 91 | } else if(Application.keyboard.keyDown(kha.input.KeyCode.D)) { 92 | characterPosition.x -= delta * characterSpeed; 93 | animatedMesh.transform.rotationY = Math.PI * 1.5; 94 | } 95 | if(Application.keyboard.keyDown(kha.input.KeyCode.W)) { 96 | characterPosition.y += delta * characterSpeed; 97 | animatedMesh.transform.rotationY = Math.PI; 98 | } else if(Application.keyboard.keyDown(kha.input.KeyCode.S)) { 99 | characterPosition.y -= delta * characterSpeed; 100 | animatedMesh.transform.rotationY = 0; 101 | } 102 | } 103 | 104 | private function rotateCamera(delta:Float) { 105 | cameraAngle += delta * cameraRotationSpeed * Math.PI * 2; 106 | 107 | cameraPosition.x = characterPosition.x + Math.sin(cameraAngle) * cameraRotationRadius; 108 | cameraPosition.y = characterPosition.y + Math.cos(cameraAngle) * cameraRotationRadius; 109 | } 110 | 111 | override public function render(backbuffer:Image) { 112 | camera.transform.setPosition(cameraPosition); 113 | animatedMesh.transform.setPosition(characterPosition); 114 | var fastCharacterPosition:FastVector3 = new FastVector3(characterPosition.x, characterPosition.y, characterPosition.z); 115 | 116 | camera.lookAt( 117 | lookAtCharacter ? characterPosition.fast() : new FastVector3(0, 0, 0), 118 | new FastVector3(0, 0, -1) 119 | ); 120 | 121 | backbuffer.g4.begin(); 122 | backbuffer.g4.clear(Color.Black, Math.POSITIVE_INFINITY); 123 | 124 | animatedMesh.render(backbuffer); 125 | 126 | floor.render(backbuffer); 127 | 128 | backbuffer.g4.end(); 129 | } 130 | 131 | override public function renderFramebuffer(framebuffer:Framebuffer) { 132 | ui.begin(framebuffer.g2); 133 | if(ui.window(Id.handle(), 0, 0, 400, 800)) { 134 | uiToggle = ui.check(Id.handle({selected: true}), "UI On/Off"); 135 | if(uiToggle) { 136 | lookAtCharacter = ui.check(Id.handle({selected: lookAtCharacter}), "Look At Character"); 137 | 138 | characterSpeed = ui.slider(Id.handle({value: characterSpeed}), "Character Speed", 0, 100, true, 10, true); 139 | 140 | rotateArroundChacter = ui.check(Id.handle({selected: rotateArroundChacter}), "Rotate Arround Chacter"); 141 | if(rotateArroundChacter) { 142 | cameraRotationRadius = ui.slider(Id.handle({value: cameraRotationRadius}), "Camera Rotation Radius", 0, 100, true, 10, true); 143 | cameraRotationSpeed = ui.slider(Id.handle({value: cameraRotationSpeed}), "Camera Rotation Speed", -25, 25, true, 10, true); 144 | cameraPosition.z = ui.slider(Id.handle({value: cameraPosition.z}), "Camera Position Z", -25, 25, true, 10, true); 145 | } else { 146 | ZUIUtils.vector3Sliders(ui, Id.handle(), cameraPosition, "Camera Position", -25, 25, 10); 147 | } 148 | 149 | animatedMesh.animationSpeed = ui.slider(Id.handle({value: animatedMesh.animationSpeed}), "Animation Speed", -10, 10, true, 10, true); 150 | } 151 | } 152 | ui.end(); 153 | } 154 | 155 | } -------------------------------------------------------------------------------- /Source/simpleChallenges/SimpleImageSlideshow.hx: -------------------------------------------------------------------------------- 1 | package simpleChallenges; 2 | 3 | import kha.graphics4.ConstantLocation; 4 | import kext.g4basics.Texture; 5 | import kext.g4basics.BasicMesh; 6 | import kha.math.Vector3; 7 | import kext.g4basics.Camera3D; 8 | import kha.math.FastVector3; 9 | import kext.g4basics.BasicPipeline; 10 | import kha.Shaders; 11 | import kha.Assets; 12 | import kha.math.Vector2; 13 | import kha.graphics4.FragmentShader; 14 | import kha.Color; 15 | import kha.Image; 16 | import kext.Application; 17 | import kext.AppState; 18 | 19 | class SlideImage { 20 | public var image:Image; 21 | 22 | public var scale:Vector2 = new Vector2(1, 1); 23 | public var offset:Vector2 = new Vector2(0, 0); 24 | 25 | public var transitionIn:FragmentShader; 26 | public var transitionInTime:Float = 0; 27 | 28 | public var shader:FragmentShader; 29 | public var liveTime:Float = 1; 30 | 31 | public var transitionOut:FragmentShader; 32 | public var transitionOutTime:Float = 0; 33 | 34 | public function new(image:Image, inShader:FragmentShader, outShader:FragmentShader) { 35 | this.image = image; 36 | 37 | transitionIn = inShader; 38 | shader = Shaders.colored_frag; 39 | transitionOut = outShader; 40 | } 41 | } 42 | 43 | class SimpleImageSlideshow extends AppState { 44 | private static inline var CANVAS_WIDTH:Int = 800; 45 | private static inline var CANVAS_HEIGHT:Int = 800; 46 | private static inline var NAME:String = "Simple Image Slideshow"; 47 | 48 | public static function initApplication() { 49 | return new Application( 50 | {title: SimpleImageSlideshow.NAME, width: SimpleImageSlideshow.CANVAS_WIDTH, height: SimpleImageSlideshow.CANVAS_HEIGHT}, 51 | {initState: SimpleImageSlideshow, defaultFontName: "KenPixel"} 52 | ); 53 | } 54 | 55 | private var slides:Array; 56 | private var slideIndex:Int = -1; 57 | private var currentSlide:SlideImage; 58 | private var nextSlide:SlideImage; 59 | 60 | private var camera:Camera3D; 61 | private var pipelineIn:BasicPipeline; 62 | private var pipeline:BasicPipeline; 63 | private var pipelineOut:BasicPipeline; 64 | private var screenQuad:BasicMesh; 65 | 66 | private var counter:Float = 0; 67 | 68 | private var inTimeLocation:ConstantLocation; 69 | private var outTimeLocation:ConstantLocation; 70 | 71 | public function new() { 72 | super(); 73 | 74 | slides = []; 75 | var slide1 = new SlideImage(Assets.images.TestImage001, Shaders.imageFade_frag, Shaders.imageFade_frag); 76 | var slide2 = new SlideImage(Assets.images.TestImage002, Shaders.imageFade_frag, Shaders.imageFade_frag); 77 | slides.push(slide1); 78 | slides.push(slide2); 79 | currentSlide = slide1; 80 | nextSlide = slide2; 81 | 82 | camera = new Camera3D(); 83 | camera.transform.setPosition(new Vector3(0, 0, -10)); 84 | camera.lookAt(new FastVector3(0, 0, 0)); 85 | camera.orthogonal(1, CANVAS_WIDTH / CANVAS_HEIGHT); 86 | Application.mainCamera = camera; 87 | createPipeline(Shaders.textured_frag); 88 | createPipelineIn(Shaders.textured_frag); 89 | createPipelineOut(Shaders.textured_frag); 90 | 91 | screenQuad = BasicMesh.createQuadMesh(new Vector3(1, -1, 0), new Vector3(-1, 1, 0), pipelineIn, Color.White); 92 | screenQuad.textures = [new Texture(slide1.image, "TEXTURE"), new Texture(slide2.image, "NEXT_IMAGE")]; 93 | screenQuad.setPipeline = false; 94 | } 95 | 96 | private function createPipeline(shader:FragmentShader) { 97 | pipeline = new BasicPipeline(Shaders.textured_vert, shader, camera); 98 | pipeline.basicTexture = false; 99 | pipeline.compile(); 100 | } 101 | 102 | private function createPipelineIn(shader:FragmentShader) { 103 | pipelineIn = new BasicPipeline(Shaders.textured_vert, shader, camera); 104 | pipelineIn.basicTexture = false; 105 | pipelineIn.compile(); 106 | 107 | inTimeLocation = pipelineIn.getConstantLocation("TIME"); 108 | } 109 | 110 | private function createPipelineOut(shader:FragmentShader) { 111 | pipelineOut = new BasicPipeline(Shaders.textured_vert, shader, camera); 112 | pipelineOut.basicTexture = false; 113 | pipelineOut.compile(); 114 | 115 | outTimeLocation = pipelineOut.getConstantLocation("TIME"); 116 | } 117 | 118 | override function update(delta:Float) { 119 | super.update(delta); 120 | 121 | counter += delta; 122 | } 123 | 124 | override function render(backbuffer:Image) { 125 | super.render(backbuffer); 126 | 127 | beginAndClear3D(backbuffer, Color.Black); 128 | 129 | screenQuad.transform.scaleY = currentSlide.image.height / currentSlide.image.width; 130 | 131 | screenQuad.pipeline = pipelineIn; 132 | backbuffer.g4.setPipeline(pipelineIn); 133 | backbuffer.g4.setFloat(timeLocation, counter); 134 | screenQuad.render(backbuffer); 135 | 136 | end3D(backbuffer); 137 | } 138 | 139 | } -------------------------------------------------------------------------------- /Source/simpleChallenges/SimpleLighting.hx: -------------------------------------------------------------------------------- 1 | package simpleChallenges; 2 | 3 | import kha.Assets; 4 | import kha.Color; 5 | import kha.Image; 6 | import kha.Framebuffer; 7 | import kha.Shaders; 8 | 9 | import kha.math.FastMatrix4; 10 | import kha.math.FastMatrix3; 11 | import kha.math.Vector3; 12 | import kha.math.FastVector3; 13 | import kha.math.FastVector4; 14 | import kha.graphics4.ConstantLocation; 15 | 16 | import kext.Application; 17 | import kext.AppState; 18 | import kext.g4basics.BasicMesh; 19 | import kext.g4basics.BasicPipeline; 20 | import kext.loaders.STLMeshLoader; 21 | import kext.loaders.OBJMeshLoader; 22 | import kext.debug.Debug; 23 | 24 | import zui.Zui; 25 | import zui.Ext; 26 | import zui.Id; 27 | 28 | class SimpleLighting extends AppState { 29 | private static inline var CANVAS_WIDTH:Int = 1600; 30 | private static inline var CANVAS_HEIGHT:Int = 800; 31 | private static inline var NAME:String = "Simple Lighting"; 32 | 33 | private var pipeline:BasicPipeline; 34 | private var cubeOBJMesh:BasicMesh; 35 | private var sphereOBJMesh:BasicMesh; 36 | private var torusOBJMesh:BasicMesh; 37 | private var suzanneOBJMesh:BasicMesh; 38 | private var carFormulaOBJMesh:BasicMesh; 39 | private var cubeSTLMesh:BasicMesh; 40 | private var sphereSTLMesh:BasicMesh; 41 | private var torusSTLMesh:BasicMesh; 42 | private var suzanneSTLMesh:BasicMesh; 43 | private var carFormulaSTLMesh:BasicMesh; 44 | 45 | private var locationDirectionalLight:ConstantLocation; 46 | private var locationDirectionalColor:ConstantLocation; 47 | private var locationAmbientLight:ConstantLocation; 48 | 49 | private var projectionMatrix:FastMatrix4; 50 | private var viewMatrix:FastMatrix4; 51 | private var modelMatrix:FastMatrix4; 52 | private var projectionViewMatrix:FastMatrix4; 53 | private var mvpMatrix:FastMatrix4; 54 | private var normalMatrix:FastMatrix3; 55 | 56 | private var directionalLight:FastVector4; 57 | private var directionalColor:Color; 58 | private var ambientLight:Color; 59 | private var deltaAngle:FastVector3; 60 | private var meshScale:FastVector3; 61 | 62 | private var meshType:MeshType = MeshType.CUBE_OBJ; 63 | 64 | public static function initApplication() { 65 | return new Application( 66 | {title: SimpleLighting.NAME, width: SimpleLighting.CANVAS_WIDTH, height: SimpleLighting.CANVAS_HEIGHT}, 67 | {initState: SimpleLighting, defaultFontName: "KenPixel"} 68 | ); 69 | } 70 | 71 | public function new() { 72 | super(); 73 | 74 | pipeline = new BasicPipeline(Shaders.directionalLighting_vert, Shaders.directionalLighting_frag); 75 | pipeline.compile(); 76 | locationDirectionalLight = pipeline.getConstantLocation("LIGHT_DIRECTION"); 77 | locationDirectionalColor = pipeline.getConstantLocation("LIGHT_COLOR"); 78 | locationAmbientLight = pipeline.getConstantLocation("AMBIENT_COLOR"); 79 | 80 | directionalLight = new FastVector4(0, 1, 0, 0); 81 | directionalColor = Color.fromFloats(1, 0, 0, 1); 82 | ambientLight = Color.fromFloats(.2, .2, .2, 1); 83 | deltaAngle = new FastVector3(0, 0, 1); 84 | meshScale = new FastVector3(1, 1, 1); 85 | var size:UInt = 5; 86 | var ratio:Float = CANVAS_WIDTH / CANVAS_HEIGHT; 87 | projectionMatrix = FastMatrix4.orthogonalProjection(-size * ratio, size * ratio, size, -size, .1, 100); 88 | viewMatrix = FastMatrix4.lookAt( 89 | new FastVector3(-1, 1, -1).mult(20), 90 | new FastVector3(0, 0, 0), 91 | new FastVector3(0, 1, 0) 92 | ); 93 | modelMatrix = FastMatrix4.identity(); 94 | projectionViewMatrix = projectionMatrix.multmat(viewMatrix); 95 | mvpMatrix = projectionViewMatrix.multmat(modelMatrix); 96 | 97 | cubeOBJMesh = BasicMesh.getOBJMesh(Assets.blobs.cube_obj, pipeline.vertexStructure, Color.White); 98 | cubeSTLMesh = BasicMesh.getSTLMesh(Assets.blobs.cube_stl, pipeline.vertexStructure, Color.White); 99 | 100 | sphereOBJMesh = BasicMesh.getOBJMesh(Assets.blobs.sphere_obj, pipeline.vertexStructure, Color.White); 101 | sphereSTLMesh = BasicMesh.getSTLMesh(Assets.blobs.sphere_stl, pipeline.vertexStructure, Color.White); 102 | 103 | torusOBJMesh = BasicMesh.getOBJMesh(Assets.blobs.torus_obj, pipeline.vertexStructure, Color.White); 104 | torusSTLMesh = BasicMesh.getSTLMesh(Assets.blobs.torus_stl, pipeline.vertexStructure, Color.White); 105 | 106 | suzanneOBJMesh = BasicMesh.getOBJMesh(Assets.blobs.suzanne_obj, pipeline.vertexStructure, Color.White); 107 | suzanneSTLMesh = BasicMesh.getSTLMesh(Assets.blobs.suzanne_stl, pipeline.vertexStructure, Color.White); 108 | 109 | carFormulaOBJMesh = BasicMesh.getOBJMesh(Assets.blobs.carFormula_obj, pipeline.vertexStructure, Color.White); 110 | carFormulaSTLMesh = BasicMesh.getSTLMesh(Assets.blobs.carFormula_stl, pipeline.vertexStructure, Color.White); 111 | } 112 | 113 | override public function render(backbuffer:Image) { 114 | renderMesh(backbuffer); 115 | } 116 | 117 | private inline function renderMesh(backbuffer:Image) { 118 | backbuffer.g4.begin(); 119 | backbuffer.g4.clear(Color.Black, Math.POSITIVE_INFINITY); 120 | 121 | backbuffer.g4.setPipeline(pipeline); 122 | 123 | drawMesh(backbuffer); 124 | 125 | Debug.drawDebugCube(backbuffer, projectionViewMatrix, new Vector3(directionalLight.x, directionalLight.y, directionalLight.z).mult(5), 0.1); 126 | 127 | backbuffer.g4.end(); 128 | } 129 | 130 | private inline function drawMesh(backbuffer:Image) { 131 | switch(meshType) { 132 | case MeshType.CUBE_OBJ: 133 | cubeOBJMesh.setBufferMesh(backbuffer); 134 | case MeshType.SPHERE_OBJ: 135 | sphereOBJMesh.setBufferMesh(backbuffer); 136 | case MeshType.TORUS_OBJ: 137 | torusOBJMesh.setBufferMesh(backbuffer); 138 | case MeshType.SUZANNE_OBJ: 139 | suzanneOBJMesh.setBufferMesh(backbuffer); 140 | case MeshType.CAR_FORMULA_OBJ: 141 | carFormulaOBJMesh.setBufferMesh(backbuffer); 142 | case MeshType.CUBE_STL: 143 | cubeSTLMesh.setBufferMesh(backbuffer); 144 | case MeshType.TORUS_STL: 145 | torusSTLMesh.setBufferMesh(backbuffer); 146 | case MeshType.SPHERE_STL: 147 | sphereSTLMesh.setBufferMesh(backbuffer); 148 | case MeshType.SUZANNE_STL: 149 | suzanneSTLMesh.setBufferMesh(backbuffer); 150 | case MeshType.CAR_FORMULA_STL: 151 | carFormulaSTLMesh.setBufferMesh(backbuffer); 152 | } 153 | 154 | modelMatrix = FastMatrix4.identity() 155 | .multmat(FastMatrix4.scale(meshScale.x, meshScale.y, meshScale.z)) 156 | .multmat(FastMatrix4.rotation(deltaAngle.x * Application.time, deltaAngle.y * Application.time, deltaAngle.z * Application.time)); 157 | mvpMatrix = projectionViewMatrix.multmat(modelMatrix); 158 | 159 | normalMatrix = new FastMatrix3(modelMatrix._00, modelMatrix._10, modelMatrix._20, 160 | modelMatrix._01, modelMatrix._11, modelMatrix._21, 161 | modelMatrix._02, modelMatrix._12, modelMatrix._22).inverse().transpose(); 162 | 163 | backbuffer.g4.setMatrix(pipeline.locationMVPMatrix, mvpMatrix); 164 | backbuffer.g4.setMatrix(pipeline.locationViewMatrix, viewMatrix); 165 | backbuffer.g4.setMatrix3(pipeline.locationNormalMatrix, normalMatrix); 166 | backbuffer.g4.setVector4(locationDirectionalLight, directionalLight); 167 | backbuffer.g4.setVector4(locationAmbientLight, new FastVector4(ambientLight.R, ambientLight.G, ambientLight.B, ambientLight.A)); 168 | backbuffer.g4.setVector4(locationDirectionalColor, new FastVector4(directionalColor.R, directionalColor.G, directionalColor.B, directionalColor.A)); 169 | 170 | backbuffer.g4.drawIndexedVertices(); 171 | } 172 | 173 | override public function renderFramebuffer(framebuffer:Framebuffer) { 174 | ui.begin(framebuffer.g2); 175 | if(ui.window(Id.handle(), 0, 0, 400, 800)) { 176 | uiToggle = ui.check(Id.handle({selected: true}), "UI On/Off"); 177 | if(uiToggle) { 178 | if(ui.panel(Id.handle({selected: true}), "General")) { 179 | meshScale.x = ui.slider(Id.handle({value: meshScale.x}), "Mesh Scale X", 0.01, 4, true, 100, true); 180 | meshScale.y = ui.slider(Id.handle({value: meshScale.y}), "Mesh Scale Y", 0.01, 4, true, 100, true); 181 | meshScale.z = ui.slider(Id.handle({value: meshScale.z}), "Mesh Scale Z", 0.01, 4, true, 100, true); 182 | deltaAngle.x = ui.slider(Id.handle({value: deltaAngle.x}), "Delta Angle X", -5, 5, true, 100, true); 183 | deltaAngle.y = ui.slider(Id.handle({value: deltaAngle.y}), "Delta Angle Y", -5, 5, true, 100, true); 184 | deltaAngle.z = ui.slider(Id.handle({value: deltaAngle.z}), "Delta Angle Z", -5, 5, true, 100, true); 185 | } 186 | if(ui.panel(Id.handle({selected: true}), "Mesh Type")) { 187 | if(ui.button("Cube OBJ")) { meshType = MeshType.CUBE_OBJ; } 188 | if(ui.button("Sphere OBJ")) { meshType = MeshType.SPHERE_OBJ; } 189 | if(ui.button("Torus OBJ")) { meshType = MeshType.TORUS_OBJ; } 190 | if(ui.button("Suzanne OBJ")) { meshType = MeshType.SUZANNE_OBJ; } 191 | if(ui.button("Racing Car OBJ")) { meshType = MeshType.CAR_FORMULA_OBJ; } 192 | if(ui.button("Cube STL")) { meshType = MeshType.CUBE_STL; } 193 | if(ui.button("Sphere STL")) { meshType = MeshType.SPHERE_STL; } 194 | if(ui.button("Torus STL")) { meshType = MeshType.TORUS_STL; } 195 | if(ui.button("Suzanne STL")) { meshType = MeshType.SUZANNE_STL; } 196 | if(ui.button("Racing Car STL")) { meshType = MeshType.CAR_FORMULA_STL; } 197 | } 198 | if(ui.panel(Id.handle({selected: true}), "Lighting")) { 199 | directionalLight.x = ui.slider(Id.handle({value: directionalLight.x}), "Light Direction X", -1, 1, true, 100, true); 200 | directionalLight.y = ui.slider(Id.handle({value: directionalLight.y}), "Light Direction Y", -1, 1, true, 100, true); 201 | directionalLight.z = ui.slider(Id.handle({value: directionalLight.z}), "Light Direction Z", -1, 1, true, 100, true); 202 | directionalColor = Ext.colorPicker(ui, Id.handle({color: directionalColor}), false); 203 | ambientLight = Ext.colorPicker(ui, Id.handle({color: ambientLight}), false); 204 | } 205 | } 206 | } 207 | ui.end(); 208 | } 209 | 210 | override public function update(delta:Float) { 211 | 212 | } 213 | 214 | } -------------------------------------------------------------------------------- /Source/utils/DemoMeshes.hx: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import kha.math.Vector3; 4 | import kext.g4basics.BasicPipeline; 5 | import kha.Assets; 6 | import kha.Color; 7 | import kha.graphics4.VertexStructure; 8 | 9 | import kext.g4basics.BasicMesh; 10 | 11 | class DemoMeshes { 12 | 13 | public static var QUAD:BasicMesh; 14 | public static var CUBE:BasicMesh; 15 | public static var SPHERE:BasicMesh; 16 | public static var TORUS:BasicMesh; 17 | public static var ARROW:BasicMesh; 18 | public static var SUZANNE:BasicMesh; 19 | 20 | public static function init(pipeline:BasicPipeline, color:Color = null) { 21 | QUAD = BasicMesh.createQuadMesh(new Vector3(-1, -1, 0), new Vector3(1, 1, 0), pipeline, color); 22 | CUBE = BasicMesh.getOBJMesh(Assets.blobs.cube_obj, pipeline, color); 23 | SPHERE = BasicMesh.getOBJMesh(Assets.blobs.sphere_obj, pipeline, color); 24 | TORUS = BasicMesh.getOBJMesh(Assets.blobs.torus_obj, pipeline, color); 25 | ARROW = BasicMesh.getOBJMesh(Assets.blobs.arrow_obj, pipeline, color); 26 | SUZANNE = BasicMesh.getOBJMesh(Assets.blobs.suzanne_obj, pipeline, color); 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /Source/utils/ZUIUtils.hx: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import kha.graphics4.TextureAddressing; 4 | import kha.Color; 5 | import kha.math.Vector2; 6 | import kha.math.Vector3; 7 | import kha.math.FastVector4; 8 | import kext.g4basics.BasicMesh; 9 | 10 | import zui.Zui; 11 | import zui.Ext; 12 | import zui.Id; 13 | 14 | using tweenxcore.Tools; 15 | 16 | class ZUIUtils { 17 | 18 | private static var easingFunctions:Array = [ "linear", "sineIn", "sineOut", "sineInOut", "sineOutIn", "quadIn", "quadOut", "quadInOut", "quadOutIn", "cubicIn", "cubicOut", "cubicInOut", "cubicOutIn", "quartIn", "quartOut", "quartInOut", "quartOutIn", "quintIn", "quintOut", "quintInOut", "quintOutIn", "expoIn", "expoOut", "expoInOut", "expoOutIn", "circIn", "circOut", "circInOut", "circOutIn", "bounceIn", "bounceOut", "bounceInOut", "bounceOutIn", "backIn", "backOut", "backInOut", "backOutIn", "elasticIn", "elasticOut", "elasticInOut", "elasticOutIn", "warpOut", "warpIn", "warpInOut", "warpOutIn" ]; 19 | 20 | public static inline function vector2Sliders(ui:Zui, handle: Handle, vector:Vector2, label:String, from:Float, to:Float, precision:Int) { 21 | vector.x = ui.slider(handle.nest(0, {value: vector.x}), '$label X', from, to, true, precision, true); 22 | vector.y = ui.slider(handle.nest(1, {value: vector.y}), '$label Y', from, to, true, precision, true); 23 | } 24 | 25 | public static inline function vector3Sliders(ui:Zui, handle: Handle, vector:Vector3, label:String, from:Float, to:Float, precision:Int) { 26 | vector.x = ui.slider(handle.nest(0, {value: vector.x}), '$label X', from, to, true, precision, true); 27 | vector.y = ui.slider(handle.nest(1, {value: vector.y}), '$label Y', from, to, true, precision, true); 28 | vector.z = ui.slider(handle.nest(2, {value: vector.z}), '$label Z', from, to, true, precision, true); 29 | } 30 | 31 | public static inline function lightingParameters(ui:Zui, handle: Handle, lightDirection:FastVector4, lightColor:FastVector4, ambientColor:FastVector4, selected:Bool = true) { 32 | if(ui.panel(Id.handle({selected: selected}), "Lighting")) { 33 | var light:Vector3 = new Vector3(lightDirection.x, lightDirection.y, lightDirection.z); 34 | vector3Sliders(ui, handle.nest(0), light, "Light Direction", -1, 1, 100); 35 | lightDirection.x = light.x; 36 | lightDirection.y = light.y; 37 | lightDirection.z = light.z; 38 | 39 | var color:Color; 40 | ui.text("Light Color"); 41 | color = Color.fromValue(Ext.colorPicker(ui, handle.nest(1, {color: Color.fromFloats(lightColor.x, lightColor.y, lightColor.z, lightColor.w)}), true)); 42 | lightColor.x = color.R; 43 | lightColor.y = color.G; 44 | lightColor.z = color.B; 45 | lightColor.w = color.A; 46 | 47 | ui.text("Ambient Color"); 48 | color = Color.fromValue(Ext.colorPicker(ui, handle.nest(2, {color: Color.fromFloats(ambientColor.x, ambientColor.y, ambientColor.z, ambientColor.w)}), true)); 49 | ambientColor.x = color.R; 50 | ambientColor.y = color.G; 51 | ambientColor.z = color.B; 52 | ambientColor.w = color.A; 53 | } 54 | } 55 | 56 | #if DEMO_MESHES 57 | public static function meshSelector(ui:Zui, handle: Handle, lastValue:BasicMesh, selected:Bool = true):BasicMesh { 58 | if(ui.panel(handle.nest(0, {selected: selected}), "Mesh Type")) { 59 | if(ui.button("Quad")) { return DemoMeshes.QUAD; } 60 | if(ui.button("Cube")) { return DemoMeshes.CUBE; } 61 | if(ui.button("Sphere")) { return DemoMeshes.SPHERE; } 62 | if(ui.button("Torus")) { return DemoMeshes.TORUS; } 63 | if(ui.button("Arrow")) { return DemoMeshes.ARROW; } 64 | if(ui.button("Suzanne")) { return DemoMeshes.SUZANNE; } 65 | } 66 | return null; 67 | } 68 | #end 69 | 70 | public static function textureAddresing(ui:Zui, handle: Handle, value:TextureAddressing, label:String = null, selected:Bool = false):TextureAddressing { 71 | if(ui.panel(handle.nest(0, {selected: selected}), label == null ? "Texture Addressing" : label)) { 72 | if(ui.button("Repeat")) { return Repeat; } 73 | if(ui.button("Mirror")) { return Mirror; } 74 | if(ui.button("Clamp")) { return Clamp; } 75 | } 76 | return value; 77 | } 78 | 79 | public static function tweenEasing(ui:Zui, handle: Handle, label:String = null, selected:Bool = false):Int 80 | { 81 | var easingIndex:Int = Math.floor(handle.value); 82 | ui.text(label, Align.Center); 83 | easingIndex = Math.floor(ui.slider(handle, easingFunctions[easingIndex], 0, easingFunctions.length - 1, false, 1, false, Align.Right, false)); 84 | return easingIndex; 85 | } 86 | 87 | public static function getEasingByIndex(index:Int):Float -> Float 88 | { 89 | return Reflect.field(Easing, easingFunctions[index]); 90 | } 91 | 92 | public static function callEasingByIndex(index:Int, value:Float):Float 93 | { 94 | return Reflect.callMethod(Easing, Reflect.field(Easing, easingFunctions[index]), [value]); 95 | } 96 | 97 | } -------------------------------------------------------------------------------- /build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | ::Go up a folder, so khamake is called from the right directory 3 | ::cd ..\ 4 | 5 | echo ___________________________________ 6 | echo khamake builder 7 | echo type q to quit. 8 | echo ___________________________________ 9 | ::Target input. 10 | :platform_input 11 | set /p target="Specify target:" 12 | 13 | 14 | if %target%==q ( 15 | echo Quitting... 16 | goto end_of_file 17 | ) 18 | ::Options input. 19 | set /p options="Specify options:" 20 | 21 | set "TRUE=" 22 | ::Checks if the input matches any of the valid targets 23 | IF %target%==windows set TRUE=1 24 | IF %target%==linux set TRUE=1 25 | IF %target%==android set TRUE=1 26 | IF %target%==android-native set TRUE=1 27 | IF %target%==windowsrt set TRUE=1 28 | IF %target%==osx set TRUE=1 29 | IF %target%==ios set TRUE=1 30 | IF %target%==html5 set TRUE=1 31 | IF %target%==flash set TRUE=1 32 | IF %target%==wpf set TRUE=1 33 | IF %target%==xna set TRUE=1 34 | IF %target%==java set TRUE=1 35 | IF %target%==psm set TRUE=1 36 | IF %target%==dalvik set TRUE=1 37 | IF %target%==tizen set TRUE=1 38 | 39 | ::If the input is valid call Hake 40 | ::If True is not defined ( no valid target ) jump back to the start 41 | IF defined TRUE ( 42 | start /b /wait %opt% node Kha\make %target% %options% 43 | ) else ( 44 | echo Unsupported platform... 45 | goto platform_input 46 | ) 47 | 48 | :end_of_file 49 | 50 | echo ___________________________________ 51 | pause 52 | -------------------------------------------------------------------------------- /buildAndroid.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | ::Go up a folder, so khamake is called from the right directory 3 | ::cd ..\ 4 | 5 | echo ___________________________________ 6 | echo khamake builder 7 | echo type q to quit. 8 | echo ___________________________________ 9 | 10 | ::Target input. 11 | :platform_input 12 | set target=android 13 | 14 | ::Options input. 15 | set options= 16 | 17 | start /b /wait %opt% node Kha\make %target% %options% 18 | 19 | echo ___________________________________ -------------------------------------------------------------------------------- /buildAndroidNative.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | ::Go up a folder, so khamake is called from the right directory 3 | ::cd ..\ 4 | 5 | echo ___________________________________ 6 | echo khamake builder 7 | echo type q to quit. 8 | echo ___________________________________ 9 | 10 | ::Target input. 11 | :platform_input 12 | set target=android-native 13 | 14 | ::Options input. 15 | set options= 16 | 17 | start /b /wait %opt% node Kha\make %target% %options% 18 | 19 | echo ___________________________________ -------------------------------------------------------------------------------- /buildHTML5.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | ::Go up a folder, so khamake is called from the right directory 3 | ::cd ..\ 4 | 5 | echo ___________________________________ 6 | echo khamake builder 7 | echo type q to quit. 8 | echo ___________________________________ 9 | 10 | ::Target input. 11 | :platform_input 12 | set target=html5 13 | 14 | ::Options input. 15 | set options= 16 | 17 | start /b /wait %opt% node Kha\make %target% %options% 18 | 19 | echo ___________________________________ -------------------------------------------------------------------------------- /buildKrom.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | ::Go up a folder, so khamake is called from the right directory 3 | ::cd ..\ 4 | 5 | echo ___________________________________ 6 | echo khamake builder 7 | echo type q to quit. 8 | echo ___________________________________ 9 | 10 | ::Target input. 11 | :platform_input 12 | set target=krom 13 | 14 | ::Options input. 15 | set options= 16 | 17 | start /b /wait %opt% node Kha\make %target% %options% -g opengl 18 | 19 | echo ___________________________________ -------------------------------------------------------------------------------- /buildWindows.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | ::Go up a folder, so khamake is called from the right directory 3 | ::cd ..\ 4 | 5 | echo ___________________________________ 6 | echo khamake builder 7 | echo type q to quit. 8 | echo ___________________________________ 9 | 10 | ::Target input. 11 | :platform_input 12 | set target=windows 13 | 14 | ::Options input. 15 | set options= 16 | 17 | start /b /wait %opt% node Kha\make %target% %options% 18 | 19 | echo ___________________________________ -------------------------------------------------------------------------------- /initKha.bat: -------------------------------------------------------------------------------- 1 | git submodule add https://github.com/Kode/Kha 2 | git submodule update --init --recursive -------------------------------------------------------------------------------- /initLibraries.bat: -------------------------------------------------------------------------------- 1 | git submodule add https://github.com/JuanRinaudo/kext Libraries/kext 2 | git submodule add https://github.com/armory3d/zui Libraries/zui -------------------------------------------------------------------------------- /khafile.js: -------------------------------------------------------------------------------- 1 | let project = new Project('Coding Challenges Kha'); 2 | 3 | project.addLibrary('zui'); 4 | project.addLibrary('kext'); 5 | project.addLibrary('tweenxcore'); 6 | 7 | project.addShaders('Assets/Shaders/**'); 8 | project.addShaders('Assets/FlowField/**'); 9 | // project.addShaders('Assets/GameOfLife/**'); 10 | // project.addShaders('Assets/PostProcessingShaders/**'); 11 | 12 | project.addAssets('Assets/Common/**'); 13 | 14 | // project.addAssets('Assets/Images/**'); 15 | // project.addDefine('DEMO_MESHES'); 16 | // project.addAssets('Assets/BasicGeometry/**'); 17 | // project.addAssets('Assets/Models/**'); 18 | // project.addAssets('Assets/Bones/**'); 19 | 20 | // project.addAssets('Assets/Transitions/**'); 21 | // project.addAssets('Assets/GameAssets/SimpleCarGame'); 22 | 23 | project.addSources('Source'); 24 | 25 | project.addParameter('-dce std'); 26 | 27 | resolve(project); -------------------------------------------------------------------------------- /korefile.js: -------------------------------------------------------------------------------- 1 | let fs = require('fs'); 2 | let path = require('path'); 3 | let project = new Project('Coding Challenges Kha'); 4 | project.addDefine('HXCPP_API_LEVEL=332'); 5 | project.targetOptions = {"html5":{},"flash":{},"android":{},"ios":{}}; 6 | project.setDebugDir('build/windows'); 7 | await project.addProject('build/windows-build'); 8 | await project.addProject('C:/Users/Us/Desktop/Development/CodingChallengesKha/Kha'); 9 | if (fs.existsSync(path.join('Libraries/zui', 'korefile.js'))) { 10 | await project.addProject('Libraries/zui'); 11 | } 12 | if (fs.existsSync(path.join('Libraries/kext', 'korefile.js'))) { 13 | await project.addProject('Libraries/kext'); 14 | } 15 | if (fs.existsSync(path.join('C:/HaxeToolkit/haxe/lib/tweenxcore', 'korefile.js'))) { 16 | await project.addProject('C:/HaxeToolkit/haxe/lib/tweenxcore'); 17 | } 18 | resolve(project); 19 | -------------------------------------------------------------------------------- /updateKha.bat: -------------------------------------------------------------------------------- 1 | git submodule foreach --recursive git pull origin master --------------------------------------------------------------------------------