]> gitweb.factorcode.org Git - factor.git/blob - extra/spheres/spheres.factor
core/basis/extra: use flags{ } in places.
[factor.git] / extra / spheres / spheres.factor
1 USING: kernel opengl opengl.demo-support opengl.gl opengl.textures
2 opengl.shaders opengl.framebuffers opengl.capabilities multiline
3 ui.gadgets accessors sequences ui.render ui math locals arrays
4 generalizations combinators ui.gadgets.worlds
5 literals ui.pixel-formats ;
6 IN: spheres
7
8 STRING: plane-vertex-shader
9 varying vec3 object_position;
10 void
11 main()
12 {
13     object_position = gl_Vertex.xyz;
14     gl_Position = ftransform();
15 }
16 ;
17
18 STRING: plane-fragment-shader
19 uniform float checker_size_inv;
20 uniform vec4 checker_color_1, checker_color_2;
21 varying vec3 object_position;
22
23 bool
24 checker_color(vec3 p)
25 {
26     vec3 pprime = checker_size_inv * object_position;
27     return fract((floor(pprime.x) + floor(pprime.z)) * 0.5) == 0.0;
28 }
29
30 void
31 main()
32 {
33     float distance_factor = (gl_FragCoord.z * 0.5 + 0.5);
34     distance_factor = pow(distance_factor, 500.0)*0.5;
35
36     gl_FragColor = checker_color(object_position)
37         ? mix(checker_color_1, checker_color_2, distance_factor)
38         : mix(checker_color_2, checker_color_1, distance_factor);
39 }
40 ;
41
42 STRING: sphere-vertex-shader
43 attribute vec3 center;
44 attribute float radius;
45 attribute vec4 surface_color;
46 varying float vradius;
47 varying vec3 sphere_position;
48 varying vec4 world_position, vcolor;
49
50 void
51 main()
52 {
53     world_position = gl_ModelViewMatrix * vec4(center, 1);
54     sphere_position = gl_Vertex.xyz;
55
56     gl_Position = gl_ProjectionMatrix * (world_position + vec4(sphere_position * radius, 0));
57
58     vcolor = surface_color;
59     vradius = radius;
60 }
61 ;
62
63 STRING: sphere-solid-color-fragment-shader
64 uniform vec3 light_position;
65 varying vec4 vcolor;
66
67 const vec4 ambient = vec4(0.25, 0.2, 0.25, 1.0);
68 const vec4 diffuse = vec4(0.75, 0.8, 0.75, 1.0);
69
70 vec4
71 sphere_color(vec3 point, vec3 normal)
72 {
73     vec3 transformed_light_position = (gl_ModelViewMatrix * vec4(light_position, 1)).xyz;
74     vec3 direction = normalize(transformed_light_position - point);
75     float d = max(0.0, dot(normal, direction));
76
77     return ambient * vcolor + diffuse * vec4(d * vcolor.rgb, vcolor.a);
78 }
79 ;
80
81 STRING: sphere-texture-fragment-shader
82 uniform samplerCube surface_texture;
83
84 vec4
85 sphere_color(vec3 point, vec3 normal)
86 {
87     vec3 reflect = reflect(normalize(point), normal);
88     return textureCube(surface_texture, reflect * gl_NormalMatrix);
89 }
90 ;
91
92 STRING: sphere-main-fragment-shader
93 varying float vradius;
94 varying vec3 sphere_position;
95 varying vec4 world_position;
96
97 vec4 sphere_color(vec3 point, vec3 normal);
98
99 void
100 main()
101 {
102         float radius = length(sphere_position);
103         if(radius > 1.0) discard;
104         
105         vec3 surface = sphere_position + vec3(0.0, 0.0, sqrt(1.0 - radius*radius));
106         vec4 world_surface = world_position + vec4(surface * vradius, 0);
107         vec4 transformed_surface = gl_ProjectionMatrix * world_surface;
108         
109     gl_FragDepth = (transformed_surface.z/transformed_surface.w + 1.0) * 0.5;
110         gl_FragColor = sphere_color(world_surface.xyz, surface);
111 }
112 ;
113
114 TUPLE: spheres-world < demo-world
115     plane-program solid-sphere-program texture-sphere-program
116     reflection-framebuffer reflection-depthbuffer
117     reflection-texture ;
118
119 M: spheres-world near-plane
120     drop 1.0 ;
121 M: spheres-world far-plane
122     drop 512.0 ;
123 M: spheres-world distance-step
124     drop 0.5 ;
125
126 : (reflection-dim) ( -- w h )
127     512 512 ;
128
129 : (make-reflection-texture) ( -- texture )
130     gen-texture [
131         GL_TEXTURE_CUBE_MAP swap glBindTexture
132         GL_TEXTURE_CUBE_MAP GL_TEXTURE_MAG_FILTER GL_LINEAR glTexParameteri
133         GL_TEXTURE_CUBE_MAP GL_TEXTURE_MIN_FILTER GL_LINEAR glTexParameteri
134         GL_TEXTURE_CUBE_MAP GL_TEXTURE_WRAP_S GL_CLAMP glTexParameteri
135         GL_TEXTURE_CUBE_MAP GL_TEXTURE_WRAP_T GL_CLAMP glTexParameteri
136         GL_TEXTURE_CUBE_MAP GL_TEXTURE_WRAP_R GL_CLAMP glTexParameteri
137         ${
138             GL_TEXTURE_CUBE_MAP_POSITIVE_X
139             GL_TEXTURE_CUBE_MAP_POSITIVE_Y
140             GL_TEXTURE_CUBE_MAP_POSITIVE_Z
141             GL_TEXTURE_CUBE_MAP_NEGATIVE_X
142             GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
143             GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
144         }
145         [ 0 GL_RGBA8 (reflection-dim) 0 GL_RGBA GL_UNSIGNED_BYTE f glTexImage2D ]
146         each
147     ] keep ;
148
149 : (make-reflection-depthbuffer) ( -- depthbuffer )
150     gen-renderbuffer [
151         GL_RENDERBUFFER swap glBindRenderbuffer
152         GL_RENDERBUFFER GL_DEPTH_COMPONENT32 (reflection-dim) glRenderbufferStorage
153     ] keep ;
154
155 : (make-reflection-framebuffer) ( depthbuffer -- framebuffer )
156     gen-framebuffer dup [
157         swap [ GL_DRAW_FRAMEBUFFER GL_DEPTH_ATTACHMENT GL_RENDERBUFFER ] dip
158         glFramebufferRenderbuffer
159     ] with-framebuffer ;
160
161 : (plane-program) ( -- program )
162     plane-vertex-shader plane-fragment-shader <simple-gl-program> ;
163 : (solid-sphere-program) ( -- program )
164     sphere-vertex-shader <vertex-shader> check-gl-shader
165     sphere-solid-color-fragment-shader <fragment-shader> check-gl-shader
166     sphere-main-fragment-shader <fragment-shader> check-gl-shader
167     3array <gl-program> check-gl-program ;
168 : (texture-sphere-program) ( -- program )
169     sphere-vertex-shader <vertex-shader> check-gl-shader
170     sphere-texture-fragment-shader <fragment-shader> check-gl-shader
171     sphere-main-fragment-shader <fragment-shader> check-gl-shader
172     3array <gl-program> check-gl-program ;
173
174 M: spheres-world begin-world
175     "2.0" { "GL_ARB_shader_objects" } require-gl-version-or-extensions
176     { "GL_EXT_framebuffer_object" } require-gl-extensions
177     GL_DEPTH_TEST glEnable
178     GL_VERTEX_ARRAY glEnableClientState
179     0.15 0.15 1.0 1.0 glClearColor
180     20.0 10.0 20.0 set-demo-orientation
181     (plane-program) >>plane-program
182     (solid-sphere-program) >>solid-sphere-program
183     (texture-sphere-program) >>texture-sphere-program
184     (make-reflection-texture) >>reflection-texture
185     (make-reflection-depthbuffer) [ >>reflection-depthbuffer ] keep
186     (make-reflection-framebuffer) >>reflection-framebuffer
187     drop ;
188
189 M: spheres-world end-world
190     {
191         [ reflection-framebuffer>> [ delete-framebuffer ] when* ]
192         [ reflection-depthbuffer>> [ delete-renderbuffer ] when* ]
193         [ reflection-texture>> [ delete-texture ] when* ]
194         [ solid-sphere-program>> [ delete-gl-program ] when* ]
195         [ texture-sphere-program>> [ delete-gl-program ] when* ]
196         [ plane-program>> [ delete-gl-program ] when* ]
197     } cleave ;
198
199 :: (draw-sphere) ( program center radius -- )
200     program "center" glGetAttribLocation center first3 glVertexAttrib3f
201     program "radius" glGetAttribLocation radius glVertexAttrib1f
202     { -1.0 -1.0 } { 2.0 2.0 } gl-fill-rect ;
203
204 :: (draw-colored-sphere) ( program center radius surfacecolor -- )
205     program "surface_color" glGetAttribLocation surfacecolor first4 glVertexAttrib4f
206     program center radius (draw-sphere) ;
207
208 : sphere-scene ( gadget -- )
209     flags{ GL_DEPTH_BUFFER_BIT GL_COLOR_BUFFER_BIT } glClear
210     [
211         solid-sphere-program>> [
212             {
213                 [ "light_position" glGetUniformLocation 0.0 0.0 100.0 glUniform3f ]
214                 [ {  7.0  0.0  0.0 } 1.0 { 1.0 0.0 0.0 1.0 } (draw-colored-sphere) ]
215                 [ { -7.0  0.0  0.0 } 1.0 { 0.0 1.0 0.0 1.0 } (draw-colored-sphere) ]
216                 [ {  0.0  0.0  7.0 } 1.0 { 0.0 0.0 1.0 1.0 } (draw-colored-sphere) ]
217                 [ {  0.0  0.0 -7.0 } 1.0 { 1.0 1.0 0.0 1.0 } (draw-colored-sphere) ]
218                 [ {  0.0  7.0  0.0 } 1.0 { 1.0 0.0 1.0 1.0 } (draw-colored-sphere) ]
219                 [ {  0.0 -7.0  0.0 } 1.0 { 0.0 1.0 1.0 1.0 } (draw-colored-sphere) ]
220             } cleave
221         ] with-gl-program
222     ] [
223         plane-program>> [
224             {
225                 [ "checker_size_inv" glGetUniformLocation 0.125 glUniform1f ]
226                 [ "checker_color_1"  glGetUniformLocation 1.0 0.0 0.0 1.0 glUniform4f ]
227                 [ "checker_color_2"  glGetUniformLocation 1.0 1.0 1.0 1.0 glUniform4f ]
228             } cleave
229             GL_QUADS [
230                 -1000.0 -30.0  1000.0 glVertex3f
231                 -1000.0 -30.0 -1000.0 glVertex3f
232                  1000.0 -30.0 -1000.0 glVertex3f
233                  1000.0 -30.0  1000.0 glVertex3f
234             ] do-state
235         ] with-gl-program
236     ] bi ;
237
238 : reflection-frustum ( gadget -- -x x -y y near far )
239     [ near-plane ] [ far-plane ] bi
240     [ drop dup [ -+ ] bi@ ] 2keep ;
241
242 : (reflection-face) ( gadget face -- )
243     swap reflection-texture>> [
244         GL_DRAW_FRAMEBUFFER
245         GL_COLOR_ATTACHMENT0
246     ] 2dip 0 glFramebufferTexture2D
247     check-framebuffer ;
248
249 : (draw-reflection-texture) ( gadget -- )
250     dup reflection-framebuffer>> [ {
251         [ drop { 0 0 } (reflection-dim) 2array gl-viewport ]
252         [
253             GL_PROJECTION glMatrixMode
254             glPushMatrix glLoadIdentity
255             reflection-frustum glFrustum
256             GL_MODELVIEW glMatrixMode
257             glLoadIdentity
258             180.0 0.0 0.0 1.0 glRotatef
259         ]
260         [ GL_TEXTURE_CUBE_MAP_NEGATIVE_Z (reflection-face) ]
261         [ sphere-scene ]
262         [ GL_TEXTURE_CUBE_MAP_POSITIVE_X (reflection-face)
263           90.0 0.0 1.0 0.0 glRotatef ]
264         [ sphere-scene ]
265         [ GL_TEXTURE_CUBE_MAP_POSITIVE_Z (reflection-face)
266           90.0 0.0 1.0 0.0 glRotatef glPushMatrix ]
267         [ sphere-scene ]
268         [ GL_TEXTURE_CUBE_MAP_NEGATIVE_X (reflection-face)
269           90.0 0.0 1.0 0.0 glRotatef ]
270         [ sphere-scene ]
271         [ GL_TEXTURE_CUBE_MAP_NEGATIVE_Y (reflection-face)
272           glPopMatrix glPushMatrix -90.0 1.0 0.0 0.0 glRotatef ]
273         [ sphere-scene ]
274         [ GL_TEXTURE_CUBE_MAP_POSITIVE_Y (reflection-face)
275           glPopMatrix 90.0 1.0 0.0 0.0 glRotatef ]
276         [ sphere-scene ]
277         [
278             [ { 0 0 } ] dip dim>> gl-viewport
279             GL_PROJECTION glMatrixMode
280             glPopMatrix
281         ]
282     } cleave ] with-framebuffer ;
283
284 M: spheres-world draw-world*
285     {
286         [ (draw-reflection-texture) ]
287         [ demo-world-set-matrix ]
288         [ sphere-scene ]
289         [ reflection-texture>> GL_TEXTURE_CUBE_MAP GL_TEXTURE0 bind-texture-unit ]
290         [
291             texture-sphere-program>> [
292                 [ "surface_texture" glGetUniformLocation 0 glUniform1i ]
293                 [ { 0.0 0.0 0.0 } 4.0 (draw-sphere) ]
294                 bi
295             ] with-gl-program
296         ]
297     } cleave ;
298
299 MAIN-WINDOW: spheres-window {
300         { world-class spheres-world }
301         { title "Spheres" }
302         { pixel-format-attributes {
303             windowed
304             double-buffered
305             T{ depth-bits { value 16 } }
306         } }
307         { pref-dim { 640 480 } }
308     } ;