Skip to content

mmerchante/sdf-gen-unity

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

40 Commits
 
 
 
 
 
 
 
 

Repository files navigation

sdf-gen-unity

A signed distance function generator running inside Unity. An example result raymarched scene can be found here or here.

It lets the user make and combine distance functions to make interesting scenes, inside an intuitive editor such as Unity. It tries to optimize the code for specific known cases (for example, it tries to prevent using matrices when dealing with planes), but it is far from complete.

It also features a generic, dynamic raymarching renderer inside Unity's editor so that composing the final SDF is easy. However, because it is generic it is also very slow (unless using the optimized output code), so it uses an iterative approach to converge to the solution.

It can output GLSL and HLSL code.

As an example, it converts the following scene:

Into the following code:

const mat4 tr[45] = mat4[45](
	mat4(.999, .0, .055, .0, .0, 1.0, .0, .0, -.055, .0, .999, .0, -1.509, .14, .498, 1.0),
	mat4(.795, .934, 2.28, .0, -.491, 1.642, -1.25, .0, -1.401, -.045, 1.732, .0, -.397, -.911, -7.876, 1.0),
	mat4(.5, .0, .0, .0, .0, .137, -.104, .0, .0, .029, .489, .0, -.8, -.064, .867, 1.0),
	mat4(1.128, .386, .417, .0, -.926, .053, 1.543, .0, 1.235, -.313, .775, .0, -.769, -1.532, -2.843, 1.0),
	mat4(-1.008, .237, -1.253, .0, -1.259, .149, 1.228, .0, 1.027, .415, .275, .0, 4.273, -.714, -.96, 1.0),
	mat4(-1.633, -.219, .498, .0, .244, .173, 1.651, .0, -.964, .415, -.425, .0, 3.007, -.072, -3.193, 1.0),
	mat4(-.526, -.46, -.495, .0, -1.791, .161, -.242, .0, .411, .112, -1.689, .0, 5.514, .189, 1.112, 1.0),
	mat4(.788, .097, .425, .0, -.135, .792, .022, .0, -.418, -.073, .795, .0, 1.929, -6.665, -.972, 1.0),
	mat4(.203, .084, .048, .0, -.057, .293, -.032, .0, -.028, .013, .407, .0, -.895, .281, 1.418, 1.0),
	mat4(.149, .025, -.291, .0, .07, .222, .18, .0, .135, -.143, .228, .0, -.128, .448, .615, 1.0),
	mat4(.163, -.007, .238, .0, -.015, .102, .035, .0, -.23, -.012, .166, .0, -.815, .176, -.268, 1.0),
	mat4(1.68, -.01, .848, .0, -.871, .133, 1.509, .0, -.276, -.482, .4, .0, -5.624, -1.2, .976, 1.0),
	mat4(-1.288, -.085, -1.277, .0, -1.377, .184, 1.044, .0, .314, .457, -.658, .0, 2.367, .783, 2.615, 1.0),
	mat4(-.526, -.46, -.495, .0, -1.791, .161, -.242, .0, .411, .112, -1.689, .0, 1.346, .968, -.74, 1.0),
	mat4(.649, .468, -.157, .0, -1.578, .171, .798, .0, .862, -.04, 1.579, .0, .804, -1.56, 3.123, 1.0),
	mat4(-.446, -.32, 1.219, .0, -1.751, .078, -.321, .0, .016, -.369, -1.124, .0, -1.128, -.361, -6.142, 1.0),
	mat4(1.533, .154, .696, .0, -.87, .377, .718, .0, -.329, -.281, 1.342, .0, -4.104, -1.442, -.118, 1.0),
	mat4(1.853, -.102, -.211, .0, .221, -.014, 1.757, .0, -.392, -.489, -.008, .0, -1.772, -1.406, 6.376, 1.0),
	mat4(-.556, -.453, -.525, .0, -.17, -.141, 1.687, .0, -1.815, .152, .003, .0, -1.992, -.067, 6.05, 1.0),
	mat4(-.943, -.128, .043, .0, -.107, 1.049, .137, .0, -.059, .146, -.94, .0, 1.858, .33, -1.42, 1.0),
	mat4(.7, .065, .111, .0, -.117, .263, -.261, .0, -.161, .092, .671, .0, -1.761, -.553, -.067, 1.0),
	mat4(1.676, .466, 1.232, .0, -1.862, .058, 1.912, .0, 1.213, -.556, 1.231, .0, -3.822, -1.844, -6.583, 1.0),
	mat4(-1.467, .491, -1.337, .0, -1.788, .06, 1.971, .0, 1.549, .534, 1.009, .0, 6.023, -1.973, -.383, 1.0),
	mat4(-2.494, -.141, 1.034, .0, .951, .2, 2.324, .0, -.79, .686, -.467, .0, 6.624, -.322, -6.471, 1.0),
	mat4(-1.116, -.568, -1.242, .0, -2.513, .31, .163, .0, .432, .334, -2.263, .0, 7.905, .708, 4.921, 1.0),
	mat4(-.025, -.278, 1.937, .0, -.454, 1.573, .319, .0, -1.912, -.37, -.101, .0, .038, -4.893, -1.369, 1.0),
	mat4(.326, .111, .293, .0, -.106, .197, -.236, .0, -.365, .042, .33, .0, -1.141, -.145, -1.004, 1.0),
	mat4(1.01, .023, 1.506, .0, -1.623, .004, .939, .0, .032, -.499, .078, .0, -4.952, -.781, -2.879, 1.0),
	mat4(-1.354, .304, -.64, .0, -.774, .034, 1.62, .0, 1.106, .396, .35, .0, 2.953, -1.14, 2.649, 1.0),
	mat4(-1.462, -.104, 1.084, .0, .892, .238, 1.325, .0, -.851, .427, -.474, .0, 6.541, .212, -.951, 1.0),
	mat4(-1.166, -.349, -.663, .0, -1.442, .328, .007, .0, .463, .142, -1.648, .0, 3.098, 1.04, 2.74, 1.0),
	mat4(.024, .494, .28, .0, -1.723, -.028, .764, .0, .829, -.074, 1.579, .0, .498, -2.115, -.172, 1.0),
	mat4(.795, .0, -.714, .0, .302, 3.241, .336, .0, .647, -1.512, .721, .0, -.378, -3.143, .939, 1.0),
	mat4(.28, .504, 2.966, .0, -.047, 1.821, -.83, .0, -1.66, .033, .523, .0, 1.505, 4.294, -7.819, 1.0),
	mat4(.5, .0, .0, .0, .0, .137, -.104, .0, .0, .029, .489, .0, -.805, -.247, .582, 1.0),
	mat4(1.128, .386, .417, .0, -.926, .053, 1.543, .0, 1.235, -.313, .775, .0, -.769, -1.532, -2.843, 1.0),
	mat4(-1.008, .237, -1.253, .0, -1.259, .149, 1.228, .0, 1.027, .415, .275, .0, 4.273, -.714, -.96, 1.0),
	mat4(-1.633, -.219, .498, .0, .244, .173, 1.651, .0, -.964, .415, -.425, .0, 3.007, -.072, -3.193, 1.0),
	mat4(-.526, -.46, -.495, .0, -1.791, .161, -.242, .0, .411, .112, -1.689, .0, 5.514, .189, 1.112, 1.0),
	mat4(1.43, -.088, -1.481, .0, -.092, 1.769, -.567, .0, .828, .35, 2.494, .0, -1.382, -4.146, -2.058, 1.0),
	mat4(.461, .046, -.065, .0, -.193, .102, -.182, .0, -.02, .084, .259, .0, -.378, -.212, .663, 1.0),
	mat4(1.128, .386, .417, .0, -.926, .053, 1.543, .0, 1.235, -.313, .775, .0, -.769, -1.532, -2.843, 1.0),
	mat4(-1.008, .237, -1.253, .0, -1.259, .149, 1.228, .0, 1.027, .415, .275, .0, 4.057, -.994, -1.057, 1.0),
	mat4(-1.633, -.219, .498, .0, .244, .173, 1.651, .0, -.964, .415, -.425, .0, 3.007, -.072, -3.193, 1.0),
	mat4(-.526, -.46, -.495, .0, -1.791, .161, -.242, .0, .411, .112, -1.689, .0, 5.374, .102, 1.328, 1.0)
);


