summaryrefslogtreecommitdiff
path: root/kernels/compiler_menger_sponge_no_shadow.cl
blob: 95469c5ac019ace983e0ae754161e6cf3227c213 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// See http://www.iquilezles.org/articles/menger/menger.htm for the 
// full explanation of how this was done

typedef float2 vec2;
typedef float3 vec3;
typedef float4 vec4;

#define sin native_sin
#define cos native_cos
#define tan native_tan
#define normalize fast_normalize
#define length fast_length
#define mod fmod
#define time 1.f

// fmod is not like glsl mod!
__attribute__((always_inline, overloadable))
float glsl_mod(float x,float y) { return x-y*floor(x/y); }
__attribute__((always_inline, overloadable))
float2 glsl_mod(float2 a,float2 b) { return (float2)(glsl_mod(a.x,b.x), glsl_mod(a.y,b.y)); }
__attribute__((always_inline, overloadable))
float3 glsl_mod(float3 a,float3 b) { return (float3)(glsl_mod(a.x,b.x), glsl_mod(a.y,b.y), glsl_mod(a.z,b.z)); }

inline vec3 reflect(vec3 I, vec3 N) {
  return I - 2.0f * dot(N, I) * N;
}

inline uint pack_fp4(float4 u4) {
  uint u;
  u = (((uint) u4.x)) |
      (((uint) u4.y) << 8) |
      (((uint) u4.z) << 16);
  return u;
}

#define OUTPUT do {\
  const vec4 final = 255.f * max(min(gl_FragColor, (vec4)(1.f)), (vec4)(0.f)); \
  dst[get_global_id(0) + get_global_id(1) * w] = pack_fp4(final); \
} while (0)

__attribute__((always_inline))
float maxcomp(vec3 p) { return max(p.x,max(p.y,p.z));}

__attribute__((always_inline))
float sdBox(vec3 p, vec3 b)
{
  vec3  di = fabs(p) - b;
  float mc = maxcomp(di);
  return min(mc,length(max(di,0.0f)));
}

__attribute__((always_inline))
vec4 map(vec3 p)
{
   float d = sdBox(p,(vec3)(1.0f));
   float4 res = (vec4)(d,1.f,0.f,0.f);

   float s = 1.0f;
   for( int m=0; m<3; m++ ) 
   {
      vec3 a = glsl_mod(p*s, 2.0f)-1.0f;
      s *= 3.0f;
      float rx = fabs(1.0f - 3.0f*fabs(a.x));
      float ry = fabs(1.0f - 3.0f*fabs(a.y));
      float rz = fabs(1.0f - 3.0f*fabs(a.z));

      float da = max(rx,ry);
      float db = max(ry,rz);
      float dc = max(rz,rx);
      float c = (min(da,min(db,dc))-1.0f)/s;
      if (c > d)
      {
          d = c;
          res = (vec4)(d, 0.2f*da*db*dc, (1.0f+(float)(m))/4.0f, 0.0f);
      }
   }
   return (vec4)(res.x,res.y,res.z,0.f);
}

// GLSL ES doesn't seem to like loops with conditional break/return...
__attribute__((always_inline))
vec4 intersect( vec3 ro, vec3 rd )
{
    float t = 0.0f;
    for(int i=0;i<64;i++)
    {
        vec4 h = map(ro + rd*t);
        if( h.x<0.002f )
            return (vec4)(t,h.yzw);
        t += h.x;
    }
    return (vec4)(-1.0f);
}

__kernel void compiler_menger_sponge_no_shadow(__global uint *dst, float resx, float resy, int w)
{
    vec2 gl_FragCoord = (vec2)(get_global_id(0), get_global_id(1));
    vec2 p=-1.0f+2.0f*gl_FragCoord.xy/(vec2)(resx,resy);

    // light
    vec3 light = normalize((vec3)(1.0f,0.8f,-0.6f));

    float ctime = time;
    // camera
    vec3 ro = 1.1f*(vec3)(2.5f*cos(0.5f*ctime),1.5f*cos(ctime*.23f),2.5f*sin(0.5f*ctime));
    vec3 ww = normalize((vec3)(0.0f) - ro);
    vec3 uu = normalize(cross( (vec3)(0.0f,1.0f,0.0f), ww ));
    vec3 vv = normalize(cross(ww,uu));
    vec3 rd = normalize( p.x*uu + p.y*vv + 1.5f*ww );
    vec3 col = (vec3)(0.0f);
    vec4 tmat = intersect(ro,rd);

    if( tmat.x>0.0f )
        col = (vec3)(
            0.6f+0.4f*cos(5.0f+6.2831f*tmat.z),
            0.6f+0.4f*cos(5.4f+6.2831f*tmat.z),
            0.6f+0.4f*cos(5.7f+6.2831f*tmat.z) );

  vec4 gl_FragColor = (vec4)(col,1.0f);
  OUTPUT;
}