combine sdf

This commit is contained in:
Tanasart 2024-06-15 09:03:30 +07:00
parent c935b6664a
commit a06e66c453
7 changed files with 248 additions and 135 deletions

View file

@ -37,6 +37,7 @@
{"name":"d3d_mesh","order":5,"path":"folders/nodes/data/3D/d3d_mesh.yy",}, {"name":"d3d_mesh","order":5,"path":"folders/nodes/data/3D/d3d_mesh.yy",},
{"name":"d3d_modifier","order":6,"path":"folders/nodes/data/3D/d3d_modifier.yy",}, {"name":"d3d_modifier","order":6,"path":"folders/nodes/data/3D/d3d_modifier.yy",},
{"name":"d3d_particle","order":7,"path":"folders/nodes/data/3D/d3d_particle.yy",}, {"name":"d3d_particle","order":7,"path":"folders/nodes/data/3D/d3d_particle.yy",},
{"name":"raymarching","order":13,"path":"folders/nodes/data/3D/raymarching.yy",},
{"name":"animation","order":13,"path":"folders/nodes/data/animation.yy",}, {"name":"animation","order":13,"path":"folders/nodes/data/animation.yy",},
{"name":"fn","order":7,"path":"folders/nodes/data/animation/fn.yy",}, {"name":"fn","order":7,"path":"folders/nodes/data/animation/fn.yy",},
{"name":"canvas","order":30,"path":"folders/nodes/data/canvas.yy",}, {"name":"canvas","order":30,"path":"folders/nodes/data/canvas.yy",},
@ -57,7 +58,6 @@
{"name":"drawer","order":11,"path":"folders/nodes/data/generator/drawer.yy",}, {"name":"drawer","order":11,"path":"folders/nodes/data/generator/drawer.yy",},
{"name":"noise","order":14,"path":"folders/nodes/data/generator/noise.yy",}, {"name":"noise","order":14,"path":"folders/nodes/data/generator/noise.yy",},
{"name":"pattern","order":15,"path":"folders/nodes/data/generator/pattern.yy",}, {"name":"pattern","order":15,"path":"folders/nodes/data/generator/pattern.yy",},
{"name":"raymarching","order":13,"path":"folders/nodes/data/3D/raymarching.yy",},
{"name":"regions","order":19,"path":"folders/nodes/data/generator/regions.yy",}, {"name":"regions","order":19,"path":"folders/nodes/data/generator/regions.yy",},
{"name":"group","order":18,"path":"folders/nodes/data/group.yy",}, {"name":"group","order":18,"path":"folders/nodes/data/group.yy",},
{"name":"io","order":19,"path":"folders/nodes/data/io.yy",}, {"name":"io","order":19,"path":"folders/nodes/data/io.yy",},

View file

