Added new component
Some checks failed
Build, Test & Push Frontend / quality-check (pull_request) Failing after 30s
Build, Test & Push Frontend / docker (pull_request) Has been skipped

This commit is contained in:
2026-02-11 08:11:42 +01:00
parent 6cb033bd9f
commit 07b6296294
4 changed files with 120 additions and 0 deletions

View File

@@ -0,0 +1 @@
<p>fractal3d works!</p>

View File

@@ -0,0 +1,11 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-fractal3d',
imports: [],
templateUrl: './fractal3d.component.html',
styleUrl: './fractal3d.component.scss',
})
export class Fractal3dComponent {
}

View File

@@ -0,0 +1,108 @@
const mandelbulbFragmentShader = `
precision highp float;
// Uniforms (Werte von der CPU)
uniform float time;
uniform vec2 resolution;
uniform vec3 cameraPosition;
uniform vec3 targetPosition;
uniform float power; // Die "Potenz" des Fraktals (z.B. 8.0)
// Hilfsfunktion: Rotation
mat2 rot(float a) {
float s = sin(a), c = cos(a);
return mat2(c, -s, s, c);
}
// --- Distance Estimator (Mandelbulb) ---
float map(vec3 pos) {
vec3 z = pos;
float dr = 1.0;
float r = 0.0;
// Die Fraktal-Iteration
for (int i = 0; i < 8; i++) {
r = length(z);
if (r > 2.0) break;
// Konvertierung in Polarkoordinaten
float theta = acos(z.y / r);
float phi = atan(z.z, z.x);
dr = pow(r, power - 1.0) * power * dr + 1.0;
// Skalieren und Rotieren (Power)
float zr = pow(r, power);
theta = theta * power;
phi = phi * power;
// Zurück zu Kartesischen Koordinaten
z = zr * vec3(sin(theta) * cos(phi), cos(theta), sin(theta) * sin(phi));
// Den ursprünglichen Punkt addieren (wie beim Mandelbrot z = z^2 + c)
z += pos;
}
return 0.5 * log(r) * r / dr;
}
// --- Raymarching ---
float raymarch(vec3 ro, vec3 rd) {
float t = 0.0;
for(int i = 0; i < 100; i++) {
vec3 pos = ro + t * rd;
float d = map(pos);
if(d < 0.001) return t; // Getroffen!
if(t > 10.0) break; // Zu weit weg
t += d;
}
return -1.0; // Nichts getroffen
}
// --- Normalenberechnung für Licht ---
vec3 getNormal(vec3 p) {
float d = map(p);
vec2 e = vec2(0.001, 0.0);
return normalize(vec3(
d - map(p - e.xyy),
d - map(p - e.yxy),
d - map(p - e.yyx)
));
}
void main(void) {
// UV Koordinaten zentrieren (-1 bis 1) und Aspekt korrigieren
vec2 uv = (gl_FragCoord.xy - 0.5 * resolution.xy) / resolution.y;
// Kamera Setup (LookAt)
vec3 ro = cameraPosition; // Ray Origin
vec3 ta = targetPosition; // Target LookAt
vec3 fwd = normalize(ta - ro);
vec3 right = normalize(cross(vec3(0,1,0), fwd));
vec3 up = normalize(cross(fwd, right));
vec3 rd = normalize(fwd + uv.x * right + uv.y * up); // Ray Direction
// Rendern
float t = raymarch(ro, rd);
vec3 color = vec3(0.0); // Hintergrund Schwarz
if(t > 0.0) {
vec3 pos = ro + t * rd;
vec3 nor = getNormal(pos);
// Einfaches Licht (Phong)
vec3 lightDir = normalize(vec3(1.0, 1.0, -1.0));
float diff = max(dot(nor, lightDir), 0.0);
float amb = 0.2; // Ambient
// Farbe basierend auf Position (gibt diesen Alien-Look)
vec3 baseColor = vec3(0.5) + 0.5 * cos(vec3(0.0, 0.4, 0.8) + length(pos) * 2.0);
color = baseColor * (diff + amb);
}
gl_FragColor = vec4(color, 1.0);
}
`;