1 USING: arrays bunny.model bunny.cel-shaded
2 combinators.cleave continuations kernel math multiline
3 opengl opengl.shaders opengl.framebuffers opengl.gl
4 opengl.capabilities sequences ui.gadgets combinators.cleave ;
7 STRING: outlined-pass1-fragment-shader-main-source
14 gl_FragData[0] = cel_light();
15 gl_FragData[1] = vec4(normal, 1);
20 STRING: outlined-pass2-vertex-shader-source
26 gl_Position = ftransform();
27 coord = (gl_Vertex * vec4(0.5) + vec4(0.5)).xy;
32 STRING: outlined-pass2-fragment-shader-source
33 uniform sampler2D colormap, normalmap, depthmap;
34 uniform vec4 line_color;
37 const float DEPTH_RATIO_THRESHOLD = 1.001, SAMPLE_SPREAD = 1.0/512.0;
42 return texture2D(depthmap, c).x;
45 are_depths_border(vec3 depths)
47 return any(lessThan(depths, vec3(1.0/DEPTH_RATIO_THRESHOLD)))
48 || any(greaterThan(depths, vec3(DEPTH_RATIO_THRESHOLD)));
54 return texture2D(normalmap, c).xyz;
58 min6(float a, float b, float c, float d, float e, float f)
60 return min(min(min(min(min(a, b), c), d), e), f);
66 vec2 coord1 = c + vec2(-SAMPLE_SPREAD, -SAMPLE_SPREAD),
67 coord2 = c + vec2( SAMPLE_SPREAD, -SAMPLE_SPREAD),
68 coord3 = c + vec2(-SAMPLE_SPREAD, SAMPLE_SPREAD),
69 coord4 = c + vec2( SAMPLE_SPREAD, SAMPLE_SPREAD);
71 vec3 normal1 = normal_sample(coord1),
72 normal2 = normal_sample(coord2),
73 normal3 = normal_sample(coord3),
74 normal4 = normal_sample(coord4);
76 if (dot(normal1, normal1) < 0.5
77 && dot(normal2, normal2) < 0.5
78 && dot(normal3, normal3) < 0.5
79 && dot(normal4, normal4) < 0.5) {
82 vec4 depths = vec4(depth_sample(coord1),
85 depth_sample(coord4));
87 vec3 ratios1 = depths.xxx/depths.yzw, ratios2 = depths.yyz/depths.zww;
89 if (are_depths_border(ratios1) || are_depths_border(ratios2)) {
92 float normal_border = 1.0 - min6(
93 dot(normal1, normal2),
94 dot(normal1, normal3),
95 dot(normal1, normal4),
96 dot(normal2, normal3),
97 dot(normal2, normal4),
101 return normal_border;
109 gl_FragColor = mix(texture2D(colormap, coord), line_color, border_factor(coord));
114 TUPLE: bunny-outlined
116 pass1-program pass2-program
117 color-texture normal-texture depth-texture
118 framebuffer framebuffer-dim ;
120 : outlining-supported? ( -- ? )
122 "GL_ARB_shading_objects"
123 "GL_ARB_draw_buffers"
124 "GL_ARB_multitexture"
125 } has-gl-version-or-extensions? {
126 "GL_EXT_framebuffer_object"
127 "GL_ARB_texture_float"
128 } has-gl-extensions? and ;
130 : pass1-program ( -- program )
131 vertex-shader-source <vertex-shader> check-gl-shader
132 cel-shaded-fragment-shader-lib-source <fragment-shader> check-gl-shader
133 outlined-pass1-fragment-shader-main-source <fragment-shader> check-gl-shader
134 3array <gl-program> check-gl-program ;
136 : pass2-program ( -- program )
137 outlined-pass2-vertex-shader-source
138 outlined-pass2-fragment-shader-source <simple-gl-program> ;
140 : <bunny-outlined> ( gadget -- draw )
141 outlining-supported? [
142 pass1-program pass2-program {
143 set-bunny-outlined-gadget
144 set-bunny-outlined-pass1-program
145 set-bunny-outlined-pass2-program
146 } bunny-outlined construct
149 : (framebuffer-texture) ( dim iformat xformat -- texture )
151 GL_TEXTURE0 glActiveTexture
152 gen-texture GL_TEXTURE_2D over glBindTexture
153 GL_TEXTURE_2D GL_TEXTURE_WRAP_S GL_CLAMP glTexParameteri
154 GL_TEXTURE_2D GL_TEXTURE_WRAP_T GL_CLAMP glTexParameteri
155 GL_TEXTURE_2D GL_TEXTURE_MAG_FILTER GL_NEAREST glTexParameteri
156 GL_TEXTURE_2D GL_TEXTURE_MIN_FILTER GL_NEAREST glTexParameteri
157 GL_TEXTURE_2D 0 r> r> first2 0 r> GL_UNSIGNED_BYTE f glTexImage2D ;
159 : (attach-framebuffer-texture) ( texture attachment -- )
161 GL_FRAMEBUFFER_EXT r> GL_TEXTURE_2D r> 0 glFramebufferTexture2DEXT
164 : (make-framebuffer) ( color-texture normal-texture depth-texture -- framebuffer )
165 3array gen-framebuffer dup [
166 swap GL_COLOR_ATTACHMENT0_EXT
167 GL_COLOR_ATTACHMENT1_EXT
168 GL_DEPTH_ATTACHMENT_EXT 3array [ (attach-framebuffer-texture) ] 2each
172 : dispose-framebuffer ( draw -- )
173 dup bunny-outlined-framebuffer-dim [
175 [ bunny-outlined-framebuffer [ delete-framebuffer ] when* ]
176 [ bunny-outlined-color-texture [ delete-texture ] when* ]
177 [ bunny-outlined-normal-texture [ delete-texture ] when* ]
178 [ bunny-outlined-depth-texture [ delete-texture ] when* ]
179 [ f swap set-bunny-outlined-framebuffer-dim ]
183 : remake-framebuffer-if-needed ( draw -- )
184 dup bunny-outlined-gadget rect-dim
185 over bunny-outlined-framebuffer-dim
189 swap dup dispose-framebuffer >r
190 dup GL_RGBA16F_ARB GL_RGBA (framebuffer-texture)
191 swap dup GL_RGBA16F_ARB GL_RGBA (framebuffer-texture)
192 swap dup GL_DEPTH_COMPONENT32 GL_DEPTH_COMPONENT (framebuffer-texture)
194 [ (make-framebuffer) ] 3keep
196 set-bunny-outlined-framebuffer
197 set-bunny-outlined-color-texture
198 set-bunny-outlined-normal-texture
199 set-bunny-outlined-depth-texture
200 set-bunny-outlined-framebuffer-dim
204 : clear-framebuffer ( -- )
205 GL_COLOR_ATTACHMENT0_EXT glDrawBuffer
206 0.15 0.15 0.15 1.0 glClearColor
207 GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT bitor glClear
208 GL_COLOR_ATTACHMENT1_EXT glDrawBuffer
209 0.0 0.0 0.0 0.0 glClearColor
210 GL_COLOR_BUFFER_BIT glClear ;
212 : (pass1) ( geom draw -- )
213 dup bunny-outlined-framebuffer [
215 { GL_COLOR_ATTACHMENT0_EXT GL_COLOR_ATTACHMENT1_EXT } set-draw-buffers
216 bunny-outlined-pass1-program (draw-cel-shaded-bunny)
219 : (pass2) ( draw -- )
221 dup bunny-outlined-color-texture GL_TEXTURE_2D GL_TEXTURE0 bind-texture-unit
222 dup bunny-outlined-normal-texture GL_TEXTURE_2D GL_TEXTURE1 bind-texture-unit
223 dup bunny-outlined-depth-texture GL_TEXTURE_2D GL_TEXTURE2 bind-texture-unit
224 bunny-outlined-pass2-program {
225 { "colormap" [ 0 glUniform1i ] }
226 { "normalmap" [ 1 glUniform1i ] }
227 { "depthmap" [ 2 glUniform1i ] }
228 { "line_color" [ 0.1 0.0 0.1 1.0 glUniform4f ] }
229 } [ { -1.0 -1.0 } { 1.0 1.0 } rect-vertices ] with-gl-program ;
231 M: bunny-outlined draw-bunny
232 dup remake-framebuffer-if-needed
233 [ (pass1) ] keep (pass2) ;
235 M: bunny-outlined dispose
237 [ bunny-outlined-pass1-program [ delete-gl-program ] when* ]
238 [ bunny-outlined-pass2-program [ delete-gl-program ] when* ]
239 [ dispose-framebuffer ]