dialog WIP paths consolidation and rendering
48
assets/dialogs/test_char.ink
Normal file
@@ -0,0 +1,48 @@
|
||||
-> encounter
|
||||
|
||||
=== encounter ===
|
||||
So. You came after all. # timer: 3.0 # parry: J
|
||||
+ [hit] -> outcome_hit
|
||||
+ [evaded] -> outcome_evaded
|
||||
+ [wrong_parry] -> outcome_wrong
|
||||
+ [parried_i] -> outcome_wrong
|
||||
+ [parried_j] -> outcome_correct
|
||||
+ [parried_l] -> outcome_wrong
|
||||
|
||||
=== outcome_correct ===
|
||||
Exactly right. # timer: 2.5
|
||||
-> END
|
||||
|
||||
=== outcome_hit ===
|
||||
You hesitate. Interesting. # timer: 2.5 # parry: I
|
||||
+ [hit] -> end_beaten
|
||||
+ [evaded] -> end_fled
|
||||
+ [wrong_parry] -> end_beaten
|
||||
+ [parried_i] -> end_strong
|
||||
+ [parried_j] -> end_beaten
|
||||
+ [parried_l] -> end_beaten
|
||||
|
||||
=== outcome_evaded ===
|
||||
Running already? # timer: 2.5
|
||||
-> END
|
||||
|
||||
=== outcome_wrong ===
|
||||
That wasn't the answer I expected. # timer: 2.5 # parry: L
|
||||
+ [hit] -> end_beaten
|
||||
+ [evaded] -> end_fled
|
||||
+ [wrong_parry] -> end_beaten
|
||||
+ [parried_i] -> end_beaten
|
||||
+ [parried_j] -> end_beaten
|
||||
+ [parried_l] -> end_strong
|
||||
|
||||
=== end_beaten ===
|
||||
I see. You are not ready. # timer: 2.5
|
||||
-> END
|
||||
|
||||
=== end_fled ===
|
||||
So be it. # timer: 2.0
|
||||
-> END
|
||||
|
||||
=== end_strong ===
|
||||
Good. Perhaps you are worthy after all. # timer: 3.0
|
||||
-> END
|
||||
1
assets/dialogs/test_char.ink.json
Normal file
@@ -0,0 +1 @@
|
||||
{"inkVersion":21,"root":[[[{"->":"encounter"},{"#n":"g-0"}],null],"done",{"encounter":[["^So. You came after all. ","#","^timer: 3.0 ","/#","#","^parry: J","/#","\n","ev","str","^hit","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^evaded","/str","/ev",{"*":".^.c-1","flg":4},"ev","str","^wrong_parry","/str","/ev",{"*":".^.c-2","flg":4},"ev","str","^parried_i","/str","/ev",{"*":".^.c-3","flg":4},"ev","str","^parried_j","/str","/ev",{"*":".^.c-4","flg":4},"ev","str","^parried_l","/str","/ev",{"*":".^.c-5","flg":4},{"c-0":["^ ",{"->":"outcome_hit"},"\n",null],"c-1":["^ ",{"->":"outcome_evaded"},"\n",null],"c-2":["^ ",{"->":"outcome_wrong"},"\n",null],"c-3":["^ ",{"->":"outcome_wrong"},"\n",null],"c-4":["^ ",{"->":"outcome_correct"},"\n",null],"c-5":["^ ",{"->":"outcome_wrong"},"\n",null]}],null],"outcome_correct":["^Exactly right. ","#","^timer: 2.5","/#","\n","end",null],"outcome_hit":[["^You hesitate. Interesting. ","#","^timer: 2.5 ","/#","#","^parry: I","/#","\n","ev","str","^hit","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^evaded","/str","/ev",{"*":".^.c-1","flg":4},"ev","str","^wrong_parry","/str","/ev",{"*":".^.c-2","flg":4},"ev","str","^parried_i","/str","/ev",{"*":".^.c-3","flg":4},"ev","str","^parried_j","/str","/ev",{"*":".^.c-4","flg":4},"ev","str","^parried_l","/str","/ev",{"*":".^.c-5","flg":4},{"c-0":["^ ",{"->":"end_beaten"},"\n",null],"c-1":["^ ",{"->":"end_fled"},"\n",null],"c-2":["^ ",{"->":"end_beaten"},"\n",null],"c-3":["^ ",{"->":"end_strong"},"\n",null],"c-4":["^ ",{"->":"end_beaten"},"\n",null],"c-5":["^ ",{"->":"end_beaten"},"\n",null]}],null],"outcome_evaded":["^Running already? ","#","^timer: 2.5","/#","\n","end",null],"outcome_wrong":[["^That wasn't the answer I expected. ","#","^timer: 2.5 ","/#","#","^parry: L","/#","\n","ev","str","^hit","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^evaded","/str","/ev",{"*":".^.c-1","flg":4},"ev","str","^wrong_parry","/str","/ev",{"*":".^.c-2","flg":4},"ev","str","^parried_i","/str","/ev",{"*":".^.c-3","flg":4},"ev","str","^parried_j","/str","/ev",{"*":".^.c-4","flg":4},"ev","str","^parried_l","/str","/ev",{"*":".^.c-5","flg":4},{"c-0":["^ ",{"->":"end_beaten"},"\n",null],"c-1":["^ ",{"->":"end_fled"},"\n",null],"c-2":["^ ",{"->":"end_beaten"},"\n",null],"c-3":["^ ",{"->":"end_beaten"},"\n",null],"c-4":["^ ",{"->":"end_beaten"},"\n",null],"c-5":["^ ",{"->":"end_strong"},"\n",null]}],null],"end_beaten":["^I see. You are not ready. ","#","^timer: 2.5","/#","\n","end",null],"end_fled":["^So be it. ","#","^timer: 2.0","/#","\n","end",null],"end_strong":["^Good. Perhaps you are worthy after all. ","#","^timer: 3.0","/#","\n","end",null]}],"listDefs":{}}
|
||||
195
assets/meshes/burrs.gltf
Executable file
BIN
assets/meshes/player_mesh.glb
Normal file
BIN
assets/meshes/terrain.bin
Normal file
561
assets/meshes/terrain.gltf
Normal file
@@ -0,0 +1,561 @@
|
||||
{
|
||||
"asset":{
|
||||
"generator":"Khronos glTF Blender I/O v5.0.21",
|
||||
"version":"2.0"
|
||||
},
|
||||
"extensionsUsed":[
|
||||
"KHR_lights_punctual",
|
||||
"EXT_mesh_gpu_instancing"
|
||||
],
|
||||
"extensionsRequired":[
|
||||
"KHR_lights_punctual"
|
||||
],
|
||||
"extensions":{
|
||||
"KHR_lights_punctual":{
|
||||
"lights":[
|
||||
{
|
||||
"color":[
|
||||
1,
|
||||
1,
|
||||
1
|
||||
],
|
||||
"intensity":543.5141306588226,
|
||||
"spot":{
|
||||
"innerConeAngle":0.18840259313583374,
|
||||
"outerConeAngle":0.18840259313583374
|
||||
},
|
||||
"type":"spot",
|
||||
"range":1000,
|
||||
"name":"Spot",
|
||||
"extras":{
|
||||
"light_tag":"lighthouse"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"scene":0,
|
||||
"scenes":[
|
||||
{
|
||||
"name":"Scene",
|
||||
"nodes":[
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7
|
||||
]
|
||||
}
|
||||
],
|
||||
"nodes":[
|
||||
{
|
||||
"mesh":0,
|
||||
"name":"TreePrime",
|
||||
"translation":[
|
||||
16.22920036315918,
|
||||
29.08228302001953,
|
||||
39.89393615722656
|
||||
]
|
||||
},
|
||||
{
|
||||
"mesh":1,
|
||||
"name":"Lighthouse_base",
|
||||
"rotation":[
|
||||
0,
|
||||
-0.31448131799697876,
|
||||
0,
|
||||
0.9492637515068054
|
||||
],
|
||||
"scale":[
|
||||
25.161100387573242,
|
||||
8.222701072692871,
|
||||
8.222701072692871
|
||||
],
|
||||
"translation":[
|
||||
-367.9805908203125,
|
||||
113.61730194091797,
|
||||
212.62832641601562
|
||||
]
|
||||
},
|
||||
{
|
||||
"mesh":2,
|
||||
"name":"Lighthouse",
|
||||
"scale":[
|
||||
2.1515703201293945,
|
||||
24.724905014038086,
|
||||
2.1515703201293945
|
||||
],
|
||||
"translation":[
|
||||
-343.6542053222656,
|
||||
152.96629333496094,
|
||||
231.81927490234375
|
||||
]
|
||||
},
|
||||
{
|
||||
"children":[
|
||||
8
|
||||
],
|
||||
"mesh":4,
|
||||
"name":"TerrainPlane",
|
||||
"scale":[
|
||||
1.000100016593933,
|
||||
1,
|
||||
1
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"Main_Light_Path",
|
||||
"translation":[
|
||||
491.1999816894531,
|
||||
0,
|
||||
-66.48489379882812
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"PlayerSpawn",
|
||||
"translation":[
|
||||
-351.4849853515625,
|
||||
119.54279327392578,
|
||||
202.97006225585938
|
||||
]
|
||||
},
|
||||
{
|
||||
"extensions":{
|
||||
"KHR_lights_punctual":{
|
||||
"light":0
|
||||
}
|
||||
},
|
||||
"name":"Spot",
|
||||
"rotation":[
|
||||
-0.16434744000434875,
|
||||
-0.37808698415756226,
|
||||
0.006467622704803944,
|
||||
0.9110424518585205
|
||||
],
|
||||
"translation":[
|
||||
-344.301025390625,
|
||||
223.67401123046875,
|
||||
232.61265563964844
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"TestCharSpawn",
|
||||
"translation":[
|
||||
-381.1509704589844,
|
||||
106.53739166259766,
|
||||
107.46959686279297
|
||||
]
|
||||
},
|
||||
{
|
||||
"extensions":{
|
||||
"EXT_mesh_gpu_instancing":{
|
||||
"attributes":{
|
||||
"TRANSLATION":19,
|
||||
"ROTATION":20,
|
||||
"SCALE":21
|
||||
}
|
||||
}
|
||||
},
|
||||
"mesh":3,
|
||||
"name":"TerrainPlane.0"
|
||||
}
|
||||
],
|
||||
"materials":[
|
||||
{
|
||||
"doubleSided":true,
|
||||
"name":"terrain"
|
||||
}
|
||||
],
|
||||
"meshes":[
|
||||
{
|
||||
"name":"Cylinder",
|
||||
"primitives":[
|
||||
{
|
||||
"attributes":{
|
||||
"POSITION":0,
|
||||
"NORMAL":1,
|
||||
"TEXCOORD_0":2
|
||||
},
|
||||
"indices":3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"Cube",
|
||||
"primitives":[
|
||||
{
|
||||
"attributes":{
|
||||
"POSITION":4,
|
||||
"NORMAL":5,
|
||||
"TEXCOORD_0":6
|
||||
},
|
||||
"indices":7
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"Cylinder.001",
|
||||
"primitives":[
|
||||
{
|
||||
"attributes":{
|
||||
"POSITION":8,
|
||||
"NORMAL":9,
|
||||
"TEXCOORD_0":10
|
||||
},
|
||||
"indices":11
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"Cylinder",
|
||||
"primitives":[
|
||||
{
|
||||
"attributes":{
|
||||
"POSITION":12,
|
||||
"NORMAL":13,
|
||||
"TEXCOORD_0":14
|
||||
},
|
||||
"indices":3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"Plane.001",
|
||||
"primitives":[
|
||||
{
|
||||
"attributes":{
|
||||
"POSITION":15,
|
||||
"NORMAL":16,
|
||||
"TEXCOORD_0":17
|
||||
},
|
||||
"indices":18,
|
||||
"material":0
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"accessors":[
|
||||
{
|
||||
"bufferView":0,
|
||||
"componentType":5126,
|
||||
"count":1280,
|
||||
"max":[
|
||||
5.561562538146973,
|
||||
16.066009521484375,
|
||||
5.561562538146973
|
||||
],
|
||||
"min":[
|
||||
-5.561562538146973,
|
||||
0,
|
||||
-5.561562538146973
|
||||
],
|
||||
"type":"VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView":1,
|
||||
"componentType":5126,
|
||||
"count":1280,
|
||||
"type":"VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView":2,
|
||||
"componentType":5126,
|
||||
"count":1280,
|
||||
"type":"VEC2"
|
||||
},
|
||||
{
|
||||
"bufferView":3,
|
||||
"componentType":5123,
|
||||
"count":2100,
|
||||
"type":"SCALAR"
|
||||
},
|
||||
{
|
||||
"bufferView":4,
|
||||
"componentType":5126,
|
||||
"count":24,
|
||||
"max":[
|
||||
1,
|
||||
1,
|
||||
1
|
||||
],
|
||||
"min":[
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
],
|
||||
"type":"VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView":5,
|
||||
"componentType":5126,
|
||||
"count":24,
|
||||
"type":"VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView":6,
|
||||
"componentType":5126,
|
||||
"count":24,
|
||||
"type":"VEC2"
|
||||
},
|
||||
{
|
||||
"bufferView":7,
|
||||
"componentType":5123,
|
||||
"count":36,
|
||||
"type":"SCALAR"
|
||||
},
|
||||
{
|
||||
"bufferView":8,
|
||||
"componentType":5126,
|
||||
"count":704,
|
||||
"max":[
|
||||
6.253715991973877,
|
||||
2.2209415435791016,
|
||||
6.253798961639404
|
||||
],
|
||||
"min":[
|
||||
-6.253823757171631,
|
||||
-1.9492745399475098,
|
||||
-6.25374174118042
|
||||
],
|
||||
"type":"VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView":9,
|
||||
"componentType":5126,
|
||||
"count":704,
|
||||
"type":"VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView":10,
|
||||
"componentType":5126,
|
||||
"count":704,
|
||||
"type":"VEC2"
|
||||
},
|
||||
{
|
||||
"bufferView":11,
|
||||
"componentType":5123,
|
||||
"count":1140,
|
||||
"type":"SCALAR"
|
||||
},
|
||||
{
|
||||
"bufferView":12,
|
||||
"componentType":5126,
|
||||
"count":1280,
|
||||
"max":[
|
||||
5.561562538146973,
|
||||
16.066009521484375,
|
||||
5.561562538146973
|
||||
],
|
||||
"min":[
|
||||
-5.561562538146973,
|
||||
0,
|
||||
-5.561562538146973
|
||||
],
|
||||
"type":"VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView":13,
|
||||
"componentType":5126,
|
||||
"count":1280,
|
||||
"type":"VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView":14,
|
||||
"componentType":5126,
|
||||
"count":1280,
|
||||
"type":"VEC2"
|
||||
},
|
||||
{
|
||||
"bufferView":15,
|
||||
"componentType":5126,
|
||||
"count":10404,
|
||||
"max":[
|
||||
500,
|
||||
110.45686340332031,
|
||||
500
|
||||
],
|
||||
"min":[
|
||||
-500,
|
||||
-0.9473495483398438,
|
||||
-500
|
||||
],
|
||||
"type":"VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView":16,
|
||||
"componentType":5126,
|
||||
"count":10404,
|
||||
"type":"VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView":17,
|
||||
"componentType":5126,
|
||||
"count":10404,
|
||||
"type":"VEC2"
|
||||
},
|
||||
{
|
||||
"bufferView":18,
|
||||
"componentType":5123,
|
||||
"count":61206,
|
||||
"type":"SCALAR"
|
||||
},
|
||||
{
|
||||
"bufferView":19,
|
||||
"componentType":5126,
|
||||
"count":2380,
|
||||
"type":"VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView":20,
|
||||
"componentType":5126,
|
||||
"count":2380,
|
||||
"type":"VEC4"
|
||||
},
|
||||
{
|
||||
"bufferView":21,
|
||||
"componentType":5126,
|
||||
"count":2380,
|
||||
"type":"VEC3"
|
||||
}
|
||||
],
|
||||
"bufferViews":[
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":15360,
|
||||
"byteOffset":0,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":15360,
|
||||
"byteOffset":15360,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":10240,
|
||||
"byteOffset":30720,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":4200,
|
||||
"byteOffset":40960,
|
||||
"target":34963
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":288,
|
||||
"byteOffset":45160,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":288,
|
||||
"byteOffset":45448,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":192,
|
||||
"byteOffset":45736,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":72,
|
||||
"byteOffset":45928,
|
||||
"target":34963
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":8448,
|
||||
"byteOffset":46000,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":8448,
|
||||
"byteOffset":54448,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":5632,
|
||||
"byteOffset":62896,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":2280,
|
||||
"byteOffset":68528,
|
||||
"target":34963
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":15360,
|
||||
"byteOffset":70808,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":15360,
|
||||
"byteOffset":86168,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":10240,
|
||||
"byteOffset":101528,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":124848,
|
||||
"byteOffset":111768,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":124848,
|
||||
"byteOffset":236616,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":83232,
|
||||
"byteOffset":361464,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":122412,
|
||||
"byteOffset":444696,
|
||||
"target":34963
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":28560,
|
||||
"byteOffset":567108
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":38080,
|
||||
"byteOffset":595668
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":28560,
|
||||
"byteOffset":633748
|
||||
}
|
||||
],
|
||||
"buffers":[
|
||||
{
|
||||
"byteLength":662308,
|
||||
"uri":"terrain.bin"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
assets/meshes/test_char.bin
Normal file
195
assets/meshes/test_char.gltf
Normal file
@@ -0,0 +1,195 @@
|
||||
{
|
||||
"asset":{
|
||||
"generator":"Khronos glTF Blender I/O v5.0.21",
|
||||
"version":"2.0"
|
||||
},
|
||||
"scene":0,
|
||||
"scenes":[
|
||||
{
|
||||
"name":"Scene",
|
||||
"nodes":[
|
||||
0,
|
||||
1
|
||||
]
|
||||
}
|
||||
],
|
||||
"nodes":[
|
||||
{
|
||||
"mesh":0,
|
||||
"name":"Cylinder",
|
||||
"scale":[
|
||||
1,
|
||||
2.6253442764282227,
|
||||
1
|
||||
],
|
||||
"translation":[
|
||||
0,
|
||||
3.3726491928100586,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"mesh":1,
|
||||
"name":"Sphere",
|
||||
"translation":[
|
||||
0,
|
||||
7.17788553237915,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"meshes":[
|
||||
{
|
||||
"name":"Cylinder",
|
||||
"primitives":[
|
||||
{
|
||||
"attributes":{
|
||||
"POSITION":0,
|
||||
"NORMAL":1,
|
||||
"TEXCOORD_0":2
|
||||
},
|
||||
"indices":3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"Sphere",
|
||||
"primitives":[
|
||||
{
|
||||
"attributes":{
|
||||
"POSITION":4,
|
||||
"NORMAL":5,
|
||||
"TEXCOORD_0":6
|
||||
},
|
||||
"indices":7
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"accessors":[
|
||||
{
|
||||
"bufferView":0,
|
||||
"componentType":5126,
|
||||
"count":192,
|
||||
"max":[
|
||||
1.9433555603027344,
|
||||
1,
|
||||
1.9433555603027344
|
||||
],
|
||||
"min":[
|
||||
-1.9433555603027344,
|
||||
-1,
|
||||
-1.9433555603027344
|
||||
],
|
||||
"type":"VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView":1,
|
||||
"componentType":5126,
|
||||
"count":192,
|
||||
"type":"VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView":2,
|
||||
"componentType":5126,
|
||||
"count":192,
|
||||
"type":"VEC2"
|
||||
},
|
||||
{
|
||||
"bufferView":3,
|
||||
"componentType":5123,
|
||||
"count":372,
|
||||
"type":"SCALAR"
|
||||
},
|
||||
{
|
||||
"bufferView":4,
|
||||
"componentType":5126,
|
||||
"count":480,
|
||||
"max":[
|
||||
1,
|
||||
1,
|
||||
1
|
||||
],
|
||||
"min":[
|
||||
-0.9999999403953552,
|
||||
-1,
|
||||
-1
|
||||
],
|
||||
"type":"VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView":5,
|
||||
"componentType":5126,
|
||||
"count":480,
|
||||
"type":"VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView":6,
|
||||
"componentType":5126,
|
||||
"count":480,
|
||||
"type":"VEC2"
|
||||
},
|
||||
{
|
||||
"bufferView":7,
|
||||
"componentType":5123,
|
||||
"count":672,
|
||||
"type":"SCALAR"
|
||||
}
|
||||
],
|
||||
"bufferViews":[
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":2304,
|
||||
"byteOffset":0,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":2304,
|
||||
"byteOffset":2304,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":1536,
|
||||
"byteOffset":4608,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":744,
|
||||
"byteOffset":6144,
|
||||
"target":34963
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":5760,
|
||||
"byteOffset":6888,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":5760,
|
||||
"byteOffset":12648,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":3840,
|
||||
"byteOffset":18408,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":1344,
|
||||
"byteOffset":22248,
|
||||
"target":34963
|
||||
}
|
||||
],
|
||||
"buffers":[
|
||||
{
|
||||
"byteLength":23592,
|
||||
"uri":"test_char.bin"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
assets/textures/blue_noise.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
assets/textures/dither/octave_0.png
Normal file
|
After Width: | Height: | Size: 425 B |
BIN
assets/textures/dither/octave_1.png
Normal file
|
After Width: | Height: | Size: 751 B |
BIN
assets/textures/dither/octave_2.png
Normal file
|
After Width: | Height: | Size: 824 B |
BIN
assets/textures/dither/octave_3.png
Normal file
|
After Width: | Height: | Size: 425 B |
BIN
assets/textures/height_map_x0_y0.exr
Executable file
BIN
assets/textures/path_direction_debug.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
assets/textures/path_distance_debug.png
Normal file
|
After Width: | Height: | Size: 392 KiB |
BIN
assets/textures/path_hotspot_debug.exr
Normal file
BIN
assets/textures/path_hotspot_heatmap.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
assets/textures/path_segment_debug.png
Normal file
|
After Width: | Height: | Size: 184 KiB |
62
assets/textures/scripts/README.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# Texture Generation Scripts
|
||||
|
||||
## Blue Noise Generator
|
||||
|
||||
`generate_blue_noise.py` - Generates blue noise textures for high-quality dithering effects.
|
||||
|
||||
### Requirements
|
||||
|
||||
```bash
|
||||
pip install numpy pillow scipy
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
Basic usage (generates 128x128 texture):
|
||||
```bash
|
||||
python generate_blue_noise.py
|
||||
```
|
||||
|
||||
Custom size:
|
||||
```bash
|
||||
python generate_blue_noise.py --width 256 --height 256
|
||||
```
|
||||
|
||||
Custom output path:
|
||||
```bash
|
||||
python generate_blue_noise.py --output ../my_blue_noise.png
|
||||
```
|
||||
|
||||
Advanced options:
|
||||
```bash
|
||||
python generate_blue_noise.py --width 128 --height 128 --sigma 1.5 --method void_cluster
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
- `--width`: Texture width in pixels (default: 128)
|
||||
- `--height`: Texture height in pixels (default: 128)
|
||||
- `--method`: Generation method
|
||||
- `void_cluster`: High-quality void-and-cluster method (default, recommended)
|
||||
- `annealing`: Simulated annealing method (slower)
|
||||
- `--sigma`: Gaussian kernel sigma for void_cluster method (default: 1.5)
|
||||
- Lower values (0.8-1.2): Tighter clustering, more high-frequency
|
||||
- Higher values (2.0-3.0): Smoother distribution
|
||||
- `--iterations`: Number of iterations (optional, auto-calculated if not specified)
|
||||
- `--output`: Output file path (default: ../blue_noise.png)
|
||||
|
||||
### What is Blue Noise?
|
||||
|
||||
Blue noise is a type of noise with energy concentrated in high frequencies and minimal low-frequency content. This makes it ideal for dithering because:
|
||||
|
||||
- No visible patterns or clustering
|
||||
- Smooth gradients without banding
|
||||
- Perceptually pleasing distribution
|
||||
- Better than Bayer or white noise for transparency effects
|
||||
|
||||
### Use Cases in snow_trail_sdl
|
||||
|
||||
- **Tree dissolve effect**: Dither trees between camera and player for unobstructed view
|
||||
- **Temporal effects**: Screen-space dithering for transitions
|
||||
- **Transparency**: High-quality alpha dithering
|
||||
- **LOD transitions**: Smooth fade between detail levels
|
||||
155
assets/textures/scripts/generate_blue_noise.py
Executable file
@@ -0,0 +1,155 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
|
||||
def gaussian_kernel(size, sigma):
|
||||
x = np.arange(-size // 2 + 1, size // 2 + 1)
|
||||
y = np.arange(-size // 2 + 1, size // 2 + 1)
|
||||
xx, yy = np.meshgrid(x, y)
|
||||
kernel = np.exp(-(xx**2 + yy**2) / (2 * sigma**2))
|
||||
return kernel / kernel.sum()
|
||||
|
||||
def apply_periodic_filter(binary_pattern, kernel):
|
||||
from scipy.signal import fftconvolve
|
||||
return fftconvolve(binary_pattern, kernel, mode='same')
|
||||
|
||||
def generate_blue_noise_void_cluster(width, height, sigma=1.5, iterations=None):
|
||||
if iterations is None:
|
||||
iterations = width * height
|
||||
|
||||
size = width * height
|
||||
pattern = np.zeros((height, width), dtype=np.float32)
|
||||
|
||||
kernel_size = int(6 * sigma)
|
||||
if kernel_size % 2 == 0:
|
||||
kernel_size += 1
|
||||
kernel = gaussian_kernel(kernel_size, sigma)
|
||||
|
||||
initial_pattern = np.random.rand(height, width)
|
||||
|
||||
print(f"Generating {width}x{height} blue noise texture...")
|
||||
print(f"Kernel size: {kernel_size}x{kernel_size}, sigma: {sigma}")
|
||||
|
||||
dither_array = np.zeros(size, dtype=np.int32)
|
||||
binary_pattern = np.zeros((height, width), dtype=np.float32)
|
||||
|
||||
for i in range(size):
|
||||
if i % (size // 10) == 0:
|
||||
print(f"Progress: {i}/{size} ({100*i//size}%)")
|
||||
|
||||
filtered = apply_periodic_filter(binary_pattern, kernel)
|
||||
|
||||
if i < size // 2:
|
||||
initial_energy = initial_pattern + filtered
|
||||
coords = np.unravel_index(np.argmax(initial_energy), initial_energy.shape)
|
||||
else:
|
||||
coords = np.unravel_index(np.argmin(filtered), filtered.shape)
|
||||
|
||||
dither_array[i] = coords[0] * width + coords[1]
|
||||
binary_pattern[coords[0], coords[1]] = 1.0
|
||||
|
||||
print("Converting to threshold map...")
|
||||
|
||||
threshold_map = np.zeros((height, width), dtype=np.float32)
|
||||
for rank, pos in enumerate(dither_array):
|
||||
y = pos // width
|
||||
x = pos % width
|
||||
threshold_map[y, x] = rank / size
|
||||
|
||||
print("Done!")
|
||||
return threshold_map
|
||||
|
||||
def generate_blue_noise_simulated_annealing(width, height, iterations=10000):
|
||||
print(f"Generating {width}x{height} blue noise using simulated annealing...")
|
||||
|
||||
pattern = np.random.rand(height, width)
|
||||
|
||||
def energy(pattern):
|
||||
fft = np.fft.fft2(pattern)
|
||||
power = np.abs(fft) ** 2
|
||||
|
||||
h, w = pattern.shape
|
||||
cy, cx = h // 2, w // 2
|
||||
y, x = np.ogrid[:h, :w]
|
||||
dist = np.sqrt((x - cx)**2 + (y - cy)**2)
|
||||
|
||||
low_freq_mask = dist < min(h, w) * 0.1
|
||||
low_freq_energy = np.sum(power * low_freq_mask)
|
||||
|
||||
return low_freq_energy
|
||||
|
||||
current_energy = energy(pattern)
|
||||
temperature = 1.0
|
||||
cooling_rate = 0.9995
|
||||
|
||||
for i in range(iterations):
|
||||
if i % (iterations // 10) == 0:
|
||||
print(f"Iteration {i}/{iterations}, Energy: {current_energy:.2f}, Temp: {temperature:.4f}")
|
||||
|
||||
y1, x1 = np.random.randint(0, height), np.random.randint(0, width)
|
||||
y2, x2 = np.random.randint(0, height), np.random.randint(0, width)
|
||||
|
||||
pattern[y1, x1], pattern[y2, x2] = pattern[y2, x2], pattern[y1, x1]
|
||||
|
||||
new_energy = energy(pattern)
|
||||
delta_energy = new_energy - current_energy
|
||||
|
||||
if delta_energy < 0 or np.random.rand() < np.exp(-delta_energy / temperature):
|
||||
current_energy = new_energy
|
||||
else:
|
||||
pattern[y1, x1], pattern[y2, x2] = pattern[y2, x2], pattern[y1, x1]
|
||||
|
||||
temperature *= cooling_rate
|
||||
|
||||
print("Done!")
|
||||
return pattern
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Generate blue noise texture for dithering')
|
||||
parser.add_argument('--width', type=int, default=128, help='Texture width (default: 128)')
|
||||
parser.add_argument('--height', type=int, default=128, help='Texture height (default: 128)')
|
||||
parser.add_argument('--method', choices=['void_cluster', 'annealing'], default='void_cluster',
|
||||
help='Generation method (default: void_cluster)')
|
||||
parser.add_argument('--sigma', type=float, default=1.5,
|
||||
help='Gaussian kernel sigma for void_cluster method (default: 1.5)')
|
||||
parser.add_argument('--iterations', type=int, default=None,
|
||||
help='Number of iterations (optional)')
|
||||
parser.add_argument('--output', type=str, default='../blue_noise.png',
|
||||
help='Output file path (default: ../blue_noise.png)')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
from scipy.signal import fftconvolve
|
||||
except ImportError:
|
||||
print("Error: scipy is required for this script.")
|
||||
print("Install it with: pip install scipy")
|
||||
return
|
||||
|
||||
if args.method == 'void_cluster':
|
||||
noise = generate_blue_noise_void_cluster(args.width, args.height, args.sigma, args.iterations)
|
||||
else:
|
||||
noise = generate_blue_noise_simulated_annealing(args.width, args.height,
|
||||
args.iterations or 10000)
|
||||
|
||||
noise_normalized = ((noise - noise.min()) / (noise.max() - noise.min()) * 255).astype(np.uint8)
|
||||
|
||||
img = Image.fromarray(noise_normalized, mode='L')
|
||||
|
||||
output_path = Path(__file__).parent / args.output
|
||||
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
img.save(output_path)
|
||||
|
||||
print(f"\nBlue noise texture saved to: {output_path}")
|
||||
print(f"Size: {args.width}x{args.height}")
|
||||
print(f"Method: {args.method}")
|
||||
|
||||
fft = np.fft.fft2(noise)
|
||||
power_spectrum = np.abs(np.fft.fftshift(fft)) ** 2
|
||||
print(f"Power spectrum range: {power_spectrum.min():.2e} - {power_spectrum.max():.2e}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
BIN
assets/textures/snow_depth.exr
Normal file
BIN
assets/textures/terrain.exr
Normal file
BIN
assets/textures/terrain_flowmap.exr
Normal file
BIN
assets/textures/terrain_flowmap.png
Normal file
|
After Width: | Height: | Size: 2.6 MiB |
BIN
assets/textures/terrain_heightmap.exr
Normal file
BIN
assets/textures/terrain_normals.png
Normal file
|
After Width: | Height: | Size: 910 KiB |