├── .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
--------------------------------------------------------------------------------