Skip to content

Commit

Permalink
Sierpinski Octahedron
Browse files Browse the repository at this point in the history
got bored, made a fractal
  • Loading branch information
srpnt3 committed May 5, 2020
1 parent 246afab commit 2721e91
Show file tree
Hide file tree
Showing 9 changed files with 2,484 additions and 0 deletions.
2,247 changes: 2,247 additions & 0 deletions Fractals Project/Assets/Scenes/OctahedronFlake.unity

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions Fractals Project/Assets/Scenes/OctahedronFlake.unity.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Fractals Project/Assets/Scripts/OctahedronFlake.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
#pragma kernel CSMain

// textures
RWTexture2D<float4> Texture;
Texture2D<float4> Source;

// matrixes
float4x4 CamToWorld;
float4x4 CamInverseProjection;

// variables
int Iterations;
float Size;
float3 Offset;
float SizeDec;

// constants
static const int steps = 100;
static const float epsilon = 0.00001;
/*static const float PI = 3.14159265f;

// rotate functions https://en.wikipedia.org/wiki/Rotation_matrix
float DegToRad(float a) { return a * PI / 180; }
float4x4 rotateX(float a) {
a = DegToRad(a);
float c = cos(a); float s = sin(a);
return float4x4(float4(1, 0, 0, 0), float4(0, c, -s, 0), float4(0, s, c, 0), float4(0, 0, 0, 1));
}
float4x4 rotateY(float a) {
a = DegToRad(a);
float c = cos(a); float s = sin(a);
return float4x4(float4(c, 0, s, 0), float4(0, 1, 0, 0), float4(-s, 0, c, 0), float4(0, 0, 0, 1));
}
float4x4 rotateZ(float a) {
a = DegToRad(a);
float c = cos(a); float s = sin(a);
return float4x4(float4(c, -s, 0, 0), float4(s, c, 0, 0), float4(0, 0, 1, 0), float4(0, 0, 0, 1));
}
float3 transform(float3 p, float4x4 m) {
return mul(m, float4(p, 1.0)).xyz;
}

// box distance estimator from https://iquilezles.org/www/articles/distfunctions/distfunctions.htm
float DEBox(float3 p, float s) {
float3 q = abs(p) - float3(s, s, s);
return length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0);
}

// 2D box distance estimator from https://iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm
float DEBox2D(float2 p, float s) {
float2 d = abs(p) - s;
return length(max(d, 0.0)) + min(max(d.x, d.y), 0);
}

// cross distance estimator from https://iquilezles.org/www/articles/distfunctions/distfunctions.htm
float DECross(float3 p, float s) {
s = s / 3;
float d = DEBox2D(p.xy, s);
d = min(d, DEBox2D(p.xz, s));
return min(d, DEBox2D(p.yz, s));
}

float DETest(float3 p, float s) {
return max(DEBox(p, s), -DECross(p, s*3));
}*/

// octahedron distance estimator from https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
float DEOctahedron(float3 p, float s) {
p = abs(p);
float m = p.x + p.y + p.z - s;
float3 q;
if (3.0 * p.x < m) q = p.xyz;
else if (3.0 * p.y < m) q = p.yzx;
else if (3.0 * p.z < m) q = p.zxy;
else return m * 0.57735027;

float k = clamp(0.5 * (q.z - q.y + s), 0.0, s);
return length(float3(q.x, q.y - s + k, q.z - k));
}

// fold space from http://blog.hvidtfeldts.net/index.php/2011/08/distance-estimated-3d-fractals-iii-folding-space
float3 Fold(float3 p, float3 n) {
return p - 2.0 * min(0.0, dot(p, n)) * n;
}

// distance to scene
float DE(float3 p) {
int i = 0;
while (i < Iterations) {
p *= SizeDec;
p = Fold(p, normalize(float3(0, 1, 1)));
p = Fold(p, normalize(float3(0, 1, -1)));
p = Fold(p, normalize(float3(1, 1, 0)));
p = Fold(p, normalize(float3(-1, 1, 0)));
p -= Offset * Size;
i++;
}
return DEOctahedron(p, Size) / pow(SizeDec, i);
}

