This commit is contained in:
Tanasart 2023-07-11 20:36:44 +02:00
parent 920c6dc1a7
commit d46795a40b
13 changed files with 1427 additions and 948 deletions

View file

@ -544,6 +544,7 @@
{"name":"sh_skew","order":6,"path":"shaders/sh_skew/sh_skew.yy",},
{"name":"libxprocess","order":4,"path":"extensions/libxprocess/libxprocess.yy",},
{"name":"fd_rectangle_get_pressure_height","order":16,"path":"scripts/fd_rectangle_get_pressure_height/fd_rectangle_get_pressure_height.yy",},
{"name":"hyperbolic_function","order":16,"path":"scripts/hyperbolic_function/hyperbolic_function.yy",},
{"name":"node_VFX_effect_destroy","order":12,"path":"scripts/node_VFX_effect_destroy/node_VFX_effect_destroy.yy",},
{"name":"node_cache","order":9,"path":"scripts/node_cache/node_cache.yy",},
{"name":"sh_bw","order":5,"path":"shaders/sh_bw/sh_bw.yy",},

View file

@ -1085,6 +1085,7 @@
{"id":{"name":"sh_skew","path":"shaders/sh_skew/sh_skew.yy",},},
{"id":{"name":"libxprocess","path":"extensions/libxprocess/libxprocess.yy",},},
{"id":{"name":"fd_rectangle_get_pressure_height","path":"scripts/fd_rectangle_get_pressure_height/fd_rectangle_get_pressure_height.yy",},},
{"id":{"name":"hyperbolic_function","path":"scripts/hyperbolic_function/hyperbolic_function.yy",},},
{"id":{"name":"s_node_fluidSim_repulse","path":"sprites/s_node_fluidSim_repulse/s_node_fluidSim_repulse.yy",},},
{"id":{"name":"node_VFX_effect_destroy","path":"scripts/node_VFX_effect_destroy/node_VFX_effect_destroy.yy",},},
{"id":{"name":"node_cache","path":"scripts/node_cache/node_cache.yy",},},

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,3 @@
function sinh(x) { return (exp(x) - exp(-x)) / 2; }
function cosh(x) { return (exp(x) + exp(-x)) / 2; }
function tanh(x) { return (exp(2 * x) - 1) / (exp(2 * x) + 1); }

View file

@ -0,0 +1,11 @@
{
"resourceType": "GMScript",
"resourceVersion": "1.0",
"name": "hyperbolic_function",
"isCompatibility": false,
"isDnD": false,
"parent": {
"name": "value",
"path": "folders/functions/value.yy",
},
}

View file