float sdf_generated(vec3 p)
{
	vec3 wsPos = vec3(.0,.0,.0);
	float stack[12];
	vec4 pStack[12];
	pStack[0] = vec4(p, 1.0);
	pStack[0] = (pStack[0] * vec4(1.0,.98,1.0,1.0));
	pStack[1] = pStack[0];
	pStack[2] = (tr[0] * pStack[1]);
	pStack[2].xz = pModPolar(pStack[2].xz , 8.0);
	pStack[3] = (tr[1] * pStack[2]);
	wsPos = (tr[2] * pStack[3]).xyz;
	stack[3] = fBox(wsPos);
	wsPos = (tr[3] * pStack[3]).xyz;
	stack[3] = max(stack[3],frPlane(wsPos));
	wsPos = (tr[4] * pStack[3]).xyz;
	stack[3] = max(stack[3],frPlane(wsPos));
	wsPos = (tr[5] * pStack[3]).xyz;
	stack[3] = max(stack[3],frPlane(wsPos));
	wsPos = (tr[6] * pStack[3]).xyz;
	stack[3] = max(stack[3],frPlane(wsPos));
	stack[2] = stack[3];
	pStack[4] = (tr[7] * pStack[1]);
	pStack[5] = pStack[4];
	pStack[6] = pStack[5];
	wsPos = (tr[8] * pStack[6]).xyz;
	stack[6] = fBox(wsPos);
	wsPos = (tr[9] * pStack[6]).xyz;
	stack[6] = min(stack[6],fBox(wsPos));
	wsPos = (tr[10] * pStack[5]).xyz;
	stack[5] = max(-stack[6],fBox(wsPos));
	wsPos = (tr[11] * pStack[4]).xyz;
	stack[4] = max(stack[5],frPlane(wsPos));
	wsPos = (tr[12] * pStack[4]).xyz;
	stack[4] = max(stack[4],frPlane(wsPos));
	wsPos = (tr[13] * pStack[4]).xyz;
	stack[4] = max(stack[4],frPlane(wsPos));
	wsPos = (tr[14] * pStack[4]).xyz;
	stack[4] = max(stack[4],frPlane(wsPos));
	wsPos = (tr[15] * pStack[4]).xyz;
	stack[4] = max(stack[4],frPlane(wsPos));
	wsPos = (tr[16] * pStack[4]).xyz;
	stack[4] = max(stack[4],frPlane(wsPos));
	wsPos = (tr[17] * pStack[4]).xyz;
	stack[4] = max(stack[4],frPlane(wsPos));
	wsPos = (tr[18] * pStack[4]).xyz;
	stack[4] = max(stack[4],frPlane(wsPos));
	stack[1] = min(stack[2],stack[4]);
	pStack[7] = (tr[19] * pStack[1]);
	pStack[7].xz = pModPolar(pStack[7].xz , 10.0);
	wsPos = (tr[20] * pStack[7]).xyz;
	stack[7] = fBox(wsPos);
	wsPos = (tr[21] * pStack[7]).xyz;
	stack[7] = max(stack[7],frPlane(wsPos));
	wsPos = (tr[22] * pStack[7]).xyz;
	stack[7] = max(stack[7],frPlane(wsPos));
	wsPos = (tr[23] * pStack[7]).xyz;
	stack[7] = max(stack[7],frPlane(wsPos));
	wsPos = (tr[24] * pStack[7]).xyz;
	stack[7] = max(stack[7],frPlane(wsPos));
	stack[1] = min(stack[1],stack[7]);
	pStack[8] = (tr[25] * pStack[1]);
	pStack[8].xz = pModPolar(pStack[8].xz , 5.0);
	wsPos = (tr[26] * pStack[8]).xyz;
	stack[8] = fBox(wsPos);
	wsPos = (tr[27] * pStack[8]).xyz;
	stack[8] = max(stack[8],frPlane(wsPos));
	wsPos = (tr[28] * pStack[8]).xyz;
	stack[8] = max(stack[8],frPlane(wsPos));
	wsPos = (tr[29] * pStack[8]).xyz;
	stack[8] = max(stack[8],frPlane(wsPos));
	wsPos = (tr[30] * pStack[8]).xyz;
	stack[8] = max(stack[8],frPlane(wsPos));
	wsPos = (tr[31] * pStack[8]).xyz;
	stack[8] = max(stack[8],frPlane(wsPos));
	stack[1] = min(stack[1],stack[8]);
	pStack[9] = (tr[32] * pStack[1]);
	pStack[9].xz = pModPolar(pStack[9].xz , 6.0);
	pStack[10] = (tr[33] * pStack[9]);
	wsPos = (tr[34] * pStack[10]).xyz;
	stack[10] = fBox(wsPos);
	wsPos = (tr[35] * pStack[10]).xyz;
	stack[10] = max(stack[10],frPlane(wsPos));
	wsPos = (tr[36] * pStack[10]).xyz;
	stack[10] = max(stack[10],frPlane(wsPos));
	wsPos = (tr[37] * pStack[10]).xyz;
	stack[10] = max(stack[10],frPlane(wsPos));
	wsPos = (tr[38] * pStack[10]).xyz;
	stack[10] = max(stack[10],frPlane(wsPos));
	stack[9] = stack[10];
	stack[1] = min(stack[1],stack[9]);
	pStack[11] = (tr[39] * pStack[1]);
	wsPos = (tr[40] * pStack[11]).xyz;
	stack[11] = fBox(wsPos);
	wsPos = (tr[41] * pStack[11]).xyz;
	stack[11] = max(stack[11],frPlane(wsPos));
	wsPos = (tr[42] * pStack[11]).xyz;
	stack[11] = max(stack[11],frPlane(wsPos));
	wsPos = (tr[43] * pStack[11]).xyz;
	stack[11] = max(stack[11],frPlane(wsPos));
	wsPos = (tr[44] * pStack[11]).xyz;
	stack[11] = max(stack[11],frPlane(wsPos));
	stack[1] = min(stack[1],stack[11]);
	stack[0] = max(stack[1],dot(pStack[0].xyz - vec3(1.24,.07,2.43), vec3(-.129,-.864,.486)));
	stack[0] = max(stack[0],dot(pStack[0].xyz - vec3(-.2,-1.41,1.48), vec3(.107,-.943,-.314)));
	return stack[0];
}

