3. Funkcja odległości (Distance estimators)

Funkcja odległości jest to matematyczny opis obiektu dla danej pozycji (f) gdzie wynikiem tej funkcji jest dystans który pozwala stwierdzić czy punkt jest na powierzchni, przed obiektem lub wewnątrz obiektu:

  • f(p)>0 – punkt (p) jest na zewnątrz obiektu
  • f(p)=0 – punkt (p) jest na powierzchni obiektu
  • f(p)<0 – punkt (p) jest wewnątrz obiektu

4. Funkcja odległości płaszczyzny (Distance Fields)

Jest to połączenie generowania sceny na podstawie jednego lub więcej obiektów, gdzie wykorzystuje się operatory min(), max(), mod(), rotateX(), itd. do wykonywania operacji łączenia obiektów, odejmowania od siebie obiektów, zwielokrotnienia, itd.

5. Przykładowe funkcje obiektów

Poniżej przedstawiam funkcje używane do otrzymywania różnych obiektów:

  • Box:
    vec3 d = abs(p-pos) – size;
    float distance=min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0));

     

  • Sphere:
    float distance=length(p - pos) – radius;

     

  • Plane:
    float distance=dot(p - pos, normal);

    gdzie normal – jest wektorem normalnym danej płaszczyzny

     

  • RoundBox:
    float distance=length(max(abs(p – pos) - size,0.0)) – radius;

     

  • Torus:
    p=p – pos;
    vec2 q = vec2(length(p.xy) – t.x, p.z);
    float distance=length(q)-t.y;

     

  • HexPrism:
    vec3 q = abs(p – pos);
    float distance=max(q.z - h.y, max(q.x + q.y * 0.57735, q.y * 1.1547) – h.x);

     

  • Capsule:
    vec3 pa = p – a;
    vec3 ba = b – a;
    float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
    float distance=length( pa - ba*h ) - r;

     

  • TriPrism:
    vec3 q = abs(p – pos);
    float distance=max(q.z - h.y, max(q.x * 0.866025 + p.y * 0.5, -p.y) - h.x * 0.5);

     

6. Funkcje modyfikujące

Funkcje modyfikujące scene/obiekty możemy podzielić na 3 główne grupy:

  1. Łączenia obiektów
    • Union
      vec2 join(vec2 a, vec2 b) {
      	if (a.x > b.x){
      		return b;
      	}
      	return a;
      }
      vec2 join(vec2 a, vec2 b, vec2 c) {
      	if (a.x > b.x){
      		if (b.x > c.x){
      			return c;
      		}
      		return b;
      	}
      	if (a.x > c.x){
      		return c;
      	}
      	return a;
      }

       

    • Substraction
      vec2 diff(vec2 a, vec2 b) {
      	b.x=-b.x;
      	if (b.x > a.x){
      		return b;
      	}
      	return a;
      }
       
      vec2 diff(vec2 a, vec2 b, vec2 c) {
      	b.x=-b.x;
      	if (b.x > a.x){
      		c.x=-c.x;
      		if (c.x > c.x){
      			return c;
      		}
      		return b;
      	}
      	if (b.x > c.x){
      		a.x=-a.x;
      		if (a.x > c.x){
      			return a;
      		}
      		return c;
      	}
      	c.x=-c.x;
      	if (c.x > a.x){
      		return c;
      	}
      	return a;
      }

       

    • Intersection
      vec2 intersect(vec2 a, vec2 b) {
      	if (a.x > b.x){
      		return a;
      	}
      	return b;
      }
      vec2 intersect(vec2 a, vec2 b, vec2 c) {
      	if (a.x > b.x){
      		if (c.x > a.x){
      			return c;
      		}
      		return a;
      	}
      	if (c.x > b.x){
      		return c;
      	}
      	return b;
      }

       

    • Smoth Union
      vec2 smothJoin(vec2 a, vec2 b, float k ) {
      	float h=clamp(0.5 + 0.5 * (b.x - a.x) / k, 0.0, 1.0);
      	float distance=mix(b.x, a.x, h) - k * h * (1.0 - h);
       
      	if (distance > b.x){
      		b.x=distance;
      		return b;
      	}
      	a.x=distance;
      	return a;
      }

       

  2. Operacji na pozycji
    • Repetition
      vec3 repetition(vec3 pos, vec3 c) {
      	return mod(pos, c) - 0.5 * c;
      }

       

    • Rotation
      vec3 rotateX(vec3 p, float angle) {
      	float c=cos(angle);
      	float s=sin(angle);
      	return vec3(p.x, c * p.y - s * p.z, s * p.y + c * p.z);
      }
      vec3 rotateY(vec3 p, float angle) {
      	float c=cos(angle);
      	float s=sin(angle);
      	return vec3(c * p.x - s * p.z, p.y, s * p.x + c * p.z);
      }
      vec3 rotateZ(vec3 p, float angle) {
      	float c=cos(angle);
      	float s=sin(angle);
      	return vec3(c * p.x - s * p.y, s * p.x + c * p.y, p.z);
      }

       

    • Scale
      vec3 scale(vec3 p, float s) {
      	return primitive(p/s)*s;
      }

       

  3. Deformacji obiektów
    • Displacement
      vec2 sinDisplace(vec3 p, vec2 primitive, float steps, float scale) {
      	primitive.x+=(sin(steps * p.x) * sin(steps * p.y) * sin(steps * p.z)) * scale;
      	return primitive;
      }
      vec2 sinDisplace(vec3 p, vec2 primitive, float steps, float scale, float tim) {
      	primitive.x+=(sin(steps * p.x + tim) * sin(steps * p.y + tim) * sin(steps * p.z + tim)) * scale;
      	return primitive;
      }

       

    • Twist
      vec3 twist(vec3 p, float tc, float ts) {
      	float c=-1. * cos(tc * p.y + ts);
      	float s=1. * sin(tc * p.y + ts);
      	mat2 m=mat2(c, -s, s, c);
      	return vec3(m * p.xz, p.y);
      }

       

    • Cheap bend
      vec3 bend(vec3 p, float tc, float ts) {
      	float c=-1. * cos(tc * p.y + ts);
      	float s=1. * sin(tc * p.y + ts);
      	mat2 m=mat2(c, -s, s, c);
      	return vec3(m * p.xy, p.z);
      }

       

Część I – wstęp, opis algorytmu

Część III – technikalia, kod shadera