@ -2,17 +2,6 @@ function Node_Camera(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) co
name = "Camera";
preview_alpha = 0.5;
shader = sh_camera;
uni_backg = shader_get_sampler_index(shader, "backg");
uni_scene = shader_get_sampler_index(shader, "scene");
uni_dim_scn = shader_get_uniform(shader, "scnDimension");
uni_dim_cam = shader_get_uniform(shader, "camDimension");
uni_pos = shader_get_uniform(shader, "position");
uni_zom = shader_get_uniform(shader, "zoom");
uni_sam_mod = shader_get_uniform(shader, "sampleMode");
uni_blur = shader_get_uniform(shader, "blur");
uni_fix_bg = shader_get_uniform(shader, "fixBG");
inputs[| 0] = nodeValue("Background", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, 0);
inputs[| 1] = nodeValue("Focus area", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, [ 0, 0, 16, 16, AREA_SHAPE.rectangle ])
.setDisplay(VALUE_DISPLAY.area, function() { return getDimension(0); });
@ -21,15 +10,23 @@ function Node_Camera(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) co
.setDisplay(VALUE_DISPLAY.slider, [ 0.01, 4, 0.01 ]);
inputs[| 3] = nodeValue("Oversample mode", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0, "How to deal with pixel outside the surface.\n - Empty: Use empty pixel\n - Clamp: Repeat edge pixel\n - Repeat: Repeat texture.")
.setDisplay(VALUE_DISPLAY.enum_scroll, [ "Empty", "Repeat" ]);
.setDisplay(VALUE_DISPLAY.enum_scroll, [ "Empty", "Repeat", "Repeat X", "Repeat Y" ]);
inputs[| 4] = nodeValue("Fix background", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
inputs[| 5] = nodeValue("Depth of Field", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
inputs[| 6] = nodeValue("Focal distance", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0);
inputs[| 7] = nodeValue("Defocus", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1);
inputs[| 8] = nodeValue("Focal range", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0);
outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
input_display_list = [
["Background", true], 0, 4, 3,
["Camera", false], 1, 2,
["Camera", false], 1, 2, 5, 6, 8, 7,
["Elements", true],
];
@ -52,7 +49,7 @@ function Node_Camera(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) co
.setUnitRef(function(index) { return getDimension(index); });
inputs[| index + 2] = nodeValue($"Oversample {_s}", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
.setDisplay(VALUE_DISPLAY.enum_scroll, [ "Empty", "Repeat" ]);
.setDisplay(VALUE_DISPLAY.enum_scroll, [ "Empty", "Repeat", "Repeat X", "Repeat Y" ]);
array_append(input_display_list, [ index + 0, index + 1, index + 2 ]);
}
@ -128,6 +125,12 @@ function Node_Camera(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) co
var _zoom = _data[2];
var _samp = _data[3];
var _fix = _data[4];
var _dof = _data[5];
var _dof_dist = _data[6];
var _dof_stop = _data[7];
var _dof_rang = _data[8];
var cDep = attrDepth();
var _cam_x = round(_area[0]);
@ -147,58 +150,65 @@ function Node_Camera(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) co
surface_set_target(temp_surface[0]);
DRAW_CLEAR
BLEND_OVERRIDE;
if(amo <= 0) {
if(_fix) {
if(_samp) draw_surface_tiled_safe(_data[0], 0, 0);
else draw_surface_safe(_data[0], 0, 0);
} else {
var sx = _cam_x / _zoom - _cam_w;
var sy = _cam_y / _zoom - _cam_h;
if(_samp) draw_surface_tiled_ext_safe(_data[0], -sx, -sy, 1 / _zoom, 1 / _zoom, c_white, 1);
else draw_surface_ext_safe(_data[0], -sx, -sy, 1 / _zoom, 1 / _zoom, 0, c_white, 1);
}
} else {
var sx = _cam_x / _zoom - _cam_w;
var sy = _cam_y / _zoom - _cam_h;
if(_fix) draw_surface_safe(_data[0], 0, 0);
else draw_surface_tiled_ext_safe(_data[0], sx, sy, 1 / _zoom, 1 / _zoom, c_white, 1);
}
BLEND_NORMAL;
surface_reset_target();
surface_set_target(temp_surface[1]);
DRAW_CLEAR
surface_reset_target();
shader_set(shader);
shader_set_uniform_f(uni_dim_cam, _surf_w, _surf_h);
shader_set_uniform_f(uni_zom, _zoom);
shader_set(sh_camera);
shader_set_f("camDimension", _surf_w, _surf_h);
shader_set_f("zoom", _zoom);
for( var i = 0; i < amo; i++ ) {
var _surface, sx, sy, sz, _samp;
var px, py;
var _scnW, _scnH;
for( var i = -1; i < amo; i++ ) {
ppInd = !ppInd;
surface_set_target(temp_surface[ppInd]);
var ind = input_fix_len + i * data_length;
if(i == -1) {
_surface = _data[0];
sx = _fix? 0 : _cam_x;
sy = _fix? 0 : _cam_y;
sz = 0;
_samp = _data[3];
px = sx;
py = sy;
} else {
var ind = input_fix_len + i * data_length;
var _surface = _data[ind];
var sz = _data[ind + 1][2];
var sx = _data[ind + 1][0] * sz * _cam_x;
var sy = _data[ind + 1][1] * sz * _cam_y;
var _samp = _data[ind + 2];
_surface = _data[ind];
sz = _data[ind + 1][2];
sx = _data[ind + 1][0] * sz * _cam_x;
sy = _data[ind + 1][1] * sz * _cam_y;
_samp = _data[ind + 2];
px = _cam_x + sx;
py = _cam_y + sy;
}
var _scnW = surface_get_width(_surface);
var _scnH = surface_get_height(_surface);
_scnW = surface_get_width(_surface);
_scnH = surface_get_height(_surface);
shader_set_uniform_i(uni_sam_mod, _samp);
shader_set_uniform_f(uni_dim_scn, _scnW, _scnH);
shader_set_uniform_f(uni_blur, sz);
shader_set_uniform_f(uni_pos, (_cam_x + sx) / _scnW, (_cam_y + sy) / _scnH);
shader_set_uniform_i(uni_fix_bg, !i && _fix);
px /= _scnW;
py /= _scnH;
shader_set_i("bg", i == -1? 1 : 0);
shader_set_i("sampleMode", _samp);
shader_set_f("scnDimension", _scnW, _scnH);
shader_set_f("position", px, py);
if(_dof) {
var _x = max(abs(sz - _dof_dist) - _dof_rang, 0);
_x = _x * tanh(_x / 10);
shader_set_f("bokehStrength", _x * _dof_stop);
} else shader_set_f("bokehStrength", 0);
shader_set_surface("backg", temp_surface[!ppInd]); //prev surface
shader_set_surface("scene", _surface); //surface to draw
texture_set_stage(uni_backg, surface_get_texture(temp_surface[!ppInd])); //prev surface
texture_set_stage(uni_scene, surface_get_texture(_surface)); //surface to draw
draw_sprite_ext(s_fx_pixel, 0, 0, 0, _surf_w, _surf_h, 0, c_white, 1);
surface_reset_target();
}

View file

@ -719,6 +719,7 @@ function NodeObject(_name, _spr, _node, _create, tags = []) constructor {
}
function nodeGetData(str) {
str = string_trim(str);
var strs = string_splice(str, ".");
if(array_length(strs) == 0) return 0;
@ -726,7 +727,7 @@ function NodeObject(_name, _spr, _node, _create, tags = []) constructor {
if(array_length(strs) == 1) {
var splt = string_splice(strs[0], "[");
var inp = PROJECT.globalNode.getInput(strs[0]);
_val = inp == noone? 0 : inp.getValueRecursive()[0];
return inp == noone? 0 : inp.getValueRecursive()[0];
} else if(string_lower(strs[0]) == "project") {
switch(string_lower(strs[1])) {
case "frame" : return PROJECT.animator.current_frame;
@ -760,7 +761,7 @@ function NodeObject(_name, _spr, _node, _create, tags = []) constructor {
return _junc.getValue();
}
return _val;
return 0;
}
#endregion

View file

@ -1109,8 +1109,10 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
} else if(value_from != self)
val = value_from.getValueRecursive(_time);
if(expUse && is_struct(expTree) && expTree.validate())
if(expUse && is_struct(expTree) && expTree.validate()) {
//print("========== Expression eval ==========")
val[0] = expTree.eval({ value: val[0] });
}
return val;
}

View file

@ -51,7 +51,7 @@ function perlin1D(seed, scale = 1, octave = 1, startRange = 0, endRange = 1) {
var val = 0;
repeat(octave) {
val = sin(seed * scale) * amp;
val = random1D(seed * scale) * amp;
scale *= 2;
amp /= 2;
}
@ -59,7 +59,22 @@ function perlin1D(seed, scale = 1, octave = 1, startRange = 0, endRange = 1) {
return lerp(startRange, endRange, val);
}
function getWiggle(_min, _max, _freq, _time, seed_shift = 0, startTime = noone, endTime = noone) {
function wiggle(_min = 0, _max = 1, _freq = 1, _time = 0, _seed = 0, _octave = 1) {
_freq = max(1, _freq);
var sdMin = floor(_time / _freq) * _freq;
var sdMax = sdMin + _freq;
var _x0 = perlin1D(PROJECT.seed + _seed + sdMin, 1, _octave);
var _x1 = perlin1D(PROJECT.seed + _seed + sdMax, 1, _octave);
var t = (_time - sdMin) / (sdMax - sdMin);
t = -(cos(pi * t) - 1) / 2;
var _lrp = lerp(_x0, _x1, t);
return lerp(_min, _max, _lrp);
}
function getWiggle(_min = 0, _max = 1, _freq = 1, _time = 0, _seed = 0, startTime = noone, endTime = noone) {
_freq = max(1, _freq);
var sdMin = floor(_time / _freq) * _freq;
@ -67,8 +82,8 @@ function getWiggle(_min, _max, _freq, _time, seed_shift = 0, startTime = noone,
if(endTime) //Clip at ending
sdMax = min(endTime, sdMax);
var _x0 = (startTime != noone && sdMin <= startTime)? 0.5 : random1D(PROJECT.seed + seed_shift + sdMin);
var _x1 = (endTime != noone && sdMax >= endTime)? 0.5 : random1D(PROJECT.seed + seed_shift + sdMax);
var _x0 = (startTime != noone && sdMin <= startTime)? 0.5 : random1D(PROJECT.seed + _seed + sdMin);
var _x1 = (endTime != noone && sdMax >= endTime)? 0.5 : random1D(PROJECT.seed + _seed + sdMax);
var t = (_time - sdMin) / (sdMax - sdMin);
t = -(cos(pi * t) - 1) / 2;

View file

@ -3,10 +3,12 @@ function string_decimal(str) {
if(neg) str = string_copy(str, 2, string_length(str) - 1);
var dec = string_pos(".", str);
if(dec == 0) return (neg? "-" : "") + string_digits(str);
var pre = string_copy(str, 1, dec - 1);
var pos = string_copy(str, dec + 1, string_length(str) - dec);
return (neg? "-" : "") + (dec? string_digits(pre) + "." + string_digits(pos) : string_digits(str));
return (neg? "-" : "") + string_digits(pre) + "." + string_digits(pos);
}
function toNumber(str) {
@ -30,5 +32,6 @@ function toNumber(str) {
function isNumber(str) {
if(is_real(str)) return true;
str = string_trim(str);
return str == string_decimal(str);
}

View file

@ -24,13 +24,16 @@
global.EQUATION_PRES[? "@"] = 5; //array accerssor symbol
global.EQUATION_PRES[? "sin"] = 5;
global.EQUATION_PRES[? "cos"] = 5;
global.EQUATION_PRES[? "tan"] = 5;
global.EQUATION_PRES[? "abs"] = 5;
global.EQUATION_PRES[? "round"] = 5;
global.EQUATION_PRES[? "ceil"] = 5;
global.EQUATION_PRES[? "floor"] = 5;
global.FUNCTIONS = ds_map_create();
global.FUNCTIONS[? "sin"] = [ 1, function(val) { return sin(val[0]); } ];
global.FUNCTIONS[? "cos"] = [ 1, function(val) { return cos(val[0]); } ];
global.FUNCTIONS[? "tan"] = [ 1, function(val) { return tan(val[0]); } ];
global.FUNCTIONS[? "abs"] = [ 1, function(val) { return abs(val[0]); } ];
global.FUNCTIONS[? "round"] = [ 1, function(val) { return round(val[0]); } ];
global.FUNCTIONS[? "ceil"] = [ 1, function(val) { return ceil(val[0]); } ];
global.FUNCTIONS[? "floor"] = [ 1, function(val) { return floor(val[0]); } ];
global.FUNCTIONS[? "wiggle"] = [ 2, function(val) { return wiggle(0, 1, val[1], val[0]); } ];
#endregion
function functionStringClean(fx) {
@ -62,7 +65,6 @@ function functionStringClean(fx) {
self.symbol = symbol;
self.l = l;
self.r = r;
isFunc = false;
static _string = function(str) {
return string_char_at(str, 1) == "\"" &&
@ -73,15 +75,15 @@ function functionStringClean(fx) {
return _string(str)? string_copy(str, 2, string_length(str) - 2) : string(str);
}
static getVal = function(val, params = {}, getStr = false) {
if(is_struct(val)) return val.eval();
static getVal = function(val, params = {}, getRaw = false) {
if(is_struct(val)) return val.eval(params);
if(is_real(val)) return val;
if(is_string(val)) val = string_trim(val);
if(struct_has(params, val))
return struct_try_get(params, val);
if(getStr)
return val;
if(getRaw) return val;
if(_string(string_trim(val)))
return string_trim(val);
@ -115,8 +117,17 @@ function functionStringClean(fx) {
}
static validate = function() {
if(ds_map_exists(global.FUNCTIONS, symbol)) {
if(!is_array(l)) return false;
for( var i = 0; i < array_length(l); i++ )
if(!_validate(l[i])) return false;
return true;
}
switch(symbol) {
case "@": return _validate(l);
case "【": return true;
case "": return true;
}
return _validate(l) && _validate(r);
@ -145,15 +156,61 @@ function functionStringClean(fx) {
}
static eval = function(params = {}) {
var v1 = getVal(l, params);
var v2 = getVal(r, params, symbol == "@");
if(ds_map_exists(global.FUNCTIONS, symbol)) {
if(!is_array(l)) return 0;
var _fn = global.FUNCTIONS[? symbol];
var _ev = _fn[1];
var _l = array_create(array_length(l));
for( var i = 0; i < array_length(l); i++ )
_l[i] = getVal(l[i], params);
var res = _ev(_l);
//print($"Function {symbol}{_l} = {res}");
//print("====================");
return res;
}
//print($"|{v1}|{symbol}|{v2}|");
var v1 = getVal(l, params, symbol == "【");
var v2 = getVal(r, params);
var res = 0;
if(symbol == "") {
res = v1;
} else if(symbol == "【") { //array builder
res = array_create(array_length(v1));
for( var i = 0; i < array_length(res); i++ )
res[i] = getVal(v1[i], params);
} else if(symbol == "@") {
res = is_real(v2)? array_safe_get(v1, v2) : 0;
} else if(is_array(v1) && !is_array(v2)) {
res = array_create(array_length(v1));
for( var i = 0; i < array_length(res); i++ )
res[i] = eval_real(array_safe_get(v1, i), v2);
} else if(!is_array(v1) && is_array(v2)) {
res = array_create(array_length(v2));
for( var i = 0; i < array_length(res); i++ )
res[i] = eval_real(v1, array_safe_get(v2, i));
} else if(is_array(v1) && is_array(v2)) {
res = array_create(max(array_length(v1), array_length(v2)));
for( var i = 0; i < array_length(res); i++ )
res[i] = eval_real(array_safe_get(v1, i), array_safe_get(v2, i));
} else
res = eval_real(v1, v2);
//print($"|{v1}|{symbol}|{v2}| = {res}");
//print($"symbol : {symbol}");
//print($"l : {l}");
//print($"r : {r}");
//print($"l : | {typeof(l)} |{l}|");
//print($"r : | {typeof(r)} |{r}|");
//print("====================");
return res;
}
static eval_real = function(v1, v2) {
switch(symbol) {
case "+":
if(_string(v1) || _string(v2))
@ -165,7 +222,7 @@ function functionStringClean(fx) {
case "∸": return is_real(v1)? -v1 : 0;
case "*": return (is_real(v1) && is_real(v2))? v1 * v2 : 0;
case "$": return (is_real(v1) && is_real(v2))? power(v1, v2) : 0;
case "/": return (is_real(v1) && is_real(v2))? v1 / v2 : 0;
case "/": return (is_real(v1) && is_real(v2) && v2 != 0)? v1 / v2 : 0;
case "&": return (is_real(v1) && is_real(v2))? v1 & v2 : 0;
case "|": return (is_real(v1) && is_real(v2))? v1 | v2 : 0;
@ -181,10 +238,6 @@ function functionStringClean(fx) {
case ">": return (is_real(v1) && is_real(v2))? v1 > v2 : 0;
case "<": return (is_real(v1) && is_real(v2))? v1 < v2 : 0;
case "@":
var val = is_real(v2)? array_safe_get(v1, v2) : 0;
return val;
case "sin" : return is_real(v1)? sin(v1) : 0;
case "cos" : return is_real(v1)? cos(v1) : 0;
case "tan" : return is_real(v1)? tan(v1) : 0;
@ -204,6 +257,7 @@ function functionStringClean(fx) {
var pres = global.EQUATION_PRES;
var vl = ds_stack_create();
var op = ds_stack_create();
var last_push = "";
fx = functionStringClean(fx);
@ -224,52 +278,86 @@ function functionStringClean(fx) {
if(ds_map_exists(pres, ch)) { //symbol is operator
if(ds_stack_empty(op)) ds_stack_push(op, ch);
else {
if(pres[? ch] > pres[? ds_stack_top(op)] || ds_stack_top(op) == "(") ds_stack_push(op, ch);
else {
var _top = ds_stack_top(op);
if(_top == "(" || ds_map_exists(global.FUNCTIONS, _top) || pres[? ch] > pres[? _top]) {
ds_stack_push(op, ch);
last_push = "op";
} else {
if(ch == "-" && ds_map_exists(pres, _ch)) ch = "∸"; //unary negative
while(pres[? ch] <= pres[? ds_stack_top(op)] && !ds_stack_empty(op))
ds_stack_push(vl, buildFuncTree(ds_stack_pop(op), vl));
ds_stack_push(op, ch);
last_push = "op";
}
}
l++;
} else if (ch == "(") {
ds_stack_push(op, ch);
if(last_push == "fn") ds_stack_push(op, [ "〚", ds_stack_size(vl) ]);
else ds_stack_push(op, ch);
last_push = "op";
l++;
} else if (ch == ")") {
while(ds_stack_top(op) != "(" && !ds_stack_empty(op)) {
ds_stack_push(vl, buildFuncTree(ds_stack_pop(op), vl));
}
ds_stack_pop(op);
l++;
//} else if (ch == "\"") {
// l++;
// var str = "";
// while(l <= len) {
// cch = string_char_at(fx, l);
// if(cch == "\"") break;
// str += cch;
// l++;
// }
// ds_stack_push(vl, str);
} else if (ch == "[") {
ds_stack_push(op, ch);
l++;
} else if (ch == "]") {
while(ds_stack_top(op) != "[" && !ds_stack_empty(op))
while(ds_stack_top(op) != "(" && !ds_stack_empty(op))
ds_stack_push(vl, buildFuncTree(ds_stack_pop(op), vl));
ds_stack_pop(op);
while(!ds_stack_empty(op)) {
var _top = ds_stack_pop(op);
if(_top == "(") break;
if(is_array(_top) && _top[0] == "〚") {
var arr = [];
while(ds_stack_size(vl) > _top[1])
array_insert(arr, 0, ds_stack_pop(vl));
ds_stack_push(vl, new __funcTree(ds_stack_pop(op), arr));
break;
}
ds_stack_push(vl, buildFuncTree(_top, vl));
}
last_push = "vl";
l++;
} else if (ch == "[") {
if(last_push == "vl") ds_stack_push(op, ch);
else ds_stack_push(op, [ "{", ds_stack_size(vl) ]);
last_push = "op";
l++;
} else if (ch == "]") {
while(!ds_stack_empty(op)) {
var _top = ds_stack_pop(op);
if(_top == "[") break;
if(is_array(_top) && _top[0] == "{") {
var arr = [];
while(ds_stack_size(vl) > _top[1])
array_insert(arr, 0, ds_stack_pop(vl));
ds_stack_push(vl, arr);
break;
}
ds_stack_push(vl, buildFuncTree(_top, vl));
}
last_push = "vl";
l++;
} else if (ch == ",") {
while(!ds_stack_empty(op)) {
var _top = ds_stack_top(op);
if(_top == "[" || _top == "(" || (is_array(_top) && _top[0] == "{")) break;
ds_stack_push(vl, buildFuncTree(_top, vl));
ds_stack_pop(op);
}
last_push = "vl";
l++;
} else {
var vsl = "";
while(l <= len) {
cch = string_char_at(fx, l);
if(ds_map_exists(pres, cch) || array_exists(__BRACKETS, cch)) break;
if(ds_map_exists(pres, cch) || array_exists(__BRACKETS, cch) || cch == ",") break;
vsl += cch;
l++;
@ -277,14 +365,18 @@ function functionStringClean(fx) {
if(vsl == "") continue;
if(ds_map_exists(pres, vsl)) {
if(ds_map_exists(global.FUNCTIONS, vsl)) { //function
ds_stack_push(op, vsl);
last_push = "fn";
} else {
vsl = string_trim(vsl);
switch(vsl) {
case "e" : ds_stack_push(vl, 2.71828); break;
case "pi": ds_stack_push(vl, pi); break;
default : ds_stack_push(vl, isNumber(vsl)? toNumber(vsl) : vsl); break;
}
last_push = "vl";
}
}
@ -298,9 +390,14 @@ function functionStringClean(fx) {
var tree = ds_stack_empty(vl)? noone : ds_stack_pop(vl)
ds_stack_destroy(vl);
if(is_string(tree))
if(!is_struct(tree))
tree = new __funcTree("", tree);
print("=====");
print(fx);
print(tree);
print("");
return tree;
}
@ -316,11 +413,19 @@ function functionStringClean(fx) {
} else
return new __funcTree("-", ds_stack_pop(vl), 0);
case "@":
var _v1 = ds_stack_pop(vl);
if(is_array(_v1))
return new __funcTree("【", _v1);
else {
var _v2 = ds_stack_pop(vl);
return new __funcTree(operator, _v2, _v1);
}
case "+": //binary operators
case "*":
case "$":
case "/":
case "@":
case "|":
case "&":

View file

@ -14,8 +14,9 @@ const float ContrastAmount = 150.0;
const vec3 ContrastFactor = vec3(9.0);
const float Smooth = 2.0;
vec3 bokeh(sampler2D tex, vec2 uv, float radius) {
vec4 bokeh(sampler2D tex, vec2 uv, float radius) {
vec3 num, weight;
float alpha = 0.;
float rec = 1.0; // reciprocal
vec2 horizontalAngle = vec2(0.0, radius * 0.01 / sqrt(Iterations));
vec2 aspect = vec2(dimension.y / dimension.x, 1.0);
@ -29,19 +30,22 @@ vec3 bokeh(sampler2D tex, vec2 uv, float radius) {
rec += 1.0 / rec;
horizontalAngle = horizontalAngle * Rotation;
vec2 offset = (rec - 1.0) * horizontalAngle;
vec2 offset = (rec - 1.0) * horizontalAngle;
vec2 sampleUV = uv + aspect * offset;
vec3 col = texture2D(tex, sampleUV).rgb;
vec4 sam = texture2D(tex, sampleUV);
vec3 col = sam.rgb * sam.a;
// increase contrast and smooth
vec3 bokeh = Smooth + pow(col, ContrastFactor) * ContrastAmount;
num += col * bokeh;
weight += bokeh;
num += col * bokeh;
alpha += sam.a * (bokeh.r + bokeh.g + bokeh.b) / 3.;
weight += bokeh;
}
return num / weight;
return vec4(num / weight, alpha / ((weight.r + weight.g + weight.b) / 3.));
}
void main() {
gl_FragColor = vec4(bokeh(gm_BaseTexture, v_vTexcoord, strength), 1.0);
gl_FragColor = bokeh(gm_BaseTexture, v_vTexcoord, strength);
}

View file

@ -10,9 +10,16 @@ uniform vec2 scnDimension;
uniform vec2 camDimension;
uniform vec2 position;
uniform float zoom;
uniform float blur;
uniform int sampleMode;
uniform int fixBG;
uniform int bg;
uniform float bokehStrength;
const float GoldenAngle = 2.39996323;
const float Iterations = 400.0;
const float ContrastAmount = 150.0;
const vec3 ContrastFactor = vec3(9.0);
const float Smooth = 2.0;
vec4 sampleTexture(sampler2D samp, vec2 pos) {
if(pos.x >= 0. && pos.y >= 0. && pos.x <= 1. && pos.y <= 1.)
@ -20,19 +27,57 @@ vec4 sampleTexture(sampler2D samp, vec2 pos) {
if(sampleMode == 0)
return vec4(0.);
if(sampleMode == 1)
else if(sampleMode == 1)
return texture2D(samp, fract(pos));
else if(sampleMode == 2)
return texture2D(samp, vec2(fract(pos.x), pos.y));
else if(sampleMode == 3)
return texture2D(samp, vec2(pos.x, fract(pos.y)));
return vec4(0.);
}
vec4 bokeh(sampler2D tex, vec2 uv, float radius) { //ref. sh_blur_bokeh
vec3 num, weight;
float alpha = 0.;
float rec = 1.0; // reciprocal
vec2 horizontalAngle = vec2(0.0, radius * 0.01 / sqrt(Iterations));
vec2 aspect = vec2(scnDimension.y / scnDimension.x, 1.0);
mat2 Rotation = mat2(
cos(GoldenAngle), sin(GoldenAngle),
-sin(GoldenAngle), cos(GoldenAngle)
);
for (float i; i < Iterations; i++) {
rec += 1.0 / rec;
horizontalAngle = horizontalAngle * Rotation;
vec2 offset = (rec - 1.0) * horizontalAngle;
vec2 sampleUV = uv + aspect * offset;
vec4 sam = sampleTexture(tex, sampleUV);
vec3 col = sam.rgb * sam.a;
// increase contrast and smooth
vec3 bokeh = Smooth + pow(col, ContrastFactor) * ContrastAmount;
num += col * bokeh;
alpha += sam.a * (bokeh.r + bokeh.g + bokeh.b) / 3.;
weight += bokeh;
}
return vec4(num / weight, alpha / ((weight.r + weight.g + weight.b) / 3.));
}
void main() {
vec2 pos = position + (v_vTexcoord - vec2(.5)) * (camDimension / scnDimension) * zoom;
vec4 _col0 = sampleTexture( scene, pos );
vec4 _col1 = sampleTexture( backg, fixBG == 1? v_vTexcoord - position + vec2(.5) : pos );
if(bg == 1) pos = position + v_vTexcoord - vec2(.5);
vec4 _col0 = sampleTexture( backg, v_vTexcoord );
vec4 _col1 = bokeh( scene, pos, bokehStrength );
float al = _col0.a + _col1.a * (1. - _col0.a);
vec4 res = ((_col0 * _col0.a) + (_col1 * _col1.a * (1. - _col0.a))) / al;
float al = _col1.a + _col0.a * (1. - _col1.a);
vec4 res = _col0 * _col0.a * (1. - _col1.a) + _col1 * _col1.a;
res /= al;
res.a = al;
gl_FragColor = res;