Modifications to the example
authorEleni Maria Stea <estea@igalia.com>
Mon, 29 Apr 2019 18:46:57 +0000 (21:46 +0300)
committerEleni Maria Stea <estea@igalia.com>
Tue, 30 Apr 2019 15:41:59 +0000 (18:41 +0300)
examples/mushroom.shader_test

index 701faab..0f6ad39 100644 (file)
@@ -19,29 +19,38 @@ uniform mat4 cam_xform;
 #define FOV 45.0
 #define M_PI 3.14159
 #define MAX_STEPS 2000
+#define GRAD_DELTA (STEP / 2.0)
 
 #define OBJ_NULL 0
 #define        OBJ_MUSHROOM_TOP 1
 #define OBJ_MUSHROOM_BOTTOM 2
 #define OBJ_MUSHROOM_STEM 3
+#define OBJ_GROUND 4
 
 const vec2 res = vec2(800.0, 600.0);
 
+float pnoise(vec2 P, vec2 rep);
+float cnoise(vec2 P);
+
+float ground_height(vec3 point)
+{
+       return cnoise(point.xz * 0.85);
+}
+
 /* dist from nearest object */
-float calc_dist_mushroom(in vec3 point, out vec3 normal, out int obj_id)
+float calc_dist_mushroom(in vec3 point, out int obj_id)
 {
        const float sep = 4.0;
        const float hsep = sep / 2.0;
        vec3 p = vec3(mod(point.x + hsep, sep) - hsep, point.y, mod(point.z + hsep, sep) - hsep);
        vec3 cap_pt = p * vec3(1.0, 1.5, 1.0);
 
-       normal = normalize(cap_pt);
-
        const float sph_radius = 1.0;
        const float bigsph_radius = 50.0;
 
        float dsph_small = sqrt(dot(cap_pt, cap_pt)) - sph_radius;
-       vec3 dvec = vec3(0.0, bigsph_radius - 0.2, 0.0) - cap_pt;
+       vec3 bigsph_center = vec3(0.0, bigsph_radius - 0.2, 0.0);
+       vec3 dvec = bigsph_center - cap_pt;
        float dsph_big = sqrt(dot(dvec, dvec)) - bigsph_radius;
 
        float stem_radius = 0.7;
@@ -69,30 +78,66 @@ float calc_dist_mushroom(in vec3 point, out vec3 normal, out int obj_id)
        return dist;
 }
 
-float calc_dist(in vec3 point, out vec3 normal, out int obj_id)
+float calc_dist_ground(in vec3 point, out int obj_id)
 {
-       return calc_dist_mushroom(point, normal, obj_id);
+       obj_id = OBJ_GROUND;
+
+       const float ground_height = -0.9 + ground_height(point); 
+       return point.y - ground_height;
+}
+
+float calc_dist(in vec3 point, out int obj_id)
+{
+       int mush_id;
+       float mush_dist = calc_dist_mushroom(point, mush_id);
+
+       int ground_id;
+       float ground_dist = calc_dist_ground(point, ground_id);
+
+       float dist = ground_dist;
+       obj_id = ground_id;
+
+       if (mush_dist < dist) {
+               obj_id = mush_id;
+               dist = mush_dist;
+       }
+
+       return dist;
 }
 
 vec3 bg_color(in vec2 uv)
 {
-       return vec3(0.02, 0.15, 0.25);
+       return vec3(1.0, 0.8, 0.05);
 }
 
 vec3 shade(in vec3 pos, in vec3 normal, in int obj_id)
 {
+       return normal * 0.5 + 0.5;
        switch(obj_id) {
        case OBJ_MUSHROOM_TOP:
                return vec3(0.9, 0.0, 0.0);
        case OBJ_MUSHROOM_BOTTOM:
-               return vec3(0.15, 0.25, 0.4);
+               return vec3(0.15, 0.15, 0.3);
        case OBJ_MUSHROOM_STEM:
                return vec3(0.0, 0.6, 0.1);
+       case OBJ_GROUND:
+               return vec3(0.5, 0.25, 0.0);
        default:
                return vec3(0.1, 0.1, 0.1);
        }
 }
 
