1 USING: accessors arrays bunny.cel-shaded bunny.model combinators
2 destructors kernel literals multiline opengl opengl.capabilities
3 opengl.demo-support opengl.framebuffers opengl.gl opengl.shaders
4 opengl.textures sequences ;
5 FROM: opengl.demo-support => rect-vertices ;
8 STRING: outlined-pass1-fragment-shader-main-source
15 gl_FragData[0] = cel_light();
16 gl_FragData[1] = vec4(normal, 1);
21 STRING: outlined-pass2-vertex-shader-source
27 gl_Position = ftransform();
28 coord = (gl_Vertex * vec4(0.5) + vec4(0.5)).xy;
33 STRING: outlined-pass2-fragment-shader-source
34 uniform sampler2D colormap, normalmap, depthmap;
35 uniform vec4 line_color;
38 const float DEPTH_RATIO_THRESHOLD = 1.001, SAMPLE_SPREAD = 1.0/512.0;
43 return texture2D(depthmap, c).x;
46 are_depths_border(vec3 depths)
48 return any(lessThan(depths, vec3(1.0/DEPTH_RATIO_THRESHOLD)))
49 || any(greaterThan(depths, vec3(DEPTH_RATIO_THRESHOLD)));
55 return texture2D(normalmap, c).xyz;
59 min6(float a, float b, float c, float d, float e, float f)
61 return min(min(min(min(min(a, b), c), d), e), f);
67 vec2 coord1 = c + vec2(-SAMPLE_SPREAD, -SAMPLE_SPREAD),
68 coord2 = c + vec2( SAMPLE_SPREAD, -SAMPLE_SPREAD),
69 coord3 = c + vec2(-SAMPLE_SPREAD, SAMPLE_SPREAD),
70 coord4 = c + vec2( SAMPLE_SPREAD, SAMPLE_SPREAD);
72 vec3 normal1 = normal_sample(coord1),
73 normal2 = normal_sample(coord2),
74 normal3 = normal_sample(coord3),
75 normal4 = normal_sample(coord4);
77 if (dot(normal1, normal1) < 0.5
78 && dot(normal2, normal2) < 0.5
79 && dot(normal3, normal3) < 0.5
80 && dot(normal4, normal4) < 0.5) {
83 vec4 depths = vec4(depth_sample(coord1),
86 depth_sample(coord4));
88 vec3 ratios1 = depths.xxx/depths.yzw, ratios2 = depths.yyz/depths.zww;
90 if (are_depths_border(ratios1) || are_depths_border(ratios2)) {
93 float normal_border = 1.0 - min6(
94 dot(normal1, normal2),
95 dot(normal1, normal3),
96 dot(normal1, normal4),
97 dot(normal2, normal3),
98 dot(normal2, normal4),
102 return normal_border;
110 gl_FragColor = mix(texture2D(colormap, coord), line_color, border_factor(coord));
115 TUPLE: bunny-outlined
117 pass1-program pass2-program
118 color-texture normal-texture depth-texture
119 framebuffer framebuffer-dim ;
121 : outlining-supported? ( -- ? )
123 "GL_ARB_shader_objects"
124 "GL_ARB_draw_buffers"
125 "GL_ARB_multitexture"
126 "GL_EXT_framebuffer_object"
127 "GL_ARB_texture_float"
128 } has-gl-version-or-extensions? ;
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 f f f f f bunny-outlined boa
145 :: (framebuffer-texture) ( dim iformat xformat -- texture )
146 GL_TEXTURE0 glActiveTexture
147 gen-texture GL_TEXTURE_2D over glBindTexture
148 GL_TEXTURE_2D GL_TEXTURE_WRAP_S GL_CLAMP glTexParameteri
149 GL_TEXTURE_2D GL_TEXTURE_WRAP_T GL_CLAMP glTexParameteri
150 GL_TEXTURE_2D GL_TEXTURE_MAG_FILTER GL_NEAREST glTexParameteri
151 GL_TEXTURE_2D GL_TEXTURE_MIN_FILTER GL_NEAREST glTexParameteri
152 GL_TEXTURE_2D 0 iformat dim first2 0 xformat GL_UNSIGNED_BYTE f glTexImage2D ;
154 :: (attach-framebuffer-texture) ( texture attachment -- )
155 GL_DRAW_FRAMEBUFFER attachment GL_TEXTURE_2D texture 0 glFramebufferTexture2D
158 : (make-framebuffer) ( color-texture normal-texture depth-texture -- framebuffer )
159 3array gen-framebuffer dup [
160 swap GL_COLOR_ATTACHMENT0
162 GL_DEPTH_ATTACHMENT 3array [ (attach-framebuffer-texture) ] 2each
166 : dispose-framebuffer ( draw -- )
167 dup framebuffer-dim>> [
169 [ framebuffer>> [ delete-framebuffer ] when* ]
170 [ color-texture>> [ delete-texture ] when* ]
171 [ normal-texture>> [ delete-texture ] when* ]
172 [ depth-texture>> [ delete-texture ] when* ]
173 [ f >>framebuffer-dim drop ]
177 MACRO: (framebuffer-texture>>draw) ( iformat xformat setter -- quot )
178 '[ _ _ (framebuffer-texture) [ @ drop ] keep ] ;
180 : (make-framebuffer-textures) ( draw dim -- draw color normal depth )
183 [ GL_RGBA16F GL_RGBA [ >>color-texture ] (framebuffer-texture>>draw) ]
184 [ GL_RGBA16F GL_RGBA [ >>normal-texture ] (framebuffer-texture>>draw) ]
186 GL_DEPTH_COMPONENT32 GL_DEPTH_COMPONENT
187 [ >>depth-texture ] (framebuffer-texture>>draw)
191 : remake-framebuffer ( draw -- )
192 [ dispose-framebuffer ]
194 [ (make-framebuffer-textures) (make-framebuffer) >>framebuffer ]
195 [ >>framebuffer-dim drop ] bi
198 : remake-framebuffer-if-needed ( draw -- )
199 dup [ gadget>> dim>> ] [ framebuffer-dim>> ] bi =
200 [ drop ] [ remake-framebuffer ] if ;
202 : clear-framebuffer ( -- )
203 GL_COLOR_ATTACHMENT0 glDrawBuffer
204 0.15 0.15 0.15 1.0 glClearColor
205 flags{ GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT } glClear
206 GL_COLOR_ATTACHMENT1 glDrawBuffer
207 0.0 0.0 0.0 0.0 glClearColor
208 GL_COLOR_BUFFER_BIT glClear ;
210 : (pass1) ( geom draw -- )
213 { GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT1 } set-draw-buffers
214 pass1-program>> (draw-cel-shaded-bunny)
217 : (pass2) ( draw -- )
218 GL_PROJECTION glMatrixMode
219 glPushMatrix glLoadIdentity
220 GL_MODELVIEW glMatrixMode
223 [ color-texture>> GL_TEXTURE_2D GL_TEXTURE0 bind-texture-unit ]
224 [ normal-texture>> GL_TEXTURE_2D GL_TEXTURE1 bind-texture-unit ]
225 [ depth-texture>> GL_TEXTURE_2D GL_TEXTURE2 bind-texture-unit ]
229 [ "colormap" glGetUniformLocation 0 glUniform1i ]
230 [ "normalmap" glGetUniformLocation 1 glUniform1i ]
231 [ "depthmap" glGetUniformLocation 2 glUniform1i ]
232 [ "line_color" glGetUniformLocation 0.1 0.0 0.1 1.0 glUniform4f ]
233 } cleave { -1.0 -1.0 } { 1.0 1.0 } rect-vertices
237 GL_PROJECTION glMatrixMode
240 M: bunny-outlined draw-bunny
241 [ remake-framebuffer-if-needed ]
245 M: bunny-outlined dispose
246 [ pass1-program>> [ delete-gl-program ] when* ]
247 [ pass2-program>> [ delete-gl-program ] when* ]
248 [ dispose-framebuffer ] tri ;