diff --git a/objects/o_dialog_preference/Create_0.gml b/objects/o_dialog_preference/Create_0.gml index 0b55bb0c7..b08c8d86c 100644 --- a/objects/o_dialog_preference/Create_0.gml +++ b/objects/o_dialog_preference/Create_0.gml @@ -197,7 +197,7 @@ event_inherited(); )); ds_list_add(pref_global, new __Panel_Linear_Setting_Item_Preference( - __txtx("pref_enable_test_mode", "Enable developer mode" + "*"), + __txtx("pref_enable_test_mode", "Enable developer mode*"), "test_mode", new checkBox(function() /*=>*/ { PREFERENCES.test_mode = !PREFERENCES.test_mode; should_restart = true; PREF_SAVE(); }) )); @@ -205,7 +205,7 @@ event_inherited(); ds_list_add(pref_global, __txt("Paths")); ds_list_add(pref_global, new __Panel_Linear_Setting_Item( - __txtx("pref_directory", "Main directory path" + "*"), + __txtx("pref_directory", "Main directory path*"), new textBox(TEXTBOX_INPUT.text, function(txt) /*=>*/ { PRESIST_PREF.path = txt; json_save_struct(APP_DIRECTORY + "persistPreference.json", PRESIST_PREF); }) .setSideButton(button(function() /*=>*/ { PRESIST_PREF.path = get_directory(PRESIST_PREF.path); @@ -218,7 +218,7 @@ event_inherited(); )); ds_list_add(pref_global, new __Panel_Linear_Setting_Item_Preference( - __txtx("pref_directory_temp", "Temp directory path" + "*"), + __txtx("pref_directory_temp", "Temp directory path*"), "temp_path", new textBox(TEXTBOX_INPUT.text, function(txt) /*=>*/ { PREFERENCES.temp_path = txt; PREF_SAVE(); }) .setSideButton(button(function() /*=>*/ { PREFERENCES.temp_path = get_directory(PREFERENCES.temp_path); PREF_SAVE(); }, THEME.button_path_icon)) @@ -226,13 +226,13 @@ event_inherited(); )); ds_list_add(pref_global, new __Panel_Linear_Setting_Item_Preference( - __txtx("pref_directory_assets", "Assets directory path" + "*"), + __txtx("pref_directory_assets", "Assets directory path*"), "path_assets", new folderArrayBox(PREFERENCES.path_assets, function() /*=>*/ { PREF_SAVE(); }).setFont(f_p2), )); ds_list_add(pref_global, new __Panel_Linear_Setting_Item_Preference( - __txtx("pref_directory_font", "Font directory path" + "*"), + __txtx("pref_directory_font", "Font directory path*"), "path_fonts", new folderArrayBox(PREFERENCES.path_fonts, function() /*=>*/ { PREF_SAVE(); }).setFont(f_p2), )); @@ -240,7 +240,7 @@ event_inherited(); ds_list_add(pref_global, __txt("Libraries")); ds_list_add(pref_global, new __Panel_Linear_Setting_Item_Preference( - __txtx("pref_directory_ImageMagick", "ImageMagick path" + "*"), + __txtx("pref_directory_ImageMagick", "ImageMagick path*"), "ImageMagick_path", new textBox(TEXTBOX_INPUT.text, function(txt) /*=>*/ { PREFERENCES.ImageMagick_path = txt; PREF_SAVE(); }) .setSideButton(button(function() /*=>*/ { PREFERENCES.ImageMagick_path = get_directory(PREFERENCES.ImageMagick_path); PREF_SAVE(); }, THEME.button_path_icon)) @@ -248,7 +248,7 @@ event_inherited(); )); ds_list_add(pref_global, new __Panel_Linear_Setting_Item_Preference( - __txtx("pref_directory_webp", "Webp path" + "*"), + __txtx("pref_directory_webp", "Webp path*"), "webp_path", new textBox(TEXTBOX_INPUT.text, function(txt) /*=>*/ { PREFERENCES.webp_path = txt; PREF_SAVE(); }) .setSideButton(button(function() /*=>*/ { PREFERENCES.webp_path = get_directory(PREFERENCES.webp_path); PREF_SAVE(); }, THEME.button_path_icon)) @@ -256,7 +256,7 @@ event_inherited(); )); ds_list_add(pref_global, new __Panel_Linear_Setting_Item_Preference( - __txtx("pref_directory_gifski", "Gifski path" + "*"), + __txtx("pref_directory_gifski", "Gifski path*"), "gifski_path", new textBox(TEXTBOX_INPUT.text, function(txt) /*=>*/ { PREFERENCES.gifski_path = txt; PREF_SAVE(); }) .setSideButton(button(function() /*=>*/ { PREFERENCES.gifski_path = get_directory(PREFERENCES.gifski_path); PREF_SAVE(); }, THEME.button_path_icon)) @@ -264,7 +264,7 @@ event_inherited(); )); ds_list_add(pref_global, new __Panel_Linear_Setting_Item_Preference( - __txtx("pref_directory_FFmpeg", "FFmpeg path" + "*"), + __txtx("pref_directory_FFmpeg", "FFmpeg path*"), "ffmpeg_path", new textBox(TEXTBOX_INPUT.text, function(txt) /*=>*/ { PREFERENCES.gifski_path = txt; PREF_SAVE(); }) .setSideButton(button(function() /*=>*/ { PREFERENCES.ffmpeg_path = get_directory(PREFERENCES.ffmpeg_path); PREF_SAVE(); }, THEME.button_path_icon)) @@ -314,7 +314,7 @@ event_inherited(); file_find_close(); ds_list_add(pref_appr, new __Panel_Linear_Setting_Item_Preference( - __txtx("pref_interface_language", "Interface Language" + "*"), + __txtx("pref_interface_language", "Interface Language*"), "local", new scrollBox(locals, function(str) /*=>*/ { if(str < 0) return; diff --git a/scripts/node_rm_cloud/node_rm_cloud.gml b/scripts/node_rm_cloud/node_rm_cloud.gml index fdce43199..8fc0de9fe 100644 --- a/scripts/node_rm_cloud/node_rm_cloud.gml +++ b/scripts/node_rm_cloud/node_rm_cloud.gml @@ -24,7 +24,7 @@ function Node_RM_Cloud(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) inputs[| 7] = nodeValue("Detail", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 8); - inputs[| 8] = nodeValue("Threshold", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.5) + inputs[| 8] = nodeValue("Threshold", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.4) .setDisplay(VALUE_DISPLAY.slider); inputs[| 9] = nodeValue("Detail Scaling", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 2.); @@ -34,14 +34,19 @@ function Node_RM_Cloud(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) inputs[| 11] = nodeValue("Shape", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0) .setDisplay(VALUE_DISPLAY.enum_scroll, [ "Volume", "Plane" ]); - + + inputs[| 12] = nodeValue("Use Fog", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, 0) + + inputs[| 13] = nodeValue("Colors", self, JUNCTION_CONNECT.input, VALUE_TYPE.gradient, new gradientObject([ cola(c_black), cola(c_white) ]) ) + outputs[| 0] = nodeValue("Surface Out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone); input_display_list = [ 0, - ["Transform", false], 1, 2, 3, - ["Camera", false], 4, 5, - ["Cloud", false], 11, 6, 8, - ["Noise", false], 7, 9, 10, + ["Transform", false], 1, 2, 3, + ["Camera", false], 4, 5, + ["Cloud", false], 11, 6, 8, + ["Noise", false], 7, 9, 10, + ["Render", false], 13, 12, ]; static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {} @@ -67,6 +72,8 @@ function Node_RM_Cloud(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) var _itrr = _data[ 7]; var _dsca = _data[ 9]; var _datt = _data[10]; + var _fogu = _data[12]; + var _colr = _data[13]; _outSurf = surface_verify(_outSurf, _dim[0], _dim[1]); @@ -83,10 +90,13 @@ function Node_RM_Cloud(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) shader_set_f("density", _dens); shader_set_f("threshold", _thrs); + shader_set_i("fogUse", _fogu); shader_set_i("iteration", _itrr); shader_set_f("detailScale", _dsca); shader_set_f("detailAtten", _datt); + _colr.shader_submit(); + draw_sprite_stretched(s_fx_pixel, 0, 0, 0, _dim[0], _dim[1]); surface_reset_shader(); diff --git a/scripts/panel_preview/panel_preview.gml b/scripts/panel_preview/panel_preview.gml index 1b92b8763..6b123826a 100644 --- a/scripts/panel_preview/panel_preview.gml +++ b/scripts/panel_preview/panel_preview.gml @@ -27,6 +27,8 @@ function panel_preview_3d_view_left() { CALL("preview_3d_view_left"); PANEL_PREVIEW.d3_view_action_left(); } function panel_preview_3d_view_top() { CALL("preview_3d_view_top"); PANEL_PREVIEW.d3_view_action_top(); } function panel_preview_3d_view_bottom() { CALL("preview_3d_view_bottom"); PANEL_PREVIEW.d3_view_action_bottom(); } + + function panel_preview_set_zoom(zoom) { CALL("preview_preview_set_zoom"); PANEL_PREVIEW.fullView(zoom); } #endregion function Panel_Preview() : PanelContent() constructor { @@ -236,6 +238,11 @@ function Panel_Preview() : PanelContent() constructor { addHotkey("Preview", "3D Left view ", vk_numpad3, MOD_KEY.alt, panel_preview_3d_view_left); addHotkey("Preview", "3D Top view", vk_numpad7, MOD_KEY.none, panel_preview_3d_view_top); addHotkey("Preview", "3D Bottom view", vk_numpad7, MOD_KEY.alt, panel_preview_3d_view_bottom); + + addHotkey("Preview", "Scale x1", "1", MOD_KEY.none, function() /*=>*/ { panel_preview_set_zoom(1); }); + addHotkey("Preview", "Scale x2", "2", MOD_KEY.none, function() /*=>*/ { panel_preview_set_zoom(2); }); + addHotkey("Preview", "Scale x4", "3", MOD_KEY.none, function() /*=>*/ { panel_preview_set_zoom(4); }); + addHotkey("Preview", "Scale x8", "4", MOD_KEY.none, function() /*=>*/ { panel_preview_set_zoom(8); }); #endregion #region ++++ toolbars & actions ++++ @@ -476,10 +483,13 @@ function Panel_Preview() : PanelContent() constructor { if(canvas_zooming) { if(!MOUSE_WRAPPING) { - var dy = -(my - canvas_zoom_m) / 200; + // var mdx = mx - canvas_zoom_mx; + var mdy = my - canvas_zoom_m; + + var dd = -(mdy) / 200; var _s = canvas_s; - canvas_s = clamp(canvas_s * (1 + dy), 0.10, 64); + canvas_s = clamp(canvas_s * (1 + dd), 0.10, 64); if(_s != canvas_s) { var dx = (canvas_s - _s) * ((canvas_zoom_mx - canvas_x) / _s); @@ -505,9 +515,11 @@ function Panel_Preview() : PanelContent() constructor { if(mouse_press(PREFERENCES.pan_mouse_key, pFOCUS)) { _doDragging = true; canvas_drag_key = PREFERENCES.pan_mouse_key; + } else if(mouse_press(mb_left, pFOCUS) && canvas_dragging_key) { _doDragging = true; canvas_drag_key = mb_left; + } else if(mouse_press(mb_left, pFOCUS) && canvas_zooming_key) { _doZooming = true; canvas_drag_key = mb_left; @@ -612,10 +624,13 @@ function Panel_Preview() : PanelContent() constructor { if(mouse_press(PREFERENCES.pan_mouse_key, pFOCUS)) { _doDragging = true; canvas_drag_key = PREFERENCES.pan_mouse_key; + } else if(mouse_press(mb_left, pFOCUS) && canvas_dragging_key) { + _doDragging = true; canvas_drag_key = mb_left; } else if(mouse_press(mb_left, pFOCUS) && canvas_zooming_key) { + _doZooming = true; canvas_drag_key = mb_left; } @@ -640,7 +655,7 @@ function Panel_Preview() : PanelContent() constructor { canvas_hover = point_in_rectangle(mx, my, 0, toolbar_height, w, h - toolbar_height); } #endregion - function fullView() { + function fullView(scale = 0) { var bbox = noone; var node = getNodePreview(); @@ -659,7 +674,8 @@ function Panel_Preview() : PanelContent() constructor { var tl = tool_side_draw_l * 40; var tr = tool_side_draw_r * 40; - var ss = min((w - 32 - tl - tr) / _w, (h - 32 - toolbar_height * 2) / _h); + var ss = scale == 0? min((w - 32 - tl - tr) / _w, (h - 32 - toolbar_height * 2) / _h) : scale; + canvas_s = ss; canvas_x = w / 2 - _w * canvas_s / 2 - _x * canvas_s + (tl - tr) / 2; canvas_y = h / 2 - _h * canvas_s / 2 - _y * canvas_s; @@ -1545,13 +1561,10 @@ function Panel_Preview() : PanelContent() constructor { overHover &= !view_hovering; overHover &= tool_hovering == noone && !overlay_hovering; - overHover &= !(view_pan_tool || view_zoom_tool); + overHover &= !canvas_dragging && !canvas_zooming; overHover &= point_in_rectangle(mx, my, (_node.tools != -1) * toolbar_width, toolbar_height, w, h - toolbar_height); var overActive = active && overHover; - - var _dragging = key_mod_press(CTRL) && !key_mod_press(SHIFT) && !key_mod_press(ALT); - overActive &= !_dragging; var params = { w, h, toolbar_height }; var mouse_free = false; @@ -1578,7 +1591,7 @@ function Panel_Preview() : PanelContent() constructor { #region node overlay overlay_hovering = false; - + if(_node.drawPreviewToolOverlay(pHOVER, pFOCUS, _mx, _my, { x, y, w, h, toolbar_height, x0: _node.tools == -1? 0 : ui(40), x1: w, diff --git a/shaders/sh_rm_cloud/sh_rm_cloud.fsh b/shaders/sh_rm_cloud/sh_rm_cloud.fsh index 4378b5f41..090e80c47 100644 --- a/shaders/sh_rm_cloud/sh_rm_cloud.fsh +++ b/shaders/sh_rm_cloud/sh_rm_cloud.fsh @@ -4,7 +4,7 @@ varying vec2 v_vTexcoord; varying vec4 v_vColour; -const int MAX_MARCHING_STEPS = 512; +const int MAX_MARCHING_STEPS = 200; const float EPSILON = 1e-6; const float PI = 3.14159265358979323846; @@ -21,12 +21,140 @@ uniform int iteration; uniform float threshold; uniform int adaptiveIteration; +uniform int fogUse; uniform float detailScale; uniform float detailAtten; mat3 rotMatrix, irotMatrix; vec3 eye, dir; +#region //////////////////////////////////// GRADIENT //////////////////////////////////// + #define GRADIENT_LIMIT 128 + + uniform int gradient_blend; + uniform vec4 gradient_color[GRADIENT_LIMIT]; + uniform float gradient_time[GRADIENT_LIMIT]; + uniform int gradient_keys; + + vec3 linearToGamma(vec3 c) { return pow(c, vec3( 2.2)); } + vec3 gammaToLinear(vec3 c) { return pow(c, vec3(1. / 2.2)); } + + vec3 rgbMix(vec3 c1, vec3 c2, float t) { + vec3 k1 = linearToGamma(c1); + vec3 k2 = linearToGamma(c2); + + return gammaToLinear(mix(k1, k2, t)); + } + + vec3 rgb2oklab(vec3 c) { + const mat3 kCONEtoLMS = mat3( + 0.4121656120, 0.2118591070, 0.0883097947, + 0.5362752080, 0.6807189584, 0.2818474174, + 0.0514575653, 0.1074065790, 0.6302613616); + + c = pow(c, vec3(2.2)); + c = pow( kCONEtoLMS * c, vec3(1.0 / 3.0) ); + + return c; + } + + vec3 oklab2rgb(vec3 c) { + const mat3 kLMStoCONE = mat3( + 4.0767245293, -1.2681437731, -0.0041119885, + -3.3072168827, 2.6093323231, -0.7034763098, + 0.2307590544, -0.3411344290, 1.7068625689); + + c = kLMStoCONE * (c * c * c); + c = pow(c, vec3(1. / 2.2)); + + return c; + } + + vec3 oklabMax(vec3 c1, vec3 c2, float t) { + vec3 k1 = rgb2oklab(c1); + vec3 k2 = rgb2oklab(c2); + + return oklab2rgb(mix(k1, k2, t)); + } + + vec3 rgb2hsv(vec3 c) { + vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); + vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); + vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); + + float d = q.x - min(q.w, q.y); + float e = 0.0000000001; + return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); + } + + vec3 hsv2rgb(vec3 c) { + vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); + vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); + return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); + } + + float hueDist(float a0, float a1, float t) { + float da = fract(a1 - a0); + float ds = fract(2. * da) - da; + return a0 + ds * t; + } + + vec3 hsvMix(vec3 c1, vec3 c2, float t) { + vec3 h1 = rgb2hsv(c1); + vec3 h2 = rgb2hsv(c2); + + vec3 h = vec3(0.); + h.x = h.x + hueDist(h1.x, h2.x, t); + h.y = mix(h1.y, h2.y, t); + h.z = mix(h1.z, h2.z, t); + + return hsv2rgb(h); + } + + vec4 gradientEval(in float prog) { + vec4 col = vec4(0.); + + for(int i = 0; i < GRADIENT_LIMIT; i++) { + if(gradient_time[i] == prog) { + col = gradient_color[i]; + break; + } else if(gradient_time[i] > prog) { + if(i == 0) + col = gradient_color[i]; + else { + float t = (prog - gradient_time[i - 1]) / (gradient_time[i] - gradient_time[i - 1]); + vec3 c0 = gradient_color[i - 1].rgb; + vec3 c1 = gradient_color[i].rgb; + float a = mix(gradient_color[i - 1].a, gradient_color[i].a, t); + + if(gradient_blend == 0) + col = vec4(mix(c0, c1, t), a); + + else if(gradient_blend == 1) + col = gradient_color[i - 1]; + + else if(gradient_blend == 2) + col = vec4(hsvMix(c0, c1, t), a); + + else if(gradient_blend == 3) + col = vec4(oklabMax(c0, c1, t), a); + + else if(gradient_blend == 4) + col = vec4(rgbMix(c0, c1, t), a); + } + break; + } + if(i >= gradient_keys - 1) { + col = gradient_color[gradient_keys - 1]; + break; + } + } + + return col; + } + +#endregion //////////////////////////////////// GRADIENT //////////////////////////////////// + #region ////========== Transform ============ mat3 rotateX(float dg) { float c = cos(radians(dg)); @@ -76,10 +204,10 @@ vec3 eye, dir; #endregion #region ////============= Noise ============== - - vec3 mod289(vec3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; } - vec4 mod289(vec4 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; } - vec4 permute(vec4 x) { return mod289(((x * 34.0) + 10.0) * x); } + + vec3 mod289(vec3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; } + vec4 mod289(vec4 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; } + vec4 permute(vec4 x) { return mod289(((x * 34.0) + 10.0) * x); } vec4 taylorInvSqrt(vec4 r) { return 1.79284291400159 - 0.85373472095314 * r; } float snoise(vec3 vec) { @@ -195,6 +323,7 @@ float volume(vec3 pos, float ratio) { float ds = clamp(max(0., sp - thr) / (1. - thr), 0., 1.); ds *= d1; + if(fogUse == 1) ds *= sqrt(ratio); if(type == 0) return ds; else if(type == 1) return smoothstep(-.1, .1, pos.y) * ds; @@ -202,17 +331,23 @@ float volume(vec3 pos, float ratio) { return 0.; } -float marchDensity(vec3 camera, vec3 direction) { +vec3 marchDensity(in vec3 camera, in vec3 direction, out vec3 hitPos) { float maxx = float(MAX_MARCHING_STEPS); float st = 1. / maxx; - float _densi = 0.; + vec3 _densi = vec3(0.); float dens = pow(2., 10. * density - 10.); - + bool hitted = false; + for (float i = 0.; i <= maxx; i++) { float depth = mix(viewRange.x, viewRange.y, i * st); vec3 pos = camera + depth * direction; float mden = volume(pos, 1. - i * st); - _densi += dens * mden; + _densi += dens * gradientEval(mden).rgb; + + if(!hitted && mden > 0.) { + hitPos = pos; + hitted = true; + } } return _densi; @@ -234,6 +369,9 @@ void main() { eye /= objectScale; eye -= position; - float dens = marchDensity(eye, dir); - gl_FragColor = vec4(vec3(dens), 1.); + vec3 hitPos = vec3(0.); + vec3 rayDen = marchDensity(eye, dir, hitPos); + + vec3 color = rayDen; + gl_FragColor = vec4(color, 1.); } \ No newline at end of file