// ray
struct Ray {
float3 origin;
float3 direction;
};

// from http://blog.three-eyed-games.com/2018/05/03/gpu-ray-tracing-in-unity-part-1/
Ray CreateRay(float3 origin, float3 direction) {
Ray ray;
ray.origin = origin;
ray.direction = direction;
return ray;
}

// from http://blog.three-eyed-games.com/2018/05/03/gpu-ray-tracing-in-unity-part-1/
Ray CreateCameraRay(float2 uv) {
float3 origin = mul(CamToWorld, float4(0, 0, 0, 1)).xyz;
float3 direction = mul(CamInverseProjection, float4(uv, 0, 1)).xyz;
direction = mul(CamToWorld, float4(direction, 0)).xyz;
direction = normalize(direction);
return CreateRay(origin, direction);
}

// cast a ray and return the result
float March(Ray ray) {
float d = 0;
float3 eye = ray.origin;

int s = 0;
while (s < steps) {
d = DE(ray.origin); // calculate distance
if (length(eye - ray.origin) > 200) s = steps; // to far away
if (d < epsilon) break; // hit
ray.origin += ray.direction * d; // march
s++; // next iteration
}

return 1 - float(s / float(steps));
}

[numthreads(8,8,1)]
void CSMain (uint3 id : SV_DispatchThreadID) {

// convert into range [-1, 1]
float w, h; Texture.GetDimensions(w, h);
float2 uv = id.xy / float2(w, h) * 2 - 1;

// create ray
Ray ray = CreateCameraRay(uv);

float res = March(ray);
//float4 ao = res * float4(0.1, 0.74, 0.61, 0);
float4 ao = res * float4(0.6, 0.6, 0.6, 0);
Texture[id.xy] = Source[id.xy] + ao;
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 48 additions & 0 deletions Fractals Project/Assets/Scripts/OctahedronFlake/OctahedronFlake.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using UnityEngine;

public class OctahedronFlake : App {

private int iterations = 0;
private float size = 1;
private Vector3 offset = new Vector3(0, 1, 0);
private float sizeDec = 2;

private void Start() {
cameraType = CameraType.Orbit;
}

protected override void Render(RenderTexture s) {

// shader
shader.SetTexture(0, "Texture", tex);
shader.SetTexture(0, "Source", s);
shader.SetMatrix("CamToWorld", cam.cameraToWorldMatrix);
shader.SetMatrix("CamInverseProjection", cam.projectionMatrix.inverse);
shader.SetInt("Iterations", iterations);
shader.SetFloat("Size", size);
shader.SetVector("Offset", offset);
shader.SetFloat("SizeDec", sizeDec);

shader.Dispatch(0, Mathf.CeilToInt(w / 8), Mathf.CeilToInt(h / 8), 1);
}

public float O_Iterations {
get => iterations;
set => iterations = Mathf.RoundToInt(value);
}

public float O_Size {
get => size;
set => size = value;
}

public Vector3 O_Offset {
get => offset;
set => offset = value;
}

public float O_SizeDec {
get => sizeDec;
set => sizeDec = value;
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Fractals Project/Assets/Scripts/Utils/AppManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ public void Start() {
"Press R to open the options menu in which you can modify certain variables."));
apps.Add(new App("Menger Sponge", true, 0, "03 MAR", 7,
"Press R to open the options menu in which you can modify certain variables."));
apps.Add(new App("Octahedron Flake", true, 0, "05 MAR", 8,
"Press R to open the options menu in which you can modify certain variables."));

for (int i = 0; i < apps.Count; i++) {
CreateElement(i);
Expand Down
3 changes: 3 additions & 0 deletions Fractals Project/ProjectSettings/EditorBuildSettings.asset
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,7 @@ EditorBuildSettings:
- enabled: 1
path: Assets/Scenes/MengerSponge.unity
guid: c4a3be4271829e14fa075f54d785c185
- enabled: 1
path: Assets/Scenes/OctahedronFlake.unity
guid: ab8cc282b4f3dfe4db2fb17f4e5ad301
m_configObjects: {}

0 comments on commit 2721e91

Please sign in to comment.