+vec3 calc_normal(in vec3 pos, in float dist)
+{
+       int tmp;
+
+       float dfdx = calc_dist(pos + vec3(GRAD_DELTA, 0.0, 0.0), tmp) - dist;
+       float dfdy = calc_dist(pos + vec3(0.0, GRAD_DELTA, 0.0), tmp) - dist;
+       float dfdz = calc_dist(pos + vec3(0.0, 0.0, GRAD_DELTA), tmp) - dist;
+
+       return normalize(vec3(dfdx, dfdy, dfdz));
+}
+
 void main()
 {
        vec2 uv = gl_FragCoord.xy / res;
@@ -115,12 +160,11 @@ void main()
 #endif
 
        int obj_id = OBJ_NULL;
-       vec3 normal;
        float dist;
 
        for(int i=0; i<MAX_STEPS; i++) {
                int id;
-               dist = calc_dist(pos, normal, id);
+               dist = calc_dist(pos, id);
                if(dist <= T) {
                        obj_id = id;
                        break;
@@ -129,10 +173,125 @@ void main()
                pos += dir * STEP;
        }
 
-       if(obj_id == OBJ_NULL)
+       if(obj_id == OBJ_NULL) {
                out_color = vec4(bg_color(uv), 1.0);
-       else
+       } else {
+               vec3 normal = calc_normal(pos, dist);
                out_color = vec4(shade(pos, normal, obj_id), 1.0);
+       }
+}
+
+
+/////////////////////////////////////////
+// Noise functions:
+// Author:  Stefan Gustavson (stefan.gustavson@liu.se)
+// Version: 2011-08-22
+//
+// Many thanks to Ian McEwan of Ashima Arts for the
+// ideas for permutation and gradient selection.
+//
+// Copyright (c) 2011 Stefan Gustavson. All rights reserved.
+// Distributed under the MIT license. See LICENSE file.
+// https://github.com/stegu/webgl-noise
+//
+
+vec4 mod289(vec4 x)
+{
+  return x - floor(x * (1.0 / 289.0)) * 289.0;
+}
+
+vec4 permute(vec4 x)
+{
+  return mod289(((x*34.0)+1.0)*x);
+}
+
+vec4 taylorInvSqrt(vec4 r)
+{
+  return 1.79284291400159 - 0.85373472095314 * r;
+}
+
+vec2 fade(vec2 t) {
+  return t*t*t*(t*(t*6.0-15.0)+10.0);
+}
+
+// Classic Perlin noise, periodic variant
+float pnoise(vec2 P, vec2 rep)
+{
+  vec4 Pi = floor(P.xyxy) + vec4(0.0, 0.0, 1.0, 1.0);
+  vec4 Pf = fract(P.xyxy) - vec4(0.0, 0.0, 1.0, 1.0);
+  Pi = mod(Pi, rep.xyxy); // To create noise with explicit period
+  Pi = mod289(Pi);        // To avoid truncation effects in permutation
+  vec4 ix = Pi.xzxz;
+  vec4 iy = Pi.yyww;
+  vec4 fx = Pf.xzxz;
+  vec4 fy = Pf.yyww;
+
+  vec4 i = permute(permute(ix) + iy);
+
+  vec4 gx = fract(i * (1.0 / 41.0)) * 2.0 - 1.0 ;
+  vec4 gy = abs(gx) - 0.5 ;
+  vec4 tx = floor(gx + 0.5);
+  gx = gx - tx;
+
+  vec2 g00 = vec2(gx.x,gy.x);
+  vec2 g10 = vec2(gx.y,gy.y);
+  vec2 g01 = vec2(gx.z,gy.z);
+  vec2 g11 = vec2(gx.w,gy.w);
+
+  vec4 norm = taylorInvSqrt(vec4(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11)));
+  g00 *= norm.x;  
+  g01 *= norm.y;  
+  g10 *= norm.z;  
+  g11 *= norm.w;  
+
+  float n00 = dot(g00, vec2(fx.x, fy.x));
+  float n10 = dot(g10, vec2(fx.y, fy.y));
+  float n01 = dot(g01, vec2(fx.z, fy.z));
+  float n11 = dot(g11, vec2(fx.w, fy.w));
+
+  vec2 fade_xy = fade(Pf.xy);
+  vec2 n_x = mix(vec2(n00, n01), vec2(n10, n11), fade_xy.x);
+  float n_xy = mix(n_x.x, n_x.y, fade_xy.y);
+  return 2.3 * n_xy;
+}
+
+float cnoise(vec2 P)
+{
+  vec4 Pi = floor(P.xyxy) + vec4(0.0, 0.0, 1.0, 1.0);
+  vec4 Pf = fract(P.xyxy) - vec4(0.0, 0.0, 1.0, 1.0);
+  Pi = mod289(Pi); // To avoid truncation effects in permutation
+  vec4 ix = Pi.xzxz;
+  vec4 iy = Pi.yyww;
+  vec4 fx = Pf.xzxz;
+  vec4 fy = Pf.yyww;
+
+  vec4 i = permute(permute(ix) + iy);
+
+  vec4 gx = fract(i * (1.0 / 41.0)) * 2.0 - 1.0 ;
+  vec4 gy = abs(gx) - 0.5 ;
+  vec4 tx = floor(gx + 0.5);
+  gx = gx - tx;
+
+  vec2 g00 = vec2(gx.x,gy.x);
+  vec2 g10 = vec2(gx.y,gy.y);
+  vec2 g01 = vec2(gx.z,gy.z);
+  vec2 g11 = vec2(gx.w,gy.w);
+
+  vec4 norm = taylorInvSqrt(vec4(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11)));
+  g00 *= norm.x;  
+  g01 *= norm.y;  
+  g10 *= norm.z;  
+  g11 *= norm.w;  
+
+  float n00 = dot(g00, vec2(fx.x, fy.x));
+  float n10 = dot(g10, vec2(fx.y, fy.y));
+  float n01 = dot(g01, vec2(fx.z, fy.z));
+  float n11 = dot(g11, vec2(fx.w, fy.w));
+
+  vec2 fade_xy = fade(Pf.xy);
+  vec2 n_x = mix(vec2(n00, n01), vec2(n10, n11), fade_xy.x);
+  float n_xy = mix(n_x.x, n_x.y, fade_xy.y);
+  return 2.3 * n_xy;
 }
 
 [test]