Another example scene:


float sdf(vec3 p)
{
	vec3 wsPos = vec3(.0,.0,.0);
	vec4 a0 = vec4(p, 1.0);
	a0.xz = abs(a0.xz) * vec2(-1.0,1.0);
	vec4 a1 = a0 - vec4(6.24,.0,2.5,.0);
	a1.xz = pModPolar(a1.xz , 4.0);
	float d1 = dot(a1.xyz - vec3(11.49,.0,.0), vec3(-1.0,.0,.0));
	vec4 a2 = a1 - vec4(11.02,2.15,7.28,.0);
	a2.z = domainRepeat1D(a2.z , 2.0);
	vec4 a3 = a2;
	wsPos = a3.xyz - vec3(-2.64,5.05,.0);
	float d3 = fBox(wsPos,vec3(.5,.5,.228));
	wsPos = a3.xyz - vec3(-2.275,5.05,.0);
	d3 = min(d3,fBox(wsPos,vec3(.383,.383,.175)));
	wsPos = a3.xyz - vec3(-2.64,6.97,.0);
	d3 = min(d3,fBox(wsPos,vec3(.5,.283,.111)));
	wsPos = a2.xyz - vec3(-1.28,6.38,.287);
	float d2 = max(-d3,fBox(wsPos,vec3(1.5,1.893,6.673)));
	d1 = min(d1,d2);
	vec4 a4 = a1 - vec4(9.18,-4.5,-.032,.0);
	a4.y = domainRepeat1D(a4.y , 4.5);
	vec4 a5 = a4;
	a5.z = domainRepeat1D(a5.z , 2.5);
	vec4 a6 = a5;
	a6.x = -a6.x;
	vec4 a7 = a6;
	vec4 a8 = a7 - vec4(.05,-.62,.0,.0);
	a8.xyz = rdZ(a8.xyz);
	wsPos = a8.xyz;
	float d8 = (fCylinder(wsPos, 1.398,1.361)*.75);
	wsPos = a8.xyz - vec3(.0,.152,.0);
	d8 = max(-d8,(fCylinder(wsPos, 1.434,.531)*.75));
	wsPos = a7.xyz - vec3(.786,.46,.0);
	float d7 = max(d8,fBox(wsPos,vec3(.523,.747,1.415)));
	vec4 a9 = a6;
	wsPos = a9.xyz - vec3(.47,1.953,.0);
	float d9 = fBox(wsPos,vec3(.5,.075,1.5));
	wsPos = a9.xyz - vec3(.58,2.03,.0);
	d9 = min(d9,fBox(wsPos,vec3(.5,.075,1.5)));
	vec4 a10 = a9 - vec4(.463,-.51,1.179,.0);
	a10.z = domainRepeat1D(a10.z , 2.35);
	wsPos = a10.xyz;
	float d10 = fBox(wsPos,vec3(.24,.033,.24));
	wsPos = a10.xyz - vec3(.0,-.093,.0);
	d10 = min(d10,fBox(wsPos,vec3(.24,.033,.24)));
	wsPos = a10.xyz - vec3(-2.8,-.03,.0);
	d10 = min(d10,fBox(wsPos,vec3(.25,.075,.25)));
	vec4 a11 = a10;
	a11.xz = pModPolar(a11.xz , 8.0);
	wsPos = a11.xyz - vec3(.002,-1.07,.0);
	float d11 = fBox(wsPos,vec3(.17,1.053,.424));
	d10 = min(d10,d11);
	d9 = min(d9,d10);
	vec4 a12 = a9 - vec4(-1.03,-.518,.0,.0);
	vec4 a13 = a12;
	a13.xyz = rdZ(a13.xyz);
	wsPos = (tr[0] * a13).xyz;
	float d13 = fCylinder(wsPos, 1.225,3.0);
	wsPos = a13.xyz;
	d13 = min(d13,fCylinder(wsPos, 1.094,2.061));
	wsPos = a12.xyz - vec3(.12,1.27,.0);
	float d12 = max(-d13,fBox(wsPos,vec3(1.5,1.355,1.551)));
	d9 = min(d9,d12);
	float d6 = min(d7,d9);
	vec4 a14 = a6 - vec4(.463,1.57,1.61,.0);
	wsPos = (tr[1] * a14).xyz;
	float d14 = fCylinder(wsPos, .105,.046);
	wsPos = (tr[2] * a14).xyz;
	d14 = min(d14,fCylinder(wsPos, .025,.582));
	d6 = min(d6,d14);
	float d5 = d6;
	float d4 = d5;
	d1 = min(d1,d4);
	float d0 = min(d1,dot(a0.xyz - vec3(.0,-2.0,.0), vec3(.0,1.0,.0)));
	d0 = min(d0, length(p - vec3(0.0, .35, .0)) - 1.5);
    d0 = min(d0, -(p.y - 11.15));
    return d0;
}

About

A signed distance function generator running inside Unity

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published