@ -133,6 +133,7 @@
{"$GMFolder":"","%Name":"d3d_mesh","folderPath":"folders/nodes/data/3D/d3d_mesh.yy","name":"d3d_mesh","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"d3d_mesh","folderPath":"folders/nodes/data/3D/d3d_mesh.yy","name":"d3d_mesh","resourceType":"GMFolder","resourceVersion":"2.0",},
{"$GMFolder":"","%Name":"d3d_modifier","folderPath":"folders/nodes/data/3D/d3d_modifier.yy","name":"d3d_modifier","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"d3d_modifier","folderPath":"folders/nodes/data/3D/d3d_modifier.yy","name":"d3d_modifier","resourceType":"GMFolder","resourceVersion":"2.0",},
{"$GMFolder":"","%Name":"d3d_particle","folderPath":"folders/nodes/data/3D/d3d_particle.yy","name":"d3d_particle","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"d3d_particle","folderPath":"folders/nodes/data/3D/d3d_particle.yy","name":"d3d_particle","resourceType":"GMFolder","resourceVersion":"2.0",},
{"$GMFolder":"","%Name":"raymarching","folderPath":"folders/nodes/data/3D/raymarching.yy","name":"raymarching","resourceType":"GMFolder","resourceVersion":"2.0",},
{"$GMFolder":"","%Name":"animation","folderPath":"folders/nodes/data/animation.yy","name":"animation","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"animation","folderPath":"folders/nodes/data/animation.yy","name":"animation","resourceType":"GMFolder","resourceVersion":"2.0",},
{"$GMFolder":"","%Name":"fn","folderPath":"folders/nodes/data/animation/fn.yy","name":"fn","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"fn","folderPath":"folders/nodes/data/animation/fn.yy","name":"fn","resourceType":"GMFolder","resourceVersion":"2.0",},
{"$GMFolder":"","%Name":"canvas","folderPath":"folders/nodes/data/canvas.yy","name":"canvas","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"canvas","folderPath":"folders/nodes/data/canvas.yy","name":"canvas","resourceType":"GMFolder","resourceVersion":"2.0",},
@ -155,7 +156,6 @@
{"$GMFolder":"","%Name":"drawer","folderPath":"folders/nodes/data/generator/drawer.yy","name":"drawer","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"drawer","folderPath":"folders/nodes/data/generator/drawer.yy","name":"drawer","resourceType":"GMFolder","resourceVersion":"2.0",},
{"$GMFolder":"","%Name":"noise","folderPath":"folders/nodes/data/generator/noise.yy","name":"noise","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"noise","folderPath":"folders/nodes/data/generator/noise.yy","name":"noise","resourceType":"GMFolder","resourceVersion":"2.0",},
{"$GMFolder":"","%Name":"pattern","folderPath":"folders/nodes/data/generator/pattern.yy","name":"pattern","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"pattern","folderPath":"folders/nodes/data/generator/pattern.yy","name":"pattern","resourceType":"GMFolder","resourceVersion":"2.0",},
{"$GMFolder":"","%Name":"raymarching","folderPath":"folders/nodes/data/3D/raymarching.yy","name":"raymarching","resourceType":"GMFolder","resourceVersion":"2.0",},
{"$GMFolder":"","%Name":"regions","folderPath":"folders/nodes/data/generator/regions.yy","name":"regions","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"regions","folderPath":"folders/nodes/data/generator/regions.yy","name":"regions","resourceType":"GMFolder","resourceVersion":"2.0",},
{"$GMFolder":"","%Name":"group","folderPath":"folders/nodes/data/group.yy","name":"group","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"group","folderPath":"folders/nodes/data/group.yy","name":"group","resourceType":"GMFolder","resourceVersion":"2.0",},
{"$GMFolder":"","%Name":"io","folderPath":"folders/nodes/data/io.yy","name":"io","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"io","folderPath":"folders/nodes/data/io.yy","name":"io","resourceType":"GMFolder","resourceVersion":"2.0",},

View file

@ -43,6 +43,7 @@ function RM_Object() constructor {
triplanar = []; triplanar = [];
opmap = -1; opmap = -1;
oparg = [];
uniformKeys = [ "shape", "size", "radius", "thickness", "crop", "angle", "height", "radRange", "sizeUni", "elongate", "rounded", "corner", "size2D", "sides", uniformKeys = [ "shape", "size", "radius", "thickness", "crop", "angle", "height", "radRange", "sizeUni", "elongate", "rounded", "corner", "size2D", "sides",
"waveAmp", "waveInt", "waveShift", "waveAmp", "waveInt", "waveShift",
@ -73,6 +74,7 @@ function RM_Object() constructor {
if(shapeAmount <= 0) return; if(shapeAmount <= 0) return;
shader_set_i("operations", opmap); shader_set_i("operations", opmap);
shader_set_i("opArgument", oparg);
shader_set_i("opLength", array_safe_length(opmap)); shader_set_i("opLength", array_safe_length(opmap));
shader_set_i("shape", shape); shader_set_i("shape", shape);
@ -124,6 +126,7 @@ function RM_Operation(type, left, right) : RM_Object() constructor {
self.type = type; self.type = type;
self.left = left; self.left = left;
self.right = right; self.right = right;
merge = 0;
static reset = function() { static reset = function() {
@ -175,12 +178,19 @@ function RM_Operation(type, left, right) : RM_Object() constructor {
if(is_string(_a)) { if(is_string(_a)) {
switch(_a) { switch(_a) {
case "combine" : array_push(opmap, 100); break; case "combine" : array_push(opmap, 100); break;
} case "union" : array_push(opmap, 101); break;
} else if(is_struct(_a)) case "subtract" : array_push(opmap, 102); break;
array_push(opmap, _a.flatten_index); case "intersect" : array_push(opmap, 103); break;
}
array_push(oparg, merge);
} else if(is_struct(_a)) {
array_push(opmap, _a.flatten_index);
array_push(oparg, 0);
}
} }
// print(opmap);
shapeAmount = array_length(_nodes); shapeAmount = array_length(_nodes);
reset(); reset();

View file

@ -34,28 +34,47 @@ function Node_RM_Combine(_x, _y, _group = noone) : Node_Processor(_x, _y, _group
inputs[| 10] = nodeValue("Environment", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, false); inputs[| 10] = nodeValue("Environment", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, false);
inputs[| 11] = nodeValue("Camera Rotation", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 30, 45, 0 ])
.setDisplay(VALUE_DISPLAY.vector);
inputs[| 12] = nodeValue("Camera Scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1)
.setDisplay(VALUE_DISPLAY.slider, { range: [ 0, 4, 0.01 ] });
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inputs[| 11] = nodeValue("Shape 1", self, JUNCTION_CONNECT.input, VALUE_TYPE.struct, {}) inputs[| 13] = nodeValue("Shape 1", self, JUNCTION_CONNECT.input, VALUE_TYPE.struct, {})
.setVisible(true, true); .setVisible(true, true);
inputs[| 12] = nodeValue("Shape 2", self, JUNCTION_CONNECT.input, VALUE_TYPE.struct, {}) inputs[| 14] = nodeValue("Shape 2", self, JUNCTION_CONNECT.input, VALUE_TYPE.struct, {})
.setVisible(true, true); .setVisible(true, true);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inputs[| 15] = nodeValue("Type", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
.setDisplay(VALUE_DISPLAY.enum_scroll, [ "Place", "Union", "Subtract", "Intersect" ]);
inputs[| 16] = nodeValue("Merge", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.1)
.setDisplay(VALUE_DISPLAY.slider);
outputs[| 0] = nodeValue("Surface Out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone); outputs[| 0] = nodeValue("Surface Out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
outputs[| 1] = nodeValue("Shape Data", self, JUNCTION_CONNECT.output, VALUE_TYPE.struct, noone); outputs[| 1] = nodeValue("Shape Data", self, JUNCTION_CONNECT.output, VALUE_TYPE.struct, noone);
input_display_list = [ 0, input_display_list = [ 0,
["Camera", false], 1, 2, 3, 4, 5, ["Combine", false], 15, 13, 14,
["Camera", false], 11, 12, 1, 2, 3, 4, 5,
["Render", false], 6, 7, 8, 10, 9, ["Render", false], 6, 7, 8, 10, 9,
["Shapes", false], 11, 12,
] ]
object = noone;
temp_surface = [ 0, 0 ]; temp_surface = [ 0, 0 ];
static step = function() {
var _type = getSingleValue(15);
inputs[| 16].setVisible(_type > 0);
}
static processData = function(_outSurf, _data, _output_index, _array_index = 0) { static processData = function(_outSurf, _data, _output_index, _array_index = 0) {
var _dim = _data[0]; var _dim = _data[0];
@ -70,9 +89,13 @@ function Node_RM_Combine(_x, _y, _group = noone) : Node_Processor(_x, _y, _group
var _amb = _data[8]; var _amb = _data[8];
var _lig = _data[9]; var _lig = _data[9];
var _env = _data[10]; var _env = _data[10];
var _crt = _data[11];
var _csa = _data[12];
var _sh0 = _data[11]; var _sh0 = _data[13];
var _sh1 = _data[12]; var _sh1 = _data[14];
var _typ = _data[15];
var _mer = _data[16];
if(!is_instanceof(_sh0, RM_Object)) return [ _outSurf, noone ]; if(!is_instanceof(_sh0, RM_Object)) return [ _outSurf, noone ];
if(!is_instanceof(_sh1, RM_Object)) return [ _outSurf, noone ]; if(!is_instanceof(_sh1, RM_Object)) return [ _outSurf, noone ];
@ -87,7 +110,14 @@ function Node_RM_Combine(_x, _y, _group = noone) : Node_Processor(_x, _y, _group
draw_surface_stretched_safe(_env, tx * 0, tx * 0, tx, tx); draw_surface_stretched_safe(_env, tx * 0, tx * 0, tx, tx);
surface_reset_shader(); surface_reset_shader();
var object = new RM_Operation("combine", _sh0, _sh1); switch(_typ) {
case 0 : object = new RM_Operation("combine", _sh0, _sh1); break;
case 1 : object = new RM_Operation("union", _sh0, _sh1); break;
case 2 : object = new RM_Operation("subtract", _sh0, _sh1); break;
case 3 : object = new RM_Operation("intersect", _sh0, _sh1); break;
}
object.merge = _mer;
object.flatten(); object.flatten();
object.setTexture(temp_surface[1]); object.setTexture(temp_surface[1]);
@ -96,6 +126,9 @@ function Node_RM_Combine(_x, _y, _group = noone) : Node_Processor(_x, _y, _group
shader_set_surface($"texture0", temp_surface[0]); shader_set_surface($"texture0", temp_surface[0]);
shader_set_f("camRotation", _crt);
shader_set_f("camScale", _csa);
shader_set_i("ortho", _pro); shader_set_i("ortho", _pro);
shader_set_f("fov", _fov); shader_set_f("fov", _fov);
shader_set_f("orthoScale", _ort); shader_set_f("orthoScale", _ort);

View file

@ -30,7 +30,7 @@ function Node_RM_Primitive(_x, _y, _group = noone) : Node_Processor(_x, _y, _gro
inputs[| 2] = nodeValue("Position", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0, 0 ]) inputs[| 2] = nodeValue("Position", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0, 0 ])
.setDisplay(VALUE_DISPLAY.vector); .setDisplay(VALUE_DISPLAY.vector);
inputs[| 3] = nodeValue("Rotation", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 30, 45, 0 ]) inputs[| 3] = nodeValue("Rotation", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0, 0 ])
.setDisplay(VALUE_DISPLAY.vector); .setDisplay(VALUE_DISPLAY.vector);
inputs[| 4] = nodeValue("Scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1) inputs[| 4] = nodeValue("Scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1)
@ -147,6 +147,12 @@ function Node_RM_Primitive(_x, _y, _group = noone) : Node_Processor(_x, _y, _gro
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inputs[| 42] = nodeValue("Camera Rotation", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 30, 45, 0 ])
.setDisplay(VALUE_DISPLAY.vector);
inputs[| 43] = nodeValue("Camera Scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1)
.setDisplay(VALUE_DISPLAY.slider, { range: [ 0, 4, 0.01 ] });
outputs[| 0] = nodeValue("Surface Out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone); outputs[| 0] = nodeValue("Surface Out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
outputs[| 1] = nodeValue("Shape Data", self, JUNCTION_CONNECT.output, VALUE_TYPE.struct, noone); outputs[| 1] = nodeValue("Shape Data", self, JUNCTION_CONNECT.output, VALUE_TYPE.struct, noone);
@ -157,7 +163,7 @@ function Node_RM_Primitive(_x, _y, _group = noone) : Node_Processor(_x, _y, _gro
["Deform", true], 15, 16, 17, 18, 19, ["Deform", true], 15, 16, 17, 18, 19,
["Transform", false], 2, 3, 4, ["Transform", false], 2, 3, 4,
["Material", false], 9, 36, 35, 37, 38, ["Material", false], 9, 36, 35, 37, 38,
["Camera", false], 13, 14, 5, 6, ["Camera", false], 42, 43, 13, 14, 5, 6,
["Render", false], 31, 30, 34, 10, 7, 8, ["Render", false], 31, 30, 34, 10, 7, 8,
["Tile", false], 20, 29, ["Tile", false], 20, 29,
["Volumetric", true, 32], 33, ["Volumetric", true, 32], 33,
@ -334,6 +340,9 @@ function Node_RM_Primitive(_x, _y, _group = noone) : Node_Processor(_x, _y, _gro
var _sz2d = _data[40]; var _sz2d = _data[40];
var _side = _data[41]; var _side = _data[41];
var _crt = _data[42];
var _csa = _data[43];
_outSurf = surface_verify(_outSurf, _dim[0], _dim[1]); _outSurf = surface_verify(_outSurf, _dim[0], _dim[1]);
for (var i = 0, n = array_length(temp_surface); i < n; i++) for (var i = 0, n = array_length(temp_surface); i < n; i++)
@ -422,6 +431,9 @@ function Node_RM_Primitive(_x, _y, _group = noone) : Node_Processor(_x, _y, _gro
shader_set_surface($"texture0", temp_surface[0]); shader_set_surface($"texture0", temp_surface[0]);
shader_set_f("camRotation", _crt);
shader_set_f("camScale", _csa);
shader_set_i("ortho", _ort); shader_set_i("ortho", _ort);
shader_set_f("fov", _fov); shader_set_f("fov", _fov);
shader_set_f("orthoScale", _ortS); shader_set_f("orthoScale", _ortS);
@ -443,4 +455,5 @@ function Node_RM_Primitive(_x, _y, _group = noone) : Node_Processor(_x, _y, _gro
return [ _outSurf, object ]; return [ _outSurf, object ];
} }
} }

View file

@ -23,7 +23,7 @@ function textBox(_input, _onModify) : textInput(_input, _onModify) constructor {
slidePen = false; slidePen = false;
slide_delta = 0; slide_delta = 0;
slide_int = false; slide_int = false;
slide_speed = 1 / 10; slide_speed = 1 / 25;
slide_snap = 0; slide_snap = 0;
slide_range = noone; slide_range = noone;
curr_range = [ 0, 1 ]; curr_range = [ 0, 1 ];

View file

@ -22,6 +22,7 @@ uniform sampler2D texture2;
uniform sampler2D texture3; uniform sampler2D texture3;
uniform int operations[MAX_OP]; uniform int operations[MAX_OP];
uniform float opArgument[MAX_OP];
uniform int opLength; uniform int opLength;
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
@ -69,6 +70,9 @@ uniform float triplanar[MAX_SHAPES] ;
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
uniform vec3 camRotation;
uniform float camScale;
uniform int ortho; uniform int ortho;
uniform float fov; uniform float fov;
uniform float orthoScale; uniform float orthoScale;
@ -138,10 +142,10 @@ mat3 rotMatrix, irotMatrix;
float dot2( in vec3 v ) { return dot(v,v); } float dot2( in vec3 v ) { return dot(v,v); }
float ndot( in vec2 a, in vec2 b ) { return a.x*b.x - a.y*b.y; } float ndot( in vec2 a, in vec2 b ) { return a.x*b.x - a.y*b.y; }
vec4 sampleTexture(int index, vec2 coord) { vec4 sampleTexture(int textureIndex, vec2 coord) {
if(coord.x < 0. || coord.y < 0. || coord.x > 1. || coord.y > 1.) return vec4(0.); if(coord.x < 0. || coord.y < 0. || coord.x > 1. || coord.y > 1.) return vec4(0.);
float i = float(index); float i = float(textureIndex);
float txIndex = floor(i / TEXTURE_S); float txIndex = floor(i / TEXTURE_S);
float stcInd = i - txIndex * TEXTURE_S; float stcInd = i - txIndex * TEXTURE_S;
@ -377,31 +381,31 @@ mat3 rotMatrix, irotMatrix;
return min(max(w.x, w.y), 0.0) + length(max(w, 0.0)); return min(max(w.x, w.y), 0.0) + length(max(w, 0.0));
} }
vec3 wave(int index, vec3 p) { vec3 wave(vec3 amp, vec3 shift, vec3 inten, vec3 p) {
p.x += sin(p.y * waveAmp[index].y + waveShift[index].x * PI * 2.) * waveInt[index].x + p.x += sin(p.y * amp.y + shift.x * PI * 2.) * inten.x +
sin(p.z * waveAmp[index].z + waveShift[index].x * PI * 2.) * waveInt[index].x; sin(p.z * amp.z + shift.x * PI * 2.) * inten.x;
p.y += sin(p.x * waveAmp[index].x + waveShift[index].y * PI * 2.) * waveInt[index].y + p.y += sin(p.x * amp.x + shift.y * PI * 2.) * inten.y +
sin(p.z * waveAmp[index].z + waveShift[index].y * PI * 2.) * waveInt[index].y; sin(p.z * amp.z + shift.y * PI * 2.) * inten.y;
p.z += sin(p.y * waveAmp[index].y + waveShift[index].z * PI * 2.) * waveInt[index].z + p.z += sin(p.y * amp.y + shift.z * PI * 2.) * inten.z +
sin(p.x * waveAmp[index].x + waveShift[index].z * PI * 2.) * waveInt[index].z; sin(p.x * amp.x + shift.z * PI * 2.) * inten.z;
return p; return p;
} }
vec3 twist(int index, vec3 p) { vec3 twist(float amo, int axis, vec3 p) {
float c = cos(twistAmount[index] * p[twistAxis[index]]); float c = cos(amo * p[axis]);
float s = sin(twistAmount[index] * p[twistAxis[index]]); float s = sin(amo * p[axis]);
mat2 m = mat2(c, -s, s, c); mat2 m = mat2(c, -s, s, c);
if(twistAxis[index] == 0) { if(axis == 0) {
vec2 q = m * p.yz; vec2 q = m * p.yz;
return vec3(p.x, q); return vec3(p.x, q);
} else if(twistAxis[index] == 1) { } else if(axis == 1) {
vec2 q = m * p.xz; vec2 q = m * p.xz;
return vec3(q.x, p.y, q.y); return vec3(q.x, p.y, q.y);
} else if(twistAxis[index] == 2) { } else if(axis == 2) {
vec2 q = m * p.xy; vec2 q = m * p.xy;
return vec3(q, p.z); return vec3(q, p.z);
@ -410,9 +414,16 @@ mat3 rotMatrix, irotMatrix;
return p; return p;
} }
float opSmoothUnion( float d1, float d2, float k ) { #endregion
float h = clamp( 0.5 + 0.5 * (d2 - d1) / k, 0.0, 1.0 );
return mix( d2, d1, h ) - k * h * (1.0 - h); #region ////============ Combine =============
vec2 smin( float a, float b, float k ) {
float h = 1.0 - min( abs(a - b) / (4.0 * k), 1.0 );
float w = h * h;
float m = w * 0.5;
float s = w * k;
return (a < b) ? vec2(a - s, m) : vec2(b - s, 1.0 - m);
} }
float opSmoothSubtraction( float d1, float d2, float k ) { float opSmoothSubtraction( float d1, float d2, float k ) {
@ -421,8 +432,8 @@ mat3 rotMatrix, irotMatrix;
} }
float opSmoothIntersection( float d1, float d2, float k ) { float opSmoothIntersection( float d1, float d2, float k ) {
float h = clamp( 0.5 - 0.5 * (d2 - d1) / k, 0.0, 1.0 ); float h = clamp( 0.5 - 0.5*(d2-d1)/k, 0.0, 1.0 );
return mix( d2, d1, h ) + k * h * (1.0 - h); return mix( d2, d1, h ) + k*h*(1.0-h);
} }
#endregion #endregion
@ -432,10 +443,10 @@ mat3 rotMatrix, irotMatrix;
float round(float v) { return fract(v) >= 0.5? ceil(v) : floor(v); } float round(float v) { return fract(v) >= 0.5? ceil(v) : floor(v); }
vec3 round(vec3 v) { return vec3(round(v.x), round(v.y), round(v.z)); } vec3 round(vec3 v) { return vec3(round(v.x), round(v.y), round(v.z)); }
vec3 tilePosition(int index, vec3 p) { vec3 tilePosition(vec3 amount, vec3 size, vec3 p) {
if(tileAmount[index] == vec3(0.)) if(amount == vec3(0.))
return p - tileSize[index] * round(p / tileSize[index]); return p - size * round(p / size);
return p - tileSize[index] * clamp(round(p / tileSize[index]), -tileAmount[index], tileAmount[index]); return p - size * clamp(round(p / size), -amount, amount);
} }
#endregion #endregion
@ -471,12 +482,12 @@ float sceneSDF(int index, vec3 p) {
p -= position[index]; p -= position[index];
p = irotMatrix * p; p = irotMatrix * p;
p = wave(index, p); p = wave(waveAmp[index], waveShift[index], waveInt[index], p);
if(tileSize[index] != vec3(0.)) if(tileSize[index] != vec3(0.))
p = tilePosition(index, p); p = tilePosition(tileAmount[index], tileSize[index], p);
p = twist(index, p); p = twist(twistAmount[index], twistAxis[index], p);
vec4 el = vec4(0.); vec4 el = vec4(0.);
@ -520,19 +531,102 @@ float sceneSDF(int index, vec3 p) {
return d; return d;
} }
vec3 normal(int index, vec3 p) { float operateSceneSDF(vec3 p, out vec3 blendIndx) {
blendIndx = vec3(0.);
if(operations[0] == -1)
return sceneSDF(0, p);
float depth[MAX_OP];
float index[MAX_OP];
float d1, d2, o1, o2;
float merge;
int top = 0;
int opr = 0;
for(int i = 0; i < opLength; i++) {
opr = operations[i];
merge = opArgument[i];
if(opr < 100) {
depth[top] = sceneSDF(opr, p);
index[top] = float(opr);
top++;
} else {
top--;
d1 = depth[top];
o1 = index[top];
top--;
d2 = depth[top];
o2 = index[top];
if(opr == 100) {
if(d1 < d2) {
depth[top] = d1;
index[top] = o1;
blendIndx.x = o1;
blendIndx.z = 0.;
} else {
depth[top] = d2;
index[top] = o2;
blendIndx.x = o2;
blendIndx.z = 0.;
}
top++;
} else if(opr == 101) {
vec2 m = smin(d1, d2, merge);
blendIndx.x = o1;
blendIndx.y = o2;
blendIndx.z = m.y;
depth[top] = m.x;
index[top] = d1 < d2? o1 : o2;
} else if(opr == 102) {
float m = opSmoothSubtraction(d1, d2, merge);
blendIndx.x = o1;
blendIndx.z = 0.;
depth[top] = m;
index[top] = o1;
} else if(opr == 103) {
float m = opSmoothIntersection(d1, d2, merge);
blendIndx.x = o1;
blendIndx.z = 0.;
depth[top] = m;
index[top] = o1;
}
}
}
return depth[0];
}
vec3 normal(vec3 p) {
vec3 b;
return normalize(vec3( return normalize(vec3(
sceneSDF(index, vec3(p.x + EPSILON, p.y, p.z)) - sceneSDF(index, vec3(p.x - EPSILON, p.y, p.z)), operateSceneSDF(vec3(p.x + EPSILON, p.y, p.z), b) - operateSceneSDF(vec3(p.x - EPSILON, p.y, p.z), b),
sceneSDF(index, vec3(p.x, p.y + EPSILON, p.z)) - sceneSDF(index, vec3(p.x, p.y - EPSILON, p.z)), operateSceneSDF(vec3(p.x, p.y + EPSILON, p.z), b) - operateSceneSDF(vec3(p.x, p.y - EPSILON, p.z), b),
sceneSDF(index, vec3(p.x, p.y, p.z + EPSILON)) - sceneSDF(index, vec3(p.x, p.y, p.z - EPSILON)) operateSceneSDF(vec3(p.x, p.y, p.z + EPSILON), b) - operateSceneSDF(vec3(p.x, p.y, p.z - EPSILON), b)
)); ));
} }
float march(int index, vec3 camera, vec3 direction) { float march(vec3 camera, vec3 direction, out vec3 blendIndx) {
float depth = viewRange.x; float depth = viewRange.x;
for (int i = 0; i < MAX_MARCHING_STEPS; i++) { for (int i = 0; i < MAX_MARCHING_STEPS; i++) {
float dist = sceneSDF(index, camera + depth * direction); float dist = operateSceneSDF(camera + depth * direction, blendIndx);
if (dist < EPSILON) if (dist < EPSILON)
return depth; return depth;
@ -544,46 +638,69 @@ float march(int index, vec3 camera, vec3 direction) {
return viewRange.y; return viewRange.y;
} }
float marchDensity(int index, vec3 camera, vec3 direction) { float marchDensity(vec3 camera, vec3 direction) {
float st = 1. / float(MAX_MARCHING_STEPS); float st = 1. / float(MAX_MARCHING_STEPS);
float dens = 0.; float dens = 0.;
float stp = volumeDensity[index] == 0. ? 0. : pow(2., 10. * volumeDensity[index] * 0.5 - 10.); vec3 blendIndx;
for (int i = 0; i <= MAX_MARCHING_STEPS; i++) { for (int i = 0; i <= MAX_MARCHING_STEPS; i++) {
float depth = mix(viewRange.x, viewRange.y, float(i) * st); float depth = mix(viewRange.x, viewRange.y, float(i) * st);
vec3 pos = camera + depth * direction; vec3 pos = camera + depth * direction;
float hit = sceneSDF(index, pos); float hit = operateSceneSDF(pos, blendIndx);
float inst = (pos.y + objectScale[index]) / (objectScale[index] * 2.);
inst = inst <= 0.? 0. : pow(2., 10. * inst - 10.) * 10.;
if (hit <= 0.) dens += stp; if (hit <= 0.) {
float dens = volumeDensity[int(floor(blendIndx.x))];
float stp = dens == 0. ? 0. : pow(2., 10. * dens * 0.5 - 10.);
dens += stp;
}
} }
return dens; return dens;
} }
vec4 scene(int index, out float depth, out vec3 coll, out vec3 norm) { vec4 scene() {
depth = 0.; mat3 rx = rotateX(camRotation.x);
mat3 ry = rotateY(camRotation.y);
mat3 rz = rotateZ(camRotation.z);
mat3 camRotMatrix = rx * ry * rz;
mat3 camIrotMatrix = inverse(camRotMatrix);
float dz = 1. / tan(radians(fov) / 2.); float dz = 1. / tan(radians(fov) / 2.);
vec3 dir = normalize(vec3((v_vTexcoord - .5) * 2., -dz)); vec3 dir = normalize(vec3((v_vTexcoord - .5) * 2., -dz));
vec3 eye = vec3(0., 0., 5.); vec3 eye = vec3(0., 0., 5.);
if(volumetric[index] == 1) { dir = normalize(camIrotMatrix * dir) / camScale;
float _dens = clamp(marchDensity(index, eye, dir), 0., 1.); eye = camIrotMatrix * eye;
return diffuseColor[index] * _dens; eye /= camScale;
if(volumetric[0] == 1) {
float _dens = clamp(marchDensity(eye, dir), 0., 1.);
return diffuseColor[0] * _dens;
} }
depth = march(index, eye, dir); vec3 blendIndx;
coll = eye + dir * depth; float depth = march(eye, dir, blendIndx);
norm = normal(index, coll);
int idx0 = int(floor(blendIndx.x));
int idx1 = int(floor(blendIndx.y));
float rat = blendIndx.z;
vec3 coll = eye + dir * depth;
vec3 norm = normal(coll);
if(depth > viewRange.y - EPSILON) // Not hitting anything. if(depth > viewRange.y - EPSILON) // Not hitting anything.
return vec4(0.); return vec4(0.);
vec3 c = useTexture[index] == 1? vec3 c0 = useTexture[idx0] == 1?
boxmap(int(TEXTURE_S) + index, irotMatrix * coll * textureScale[index], irotMatrix * norm, triplanar[index]).rgb * diffuseColor[index].rgb : boxmap(int(TEXTURE_S) + idx0, irotMatrix * coll * textureScale[idx0], irotMatrix * norm, triplanar[idx0]).rgb * diffuseColor[idx0].rgb :
diffuseColor[index].rgb; diffuseColor[idx0].rgb;
vec3 c1 = useTexture[idx1] == 1?
boxmap(int(TEXTURE_S) + idx1, irotMatrix * coll * textureScale[idx1], irotMatrix * norm, triplanar[idx1]).rgb * diffuseColor[idx1].rgb :
diffuseColor[idx1].rgb;
vec3 c = mix(c0, c1, rat);
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
@ -597,7 +714,7 @@ vec4 scene(int index, out float depth, out vec3 coll, out vec3 norm) {
if(useEnv == 1) { if(useEnv == 1) {
vec3 ref = reflect(dir, norm); vec3 ref = reflect(dir, norm);
vec4 refC = sampleTexture(0, equirectangularUv(ref)); vec4 refC = sampleTexture(0, equirectangularUv(ref));
c = mix(c, c * refC.rgb, reflective[index]); c = mix(c, c * refC.rgb, mix(reflective[idx0], reflective[idx1], rat));
} }
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
@ -619,66 +736,12 @@ vec4 blend(in vec4 bg, in vec4 fg) {
return res; return res;
} }
vec4 operate() {
vec4 color[MAX_OP];
vec3 colis[MAX_OP];
vec3 norml[MAX_OP];
float depth[MAX_OP];
int top = 0;
int opr = 0;
float d1, d2, dm, rt;
vec3 n1, n2, cl;
vec4 c1, c2;
float yy = viewRange.y - EPSILON;
for(int i = 0; i < opLength; i++) {
opr = operations[i];
if(opr < 100) {
color[top] = scene(opr, d1, cl, n1);
depth[top] = d1;
colis[top] = cl;
norml[top] = n1;
top++;
} else {
top--;
c1 = color[top];
d1 = depth[top];
n1 = norml[top];
top--;
c2 = color[top];
d2 = depth[top];
n2 = norml[top];
if(opr == 100) {
if(d1 < d2) {
color[top] = c1;
depth[top] = d1;
norml[top] = n1;
} else {
color[top] = c2;
depth[top] = d2;
norml[top] = n2;
}
top++;
}
}
}
return color[0];
}
void main() { void main() {
vec4 bg = background; vec4 bg = background;
if(useEnv == 1) { if(useEnv == 1) {
float edz = 1. / tan(radians(fov * 2.) / 2.); float edz = 1. / tan(radians(fov * 2.) / 2.);
vec3 edir = normalize(vec3((v_vTexcoord - .5) * 2., -edz)); vec3 edir = normalize(vec3((v_vTexcoord - .5) * 2., -edz));
//edir = normalize(irotMatrix * edir) / objectScale[index];
vec2 envUV = equirectangularUv(edir); vec2 envUV = equirectangularUv(edir);
vec4 endC = sampleTexture(0, envUV); vec4 endC = sampleTexture(0, envUV);
@ -686,13 +749,7 @@ void main() {
} }
vec4 result = drawBg == 1? bg : vec4(0.); vec4 result = drawBg == 1? bg : vec4(0.);
float d; result = blend(result, scene());
vec3 c, n;
if(operations[0] == -1)
result = blend(result, scene(0, d, c, n));
else
result = blend(result, operate());
////////////////////////////////////////////////// //////////////////////////////////////////////////