├── CascadeVisualDemo ├── objects │ ├── Obj_SampleObject │ │ ├── CleanUp_0.gml │ │ ├── Draw_76.gml │ │ ├── Create_0.gml │ │ ├── Step_0.gml │ │ ├── Obj_SampleObject.yy │ │ └── Draw_0.gml │ ├── Obj_SampleObjectDF │ │ ├── CleanUp_0.gml │ │ ├── Draw_76.gml │ │ ├── Create_0.gml │ │ ├── Obj_SampleObjectDF.yy │ │ ├── Step_0.gml │ │ └── Draw_0.gml │ ├── Obj_SampleScaling │ │ ├── Create_0.gml │ │ ├── Draw_0.gml │ │ └── Obj_SampleScaling.yy │ └── Obj_MergingSample │ │ ├── Create_0.gml │ │ ├── Obj_MergingSample.yy │ │ └── Draw_0.gml ├── fonts │ └── Fnt_Sample │ │ ├── Fnt_Sample.png │ │ └── Fnt_Sample.old.png ├── sprites │ └── Spr_SampleSprite │ │ ├── cbc5e4e8-1c87-4982-96e7-3c6679507561.png │ │ ├── layers │ │ └── cbc5e4e8-1c87-4982-96e7-3c6679507561 │ │ │ └── a20214be-ef8a-4271-9147-a5321ec81a9f.png │ │ └── Spr_SampleSprite.yy ├── shaders │ ├── Shd_Bilinear │ │ ├── Shd_Bilinear.yy │ │ ├── Shd_Bilinear.fsh │ │ └── Shd_Bilinear.vsh │ ├── Shd_CascadeVisual │ │ ├── Shd_CascadeVisual.yy │ │ ├── Shd_CascadeVisual.fsh │ │ └── Shd_CascadeVisual.vsh │ └── Shd_CascadeVisualDF │ │ ├── Shd_CascadeVisualDF.yy │ │ ├── Shd_CascadeVisualDF.fsh │ │ └── Shd_CascadeVisualDF.vsh ├── options │ ├── main │ │ └── options_main.yy │ ├── linux │ │ └── options_linux.yy │ ├── operagx │ │ └── options_operagx.yy │ ├── html5 │ │ └── options_html5.yy │ ├── mac │ │ └── options_mac.yy │ ├── tvos │ │ └── options_tvos.yy │ ├── windows │ │ └── options_windows.yy │ ├── ios │ │ └── options_ios.yy │ └── android │ │ └── options_android.yy ├── CascadeVisualDemo.resource_order ├── rooms │ └── Rm_SampleRoom │ │ └── Rm_SampleRoom.yy └── CascadeVisualDemo.yyp ├── RadianceCascades-Optimized ├── objects │ ├── Obj_RadianceCascades │ │ ├── Draw_76.gml │ │ ├── CleanUp_0.gml │ │ ├── Draw_72.gml │ │ ├── Step_0.gml │ │ ├── Obj_RadianceCascades.yy │ │ ├── Draw_73.gml │ │ └── Create_0.gml │ └── Obj_LineTesting │ │ ├── Create_0.gml │ │ ├── Step_0.gml │ │ ├── Obj_LineTesting.yy │ │ └── Draw_0.gml ├── sprites │ └── Spr_SampleScene │ │ ├── ca0f74e2-644d-4591-9d29-ab644ad1d0ff.png │ │ ├── layers │ │ └── ca0f74e2-644d-4591-9d29-ab644ad1d0ff │ │ │ └── 13980e7e-ad5c-4e05-801b-189a5701c616.png │ │ └── Spr_SampleScene.yy ├── shaders │ ├── Shd_JumpFlood │ │ ├── Shd_JumpFlood.yy │ │ ├── Shd_JumpFlood.vsh │ │ └── Shd_JumpFlood.fsh │ ├── Shd_DistanceField │ │ ├── Shd_DistanceField.yy │ │ ├── Shd_DistanceField.vsh │ │ └── Shd_DistanceField.fsh │ ├── Shd_SeedJumpFlood │ │ ├── Shd_SeedJumpFlood.yy │ │ ├── Shd_SeedJumpFlood.fsh │ │ └── Shd_SeedJumpFlood.vsh │ ├── Shd_RadianceCascades │ │ ├── Shd_RadianceCascades.yy │ │ └── Shd_RadianceCascades.vsh │ ├── Shd_RadianceCascades_Final │ │ ├── Shd_RadianceCascades_Final.yy │ │ ├── Shd_RadianceCascades_Final.vsh │ │ └── Shd_RadianceCascades_Final.fsh │ ├── Shd_RadianceCascades_FPFixed │ │ ├── Shd_RadianceCascades_FPFixed.yy │ │ ├── Shd_RadianceCascades_FPFixed.vsh │ │ └── Shd_RadianceCascades_FPFixed.fsh │ ├── Shd_RadianceCascades_NearestFix │ │ ├── Shd_RadianceCascades_NearestFix.yy │ │ ├── Shd_RadianceCascades_NearestFix.vsh │ │ └── Shd_RadianceCascades_NearestFix.fsh │ ├── Shd_RadianceCascades_BilinearFix │ │ ├── Shd_RadianceCascades_BilinearFix.yy │ │ ├── Shd_RadianceCascades_BilinearFix.vsh │ │ └── Shd_RadianceCascades_BilinearFix.fsh │ └── Shd_RadianceCascades_InterlacedFix │ │ ├── Shd_RadianceCascades_InterlacedFix.yy │ │ ├── Shd_RadianceCascades_InterlacedFix.vsh │ │ └── Shd_RadianceCascades_InterlacedFix.fsh ├── scripts │ └── Scr_HelperFunctions │ │ ├── Scr_HelperFunctions.yy │ │ └── Scr_HelperFunctions.gml ├── options │ ├── main │ │ └── options_main.yy │ ├── linux │ │ └── options_linux.yy │ ├── operagx │ │ └── options_operagx.yy │ ├── html5 │ │ └── options_html5.yy │ ├── mac │ │ └── options_mac.yy │ ├── tvos │ │ └── options_tvos.yy │ ├── windows │ │ └── options_windows.yy │ ├── ios │ │ └── options_ios.yy │ └── android │ │ └── options_android.yy ├── RadianceCascades-Optimized.resource_order ├── rooms │ └── Rm_TestRoom │ │ └── Rm_TestRoom.yy └── RadianceCascades-Optimized.yyp ├── RadianceCascades ├── sprites │ ├── Spr_SampleScene │ │ ├── b3ab27c2-5f95-4653-bf0c-4379701177f5.png │ │ ├── layers │ │ │ └── b3ab27c2-5f95-4653-bf0c-4379701177f5 │ │ │ │ └── 0d7662ca-3478-4bf6-a097-69be1c00c353.png │ │ └── Spr_SampleScene.yy │ └── Spr_VisualizeRadianceIntervals │ │ ├── f8390388-9411-4b3b-a96e-6101133fe64f.png │ │ ├── layers │ │ └── f8390388-9411-4b3b-a96e-6101133fe64f │ │ │ └── a2fde448-e5ce-4944-b09d-cff5f9b505fc.png │ │ └── Spr_VisualizeRadianceIntervals.yy ├── shaders │ ├── Shd_DistanceField │ │ ├── Shd_DistanceField.yy │ │ ├── Shd_DistanceField.vsh │ │ └── Shd_DistanceField.fsh │ ├── Shd_JumpfloodSeed │ │ ├── Shd_JumpfloodSeed.yy │ │ ├── Shd_JumpfloodSeed.vsh │ │ └── Shd_JumpfloodSeed.fsh │ ├── Shd_RadianceMipMap │ │ ├── Shd_RadianceMipMap.yy │ │ ├── Shd_RadianceMipMap.vsh │ │ └── Shd_RadianceMipMap.fsh │ ├── Shd_RadianceMerging │ │ ├── Shd_RadianceMerging.yy │ │ ├── Shd_RadianceMerging.vsh │ │ └── Shd_RadianceMerging.fsh │ ├── Shd_RadianceIntervals │ │ ├── Shd_RadianceIntervals.yy │ │ ├── Shd_RadianceIntervals.vsh │ │ └── Shd_RadianceIntervals.fsh │ └── Shd_JumpfloodAlgorithm │ │ ├── Shd_JumpfloodAlgorithm.yy │ │ ├── Shd_JumpfloodAlgorithm.vsh │ │ └── Shd_JumpfloodAlgorithm.fsh ├── scripts │ └── Scr_RadianceCascades │ │ └── Scr_RadianceCascades.yy ├── objects │ └── Obj_RadianceCascades │ │ ├── Draw_72.gml │ │ ├── Step_2.gml │ │ ├── CleanUp_0.gml │ │ ├── Obj_RadianceCascades.yy │ │ ├── Draw_76.gml │ │ ├── Draw_73.gml │ │ └── Create_0.gml ├── options │ ├── main │ │ └── options_main.yy │ ├── linux │ │ └── options_linux.yy │ ├── operagx │ │ └── options_operagx.yy │ ├── html5 │ │ └── options_html5.yy │ ├── mac │ │ └── options_mac.yy │ ├── tvos │ │ └── options_tvos.yy │ ├── windows │ │ └── options_windows.yy │ ├── ios │ │ └── options_ios.yy │ └── android │ │ └── options_android.yy ├── RadianceCascades.resource_order ├── RadianceCascades.yyp └── rooms │ └── Rm_SampleScene │ └── Rm_SampleScene.yy ├── LICENSE └── README.md /CascadeVisualDemo/objects/Obj_SampleObject/CleanUp_0.gml: -------------------------------------------------------------------------------- 1 | if (!surface_exists(render_surface)) 2 | surface_free(render_surface); -------------------------------------------------------------------------------- /CascadeVisualDemo/objects/Obj_SampleObjectDF/CleanUp_0.gml: -------------------------------------------------------------------------------- 1 | if (!surface_exists(render_surface)) 2 | surface_free(render_surface); -------------------------------------------------------------------------------- /CascadeVisualDemo/objects/Obj_SampleScaling/Create_0.gml: -------------------------------------------------------------------------------- 1 | offset = room_width * 0.25; 2 | width = room_width - (offset * 2); 3 | height = 32; 4 | 5 | sectors = 1; -------------------------------------------------------------------------------- /CascadeVisualDemo/fonts/Fnt_Sample/Fnt_Sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yaazarai/GMShaders-Radiance-Cascades/HEAD/CascadeVisualDemo/fonts/Fnt_Sample/Fnt_Sample.png -------------------------------------------------------------------------------- /CascadeVisualDemo/fonts/Fnt_Sample/Fnt_Sample.old.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yaazarai/GMShaders-Radiance-Cascades/HEAD/CascadeVisualDemo/fonts/Fnt_Sample/Fnt_Sample.old.png -------------------------------------------------------------------------------- /RadianceCascades-Optimized/objects/Obj_RadianceCascades/Draw_76.gml: -------------------------------------------------------------------------------- 1 | for(var i = 0; i < ds_list_size(radiance_renderlist); i++) 2 | surface_rebuild(ds_list_find_value(radiance_renderlist, i)); -------------------------------------------------------------------------------- /CascadeVisualDemo/sprites/Spr_SampleSprite/cbc5e4e8-1c87-4982-96e7-3c6679507561.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yaazarai/GMShaders-Radiance-Cascades/HEAD/CascadeVisualDemo/sprites/Spr_SampleSprite/cbc5e4e8-1c87-4982-96e7-3c6679507561.png -------------------------------------------------------------------------------- /RadianceCascades/sprites/Spr_SampleScene/b3ab27c2-5f95-4653-bf0c-4379701177f5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yaazarai/GMShaders-Radiance-Cascades/HEAD/RadianceCascades/sprites/Spr_SampleScene/b3ab27c2-5f95-4653-bf0c-4379701177f5.png -------------------------------------------------------------------------------- /RadianceCascades-Optimized/objects/Obj_RadianceCascades/CleanUp_0.gml: -------------------------------------------------------------------------------- 1 | for(var i = 0; i < ds_list_size(radiance_renderlist); i++) 2 | surface_delete(ds_list_find_value(radiance_renderlist, i)); 3 | 4 | ds_list_destroy(radiance_renderlist); -------------------------------------------------------------------------------- /RadianceCascades-Optimized/sprites/Spr_SampleScene/ca0f74e2-644d-4591-9d29-ab644ad1d0ff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yaazarai/GMShaders-Radiance-Cascades/HEAD/RadianceCascades-Optimized/sprites/Spr_SampleScene/ca0f74e2-644d-4591-9d29-ab644ad1d0ff.png -------------------------------------------------------------------------------- /RadianceCascades/sprites/Spr_VisualizeRadianceIntervals/f8390388-9411-4b3b-a96e-6101133fe64f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yaazarai/GMShaders-Radiance-Cascades/HEAD/RadianceCascades/sprites/Spr_VisualizeRadianceIntervals/f8390388-9411-4b3b-a96e-6101133fe64f.png -------------------------------------------------------------------------------- /RadianceCascades/shaders/Shd_DistanceField/Shd_DistanceField.yy: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "GMShader", 3 | "resourceVersion": "1.0", 4 | "name": "Shd_DistanceField", 5 | "parent": { 6 | "name": "Shaders", 7 | "path": "folders/Shaders.yy", 8 | }, 9 | "type": 1, 10 | } -------------------------------------------------------------------------------- /RadianceCascades/shaders/Shd_JumpfloodSeed/Shd_JumpfloodSeed.yy: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "GMShader", 3 | "resourceVersion": "1.0", 4 | "name": "Shd_JumpfloodSeed", 5 | "parent": { 6 | "name": "Shaders", 7 | "path": "folders/Shaders.yy", 8 | }, 9 | "type": 1, 10 | } -------------------------------------------------------------------------------- /RadianceCascades/shaders/Shd_RadianceMipMap/Shd_RadianceMipMap.yy: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "GMShader", 3 | "resourceVersion": "1.0", 4 | "name": "Shd_RadianceMipMap", 5 | "parent": { 6 | "name": "Shaders", 7 | "path": "folders/Shaders.yy", 8 | }, 9 | "type": 1, 10 | } -------------------------------------------------------------------------------- /RadianceCascades/shaders/Shd_RadianceMerging/Shd_RadianceMerging.yy: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "GMShader", 3 | "resourceVersion": "1.0", 4 | "name": "Shd_RadianceMerging", 5 | "parent": { 6 | "name": "Shaders", 7 | "path": "folders/Shaders.yy", 8 | }, 9 | "type": 1, 10 | } -------------------------------------------------------------------------------- /RadianceCascades/shaders/Shd_RadianceIntervals/Shd_RadianceIntervals.yy: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "GMShader", 3 | "resourceVersion": "1.0", 4 | "name": "Shd_RadianceIntervals", 5 | "parent": { 6 | "name": "Shaders", 7 | "path": "folders/Shaders.yy", 8 | }, 9 | "type": 1, 10 | } -------------------------------------------------------------------------------- /RadianceCascades/shaders/Shd_JumpfloodAlgorithm/Shd_JumpfloodAlgorithm.yy: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "GMShader", 3 | "resourceVersion": "1.0", 4 | "name": "Shd_JumpfloodAlgorithm", 5 | "parent": { 6 | "name": "Shaders", 7 | "path": "folders/Shaders.yy", 8 | }, 9 | "type": 1, 10 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/shaders/Shd_Bilinear/Shd_Bilinear.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMShader":"", 3 | "%Name":"Shd_Bilinear", 4 | "name":"Shd_Bilinear", 5 | "parent":{ 6 | "name":"Shaders", 7 | "path":"folders/Shaders.yy", 8 | }, 9 | "resourceType":"GMShader", 10 | "resourceVersion":"2.0", 11 | "type":1, 12 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/objects/Obj_RadianceCascades/Draw_72.gml: -------------------------------------------------------------------------------- 1 | surface_set_target(radiance_world.memory); 2 | draw_clear_alpha(c_black, 0); 3 | draw_sprite(Spr_SampleScene, 0, 0, 0); 4 | draw_set_color($00000000); 5 | draw_circle(mouse_x, mouse_y, 128, false); 6 | draw_set_color(c_white); 7 | surface_reset_target(); -------------------------------------------------------------------------------- /RadianceCascades/shaders/Shd_DistanceField/Shd_DistanceField.vsh: -------------------------------------------------------------------------------- 1 | attribute vec3 in_Position; 2 | attribute vec2 in_TextureCoord; 3 | varying vec2 in_TextCoord; 4 | 5 | void main() { 6 | gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4(in_Position, 1.0); 7 | in_TextCoord = in_TextureCoord; 8 | } -------------------------------------------------------------------------------- /RadianceCascades/shaders/Shd_JumpfloodSeed/Shd_JumpfloodSeed.vsh: -------------------------------------------------------------------------------- 1 | attribute vec3 in_Position; 2 | attribute vec2 in_TextureCoord; 3 | varying vec2 in_TextCoord; 4 | 5 | void main() { 6 | gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4(in_Position, 1.0); 7 | in_TextCoord = in_TextureCoord; 8 | } -------------------------------------------------------------------------------- /RadianceCascades/shaders/Shd_RadianceMerging/Shd_RadianceMerging.vsh: -------------------------------------------------------------------------------- 1 | attribute vec3 in_Position; 2 | attribute vec2 in_TextureCoord; 3 | varying vec2 in_TextCoord; 4 | 5 | void main() { 6 | gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4(in_Position, 1.0); 7 | in_TextCoord = in_TextureCoord; 8 | } -------------------------------------------------------------------------------- /RadianceCascades/shaders/Shd_RadianceMipMap/Shd_RadianceMipMap.vsh: -------------------------------------------------------------------------------- 1 | attribute vec3 in_Position; 2 | attribute vec2 in_TextureCoord; 3 | varying vec2 in_TextCoord; 4 | 5 | void main() { 6 | gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4(in_Position, 1.0); 7 | in_TextCoord = in_TextureCoord; 8 | } -------------------------------------------------------------------------------- /RadianceCascades/sprites/Spr_SampleScene/layers/b3ab27c2-5f95-4653-bf0c-4379701177f5/0d7662ca-3478-4bf6-a097-69be1c00c353.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yaazarai/GMShaders-Radiance-Cascades/HEAD/RadianceCascades/sprites/Spr_SampleScene/layers/b3ab27c2-5f95-4653-bf0c-4379701177f5/0d7662ca-3478-4bf6-a097-69be1c00c353.png -------------------------------------------------------------------------------- /CascadeVisualDemo/sprites/Spr_SampleSprite/layers/cbc5e4e8-1c87-4982-96e7-3c6679507561/a20214be-ef8a-4271-9147-a5321ec81a9f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yaazarai/GMShaders-Radiance-Cascades/HEAD/CascadeVisualDemo/sprites/Spr_SampleSprite/layers/cbc5e4e8-1c87-4982-96e7-3c6679507561/a20214be-ef8a-4271-9147-a5321ec81a9f.png -------------------------------------------------------------------------------- /RadianceCascades/shaders/Shd_RadianceIntervals/Shd_RadianceIntervals.vsh: -------------------------------------------------------------------------------- 1 | attribute vec3 in_Position; 2 | attribute vec2 in_TextureCoord; 3 | varying vec2 in_TextCoord; 4 | 5 | void main() { 6 | gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4(in_Position, 1.0); 7 | in_TextCoord = in_TextureCoord; 8 | } -------------------------------------------------------------------------------- /RadianceCascades/shaders/Shd_JumpfloodAlgorithm/Shd_JumpfloodAlgorithm.vsh: -------------------------------------------------------------------------------- 1 | attribute vec3 in_Position; 2 | attribute vec2 in_TextureCoord; 3 | varying vec2 in_TextCoord; 4 | 5 | void main() { 6 | gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4(in_Position, 1.0); 7 | in_TextCoord = in_TextureCoord; 8 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_JumpFlood/Shd_JumpFlood.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMShader":"", 3 | "%Name":"Shd_JumpFlood", 4 | "name":"Shd_JumpFlood", 5 | "parent":{ 6 | "name":"Shaders", 7 | "path":"folders/Shaders.yy", 8 | }, 9 | "resourceType":"GMShader", 10 | "resourceVersion":"2.0", 11 | "type":1, 12 | } -------------------------------------------------------------------------------- /RadianceCascades/scripts/Scr_RadianceCascades/Scr_RadianceCascades.yy: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "GMScript", 3 | "resourceVersion": "1.0", 4 | "name": "Scr_RadianceCascades", 5 | "isCompatibility": false, 6 | "isDnD": false, 7 | "parent": { 8 | "name": "Scripts", 9 | "path": "folders/Scripts.yy", 10 | }, 11 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/shaders/Shd_CascadeVisual/Shd_CascadeVisual.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMShader":"", 3 | "%Name":"Shd_CascadeVisual", 4 | "name":"Shd_CascadeVisual", 5 | "parent":{ 6 | "name":"Shaders", 7 | "path":"folders/Shaders.yy", 8 | }, 9 | "resourceType":"GMShader", 10 | "resourceVersion":"2.0", 11 | "type":1, 12 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/sprites/Spr_SampleScene/layers/ca0f74e2-644d-4591-9d29-ab644ad1d0ff/13980e7e-ad5c-4e05-801b-189a5701c616.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yaazarai/GMShaders-Radiance-Cascades/HEAD/RadianceCascades-Optimized/sprites/Spr_SampleScene/layers/ca0f74e2-644d-4591-9d29-ab644ad1d0ff/13980e7e-ad5c-4e05-801b-189a5701c616.png -------------------------------------------------------------------------------- /RadianceCascades/objects/Obj_RadianceCascades/Draw_72.gml: -------------------------------------------------------------------------------- 1 | surface_set_target(gameworld_worldscene); 2 | draw_clear_alpha(c_black, 0); 3 | 4 | draw_set_color($F0F066); 5 | draw_circle(mouse_x, mouse_y, 8, false); 6 | draw_set_color(c_white); 7 | 8 | draw_sprite_ext(Spr_SampleScene, 0, 0, 0, 1, 1, 0, c_white, 1.0); 9 | surface_reset_target(); -------------------------------------------------------------------------------- /CascadeVisualDemo/objects/Obj_SampleObject/Draw_76.gml: -------------------------------------------------------------------------------- 1 | if (!surface_exists(render_surface)) { 2 | render_surface = surface_create(cascade_size, cascade_size); 3 | } else { 4 | if (surface_get_width(render_surface) != cascade_size) { 5 | surface_free(render_surface); 6 | render_surface = surface_create(cascade_size, cascade_size); 7 | } 8 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/objects/Obj_SampleObjectDF/Draw_76.gml: -------------------------------------------------------------------------------- 1 | if (!surface_exists(render_surface)) { 2 | render_surface = surface_create(cascade_size, cascade_size); 3 | } else { 4 | if (surface_get_width(render_surface) != cascade_size) { 5 | surface_free(render_surface); 6 | render_surface = surface_create(cascade_size, cascade_size); 7 | } 8 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/shaders/Shd_CascadeVisualDF/Shd_CascadeVisualDF.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMShader":"", 3 | "%Name":"Shd_CascadeVisualDF", 4 | "name":"Shd_CascadeVisualDF", 5 | "parent":{ 6 | "name":"Shaders", 7 | "path":"folders/Shaders.yy", 8 | }, 9 | "resourceType":"GMShader", 10 | "resourceVersion":"2.0", 11 | "type":1, 12 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_DistanceField/Shd_DistanceField.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMShader":"", 3 | "%Name":"Shd_DistanceField", 4 | "name":"Shd_DistanceField", 5 | "parent":{ 6 | "name":"Shaders", 7 | "path":"folders/Shaders.yy", 8 | }, 9 | "resourceType":"GMShader", 10 | "resourceVersion":"2.0", 11 | "type":1, 12 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_SeedJumpFlood/Shd_SeedJumpFlood.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMShader":"", 3 | "%Name":"Shd_SeedJumpFlood", 4 | "name":"Shd_SeedJumpFlood", 5 | "parent":{ 6 | "name":"Shaders", 7 | "path":"folders/Shaders.yy", 8 | }, 9 | "resourceType":"GMShader", 10 | "resourceVersion":"2.0", 11 | "type":1, 12 | } -------------------------------------------------------------------------------- /RadianceCascades/sprites/Spr_VisualizeRadianceIntervals/layers/f8390388-9411-4b3b-a96e-6101133fe64f/a2fde448-e5ce-4944-b09d-cff5f9b505fc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yaazarai/GMShaders-Radiance-Cascades/HEAD/RadianceCascades/sprites/Spr_VisualizeRadianceIntervals/layers/f8390388-9411-4b3b-a96e-6101133fe64f/a2fde448-e5ce-4944-b09d-cff5f9b505fc.png -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_RadianceCascades/Shd_RadianceCascades.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMShader":"", 3 | "%Name":"Shd_RadianceCascades", 4 | "name":"Shd_RadianceCascades", 5 | "parent":{ 6 | "name":"Shaders", 7 | "path":"folders/Shaders.yy", 8 | }, 9 | "resourceType":"GMShader", 10 | "resourceVersion":"2.0", 11 | "type":1, 12 | } -------------------------------------------------------------------------------- /RadianceCascades/shaders/Shd_JumpfloodSeed/Shd_JumpfloodSeed.fsh: -------------------------------------------------------------------------------- 1 | varying vec2 in_TextCoord; 2 | 3 | #define F16V2(f) vec2(floor(f * 255.0) * float(0.0039215689), fract(f * 255.0)) 4 | 5 | void main() { 6 | vec4 scene = texture2D(gm_BaseTexture, in_TextCoord); 7 | gl_FragColor = vec4(F16V2(in_TextCoord.x * scene.a), F16V2(in_TextCoord.y * scene.a)); 8 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_SeedJumpFlood/Shd_SeedJumpFlood.fsh: -------------------------------------------------------------------------------- 1 | varying vec2 in_TexelCoord; 2 | 3 | #define F16V2(f) vec2(floor(f * 255.0) * float(0.0039215689), fract(f * 255.0)) 4 | 5 | void main() { 6 | vec4 scene = texture2D(gm_BaseTexture, in_TexelCoord); 7 | gl_FragColor = vec4(F16V2(in_TexelCoord.x * scene.a), F16V2(in_TexelCoord.y * scene.a)); 8 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_RadianceCascades_Final/Shd_RadianceCascades_Final.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMShader":"", 3 | "%Name":"Shd_RadianceCascades_Final", 4 | "name":"Shd_RadianceCascades_Final", 5 | "parent":{ 6 | "name":"Shaders", 7 | "path":"folders/Shaders.yy", 8 | }, 9 | "resourceType":"GMShader", 10 | "resourceVersion":"2.0", 11 | "type":1, 12 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/scripts/Scr_HelperFunctions/Scr_HelperFunctions.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMScript":"", 3 | "%Name":"Scr_HelperFunctions", 4 | "isCompatibility":false, 5 | "isDnD":false, 6 | "name":"Scr_HelperFunctions", 7 | "parent":{ 8 | "name":"Scripts", 9 | "path":"folders/Scripts.yy", 10 | }, 11 | "resourceType":"GMScript", 12 | "resourceVersion":"2.0", 13 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_RadianceCascades_FPFixed/Shd_RadianceCascades_FPFixed.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMShader":"", 3 | "%Name":"Shd_RadianceCascades_FPFixed", 4 | "name":"Shd_RadianceCascades_FPFixed", 5 | "parent":{ 6 | "name":"Shaders", 7 | "path":"folders/Shaders.yy", 8 | }, 9 | "resourceType":"GMShader", 10 | "resourceVersion":"2.0", 11 | "type":1, 12 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_RadianceCascades_NearestFix/Shd_RadianceCascades_NearestFix.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMShader":"", 3 | "%Name":"Shd_RadianceCascades_NearestFix", 4 | "name":"Shd_RadianceCascades_NearestFix", 5 | "parent":{ 6 | "name":"Shaders", 7 | "path":"folders/Shaders.yy", 8 | }, 9 | "resourceType":"GMShader", 10 | "resourceVersion":"2.0", 11 | "type":1, 12 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_RadianceCascades_BilinearFix/Shd_RadianceCascades_BilinearFix.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMShader":"", 3 | "%Name":"Shd_RadianceCascades_BilinearFix", 4 | "name":"Shd_RadianceCascades_BilinearFix", 5 | "parent":{ 6 | "name":"Shaders", 7 | "path":"folders/Shaders.yy", 8 | }, 9 | "resourceType":"GMShader", 10 | "resourceVersion":"2.0", 11 | "type":1, 12 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_JumpFlood/Shd_JumpFlood.vsh: -------------------------------------------------------------------------------- 1 | // 2 | // Simple passthrough vertex shader 3 | // 4 | attribute vec3 in_Position; 5 | attribute vec4 in_Colour; 6 | attribute vec2 in_TextureCoord; 7 | varying vec2 in_TexelCoord; 8 | 9 | void main() { 10 | gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4(in_Position, 1.0); 11 | in_TexelCoord = in_TextureCoord; 12 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_DistanceField/Shd_DistanceField.vsh: -------------------------------------------------------------------------------- 1 | // 2 | // Simple passthrough vertex shader 3 | // 4 | attribute vec3 in_Position; 5 | attribute vec4 in_Colour; 6 | attribute vec2 in_TextureCoord; 7 | varying vec2 in_TexelCoord; 8 | 9 | void main() { 10 | gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4(in_Position, 1.0); 11 | in_TexelCoord = in_TextureCoord; 12 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_RadianceCascades_InterlacedFix/Shd_RadianceCascades_InterlacedFix.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMShader":"", 3 | "%Name":"Shd_RadianceCascades_InterlacedFix", 4 | "name":"Shd_RadianceCascades_InterlacedFix", 5 | "parent":{ 6 | "name":"Shaders", 7 | "path":"folders/Shaders.yy", 8 | }, 9 | "resourceType":"GMShader", 10 | "resourceVersion":"2.0", 11 | "type":1, 12 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_SeedJumpFlood/Shd_SeedJumpFlood.vsh: -------------------------------------------------------------------------------- 1 | // 2 | // Simple passthrough vertex shader 3 | // 4 | attribute vec3 in_Position; 5 | attribute vec4 in_Colour; 6 | attribute vec2 in_TextureCoord; 7 | varying vec2 in_TexelCoord; 8 | 9 | void main() { 10 | gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4(in_Position, 1.0); 11 | in_TexelCoord = in_TextureCoord; 12 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_RadianceCascades/Shd_RadianceCascades.vsh: -------------------------------------------------------------------------------- 1 | // 2 | // Simple passthrough vertex shader 3 | // 4 | attribute vec3 in_Position; 5 | attribute vec4 in_Colour; 6 | attribute vec2 in_TextureCoord; 7 | varying vec2 in_TexelCoord; 8 | 9 | void main() { 10 | gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4(in_Position, 1.0); 11 | in_TexelCoord = in_TextureCoord; 12 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_RadianceCascades_Final/Shd_RadianceCascades_Final.vsh: -------------------------------------------------------------------------------- 1 | // 2 | // Simple passthrough vertex shader 3 | // 4 | attribute vec3 in_Position; 5 | attribute vec4 in_Colour; 6 | attribute vec2 in_TextureCoord; 7 | varying vec2 in_TexelCoord; 8 | 9 | void main() { 10 | gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4(in_Position, 1.0); 11 | in_TexelCoord = in_TextureCoord; 12 | } -------------------------------------------------------------------------------- /RadianceCascades/objects/Obj_RadianceCascades/Step_2.gml: -------------------------------------------------------------------------------- 1 | global.showcascade += keyboard_check_pressed(vk_down) - keyboard_check_pressed(vk_up); 2 | global.showcascade = clamp(global.showcascade, 0, global.radiance_cascade_count - 1); 3 | 4 | global.radiance_cascade_interval += (keyboard_check_pressed(vk_right) - keyboard_check_pressed(vk_left)) * 16.0; 5 | global.radiance_cascade_interval = clamp(global.radiance_cascade_interval, 4, 256); -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_RadianceCascades_FPFixed/Shd_RadianceCascades_FPFixed.vsh: -------------------------------------------------------------------------------- 1 | // 2 | // Simple passthrough vertex shader 3 | // 4 | attribute vec3 in_Position; 5 | attribute vec4 in_Colour; 6 | attribute vec2 in_TextureCoord; 7 | varying vec2 in_TexelCoord; 8 | 9 | void main() { 10 | gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4(in_Position, 1.0); 11 | in_TexelCoord = in_TextureCoord; 12 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_RadianceCascades_BilinearFix/Shd_RadianceCascades_BilinearFix.vsh: -------------------------------------------------------------------------------- 1 | // 2 | // Simple passthrough vertex shader 3 | // 4 | attribute vec3 in_Position; 5 | attribute vec4 in_Colour; 6 | attribute vec2 in_TextureCoord; 7 | varying vec2 in_TexelCoord; 8 | 9 | void main() { 10 | gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4(in_Position, 1.0); 11 | in_TexelCoord = in_TextureCoord; 12 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_RadianceCascades_NearestFix/Shd_RadianceCascades_NearestFix.vsh: -------------------------------------------------------------------------------- 1 | // 2 | // Simple passthrough vertex shader 3 | // 4 | attribute vec3 in_Position; 5 | attribute vec4 in_Colour; 6 | attribute vec2 in_TextureCoord; 7 | varying vec2 in_TexelCoord; 8 | 9 | void main() { 10 | gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4(in_Position, 1.0); 11 | in_TexelCoord = in_TextureCoord; 12 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/shaders/Shd_Bilinear/Shd_Bilinear.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Simple passthrough fragment shader 3 | // 4 | varying vec2 v_vTexcoord; 5 | varying vec4 v_vColour; 6 | 7 | uniform vec4 colorTL; 8 | uniform vec4 colorTR; 9 | uniform vec4 colorBL; 10 | uniform vec4 colorBR; 11 | 12 | void main() { 13 | gl_FragColor = mix( 14 | mix(colorTL, colorTR, v_vTexcoord.x), 15 | mix(colorBL, colorBR, v_vTexcoord.x), 16 | v_vTexcoord.y); 17 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_RadianceCascades_InterlacedFix/Shd_RadianceCascades_InterlacedFix.vsh: -------------------------------------------------------------------------------- 1 | // 2 | // Simple passthrough vertex shader 3 | // 4 | attribute vec3 in_Position; 5 | attribute vec4 in_Colour; 6 | attribute vec2 in_TextureCoord; 7 | varying vec2 in_TexelCoord; 8 | 9 | void main() { 10 | gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4(in_Position, 1.0); 11 | in_TexelCoord = in_TextureCoord; 12 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/shaders/Shd_CascadeVisualDF/Shd_CascadeVisualDF.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Simple passthrough fragment shader 3 | // 4 | varying vec2 v_vTexcoord; 5 | varying vec4 v_vColour; 6 | uniform float in_CascadeSize; 7 | uniform float in_CascadeIndex; 8 | 9 | void main() { 10 | vec2 texel = v_vTexcoord * in_CascadeSize; 11 | float sectors = pow(2.0, in_CascadeIndex); 12 | vec2 size = vec2(in_CascadeSize / sectors); 13 | gl_FragColor = vec4(mod(texel, size) / size, 0.0, 1.0); 14 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/objects/Obj_LineTesting/Create_0.gml: -------------------------------------------------------------------------------- 1 | cell_size = 12; 2 | sqrt_size = cell_size * sqrt(2); 3 | diag_size = cell_size * sqrt(2); 4 | step_size = 1; 5 | steps = 0; 6 | 7 | x1 = room_width / 2; 8 | y1 = room_height / 2; 9 | x2 = room_width / 2; 10 | y2 = room_height / 2; 11 | 12 | //x1 = floor(x1 / cell_size) * cell_size; 13 | //y1 = floor(y1 / cell_size) * cell_size; 14 | x1 = cell_size * 0.5; 15 | y1 = cell_size * 0.5; 16 | 17 | dx = (x2 - x1); 18 | dy = (y2 - y1); -------------------------------------------------------------------------------- /RadianceCascades/shaders/Shd_DistanceField/Shd_DistanceField.fsh: -------------------------------------------------------------------------------- 1 | varying vec2 in_TextCoord; 2 | 3 | #define V2F16(v) ((v.y * float(0.0039215689)) + v.x) 4 | #define F16V2(f) vec2(floor(f * 255.0) * float(0.0039215689), fract(f * 255.0)) 5 | 6 | void main() { 7 | vec4 jfuv = texture2D(gm_BaseTexture, in_TextCoord); 8 | vec2 jumpflood = vec2(V2F16(jfuv.rg),V2F16(jfuv.ba)); 9 | float dist = distance(in_TextCoord, jumpflood); 10 | gl_FragColor = vec4(F16V2(dist), 0.0, 1.0); 11 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/shaders/Shd_CascadeVisual/Shd_CascadeVisual.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Simple passthrough fragment shader 3 | // 4 | varying vec2 v_vTexcoord; 5 | varying vec4 v_vColour; 6 | uniform float in_CascadeSize; 7 | uniform float in_CascadeIndex; 8 | uniform float in_CascadeAngular; 9 | 10 | void main() { 11 | vec2 texel = v_vTexcoord * in_CascadeSize; 12 | float size = sqrt(pow(4.0, in_CascadeIndex) * in_CascadeAngular); 13 | gl_FragColor = vec4(mod(texel, size) / size, 0.0, 1.0); 14 | } 15 | -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_DistanceField/Shd_DistanceField.fsh: -------------------------------------------------------------------------------- 1 | varying vec2 in_TexelCoord; 2 | uniform vec2 in_RenderExtent; 3 | 4 | #define V2F16(v) ((v.y * float(0.0039215689)) + v.x) 5 | #define F16V2(f) vec2(floor(f * 255.0) * float(0.0039215689), fract(f * 255.0)) 6 | 7 | void main() { 8 | vec4 jfuv = texture2D(gm_BaseTexture, in_TexelCoord); 9 | vec2 jumpflood = vec2(V2F16(jfuv.rg),V2F16(jfuv.ba)); 10 | float dist = distance(in_TexelCoord * in_RenderExtent, jumpflood * in_RenderExtent); 11 | gl_FragColor = vec4(F16V2(dist / length(in_RenderExtent)), 0.0, 1.0); 12 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/objects/Obj_LineTesting/Step_0.gml: -------------------------------------------------------------------------------- 1 | if (mouse_check_button(mb_left)) { 2 | x2 = mouse_x; 3 | y2 = mouse_y; 4 | } 5 | 6 | if (mouse_check_button(mb_right)) { 7 | x1 = mouse_x; 8 | y1 = mouse_y; 9 | } 10 | 11 | // Directional-Delta of Line (normalized): 12 | dx = (x2 - x1); 13 | dy = (y2 - y1); 14 | 15 | // Cross-section of square as relationship to slope of line: 16 | var dir = max(abs(dx), abs(dy)); 17 | var hyp = (1.0 / dir) * cell_size; 18 | 19 | // Multiply line directional delta by cross-section length: 20 | dx *= hyp; 21 | dy *= hyp; 22 | 23 | // Step length of the line: 24 | steps = dir / cell_size; -------------------------------------------------------------------------------- /CascadeVisualDemo/objects/Obj_MergingSample/Create_0.gml: -------------------------------------------------------------------------------- 1 | 2 | colorTL = make_color_rgb(255, 000, 255); 3 | colorTR = make_color_rgb(000, 255, 000); 4 | colorBL = make_color_rgb(000, 000, 255); 5 | colorBR = make_color_rgb(255, 255, 255); 6 | 7 | colorMR = #75ca75; 8 | 9 | box_sizeN = room_height * 0.20; 10 | offsetNX = (room_width - box_sizeN) * 0.25; 11 | offsetNY = (room_height - box_sizeN) * 0.25; 12 | 13 | box_sizeN1 = room_height * 0.40; 14 | offsetN1X = (room_width - box_sizeN1) * 0.5; 15 | offsetN1Y = (room_height - box_sizeN1) * 0.5; 16 | 17 | radiusN = 32; 18 | radiusN1 = 32 * 4; 19 | 20 | angularN = 4; 21 | angularN1 = 4 * 4; 22 | 23 | intervalN = radiusN; 24 | intervalN1 = radiusN1; -------------------------------------------------------------------------------- /CascadeVisualDemo/objects/Obj_SampleScaling/Draw_0.gml: -------------------------------------------------------------------------------- 1 | 2 | 3 | for(var j = 0; j < 3; j++) { 4 | switch(j) { 5 | case 0: draw_set_color(c_red); break; 6 | case 1: draw_set_color(c_lime); break; 7 | case 2: draw_set_color(c_aqua); break; 8 | } 9 | 10 | show_debug_message(string(j) + " : " + string(sectors * power(4, j))); 11 | for(var i = 0; i < sectors * power(4, j); i++) { 12 | //var sector_width = floor(width / (sectorsA * power(j, 2))); 13 | var sector_width = width / (sectors * power(4, j)); 14 | 15 | draw_rectangle( 16 | offset + (sector_width * i), 17 | offset + (j * height) + 8, 18 | offset + (sector_width * i) + sector_width, 19 | offset + (j * height) + height, true); 20 | } 21 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/shaders/Shd_Bilinear/Shd_Bilinear.vsh: -------------------------------------------------------------------------------- 1 | // 2 | // Simple passthrough vertex shader 3 | // 4 | attribute vec3 in_Position; // (x,y,z) 5 | //attribute vec3 in_Normal; // (x,y,z) unused in this shader. 6 | attribute vec4 in_Colour; // (r,g,b,a) 7 | attribute vec2 in_TextureCoord; // (u,v) 8 | 9 | varying vec2 v_vTexcoord; 10 | varying vec4 v_vColour; 11 | 12 | void main() 13 | { 14 | vec4 object_space_pos = vec4( in_Position.x, in_Position.y, in_Position.z, 1.0); 15 | gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * object_space_pos; 16 | 17 | v_vColour = in_Colour; 18 | v_vTexcoord = in_TextureCoord; 19 | } 20 | -------------------------------------------------------------------------------- /CascadeVisualDemo/shaders/Shd_CascadeVisual/Shd_CascadeVisual.vsh: -------------------------------------------------------------------------------- 1 | // 2 | // Simple passthrough vertex shader 3 | // 4 | attribute vec3 in_Position; // (x,y,z) 5 | //attribute vec3 in_Normal; // (x,y,z) unused in this shader. 6 | attribute vec4 in_Colour; // (r,g,b,a) 7 | attribute vec2 in_TextureCoord; // (u,v) 8 | 9 | varying vec2 v_vTexcoord; 10 | varying vec4 v_vColour; 11 | 12 | void main() 13 | { 14 | vec4 object_space_pos = vec4( in_Position.x, in_Position.y, in_Position.z, 1.0); 15 | gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * object_space_pos; 16 | 17 | v_vColour = in_Colour; 18 | v_vTexcoord = in_TextureCoord; 19 | } 20 | -------------------------------------------------------------------------------- /CascadeVisualDemo/shaders/Shd_CascadeVisualDF/Shd_CascadeVisualDF.vsh: -------------------------------------------------------------------------------- 1 | // 2 | // Simple passthrough vertex shader 3 | // 4 | attribute vec3 in_Position; // (x,y,z) 5 | //attribute vec3 in_Normal; // (x,y,z) unused in this shader. 6 | attribute vec4 in_Colour; // (r,g,b,a) 7 | attribute vec2 in_TextureCoord; // (u,v) 8 | 9 | varying vec2 v_vTexcoord; 10 | varying vec4 v_vColour; 11 | 12 | void main() 13 | { 14 | vec4 object_space_pos = vec4( in_Position.x, in_Position.y, in_Position.z, 1.0); 15 | gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * object_space_pos; 16 | 17 | v_vColour = in_Colour; 18 | v_vTexcoord = in_TextureCoord; 19 | } 20 | -------------------------------------------------------------------------------- /RadianceCascades/options/main/options_main.yy: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "GMMainOptions", 3 | "resourceVersion": "1.4", 4 | "name": "Main", 5 | "option_author": "", 6 | "option_collision_compatibility": false, 7 | "option_copy_on_write_enabled": false, 8 | "option_draw_colour": 4294967295, 9 | "option_game_speed": 60, 10 | "option_gameguid": "2d354565-d33e-4ec6-8381-3834cf09503d", 11 | "option_gameid": "0", 12 | "option_mips_for_3d_textures": false, 13 | "option_sci_usesci": false, 14 | "option_spine_licence": false, 15 | "option_steam_app_id": "0", 16 | "option_template_description": null, 17 | "option_template_icon": "${base_options_dir}/main/template_icon.png", 18 | "option_template_image": "${base_options_dir}/main/template_image.png", 19 | "option_window_colour": 255, 20 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/options/main/options_main.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMMainOptions":"", 3 | "%Name":"Main", 4 | "name":"Main", 5 | "option_author":"", 6 | "option_collision_compatibility":false, 7 | "option_copy_on_write_enabled":false, 8 | "option_draw_colour":4294967295, 9 | "option_gameguid":"72c95bfc-8dce-417b-a59a-65aaff878587", 10 | "option_gameid":"0", 11 | "option_game_speed":60, 12 | "option_mips_for_3d_textures":false, 13 | "option_sci_usesci":false, 14 | "option_spine_licence":false, 15 | "option_steam_app_id":"0", 16 | "option_template_description":null, 17 | "option_template_icon":"${base_options_dir}/main/template_icon.png", 18 | "option_template_image":"${base_options_dir}/main/template_image.png", 19 | "option_window_colour":255, 20 | "resourceType":"GMMainOptions", 21 | "resourceVersion":"2.0", 22 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/options/main/options_main.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMMainOptions":"", 3 | "%Name":"Main", 4 | "name":"Main", 5 | "option_author":"", 6 | "option_collision_compatibility":false, 7 | "option_copy_on_write_enabled":false, 8 | "option_draw_colour":4294967295, 9 | "option_gameguid":"8911b170-cf7d-404c-b52a-9fd7a5cf530c", 10 | "option_gameid":"0", 11 | "option_game_speed":60, 12 | "option_mips_for_3d_textures":false, 13 | "option_sci_usesci":false, 14 | "option_spine_licence":false, 15 | "option_steam_app_id":"0", 16 | "option_template_description":null, 17 | "option_template_icon":"${base_options_dir}/main/template_icon.png", 18 | "option_template_image":"${base_options_dir}/main/template_image.png", 19 | "option_window_colour":255, 20 | "resourceType":"GMMainOptions", 21 | "resourceVersion":"2.0", 22 | } -------------------------------------------------------------------------------- /RadianceCascades/objects/Obj_RadianceCascades/CleanUp_0.gml: -------------------------------------------------------------------------------- 1 | if (surface_exists(gameworld_worldscene)) surface_free(gameworld_worldscene); 2 | if (surface_exists(gameworld_temporary)) surface_free(gameworld_temporary); 3 | if (surface_exists(gameworld_jumpflood)) surface_free(gameworld_jumpflood); 4 | if (surface_exists(gameworld_distancefield)) surface_free(gameworld_distancefield); 5 | 6 | if (surface_exists(gameworld_radiance)) surface_free(gameworld_radiance); 7 | if (surface_exists(gameworld_bouncescene)) surface_free(gameworld_bouncescene); 8 | 9 | if (surface_exists(gameworld_storage)) surface_free(gameworld_storage); 10 | for(var i = 0; i < global.radiance_cascade_count; i++) { 11 | if (surface_exists(gameworld_cascades[i])) 12 | surface_free(gameworld_cascades[i]); 13 | 14 | if (surface_exists(gameworld_mipmaps[i])) 15 | surface_free(gameworld_mipmaps[i]); 16 | } -------------------------------------------------------------------------------- /RadianceCascades/options/linux/options_linux.yy: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "GMLinuxOptions", 3 | "resourceVersion": "1.0", 4 | "name": "Linux", 5 | "option_linux_allow_fullscreen": false, 6 | "option_linux_disable_sandbox": false, 7 | "option_linux_display_cursor": true, 8 | "option_linux_display_name": "Created with GameMaker", 9 | "option_linux_display_splash": false, 10 | "option_linux_enable_steam": false, 11 | "option_linux_homepage": "http://www.yoyogames.com", 12 | "option_linux_icon": "${base_options_dir}/linux/icons/64.png", 13 | "option_linux_interpolate_pixels": true, 14 | "option_linux_long_desc": "", 15 | "option_linux_maintainer_email": "", 16 | "option_linux_resize_window": false, 17 | "option_linux_scale": 0, 18 | "option_linux_short_desc": "", 19 | "option_linux_splash_screen": "${base_options_dir}/linux/splash/splash.png", 20 | "option_linux_start_fullscreen": false, 21 | "option_linux_sync": false, 22 | "option_linux_texture_page": "2048x2048", 23 | "option_linux_version": "1.0.0.0", 24 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/options/linux/options_linux.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMLinuxOptions":"", 3 | "%Name":"Linux", 4 | "name":"Linux", 5 | "option_linux_allow_fullscreen":false, 6 | "option_linux_disable_sandbox":false, 7 | "option_linux_display_cursor":true, 8 | "option_linux_display_name":"Created with GameMaker", 9 | "option_linux_display_splash":false, 10 | "option_linux_enable_steam":false, 11 | "option_linux_homepage":"http://www.yoyogames.com", 12 | "option_linux_icon":"${base_options_dir}/linux/icons/64.png", 13 | "option_linux_interpolate_pixels":true, 14 | "option_linux_long_desc":"", 15 | "option_linux_maintainer_email":"", 16 | "option_linux_resize_window":false, 17 | "option_linux_scale":0, 18 | "option_linux_short_desc":"", 19 | "option_linux_splash_screen":"${base_options_dir}/linux/splash/splash.png", 20 | "option_linux_start_fullscreen":false, 21 | "option_linux_sync":false, 22 | "option_linux_texture_page":"2048x2048", 23 | "option_linux_version":"1.0.0.0", 24 | "resourceType":"GMLinuxOptions", 25 | "resourceVersion":"2.0", 26 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/options/linux/options_linux.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMLinuxOptions":"", 3 | "%Name":"Linux", 4 | "name":"Linux", 5 | "option_linux_allow_fullscreen":false, 6 | "option_linux_disable_sandbox":false, 7 | "option_linux_display_cursor":true, 8 | "option_linux_display_name":"Created with GameMaker", 9 | "option_linux_display_splash":false, 10 | "option_linux_enable_steam":false, 11 | "option_linux_homepage":"http://www.yoyogames.com", 12 | "option_linux_icon":"${base_options_dir}/linux/icons/64.png", 13 | "option_linux_interpolate_pixels":true, 14 | "option_linux_long_desc":"", 15 | "option_linux_maintainer_email":"", 16 | "option_linux_resize_window":false, 17 | "option_linux_scale":0, 18 | "option_linux_short_desc":"", 19 | "option_linux_splash_screen":"${base_options_dir}/linux/splash/splash.png", 20 | "option_linux_start_fullscreen":false, 21 | "option_linux_sync":false, 22 | "option_linux_texture_page":"2048x2048", 23 | "option_linux_version":"1.0.0.0", 24 | "resourceType":"GMLinuxOptions", 25 | "resourceVersion":"2.0", 26 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/objects/Obj_RadianceCascades/Step_0.gml: -------------------------------------------------------------------------------- 1 | /* 2 | Updates to "render_*" variables go here before radiance_* variables updates. 3 | */ 4 | 5 | radiance_cascades = ceil(logn(4, point_distance(0, 0, render_width, render_height))); 6 | radiance_linear = power_ofN(render_linear, 2); 7 | radiance_width = floor(render_width / radiance_linear); 8 | radiance_height = floor(render_height / radiance_linear); 9 | 10 | surface_update(radiance_world, render_width, render_height, -1); 11 | surface_update(radiance_jfa, render_width, render_height, -1); 12 | surface_update(radiance_sdf, render_width, render_height, -1); 13 | surface_update(radiance_current, radiance_width, radiance_height, -1); 14 | surface_update(radiance_previous, radiance_width, radiance_height, -1); 15 | 16 | cascade_index += keyboard_check_pressed(vk_right) - keyboard_check_pressed(vk_left); 17 | cascade_index = clamp(cascade_index, 0, radiance_cascades); 18 | 19 | radiance_interval += (keyboard_check(vk_up) - keyboard_check(vk_down)); 20 | radiance_interval = clamp(radiance_interval, sqrt(2.0)*sqrt(2.0), 128); -------------------------------------------------------------------------------- /RadianceCascades/options/operagx/options_operagx.yy: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "GMOperaGXOptions", 3 | "resourceVersion": "1.1", 4 | "name": "operagx", 5 | "option_operagx_display_cursor": true, 6 | "option_operagx_editUrl": "", 7 | "option_operagx_game_name": "RadianceCascades", 8 | "option_operagx_guid": "", 9 | "option_operagx_internalShareUrl": "", 10 | "option_operagx_interpolate_pixels": true, 11 | "option_operagx_mod_editUrl": "", 12 | "option_operagx_mod_game_name": "RadianceCascades", 13 | "option_operagx_mod_guid": "", 14 | "option_operagx_mod_internalShareUrl": "", 15 | "option_operagx_mod_next_version": "1.0.0.0", 16 | "option_operagx_mod_publicShareUrl": "", 17 | "option_operagx_mod_team_id": "", 18 | "option_operagx_mod_team_name": "", 19 | "option_operagx_mod_version": "1.0.0.0", 20 | "option_operagx_next_version": "1.0.0.0", 21 | "option_operagx_publicShareUrl": "", 22 | "option_operagx_scale": 0, 23 | "option_operagx_team_id": "", 24 | "option_operagx_team_name": "", 25 | "option_operagx_texture_page": "2048x2048", 26 | "option_operagx_version": "1.0.0.0", 27 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/options/operagx/options_operagx.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMOperaGXOptions":"", 3 | "%Name":"operagx", 4 | "name":"operagx", 5 | "option_operagx_display_cursor":true, 6 | "option_operagx_editUrl":"", 7 | "option_operagx_game_name":"Sample", 8 | "option_operagx_guid":"", 9 | "option_operagx_internalShareUrl":"", 10 | "option_operagx_interpolate_pixels":true, 11 | "option_operagx_mod_editUrl":"", 12 | "option_operagx_mod_game_name":"Sample", 13 | "option_operagx_mod_guid":"", 14 | "option_operagx_mod_internalShareUrl":"", 15 | "option_operagx_mod_next_version":"1.0.0.0", 16 | "option_operagx_mod_publicShareUrl":"", 17 | "option_operagx_mod_team_id":"", 18 | "option_operagx_mod_team_name":"", 19 | "option_operagx_mod_version":"1.0.0.0", 20 | "option_operagx_next_version":"1.0.0.0", 21 | "option_operagx_publicShareUrl":"", 22 | "option_operagx_scale":0, 23 | "option_operagx_team_id":"", 24 | "option_operagx_team_name":"", 25 | "option_operagx_texture_page":"2048x2048", 26 | "option_operagx_version":"1.0.0.0", 27 | "resourceType":"GMOperaGXOptions", 28 | "resourceVersion":"2.0", 29 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/options/operagx/options_operagx.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMOperaGXOptions":"", 3 | "%Name":"Opera GX", 4 | "name":"Opera GX", 5 | "option_operagx_display_cursor":true, 6 | "option_operagx_editUrl":"", 7 | "option_operagx_game_name":"Created with GameMaker", 8 | "option_operagx_guid":"", 9 | "option_operagx_internalShareUrl":"", 10 | "option_operagx_interpolate_pixels":true, 11 | "option_operagx_mod_editUrl":"", 12 | "option_operagx_mod_game_name":"Created with GameMaker", 13 | "option_operagx_mod_guid":"", 14 | "option_operagx_mod_internalShareUrl":"", 15 | "option_operagx_mod_next_version":"1.0.0.0", 16 | "option_operagx_mod_publicShareUrl":"", 17 | "option_operagx_mod_team_id":"", 18 | "option_operagx_mod_team_name":"", 19 | "option_operagx_mod_version":"1.0.0.0", 20 | "option_operagx_next_version":"1.0.0.0", 21 | "option_operagx_publicShareUrl":"", 22 | "option_operagx_scale":0, 23 | "option_operagx_team_id":"", 24 | "option_operagx_team_name":"", 25 | "option_operagx_texture_page":"2048x2048", 26 | "option_operagx_version":"1.0.0.0", 27 | "resourceType":"GMOperaGXOptions", 28 | "resourceVersion":"2.0", 29 | } -------------------------------------------------------------------------------- /RadianceCascades/shaders/Shd_JumpfloodAlgorithm/Shd_JumpfloodAlgorithm.fsh: -------------------------------------------------------------------------------- 1 | varying vec2 in_TextCoord; 2 | uniform float in_JumpDistance; 3 | uniform float in_RenderExtent; 4 | 5 | #define V2F16(v) ((v.y * float(0.0039215689)) + v.x) 6 | 7 | void main() { 8 | vec2 offsets[9]; 9 | offsets[0] = vec2(-1.0, -1.0); 10 | offsets[1] = vec2(-1.0, 0.0); 11 | offsets[2] = vec2(-1.0, 1.0); 12 | offsets[3] = vec2(0.0, -1.0); 13 | offsets[4] = vec2(0.0, 0.0); 14 | offsets[5] = vec2(0.0, 1.0); 15 | offsets[6] = vec2(1.0, -1.0); 16 | offsets[7] = vec2(1.0, 0.0); 17 | offsets[8] = vec2(1.0, 1.0); 18 | 19 | float closest_dist = 9999999.9; 20 | vec4 closest_data = vec4(0.0); 21 | 22 | for(int i = 0; i < 9; i++) { 23 | vec2 jump = in_TextCoord + (offsets[i] * vec2(in_JumpDistance / in_RenderExtent)); 24 | vec4 seed = texture2D(gm_BaseTexture, jump); 25 | vec2 seedpos = vec2(V2F16(seed.xy), V2F16(seed.zw)); 26 | float dist = distance(seedpos, in_TextCoord); 27 | 28 | if (seedpos != vec2(0.0) && dist <= closest_dist) { 29 | closest_dist = dist; 30 | closest_data = seed; 31 | } 32 | } 33 | 34 | gl_FragColor = closest_data; 35 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/objects/Obj_MergingSample/Obj_MergingSample.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMObject":"", 3 | "%Name":"Obj_MergingSample", 4 | "eventList":[ 5 | {"$GMEvent":"","%Name":"","collisionObjectId":null,"eventNum":0,"eventType":0,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",}, 6 | {"$GMEvent":"","%Name":"","collisionObjectId":null,"eventNum":0,"eventType":8,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",}, 7 | ], 8 | "managed":true, 9 | "name":"Obj_MergingSample", 10 | "overriddenProperties":[], 11 | "parent":{ 12 | "name":"Objects", 13 | "path":"folders/Objects.yy", 14 | }, 15 | "parentObjectId":null, 16 | "persistent":false, 17 | "physicsAngularDamping":0.1, 18 | "physicsDensity":0.5, 19 | "physicsFriction":0.2, 20 | "physicsGroup":1, 21 | "physicsKinematic":false, 22 | "physicsLinearDamping":0.1, 23 | "physicsObject":false, 24 | "physicsRestitution":0.1, 25 | "physicsSensor":false, 26 | "physicsShape":1, 27 | "physicsShapePoints":[], 28 | "physicsStartAwake":true, 29 | "properties":[], 30 | "resourceType":"GMObject", 31 | "resourceVersion":"2.0", 32 | "solid":false, 33 | "spriteId":null, 34 | "spriteMaskId":null, 35 | "visible":true, 36 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/objects/Obj_SampleScaling/Obj_SampleScaling.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMObject":"", 3 | "%Name":"Obj_SampleScaling", 4 | "eventList":[ 5 | {"$GMEvent":"","%Name":"","collisionObjectId":null,"eventNum":0,"eventType":0,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",}, 6 | {"$GMEvent":"","%Name":"","collisionObjectId":null,"eventNum":0,"eventType":8,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",}, 7 | ], 8 | "managed":true, 9 | "name":"Obj_SampleScaling", 10 | "overriddenProperties":[], 11 | "parent":{ 12 | "name":"Objects", 13 | "path":"folders/Objects.yy", 14 | }, 15 | "parentObjectId":null, 16 | "persistent":false, 17 | "physicsAngularDamping":0.1, 18 | "physicsDensity":0.5, 19 | "physicsFriction":0.2, 20 | "physicsGroup":1, 21 | "physicsKinematic":false, 22 | "physicsLinearDamping":0.1, 23 | "physicsObject":false, 24 | "physicsRestitution":0.1, 25 | "physicsSensor":false, 26 | "physicsShape":1, 27 | "physicsShapePoints":[], 28 | "physicsStartAwake":true, 29 | "properties":[], 30 | "resourceType":"GMObject", 31 | "resourceVersion":"2.0", 32 | "solid":false, 33 | "spriteId":null, 34 | "spriteMaskId":null, 35 | "visible":true, 36 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_JumpFlood/Shd_JumpFlood.fsh: -------------------------------------------------------------------------------- 1 | varying vec2 in_TexelCoord; 2 | uniform float in_JumpDistance; 3 | uniform vec2 in_RenderExtent; 4 | 5 | #define V2F16(v) ((v.y * float(0.0039215689)) + v.x) 6 | 7 | void main() { 8 | vec2 offsets[9]; 9 | offsets[0] = vec2(-1.0, -1.0); 10 | offsets[1] = vec2(-1.0, 0.0); 11 | offsets[2] = vec2(-1.0, 1.0); 12 | offsets[3] = vec2(0.0, -1.0); 13 | offsets[4] = vec2(0.0, 0.0); 14 | offsets[5] = vec2(0.0, 1.0); 15 | offsets[6] = vec2(1.0, -1.0); 16 | offsets[7] = vec2(1.0, 0.0); 17 | offsets[8] = vec2(1.0, 1.0); 18 | 19 | float closest_dist = 9999999.9; 20 | vec4 closest_data = vec4(0.0); 21 | 22 | for(int i = 0; i < 9; i++) { 23 | vec2 jump = in_TexelCoord + (offsets[i] * vec2(in_JumpDistance / in_RenderExtent)); 24 | vec4 seed = texture2D(gm_BaseTexture, jump); 25 | vec2 seedpos = vec2(V2F16(seed.xy), V2F16(seed.zw)); 26 | float dist = distance(seedpos * in_RenderExtent, in_TexelCoord * in_RenderExtent); 27 | 28 | if (seedpos != vec2(0.0) && dist <= closest_dist) { 29 | closest_dist = dist; 30 | closest_data = seed; 31 | } 32 | } 33 | 34 | gl_FragColor = closest_data; 35 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /RadianceCascades/options/html5/options_html5.yy: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "GMHtml5Options", 3 | "resourceVersion": "1.0", 4 | "name": "HTML5", 5 | "option_html5_allow_fullscreen": true, 6 | "option_html5_browser_title": "Created with GameMaker", 7 | "option_html5_centregame": false, 8 | "option_html5_display_cursor": true, 9 | "option_html5_facebook_app_display_name": "", 10 | "option_html5_facebook_id": "", 11 | "option_html5_flurry_enable": false, 12 | "option_html5_flurry_id": "", 13 | "option_html5_foldername": "html5game", 14 | "option_html5_google_analytics_enable": false, 15 | "option_html5_google_tracking_id": "", 16 | "option_html5_icon": "${base_options_dir}/html5/fav.ico", 17 | "option_html5_index": "", 18 | "option_html5_interpolate_pixels": true, 19 | "option_html5_jsprepend": "", 20 | "option_html5_loadingbar": "", 21 | "option_html5_localrunalert": true, 22 | "option_html5_outputdebugtoconsole": true, 23 | "option_html5_outputname": "index.html", 24 | "option_html5_scale": 0, 25 | "option_html5_splash_png": "${base_options_dir}/html5/splash.png", 26 | "option_html5_texture_page": "2048x2048", 27 | "option_html5_use_facebook": false, 28 | "option_html5_usebuiltinfont": true, 29 | "option_html5_usebuiltinparticles": true, 30 | "option_html5_usesplash": false, 31 | "option_html5_version": "1.0.0.0", 32 | "option_html5_webgl": 2, 33 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/objects/Obj_LineTesting/Obj_LineTesting.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMObject":"", 3 | "%Name":"Obj_LineTesting", 4 | "eventList":[ 5 | {"$GMEvent":"","%Name":"","collisionObjectId":null,"eventNum":0,"eventType":0,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",}, 6 | {"$GMEvent":"","%Name":"","collisionObjectId":null,"eventNum":0,"eventType":8,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",}, 7 | {"$GMEvent":"","%Name":"","collisionObjectId":null,"eventNum":0,"eventType":3,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",}, 8 | ], 9 | "managed":true, 10 | "name":"Obj_LineTesting", 11 | "overriddenProperties":[], 12 | "parent":{ 13 | "name":"Objects", 14 | "path":"folders/Objects.yy", 15 | }, 16 | "parentObjectId":null, 17 | "persistent":false, 18 | "physicsAngularDamping":0.1, 19 | "physicsDensity":0.5, 20 | "physicsFriction":0.2, 21 | "physicsGroup":1, 22 | "physicsKinematic":false, 23 | "physicsLinearDamping":0.1, 24 | "physicsObject":false, 25 | "physicsRestitution":0.1, 26 | "physicsSensor":false, 27 | "physicsShape":1, 28 | "physicsShapePoints":[], 29 | "physicsStartAwake":true, 30 | "properties":[], 31 | "resourceType":"GMObject", 32 | "resourceVersion":"2.0", 33 | "solid":false, 34 | "spriteId":null, 35 | "spriteMaskId":null, 36 | "visible":true, 37 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/options/html5/options_html5.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMHtml5Options":"", 3 | "%Name":"HTML5", 4 | "name":"HTML5", 5 | "option_html5_allow_fullscreen":true, 6 | "option_html5_browser_title":"Created with GameMaker", 7 | "option_html5_centregame":false, 8 | "option_html5_display_cursor":true, 9 | "option_html5_facebook_app_display_name":"", 10 | "option_html5_facebook_id":"", 11 | "option_html5_flurry_enable":false, 12 | "option_html5_flurry_id":"", 13 | "option_html5_foldername":"html5game", 14 | "option_html5_google_analytics_enable":false, 15 | "option_html5_google_tracking_id":"", 16 | "option_html5_icon":"${base_options_dir}/html5/fav.ico", 17 | "option_html5_index":"", 18 | "option_html5_interpolate_pixels":true, 19 | "option_html5_jsprepend":"", 20 | "option_html5_loadingbar":"", 21 | "option_html5_localrunalert":true, 22 | "option_html5_outputdebugtoconsole":true, 23 | "option_html5_outputname":"index.html", 24 | "option_html5_scale":0, 25 | "option_html5_splash_png":"${base_options_dir}/html5/splash.png", 26 | "option_html5_texture_page":"2048x2048", 27 | "option_html5_usebuiltinfont":true, 28 | "option_html5_usebuiltinparticles":true, 29 | "option_html5_usesplash":false, 30 | "option_html5_use_facebook":false, 31 | "option_html5_version":"1.0.0.0", 32 | "option_html5_webgl":2, 33 | "resourceType":"GMHtml5Options", 34 | "resourceVersion":"2.0", 35 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/options/html5/options_html5.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMHtml5Options":"", 3 | "%Name":"HTML5", 4 | "name":"HTML5", 5 | "option_html5_allow_fullscreen":true, 6 | "option_html5_browser_title":"Created with GameMaker", 7 | "option_html5_centregame":false, 8 | "option_html5_display_cursor":true, 9 | "option_html5_facebook_app_display_name":"", 10 | "option_html5_facebook_id":"", 11 | "option_html5_flurry_enable":false, 12 | "option_html5_flurry_id":"", 13 | "option_html5_foldername":"html5game", 14 | "option_html5_google_analytics_enable":false, 15 | "option_html5_google_tracking_id":"", 16 | "option_html5_icon":"${base_options_dir}/html5/fav.ico", 17 | "option_html5_index":"", 18 | "option_html5_interpolate_pixels":true, 19 | "option_html5_jsprepend":"", 20 | "option_html5_loadingbar":"", 21 | "option_html5_localrunalert":true, 22 | "option_html5_outputdebugtoconsole":true, 23 | "option_html5_outputname":"index.html", 24 | "option_html5_scale":0, 25 | "option_html5_splash_png":"${base_options_dir}/html5/splash.png", 26 | "option_html5_texture_page":"2048x2048", 27 | "option_html5_usebuiltinfont":true, 28 | "option_html5_usebuiltinparticles":true, 29 | "option_html5_usesplash":false, 30 | "option_html5_use_facebook":false, 31 | "option_html5_version":"1.0.0.0", 32 | "option_html5_webgl":2, 33 | "resourceType":"GMHtml5Options", 34 | "resourceVersion":"2.0", 35 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/objects/Obj_SampleObject/Create_0.gml: -------------------------------------------------------------------------------- 1 | // User Settings: 2 | size = 32; 3 | angular = 4; 4 | spacing = 1; 5 | interval = 1; 6 | cascadeIndex = 0; 7 | 8 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | function power_of2(number) { return power(2, ceil(logn(2, number))); } 10 | function power_of4(number) { return power(4, ceil(logn(4, number))); } 11 | 12 | angular = power_of4(angular); 13 | cascade_size = floor(size / spacing) * sqrt(angular); 14 | render_size = 512; 15 | 16 | cascadeCount = floor(logn(2, cascade_size / sqrt(angular))) - 1; 17 | probeCount = floor(cascade_size / sqrt(angular)); 18 | probeSpacing = cascade_size / probeCount; 19 | 20 | cascade_offsetx = 128 + 80; 21 | cascade_offsety = 128; 22 | cascade_offsetx2 = 128 + 80 + render_size; 23 | cascade_offsety2 = 128; 24 | 25 | current_spacingindex = 0; 26 | current_spacing = spacing = max(2, power_of2(spacing)); 27 | current_angular = angular; 28 | current_probex = 0; 29 | current_probey = 0; 30 | current_probesize = 0; 31 | current_interval = (interval * (1.0 - power(4.0, cascadeIndex))) / (1.0 - 4.0); 32 | current_intervalstart = interval * power(4.0, cascadeIndex); 33 | 34 | render_surface = -1; 35 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /RadianceCascades/options/mac/options_mac.yy: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "GMMacOptions", 3 | "resourceVersion": "1.0", 4 | "name": "macOS", 5 | "option_mac_allow_fullscreen": false, 6 | "option_mac_allow_incoming_network": false, 7 | "option_mac_allow_outgoing_network": false, 8 | "option_mac_app_category": "Games", 9 | "option_mac_app_id": "com.company.game", 10 | "option_mac_apple_sign_in": false, 11 | "option_mac_arm64": true, 12 | "option_mac_build_app_store": false, 13 | "option_mac_copyright": "", 14 | "option_mac_disable_sandbox": false, 15 | "option_mac_display_cursor": true, 16 | "option_mac_display_name": "Created with GameMaker", 17 | "option_mac_enable_retina": false, 18 | "option_mac_enable_steam": false, 19 | "option_mac_icon_png": "${base_options_dir}/mac/icons/1024.png", 20 | "option_mac_installer_background_png": "${base_options_dir}/mac/splash/installer_background.png", 21 | "option_mac_interpolate_pixels": true, 22 | "option_mac_menu_dock": false, 23 | "option_mac_min_version": "10.10", 24 | "option_mac_output_dir": "~/gamemakerstudio2", 25 | "option_mac_resize_window": false, 26 | "option_mac_scale": 0, 27 | "option_mac_signing_identity": "Developer ID Application:", 28 | "option_mac_splash_png": "${base_options_dir}/mac/splash/splash.png", 29 | "option_mac_start_fullscreen": false, 30 | "option_mac_team_id": "", 31 | "option_mac_texture_page": "2048x2048", 32 | "option_mac_version": "1.0.0.0", 33 | "option_mac_vsync": false, 34 | "option_mac_x86_64": true, 35 | } -------------------------------------------------------------------------------- /RadianceCascades/options/tvos/options_tvos.yy: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "GMtvOSOptions", 3 | "resourceVersion": "1.3", 4 | "name": "tvOS", 5 | "option_tvos_bundle_name": "com.company.game", 6 | "option_tvos_cocoapods_checkbox": true, 7 | "option_tvos_display_cursor": false, 8 | "option_tvos_display_name": "Made in GameMaker", 9 | "option_tvos_icon_1280": "${base_options_dir}/tvos/icons/1280.png", 10 | "option_tvos_icon_400": "${base_options_dir}/tvos/icons/400.png", 11 | "option_tvos_icon_400_2x": "${base_options_dir}/tvos/icons/400_2x.png", 12 | "option_tvos_interpolate_pixels": true, 13 | "option_tvos_min_version": "10.0", 14 | "option_tvos_output_dir": "~/GameMakerStudio2/tvOS", 15 | "option_tvos_podfile_lock_path": "${options_dir}\\tvos\\Podfile.lock", 16 | "option_tvos_podfile_path": "${options_dir}\\tvos\\Podfile", 17 | "option_tvos_scale": 0, 18 | "option_tvos_splash_time": 0, 19 | "option_tvos_splashscreen": "${base_options_dir}/tvos/splash/splash.png", 20 | "option_tvos_splashscreen_2x": "${base_options_dir}/tvos/splash/splash_2x.png", 21 | "option_tvos_team_id": "", 22 | "option_tvos_texture_page": "2048x2048", 23 | "option_tvos_topshelf": "${base_options_dir}/tvos/topshelf/topshelf.png", 24 | "option_tvos_topshelf_2x": "${base_options_dir}/tvos/topshelf/topshelf_2x.png", 25 | "option_tvos_topshelf_wide": "${base_options_dir}/tvos/topshelf/topshelf_wide.png", 26 | "option_tvos_topshelf_wide_2x": "${base_options_dir}/tvos/topshelf/topshelf_wide_2x.png", 27 | "option_tvos_version": "1.0.0.0", 28 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/objects/Obj_SampleObjectDF/Create_0.gml: -------------------------------------------------------------------------------- 1 | // User Settings: 2 | size = 32; 3 | angular = 4; // DO NOT CHANGE THIS FOR DIRECTION-FIRST PROBES. 4 | spacing = 1; 5 | interval = 1; 6 | cascadeIndex = 0; 7 | 8 | track_moused = 0; 9 | 10 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | function power_of2(number) { return power(2, ceil(logn(2, number))); } 12 | function power_of4(number) { return power(4, ceil(logn(4, number))); } 13 | 14 | angular = power_of4(angular); 15 | cascade_size = floor(size / spacing) * sqrt(angular); 16 | render_size = 512; 17 | 18 | cascadeCount = floor(logn(2, cascade_size / sqrt(angular))) - 1; 19 | probeCount = floor(cascade_size / sqrt(angular)); 20 | probeSpacing = cascade_size / probeCount; 21 | 22 | cascade_offsetx = 128 + 80; 23 | cascade_offsety = 128; 24 | cascade_offsetx2 = 128 + 80 + render_size; 25 | cascade_offsety2 = 128; 26 | 27 | current_spacingindex = 0; 28 | current_spacing = spacing = max(2, power_of2(spacing)); 29 | current_angular = angular; 30 | current_probex = 0; 31 | current_probey = 0; 32 | current_probesize = 0; 33 | current_sectorsize = 0; 34 | current_interval = (interval * (1.0 - power(4.0, cascadeIndex))) / (1.0 - 4.0); 35 | current_intervalstart = interval * power(4.0, cascadeIndex); 36 | 37 | render_surface = -1; 38 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /CascadeVisualDemo/options/mac/options_mac.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMMacOptions":"", 3 | "%Name":"macOS", 4 | "name":"macOS", 5 | "option_mac_allow_fullscreen":false, 6 | "option_mac_allow_incoming_network":false, 7 | "option_mac_allow_outgoing_network":false, 8 | "option_mac_apple_sign_in":false, 9 | "option_mac_app_category":"Games", 10 | "option_mac_app_id":"com.company.game", 11 | "option_mac_arm64":true, 12 | "option_mac_build_app_store":false, 13 | "option_mac_build_number":0, 14 | "option_mac_copyright":"", 15 | "option_mac_disable_sandbox":false, 16 | "option_mac_display_cursor":true, 17 | "option_mac_display_name":"Created with GameMaker", 18 | "option_mac_enable_retina":false, 19 | "option_mac_enable_steam":false, 20 | "option_mac_icon_png":"${base_options_dir}/mac/icons/1024.png", 21 | "option_mac_installer_background_png":"${base_options_dir}/mac/splash/installer_background.png", 22 | "option_mac_interpolate_pixels":true, 23 | "option_mac_menu_dock":false, 24 | "option_mac_min_version":"10.10", 25 | "option_mac_output_dir":"~/gamemakerstudio2", 26 | "option_mac_resize_window":false, 27 | "option_mac_scale":0, 28 | "option_mac_signing_identity":"Developer ID Application:", 29 | "option_mac_splash_png":"${base_options_dir}/mac/splash/splash.png", 30 | "option_mac_start_fullscreen":false, 31 | "option_mac_team_id":"", 32 | "option_mac_texture_page":"2048x2048", 33 | "option_mac_version":"1.0.0.0", 34 | "option_mac_vsync":false, 35 | "option_mac_x86_64":true, 36 | "resourceType":"GMMacOptions", 37 | "resourceVersion":"2.0", 38 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/options/mac/options_mac.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMMacOptions":"", 3 | "%Name":"macOS", 4 | "name":"macOS", 5 | "option_mac_allow_fullscreen":false, 6 | "option_mac_allow_incoming_network":false, 7 | "option_mac_allow_outgoing_network":false, 8 | "option_mac_apple_sign_in":false, 9 | "option_mac_app_category":"Games", 10 | "option_mac_app_id":"com.company.game", 11 | "option_mac_arm64":true, 12 | "option_mac_build_app_store":false, 13 | "option_mac_build_number":0, 14 | "option_mac_copyright":"", 15 | "option_mac_disable_sandbox":false, 16 | "option_mac_display_cursor":true, 17 | "option_mac_display_name":"Created with GameMaker", 18 | "option_mac_enable_retina":false, 19 | "option_mac_enable_steam":false, 20 | "option_mac_icon_png":"${base_options_dir}/mac/icons/1024.png", 21 | "option_mac_installer_background_png":"${base_options_dir}/mac/splash/installer_background.png", 22 | "option_mac_interpolate_pixels":true, 23 | "option_mac_menu_dock":false, 24 | "option_mac_min_version":"10.10", 25 | "option_mac_output_dir":"~/gamemakerstudio2", 26 | "option_mac_resize_window":false, 27 | "option_mac_scale":0, 28 | "option_mac_signing_identity":"Developer ID Application:", 29 | "option_mac_splash_png":"${base_options_dir}/mac/splash/splash.png", 30 | "option_mac_start_fullscreen":false, 31 | "option_mac_team_id":"", 32 | "option_mac_texture_page":"2048x2048", 33 | "option_mac_version":"1.0.0.0", 34 | "option_mac_vsync":false, 35 | "option_mac_x86_64":true, 36 | "resourceType":"GMMacOptions", 37 | "resourceVersion":"2.0", 38 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/options/tvos/options_tvos.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMtvOSOptions":"", 3 | "%Name":"tvOS", 4 | "name":"tvOS", 5 | "option_tvos_build_number":0, 6 | "option_tvos_bundle_name":"com.company.game", 7 | "option_tvos_cocoapods_checkbox":true, 8 | "option_tvos_display_cursor":false, 9 | "option_tvos_display_name":"Made in GameMaker", 10 | "option_tvos_enable_broadcast":false, 11 | "option_tvos_icon_1280":"${base_options_dir}/tvos/icons/1280.png", 12 | "option_tvos_icon_400":"${base_options_dir}/tvos/icons/400.png", 13 | "option_tvos_icon_400_2x":"${base_options_dir}/tvos/icons/400_2x.png", 14 | "option_tvos_interpolate_pixels":true, 15 | "option_tvos_min_version":"10.0", 16 | "option_tvos_output_dir":"~/GameMakerStudio2/tvOS", 17 | "option_tvos_podfile_lock_path":"${options_dir}\\tvos\\Podfile.lock", 18 | "option_tvos_podfile_path":"${options_dir}\\tvos\\Podfile", 19 | "option_tvos_scale":0, 20 | "option_tvos_splashscreen":"${base_options_dir}/tvos/splash/splash.png", 21 | "option_tvos_splashscreen_2x":"${base_options_dir}/tvos/splash/splash_2x.png", 22 | "option_tvos_splash_time":0, 23 | "option_tvos_team_id":"", 24 | "option_tvos_texture_page":"2048x2048", 25 | "option_tvos_topshelf":"${base_options_dir}/tvos/topshelf/topshelf.png", 26 | "option_tvos_topshelf_2x":"${base_options_dir}/tvos/topshelf/topshelf_2x.png", 27 | "option_tvos_topshelf_wide":"${base_options_dir}/tvos/topshelf/topshelf_wide.png", 28 | "option_tvos_topshelf_wide_2x":"${base_options_dir}/tvos/topshelf/topshelf_wide_2x.png", 29 | "option_tvos_version":"1.0.0.0", 30 | "resourceType":"GMtvOSOptions", 31 | "resourceVersion":"2.0", 32 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/options/tvos/options_tvos.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMtvOSOptions":"", 3 | "%Name":"tvOS", 4 | "name":"tvOS", 5 | "option_tvos_build_number":0, 6 | "option_tvos_bundle_name":"com.company.game", 7 | "option_tvos_cocoapods_checkbox":true, 8 | "option_tvos_display_cursor":false, 9 | "option_tvos_display_name":"Made in GameMaker", 10 | "option_tvos_enable_broadcast":false, 11 | "option_tvos_icon_1280":"${base_options_dir}/tvos/icons/1280.png", 12 | "option_tvos_icon_400":"${base_options_dir}/tvos/icons/400.png", 13 | "option_tvos_icon_400_2x":"${base_options_dir}/tvos/icons/400_2x.png", 14 | "option_tvos_interpolate_pixels":true, 15 | "option_tvos_min_version":"10.0", 16 | "option_tvos_output_dir":"~/GameMakerStudio2/tvOS", 17 | "option_tvos_podfile_lock_path":"${options_dir}\\tvos\\Podfile.lock", 18 | "option_tvos_podfile_path":"${options_dir}\\tvos\\Podfile", 19 | "option_tvos_scale":0, 20 | "option_tvos_splashscreen":"${base_options_dir}/tvos/splash/splash.png", 21 | "option_tvos_splashscreen_2x":"${base_options_dir}/tvos/splash/splash_2x.png", 22 | "option_tvos_splash_time":0, 23 | "option_tvos_team_id":"", 24 | "option_tvos_texture_page":"2048x2048", 25 | "option_tvos_topshelf":"${base_options_dir}/tvos/topshelf/topshelf.png", 26 | "option_tvos_topshelf_2x":"${base_options_dir}/tvos/topshelf/topshelf_2x.png", 27 | "option_tvos_topshelf_wide":"${base_options_dir}/tvos/topshelf/topshelf_wide.png", 28 | "option_tvos_topshelf_wide_2x":"${base_options_dir}/tvos/topshelf/topshelf_wide_2x.png", 29 | "option_tvos_version":"1.0.0.0", 30 | "resourceType":"GMtvOSOptions", 31 | "resourceVersion":"2.0", 32 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/CascadeVisualDemo.resource_order: -------------------------------------------------------------------------------- 1 | { 2 | "FolderOrderSettings":[ 3 | {"name":"Animation Curves","order":12,"path":"folders/Animation Curves.yy",}, 4 | {"name":"Extensions","order":14,"path":"folders/Extensions.yy",}, 5 | {"name":"Fonts","order":7,"path":"folders/Fonts.yy",}, 6 | {"name":"Notes","order":13,"path":"folders/Notes.yy",}, 7 | {"name":"Objects","order":9,"path":"folders/Objects.yy",}, 8 | {"name":"Particle Systems","order":15,"path":"folders/Particle Systems.yy",}, 9 | {"name":"Paths","order":4,"path":"folders/Paths.yy",}, 10 | {"name":"Rooms","order":10,"path":"folders/Rooms.yy",}, 11 | {"name":"Scripts","order":5,"path":"folders/Scripts.yy",}, 12 | {"name":"Sequences","order":11,"path":"folders/Sequences.yy",}, 13 | {"name":"Shaders","order":6,"path":"folders/Shaders.yy",}, 14 | {"name":"Sounds","order":3,"path":"folders/Sounds.yy",}, 15 | {"name":"Sprites","order":1,"path":"folders/Sprites.yy",}, 16 | {"name":"Tile Sets","order":2,"path":"folders/Tile Sets.yy",}, 17 | {"name":"Timelines","order":8,"path":"folders/Timelines.yy",}, 18 | ], 19 | "ResourceOrderSettings":[ 20 | {"name":"Obj_MergingSample","order":2,"path":"objects/Obj_MergingSample/Obj_MergingSample.yy",}, 21 | {"name":"Obj_SampleObjectDF","order":1,"path":"objects/Obj_SampleObjectDF/Obj_SampleObjectDF.yy",}, 22 | {"name":"Obj_SampleScaling","order":3,"path":"objects/Obj_SampleScaling/Obj_SampleScaling.yy",}, 23 | {"name":"Shd_Bilinear","order":2,"path":"shaders/Shd_Bilinear/Shd_Bilinear.yy",}, 24 | {"name":"Shd_CascadeVisualDF","order":1,"path":"shaders/Shd_CascadeVisualDF/Shd_CascadeVisualDF.yy",}, 25 | ], 26 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/objects/Obj_SampleObject/Step_0.gml: -------------------------------------------------------------------------------- 1 | cascadeIndex += keyboard_check_pressed(vk_right) - keyboard_check_pressed(vk_left); 2 | cascadeIndex = clamp(cascadeIndex, 0, cascadeCount); 3 | current_spacingindex += keyboard_check_pressed(vk_down) - keyboard_check_pressed(vk_up); 4 | current_spacingindex = clamp(current_spacingindex, 0, logn(2, size) - 1); 5 | 6 | current_spacing = spacing * power(2.0, current_spacingindex); 7 | cascade_size = floor(size / current_spacing) * sqrt(angular); 8 | cascadeCount = floor(logn(2, cascade_size / sqrt(angular))) - 1; 9 | 10 | current_angular = angular * power(4.0, cascadeIndex); 11 | probeCount = floor(cascade_size / sqrt(current_angular)); 12 | probeSpacing = cascade_size / probeCount; 13 | 14 | current_probesize = sqrt(current_angular) * (render_size / cascade_size); 15 | 16 | if (mouse_check_button(mb_left)) { 17 | current_probex = floor((mouse_x - cascade_offsetx2) / current_probesize) * current_probesize; 18 | current_probey = floor((mouse_y - cascade_offsety2) / current_probesize) * current_probesize; 19 | } 20 | 21 | current_probex = floor(current_probex / current_probesize) * current_probesize; 22 | current_probey = floor(current_probey / current_probesize) * current_probesize; 23 | current_probex = clamp(current_probex, 0, render_size-current_probesize); 24 | current_probey = clamp(current_probey, 0, render_size-current_probesize); 25 | 26 | current_intervalstart = (interval * (1.0 - power(4.0, cascadeIndex))) / (1.0 - 4.0); 27 | current_interval = interval * power(4.0, cascadeIndex); 28 | 29 | if (keyboard_check_pressed(vk_space)) { 30 | instance_destroy(self); 31 | instance_create_depth(x, y, depth, Obj_SampleObjectDF); 32 | } -------------------------------------------------------------------------------- /RadianceCascades/objects/Obj_RadianceCascades/Obj_RadianceCascades.yy: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "GMObject", 3 | "resourceVersion": "1.0", 4 | "name": "Obj_RadianceCascades", 5 | "eventList": [ 6 | {"resourceType":"GMEvent","resourceVersion":"1.0","name":"","collisionObjectId":null,"eventNum":0,"eventType":0,"isDnD":false,}, 7 | {"resourceType":"GMEvent","resourceVersion":"1.0","name":"","collisionObjectId":null,"eventNum":0,"eventType":12,"isDnD":false,}, 8 | {"resourceType":"GMEvent","resourceVersion":"1.0","name":"","collisionObjectId":null,"eventNum":76,"eventType":8,"isDnD":false,}, 9 | {"resourceType":"GMEvent","resourceVersion":"1.0","name":"","collisionObjectId":null,"eventNum":73,"eventType":8,"isDnD":false,}, 10 | {"resourceType":"GMEvent","resourceVersion":"1.0","name":"","collisionObjectId":null,"eventNum":72,"eventType":8,"isDnD":false,}, 11 | {"resourceType":"GMEvent","resourceVersion":"1.0","name":"","collisionObjectId":null,"eventNum":2,"eventType":3,"isDnD":false,}, 12 | ], 13 | "managed": true, 14 | "overriddenProperties": [], 15 | "parent": { 16 | "name": "Objects", 17 | "path": "folders/Objects.yy", 18 | }, 19 | "parentObjectId": null, 20 | "persistent": false, 21 | "physicsAngularDamping": 0.1, 22 | "physicsDensity": 0.5, 23 | "physicsFriction": 0.2, 24 | "physicsGroup": 1, 25 | "physicsKinematic": false, 26 | "physicsLinearDamping": 0.1, 27 | "physicsObject": false, 28 | "physicsRestitution": 0.1, 29 | "physicsSensor": false, 30 | "physicsShape": 1, 31 | "physicsShapePoints": [], 32 | "physicsStartAwake": true, 33 | "properties": [], 34 | "solid": false, 35 | "spriteId": null, 36 | "spriteMaskId": null, 37 | "visible": true, 38 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/objects/Obj_SampleObject/Obj_SampleObject.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMObject":"", 3 | "%Name":"Obj_SampleObject", 4 | "eventList":[ 5 | {"$GMEvent":"","%Name":"","collisionObjectId":null,"eventNum":0,"eventType":8,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",}, 6 | {"$GMEvent":"","%Name":"","collisionObjectId":null,"eventNum":0,"eventType":0,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",}, 7 | {"$GMEvent":"","%Name":"","collisionObjectId":null,"eventNum":0,"eventType":3,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",}, 8 | {"$GMEvent":"","%Name":"","collisionObjectId":null,"eventNum":76,"eventType":8,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",}, 9 | {"$GMEvent":"","%Name":"","collisionObjectId":null,"eventNum":0,"eventType":12,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",}, 10 | ], 11 | "managed":true, 12 | "name":"Obj_SampleObject", 13 | "overriddenProperties":[], 14 | "parent":{ 15 | "name":"Objects", 16 | "path":"folders/Objects.yy", 17 | }, 18 | "parentObjectId":null, 19 | "persistent":false, 20 | "physicsAngularDamping":0.1, 21 | "physicsDensity":0.5, 22 | "physicsFriction":0.2, 23 | "physicsGroup":1, 24 | "physicsKinematic":false, 25 | "physicsLinearDamping":0.1, 26 | "physicsObject":false, 27 | "physicsRestitution":0.1, 28 | "physicsSensor":false, 29 | "physicsShape":1, 30 | "physicsShapePoints":[], 31 | "physicsStartAwake":true, 32 | "properties":[], 33 | "resourceType":"GMObject", 34 | "resourceVersion":"2.0", 35 | "solid":false, 36 | "spriteId":null, 37 | "spriteMaskId":null, 38 | "visible":true, 39 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/objects/Obj_SampleObjectDF/Obj_SampleObjectDF.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMObject":"", 3 | "%Name":"Obj_SampleObjectDF", 4 | "eventList":[ 5 | {"$GMEvent":"","%Name":"","collisionObjectId":null,"eventNum":0,"eventType":8,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",}, 6 | {"$GMEvent":"","%Name":"","collisionObjectId":null,"eventNum":0,"eventType":0,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",}, 7 | {"$GMEvent":"","%Name":"","collisionObjectId":null,"eventNum":0,"eventType":3,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",}, 8 | {"$GMEvent":"","%Name":"","collisionObjectId":null,"eventNum":76,"eventType":8,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",}, 9 | {"$GMEvent":"","%Name":"","collisionObjectId":null,"eventNum":0,"eventType":12,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",}, 10 | ], 11 | "managed":true, 12 | "name":"Obj_SampleObjectDF", 13 | "overriddenProperties":[], 14 | "parent":{ 15 | "name":"Objects", 16 | "path":"folders/Objects.yy", 17 | }, 18 | "parentObjectId":null, 19 | "persistent":false, 20 | "physicsAngularDamping":0.1, 21 | "physicsDensity":0.5, 22 | "physicsFriction":0.2, 23 | "physicsGroup":1, 24 | "physicsKinematic":false, 25 | "physicsLinearDamping":0.1, 26 | "physicsObject":false, 27 | "physicsRestitution":0.1, 28 | "physicsSensor":false, 29 | "physicsShape":1, 30 | "physicsShapePoints":[], 31 | "physicsStartAwake":true, 32 | "properties":[], 33 | "resourceType":"GMObject", 34 | "resourceVersion":"2.0", 35 | "solid":false, 36 | "spriteId":null, 37 | "spriteMaskId":null, 38 | "visible":true, 39 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/objects/Obj_LineTesting/Draw_0.gml: -------------------------------------------------------------------------------- 1 | draw_set_color(c_dkgray); 2 | 3 | for(var xx = 0; xx < room_width; xx += cell_size;) { 4 | draw_line(xx, 0, xx, room_height); 5 | } 6 | 7 | for(var yy = 0; yy < room_height; yy += cell_size) { 8 | draw_line(0, yy, room_width, yy); 9 | } 10 | 11 | var cpx = x1, cpy = y1; 12 | var px = x1; 13 | var py = y1; 14 | 15 | draw_set_color(c_blue); 16 | draw_line(x1, y1, x2, y2); 17 | 18 | for(var i = 0; i <= steps; i++) { 19 | //////////////////////////////////////////////////////////////////////////// 20 | ///////////////////////////// DRAWING CODE ///////////////////////////////// 21 | var p_cpx = cpx- (cell_size * 0.5), p_cpy = cpy- (cell_size * 0.5); 22 | cpx = (floor(px / cell_size) * cell_size); 23 | cpy = (floor(py / cell_size) * cell_size); 24 | 25 | draw_set_color(c_red); 26 | draw_rectangle(cpx, cpy, cpx + cell_size, cpy + cell_size, false); 27 | 28 | if (p_cpx == cpx && p_cpy == cpy) { 29 | draw_set_color(c_green); 30 | draw_rectangle(cpx, cpy, cpx + cell_size, cpy + cell_size, false); 31 | } 32 | 33 | cpx += (cell_size * 0.5); 34 | cpy += (cell_size * 0.5); 35 | draw_set_color(c_lime); 36 | draw_circle(cpx, cpy, cell_size * 0.125, false); 37 | draw_set_color(c_aqua); 38 | draw_circle(px, py, cell_size * 0.125, false); 39 | //////////////////////////////////////////////////////////////////////////// 40 | 41 | // Line iteration: 42 | px += dx; 43 | py += dy; 44 | } 45 | 46 | var dx1 = abs(dx), dy1 = abs(dy); 47 | var amount = (dx1 < dy1)? dx1/dy1 : dy1/dx1; 48 | draw_set_color(c_white); 49 | draw_text(5, 5, "DELTA-X: " + string(dx1/dy1)); 50 | draw_text(5, 25, "DELTA-Y: " + string(dy1/dx1)); 51 | draw_text(5, 45, "DELTA-z: " + string(amount)); -------------------------------------------------------------------------------- /RadianceCascades/options/windows/options_windows.yy: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "GMWindowsOptions", 3 | "resourceVersion": "1.1", 4 | "name": "Windows", 5 | "option_windows_allow_fullscreen_switching": false, 6 | "option_windows_borderless": false, 7 | "option_windows_company_info": "YoYo Games Ltd", 8 | "option_windows_copy_exe_to_dest": false, 9 | "option_windows_copyright_info": "", 10 | "option_windows_description_info": "A GameMaker Game", 11 | "option_windows_disable_sandbox": false, 12 | "option_windows_display_cursor": true, 13 | "option_windows_display_name": "Created with GameMaker", 14 | "option_windows_enable_steam": false, 15 | "option_windows_executable_name": "${project_name}.exe", 16 | "option_windows_icon": "${base_options_dir}/windows/icons/icon.ico", 17 | "option_windows_installer_finished": "${base_options_dir}/windows/installer/finished.bmp", 18 | "option_windows_installer_header": "${base_options_dir}/windows/installer/header.bmp", 19 | "option_windows_interpolate_pixels": false, 20 | "option_windows_license": "${base_options_dir}/windows/installer/license.txt", 21 | "option_windows_nsis_file": "${base_options_dir}/windows/installer/nsis_script.nsi", 22 | "option_windows_product_info": "Created with GameMaker", 23 | "option_windows_resize_window": false, 24 | "option_windows_save_location": 0, 25 | "option_windows_scale": 0, 26 | "option_windows_sleep_margin": 10, 27 | "option_windows_splash_screen": "${base_options_dir}/windows/splash/splash.png", 28 | "option_windows_start_fullscreen": false, 29 | "option_windows_steam_use_alternative_launcher": false, 30 | "option_windows_texture_page": "2048x2048", 31 | "option_windows_use_splash": false, 32 | "option_windows_version": "1.0.0.0", 33 | "option_windows_vsync": false, 34 | } -------------------------------------------------------------------------------- /RadianceCascades/objects/Obj_RadianceCascades/Draw_76.gml: -------------------------------------------------------------------------------- 1 | if (!surface_exists(gameworld_worldscene)) gameworld_worldscene = surface_create(global.radiance_render_extent, global.radiance_render_extent); 2 | if (!surface_exists(gameworld_temporary)) gameworld_temporary = surface_create(global.radiance_render_extent, global.radiance_render_extent); 3 | if (!surface_exists(gameworld_jumpflood)) gameworld_jumpflood = surface_create(global.radiance_render_extent, global.radiance_render_extent); 4 | if (!surface_exists(gameworld_distancefield)) gameworld_distancefield = surface_create(global.radiance_render_extent, global.radiance_render_extent); 5 | 6 | if (!surface_exists(gameworld_radiance)) gameworld_radiance = surface_create(global.radiance_render_extent, global.radiance_render_extent); 7 | if (!surface_exists(gameworld_bouncescene)) gameworld_bouncescene = surface_create(global.radiance_render_extent, global.radiance_render_extent); 8 | 9 | if (!surface_exists(gameworld_storage)) gameworld_storage = surface_create(global.radiance_cascade_extent, global.radiance_cascade_extent); 10 | 11 | for(var i = 0; i < global.radiance_cascade_count; i++) { 12 | var cascade_extent = global.radiance_cascade_extent; 13 | if (!surface_exists(gameworld_cascades[i])) 14 | gameworld_cascades[i] = surface_create(cascade_extent, cascade_extent); 15 | 16 | radiance_clear(gameworld_cascades[i]); 17 | 18 | var angular_resolution = sqrt(global.radiance_cascade_angular * power(4.0, i)); 19 | var mipmap_extent = global.radiance_cascade_extent / angular_resolution; 20 | //show_debug_message("RESOLUTION[I]: {0} -- {1} : {2} : {3}", i, cascade_extent, mipmap_extent, angular_resolution); 21 | 22 | if (!surface_exists(gameworld_mipmaps[i])) 23 | gameworld_mipmaps[i] = surface_create(mipmap_extent, mipmap_extent); 24 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/options/windows/options_windows.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMWindowsOptions":"", 3 | "%Name":"Windows", 4 | "name":"Windows", 5 | "option_windows_allow_fullscreen_switching":false, 6 | "option_windows_borderless":false, 7 | "option_windows_company_info":"YoYo Games Ltd", 8 | "option_windows_copyright_info":"", 9 | "option_windows_copy_exe_to_dest":false, 10 | "option_windows_description_info":"A GameMaker Game", 11 | "option_windows_disable_sandbox":false, 12 | "option_windows_display_cursor":true, 13 | "option_windows_display_name":"Created with GameMaker", 14 | "option_windows_enable_steam":false, 15 | "option_windows_executable_name":"${project_name}.exe", 16 | "option_windows_icon":"${base_options_dir}/windows/icons/icon.ico", 17 | "option_windows_installer_finished":"${base_options_dir}/windows/installer/finished.bmp", 18 | "option_windows_installer_header":"${base_options_dir}/windows/installer/header.bmp", 19 | "option_windows_interpolate_pixels":false, 20 | "option_windows_license":"${base_options_dir}/windows/installer/license.txt", 21 | "option_windows_nsis_file":"${base_options_dir}/windows/installer/nsis_script.nsi", 22 | "option_windows_product_info":"Created with GameMaker", 23 | "option_windows_resize_window":false, 24 | "option_windows_save_location":0, 25 | "option_windows_scale":0, 26 | "option_windows_sleep_margin":10, 27 | "option_windows_splash_screen":"${base_options_dir}/windows/splash/splash.png", 28 | "option_windows_start_fullscreen":false, 29 | "option_windows_steam_use_alternative_launcher":false, 30 | "option_windows_texture_page":"2048x2048", 31 | "option_windows_use_splash":false, 32 | "option_windows_version":"1.0.0.0", 33 | "option_windows_vsync":false, 34 | "resourceType":"GMWindowsOptions", 35 | "resourceVersion":"2.0", 36 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/options/windows/options_windows.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMWindowsOptions":"", 3 | "%Name":"Windows", 4 | "name":"Windows", 5 | "option_windows_allow_fullscreen_switching":false, 6 | "option_windows_borderless":false, 7 | "option_windows_company_info":"YoYo Games Ltd", 8 | "option_windows_copyright_info":"", 9 | "option_windows_copy_exe_to_dest":false, 10 | "option_windows_description_info":"A GameMaker Game", 11 | "option_windows_disable_sandbox":false, 12 | "option_windows_display_cursor":true, 13 | "option_windows_display_name":"Created with GameMaker", 14 | "option_windows_enable_steam":false, 15 | "option_windows_executable_name":"${project_name}.exe", 16 | "option_windows_icon":"${base_options_dir}/windows/icons/icon.ico", 17 | "option_windows_installer_finished":"${base_options_dir}/windows/installer/finished.bmp", 18 | "option_windows_installer_header":"${base_options_dir}/windows/installer/header.bmp", 19 | "option_windows_interpolate_pixels":false, 20 | "option_windows_license":"${base_options_dir}/windows/installer/license.txt", 21 | "option_windows_nsis_file":"${base_options_dir}/windows/installer/nsis_script.nsi", 22 | "option_windows_product_info":"Created with GameMaker", 23 | "option_windows_resize_window":false, 24 | "option_windows_save_location":0, 25 | "option_windows_scale":0, 26 | "option_windows_sleep_margin":10, 27 | "option_windows_splash_screen":"${base_options_dir}/windows/splash/splash.png", 28 | "option_windows_start_fullscreen":false, 29 | "option_windows_steam_use_alternative_launcher":false, 30 | "option_windows_texture_page":"2048x2048", 31 | "option_windows_use_splash":false, 32 | "option_windows_version":"1.0.0.0", 33 | "option_windows_vsync":false, 34 | "resourceType":"GMWindowsOptions", 35 | "resourceVersion":"2.0", 36 | } -------------------------------------------------------------------------------- /RadianceCascades/shaders/Shd_RadianceMipMap/Shd_RadianceMipMap.fsh: -------------------------------------------------------------------------------- 1 | varying vec2 in_TextCoord; 2 | uniform float in_MipMapExtent; // Cascade MipMap Resolution. 3 | uniform float in_CascadeExtent; // Cascade Diagonal Resolution. 4 | uniform float in_CascadeIndex; // Cascade index. 5 | uniform float in_CascadeAngular; // Cascade angular resolution. 6 | uniform sampler2D in_CascadeAtlas; // MipMap Source Cascade [N]. 7 | 8 | struct ProbeTexel { 9 | float count; 10 | float size; 11 | float probes; 12 | }; 13 | 14 | ProbeTexel cascadeProbeTexel(float cascadeIndex) { 15 | float count = in_CascadeAngular * pow(4.0, cascadeIndex); 16 | float size = sqrt(count); 17 | float probes = in_CascadeExtent / size; 18 | return ProbeTexel(count, size, probes); 19 | } 20 | 21 | // We fetch radiance intervals within the cascade by angle (thetaIndex) and probe (texelIndex). 22 | vec4 cascadeFetch(ProbeTexel info, vec2 texelIndex, float thetaIndex) { 23 | vec2 probeTexel = texelIndex * info.size; 24 | probeTexel += vec2(mod(thetaIndex, info.size), (thetaIndex / info.size)); 25 | vec2 cascadeTexelPosition = probeTexel / in_CascadeExtent; 26 | return texture2D(in_CascadeAtlas, cascadeTexelPosition); 27 | } 28 | 29 | void main() { 30 | // Get the mipmap's cascade texel info based on the cascade being rendered. 31 | ProbeTexel probeInfo = cascadeProbeTexel(in_CascadeIndex); 32 | vec2 mipmapCoord = vec2(in_TextCoord * in_MipMapExtent); 33 | 34 | // Loops through all of the radiance intervals for this mip-map and accumulate. 35 | vec4 radiance = vec4(0.0, 0.0, 0.0, 0.0); 36 | for(float i = 0.0; i < probeInfo.count; i ++) 37 | // cascadeFetch uses the probe's cell index, which is the same as the mipmap's pixel position. 38 | radiance += cascadeFetch(probeInfo, mipmapCoord, i); 39 | 40 | gl_FragColor = vec4(radiance.rgb / probeInfo.count, 1.0); 41 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/objects/Obj_RadianceCascades/Obj_RadianceCascades.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMObject":"", 3 | "%Name":"Obj_RadianceCascades", 4 | "eventList":[ 5 | {"$GMEvent":"","%Name":"","collisionObjectId":null,"eventNum":0,"eventType":0,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",}, 6 | {"$GMEvent":"","%Name":"","collisionObjectId":null,"eventNum":0,"eventType":12,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",}, 7 | {"$GMEvent":"","%Name":"","collisionObjectId":null,"eventNum":76,"eventType":8,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",}, 8 | {"$GMEvent":"","%Name":"","collisionObjectId":null,"eventNum":0,"eventType":3,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",}, 9 | {"$GMEvent":"","%Name":"","collisionObjectId":null,"eventNum":72,"eventType":8,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",}, 10 | {"$GMEvent":"","%Name":"","collisionObjectId":null,"eventNum":73,"eventType":8,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",}, 11 | ], 12 | "managed":true, 13 | "name":"Obj_RadianceCascades", 14 | "overriddenProperties":[], 15 | "parent":{ 16 | "name":"Objects", 17 | "path":"folders/Objects.yy", 18 | }, 19 | "parentObjectId":null, 20 | "persistent":false, 21 | "physicsAngularDamping":0.1, 22 | "physicsDensity":0.5, 23 | "physicsFriction":0.2, 24 | "physicsGroup":1, 25 | "physicsKinematic":false, 26 | "physicsLinearDamping":0.1, 27 | "physicsObject":false, 28 | "physicsRestitution":0.1, 29 | "physicsSensor":false, 30 | "physicsShape":1, 31 | "physicsShapePoints":[], 32 | "physicsStartAwake":true, 33 | "properties":[], 34 | "resourceType":"GMObject", 35 | "resourceVersion":"2.0", 36 | "solid":false, 37 | "spriteId":null, 38 | "spriteMaskId":null, 39 | "visible":true, 40 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/objects/Obj_SampleObjectDF/Step_0.gml: -------------------------------------------------------------------------------- 1 | cascadeIndex += keyboard_check_pressed(vk_right) - keyboard_check_pressed(vk_left); 2 | cascadeIndex = clamp(cascadeIndex, 0, cascadeCount); 3 | current_spacingindex += keyboard_check_pressed(vk_down) - keyboard_check_pressed(vk_up); 4 | current_spacingindex = clamp(current_spacingindex, 0, logn(2, size) - 1); 5 | 6 | current_spacing = spacing * power(2.0, current_spacingindex); 7 | cascade_size = floor(size / current_spacing) * sqrt(angular); 8 | cascadeCount = floor(logn(2, cascade_size / sqrt(angular))) - 1; 9 | 10 | current_angular = sqrt(angular / 4.0) * power(4.0, cascadeIndex); 11 | probeCount = floor(cascade_size / sqrt(current_angular)); 12 | probeSpacing = cascade_size / probeCount; 13 | 14 | current_sectorsize = render_size / sqrt(current_angular); 15 | current_probesize = sqrt(current_angular) * (render_size / cascade_size); 16 | 17 | show_debug_message(string(current_angular) + " >> " + string(current_probesize)); 18 | 19 | if (mouse_check_button(mb_left)) { 20 | current_probex = floor((mouse_x - cascade_offsetx2) / current_probesize) * current_probesize; 21 | current_probey = floor((mouse_y - cascade_offsety2) / current_probesize) * current_probesize; 22 | } 23 | 24 | if (mouse_check_button(mb_right)) { 25 | track_moused = point_direction( 26 | cascade_offsetx2 + current_probex + (current_probesize * 0.5), 27 | cascade_offsety2 + current_probey + (current_probesize * 0.5), 28 | mouse_x, mouse_y); 29 | } 30 | 31 | current_probex = floor(current_probex / current_probesize) * current_probesize; 32 | current_probey = floor(current_probey / current_probesize) * current_probesize; 33 | current_probex = clamp(current_probex, 0, render_size-current_probesize); 34 | current_probey = clamp(current_probey, 0, render_size-current_probesize); 35 | 36 | current_intervalstart = (interval * (1.0 - power(4.0, cascadeIndex))) / (1.0 - 4.0); 37 | current_interval = interval * power(4.0, cascadeIndex); 38 | 39 | if (keyboard_check_pressed(vk_space)) { 40 | instance_destroy(self); 41 | instance_create_depth(x, y, depth, Obj_SampleObject); 42 | } -------------------------------------------------------------------------------- /RadianceCascades/RadianceCascades.resource_order: -------------------------------------------------------------------------------- 1 | { 2 | "FolderOrderSettings": [ 3 | {"name":"Animation Curves","order":12,"path":"folders/Animation Curves.yy",}, 4 | {"name":"Extensions","order":14,"path":"folders/Extensions.yy",}, 5 | {"name":"Fonts","order":7,"path":"folders/Fonts.yy",}, 6 | {"name":"Notes","order":13,"path":"folders/Notes.yy",}, 7 | {"name":"Objects","order":9,"path":"folders/Objects.yy",}, 8 | {"name":"Particle Systems","order":15,"path":"folders/Particle Systems.yy",}, 9 | {"name":"Paths","order":4,"path":"folders/Paths.yy",}, 10 | {"name":"Rooms","order":10,"path":"folders/Rooms.yy",}, 11 | {"name":"Scripts","order":5,"path":"folders/Scripts.yy",}, 12 | {"name":"Sequences","order":11,"path":"folders/Sequences.yy",}, 13 | {"name":"Shaders","order":6,"path":"folders/Shaders.yy",}, 14 | {"name":"Sounds","order":3,"path":"folders/Sounds.yy",}, 15 | {"name":"Sprites","order":1,"path":"folders/Sprites.yy",}, 16 | {"name":"Tile Sets","order":2,"path":"folders/Tile Sets.yy",}, 17 | {"name":"Timelines","order":8,"path":"folders/Timelines.yy",}, 18 | ], 19 | "ResourceOrderSettings": [ 20 | {"name":"Shd_JumpfloodSeed","order":1,"path":"shaders/Shd_JumpfloodSeed/Shd_JumpfloodSeed.yy",}, 21 | {"name":"Shd_RadianceMipMap","order":6,"path":"shaders/Shd_RadianceMipMap/Shd_RadianceMipMap.yy",}, 22 | {"name":"Shd_DistanceField","order":2,"path":"shaders/Shd_DistanceField/Shd_DistanceField.yy",}, 23 | {"name":"Shd_JumpfloodAlgorithm","order":3,"path":"shaders/Shd_JumpfloodAlgorithm/Shd_JumpfloodAlgorithm.yy",}, 24 | {"name":"Shd_RadianceIntervals","order":4,"path":"shaders/Shd_RadianceIntervals/Shd_RadianceIntervals.yy",}, 25 | {"name":"Spr_SampleScene","order":1,"path":"sprites/Spr_SampleScene/Spr_SampleScene.yy",}, 26 | {"name":"Obj_RadianceCascades","order":2,"path":"objects/Obj_RadianceCascades/Obj_RadianceCascades.yy",}, 27 | {"name":"Scr_RadianceCascades","order":2,"path":"scripts/Scr_RadianceCascades/Scr_RadianceCascades.yy",}, 28 | {"name":"Shd_RadianceMerging","order":5,"path":"shaders/Shd_RadianceMerging/Shd_RadianceMerging.yy",}, 29 | ], 30 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/RadianceCascades-Optimized.resource_order: -------------------------------------------------------------------------------- 1 | { 2 | "FolderOrderSettings":[ 3 | {"name":"Animation Curves","order":12,"path":"folders/Animation Curves.yy",}, 4 | {"name":"Extensions","order":14,"path":"folders/Extensions.yy",}, 5 | {"name":"Fonts","order":7,"path":"folders/Fonts.yy",}, 6 | {"name":"Notes","order":13,"path":"folders/Notes.yy",}, 7 | {"name":"Objects","order":9,"path":"folders/Objects.yy",}, 8 | {"name":"Particle Systems","order":15,"path":"folders/Particle Systems.yy",}, 9 | {"name":"Paths","order":4,"path":"folders/Paths.yy",}, 10 | {"name":"Rooms","order":10,"path":"folders/Rooms.yy",}, 11 | {"name":"Scripts","order":5,"path":"folders/Scripts.yy",}, 12 | {"name":"Sequences","order":11,"path":"folders/Sequences.yy",}, 13 | {"name":"Shaders","order":6,"path":"folders/Shaders.yy",}, 14 | {"name":"Sounds","order":3,"path":"folders/Sounds.yy",}, 15 | {"name":"Sprites","order":1,"path":"folders/Sprites.yy",}, 16 | {"name":"Tile Sets","order":2,"path":"folders/Tile Sets.yy",}, 17 | {"name":"Timelines","order":8,"path":"folders/Timelines.yy",}, 18 | ], 19 | "ResourceOrderSettings":[ 20 | {"name":"Obj_LineTesting","order":1,"path":"objects/Obj_LineTesting/Obj_LineTesting.yy",}, 21 | {"name":"Shd_DistanceField","order":2,"path":"shaders/Shd_DistanceField/Shd_DistanceField.yy",}, 22 | {"name":"Shd_JumpFlood","order":1,"path":"shaders/Shd_JumpFlood/Shd_JumpFlood.yy",}, 23 | {"name":"Shd_RadianceCascades_BilinearFix","order":7,"path":"shaders/Shd_RadianceCascades_BilinearFix/Shd_RadianceCascades_BilinearFix.yy",}, 24 | {"name":"Shd_RadianceCascades_Final","order":5,"path":"shaders/Shd_RadianceCascades_Final/Shd_RadianceCascades_Final.yy",}, 25 | {"name":"Shd_RadianceCascades_FPFixed","order":4,"path":"shaders/Shd_RadianceCascades_FPFixed/Shd_RadianceCascades_FPFixed.yy",}, 26 | {"name":"Shd_RadianceCascades_InterlacedFix","order":6,"path":"shaders/Shd_RadianceCascades_InterlacedFix/Shd_RadianceCascades_InterlacedFix.yy",}, 27 | {"name":"Shd_RadianceCascades_NearestFix","order":9,"path":"shaders/Shd_RadianceCascades_NearestFix/Shd_RadianceCascades_NearestFix.yy",}, 28 | {"name":"Shd_SeedJumpFlood","order":3,"path":"shaders/Shd_SeedJumpFlood/Shd_SeedJumpFlood.yy",}, 29 | ], 30 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Radiance-Cascades [GMShaders](https://mini.gmshaders.com/p/radiance-cascades2) 2 | A 2D implementation of Radiance Cascades by [Alexander Sannikov](https://drive.google.com/file/d/1L6v1_7HY2X-LV3Ofb6oyTIxgEaP4LOI6/view) based on fad's implementation from [Shadertoy](https://www.shadertoy.com/view/mtlBzX). This particular repository is for the GM Shaders deep dive into my [Radiance Cascades](https://github.com/Yaazarai/RadianceCascades) demonstration. 3 | 4 | 5 | #1 (Default) Visual Demo showing Probe Spacing and Cascade Ray Mapping: position-first probes (rays grouped by probe position) 6 | 7 | https://github.com/Yaazarai/GMShaders-Radiance-Cascades/assets/7478702/69cbc31e-2b17-4642-bf81-666b843d51a1 8 | 9 | #2 (Optimized) Visual Demo showing Probe Spacing and Cascade Ray Mapping: direction-first (rays grouped by ray direction) 10 | 11 | https://github.com/Yaazarai/GMShaders-Radiance-Cascades/assets/7478702/d17a705c-8b03-4a50-ad4b-d34d26f7d879 12 | 13 | 14 | 15 | https://github.com/Yaazarai/GMShaders-Radiance-Cascades/assets/7478702/73df7cea-ef45-4ebc-8a9e-dbc8ca0e4cec 16 | 17 | 18 | Bilinear-Fix: Casts 4x rays , one reprojected to the rays of each cN+1 bilinear probe before merging and interpolating. This reduces interpolation artifacts and fixes occlusion since merged rays are now perfectly continuous. 19 | ![image](https://github.com/user-attachments/assets/b117e3ec-65f9-4565-886b-7a1df3b34b9d) 20 | 21 | Nearest--Fix: Casts one reprojected ray to the rays of only the nearest cN+1 bilinear probe. Since we're using only one bilinear-probe this causes pixelation due to 2x2 groups of cN probes sharing the same cN+1 bilinear probe. The 2x2 groups issue is because each cascade has 1/2 as many probes each axis or 1 probe per 2x2 probes in the previous cascade. 22 | ![image](https://github.com/user-attachments/assets/343a0882-617e-4c9a-b8b9-2ea6667f84b0) 23 | 24 | Nearest-Interlaced-Fix: Same as Nearest-Fix however bilinear-probes are interlaced such that no adjacent cN probes share the same cN+1 bilinear-probe. This produces stylistic dithering artifacts while solving ringing and occlusion. By interlaced I just mean I've shifted which bilinear probe is considered "nearest." 25 | ![image](https://github.com/user-attachments/assets/b0aa2b35-f4da-40ca-af36-02a9b39a845e) 26 | 27 | Vanilla: provided for reference no ringing or occlusion fixes. 28 | ![image](https://github.com/user-attachments/assets/045dc791-e237-4746-a8bf-63c4c5b7e78e) 29 | -------------------------------------------------------------------------------- /RadianceCascades/objects/Obj_RadianceCascades/Draw_73.gml: -------------------------------------------------------------------------------- 1 | // Disable blending for Jump Flood render processes (we don't care about alpha components here). 2 | surface_set_target(gameworld_bouncescene); 3 | draw_surface(gameworld_radiance, 0, 0); 4 | draw_set_color(c_white); 5 | draw_set_alpha(1.0); 6 | draw_surface(gameworld_worldscene, 0, 0); 7 | surface_reset_target(); 8 | 9 | gpu_set_blendenable(false); 10 | gpu_set_texrepeat(false); 11 | 12 | // Generate the JFA + SDF of the world scene. 13 | radiance_jfaseed(gameworld_worldscene, gameworld_temporary, gameworld_jumpflood); 14 | radiance_jumpflood(gameworld_temporary, gameworld_jumpflood); 15 | radiance_distancefield(gameworld_jumpflood, gameworld_distancefield); 16 | radiance_clear(gameworld_storage); 17 | 18 | // Calculate initial Radiance Intervals. 19 | radiancecascades_intervals(gameworld_bouncescene, gameworld_distancefield, gameworld_cascades, gameworld_storage); 20 | 21 | // Merged Radiance Intervals from Cascades. 22 | radiancecascades_merging(gameworld_cascades, gameworld_storage); 23 | 24 | // Generate Cascade[N] mip-map (debugging visualization). 25 | radiancecascades_mipmap(gameworld_cascades, gameworld_mipmaps); 26 | 27 | // Generate Screen Radiance from Merged Cascade mip-map. 28 | //radiancecascades_screenmerge(gameworld_radiance, gameworld_temporary, gameworld_mipmaps); 29 | 30 | // Re-Enable Alpha Blending since the Jump Flood pass is complete. 31 | gpu_set_blendenable(true); 32 | 33 | //draw_surface(gameworld_worldscene, 0, 0); 34 | //draw_surface(gameworld_jumpflood, 0, 0); 35 | //draw_surface(gameworld_distancefield, 0, 0); 36 | draw_surface(gameworld_radiance, 0, 0); 37 | 38 | //var xscale = global.radiance_render_extent / global.radiance_cascade_extent; 39 | //var yscale = global.radiance_render_extent / global.radiance_cascade_extent; 40 | //draw_surface_ext(gameworld_cascades[global.showcascade], 0, 0, xscale, yscale, 0, c_white, 1); 41 | 42 | surface_set_target(gameworld_radiance); 43 | draw_clear_alpha(c_black, 0); 44 | gpu_set_blendmode(bm_add); 45 | var xscale = global.radiance_render_extent / surface_get_width(gameworld_mipmaps[global.showcascade]); 46 | var yscale = global.radiance_render_extent / surface_get_height(gameworld_mipmaps[global.showcascade]); 47 | gpu_set_tex_mip_filter(tf_linear); 48 | draw_surface_ext(gameworld_mipmaps[global.showcascade], 0, 0, xscale, yscale, 0, c_white, 1.0); 49 | draw_surface_ext(gameworld_mipmaps[global.showcascade], 0, 0, xscale, yscale, 0, c_white, 0.5); 50 | gpu_set_blendmode(bm_normal); 51 | surface_reset_target(); 52 | 53 | draw_surface(gameworld_radiance, 0, 0); -------------------------------------------------------------------------------- /RadianceCascades-Optimized/objects/Obj_RadianceCascades/Draw_73.gml: -------------------------------------------------------------------------------- 1 | var gpu_blend = gpu_get_blendenable(); 2 | var gpu_texrepeat = gpu_get_tex_repeat(); 3 | var gpu_filter = gpu_get_tex_filter(); 4 | 5 | gpu_set_blendenable(false); 6 | gpu_set_texrepeat(false); 7 | gpu_set_tex_filter(true); 8 | 9 | // Calculate scene JFA and output SDF. 10 | radiance_jfaseed(radiance_world.memory, radiance_jfa.memory, radiance_sdf.memory, Shd_SeedJumpFlood); 11 | radiance_jumpflood(radiance_sdf.memory, radiance_jfa.memory, Shd_JumpFlood, radiance_u_jumpflood_uRenderExtent, radiance_u_jumpflood_uJumpDistance, render_width, render_height); 12 | radiance_distancefield(radiance_jfa.memory, radiance_sdf.memory, Shd_DistanceField, radiance_u_distancefield_uRenderExtent, render_width, render_height); 13 | 14 | // Loop through all cascades in reverse and merge radiance down the cascades (one pass merge and interval). 15 | for(var n = radiance_cascades - 1; n >= 0; n--) { 16 | shader_set(radiance_u_cascades); 17 | shader_texture(radiance_u_cascades_RenderScene, radiance_world.memory); 18 | shader_texture(radiance_u_cascades_DistanceField, radiance_sdf.memory); 19 | shader_vec2(radiance_u_cascades_RenderExtent, render_width, render_height); 20 | shader_vec2(radiance_u_cascades_CascadeExtent, radiance_width, radiance_height); 21 | shader_float(radiance_u_cascades_CascadeCount, radiance_cascades); 22 | shader_float(radiance_u_cascades_CascadeIndex, cascade_index + n); 23 | shader_float(radiance_u_cascades_CascadeLinear, radiance_linear); 24 | shader_float(radiance_u_cascades_CascadeInterval, radiance_interval); 25 | // Render the current cascade... 26 | surface_set_target(radiance_current.memory); 27 | draw_clear_alpha(c_black, 0); 28 | // Pass in the previous cascade... 29 | draw_surface(radiance_previous.memory, 0, 0); 30 | surface_reset_target(); 31 | shader_reset(); 32 | 33 | // Set current cascade as previous after rendering to prep for next cascade... 34 | surface_set_target(radiance_previous.memory); 35 | draw_clear_alpha(c_black, 0); 36 | draw_surface(radiance_current.memory, 0, 0); 37 | surface_reset_target(); 38 | } 39 | 40 | gpu_set_blendenable(gpu_blend); 41 | gpu_set_texrepeat(gpu_texrepeat); 42 | gpu_set_tex_filter(gpu_filter); 43 | 44 | //gpu_set_blendmode(bm_add); 45 | var xscale = render_width / radiance_width; 46 | var yscale = render_height / radiance_height; 47 | draw_surface_ext(surface_source(radiance_current), 0, 0, xscale, yscale, 0, c_white, 1.0); 48 | //draw_surface_ext(surface_source(radiance_current), 0, 0, xscale, yscale, 0, c_white, 1.0); 49 | //gpu_set_blendmode(bm_normal); 50 | 51 | draw_set_color(c_yellow); 52 | draw_text(5, 5, "Frame Time: " + string(delta_time / 1000) + " / " + string(1000 * (1.0/game_get_speed(gamespeed_fps)))); 53 | draw_set_color(c_white); -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_RadianceCascades_Final/Shd_RadianceCascades_Final.fsh: -------------------------------------------------------------------------------- 1 | varying vec2 in_TexelCoord; 2 | uniform sampler2D in_RenderScene; 3 | uniform sampler2D in_DistanceField; 4 | uniform vec2 in_RenderExtent; 5 | uniform vec2 in_CascadeExtent; 6 | uniform float in_CascadeCount; 7 | uniform float in_CascadeIndex; 8 | uniform float in_CascadeLinear; 9 | uniform float in_CascadeInterval; 10 | 11 | #define TAU 6.283185 12 | #define V2F16(v) ((v.y * float(0.0039215689)) + v.x) 13 | #define SRGB(c) pow(c.rgb, vec3(2.2)) 14 | #define LINEAR(c) pow(c.rgb, vec3(1.0 / 2.2)) 15 | 16 | vec4 raymarch(vec2 origin, vec2 delta, float interval) { 17 | for(float ii = 0.0, dd = 0.0, rr = 0.0, ee = 0.0001, scale = length(in_RenderExtent); ii < interval; ii++) { 18 | vec2 ray = (origin + (delta * rr)) * (1.0 / in_RenderExtent); 19 | rr += scale * (dd = V2F16(texture2D(in_DistanceField, ray).rg)); 20 | if (rr >= interval || floor(ray) != vec2(0.0)) break; 21 | if (dd <= ee) return vec4(SRGB(texture2D(in_RenderScene, ray).rgb), 0.0); 22 | } 23 | return vec4(0.0, 0.0, 0.0, 1.0); 24 | } 25 | 26 | vec4 merge(vec4 radiance, float index, vec2 extent, vec2 probe) { 27 | if (radiance.a == 0.0 || in_CascadeIndex >= in_CascadeCount - 1.0) 28 | return vec4(radiance.rgb, 1.0 - radiance.a); 29 | float angularN1 = pow(2.0, floor(in_CascadeIndex + 1.0)); 30 | vec2 extentN1 = floor(in_CascadeExtent / angularN1); 31 | vec2 interpN1 = vec2(mod(index, angularN1), floor(index / angularN1)) * extentN1; 32 | interpN1 += clamp((probe * 0.5) + 0.25, vec2(0.5), extentN1 - 0.5); 33 | return radiance + texture2D(gm_BaseTexture, interpN1 * (1.0 / in_CascadeExtent)); 34 | } 35 | 36 | void main() { 37 | vec2 coord = floor(in_TexelCoord * in_CascadeExtent); 38 | float sqr_angular = pow(2.0, floor(in_CascadeIndex)); 39 | vec2 extent = floor(in_CascadeExtent / sqr_angular); 40 | vec4 probe = vec4(mod(coord, extent), floor(coord / extent)); 41 | float interval = (1.0 - pow(4.0, in_CascadeIndex)) / (1.0 - 4.0); 42 | interval *= in_CascadeInterval; 43 | vec2 linear = vec2(in_CascadeLinear * pow(2.0, in_CascadeIndex)); 44 | float limit = (in_CascadeInterval * pow(4.0, in_CascadeIndex));// + length(linear * 2.0); 45 | 46 | //float interval = 1.0 * pow(4.0, in_CascadeIndex) * sign(in_CascadeIndex); 47 | //float limit = 1.0 * pow(4.0, in_CascadeIndex + 1.0); 48 | 49 | vec2 origin = (probe.xy + 0.5) * linear; 50 | float angular = sqr_angular * sqr_angular * 4.0; 51 | float index = (probe.z + (probe.w * sqr_angular)) * 4.0; 52 | 53 | gl_FragColor = vec4(0.0); 54 | for(float i = 0.0; i < 4.0; i++) { 55 | float preavg = index + float(i); 56 | float theta = (preavg + 0.5) * (TAU / angular); 57 | vec2 delta = vec2(cos(theta), -sin(theta)); 58 | vec2 ray = origin + (delta * interval); 59 | vec4 radiance = raymarch(ray, delta, limit); 60 | gl_FragColor += merge(radiance, preavg, extent, probe.xy) * 0.25; 61 | } 62 | 63 | if (in_CascadeIndex == 0.0) 64 | gl_FragColor = vec4(LINEAR(gl_FragColor), 1.0); 65 | } 66 | -------------------------------------------------------------------------------- /RadianceCascades/sprites/Spr_SampleScene/Spr_SampleScene.yy: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "GMSprite", 3 | "resourceVersion": "1.0", 4 | "name": "Spr_SampleScene", 5 | "bbox_bottom": 1023, 6 | "bbox_left": 0, 7 | "bbox_right": 1023, 8 | "bbox_top": 0, 9 | "bboxMode": 0, 10 | "collisionKind": 1, 11 | "collisionTolerance": 0, 12 | "DynamicTexturePage": false, 13 | "edgeFiltering": false, 14 | "For3D": false, 15 | "frames": [ 16 | {"resourceType":"GMSpriteFrame","resourceVersion":"1.1","name":"b3ab27c2-5f95-4653-bf0c-4379701177f5",}, 17 | ], 18 | "gridX": 0, 19 | "gridY": 0, 20 | "height": 1024, 21 | "HTile": false, 22 | "layers": [ 23 | {"resourceType":"GMImageLayer","resourceVersion":"1.0","name":"0d7662ca-3478-4bf6-a097-69be1c00c353","blendMode":0,"displayName":"default","isLocked":false,"opacity":100.0,"visible":true,}, 24 | ], 25 | "nineSlice": null, 26 | "origin": 0, 27 | "parent": { 28 | "name": "Sprites", 29 | "path": "folders/Sprites.yy", 30 | }, 31 | "preMultiplyAlpha": false, 32 | "sequence": { 33 | "resourceType": "GMSequence", 34 | "resourceVersion": "1.4", 35 | "name": "Spr_SampleScene", 36 | "autoRecord": true, 37 | "backdropHeight": 768, 38 | "backdropImageOpacity": 0.5, 39 | "backdropImagePath": "", 40 | "backdropWidth": 1366, 41 | "backdropXOffset": 0.0, 42 | "backdropYOffset": 0.0, 43 | "events": {"resourceType":"KeyframeStore","resourceVersion":"1.0","Keyframes":[],}, 44 | "eventStubScript": null, 45 | "eventToFunction": {}, 46 | "length": 1.0, 47 | "lockOrigin": false, 48 | "moments": {"resourceType":"KeyframeStore","resourceVersion":"1.0","Keyframes":[],}, 49 | "playback": 1, 50 | "playbackSpeed": 30.0, 51 | "playbackSpeedType": 0, 52 | "showBackdrop": true, 53 | "showBackdropImage": false, 54 | "timeUnits": 1, 55 | "tracks": [ 56 | {"resourceType":"GMSpriteFramesTrack","resourceVersion":"1.0","name":"frames","builtinName":0,"events":[],"inheritsTrackColour":true,"interpolation":1,"isCreationTrack":false,"keyframes":{"resourceType":"KeyframeStore","resourceVersion":"1.0","Keyframes":[ 57 | {"resourceType":"Keyframe","resourceVersion":"1.0","Channels":{"0":{"resourceType":"SpriteFrameKeyframe","resourceVersion":"1.0","Id":{"name":"b3ab27c2-5f95-4653-bf0c-4379701177f5","path":"sprites/Spr_SampleScene/Spr_SampleScene.yy",},},},"Disabled":false,"id":"4568c303-27c8-4f41-a5eb-6ca3ad055ea0","IsCreationKey":false,"Key":0.0,"Length":1.0,"Stretch":false,}, 58 | ],},"modifiers":[],"spriteId":null,"trackColour":0,"tracks":[],"traits":0,}, 59 | ], 60 | "visibleRange": null, 61 | "volume": 1.0, 62 | "xorigin": 0, 63 | "yorigin": 0, 64 | }, 65 | "swatchColours": null, 66 | "swfPrecision": 2.525, 67 | "textureGroupId": { 68 | "name": "Default", 69 | "path": "texturegroups/Default", 70 | }, 71 | "type": 0, 72 | "VTile": false, 73 | "width": 1024, 74 | } -------------------------------------------------------------------------------- /RadianceCascades/options/ios/options_ios.yy: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "GMiOSOptions", 3 | "resourceVersion": "1.3", 4 | "name": "iOS", 5 | "option_ios_bundle_name": "com.company.game", 6 | "option_ios_cocoapods_checkbox": true, 7 | "option_ios_defer_home_indicator": false, 8 | "option_ios_devices": 2, 9 | "option_ios_display_name": "Created with GameMaker", 10 | "option_ios_half_ipad1_textures": false, 11 | "option_ios_icon_ipad_app_152": "${base_options_dir}/ios/icons/app/ipad_152.png", 12 | "option_ios_icon_ipad_app_76": "${base_options_dir}/ios/icons/app/ipad_76.png", 13 | "option_ios_icon_ipad_notification_20": "${base_options_dir}/ios/icons/notification/ipad_20.png", 14 | "option_ios_icon_ipad_notification_40": "${base_options_dir}/ios/icons/notification/ipad_40.png", 15 | "option_ios_icon_ipad_pro_app_167": "${base_options_dir}/ios/icons/app/ipad_pro_167.png", 16 | "option_ios_icon_ipad_settings_29": "${base_options_dir}/ios/icons/settings/ipad_29.png", 17 | "option_ios_icon_ipad_settings_58": "${base_options_dir}/ios/icons/settings/ipad_58.png", 18 | "option_ios_icon_ipad_spotlight_40": "${base_options_dir}/ios/icons/spotlight/ipad_40.png", 19 | "option_ios_icon_ipad_spotlight_80": "${base_options_dir}/ios/icons/spotlight/ipad_80.png", 20 | "option_ios_icon_iphone_app_120": "${base_options_dir}/ios/icons/app/iphone_120.png", 21 | "option_ios_icon_iphone_app_180": "${base_options_dir}/ios/icons/app/iphone_180.png", 22 | "option_ios_icon_iphone_notification_40": "${base_options_dir}/ios/icons/notification/iphone_40.png", 23 | "option_ios_icon_iphone_notification_60": "${base_options_dir}/ios/icons/notification/iphone_60.png", 24 | "option_ios_icon_iphone_settings_58": "${base_options_dir}/ios/icons/settings/iphone_58.png", 25 | "option_ios_icon_iphone_settings_87": "${base_options_dir}/ios/icons/settings/iphone_87.png", 26 | "option_ios_icon_iphone_spotlight_120": "${base_options_dir}/ios/icons/spotlight/iphone_120.png", 27 | "option_ios_icon_iphone_spotlight_80": "${base_options_dir}/ios/icons/spotlight/iphone_80.png", 28 | "option_ios_icon_itunes_artwork_1024": "${base_options_dir}/ios/icons/itunes/itunes_1024.png", 29 | "option_ios_interpolate_pixels": false, 30 | "option_ios_launchscreen_fill": 0, 31 | "option_ios_launchscreen_image": "${base_options_dir}/ios/splash/launchscreen.png", 32 | "option_ios_launchscreen_image_landscape": "${base_options_dir}/ios/splash/launchscreen-landscape.png", 33 | "option_ios_min_version": "10.0", 34 | "option_ios_orientation_landscape": true, 35 | "option_ios_orientation_landscape_flipped": true, 36 | "option_ios_orientation_portrait": true, 37 | "option_ios_orientation_portrait_flipped": true, 38 | "option_ios_output_dir": "~/gamemakerstudio2", 39 | "option_ios_podfile_lock_path": "${options_dir}/ios/Podfile.lock", 40 | "option_ios_podfile_path": "${options_dir}/ios/Podfile", 41 | "option_ios_scale": 0, 42 | "option_ios_splashscreen_background_colour": 255, 43 | "option_ios_team_id": "", 44 | "option_ios_texture_page": "2048x2048", 45 | "option_ios_version": "1.0.0.0", 46 | } -------------------------------------------------------------------------------- /RadianceCascades/sprites/Spr_VisualizeRadianceIntervals/Spr_VisualizeRadianceIntervals.yy: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "GMSprite", 3 | "resourceVersion": "1.0", 4 | "name": "Spr_VisualizeRadianceIntervals", 5 | "bbox_bottom": 511, 6 | "bbox_left": 0, 7 | "bbox_right": 511, 8 | "bbox_top": 0, 9 | "bboxMode": 0, 10 | "collisionKind": 1, 11 | "collisionTolerance": 0, 12 | "DynamicTexturePage": false, 13 | "edgeFiltering": false, 14 | "For3D": false, 15 | "frames": [ 16 | {"resourceType":"GMSpriteFrame","resourceVersion":"1.1","name":"f8390388-9411-4b3b-a96e-6101133fe64f",}, 17 | ], 18 | "gridX": 0, 19 | "gridY": 0, 20 | "height": 512, 21 | "HTile": false, 22 | "layers": [ 23 | {"resourceType":"GMImageLayer","resourceVersion":"1.0","name":"a2fde448-e5ce-4944-b09d-cff5f9b505fc","blendMode":0,"displayName":"default","isLocked":false,"opacity":100.0,"visible":true,}, 24 | ], 25 | "nineSlice": null, 26 | "origin": 0, 27 | "parent": { 28 | "name": "Sprites", 29 | "path": "folders/Sprites.yy", 30 | }, 31 | "preMultiplyAlpha": false, 32 | "sequence": { 33 | "resourceType": "GMSequence", 34 | "resourceVersion": "1.4", 35 | "name": "Spr_VisualizeRadianceIntervals", 36 | "autoRecord": true, 37 | "backdropHeight": 768, 38 | "backdropImageOpacity": 0.5, 39 | "backdropImagePath": "", 40 | "backdropWidth": 1366, 41 | "backdropXOffset": 0.0, 42 | "backdropYOffset": 0.0, 43 | "events": {"resourceType":"KeyframeStore","resourceVersion":"1.0","Keyframes":[],}, 44 | "eventStubScript": null, 45 | "eventToFunction": {}, 46 | "length": 1.0, 47 | "lockOrigin": false, 48 | "moments": {"resourceType":"KeyframeStore","resourceVersion":"1.0","Keyframes":[],}, 49 | "playback": 1, 50 | "playbackSpeed": 30.0, 51 | "playbackSpeedType": 0, 52 | "showBackdrop": true, 53 | "showBackdropImage": false, 54 | "timeUnits": 1, 55 | "tracks": [ 56 | {"resourceType":"GMSpriteFramesTrack","resourceVersion":"1.0","name":"frames","builtinName":0,"events":[],"inheritsTrackColour":true,"interpolation":1,"isCreationTrack":false,"keyframes":{"resourceType":"KeyframeStore","resourceVersion":"1.0","Keyframes":[ 57 | {"resourceType":"Keyframe","resourceVersion":"1.0","Channels":{"0":{"resourceType":"SpriteFrameKeyframe","resourceVersion":"1.0","Id":{"name":"f8390388-9411-4b3b-a96e-6101133fe64f","path":"sprites/Spr_VisualizeRadianceIntervals/Spr_VisualizeRadianceIntervals.yy",},},},"Disabled":false,"id":"7eb7b798-6132-4438-9024-5f9576a7206e","IsCreationKey":false,"Key":0.0,"Length":1.0,"Stretch":false,}, 58 | ],},"modifiers":[],"spriteId":null,"trackColour":0,"tracks":[],"traits":0,}, 59 | ], 60 | "visibleRange": null, 61 | "volume": 1.0, 62 | "xorigin": 0, 63 | "yorigin": 0, 64 | }, 65 | "swatchColours": null, 66 | "swfPrecision": 2.525, 67 | "textureGroupId": { 68 | "name": "Default", 69 | "path": "texturegroups/Default", 70 | }, 71 | "type": 0, 72 | "VTile": false, 73 | "width": 512, 74 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/objects/Obj_MergingSample/Draw_0.gml: -------------------------------------------------------------------------------- 1 | draw_set_color(c_yellow); 2 | 3 | draw_circle(offsetN1X, offsetN1Y, radiusN * 2, true); 4 | draw_circle(offsetN1X + box_sizeN1, offsetN1Y, radiusN * 2, true); 5 | draw_circle(offsetN1X, offsetN1Y + box_sizeN1, radiusN * 2, true); 6 | draw_circle(offsetN1X + box_sizeN1, offsetN1Y + box_sizeN1, radiusN * 2, true); 7 | 8 | shader_set(Shd_Bilinear); 9 | shader_set_uniform_f(shader_get_uniform(Shd_Bilinear, "colorTL"), 1, 0, 1, 1); 10 | shader_set_uniform_f(shader_get_uniform(Shd_Bilinear, "colorTR"), 0, 1, 0, 1); 11 | shader_set_uniform_f(shader_get_uniform(Shd_Bilinear, "colorBL"), 0, 0, 1, 1); 12 | shader_set_uniform_f(shader_get_uniform(Shd_Bilinear, "colorBR"), 1, 1, 1, 1); 13 | var xscale = box_sizeN1 / sprite_get_width(Spr_SampleSprite); 14 | var yscale = box_sizeN1 / sprite_get_height(Spr_SampleSprite); 15 | draw_sprite_ext(Spr_SampleSprite, 0, offsetN1X, offsetN1Y, xscale, yscale, 0, c_white, 1); 16 | shader_reset(); 17 | 18 | for(var i = 0; i < 4; i++) { 19 | for(var j = 0; j < 4; j++) { 20 | draw_set_color(c_red); 21 | draw_circle(offsetNX + box_sizeN + (box_sizeN * i), offsetNY + (box_sizeN * j), radiusN, true); 22 | 23 | if (i == 2 && j == 1) { 24 | draw_set_color(c_black); 25 | draw_circle(offsetNX + box_sizeN + (box_sizeN * i), offsetNY + (box_sizeN * j), radiusN+1, false); 26 | draw_set_color(colorMR); 27 | draw_circle(offsetNX + box_sizeN + (box_sizeN * i), offsetNY + (box_sizeN * j), radiusN-1, false); 28 | } 29 | } 30 | } 31 | 32 | var dNx1, dNy1, dNx2, dNy2, dNt, posNx, posNx; 33 | dNt = (0.5 / angularN) * 2.0 * pi; 34 | dNx1 = lengthdir_x(radiusN, radtodeg(dNt)); 35 | dNy1 = lengthdir_y(radiusN, radtodeg(dNt)); 36 | dNx2 = lengthdir_x(radiusN + intervalN, radtodeg(dNt)); 37 | dNy2 = lengthdir_y(radiusN + intervalN, radtodeg(dNt)); 38 | posNx = offsetNX + box_sizeN + (box_sizeN * 2); 39 | posNy = offsetNY + (box_sizeN * 1); 40 | 41 | draw_set_color(c_black); 42 | draw_line_width( 43 | posNx + dNx1, 44 | posNy + dNy1, 45 | posNx + dNx2, 46 | posNy + dNy2, 8); 47 | draw_set_color(colorMR); 48 | draw_line_width( 49 | posNx + dNx1, 50 | posNy + dNy1, 51 | posNx + dNx2, 52 | posNy + dNy2, 6); 53 | 54 | for(var i = 0; i < 2; i++) { 55 | for(var j = 0; j < 2; j++) { 56 | var posx = offsetN1X + (box_sizeN1 * i); 57 | var posy = offsetN1Y + (box_sizeN1 * j); 58 | 59 | for(var r = 0; r < angularN1; r++) { 60 | var dx1, dy1, dx2, dy2, dt; 61 | dt = ((r + 0.5) / angularN1) * 2.0 * pi; 62 | dx1 = lengthdir_x((radiusN * 2), radtodeg(dt)); 63 | dy1 = lengthdir_y((radiusN * 2), radtodeg(dt)); 64 | dx2 = lengthdir_x((radiusN * 2) + intervalN1, radtodeg(dt)); 65 | dy2 = lengthdir_y((radiusN * 2) + intervalN1, radtodeg(dt)); 66 | 67 | switch((i * 2) + j) { 68 | case 0: draw_set_color(colorTL); break; 69 | case 1: draw_set_color(colorBL); break; 70 | case 2: draw_set_color(colorTR); break; 71 | case 3: draw_set_color(colorBR); break; 72 | } 73 | 74 | draw_line_width( 75 | posx + dx1, 76 | posy + dy1, 77 | posx + dx2, 78 | posy + dy2, 6); 79 | 80 | if (r == 3) break; 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/options/ios/options_ios.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMiOSOptions":"", 3 | "%Name":"iOS", 4 | "name":"iOS", 5 | "option_ios_build_number":0, 6 | "option_ios_bundle_name":"com.company.game", 7 | "option_ios_cocoapods_checkbox":true, 8 | "option_ios_defer_home_indicator":false, 9 | "option_ios_devices":2, 10 | "option_ios_display_name":"Created with GameMaker", 11 | "option_ios_enable_broadcast":false, 12 | "option_ios_half_ipad1_textures":false, 13 | "option_ios_icon_ipad_app_152":"${base_options_dir}/ios/icons/app/ipad_152.png", 14 | "option_ios_icon_ipad_app_76":"${base_options_dir}/ios/icons/app/ipad_76.png", 15 | "option_ios_icon_ipad_notification_20":"${base_options_dir}/ios/icons/notification/ipad_20.png", 16 | "option_ios_icon_ipad_notification_40":"${base_options_dir}/ios/icons/notification/ipad_40.png", 17 | "option_ios_icon_ipad_pro_app_167":"${base_options_dir}/ios/icons/app/ipad_pro_167.png", 18 | "option_ios_icon_ipad_settings_29":"${base_options_dir}/ios/icons/settings/ipad_29.png", 19 | "option_ios_icon_ipad_settings_58":"${base_options_dir}/ios/icons/settings/ipad_58.png", 20 | "option_ios_icon_ipad_spotlight_40":"${base_options_dir}/ios/icons/spotlight/ipad_40.png", 21 | "option_ios_icon_ipad_spotlight_80":"${base_options_dir}/ios/icons/spotlight/ipad_80.png", 22 | "option_ios_icon_iphone_app_120":"${base_options_dir}/ios/icons/app/iphone_120.png", 23 | "option_ios_icon_iphone_app_180":"${base_options_dir}/ios/icons/app/iphone_180.png", 24 | "option_ios_icon_iphone_notification_40":"${base_options_dir}/ios/icons/notification/iphone_40.png", 25 | "option_ios_icon_iphone_notification_60":"${base_options_dir}/ios/icons/notification/iphone_60.png", 26 | "option_ios_icon_iphone_settings_58":"${base_options_dir}/ios/icons/settings/iphone_58.png", 27 | "option_ios_icon_iphone_settings_87":"${base_options_dir}/ios/icons/settings/iphone_87.png", 28 | "option_ios_icon_iphone_spotlight_120":"${base_options_dir}/ios/icons/spotlight/iphone_120.png", 29 | "option_ios_icon_iphone_spotlight_80":"${base_options_dir}/ios/icons/spotlight/iphone_80.png", 30 | "option_ios_icon_itunes_artwork_1024":"${base_options_dir}/ios/icons/itunes/itunes_1024.png", 31 | "option_ios_interpolate_pixels":false, 32 | "option_ios_launchscreen_fill":0, 33 | "option_ios_launchscreen_image":"${base_options_dir}/ios/splash/launchscreen.png", 34 | "option_ios_launchscreen_image_landscape":"${base_options_dir}/ios/splash/launchscreen-landscape.png", 35 | "option_ios_min_version":"10.0", 36 | "option_ios_orientation_landscape":true, 37 | "option_ios_orientation_landscape_flipped":true, 38 | "option_ios_orientation_portrait":true, 39 | "option_ios_orientation_portrait_flipped":true, 40 | "option_ios_output_dir":"~/gamemakerstudio2", 41 | "option_ios_podfile_lock_path":"${options_dir}/ios/Podfile.lock", 42 | "option_ios_podfile_path":"${options_dir}/ios/Podfile", 43 | "option_ios_scale":0, 44 | "option_ios_splashscreen_background_colour":255, 45 | "option_ios_team_id":"", 46 | "option_ios_texture_page":"2048x2048", 47 | "option_ios_version":"1.0.0.0", 48 | "resourceType":"GMiOSOptions", 49 | "resourceVersion":"2.0", 50 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/options/ios/options_ios.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMiOSOptions":"", 3 | "%Name":"iOS", 4 | "name":"iOS", 5 | "option_ios_build_number":0, 6 | "option_ios_bundle_name":"com.company.game", 7 | "option_ios_cocoapods_checkbox":true, 8 | "option_ios_defer_home_indicator":false, 9 | "option_ios_devices":2, 10 | "option_ios_display_name":"Created with GameMaker", 11 | "option_ios_enable_broadcast":false, 12 | "option_ios_half_ipad1_textures":false, 13 | "option_ios_icon_ipad_app_152":"${base_options_dir}/ios/icons/app/ipad_152.png", 14 | "option_ios_icon_ipad_app_76":"${base_options_dir}/ios/icons/app/ipad_76.png", 15 | "option_ios_icon_ipad_notification_20":"${base_options_dir}/ios/icons/notification/ipad_20.png", 16 | "option_ios_icon_ipad_notification_40":"${base_options_dir}/ios/icons/notification/ipad_40.png", 17 | "option_ios_icon_ipad_pro_app_167":"${base_options_dir}/ios/icons/app/ipad_pro_167.png", 18 | "option_ios_icon_ipad_settings_29":"${base_options_dir}/ios/icons/settings/ipad_29.png", 19 | "option_ios_icon_ipad_settings_58":"${base_options_dir}/ios/icons/settings/ipad_58.png", 20 | "option_ios_icon_ipad_spotlight_40":"${base_options_dir}/ios/icons/spotlight/ipad_40.png", 21 | "option_ios_icon_ipad_spotlight_80":"${base_options_dir}/ios/icons/spotlight/ipad_80.png", 22 | "option_ios_icon_iphone_app_120":"${base_options_dir}/ios/icons/app/iphone_120.png", 23 | "option_ios_icon_iphone_app_180":"${base_options_dir}/ios/icons/app/iphone_180.png", 24 | "option_ios_icon_iphone_notification_40":"${base_options_dir}/ios/icons/notification/iphone_40.png", 25 | "option_ios_icon_iphone_notification_60":"${base_options_dir}/ios/icons/notification/iphone_60.png", 26 | "option_ios_icon_iphone_settings_58":"${base_options_dir}/ios/icons/settings/iphone_58.png", 27 | "option_ios_icon_iphone_settings_87":"${base_options_dir}/ios/icons/settings/iphone_87.png", 28 | "option_ios_icon_iphone_spotlight_120":"${base_options_dir}/ios/icons/spotlight/iphone_120.png", 29 | "option_ios_icon_iphone_spotlight_80":"${base_options_dir}/ios/icons/spotlight/iphone_80.png", 30 | "option_ios_icon_itunes_artwork_1024":"${base_options_dir}/ios/icons/itunes/itunes_1024.png", 31 | "option_ios_interpolate_pixels":false, 32 | "option_ios_launchscreen_fill":0, 33 | "option_ios_launchscreen_image":"${base_options_dir}/ios/splash/launchscreen.png", 34 | "option_ios_launchscreen_image_landscape":"${base_options_dir}/ios/splash/launchscreen-landscape.png", 35 | "option_ios_min_version":"10.0", 36 | "option_ios_orientation_landscape":true, 37 | "option_ios_orientation_landscape_flipped":true, 38 | "option_ios_orientation_portrait":true, 39 | "option_ios_orientation_portrait_flipped":true, 40 | "option_ios_output_dir":"~/gamemakerstudio2", 41 | "option_ios_podfile_lock_path":"${options_dir}/ios/Podfile.lock", 42 | "option_ios_podfile_path":"${options_dir}/ios/Podfile", 43 | "option_ios_scale":0, 44 | "option_ios_splashscreen_background_colour":255, 45 | "option_ios_team_id":"", 46 | "option_ios_texture_page":"2048x2048", 47 | "option_ios_version":"1.0.0.0", 48 | "resourceType":"GMiOSOptions", 49 | "resourceVersion":"2.0", 50 | } -------------------------------------------------------------------------------- /RadianceCascades/shaders/Shd_RadianceMerging/Shd_RadianceMerging.fsh: -------------------------------------------------------------------------------- 1 | varying vec2 in_TextCoord; 2 | uniform float in_CascadeExtent; // Cascade Diagonal Resolution. 3 | uniform float in_CascadeAngular; // Cascade angular resolution. 4 | uniform float in_CascadeCount; // Total number of used cascades. 5 | uniform float in_CascadeIndex; // Cascade index. 6 | uniform sampler2D in_CascadeAtlas; // Cascade Upper (N+1). 7 | 8 | struct ProbeTexel { 9 | float count; 10 | float size; 11 | float index; 12 | vec2 texel; 13 | vec2 probe; 14 | }; 15 | 16 | ProbeTexel cascadeProbeTexel(vec2 coord, float cascade) { 17 | float count = in_CascadeAngular * pow(4.0, cascade); 18 | float size = sqrt(count); 19 | vec2 texel = mod(floor(coord), vec2(size)); 20 | float index = (texel.y * size) + texel.x; 21 | vec2 probe = floor(coord / vec2(size)); 22 | return ProbeTexel(count, size, index, texel, probe); 23 | } 24 | 25 | vec4 cascadeFetch(ProbeTexel info, vec2 texelIndex, float thetaIndex) { 26 | vec2 probeTexel = texelIndex * info.size; 27 | probeTexel += vec2(mod(thetaIndex, info.size), thetaIndex / info.size); 28 | vec2 cascadeTexelPosition = probeTexel / in_CascadeExtent; 29 | 30 | if (cascadeTexelPosition.x < 0.0 || cascadeTexelPosition.y < 0.0 || cascadeTexelPosition.x >= 1.0 || cascadeTexelPosition.y >= 1.0) 31 | return vec4(0.0, 0.0, 0.0, 0.0); 32 | 33 | return texture2D(in_CascadeAtlas, cascadeTexelPosition); 34 | } 35 | 36 | void main() { 37 | vec2 cascadeCoord = in_TextCoord * in_CascadeExtent; 38 | ProbeTexel probeInfo = cascadeProbeTexel(cascadeCoord, in_CascadeIndex); 39 | ProbeTexel probeInfoN1 = cascadeProbeTexel(cascadeCoord, in_CascadeIndex + 1.0); 40 | 41 | vec2 texelIndexN1 = floor((vec2(probeInfo.probe) - 1.0) / 2.0); 42 | vec2 texelIndexN1_N = floor((texelIndexN1 * 2.0) + 1.0); 43 | 44 | vec4 radiance = texture2D(gm_BaseTexture, in_TextCoord); 45 | radiance.a = 1.0 - radiance.a; 46 | 47 | // Check ray visibility term from raymarching, on hit merge, otherwise no merge: 48 | if (radiance.a != 0.0 && in_CascadeIndex < in_CascadeCount - 1.0) { 49 | vec4 TL = vec4(0.0), TR = vec4(0.0), 50 | BL = vec4(0.0), BR = vec4(0.0); 51 | 52 | // We always default to a 4x ray branch scaling between cascades. 53 | const float branch4 = 4.0; 54 | for(float i = 0.0; i < branch4; i++) { 55 | float thetaIndexN1 = (probeInfo.index * branch4) + i; 56 | TL += cascadeFetch(probeInfoN1, texelIndexN1 + vec2(0.0,0.0), thetaIndexN1); 57 | TR += cascadeFetch(probeInfoN1, texelIndexN1 + vec2(1.0,0.0), thetaIndexN1); 58 | BL += cascadeFetch(probeInfoN1, texelIndexN1 + vec2(0.0,1.0), thetaIndexN1); 59 | BR += cascadeFetch(probeInfoN1, texelIndexN1 + vec2(1.0,1.0), thetaIndexN1); 60 | } 61 | 62 | // Per Specification: 63 | //vec2 weight = vec2(0.25) + (vec2(probeInfo.probe) - texelIndexN1_N) * vec2(0.5); 64 | 65 | // Smoother Weights: 66 | vec2 weight = vec2(0.33) + (vec2(probeInfo.probe) - texelIndexN1_N) * vec2(0.33); 67 | 68 | vec4 interpolated = mix(mix(TL, TR, weight.x), mix(BL, BR, weight.x), weight.y) / branch4; 69 | interpolated.a = 1.0 - interpolated.a; 70 | radiance += radiance.a * interpolated; 71 | } 72 | 73 | gl_FragColor = vec4(radiance.rgb, 1.0); 74 | } 75 | -------------------------------------------------------------------------------- /RadianceCascades/objects/Obj_RadianceCascades/Create_0.gml: -------------------------------------------------------------------------------- 1 | /* 2 | Radiance Cascades solves the rendering equation by having several 3 | grids of radiance probes (cascades) within a scene that check raymarch 4 | for light at varying intervals (distances and ranges) away from the 5 | radiance probes depending on the N-index of the cascade. 6 | 7 | Lower cascades have higher linear resolution and sample closer to the 8 | the probes with less rays-per-probe and have more probes per cascade. 9 | 10 | Higher cascades have higher anuglar resolution and sample further from 11 | the probes with more rays-per-probe and have less probes per cascade. 12 | 13 | This is due to how penumbras (edges of shadows) work where the accuracy 14 | of the shadow (how blurry it is) is sharper closer to light sources and 15 | blurrier further from light sources. Neat! 16 | 17 | By default this implementation uses quadrupling for ray counts and probes 18 | between cascades. If cascade0 has 16 rays and 256 probes, cascade1 has 64 19 | rays and 64 probes, then 256 rays and 16 probes and so on. 20 | 21 | Shader Passes: 22 | 1. Cascades (Raymarches the probes in each cascade). 23 | 2. Merging (Merges N and N+1 cascades for all cascades, excludes mipmapping). 24 | 3. Interpolate (-1 with 0. Cascade -1 is screen space, Cascade 0 is the first/final cascade). 25 | */ 26 | // Disable Surface Depth Buffer (for memory profiling). 27 | surface_depth_disable(true); 28 | 29 | var width = 1024.0, height = 1024.0; 30 | // Passing 0 or less cascades will optimally calculate the number of required cascades. 31 | // Parameters: [angular] is power of 4, [interval] is multiple of 4, [spacing] is power of 2. 32 | // Any value passed that does not conform to these rules will be automatically adjusted (adjusted up). 33 | radiance_initialize(max(width, height), 4, 4, 2, 1.0, 0.65); 34 | radiance_defaultshaders(Shd_JumpfloodSeed, Shd_JumpfloodAlgorithm, Shd_DistanceField, Shd_RadianceIntervals, Shd_RadianceMerging, Shd_RadianceMipMap); 35 | 36 | var bytes = 4.0 * sqr(global.radiance_cascade_extent) * global.radiance_cascade_count; 37 | show_debug_message("\nRender Diagonal: {0}", string(global.radiance_render_extent)); 38 | show_debug_message( "Cascade Diagonal: {0}", string(global.radiance_cascade_extent)); 39 | show_debug_message( "Cascade Count: {0}", string(global.radiance_cascade_count)); 40 | show_debug_message( "Cascade Angular: {0}", string(global.radiance_cascade_angular)); 41 | show_debug_message( "Cascade Interval: {0}", string(global.radiance_cascade_interval)); 42 | show_debug_message( "Cascade Spacing: {0}", string(global.radiance_cascade_spacing)); 43 | show_debug_message( "Cascade Memory: {0} MB\n", string(bytes / 1024 / 1024)); 44 | 45 | #macro INVALID_SURFACE -1 46 | gameworld_worldscene = INVALID_SURFACE; 47 | gameworld_temporary = INVALID_SURFACE; 48 | gameworld_jumpflood = INVALID_SURFACE; 49 | gameworld_distancefield = INVALID_SURFACE; 50 | 51 | gameworld_radiance = INVALID_SURFACE; 52 | gameworld_bouncescene = INVALID_SURFACE; 53 | 54 | gameworld_storage = INVALID_SURFACE; 55 | for(var i = 0; i < global.radiance_cascade_count + 1; i++) { 56 | gameworld_cascades[i] = INVALID_SURFACE; 57 | gameworld_mipmaps[i] = INVALID_SURFACE; 58 | } 59 | 60 | global.showcascade = 0; -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_RadianceCascades_FPFixed/Shd_RadianceCascades_FPFixed.fsh: -------------------------------------------------------------------------------- 1 | varying vec2 in_TexelCoord; 2 | uniform sampler2D in_RenderScene; 3 | uniform sampler2D in_DistanceField; 4 | uniform vec2 in_RenderExtent; 5 | uniform vec2 in_CascadeExtent; 6 | uniform float in_CascadeCount; 7 | uniform float in_CascadeIndex; 8 | uniform float in_CascadeLinear; 9 | uniform float in_CascadeInterval; 10 | 11 | #define TAU 6.283185 12 | #define EPS 0.000100 13 | #define V2F16(v) ((v.y * float(0.0039215689)) + v.x) 14 | #define SRGB(c) pow(c.rgb, vec3(2.2)) 15 | 16 | struct probe_info { float angular, linear; vec2 extent, probe; float index, interval, limit; }; 17 | probe_info cascadeTexelInfo() { 18 | float angular = pow(2.0, in_CascadeIndex); 19 | float raycount = angular * angular; 20 | float linear = in_CascadeLinear * pow(2.0, in_CascadeIndex); 21 | vec2 extent = floor(in_CascadeExtent / angular); 22 | vec2 texel = floor(in_TexelCoord * in_CascadeExtent); 23 | vec2 probe = mod(texel, extent); 24 | vec2 sector = floor(texel / extent); 25 | float index = mod(sector.x + (sector.y * angular), raycount); 26 | float interval = (in_CascadeInterval * (1.0 - pow(4.0, in_CascadeIndex))) / (1.0 - 4.0); 27 | float limit = in_CascadeInterval * pow(4.0, in_CascadeIndex); 28 | limit += length(vec2(in_CascadeLinear * pow(2.0, in_CascadeIndex + 1.0))); 29 | return probe_info(raycount, linear, extent, probe, index, interval, limit); 30 | } 31 | 32 | vec4 raymarch(vec2 point, float theta, float sdfscale, probe_info pinfo) { 33 | vec2 texel = 1.0 / in_RenderExtent; 34 | vec2 delta = vec2(cos(theta), -sin(theta)); 35 | vec2 ray = (point + (delta * pinfo.interval)) * texel; 36 | 37 | for(float i = 0.0, df = 0.0, rd = 0.0; i < pinfo.limit; i++) { 38 | df = V2F16(texture2D(in_DistanceField, ray).rg); 39 | rd += df * sdfscale; 40 | ray += delta * df * sdfscale * texel; 41 | 42 | if (rd >= pinfo.limit || floor(ray) != vec2(0.0)) break; 43 | if (df <= EPS && rd <= EPS && in_CascadeIndex != 0.0) return vec4(0.0); 44 | if (df <= EPS) return vec4(SRGB(texture2D(in_RenderScene, ray).rgb), 0.0); 45 | } 46 | 47 | return vec4(0.0, 0.0, 0.0, 1.0); 48 | } 49 | 50 | vec4 merge(vec4 rinfo, float index, probe_info pinfo) { 51 | if (rinfo.a == 0.0 || in_CascadeIndex >= in_CascadeCount - 1.0) 52 | return vec4(rinfo.rgb, 1.0 - rinfo.a); 53 | 54 | float angularN1 = pow(2.0, in_CascadeIndex + 1.0); 55 | vec2 sizeN1 = floor(pinfo.extent * 0.5); 56 | vec2 probeN1 = vec2(mod(index, angularN1), floor(index / angularN1)) * sizeN1; 57 | vec2 interpUVN1 = (pinfo.probe * 0.5) + 0.25; 58 | vec2 clampedUVN1 = max(vec2(1.0), min(interpUVN1, sizeN1 - 1.0)); 59 | vec2 probeUVN1 = probeN1 + clampedUVN1; 60 | vec4 interpolated = texture2D(gm_BaseTexture, probeUVN1 * (1.0 / in_CascadeExtent)); 61 | return rinfo + interpolated; 62 | } 63 | 64 | void main() { 65 | float sdfscale = length(in_RenderExtent); 66 | probe_info pinfo = cascadeTexelInfo(); 67 | vec2 origin = (pinfo.probe + 0.5) * pinfo.linear; 68 | float preavg_index = pinfo.index * 4.0; 69 | float theta_scalar = TAU / (pinfo.angular * 4.0); 70 | 71 | for(float i = 0.0; i < 4.0; i++) { 72 | float index = preavg_index + float(i), 73 | theta = (index + 0.5) * theta_scalar; 74 | vec4 rinfo = raymarch(origin, theta, sdfscale, pinfo); 75 | gl_FragColor += merge(rinfo, index, pinfo) * 0.25; 76 | } 77 | 78 | if (in_CascadeIndex == 0.0) 79 | gl_FragColor = vec4(pow(gl_FragColor.rgb, vec3(1.0 / 2.2)), 1.0); 80 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/sprites/Spr_SampleSprite/Spr_SampleSprite.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMSprite":"", 3 | "%Name":"Spr_SampleSprite", 4 | "bboxMode":0, 5 | "bbox_bottom":255, 6 | "bbox_left":0, 7 | "bbox_right":255, 8 | "bbox_top":0, 9 | "collisionKind":1, 10 | "collisionTolerance":0, 11 | "DynamicTexturePage":false, 12 | "edgeFiltering":false, 13 | "For3D":true, 14 | "frames":[ 15 | {"$GMSpriteFrame":"","%Name":"cbc5e4e8-1c87-4982-96e7-3c6679507561","name":"cbc5e4e8-1c87-4982-96e7-3c6679507561","resourceType":"GMSpriteFrame","resourceVersion":"2.0",}, 16 | ], 17 | "gridX":0, 18 | "gridY":0, 19 | "height":256, 20 | "HTile":false, 21 | "layers":[ 22 | {"$GMImageLayer":"","%Name":"a20214be-ef8a-4271-9147-a5321ec81a9f","blendMode":0,"displayName":"default","isLocked":false,"name":"a20214be-ef8a-4271-9147-a5321ec81a9f","opacity":100.0,"resourceType":"GMImageLayer","resourceVersion":"2.0","visible":true,}, 23 | ], 24 | "name":"Spr_SampleSprite", 25 | "nineSlice":null, 26 | "origin":0, 27 | "parent":{ 28 | "name":"Sprites", 29 | "path":"folders/Sprites.yy", 30 | }, 31 | "preMultiplyAlpha":false, 32 | "resourceType":"GMSprite", 33 | "resourceVersion":"2.0", 34 | "sequence":{ 35 | "$GMSequence":"", 36 | "%Name":"Spr_SampleSprite", 37 | "autoRecord":true, 38 | "backdropHeight":768, 39 | "backdropImageOpacity":0.5, 40 | "backdropImagePath":"", 41 | "backdropWidth":1366, 42 | "backdropXOffset":0.0, 43 | "backdropYOffset":0.0, 44 | "events":{ 45 | "$KeyframeStore":"", 46 | "Keyframes":[], 47 | "resourceType":"KeyframeStore", 48 | "resourceVersion":"2.0", 49 | }, 50 | "eventStubScript":null, 51 | "eventToFunction":{}, 52 | "length":1.0, 53 | "lockOrigin":false, 54 | "moments":{ 55 | "$KeyframeStore":"", 56 | "Keyframes":[], 57 | "resourceType":"KeyframeStore", 58 | "resourceVersion":"2.0", 59 | }, 60 | "name":"Spr_SampleSprite", 61 | "playback":1, 62 | "playbackSpeed":30.0, 63 | "playbackSpeedType":0, 64 | "resourceType":"GMSequence", 65 | "resourceVersion":"2.0", 66 | "showBackdrop":true, 67 | "showBackdropImage":false, 68 | "timeUnits":1, 69 | "tracks":[ 70 | {"$GMSpriteFramesTrack":"","builtinName":0,"events":[],"inheritsTrackColour":true,"interpolation":1,"isCreationTrack":false,"keyframes":{"$KeyframeStore":"","Keyframes":[ 71 | {"$Keyframe":"","Channels":{ 72 | "0":{"$SpriteFrameKeyframe":"","Id":{"name":"cbc5e4e8-1c87-4982-96e7-3c6679507561","path":"sprites/Spr_SampleSprite/Spr_SampleSprite.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",}, 73 | },"Disabled":false,"id":"dec6e684-7b47-4642-9f2a-bc46b9b8466c","IsCreationKey":false,"Key":0.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, 74 | ],"resourceType":"KeyframeStore","resourceVersion":"2.0",},"modifiers":[],"name":"frames","resourceType":"GMSpriteFramesTrack","resourceVersion":"2.0","spriteId":null,"trackColour":0,"tracks":[],"traits":0,}, 75 | ], 76 | "visibleRange":null, 77 | "volume":1.0, 78 | "xorigin":0, 79 | "yorigin":0, 80 | }, 81 | "swatchColours":null, 82 | "swfPrecision":2.525, 83 | "textureGroupId":{ 84 | "name":"Default", 85 | "path":"texturegroups/Default", 86 | }, 87 | "type":0, 88 | "VTile":false, 89 | "width":256, 90 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/sprites/Spr_SampleScene/Spr_SampleScene.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMSprite":"", 3 | "%Name":"Spr_SampleScene", 4 | "bboxMode":0, 5 | "bbox_bottom":1079, 6 | "bbox_left":0, 7 | "bbox_right":1221, 8 | "bbox_top":0, 9 | "collisionKind":1, 10 | "collisionTolerance":0, 11 | "DynamicTexturePage":false, 12 | "edgeFiltering":false, 13 | "For3D":false, 14 | "frames":[ 15 | {"$GMSpriteFrame":"","%Name":"ca0f74e2-644d-4591-9d29-ab644ad1d0ff","name":"ca0f74e2-644d-4591-9d29-ab644ad1d0ff","resourceType":"GMSpriteFrame","resourceVersion":"2.0",}, 16 | ], 17 | "gridX":0, 18 | "gridY":0, 19 | "height":1080, 20 | "HTile":false, 21 | "layers":[ 22 | {"$GMImageLayer":"","%Name":"13980e7e-ad5c-4e05-801b-189a5701c616","blendMode":0,"displayName":"default","isLocked":false,"name":"13980e7e-ad5c-4e05-801b-189a5701c616","opacity":100.0,"resourceType":"GMImageLayer","resourceVersion":"2.0","visible":true,}, 23 | ], 24 | "name":"Spr_SampleScene", 25 | "nineSlice":null, 26 | "origin":0, 27 | "parent":{ 28 | "name":"Sprites", 29 | "path":"folders/Sprites.yy", 30 | }, 31 | "preMultiplyAlpha":false, 32 | "resourceType":"GMSprite", 33 | "resourceVersion":"2.0", 34 | "sequence":{ 35 | "$GMSequence":"", 36 | "%Name":"Spr_SampleScene", 37 | "autoRecord":true, 38 | "backdropHeight":768, 39 | "backdropImageOpacity":0.5, 40 | "backdropImagePath":"", 41 | "backdropWidth":1366, 42 | "backdropXOffset":0.0, 43 | "backdropYOffset":0.0, 44 | "events":{ 45 | "$KeyframeStore":"", 46 | "Keyframes":[], 47 | "resourceType":"KeyframeStore", 48 | "resourceVersion":"2.0", 49 | }, 50 | "eventStubScript":null, 51 | "eventToFunction":{}, 52 | "length":1.0, 53 | "lockOrigin":false, 54 | "moments":{ 55 | "$KeyframeStore":"", 56 | "Keyframes":[], 57 | "resourceType":"KeyframeStore", 58 | "resourceVersion":"2.0", 59 | }, 60 | "name":"Spr_SampleScene", 61 | "playback":1, 62 | "playbackSpeed":30.0, 63 | "playbackSpeedType":0, 64 | "resourceType":"GMSequence", 65 | "resourceVersion":"2.0", 66 | "showBackdrop":true, 67 | "showBackdropImage":false, 68 | "timeUnits":1, 69 | "tracks":[ 70 | {"$GMSpriteFramesTrack":"","builtinName":0,"events":[],"inheritsTrackColour":true,"interpolation":1,"isCreationTrack":false,"keyframes":{"$KeyframeStore":"","Keyframes":[ 71 | {"$Keyframe":"","Channels":{ 72 | "0":{"$SpriteFrameKeyframe":"","Id":{"name":"ca0f74e2-644d-4591-9d29-ab644ad1d0ff","path":"sprites/Spr_SampleScene/Spr_SampleScene.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",}, 73 | },"Disabled":false,"id":"7e8de228-a427-48c4-a134-147e7041fdce","IsCreationKey":false,"Key":0.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, 74 | ],"resourceType":"KeyframeStore","resourceVersion":"2.0",},"modifiers":[],"name":"frames","resourceType":"GMSpriteFramesTrack","resourceVersion":"2.0","spriteId":null,"trackColour":0,"tracks":[],"traits":0,}, 75 | ], 76 | "visibleRange":null, 77 | "volume":1.0, 78 | "xorigin":0, 79 | "yorigin":0, 80 | }, 81 | "swatchColours":null, 82 | "swfPrecision":0.5, 83 | "textureGroupId":{ 84 | "name":"Default", 85 | "path":"texturegroups/Default", 86 | }, 87 | "type":0, 88 | "VTile":false, 89 | "width":1920, 90 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/scripts/Scr_HelperFunctions/Scr_HelperFunctions.gml: -------------------------------------------------------------------------------- 1 | #macro INVALID_SURFACE -1 2 | 3 | // Easy surface usage. 4 | function surface(w, h, f) constructor { width = w; height = h; format = f; memory = INVALID_SURFACE; } 5 | function surface_build(w, h, f, l) { var surf = new surface(w, h, f); ds_list_add(l, surf); return surf; } 6 | function surface_rebuild(surf) { if (!surface_exists(surf.memory)) surf.memory = surface_create(surf.width, surf.height, surf.format); } 7 | function surface_delete(surf) { if (surface_exists(surf.memory)) surface_free(surf.memory); delete surf; } 8 | function surface_source(surf) { return surf.memory; } 9 | function surface_update(surf, w, h, f) { surf.width = (w > 0)? w: surf.width; surf.height = (h > 0)? h : surf.height; surf.format = (f > 0)? f : surf.format; } 10 | function surface_clear(surf) { surface_set_target(surf.memory); draw_clear_alpha(c_black, 0); surface_reset_target(); } 11 | 12 | // Shader Functions 13 | function texture(shd, uid) { return shader_get_sampler_index(shd, uid); } 14 | function uniform(shd, uid) { return shader_get_uniform(shd, uid); } 15 | function shader_texture(uid, surf) { texture_set_stage(uid, surface_get_texture(surf)); } 16 | function shader_float(uid, f1) { shader_set_uniform_f(uid, f1); } 17 | function shader_vec2(uid, f1, f2) { shader_set_uniform_f(uid, f1, f2); } 18 | 19 | // Math Functions 20 | function power_ofN(number, n) { return power(n, ceil(logn(n, number))); } 21 | function multiple_ofN(number, n) { return (n == 0) ? number : ceil(number / n) * n; } 22 | function geometric_ofN(number, n, p) { return (number * (1.0 - power(p, n))) / (1.0 - p); } 23 | 24 | // Draw Functions 25 | function draw_sprite_scalable(spr, xx, yy, w, h) { return draw_sprite_ext(spr, 0, xx, yy, w/sprite_get_width(spr), h/sprite_get_height(spr), 0, c_white, 1); } 26 | 27 | // Color Functions 28 | function make_color_normalized_rgb(red, green, blue) { return make_color_rgb(red * 255.0, green * 255.0, blue * 255.0); } 29 | 30 | // Shader Specific Functions 31 | function radiance_jfaseed(init, jfa, dist, shader) { 32 | surface_set_target(jfa); 33 | draw_clear_alpha(c_black, 0); 34 | shader_set(shader); 35 | draw_surface(init,0,0); 36 | shader_reset(); 37 | surface_reset_target(); 38 | 39 | surface_set_target(dist); 40 | draw_clear_alpha(c_black, 0); 41 | surface_reset_target(); 42 | } 43 | 44 | function radiance_jumpflood(source, destination, shader, uniform_extent, uniform_jumpdist, width, height) { 45 | var passes = ceil(log2(max(width, height))); 46 | 47 | shader_set(shader); 48 | shader_set_uniform_f(uniform_extent, width, height); 49 | 50 | var tempA = source, tempB = destination, tempC = source; 51 | var i = 0; repeat(passes) { 52 | var offset = power(2, passes - i - 1); 53 | shader_set_uniform_f(uniform_jumpdist, offset); 54 | surface_set_target(tempA); 55 | draw_surface(tempB,0,0); 56 | surface_reset_target(); 57 | 58 | tempC = tempA; 59 | tempA = tempB; 60 | tempB = tempC; 61 | i++; 62 | } 63 | 64 | shader_reset(); 65 | if (destination != tempC) { 66 | surface_set_target(destination); 67 | draw_surface(tempC,0,0); 68 | surface_reset_target(); 69 | } 70 | } 71 | 72 | function radiance_distancefield(jfa, dist, shader, uniform_extent, width, height) { 73 | surface_set_target(dist); 74 | draw_clear_alpha(c_black, 0); 75 | shader_set(shader); 76 | shader_set_uniform_f(uniform_extent, width, height); 77 | draw_surface(jfa, 0, 0); 78 | shader_reset(); 79 | surface_reset_target(); 80 | } -------------------------------------------------------------------------------- /RadianceCascades/RadianceCascades.yyp: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "GMProject", 3 | "resourceVersion": "1.7", 4 | "name": "RadianceCascades", 5 | "AudioGroups": [ 6 | {"resourceType":"GMAudioGroup","resourceVersion":"1.3","name":"audiogroup_default","targets":-1,}, 7 | ], 8 | "configs": { 9 | "children": [], 10 | "name": "Default", 11 | }, 12 | "defaultScriptType": 1, 13 | "Folders": [ 14 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Animation Curves","folderPath":"folders/Animation Curves.yy",}, 15 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Extensions","folderPath":"folders/Extensions.yy",}, 16 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Fonts","folderPath":"folders/Fonts.yy",}, 17 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Notes","folderPath":"folders/Notes.yy",}, 18 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Objects","folderPath":"folders/Objects.yy",}, 19 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Particle Systems","folderPath":"folders/Particle Systems.yy",}, 20 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Paths","folderPath":"folders/Paths.yy",}, 21 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Rooms","folderPath":"folders/Rooms.yy",}, 22 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Scripts","folderPath":"folders/Scripts.yy",}, 23 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Sequences","folderPath":"folders/Sequences.yy",}, 24 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Shaders","folderPath":"folders/Shaders.yy",}, 25 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Sounds","folderPath":"folders/Sounds.yy",}, 26 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Sprites","folderPath":"folders/Sprites.yy",}, 27 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Tile Sets","folderPath":"folders/Tile Sets.yy",}, 28 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Timelines","folderPath":"folders/Timelines.yy",}, 29 | ], 30 | "IncludedFiles": [], 31 | "isEcma": false, 32 | "LibraryEmitters": [], 33 | "MetaData": { 34 | "IDEVersion": "2023.6.0.92", 35 | }, 36 | "resources": [ 37 | {"id":{"name":"Spr_VisualizeRadianceIntervals","path":"sprites/Spr_VisualizeRadianceIntervals/Spr_VisualizeRadianceIntervals.yy",},}, 38 | {"id":{"name":"Shd_JumpfloodSeed","path":"shaders/Shd_JumpfloodSeed/Shd_JumpfloodSeed.yy",},}, 39 | {"id":{"name":"Shd_RadianceMipMap","path":"shaders/Shd_RadianceMipMap/Shd_RadianceMipMap.yy",},}, 40 | {"id":{"name":"Shd_DistanceField","path":"shaders/Shd_DistanceField/Shd_DistanceField.yy",},}, 41 | {"id":{"name":"Shd_JumpfloodAlgorithm","path":"shaders/Shd_JumpfloodAlgorithm/Shd_JumpfloodAlgorithm.yy",},}, 42 | {"id":{"name":"Shd_RadianceIntervals","path":"shaders/Shd_RadianceIntervals/Shd_RadianceIntervals.yy",},}, 43 | {"id":{"name":"Spr_SampleScene","path":"sprites/Spr_SampleScene/Spr_SampleScene.yy",},}, 44 | {"id":{"name":"Obj_RadianceCascades","path":"objects/Obj_RadianceCascades/Obj_RadianceCascades.yy",},}, 45 | {"id":{"name":"Scr_RadianceCascades","path":"scripts/Scr_RadianceCascades/Scr_RadianceCascades.yy",},}, 46 | {"id":{"name":"Shd_RadianceMerging","path":"shaders/Shd_RadianceMerging/Shd_RadianceMerging.yy",},}, 47 | {"id":{"name":"Rm_SampleScene","path":"rooms/Rm_SampleScene/Rm_SampleScene.yy",},}, 48 | ], 49 | "RoomOrderNodes": [ 50 | {"roomId":{"name":"Rm_SampleScene","path":"rooms/Rm_SampleScene/Rm_SampleScene.yy",},}, 51 | ], 52 | "TextureGroups": [ 53 | {"resourceType":"GMTextureGroup","resourceVersion":"1.3","name":"Default","autocrop":true,"border":2,"compressFormat":"bz2","directory":"","groupParent":null,"isScaled":true,"loadType":"default","mipsToGenerate":0,"targets":-1,}, 54 | ], 55 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/objects/Obj_SampleObject/Draw_0.gml: -------------------------------------------------------------------------------- 1 | gpu_set_blendenable(false); 2 | shader_set(Shd_CascadeVisual); 3 | shader_set_uniform_f(shader_get_uniform(Shd_CascadeVisual, "in_CascadeSize"), cascade_size); 4 | shader_set_uniform_f(shader_get_uniform(Shd_CascadeVisual, "in_CascadeIndex"), cascadeIndex); 5 | shader_set_uniform_f(shader_get_uniform(Shd_CascadeVisual, "in_CascadeAngular"), angular); 6 | 7 | surface_set_target(render_surface); 8 | var sprw = sprite_get_width(Spr_SampleSprite); 9 | var sprh = sprite_get_height(Spr_SampleSprite); 10 | draw_sprite_ext(Spr_SampleSprite, 0, 0, 0, cascade_size/sprw, cascade_size/sprh, 0, c_white, 1); 11 | surface_reset_target(); 12 | shader_reset(); 13 | gpu_set_blendenable(true); 14 | gpu_set_tex_filter(false); 15 | draw_surface_ext(render_surface, cascade_offsetx, cascade_offsety, render_size/cascade_size, render_size/cascade_size, 0, c_white, 1); 16 | gpu_set_tex_filter(true); 17 | 18 | draw_set_color(c_white); 19 | draw_set_font(Fnt_Sample); 20 | draw_set_halign(fa_left); 21 | draw_text(cascade_offsetx, cascade_offsety - 32, "Cascade Memory:"); 22 | draw_text(cascade_offsetx2, cascade_offsety2 - 32, "Screen Probe/Ray Spacing:"); 23 | draw_set_halign(fa_center); 24 | draw_text(cascade_offsetx + render_size, cascade_offsety + render_size + 16, 25 | "Controls: [Up]/[Down] Probe Spacing; [Left]/[Right] Cascade Index"); 26 | draw_text(cascade_offsetx + render_size, cascade_offsety + render_size + 40, 27 | "[Space] to switch to Direction-First Probe Layout"); 28 | 29 | draw_set_color(c_red); 30 | draw_rectangle(cascade_offsetx2, cascade_offsety2, cascade_offsetx2 + render_size - 1, cascade_offsety2 + render_size - 1, true); 31 | 32 | for(var xx = 0; xx < probeCount; xx++) { 33 | for(var yy = 0; yy < probeCount; yy++) { 34 | var pspacing = probeSpacing * (render_size / cascade_size); 35 | draw_circle(cascade_offsetx2 + (pspacing * 0.5) + (pspacing * xx), cascade_offsety2 + (pspacing * 0.5) + (pspacing * yy), 2, false); 36 | } 37 | } 38 | 39 | draw_set_color(c_blue); 40 | 41 | draw_rectangle(cascade_offsetx2 + current_probex, 42 | cascade_offsety2 + current_probey, 43 | cascade_offsetx2 + current_probex + current_probesize - 1, 44 | cascade_offsety2 + current_probey + current_probesize - 1, true); 45 | 46 | draw_set_color(c_aqua); 47 | 48 | for(var r = 0; r < current_angular; r++) { 49 | var dx1, dy1, dx2, dy2, dt, intrs, intr; 50 | intrs = current_intervalstart * (render_size / cascade_size); 51 | intr = current_interval * (render_size / cascade_size); 52 | dt = ((r + 0.5) / current_angular) * 2.0 * pi; 53 | dx1 = lengthdir_x(intrs, radtodeg(dt)); 54 | dy1 = lengthdir_y(intrs, radtodeg(dt)); 55 | dx2 = lengthdir_x(intrs + intr, radtodeg(dt)); 56 | dy2 = lengthdir_y(intrs + intr, radtodeg(dt)); 57 | draw_line( 58 | cascade_offsetx2 + current_probex + (current_probesize * 0.5) + dx1, 59 | cascade_offsety2 + current_probey + (current_probesize * 0.5) + dy1, 60 | cascade_offsetx2 + current_probex + (current_probesize * 0.5) + dx2, 61 | cascade_offsety2 + current_probey + (current_probesize * 0.5) + dy2); 62 | } 63 | 64 | draw_set_color(c_fuchsia); 65 | 66 | var mrindex = floor((point_direction( 67 | cascade_offsetx2 + current_probex + (current_probesize * 0.5), 68 | cascade_offsety2 + current_probey + (current_probesize * 0.5), 69 | mouse_x, mouse_y) / 360.0) * current_angular); 70 | var dx, dy, dr; 71 | var croffset = (render_size / cascade_size) * 0.5; 72 | dr = ((mrindex + 0.5) / current_angular) * 2.0 * pi; 73 | dx = lengthdir_x(intrs + intr, radtodeg(dr)); 74 | dy = lengthdir_y(intrs + intr, radtodeg(dr)); 75 | draw_circle(cascade_offsetx2 + current_probex + (current_probesize * 0.5) + dx, 76 | cascade_offsety2 + current_probey + (current_probesize * 0.5) + dy, croffset, false); 77 | 78 | var rayx = mrindex mod sqrt(current_angular) * (render_size / cascade_size); 79 | var rayy = floor(mrindex / sqrt(current_angular)) * (render_size / cascade_size); 80 | draw_circle(cascade_offsetx + current_probex + croffset + rayx, 81 | cascade_offsety + current_probey + croffset + rayy, croffset, false); 82 | 83 | draw_set_color(c_white); -------------------------------------------------------------------------------- /RadianceCascades/rooms/Rm_SampleScene/Rm_SampleScene.yy: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "GMRoom", 3 | "resourceVersion": "1.0", 4 | "name": "Rm_SampleScene", 5 | "creationCodeFile": "", 6 | "inheritCode": false, 7 | "inheritCreationOrder": false, 8 | "inheritLayers": false, 9 | "instanceCreationOrder": [ 10 | {"name":"inst_39704A3E","path":"rooms/Rm_SampleScene/Rm_SampleScene.yy",}, 11 | ], 12 | "isDnd": false, 13 | "layers": [ 14 | {"resourceType":"GMRInstanceLayer","resourceVersion":"1.0","name":"Instances","depth":0,"effectEnabled":true,"effectType":null,"gridX":32,"gridY":32,"hierarchyFrozen":false,"inheritLayerDepth":false,"inheritLayerSettings":false,"inheritSubLayers":true,"inheritVisibility":true,"instances":[ 15 | {"resourceType":"GMRInstance","resourceVersion":"1.0","name":"inst_39704A3E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"objectId":{"name":"Obj_RadianceCascades","path":"objects/Obj_RadianceCascades/Obj_RadianceCascades.yy",},"properties":[],"rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":32.0,}, 16 | ],"layers":[],"properties":[],"userdefinedDepth":false,"visible":true,}, 17 | {"resourceType":"GMRBackgroundLayer","resourceVersion":"1.0","name":"Background","animationFPS":15.0,"animationSpeedType":0,"colour":4278190080,"depth":100,"effectEnabled":true,"effectType":null,"gridX":32,"gridY":32,"hierarchyFrozen":false,"hspeed":0.0,"htiled":false,"inheritLayerDepth":false,"inheritLayerSettings":false,"inheritSubLayers":true,"inheritVisibility":true,"layers":[],"properties":[],"spriteId":null,"stretch":false,"userdefinedAnimFPS":false,"userdefinedDepth":false,"visible":true,"vspeed":0.0,"vtiled":false,"x":0,"y":0,}, 18 | ], 19 | "parent": { 20 | "name": "Rooms", 21 | "path": "folders/Rooms.yy", 22 | }, 23 | "parentRoom": null, 24 | "physicsSettings": { 25 | "inheritPhysicsSettings": false, 26 | "PhysicsWorld": false, 27 | "PhysicsWorldGravityX": 0.0, 28 | "PhysicsWorldGravityY": 10.0, 29 | "PhysicsWorldPixToMetres": 0.1, 30 | }, 31 | "roomSettings": { 32 | "Height": 1024, 33 | "inheritRoomSettings": false, 34 | "persistent": false, 35 | "Width": 1024, 36 | }, 37 | "sequenceId": null, 38 | "views": [ 39 | {"hborder":32,"hport":1024,"hspeed":-1,"hview":1024,"inherit":false,"objectId":null,"vborder":32,"visible":true,"vspeed":-1,"wport":1024,"wview":1024,"xport":0,"xview":0,"yport":0,"yview":0,}, 40 | {"hborder":32,"hport":768,"hspeed":-1,"hview":768,"inherit":false,"objectId":null,"vborder":32,"visible":false,"vspeed":-1,"wport":1366,"wview":1366,"xport":0,"xview":0,"yport":0,"yview":0,}, 41 | {"hborder":32,"hport":768,"hspeed":-1,"hview":768,"inherit":false,"objectId":null,"vborder":32,"visible":false,"vspeed":-1,"wport":1366,"wview":1366,"xport":0,"xview":0,"yport":0,"yview":0,}, 42 | {"hborder":32,"hport":768,"hspeed":-1,"hview":768,"inherit":false,"objectId":null,"vborder":32,"visible":false,"vspeed":-1,"wport":1366,"wview":1366,"xport":0,"xview":0,"yport":0,"yview":0,}, 43 | {"hborder":32,"hport":768,"hspeed":-1,"hview":768,"inherit":false,"objectId":null,"vborder":32,"visible":false,"vspeed":-1,"wport":1366,"wview":1366,"xport":0,"xview":0,"yport":0,"yview":0,}, 44 | {"hborder":32,"hport":768,"hspeed":-1,"hview":768,"inherit":false,"objectId":null,"vborder":32,"visible":false,"vspeed":-1,"wport":1366,"wview":1366,"xport":0,"xview":0,"yport":0,"yview":0,}, 45 | {"hborder":32,"hport":768,"hspeed":-1,"hview":768,"inherit":false,"objectId":null,"vborder":32,"visible":false,"vspeed":-1,"wport":1366,"wview":1366,"xport":0,"xview":0,"yport":0,"yview":0,}, 46 | {"hborder":32,"hport":768,"hspeed":-1,"hview":768,"inherit":false,"objectId":null,"vborder":32,"visible":false,"vspeed":-1,"wport":1366,"wview":1366,"xport":0,"xview":0,"yport":0,"yview":0,}, 47 | ], 48 | "viewSettings": { 49 | "clearDisplayBuffer": true, 50 | "clearViewBackground": true, 51 | "enableViews": true, 52 | "inheritViewSettings": false, 53 | }, 54 | "volume": 1.0, 55 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/rooms/Rm_SampleRoom/Rm_SampleRoom.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMRoom":"", 3 | "%Name":"Rm_SampleRoom", 4 | "creationCodeFile":"", 5 | "inheritCode":false, 6 | "inheritCreationOrder":false, 7 | "inheritLayers":false, 8 | "instanceCreationOrder":[ 9 | {"name":"inst_601E3141","path":"rooms/Rm_SampleRoom/Rm_SampleRoom.yy",}, 10 | ], 11 | "isDnd":false, 12 | "layers":[ 13 | {"$GMRInstanceLayer":"","%Name":"Instances_1","depth":0,"effectEnabled":true,"effectType":null,"gridX":32,"gridY":32,"hierarchyFrozen":false,"inheritLayerDepth":false,"inheritLayerSettings":false,"inheritSubLayers":true,"inheritVisibility":true,"instances":[ 14 | {"$GMRInstance":"","%Name":"inst_601E3141","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_601E3141","objectId":{"name":"Obj_SampleObjectDF","path":"objects/Obj_SampleObjectDF/Obj_SampleObjectDF.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":32.0,}, 15 | ],"layers":[],"name":"Instances_1","properties":[],"resourceType":"GMRInstanceLayer","resourceVersion":"2.0","userdefinedDepth":false,"visible":true,}, 16 | {"$GMRBackgroundLayer":"","%Name":"Background","animationFPS":15.0,"animationSpeedType":0,"colour":4278190080,"depth":100,"effectEnabled":true,"effectType":null,"gridX":32,"gridY":32,"hierarchyFrozen":false,"hspeed":0.0,"htiled":false,"inheritLayerDepth":false,"inheritLayerSettings":false,"inheritSubLayers":true,"inheritVisibility":true,"layers":[],"name":"Background","properties":[],"resourceType":"GMRBackgroundLayer","resourceVersion":"2.0","spriteId":null,"stretch":false,"userdefinedAnimFPS":false,"userdefinedDepth":false,"visible":true,"vspeed":0.0,"vtiled":false,"x":0,"y":0,}, 17 | ], 18 | "name":"Rm_SampleRoom", 19 | "parent":{ 20 | "name":"Rooms", 21 | "path":"folders/Rooms.yy", 22 | }, 23 | "parentRoom":null, 24 | "physicsSettings":{ 25 | "inheritPhysicsSettings":false, 26 | "PhysicsWorld":false, 27 | "PhysicsWorldGravityX":0.0, 28 | "PhysicsWorldGravityY":10.0, 29 | "PhysicsWorldPixToMetres":0.1, 30 | }, 31 | "resourceType":"GMRoom", 32 | "resourceVersion":"2.0", 33 | "roomSettings":{ 34 | "Height":768, 35 | "inheritRoomSettings":false, 36 | "persistent":false, 37 | "Width":1366, 38 | }, 39 | "sequenceId":null, 40 | "views":[ 41 | {"hborder":32,"hport":768,"hspeed":-1,"hview":768,"inherit":false,"objectId":null,"vborder":32,"visible":false,"vspeed":-1,"wport":1366,"wview":1366,"xport":0,"xview":0,"yport":0,"yview":0,}, 42 | {"hborder":32,"hport":768,"hspeed":-1,"hview":768,"inherit":false,"objectId":null,"vborder":32,"visible":false,"vspeed":-1,"wport":1366,"wview":1366,"xport":0,"xview":0,"yport":0,"yview":0,}, 43 | {"hborder":32,"hport":768,"hspeed":-1,"hview":768,"inherit":false,"objectId":null,"vborder":32,"visible":false,"vspeed":-1,"wport":1366,"wview":1366,"xport":0,"xview":0,"yport":0,"yview":0,}, 44 | {"hborder":32,"hport":768,"hspeed":-1,"hview":768,"inherit":false,"objectId":null,"vborder":32,"visible":false,"vspeed":-1,"wport":1366,"wview":1366,"xport":0,"xview":0,"yport":0,"yview":0,}, 45 | {"hborder":32,"hport":768,"hspeed":-1,"hview":768,"inherit":false,"objectId":null,"vborder":32,"visible":false,"vspeed":-1,"wport":1366,"wview":1366,"xport":0,"xview":0,"yport":0,"yview":0,}, 46 | {"hborder":32,"hport":768,"hspeed":-1,"hview":768,"inherit":false,"objectId":null,"vborder":32,"visible":false,"vspeed":-1,"wport":1366,"wview":1366,"xport":0,"xview":0,"yport":0,"yview":0,}, 47 | {"hborder":32,"hport":768,"hspeed":-1,"hview":768,"inherit":false,"objectId":null,"vborder":32,"visible":false,"vspeed":-1,"wport":1366,"wview":1366,"xport":0,"xview":0,"yport":0,"yview":0,}, 48 | {"hborder":32,"hport":768,"hspeed":-1,"hview":768,"inherit":false,"objectId":null,"vborder":32,"visible":false,"vspeed":-1,"wport":1366,"wview":1366,"xport":0,"xview":0,"yport":0,"yview":0,}, 49 | ], 50 | "viewSettings":{ 51 | "clearDisplayBuffer":true, 52 | "clearViewBackground":false, 53 | "enableViews":false, 54 | "inheritViewSettings":false, 55 | }, 56 | "volume":1.0, 57 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/rooms/Rm_TestRoom/Rm_TestRoom.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMRoom":"", 3 | "%Name":"Rm_TestRoom", 4 | "creationCodeFile":"", 5 | "inheritCode":false, 6 | "inheritCreationOrder":false, 7 | "inheritLayers":false, 8 | "instanceCreationOrder":[ 9 | {"name":"inst_7F30BAF7","path":"rooms/Rm_TestRoom/Rm_TestRoom.yy",}, 10 | ], 11 | "isDnd":false, 12 | "layers":[ 13 | {"$GMRInstanceLayer":"","%Name":"Instances","depth":0,"effectEnabled":true,"effectType":null,"gridX":32,"gridY":32,"hierarchyFrozen":false,"inheritLayerDepth":false,"inheritLayerSettings":false,"inheritSubLayers":true,"inheritVisibility":true,"instances":[ 14 | {"$GMRInstance":"","%Name":"inst_7F30BAF7","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_7F30BAF7","objectId":{"name":"Obj_RadianceCascades","path":"objects/Obj_RadianceCascades/Obj_RadianceCascades.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":32.0,}, 15 | ],"layers":[],"name":"Instances","properties":[],"resourceType":"GMRInstanceLayer","resourceVersion":"2.0","userdefinedDepth":false,"visible":true,}, 16 | {"$GMRBackgroundLayer":"","%Name":"Background","animationFPS":15.0,"animationSpeedType":0,"colour":4278190080,"depth":100,"effectEnabled":true,"effectType":null,"gridX":32,"gridY":32,"hierarchyFrozen":false,"hspeed":0.0,"htiled":false,"inheritLayerDepth":false,"inheritLayerSettings":false,"inheritSubLayers":true,"inheritVisibility":true,"layers":[],"name":"Background","properties":[],"resourceType":"GMRBackgroundLayer","resourceVersion":"2.0","spriteId":null,"stretch":false,"userdefinedAnimFPS":false,"userdefinedDepth":false,"visible":true,"vspeed":0.0,"vtiled":false,"x":0,"y":0,}, 17 | ], 18 | "name":"Rm_TestRoom", 19 | "parent":{ 20 | "name":"Rooms", 21 | "path":"folders/Rooms.yy", 22 | }, 23 | "parentRoom":null, 24 | "physicsSettings":{ 25 | "inheritPhysicsSettings":false, 26 | "PhysicsWorld":false, 27 | "PhysicsWorldGravityX":0.0, 28 | "PhysicsWorldGravityY":10.0, 29 | "PhysicsWorldPixToMetres":0.1, 30 | }, 31 | "resourceType":"GMRoom", 32 | "resourceVersion":"2.0", 33 | "roomSettings":{ 34 | "Height":1080, 35 | "inheritRoomSettings":false, 36 | "persistent":false, 37 | "Width":1920, 38 | }, 39 | "sequenceId":null, 40 | "views":[ 41 | {"hborder":32,"hport":768,"hspeed":-1,"hview":768,"inherit":false,"objectId":null,"vborder":32,"visible":false,"vspeed":-1,"wport":1366,"wview":1366,"xport":0,"xview":0,"yport":0,"yview":0,}, 42 | {"hborder":32,"hport":768,"hspeed":-1,"hview":768,"inherit":false,"objectId":null,"vborder":32,"visible":false,"vspeed":-1,"wport":1366,"wview":1366,"xport":0,"xview":0,"yport":0,"yview":0,}, 43 | {"hborder":32,"hport":768,"hspeed":-1,"hview":768,"inherit":false,"objectId":null,"vborder":32,"visible":false,"vspeed":-1,"wport":1366,"wview":1366,"xport":0,"xview":0,"yport":0,"yview":0,}, 44 | {"hborder":32,"hport":768,"hspeed":-1,"hview":768,"inherit":false,"objectId":null,"vborder":32,"visible":false,"vspeed":-1,"wport":1366,"wview":1366,"xport":0,"xview":0,"yport":0,"yview":0,}, 45 | {"hborder":32,"hport":768,"hspeed":-1,"hview":768,"inherit":false,"objectId":null,"vborder":32,"visible":false,"vspeed":-1,"wport":1366,"wview":1366,"xport":0,"xview":0,"yport":0,"yview":0,}, 46 | {"hborder":32,"hport":768,"hspeed":-1,"hview":768,"inherit":false,"objectId":null,"vborder":32,"visible":false,"vspeed":-1,"wport":1366,"wview":1366,"xport":0,"xview":0,"yport":0,"yview":0,}, 47 | {"hborder":32,"hport":768,"hspeed":-1,"hview":768,"inherit":false,"objectId":null,"vborder":32,"visible":false,"vspeed":-1,"wport":1366,"wview":1366,"xport":0,"xview":0,"yport":0,"yview":0,}, 48 | {"hborder":32,"hport":768,"hspeed":-1,"hview":768,"inherit":false,"objectId":null,"vborder":32,"visible":false,"vspeed":-1,"wport":1366,"wview":1366,"xport":0,"xview":0,"yport":0,"yview":0,}, 49 | ], 50 | "viewSettings":{ 51 | "clearDisplayBuffer":true, 52 | "clearViewBackground":false, 53 | "enableViews":false, 54 | "inheritViewSettings":false, 55 | }, 56 | "volume":1.0, 57 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/CascadeVisualDemo.yyp: -------------------------------------------------------------------------------- 1 | { 2 | "$GMProject":"", 3 | "%Name":"CascadeVisualDemo", 4 | "AudioGroups":[ 5 | {"$GMAudioGroup":"","%Name":"audiogroup_default","name":"audiogroup_default","resourceType":"GMAudioGroup","resourceVersion":"2.0","targets":-1,}, 6 | ], 7 | "configs":{ 8 | "children":[], 9 | "name":"Default", 10 | }, 11 | "defaultScriptType":1, 12 | "Folders":[ 13 | {"$GMFolder":"","%Name":"Animation Curves","folderPath":"folders/Animation Curves.yy","name":"Animation Curves","resourceType":"GMFolder","resourceVersion":"2.0",}, 14 | {"$GMFolder":"","%Name":"Extensions","folderPath":"folders/Extensions.yy","name":"Extensions","resourceType":"GMFolder","resourceVersion":"2.0",}, 15 | {"$GMFolder":"","%Name":"Fonts","folderPath":"folders/Fonts.yy","name":"Fonts","resourceType":"GMFolder","resourceVersion":"2.0",}, 16 | {"$GMFolder":"","%Name":"Notes","folderPath":"folders/Notes.yy","name":"Notes","resourceType":"GMFolder","resourceVersion":"2.0",}, 17 | {"$GMFolder":"","%Name":"Objects","folderPath":"folders/Objects.yy","name":"Objects","resourceType":"GMFolder","resourceVersion":"2.0",}, 18 | {"$GMFolder":"","%Name":"Particle Systems","folderPath":"folders/Particle Systems.yy","name":"Particle Systems","resourceType":"GMFolder","resourceVersion":"2.0",}, 19 | {"$GMFolder":"","%Name":"Paths","folderPath":"folders/Paths.yy","name":"Paths","resourceType":"GMFolder","resourceVersion":"2.0",}, 20 | {"$GMFolder":"","%Name":"Rooms","folderPath":"folders/Rooms.yy","name":"Rooms","resourceType":"GMFolder","resourceVersion":"2.0",}, 21 | {"$GMFolder":"","%Name":"Scripts","folderPath":"folders/Scripts.yy","name":"Scripts","resourceType":"GMFolder","resourceVersion":"2.0",}, 22 | {"$GMFolder":"","%Name":"Sequences","folderPath":"folders/Sequences.yy","name":"Sequences","resourceType":"GMFolder","resourceVersion":"2.0",}, 23 | {"$GMFolder":"","%Name":"Shaders","folderPath":"folders/Shaders.yy","name":"Shaders","resourceType":"GMFolder","resourceVersion":"2.0",}, 24 | {"$GMFolder":"","%Name":"Sounds","folderPath":"folders/Sounds.yy","name":"Sounds","resourceType":"GMFolder","resourceVersion":"2.0",}, 25 | {"$GMFolder":"","%Name":"Sprites","folderPath":"folders/Sprites.yy","name":"Sprites","resourceType":"GMFolder","resourceVersion":"2.0",}, 26 | {"$GMFolder":"","%Name":"Tile Sets","folderPath":"folders/Tile Sets.yy","name":"Tile Sets","resourceType":"GMFolder","resourceVersion":"2.0",}, 27 | {"$GMFolder":"","%Name":"Timelines","folderPath":"folders/Timelines.yy","name":"Timelines","resourceType":"GMFolder","resourceVersion":"2.0",}, 28 | ], 29 | "IncludedFiles":[], 30 | "isEcma":false, 31 | "LibraryEmitters":[], 32 | "MetaData":{ 33 | "IDEVersion":"2024.2.0.132", 34 | }, 35 | "name":"CascadeVisualDemo", 36 | "resources":[ 37 | {"id":{"name":"Fnt_Sample","path":"fonts/Fnt_Sample/Fnt_Sample.yy",},}, 38 | {"id":{"name":"Obj_MergingSample","path":"objects/Obj_MergingSample/Obj_MergingSample.yy",},}, 39 | {"id":{"name":"Obj_SampleObject","path":"objects/Obj_SampleObject/Obj_SampleObject.yy",},}, 40 | {"id":{"name":"Obj_SampleObjectDF","path":"objects/Obj_SampleObjectDF/Obj_SampleObjectDF.yy",},}, 41 | {"id":{"name":"Obj_SampleScaling","path":"objects/Obj_SampleScaling/Obj_SampleScaling.yy",},}, 42 | {"id":{"name":"Rm_SampleRoom","path":"rooms/Rm_SampleRoom/Rm_SampleRoom.yy",},}, 43 | {"id":{"name":"Shd_Bilinear","path":"shaders/Shd_Bilinear/Shd_Bilinear.yy",},}, 44 | {"id":{"name":"Shd_CascadeVisual","path":"shaders/Shd_CascadeVisual/Shd_CascadeVisual.yy",},}, 45 | {"id":{"name":"Shd_CascadeVisualDF","path":"shaders/Shd_CascadeVisualDF/Shd_CascadeVisualDF.yy",},}, 46 | {"id":{"name":"Spr_SampleSprite","path":"sprites/Spr_SampleSprite/Spr_SampleSprite.yy",},}, 47 | ], 48 | "resourceType":"GMProject", 49 | "resourceVersion":"2.0", 50 | "RoomOrderNodes":[ 51 | {"roomId":{"name":"Rm_SampleRoom","path":"rooms/Rm_SampleRoom/Rm_SampleRoom.yy",},}, 52 | ], 53 | "templateType":null, 54 | "TextureGroups":[ 55 | {"$GMTextureGroup":"","%Name":"Default","autocrop":true,"border":2,"compressFormat":"bz2","customOptions":"","directory":"","groupParent":null,"isScaled":true,"loadType":"default","mipsToGenerate":0,"name":"Default","resourceType":"GMTextureGroup","resourceVersion":"2.0","targets":-1,}, 56 | ], 57 | } -------------------------------------------------------------------------------- /RadianceCascades/shaders/Shd_RadianceIntervals/Shd_RadianceIntervals.fsh: -------------------------------------------------------------------------------- 1 | varying vec2 in_TextCoord; 2 | uniform float in_RenderExtent; // Scren Space Resolution. 3 | uniform sampler2D in_DistanceField; // World Input Distance Field. 4 | uniform sampler2D in_WorldScene; // World Input Raymarch Scene. 5 | uniform float in_RenderDecayRate; // How quickly 6 | 7 | uniform float in_CascadeExtent; // Cascade Diagonal Resolution. 8 | uniform float in_CascadeSpacing; // Cascade 0 probe spacing. 9 | uniform float in_CascadeInterval; // Cascade 0 radiance interval. 10 | uniform float in_CascadeAngular; // Cascade angular resolution. 11 | uniform float in_CascadeIndex; // Cascade index. 12 | 13 | #define EPSILON 0.0001 14 | #define TAU 6.283185 15 | #define V2F16(v) ((v.y * float(0.0039215689)) + v.x) 16 | 17 | struct ProbeTexel { 18 | float count; // number of ray-directions in this probe. 19 | vec2 probe; // the cell index of this probe. 20 | vec2 spacing; // spacing between radiance probes. 21 | float index; // the theta-index of this texel in it's probe. 22 | float minimum; // minimum interval-range. 23 | float range; // interval length (range). 24 | float texel; // texel size: 1.0 / cascadeExtent; 25 | //vec2 position; // cascade texel probe position. 26 | }; 27 | 28 | ProbeTexel cascadeProbeTexel(vec2 coord, float cascade) { 29 | float count = in_CascadeAngular * pow(4.0, cascade); 30 | float size = sqrt(count); 31 | vec2 probe = floor(coord / vec2(size)); 32 | vec2 spacing = vec2(in_CascadeSpacing * pow(2.0, cascade)); 33 | 34 | vec2 probePos = mod(floor(coord), vec2(size)); 35 | float index = (probePos.y * size) + probePos.x; 36 | 37 | float minimum = sign(cascade) * ((in_CascadeInterval * (1.0 - pow(4.0, cascade))) / (1.0 - 4.0)); 38 | float range = in_CascadeInterval * pow(4.0, cascade); 39 | 40 | // Light Leak Fix: (expand interval by diag-length of the cascade spacing). 41 | float d = in_CascadeSpacing * pow(2.0, cascade+1.0); 42 | range += sign(cascade) * length(vec2(d,d)); 43 | 44 | float texel = 1.0 / in_RenderExtent; 45 | return ProbeTexel(count, probe, spacing, index, minimum, range, texel /*, probePos / vec2(size)*/); 46 | } 47 | 48 | // Raymarching function: Raymarch from "pos" in direction of "delta," for length of "range" (non-normalized, range in pixel space): 49 | vec4 raymarch(vec2 pos, vec2 delta, float range, float texel) { 50 | // 51 | // Ray Visibility Term: The A (Alpha Component) returns the transparency of this ray. 52 | // * A visibility term of 0.0 means this ray is fully opaque (object hit). 53 | // * A visibility term of 1.0 means this ray is transparent (no hit). 54 | // When merging cascade rays with NO hits (1.0 visibility term) are the only 55 | // rays which will merge with above cascades. This applies merging/smoothing 56 | // of rays between cascade ranges to create those smooth shadows. 57 | // 58 | // Interval Raymarching (raymarches a specific range away from probe): 59 | // 60 | for(float ii = 0.0, dd = 0.0, rd = 0.0, rt = range * texel; ii < range; ii++) { 61 | vec2 ray = pos + delta * min(rd, rt); 62 | rd += dd = V2F16(texture2D(in_DistanceField, ray).rg); 63 | // Offscreen or End of Interval no collision: 64 | if (rd >= rt || ray.x < 0.0 || ray.y < 0.0 || ray.x >= 1.0 || ray.y >= 1.0) break; 65 | // Surface/Object collision: 66 | if (dd <= EPSILON) return vec4(texture2D(in_WorldScene, ray).rgb, 1.0); 67 | } 68 | return vec4(0.0, 0.0, 0.0, 0.0); 69 | } 70 | 71 | // Default Ray-marching Implementation. 72 | vec4 marchInterval_VanillaBranch(vec2 texel) { 73 | ProbeTexel probeInfo = cascadeProbeTexel(texel, in_CascadeIndex); 74 | vec2 probe = vec2((probeInfo.probe+0.5) * probeInfo.spacing) * probeInfo.texel; 75 | float theta = TAU * ((probeInfo.index+0.5) / probeInfo.count); 76 | vec2 delta = vec2(cos(theta), -sin(theta)); 77 | vec2 interval = probe + (delta * probeInfo.minimum * probeInfo.texel); 78 | return raymarch(interval, delta, probeInfo.range, probeInfo.texel); 79 | } 80 | 81 | void main() { 82 | vec2 texel = in_TextCoord * vec2(in_CascadeExtent); 83 | gl_FragColor = marchInterval_VanillaBranch(texel); 84 | } 85 | 86 | // 87 | // Cascade Radiance: 88 | // gl_FragColor = vec4(intervalRayMarch(probeInfo).rgb, 1.0); 89 | // 90 | // Cascade Prob Texel Space: 91 | // gl_FragColor = vec4(probeInfo.position, 0.0, 1.0); 92 | // 93 | -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_RadianceCascades_NearestFix/Shd_RadianceCascades_NearestFix.fsh: -------------------------------------------------------------------------------- 1 | varying vec2 in_TexelCoord; 2 | uniform sampler2D in_RenderScene; 3 | uniform sampler2D in_DistanceField; 4 | uniform vec2 in_RenderExtent; 5 | uniform vec2 in_CascadeExtent; 6 | uniform float in_CascadeCount; 7 | uniform float in_CascadeIndex; 8 | uniform float in_CascadeLinear; 9 | uniform float in_CascadeInterval; 10 | uniform float in_WorldTime; 11 | 12 | #define TAU 6.283185 13 | #define PI (0.5*TAU) 14 | #define V2F16(v) ((v.y * float(0.0039215689)) + v.x) 15 | #define SRGB(c) pow(c.rgb, vec3(2.2)) 16 | #define LINEAR(c) pow(c.rgb, vec3(1.0 / 2.2)) 17 | 18 | vec4 raymarch(vec2 origin, vec2 delta, float interval) { 19 | for(float ii = 0.0, dd = 0.0, rr = 0.0, ee = 0.00001, scale = length(in_RenderExtent); ii < interval; ii++) { 20 | vec2 ray = (origin + (delta * rr)) * (1.0 / in_RenderExtent); 21 | rr += scale * (dd = V2F16(texture2D(in_DistanceField, ray).rg)); 22 | if (rr >= interval || floor(ray) != vec2(0.0)) break; 23 | if (dd <= ee) return vec4(SRGB(texture2D(in_RenderScene, ray).rgb), 0.0); 24 | } 25 | return vec4(0.0, 0.0, 0.0, 1.0); 26 | } 27 | 28 | vec4 mergeNearestProbe(vec4 radiance, float index, vec2 probe) { 29 | if (radiance.a == 0.0 || in_CascadeIndex >= in_CascadeCount - 1.0) 30 | return vec4(radiance.rgb, 1.0 - radiance.a); 31 | 32 | float angularN1 = pow(2.0, floor(in_CascadeIndex + 1.0)); 33 | vec2 extentN1 = floor(in_CascadeExtent / angularN1); 34 | vec2 interpN1 = vec2(mod(index, angularN1), floor(index / angularN1)) * extentN1; 35 | interpN1 += clamp(probe + 0.5, vec2(0.5), extentN1 - vec2(0.5)); 36 | return texture2D(gm_BaseTexture, interpN1 * (1.0 / in_CascadeExtent)); 37 | } 38 | 39 | void main() { 40 | vec2 coord = floor(in_TexelCoord * in_CascadeExtent); 41 | float sqr_angular = pow(2.0, floor(in_CascadeIndex)); 42 | vec2 extent = floor(in_CascadeExtent / sqr_angular); 43 | vec4 probe = vec4(mod(coord, extent), floor(coord / extent)); 44 | float interval = (in_CascadeInterval * (1.0 - pow(4.0, in_CascadeIndex))) / (1.0 - 4.0); 45 | float limit = in_CascadeInterval * pow(4.0, in_CascadeIndex); 46 | 47 | float interval_start = interval; 48 | float interval_end = interval + limit; 49 | 50 | vec2 linear = vec2(in_CascadeLinear * pow(2.0, in_CascadeIndex)); 51 | vec2 linearN1 = vec2(in_CascadeLinear * pow(2.0, in_CascadeIndex + 1.0)); 52 | 53 | vec2 origin = (probe.xy + 0.5) * linear; 54 | float angular = sqr_angular * sqr_angular * 4.0; 55 | float index = (probe.z + (probe.w * sqr_angular)) * 4.0; 56 | 57 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 58 | // Nearest Neighbor: 59 | vec2 probeN1 = floor(probe.xy * 0.5); 60 | vec2 originN1 = (probeN1 + 0.5) * linearN1; 61 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 62 | 63 | gl_FragColor = vec4(0.0); 64 | for(float i = 0.0; i < 4.0; i++) { 65 | float preavg = index + float(i); 66 | float theta = (preavg + 0.5) * (TAU / angular); 67 | float thetaNm1 = (floor(preavg/4.0) + 0.5) * (TAU / (angular/4.0)); 68 | vec2 delta = vec2(cos(theta), -sin(theta)); 69 | vec2 deltaNm1 = vec2(cos(thetaNm1), -sin(thetaNm1)); 70 | vec2 ray_start = origin + (deltaNm1 * interval); 71 | 72 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 73 | /// Nearest Neighbor: 74 | vec2 ray_end = originN1 + (delta * (interval + limit)); 75 | vec4 rad = raymarch(ray_start, normalize(ray_end - ray_start), length(ray_end - ray_start)); 76 | rad = mergeNearestProbe(rad, preavg, probeN1); 77 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 78 | 79 | gl_FragColor += rad * 0.25; 80 | } 81 | 82 | if (in_CascadeIndex < 1.0) 83 | gl_FragColor = vec4(LINEAR(gl_FragColor), 1.0); 84 | } 85 | 86 | /* 87 | Nearest-Neighbor Fix: 88 | This is a no-interpolation "reprojection fix," where rays are reprojected to point 89 | towards the rays of the nearest probe within the higher cascade. 90 | 91 | We only merge with the nearest cN+1 probe rather than interpolating between rays 92 | of each bilinear probe (TL, TR, BL and BR). 93 | 94 | To fix light leak rays are "forked," starting from 1/4th as many positions to match 95 | the angular resolution of the previous cascade for perfectly continuous intervals. 96 | */ -------------------------------------------------------------------------------- /RadianceCascades/options/android/options_android.yy: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "GMAndroidOptions", 3 | "resourceVersion": "1.0", 4 | "name": "Android", 5 | "option_android_application_tag_inject": "", 6 | "option_android_arch_arm64": true, 7 | "option_android_arch_armv7": false, 8 | "option_android_arch_x86_64": false, 9 | "option_android_build_tools": "", 10 | "option_android_compile_sdk": "", 11 | "option_android_device_support": 0, 12 | "option_android_display_name": "Created with GameMaker", 13 | "option_android_facebook_app_display_name": "", 14 | "option_android_facebook_id": "", 15 | "option_android_gamepad_support": true, 16 | "option_android_google_apk_expansion": false, 17 | "option_android_google_cloud_saving": false, 18 | "option_android_google_dynamic_asset_delivery": false, 19 | "option_android_google_licensing_public_key": "", 20 | "option_android_google_services_app_id": "", 21 | "option_android_icon_adaptive_generate": false, 22 | "option_android_icon_adaptive_hdpi": "${base_options_dir}/android/icons_adaptive/hdpi.png", 23 | "option_android_icon_adaptive_ldpi": "${base_options_dir}/android/icons_adaptive/ldpi.png", 24 | "option_android_icon_adaptive_mdpi": "${base_options_dir}/android/icons_adaptive/mdpi.png", 25 | "option_android_icon_adaptive_xhdpi": "${base_options_dir}/android/icons_adaptive/xhdpi.png", 26 | "option_android_icon_adaptive_xxhdpi": "${base_options_dir}/android/icons_adaptive/xxhdpi.png", 27 | "option_android_icon_adaptive_xxxhdpi": "${base_options_dir}/android/icons_adaptive/xxxhdpi.png", 28 | "option_android_icon_adaptivebg_hdpi": "${base_options_dir}/android/icons_adaptivebg/hdpi.png", 29 | "option_android_icon_adaptivebg_ldpi": "${base_options_dir}/android/icons_adaptivebg/ldpi.png", 30 | "option_android_icon_adaptivebg_mdpi": "${base_options_dir}/android/icons_adaptivebg/mdpi.png", 31 | "option_android_icon_adaptivebg_xhdpi": "${base_options_dir}/android/icons_adaptivebg/xhdpi.png", 32 | "option_android_icon_adaptivebg_xxhdpi": "${base_options_dir}/android/icons_adaptivebg/xxhdpi.png", 33 | "option_android_icon_adaptivebg_xxxhdpi": "${base_options_dir}/android/icons_adaptivebg/xxxhdpi.png", 34 | "option_android_icon_hdpi": "${base_options_dir}/android/icons/hdpi.png", 35 | "option_android_icon_ldpi": "${base_options_dir}/android/icons/ldpi.png", 36 | "option_android_icon_mdpi": "${base_options_dir}/android/icons/mdpi.png", 37 | "option_android_icon_xhdpi": "${base_options_dir}/android/icons/xhdpi.png", 38 | "option_android_icon_xxhdpi": "${base_options_dir}/android/icons/xxhdpi.png", 39 | "option_android_icon_xxxhdpi": "${base_options_dir}/android/icons/xxxhdpi.png", 40 | "option_android_install_location": 0, 41 | "option_android_interpolate_pixels": false, 42 | "option_android_launchscreen_fill": 0, 43 | "option_android_lint": false, 44 | "option_android_logcat": "yoyo:V DEBUG:V AndroidRuntime:V", 45 | "option_android_minimum_sdk": "", 46 | "option_android_orient_landscape": true, 47 | "option_android_orient_landscape_flipped": true, 48 | "option_android_orient_portrait": true, 49 | "option_android_orient_portrait_flipped": true, 50 | "option_android_package_company": "company", 51 | "option_android_package_domain": "com", 52 | "option_android_package_product": "game", 53 | "option_android_permission_bluetooth": true, 54 | "option_android_permission_internet": true, 55 | "option_android_permission_network_state": false, 56 | "option_android_permission_read_phone_state": false, 57 | "option_android_permission_record_audio": false, 58 | "option_android_permission_write_external_storage": false, 59 | "option_android_proguard_minifying": false, 60 | "option_android_proguard_shrinking": false, 61 | "option_android_scale": 0, 62 | "option_android_screen_depth": 0, 63 | "option_android_sleep_margin": 4, 64 | "option_android_splash_screens_landscape": "${base_options_dir}/android/splash/landscape.png", 65 | "option_android_splash_screens_portrait": "${base_options_dir}/android/splash/portrait.png", 66 | "option_android_splash_time": 0, 67 | "option_android_splashscreen_background_colour": 255, 68 | "option_android_support_lib": "", 69 | "option_android_sync_amazon": false, 70 | "option_android_target_sdk": "", 71 | "option_android_texture_page": "2048x2048", 72 | "option_android_tools_from_version": false, 73 | "option_android_tv_banner": "${base_options_dir}/android/tv_banner.png", 74 | "option_android_tv_isgame": true, 75 | "option_android_use_facebook": false, 76 | "option_android_version": "1.0.0.0", 77 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/options/android/options_android.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMAndroidOptions":"", 3 | "%Name":"Android", 4 | "name":"Android", 5 | "option_android_application_tag_inject":"", 6 | "option_android_arch_arm64":true, 7 | "option_android_arch_armv7":false, 8 | "option_android_arch_x86_64":false, 9 | "option_android_attribute_allow_backup":false, 10 | "option_android_build_tools":"", 11 | "option_android_compile_sdk":"", 12 | "option_android_device_support":0, 13 | "option_android_display_name":"Created with GameMaker", 14 | "option_android_facebook_app_display_name":"", 15 | "option_android_facebook_id":"", 16 | "option_android_gamepad_support":true, 17 | "option_android_google_apk_expansion":false, 18 | "option_android_google_cloud_saving":false, 19 | "option_android_google_dynamic_asset_delivery":false, 20 | "option_android_google_licensing_public_key":"", 21 | "option_android_google_services_app_id":"", 22 | "option_android_icon_adaptivebg_hdpi":"${base_options_dir}/android/icons_adaptivebg/hdpi.png", 23 | "option_android_icon_adaptivebg_ldpi":"${base_options_dir}/android/icons_adaptivebg/ldpi.png", 24 | "option_android_icon_adaptivebg_mdpi":"${base_options_dir}/android/icons_adaptivebg/mdpi.png", 25 | "option_android_icon_adaptivebg_xhdpi":"${base_options_dir}/android/icons_adaptivebg/xhdpi.png", 26 | "option_android_icon_adaptivebg_xxhdpi":"${base_options_dir}/android/icons_adaptivebg/xxhdpi.png", 27 | "option_android_icon_adaptivebg_xxxhdpi":"${base_options_dir}/android/icons_adaptivebg/xxxhdpi.png", 28 | "option_android_icon_adaptive_generate":false, 29 | "option_android_icon_adaptive_hdpi":"${base_options_dir}/android/icons_adaptive/hdpi.png", 30 | "option_android_icon_adaptive_ldpi":"${base_options_dir}/android/icons_adaptive/ldpi.png", 31 | "option_android_icon_adaptive_mdpi":"${base_options_dir}/android/icons_adaptive/mdpi.png", 32 | "option_android_icon_adaptive_xhdpi":"${base_options_dir}/android/icons_adaptive/xhdpi.png", 33 | "option_android_icon_adaptive_xxhdpi":"${base_options_dir}/android/icons_adaptive/xxhdpi.png", 34 | "option_android_icon_adaptive_xxxhdpi":"${base_options_dir}/android/icons_adaptive/xxxhdpi.png", 35 | "option_android_icon_hdpi":"${base_options_dir}/android/icons/hdpi.png", 36 | "option_android_icon_ldpi":"${base_options_dir}/android/icons/ldpi.png", 37 | "option_android_icon_mdpi":"${base_options_dir}/android/icons/mdpi.png", 38 | "option_android_icon_xhdpi":"${base_options_dir}/android/icons/xhdpi.png", 39 | "option_android_icon_xxhdpi":"${base_options_dir}/android/icons/xxhdpi.png", 40 | "option_android_icon_xxxhdpi":"${base_options_dir}/android/icons/xxxhdpi.png", 41 | "option_android_install_location":0, 42 | "option_android_interpolate_pixels":false, 43 | "option_android_launchscreen_fill":0, 44 | "option_android_lint":false, 45 | "option_android_logcat":"yoyo:V DEBUG:V AndroidRuntime:V", 46 | "option_android_minimum_sdk":"", 47 | "option_android_orient_landscape":true, 48 | "option_android_orient_landscape_flipped":true, 49 | "option_android_orient_portrait":true, 50 | "option_android_orient_portrait_flipped":true, 51 | "option_android_package_company":"company", 52 | "option_android_package_domain":"com", 53 | "option_android_package_product":"game", 54 | "option_android_permission_bluetooth":true, 55 | "option_android_permission_internet":true, 56 | "option_android_permission_network_state":false, 57 | "option_android_permission_read_phone_state":false, 58 | "option_android_permission_record_audio":false, 59 | "option_android_permission_write_external_storage":false, 60 | "option_android_proguard_minifying":false, 61 | "option_android_proguard_shrinking":false, 62 | "option_android_scale":0, 63 | "option_android_screen_depth":0, 64 | "option_android_sleep_margin":4, 65 | "option_android_splashscreen_background_colour":255, 66 | "option_android_splash_screens_landscape":"${base_options_dir}/android/splash/landscape.png", 67 | "option_android_splash_screens_portrait":"${base_options_dir}/android/splash/portrait.png", 68 | "option_android_splash_time":0, 69 | "option_android_support_lib":"", 70 | "option_android_sync_amazon":false, 71 | "option_android_target_sdk":"", 72 | "option_android_texture_page":"2048x2048", 73 | "option_android_tools_from_version":false, 74 | "option_android_tv_banner":"${base_options_dir}/android/tv_banner.png", 75 | "option_android_tv_isgame":true, 76 | "option_android_tv_supports_leanback":true, 77 | "option_android_use_facebook":false, 78 | "option_android_version":"1.0.0.0", 79 | "resourceType":"GMAndroidOptions", 80 | "resourceVersion":"2.0", 81 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/options/android/options_android.yy: -------------------------------------------------------------------------------- 1 | { 2 | "$GMAndroidOptions":"", 3 | "%Name":"Android", 4 | "name":"Android", 5 | "option_android_application_tag_inject":"", 6 | "option_android_arch_arm64":true, 7 | "option_android_arch_armv7":false, 8 | "option_android_arch_x86_64":false, 9 | "option_android_attribute_allow_backup":false, 10 | "option_android_build_tools":"", 11 | "option_android_compile_sdk":"", 12 | "option_android_device_support":0, 13 | "option_android_display_name":"Created with GameMaker", 14 | "option_android_facebook_app_display_name":"", 15 | "option_android_facebook_id":"", 16 | "option_android_gamepad_support":true, 17 | "option_android_google_apk_expansion":false, 18 | "option_android_google_cloud_saving":false, 19 | "option_android_google_dynamic_asset_delivery":false, 20 | "option_android_google_licensing_public_key":"", 21 | "option_android_google_services_app_id":"", 22 | "option_android_icon_adaptivebg_hdpi":"${base_options_dir}/android/icons_adaptivebg/hdpi.png", 23 | "option_android_icon_adaptivebg_ldpi":"${base_options_dir}/android/icons_adaptivebg/ldpi.png", 24 | "option_android_icon_adaptivebg_mdpi":"${base_options_dir}/android/icons_adaptivebg/mdpi.png", 25 | "option_android_icon_adaptivebg_xhdpi":"${base_options_dir}/android/icons_adaptivebg/xhdpi.png", 26 | "option_android_icon_adaptivebg_xxhdpi":"${base_options_dir}/android/icons_adaptivebg/xxhdpi.png", 27 | "option_android_icon_adaptivebg_xxxhdpi":"${base_options_dir}/android/icons_adaptivebg/xxxhdpi.png", 28 | "option_android_icon_adaptive_generate":false, 29 | "option_android_icon_adaptive_hdpi":"${base_options_dir}/android/icons_adaptive/hdpi.png", 30 | "option_android_icon_adaptive_ldpi":"${base_options_dir}/android/icons_adaptive/ldpi.png", 31 | "option_android_icon_adaptive_mdpi":"${base_options_dir}/android/icons_adaptive/mdpi.png", 32 | "option_android_icon_adaptive_xhdpi":"${base_options_dir}/android/icons_adaptive/xhdpi.png", 33 | "option_android_icon_adaptive_xxhdpi":"${base_options_dir}/android/icons_adaptive/xxhdpi.png", 34 | "option_android_icon_adaptive_xxxhdpi":"${base_options_dir}/android/icons_adaptive/xxxhdpi.png", 35 | "option_android_icon_hdpi":"${base_options_dir}/android/icons/hdpi.png", 36 | "option_android_icon_ldpi":"${base_options_dir}/android/icons/ldpi.png", 37 | "option_android_icon_mdpi":"${base_options_dir}/android/icons/mdpi.png", 38 | "option_android_icon_xhdpi":"${base_options_dir}/android/icons/xhdpi.png", 39 | "option_android_icon_xxhdpi":"${base_options_dir}/android/icons/xxhdpi.png", 40 | "option_android_icon_xxxhdpi":"${base_options_dir}/android/icons/xxxhdpi.png", 41 | "option_android_install_location":0, 42 | "option_android_interpolate_pixels":false, 43 | "option_android_launchscreen_fill":0, 44 | "option_android_lint":false, 45 | "option_android_logcat":"yoyo:V DEBUG:V AndroidRuntime:V", 46 | "option_android_minimum_sdk":"", 47 | "option_android_orient_landscape":true, 48 | "option_android_orient_landscape_flipped":true, 49 | "option_android_orient_portrait":true, 50 | "option_android_orient_portrait_flipped":true, 51 | "option_android_package_company":"company", 52 | "option_android_package_domain":"com", 53 | "option_android_package_product":"game", 54 | "option_android_permission_bluetooth":true, 55 | "option_android_permission_internet":true, 56 | "option_android_permission_network_state":false, 57 | "option_android_permission_read_phone_state":false, 58 | "option_android_permission_record_audio":false, 59 | "option_android_permission_write_external_storage":false, 60 | "option_android_proguard_minifying":false, 61 | "option_android_proguard_shrinking":false, 62 | "option_android_scale":0, 63 | "option_android_screen_depth":0, 64 | "option_android_sleep_margin":4, 65 | "option_android_splashscreen_background_colour":255, 66 | "option_android_splash_screens_landscape":"${base_options_dir}/android/splash/landscape.png", 67 | "option_android_splash_screens_portrait":"${base_options_dir}/android/splash/portrait.png", 68 | "option_android_splash_time":0, 69 | "option_android_support_lib":"", 70 | "option_android_sync_amazon":false, 71 | "option_android_target_sdk":"", 72 | "option_android_texture_page":"2048x2048", 73 | "option_android_tools_from_version":false, 74 | "option_android_tv_banner":"${base_options_dir}/android/tv_banner.png", 75 | "option_android_tv_isgame":true, 76 | "option_android_tv_supports_leanback":true, 77 | "option_android_use_facebook":false, 78 | "option_android_version":"1.0.0.0", 79 | "resourceType":"GMAndroidOptions", 80 | "resourceVersion":"2.0", 81 | } -------------------------------------------------------------------------------- /CascadeVisualDemo/objects/Obj_SampleObjectDF/Draw_0.gml: -------------------------------------------------------------------------------- 1 | gpu_set_blendenable(false); 2 | shader_set(Shd_CascadeVisualDF); 3 | shader_set_uniform_f(shader_get_uniform(Shd_CascadeVisualDF, "in_CascadeSize"), cascade_size); 4 | shader_set_uniform_f(shader_get_uniform(Shd_CascadeVisualDF, "in_CascadeIndex"), cascadeIndex); 5 | 6 | surface_set_target(render_surface); 7 | var sprw = sprite_get_width(Spr_SampleSprite); 8 | var sprh = sprite_get_height(Spr_SampleSprite); 9 | draw_sprite_ext(Spr_SampleSprite, 0, 0, 0, cascade_size/sprw, cascade_size/sprh, 0, c_white, 1); 10 | surface_reset_target(); 11 | shader_reset(); 12 | gpu_set_blendenable(true); 13 | gpu_set_tex_filter(false); 14 | draw_surface_ext(render_surface, cascade_offsetx, cascade_offsety, render_size/cascade_size, render_size/cascade_size, 0, c_white, 1); 15 | gpu_set_tex_filter(true); 16 | 17 | draw_set_color(c_white); 18 | draw_set_font(Fnt_Sample); 19 | draw_set_halign(fa_left); 20 | draw_text(cascade_offsetx, cascade_offsety - 32, "Cascade Memory:"); 21 | draw_text(cascade_offsetx2, cascade_offsety2 - 32, "Screen Probe/Ray Spacing:"); 22 | draw_set_halign(fa_center); 23 | draw_text(cascade_offsetx + render_size, cascade_offsety + render_size + 16, 24 | "Controls: [Up]/[Down] Probe Spacing; [Left]/[Right] Cascade Index"); 25 | draw_text(cascade_offsetx + render_size, cascade_offsety + render_size + 40, 26 | "[Space] to switch to Position-First Probe Layout"); 27 | draw_text(cascade_offsetx + render_size, cascade_offsety + render_size + 64, 28 | "[Right-Click] change ray direction with mouse"); 29 | 30 | draw_set_color(c_red); 31 | draw_rectangle(cascade_offsetx2, cascade_offsety2, cascade_offsetx2 + render_size - 1, cascade_offsety2 + render_size - 1, true); 32 | 33 | for(var xx = 0; xx < probeCount; xx++) { 34 | for(var yy = 0; yy < probeCount; yy++) { 35 | var pspacing = probeSpacing * (render_size / cascade_size); 36 | draw_circle(cascade_offsetx2 + (pspacing * 0.5) + (pspacing * xx), cascade_offsety2 + (pspacing * 0.5) + (pspacing * yy), 2, false); 37 | } 38 | } 39 | 40 | draw_set_color(c_blue); 41 | 42 | draw_rectangle(cascade_offsetx2 + current_probex, 43 | cascade_offsety2 + current_probey, 44 | cascade_offsetx2 + current_probex + current_probesize - 1, 45 | cascade_offsety2 + current_probey + current_probesize - 1, true); 46 | 47 | draw_set_color(c_aqua); 48 | 49 | var mrindex = floor((track_moused / 360.0) * (current_angular * 4)); 50 | 51 | for(var r = 0; r < (current_angular * 4); r++) { 52 | var dx1, dy1, dx2, dy2, dt, intrs, intr; 53 | intrs = current_intervalstart * (render_size / cascade_size); 54 | intr = current_interval * (render_size / cascade_size); 55 | dt = ((r + 0.5) / (current_angular * 4)) * 2.0 * pi; 56 | dx1 = lengthdir_x(intrs, radtodeg(dt)); 57 | dy1 = lengthdir_y(intrs, radtodeg(dt)); 58 | dx2 = lengthdir_x(intrs + intr, radtodeg(dt)); 59 | dy2 = lengthdir_y(intrs + intr, radtodeg(dt)); 60 | 61 | if (floor(r / 4) == floor(mrindex / 4)) { 62 | draw_set_color(c_yellow); 63 | } else { 64 | draw_set_color(c_aqua); 65 | } 66 | 67 | draw_line( 68 | cascade_offsetx2 + current_probex + (current_probesize * 0.5) + dx1, 69 | cascade_offsety2 + current_probey + (current_probesize * 0.5) + dy1, 70 | cascade_offsetx2 + current_probex + (current_probesize * 0.5) + dx2, 71 | cascade_offsety2 + current_probey + (current_probesize * 0.5) + dy2); 72 | } 73 | 74 | draw_set_color(c_fuchsia); 75 | 76 | var dx, dy, dr; 77 | var croffset = (render_size / cascade_size) * 0.5; 78 | dr = ((mrindex + 0.5) / (current_angular * 4)) * 2.0 * pi; 79 | dx = lengthdir_x(intrs + intr, radtodeg(dr)); 80 | dy = lengthdir_y(intrs + intr, radtodeg(dr)); 81 | draw_circle(cascade_offsetx2 + current_probex + (current_probesize * 0.5) + dx, 82 | cascade_offsety2 + current_probey + (current_probesize * 0.5) + dy, croffset, false); 83 | 84 | var angular_offsetx, angular_offsety, dfirst_offsetx, dfirst_offsety; 85 | angular_offsetx = floor((mrindex / 4.0) % sqrt(current_angular)) * current_sectorsize; 86 | angular_offsety = floor((mrindex / 4.0) / sqrt(current_angular)) * current_sectorsize; 87 | show_debug_message(string(floor(mrindex / 4.0)) + " : " + string(angular_offsetx) + " : " + string(angular_offsety)) 88 | dfirst_offsetx = (current_sectorsize * (current_probex / render_size)) + (croffset * 0.5) + angular_offsetx; 89 | dfirst_offsety = (current_sectorsize * (current_probey / render_size)) + (croffset * 0.5) + angular_offsety; 90 | 91 | draw_circle(cascade_offsetx + dfirst_offsetx, cascade_offsety + dfirst_offsety, croffset, false); 92 | //var rayx = mrindex mod sqrt(current_angular / 4.0) * (render_size / cascade_size); 93 | //var rayy = floor(mrindex / sqrt(current_angular / 4.0)) * (render_size / cascade_size); 94 | //draw_circle(cascade_offsetx + current_probex + croffset + rayx, cascade_offsety + current_probey + croffset + rayy, croffset, false); 95 | 96 | draw_set_color(c_white); -------------------------------------------------------------------------------- /RadianceCascades-Optimized/RadianceCascades-Optimized.yyp: -------------------------------------------------------------------------------- 1 | { 2 | "$GMProject":"", 3 | "%Name":"RadianceCascades-Optimized", 4 | "AudioGroups":[ 5 | {"$GMAudioGroup":"","%Name":"audiogroup_default","name":"audiogroup_default","resourceType":"GMAudioGroup","resourceVersion":"2.0","targets":-1,}, 6 | ], 7 | "configs":{ 8 | "children":[], 9 | "name":"Default", 10 | }, 11 | "defaultScriptType":1, 12 | "Folders":[ 13 | {"$GMFolder":"","%Name":"Animation Curves","folderPath":"folders/Animation Curves.yy","name":"Animation Curves","resourceType":"GMFolder","resourceVersion":"2.0",}, 14 | {"$GMFolder":"","%Name":"Extensions","folderPath":"folders/Extensions.yy","name":"Extensions","resourceType":"GMFolder","resourceVersion":"2.0",}, 15 | {"$GMFolder":"","%Name":"Fonts","folderPath":"folders/Fonts.yy","name":"Fonts","resourceType":"GMFolder","resourceVersion":"2.0",}, 16 | {"$GMFolder":"","%Name":"Notes","folderPath":"folders/Notes.yy","name":"Notes","resourceType":"GMFolder","resourceVersion":"2.0",}, 17 | {"$GMFolder":"","%Name":"Objects","folderPath":"folders/Objects.yy","name":"Objects","resourceType":"GMFolder","resourceVersion":"2.0",}, 18 | {"$GMFolder":"","%Name":"Particle Systems","folderPath":"folders/Particle Systems.yy","name":"Particle Systems","resourceType":"GMFolder","resourceVersion":"2.0",}, 19 | {"$GMFolder":"","%Name":"Paths","folderPath":"folders/Paths.yy","name":"Paths","resourceType":"GMFolder","resourceVersion":"2.0",}, 20 | {"$GMFolder":"","%Name":"Rooms","folderPath":"folders/Rooms.yy","name":"Rooms","resourceType":"GMFolder","resourceVersion":"2.0",}, 21 | {"$GMFolder":"","%Name":"Scripts","folderPath":"folders/Scripts.yy","name":"Scripts","resourceType":"GMFolder","resourceVersion":"2.0",}, 22 | {"$GMFolder":"","%Name":"Sequences","folderPath":"folders/Sequences.yy","name":"Sequences","resourceType":"GMFolder","resourceVersion":"2.0",}, 23 | {"$GMFolder":"","%Name":"Shaders","folderPath":"folders/Shaders.yy","name":"Shaders","resourceType":"GMFolder","resourceVersion":"2.0",}, 24 | {"$GMFolder":"","%Name":"Sounds","folderPath":"folders/Sounds.yy","name":"Sounds","resourceType":"GMFolder","resourceVersion":"2.0",}, 25 | {"$GMFolder":"","%Name":"Sprites","folderPath":"folders/Sprites.yy","name":"Sprites","resourceType":"GMFolder","resourceVersion":"2.0",}, 26 | {"$GMFolder":"","%Name":"Tile Sets","folderPath":"folders/Tile Sets.yy","name":"Tile Sets","resourceType":"GMFolder","resourceVersion":"2.0",}, 27 | {"$GMFolder":"","%Name":"Timelines","folderPath":"folders/Timelines.yy","name":"Timelines","resourceType":"GMFolder","resourceVersion":"2.0",}, 28 | ], 29 | "IncludedFiles":[], 30 | "isEcma":false, 31 | "LibraryEmitters":[], 32 | "MetaData":{ 33 | "IDEVersion":"2024.2.0.132", 34 | }, 35 | "name":"RadianceCascades-Optimized", 36 | "resources":[ 37 | {"id":{"name":"Obj_LineTesting","path":"objects/Obj_LineTesting/Obj_LineTesting.yy",},}, 38 | {"id":{"name":"Obj_RadianceCascades","path":"objects/Obj_RadianceCascades/Obj_RadianceCascades.yy",},}, 39 | {"id":{"name":"Rm_TestRoom","path":"rooms/Rm_TestRoom/Rm_TestRoom.yy",},}, 40 | {"id":{"name":"Scr_HelperFunctions","path":"scripts/Scr_HelperFunctions/Scr_HelperFunctions.yy",},}, 41 | {"id":{"name":"Shd_DistanceField","path":"shaders/Shd_DistanceField/Shd_DistanceField.yy",},}, 42 | {"id":{"name":"Shd_JumpFlood","path":"shaders/Shd_JumpFlood/Shd_JumpFlood.yy",},}, 43 | {"id":{"name":"Shd_RadianceCascades_BilinearFix","path":"shaders/Shd_RadianceCascades_BilinearFix/Shd_RadianceCascades_BilinearFix.yy",},}, 44 | {"id":{"name":"Shd_RadianceCascades_Final","path":"shaders/Shd_RadianceCascades_Final/Shd_RadianceCascades_Final.yy",},}, 45 | {"id":{"name":"Shd_RadianceCascades_FPFixed","path":"shaders/Shd_RadianceCascades_FPFixed/Shd_RadianceCascades_FPFixed.yy",},}, 46 | {"id":{"name":"Shd_RadianceCascades_InterlacedFix","path":"shaders/Shd_RadianceCascades_InterlacedFix/Shd_RadianceCascades_InterlacedFix.yy",},}, 47 | {"id":{"name":"Shd_RadianceCascades_NearestFix","path":"shaders/Shd_RadianceCascades_NearestFix/Shd_RadianceCascades_NearestFix.yy",},}, 48 | {"id":{"name":"Shd_RadianceCascades","path":"shaders/Shd_RadianceCascades/Shd_RadianceCascades.yy",},}, 49 | {"id":{"name":"Shd_SeedJumpFlood","path":"shaders/Shd_SeedJumpFlood/Shd_SeedJumpFlood.yy",},}, 50 | {"id":{"name":"Spr_SampleScene","path":"sprites/Spr_SampleScene/Spr_SampleScene.yy",},}, 51 | ], 52 | "resourceType":"GMProject", 53 | "resourceVersion":"2.0", 54 | "RoomOrderNodes":[ 55 | {"roomId":{"name":"Rm_TestRoom","path":"rooms/Rm_TestRoom/Rm_TestRoom.yy",},}, 56 | ], 57 | "templateType":"game", 58 | "TextureGroups":[ 59 | {"$GMTextureGroup":"","%Name":"Default","autocrop":true,"border":2,"compressFormat":"bz2","customOptions":"","directory":"","groupParent":null,"isScaled":true,"loadType":"default","mipsToGenerate":0,"name":"Default","resourceType":"GMTextureGroup","resourceVersion":"2.0","targets":-1,}, 60 | ], 61 | } -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_RadianceCascades_BilinearFix/Shd_RadianceCascades_BilinearFix.fsh: -------------------------------------------------------------------------------- 1 | varying vec2 in_TexelCoord; 2 | uniform sampler2D in_RenderScene; 3 | uniform sampler2D in_DistanceField; 4 | uniform vec2 in_RenderExtent; 5 | uniform vec2 in_CascadeExtent; 6 | uniform float in_CascadeCount; 7 | uniform float in_CascadeIndex; 8 | uniform float in_CascadeLinear; 9 | uniform float in_CascadeInterval; 10 | 11 | #define TAU 6.283185 12 | #define PI (0.5*TAU) 13 | #define V2F16(v) ((v.y * float(0.0039215689)) + v.x) 14 | #define SRGB(c) pow(c.rgb, vec3(2.2)) 15 | #define LINEAR(c) pow(c.rgb, vec3(1.0 / 2.2)) 16 | 17 | vec4 raymarch(vec2 origin, vec2 delta, float interval) { 18 | for(float ii = 0.0, dd = 0.0, rr = 0.0, ee = 0.00001, scale = length(in_RenderExtent); ii < interval; ii++) { 19 | vec2 ray = (origin + (delta * rr)) * (1.0 / in_RenderExtent); 20 | rr += scale * (dd = V2F16(texture2D(in_DistanceField, ray).rg)); 21 | if (rr >= interval || floor(ray) != vec2(0.0)) break; 22 | if (dd <= ee) return vec4(SRGB(texture2D(in_RenderScene, ray).rgb), 0.0); 23 | } 24 | return vec4(0.0, 0.0, 0.0, 1.0); 25 | } 26 | 27 | vec4 mergeNearestProbe(vec4 radiance, float index, vec2 probe) { 28 | if (radiance.a == 0.0 || in_CascadeIndex >= in_CascadeCount - 1.0) 29 | return vec4(radiance.rgb, 1.0 - radiance.a); 30 | 31 | float angularN1 = pow(2.0, floor(in_CascadeIndex + 1.0)); 32 | vec2 extentN1 = floor(in_CascadeExtent / angularN1); 33 | vec2 interpN1 = vec2(mod(index, angularN1), floor(index / angularN1)) * extentN1; 34 | interpN1 += clamp(probe + 0.5, vec2(0.5), extentN1 - vec2(0.5)); 35 | return texture2D(gm_BaseTexture, interpN1 * (1.0 / in_CascadeExtent)); 36 | } 37 | 38 | void getBilinearProbes(vec2 probe, out vec2 probes[4]) { 39 | vec2 probeN1 = floor((probe - 1.0) / 2.0); 40 | probes[0] = probeN1 + vec2(0.0, 0.0); 41 | probes[1] = probeN1 + vec2(1.0, 0.0); 42 | probes[2] = probeN1 + vec2(0.0, 1.0); 43 | probes[3] = probeN1 + vec2(1.0, 1.0); 44 | } 45 | 46 | float ATAN2(float yy, float xx) { return mod(atan(yy, xx), TAU); } 47 | 48 | void main() { 49 | vec2 coord = floor(in_TexelCoord * in_CascadeExtent); 50 | float sqr_angular = pow(2.0, floor(in_CascadeIndex)); 51 | vec2 extent = floor(in_CascadeExtent / sqr_angular); 52 | vec4 probe = vec4(mod(coord, extent), floor(coord / extent)); 53 | float interval = (in_CascadeInterval * (1.0 - pow(4.0, in_CascadeIndex))) / (1.0 - 4.0); 54 | float limit = in_CascadeInterval * pow(4.0, in_CascadeIndex); 55 | 56 | float interval_start = interval; 57 | float interval_end = interval + limit; 58 | 59 | vec2 linear = vec2(in_CascadeLinear * pow(2.0, in_CascadeIndex)); 60 | vec2 linearN1 = vec2(in_CascadeLinear * pow(2.0, in_CascadeIndex + 1.0)); 61 | 62 | vec2 origin = (probe.xy + 0.5) * linear; 63 | float angular = sqr_angular * sqr_angular * 4.0; 64 | float index = (probe.z + (probe.w * sqr_angular)) * 4.0; 65 | 66 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 67 | // Bilinear Fix: 68 | vec2 bilinearN1[4]; 69 | getBilinearProbes(probe.xy, bilinearN1); 70 | vec2 texelIndexN1 = floor((vec2(probe.xy) - 1.0) / 2.0); 71 | vec2 texelIndexN1_N = floor((texelIndexN1 * 2.0) + 1.0); 72 | vec2 weight = vec2(0.25) + (vec2(probe.xy) - texelIndexN1_N) * vec2(0.5); 73 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 74 | 75 | gl_FragColor = vec4(0.0); 76 | for(float i = 0.0; i < 4.0; i++) { 77 | float preavg = index + float(i); 78 | float theta = (preavg + 0.5) * (TAU / angular); 79 | float thetaNm1 = (floor(preavg/4.0) + 0.5) * (TAU / (angular/4.0)); 80 | vec2 delta = vec2(cos(theta), -sin(theta)); 81 | vec2 deltaNm1 = vec2(cos(thetaNm1), -sin(thetaNm1)); 82 | vec2 ray_start = origin + (deltaNm1 * interval); 83 | 84 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 85 | /// Bilinear Fix: 86 | vec4 samples[4]; 87 | for(float j = 0.0; j < 4.0; j++) { 88 | vec2 originN1 = (bilinearN1[int(j)] + 0.5) * linearN1; 89 | vec2 ray_end = originN1 + (delta * (interval + limit)); 90 | samples[int(j)] = raymarch(ray_start, normalize(ray_end - ray_start), length(ray_end - ray_start)); 91 | samples[int(j)] = mergeNearestProbe(samples[int(j)], preavg, bilinearN1[int(j)]); 92 | } 93 | 94 | vec4 top = mix(samples[0], samples[1], weight.x); 95 | vec4 bot = mix(samples[2], samples[3], weight.x); 96 | vec4 rad = mix(top, bot, weight.y); 97 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 98 | 99 | gl_FragColor += rad * 0.25; 100 | } 101 | 102 | if (in_CascadeIndex < 1.0) 103 | gl_FragColor = vec4(LINEAR(gl_FragColor), 1.0); 104 | } 105 | 106 | /* 107 | Bilinear Fix: 108 | This is a reprojection fix which casts 4x as many rays, one ray to the starting position 109 | of each set of bilinear rays (merged rays from bilinear probes). This ensures that we 110 | continuously and consistently observe radiance projected from each bilinear probe. 111 | 112 | Then each ray merges with the rays from its respective bilinear-probe WITHOUT interpolation. 113 | Finally radiance is manually interpolated from the reprojected bilinear-rays just like Vanilla RC. 114 | 115 | To fix light leak rays are "forked," starting from 1/4th as many positions to match 116 | the angular resolution of the previous cascade for perfectly continuous intervals. 117 | */ -------------------------------------------------------------------------------- /RadianceCascades-Optimized/shaders/Shd_RadianceCascades_InterlacedFix/Shd_RadianceCascades_InterlacedFix.fsh: -------------------------------------------------------------------------------- 1 | varying vec2 in_TexelCoord; 2 | uniform sampler2D in_RenderScene; 3 | uniform sampler2D in_DistanceField; 4 | uniform vec2 in_RenderExtent; 5 | uniform vec2 in_CascadeExtent; 6 | uniform float in_CascadeCount; 7 | uniform float in_CascadeIndex; 8 | uniform float in_CascadeLinear; 9 | uniform float in_CascadeInterval; 10 | uniform float in_WorldTime; 11 | 12 | #define TAU 6.283185 13 | #define PI (0.5*TAU) 14 | #define V2F16(v) ((v.y * float(0.0039215689)) + v.x) 15 | #define SRGB(c) pow(c.rgb, vec3(2.2)) 16 | #define LINEAR(c) pow(c.rgb, vec3(1.0 / 2.2)) 17 | 18 | vec4 raymarch(vec2 origin, vec2 delta, float interval) { 19 | for(float ii = 0.0, dd = 0.0, rr = 0.0, ee = 0.00001, scale = length(in_RenderExtent); ii < interval; ii++) { 20 | vec2 ray = (origin + (delta * rr)) * (1.0 / in_RenderExtent); 21 | rr += scale * (dd = V2F16(texture2D(in_DistanceField, ray).rg)); 22 | if (rr >= interval || floor(ray) != vec2(0.0)) break; 23 | if (dd <= ee) return vec4(SRGB(texture2D(in_RenderScene, ray).rgb), 0.0); 24 | } 25 | return vec4(0.0, 0.0, 0.0, 1.0); 26 | } 27 | 28 | vec4 mergeNearestProbe(vec4 radiance, float index, vec2 probe) { 29 | if (radiance.a == 0.0 || in_CascadeIndex >= in_CascadeCount - 1.0) 30 | return vec4(radiance.rgb, 1.0 - radiance.a); 31 | 32 | float angularN1 = pow(2.0, floor(in_CascadeIndex + 1.0)); 33 | vec2 extentN1 = floor(in_CascadeExtent / angularN1); 34 | vec2 interpN1 = vec2(mod(index, angularN1), floor(index / angularN1)) * extentN1; 35 | interpN1 += clamp(probe + 0.5, vec2(0.5), extentN1 - vec2(0.5)); 36 | return texture2D(gm_BaseTexture, interpN1 * (1.0 / in_CascadeExtent)); 37 | } 38 | 39 | void getInterlacedProbes(vec2 probe, out vec2 probes[4]) { 40 | vec2 probeN1 = floor((probe - 1.0) / 2.0); 41 | // Blurrier: 42 | probes[2] = probeN1 + vec2(0.0, 0.0); 43 | probes[1] = probeN1 + vec2(1.0, 0.0); 44 | probes[0] = probeN1 + vec2(0.0, 1.0); 45 | probes[3] = probeN1 + vec2(1.0, 1.0); 46 | 47 | // Sharper: 48 | //probes[1] = probeN1 + vec2(0.0, 0.0); 49 | //probes[0] = probeN1 + vec2(1.0, 0.0); 50 | //probes[2] = probeN1 + vec2(0.0, 1.0); 51 | //probes[3] = probeN1 + vec2(1.0, 1.0); 52 | } 53 | 54 | float ATAN2(float yy, float xx) { return mod(atan(yy, xx), TAU); } 55 | 56 | void main() { 57 | vec2 coord = floor(in_TexelCoord * in_CascadeExtent); 58 | float sqr_angular = pow(2.0, floor(in_CascadeIndex)); 59 | vec2 extent = floor(in_CascadeExtent / sqr_angular); 60 | vec4 probe = vec4(mod(coord, extent), floor(coord / extent)); 61 | float interval = (in_CascadeInterval * (1.0 - pow(4.0, in_CascadeIndex))) / (1.0 - 4.0); 62 | float limit = in_CascadeInterval * pow(4.0, in_CascadeIndex); 63 | 64 | float interval_start = interval; 65 | float interval_end = interval + limit; 66 | 67 | vec2 linear = vec2(in_CascadeLinear * pow(2.0, in_CascadeIndex)); 68 | vec2 linearN1 = vec2(in_CascadeLinear * pow(2.0, in_CascadeIndex + 1.0)); 69 | 70 | vec2 origin = (probe.xy + 0.5) * linear; 71 | float angular = sqr_angular * sqr_angular * 4.0; 72 | float index = (probe.z + (probe.w * sqr_angular)) * 4.0; 73 | 74 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 75 | // Nearest Interlaced: 76 | vec2 probesN1[4]; 77 | getInterlacedProbes(probe.xy, probesN1); 78 | vec2 probeN1 = floor(probe.xy * 0.5); 79 | float offset = (probe.x * 2.0) + probe.y; 80 | probeN1 = probesN1[int(mod(offset, 4.0))]; 81 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 82 | 83 | gl_FragColor = vec4(0.0); 84 | for(float i = 0.0; i < 4.0; i++) { 85 | float preavg = index + float(i); 86 | float theta = (preavg + 0.5) * (TAU / angular); 87 | float thetaNm1 = (floor(preavg/4.0) + 0.5) * (TAU / (angular/4.0)); 88 | vec2 delta = vec2(cos(theta), -sin(theta)); 89 | vec2 deltaNm1 = vec2(cos(thetaNm1), -sin(thetaNm1)); 90 | vec2 ray_start = origin + (deltaNm1 * interval); 91 | 92 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 93 | /// Nearest Interlaced: 94 | vec2 originN1 = (probeN1 + 0.5) * linearN1; 95 | vec2 ray_end = originN1 + (delta * (interval + limit)); 96 | vec4 rad = raymarch(ray_start, normalize(ray_end - ray_start), length(ray_end - ray_start)); 97 | rad = mergeNearestProbe(rad, preavg, probeN1); 98 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 99 | 100 | gl_FragColor += rad * 0.25; 101 | } 102 | 103 | if (in_CascadeIndex < 1.0) 104 | gl_FragColor = vec4(LINEAR(gl_FragColor), 1.0); 105 | } 106 | 107 | /* 108 | Nearest-Interlaced Fix: 109 | Nearest-Interlaced is the same as Nearest-Neighbor, except that we "interlace," the 110 | nearest cN+1 probe such that no probe of any 2x2 group of cN probes share the same 111 | cN+1 probe. With 1/2 as many cN+1 probes per axis in cN we have one cN+1 probe per 112 | 2x2 group of cN probes. The goal is to ensure that these 2x2 probe groups cannot 113 | share the same cN+1 probe. This produces a form of stylistic dithering while solving 114 | ringing and smoothing radiance. 115 | 116 | Nearest-Neighbor Fix: 117 | This is a no-interpolation "reprojection fix," where rays are reprojected to point 118 | towards the rays of the nearest-interlaced probe within the higher cascade. 119 | 120 | We only merge with the nearest-interlaced cN+1 probe rather than interpolating between rays 121 | of each bilinear probe (TL, TR, BL and BR). 122 | 123 | To fix light leak rays are "forked," starting from 1/4th as many positions to match 124 | the angular resolution of the previous cascade for perfectly continuous intervals. 125 | */ -------------------------------------------------------------------------------- /RadianceCascades-Optimized/objects/Obj_RadianceCascades/Create_0.gml: -------------------------------------------------------------------------------- 1 | /* 2 | Implementation assumes pre-averging--cannot be disabled. 3 | Due to pre-averaging, angular resolution for cascade0 is defaulted to 4-rays per-pixel. Instead decrease linear 4 | spacing-as explained below--to increase visual fidelity. With 4-ray-per-pixel and pre-averaging cascade0 always 5 | contains the final displayable output radiance. 6 | */ 7 | 8 | game_set_speed(60, gamespeed_fps); 9 | 10 | // Should be pow2 sizes only (either whole or fractional: 0.25, 0.5, 1.0, 2.0, 4.0, 8.0, etc.). 11 | // Increasing linear spacing will reduce quality, decreasing linear spacing will increase quality. 12 | render_linear = 1.0; 13 | 14 | // Should be equal to diagonal of the square of linear resolution. 15 | // Set to a large distance for debugging (should see individually cascaded rays in scene). 16 | render_interval = point_distance(0.0, 0.0, render_linear, render_linear) * 0.5; 17 | 18 | render_width = 1920; 19 | render_height = 1080; 20 | 21 | // PENDING IMPLEMENTATION: 22 | // render_skybox = make_color_normalized_rgb(0.2, 0.5, 1.0); 23 | // render_sunbox = make_color_normalized_rgb(1.0, 0.7, 0.1); 24 | 25 | // Calculate the max cascade count based on the highest interval distance that would reach outside the screen. 26 | // Valdiate intput and correct input settings. 27 | // Divide the final cascade size by 2, since we're "pre-avergaing." 28 | // Angular resolution is now set to a minimuim default 4-rays per probe (keeps cascade size consistent). 29 | // Fidelity can be increased by decreasing spacing between probes instead of rays per probe. 30 | radiance_cascades = ceil(logn(4, point_distance(0, 0, render_width, render_height))); 31 | radiance_linear = power_ofN(render_linear, 2); 32 | radiance_interval = multiple_ofN(render_interval, 2); 33 | 34 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 35 | // FIXES CASCADE RAY/PROBE TRADE-OFF ERROR RATE FOR NON-POW2 RESOLUTIONS: (very important). 36 | error_rate = power(2.0, radiance_cascades - 1); 37 | errorx = ceil(render_width / error_rate); 38 | errory = ceil(render_height / error_rate); 39 | render_width = errorx * error_rate; 40 | render_height = errory * error_rate; 41 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 42 | 43 | radiance_width = floor(render_width / radiance_linear); 44 | radiance_height = floor(render_height / radiance_linear); 45 | cascade_index = 0; 46 | 47 | show_debug_message("Render Extent: " + string(render_width) + " : " + string(render_height)); 48 | show_debug_message("Radiance Extent: " + string(radiance_width) + " : " + string(radiance_height)); 49 | show_debug_message("Radiance Cascades: " + string(radiance_cascades)); 50 | 51 | // Create a render list of surfaces that will be re-built everyframe. 52 | radiance_renderlist = ds_list_create(); 53 | radiance_world = surface_build(render_width, render_height, surface_rgba8unorm, radiance_renderlist); // Intput game/world scene to process. 54 | radiance_jfa = surface_build(render_width, render_height, surface_rgba8unorm, radiance_renderlist); // Intput game/world scene to process. 55 | radiance_sdf = surface_build(render_width, render_height, surface_rgba8unorm, radiance_renderlist); // Intput game/world scene to process. 56 | radiance_current = surface_build(radiance_width, radiance_height, surface_rgba16float, radiance_renderlist); // Fetch texture for current cascade. 57 | radiance_previous = surface_build(radiance_width, radiance_height, surface_rgba16float, radiance_renderlist); // Fetch texture for previous cascade. 58 | 59 | // Shader uniform inputs for Intervals and Merging combined into a single shader. 60 | //radiance_u_cascades = Shd_RadianceCascades; 61 | //radiance_u_cascades = Shd_RadianceCascades_FPFixed; 62 | //radiance_u_cascades = Shd_RadianceCascades_Final; 63 | //radiance_u_cascades = Shd_RadianceCascades_InterlacedFix; 64 | //radiance_u_cascades = Shd_RadianceCascades_NearestFix; 65 | radiance_u_cascades = Shd_RadianceCascades_BilinearFix; 66 | radiance_u_cascades_RenderScene = texture(radiance_u_cascades, "in_RenderScene"); 67 | radiance_u_cascades_DistanceField = texture(radiance_u_cascades, "in_DistanceField"); 68 | radiance_u_cascades_RenderExtent = uniform(radiance_u_cascades, "in_RenderExtent"); 69 | radiance_u_cascades_CascadeExtent = uniform(radiance_u_cascades, "in_CascadeExtent"); 70 | radiance_u_cascades_CascadeCount = uniform(radiance_u_cascades, "in_CascadeCount"); 71 | radiance_u_cascades_CascadeIndex = uniform(radiance_u_cascades, "in_CascadeIndex"); 72 | radiance_u_cascades_CascadeLinear = uniform(radiance_u_cascades, "in_CascadeLinear"); 73 | radiance_u_cascades_CascadeInterval = uniform(radiance_u_cascades, "in_CascadeInterval"); 74 | 75 | radiance_u_jumpflood = Shd_JumpFlood; 76 | radiance_u_jumpflood_uRenderExtent = uniform(radiance_u_jumpflood, "in_RenderExtent"); 77 | radiance_u_jumpflood_uJumpDistance = uniform(radiance_u_jumpflood, "in_JumpDistance"); 78 | 79 | radiance_u_distancefield = Shd_DistanceField; 80 | radiance_u_distancefield_uRenderExtent = uniform(radiance_u_distancefield, "in_RenderExtent"); 81 | 82 | /* 83 | Forced Optimizations: 84 | 1. Pre-Averaging 85 | Merging happens top-down, e.g. we merge Cascade N into N-1. 86 | Since cascade N has 4x the number of rays per ray in cascade N-1, 87 | cascade N-1 must lookup the associated 4 rays per probe, average their 88 | results and then merge the results into the current ray. 89 | 90 | Instead we can cast 4 rays per texel, then average and store their 91 | results. That way during merging we only need to perform 1 texel lookup. 92 | This is called pre-merge averaging, which allows for a 75% memory reduction. 93 | 94 | Also pre-averaging causes inconcsistent cascade sizes if you start cascade0 95 | with 1 ray-per-probe which complicates the implementation. Instead angular 96 | resolution is fixed (4 rays per probe in cascade0) to maintain consistency. 97 | Instead you can adjust the linear resolution (up or down) to change visual 98 | fidelity. Linear Resolution (probe spacing) can be less than one (0.5 or 1/2, 99 | 0.25 or 1/4, 0.125 or 1/8, etc.) so long as the number is a power of 2. 100 | 101 | NOTE: We're dividng the memory space by 4x, but we do so across two axis, so 102 | we actually divide each individual x/y-axis by 2x for a total 4x reduction. 103 | 104 | 2. Direction First Storage 105 | Each cascade stores results for ray hits cast from each probe. These rays 106 | are grouped together by their probe position in memory. So one "block," 107 | in memory represents on probe and each pixel in that block represents a ray. 108 | 109 | Instead we can store rays direction first, so that each "block," represents 110 | one ray direction and each pixel within that block represents a ray that is 111 | cast from a probe in that direction. 112 | 113 | This direction first approach allows us to utilize hardware interpolation 114 | between probes, since we interpolate between adjacent N+1 probes when merging. 115 | 116 | NOTE: That direction first + pre-averaging means that each ray actually 117 | represents 4 rays and each direction actually represents 4 directions. 118 | 119 | This combined result uses 75% less memory and 75% less merge samples and also 120 | benefits from texture cache localization and hardware interpolation. 121 | */ --------------------------------------------------------------------------------