cel-shading, line-art, and bunny touch their magic rings together and become Super Bunny Demo

db4
Joe Groff 2008-02-02 13:14:22 -08:00
parent 5e77685811
commit 9667afcb81
9 changed files with 63 additions and 479 deletions

View File

@ -109,7 +109,7 @@ M: c-type stack-size c-type-size ;
GENERIC: byte-length ( seq -- n ) flushable GENERIC: byte-length ( seq -- n ) flushable
M: float-array byte-length length "float" heap-size * ; M: float-array byte-length length "double" heap-size * ;
M: byte-array byte-length length ; M: byte-array byte-length length ;

View File

@ -1,123 +1,73 @@
! From http://www.ffconsultancy.com/ocaml/bunny/index.html
USING: alien alien.c-types arrays sequences math USING: alien alien.c-types arrays sequences math
math.vectors math.matrices math.parser io io.files kernel opengl math.vectors math.matrices math.parser io io.files kernel opengl
opengl.gl opengl.glu shuffle http.client vectors timers opengl.gl opengl.glu shuffle http.client vectors timers
namespaces ui.gadgets ui.gadgets.canvas ui.render ui splitting namespaces ui.gadgets ui.gadgets.canvas ui.render ui splitting
combinators tools.time system combinators.lib combinators.cleave combinators tools.time system combinators.lib combinators.cleave
float-arrays ; float-arrays continuations opengl.demo-support multiline
ui.gestures
bunny.fixed-pipeline bunny.cel-shaded bunny.outlined bunny.model ;
IN: bunny IN: bunny
: numbers ( str -- seq ) <PRIVATE
" " split [ string>number ] map [ ] subset ;
: (parse-model) ( vs is -- vs is ) PRIVATE>
readln [
numbers {
{ [ dup length 5 = ] [ 3 head pick push ] }
{ [ dup first 3 = ] [ 1 tail over push ] }
{ [ t ] [ drop ] }
} cond (parse-model)
] when* ;
: parse-model ( stream -- vs is ) TUPLE: bunny-gadget model geom draw-seq draw-n ;
[
100000 <vector> 100000 <vector> (parse-model)
] with-stream
[
over length # " vertices, " %
dup length # " triangles" %
] "" make print ;
: n ( vs triple -- n ) : <bunny-gadget> ( -- bunny-gadget )
swap [ nth ] curry map 0.0 0.0 0.375 <demo-gadget>
dup third over first v- >r dup second swap first v- r> cross maybe-download read-model {
vneg normalize ; set-delegate
set-bunny-gadget-model
} bunny-gadget construct ;
: normal ( ns vs triple -- ) : bunny-gadget-draw ( gadget -- draw )
[ n ] keep [ rot [ v+ ] change-nth ] each-with2 ; { bunny-gadget-draw-n bunny-gadget-draw-seq }
get-slots nth ;
: normals ( vs is -- ns ) : bunny-gadget-next-draw ( gadget -- )
over length { 0.0 0.0 0.0 } <array> -rot dup { bunny-gadget-draw-seq bunny-gadget-draw-n }
[ >r 2dup r> normal ] each drop get-slots
[ normalize ] map ; 1+ swap length mod
swap [ set-bunny-gadget-draw-n ] keep relayout-1 ;
: read-model ( stream -- model ) M: bunny-gadget graft* ( gadget -- )
"Reading model" print flush [
<file-reader> parse-model [ normals ] 2keep 3array
] time ;
: make-vertex-buffers ( model -- array element-array )
[
[ first concat ] [ second concat ] bi
append >float-array
GL_ARRAY_BUFFER swap GL_STATIC_DRAW <gl-buffer>
] [
third concat >c-uint-array
GL_ELEMENT_ARRAY_BUFFER swap GL_STATIC_DRAW <gl-buffer>
] bi ;
: model-path "bun_zipper.ply" ;
: model-url "http://factorcode.org/bun_zipper.ply" ;
: maybe-download ( -- path )
model-path resource-path dup exists? [
"Downloading bunny from " write
model-url dup print flush
over download-to
] unless ;
: draw-triangle ( ns vs triple -- )
[ dup roll nth gl-normal swap nth gl-vertex ] each-with2 ;
: draw-bunny ( ns vs is -- )
GL_TRIANGLES [ [ draw-triangle ] each-with2 ] do-state ;
TUPLE: bunny-gadget model ;
: <bunny-gadget> ( model -- gadget )
<canvas>
{ set-bunny-gadget-model set-delegate }
bunny-gadget construct ;
M: bunny-gadget graft* 10 10 add-timer ;
M: bunny-gadget ungraft* dup delegate ungraft* remove-timer ;
M: bunny-gadget tick relayout-1 ;
: aspect ( gadget -- x ) rect-dim first2 /f ;
M: bunny-gadget draw-gadget*
GL_DEPTH_TEST glEnable GL_DEPTH_TEST glEnable
GL_SCISSOR_TEST glDisable dup bunny-gadget-model <bunny-geom>
1.0 glClearDepth over {
0.0 0.0 0.0 1.0 glClearColor [ <bunny-fixed-pipeline> ]
GL_DEPTH_BUFFER_BIT GL_COLOR_BUFFER_BIT bitor glClear [ <bunny-cel-shaded> ]
GL_PROJECTION glMatrixMode [ <bunny-outlined> ]
glLoadIdentity } map-call-with [ ] subset
45.0 over aspect 0.1 1.0 gluPerspective 0
0.0 0.12 -0.25 0.0 0.1 0.0 0.0 1.0 0.0 gluLookAt roll {
GL_MODELVIEW glMatrixMode set-bunny-gadget-geom
glLoadIdentity set-bunny-gadget-draw-seq
GL_LEQUAL glDepthFunc set-bunny-gadget-draw-n
GL_LIGHTING glEnable } set-slots ;
GL_LIGHT0 glEnable
GL_COLOR_MATERIAL glEnable
GL_LIGHT0 GL_POSITION { 1.0 -1.0 1.0 1.0 } >c-float-array glLightfv
millis 24000 mod 0.015 * 0.0 1.0 0.0 glRotated
GL_FRONT_AND_BACK GL_SHININESS 100.0 glMaterialf
GL_FRONT_AND_BACK GL_SPECULAR glColorMaterial
GL_FRONT_AND_BACK GL_AMBIENT_AND_DIFFUSE glColorMaterial
0.6 0.5 0.5 1.0 glColor4d
[ bunny-gadget-model first3 draw-bunny ] draw-canvas ;
M: bunny-gadget pref-dim* drop { 400 300 } ; M: bunny-gadget ungraft* ( gadget -- )
{ bunny-gadget-geom bunny-gadget-draw-seq } get-slots
[ [ dispose ] when* ] each
[ dispose ] when* ;
M: bunny-gadget draw-gadget* ( gadget -- )
0.15 0.15 0.15 1.0 glClearColor
GL_DEPTH_BUFFER_BIT GL_COLOR_BUFFER_BIT bitor glClear
dup demo-gadget-set-matrices
GL_MODELVIEW glMatrixMode
0.0 -0.12 0.0 glTranslatef
{ bunny-gadget-geom bunny-gadget-draw } get-slots
draw-bunny ;
M: bunny-gadget pref-dim* ( gadget -- dim )
drop { 640 480 } ;
bunny-gadget H{
{ T{ key-down f f "TAB" } [ bunny-gadget-next-draw ] }
} set-gestures
: bunny-window ( -- ) : bunny-window ( -- )
[ [ <bunny-gadget> "Bunny" open-window ] with-ui ;
maybe-download read-model <bunny-gadget>
"Bunny" open-window
] with-ui ;
MAIN: bunny-window MAIN: bunny-window

View File

@ -1,115 +0,0 @@
USING: arrays bunny combinators.lib io io.files kernel
math math.functions multiline continuations debugger
opengl opengl.gl opengl-demo-support
sequences ui ui.gadgets ui.render ;
IN: cel-shading
TUPLE: cel-shading-gadget model program vertices elements ;
: <cel-shading-gadget> ( -- cel-shading-gadget )
0.0 0.0 0.375 <demo-gadget>
maybe-download read-model {
set-delegate
set-cel-shading-gadget-model
} cel-shading-gadget construct ;
STRING: cel-shading-vertex-shader-source
varying vec3 position, normal;
void
main()
{
gl_Position = ftransform();
position = gl_Vertex.xyz;
normal = gl_Normal;
}
;
STRING: cel-shading-fragment-shader-source
varying vec3 position, normal;
uniform vec3 light_direction;
uniform vec4 color;
uniform vec4 ambient, diffuse;
float
smooth_modulate(vec3 direction, vec3 normal)
{
return clamp(dot(direction, normal), 0.0, 1.0);
}
float
modulate(vec3 direction, vec3 normal)
{
float m = smooth_modulate(direction, normal);
return smoothstep(0.0, 0.01, m) * 0.4 + smoothstep(0.49, 0.5, m) * 0.5;
}
void
main()
{
vec3 direction = normalize(light_direction - position);
gl_FragColor = ambient + diffuse * color * vec4(vec3(modulate(direction, normal)), 1);
}
;
: make-cel-shading-program ( -- program )
cel-shading-vertex-shader-source cel-shading-fragment-shader-source
<simple-gl-program> ;
M: cel-shading-gadget graft* ( gadget -- )
"2.0" {
"GL_ARB_shader_objects"
"GL_ARB_vertex_buffer_object"
} require-gl-version-or-extensions
0.0 0.0 0.0 1.0 glClearColor
GL_CULL_FACE glEnable
GL_DEPTH_TEST glEnable
dup cel-shading-gadget-model make-vertex-buffers
make-cel-shading-program roll {
set-cel-shading-gadget-vertices
set-cel-shading-gadget-elements
set-cel-shading-gadget-program
} set-slots ;
M: cel-shading-gadget ungraft* ( gadget -- )
{
[ cel-shading-gadget-program [ delete-gl-program ] when* ]
[ cel-shading-gadget-elements [ delete-gl-buffer ] when* ]
[ cel-shading-gadget-vertices [ delete-gl-buffer ] when* ]
} call-with ;
: cel-shading-draw-setup ( gadget -- gadget )
[ demo-gadget-set-matrices ] keep
[ cel-shading-gadget-program {
[ "light_direction" glGetUniformLocation -25.0 45.0 80.0 glUniform3f ]
[ "color" glGetUniformLocation 0.6 0.5 0.5 1.0 glUniform4f ]
[ "ambient" glGetUniformLocation 0.2 0.2 0.2 0.2 glUniform4f ]
[ "diffuse" glGetUniformLocation 0.8 0.8 0.8 0.8 glUniform4f ]
} call-with ] keep ;
M: cel-shading-gadget draw-gadget* ( gadget -- )
dup cel-shading-gadget-program [
cel-shading-draw-setup
0.0 -0.12 0.0 glTranslatef
dup {
cel-shading-gadget-vertices
cel-shading-gadget-elements
} get-slots [
GL_VERTEX_ARRAY GL_NORMAL_ARRAY 2array [
GL_FLOAT 0 0 buffer-offset glNormalPointer
cel-shading-gadget-model dup
first length 3 * 4 * buffer-offset
3 GL_FLOAT 0 roll glVertexPointer
third length 3 *
GL_TRIANGLES swap GL_UNSIGNED_INT 0 buffer-offset glDrawElements
] all-enabled-client-state
] with-array-element-buffers
] with-gl-program ;
: cel-shading-window ( -- )
[ <cel-shading-gadget> "Cel Shading" open-window ] with-ui ;
MAIN: cel-shading-window

View File

@ -1,254 +0,0 @@
USING: arrays bunny combinators.lib continuations io io.files kernel
math math.functions math.vectors multiline
namespaces debugger
opengl opengl.gl opengl-demo-support
prettyprint
sequences ui ui.gadgets ui.gestures ui.render ;
IN: line-art
TUPLE: line-art-gadget
model step1-program step2-program
framebuffer color-texture normal-texture depth-texture framebuffer-dim ;
: <line-art-gadget> ( -- line-art-gadget )
40.0 -5.0 0.275 <demo-gadget>
maybe-download read-model
{ set-delegate set-line-art-gadget-model } line-art-gadget construct ;
STRING: line-art-step1-vertex-shader-source
varying vec3 normal;
void
main()
{
gl_Position = ftransform();
normal = gl_Normal;
}
;
STRING: line-art-step1-fragment-shader-source
varying vec3 normal;
uniform vec4 color;
void
main()
{
gl_FragData[0] = color;
gl_FragData[1] = vec4(normal, 1);
}
;
STRING: line-art-step2-vertex-shader-source
varying vec2 coord;
void
main()
{
gl_Position = ftransform();
coord = (gl_Vertex * vec4(0.5) + vec4(0.5)).xy;
}
;
STRING: line-art-step2-fragment-shader-source
uniform sampler2D colormap, normalmap, depthmap;
uniform vec4 line_color;
varying vec2 coord;
const float DEPTH_RATIO_THRESHOLD = 1.001, SAMPLE_SPREAD = 1.0/512.0;
float
depth_sample(vec2 c)
{
return texture2D(depthmap, c).x;
}
bool
are_depths_border(vec3 depths)
{
return any(lessThan(depths, vec3(1.0/DEPTH_RATIO_THRESHOLD)))
|| any(greaterThan(depths, vec3(DEPTH_RATIO_THRESHOLD)));
}
vec3
normal_sample(vec2 c)
{
return texture2D(normalmap, c).xyz;
}
float
min6(float a, float b, float c, float d, float e, float f)
{
return min(min(min(min(min(a, b), c), d), e), f);
}
float
border_factor(vec2 c)
{
vec2 coord1 = c + vec2(-SAMPLE_SPREAD, -SAMPLE_SPREAD),
coord2 = c + vec2( SAMPLE_SPREAD, -SAMPLE_SPREAD),
coord3 = c + vec2(-SAMPLE_SPREAD, SAMPLE_SPREAD),
coord4 = c + vec2( SAMPLE_SPREAD, SAMPLE_SPREAD);
vec3 normal1 = normal_sample(coord1),
normal2 = normal_sample(coord2),
normal3 = normal_sample(coord3),
normal4 = normal_sample(coord4);
if (dot(normal1, normal1) < 0.5
&& dot(normal2, normal2) < 0.5
&& dot(normal3, normal3) < 0.5
&& dot(normal4, normal4) < 0.5) {
return 0.0;
} else {
vec4 depths = vec4(depth_sample(coord1),
depth_sample(coord2),
depth_sample(coord3),
depth_sample(coord4));
vec3 ratios1 = depths.xxx/depths.yzw, ratios2 = depths.yyz/depths.zww;
if (are_depths_border(ratios1) || are_depths_border(ratios2)) {
return 1.0;
} else {
float normal_border = 1.0 - min6(
dot(normal1, normal2),
dot(normal1, normal3),
dot(normal1, normal4),
dot(normal2, normal3),
dot(normal2, normal4),
dot(normal3, normal4)
);
return normal_border;
}
}
}
void
main()
{
gl_FragColor = mix(texture2D(colormap, coord), line_color, border_factor(coord));
}
;
: (line-art-step1-program) ( -- step1 )
line-art-step1-vertex-shader-source line-art-step1-fragment-shader-source
<simple-gl-program> ;
: (line-art-step2-program) ( -- step2 )
line-art-step2-vertex-shader-source line-art-step2-fragment-shader-source
<simple-gl-program> ;
: (line-art-framebuffer-texture) ( dim iformat xformat -- texture )
swapd >r >r >r
GL_TEXTURE0 glActiveTexture
gen-texture GL_TEXTURE_2D over glBindTexture
GL_TEXTURE_2D GL_TEXTURE_WRAP_S GL_CLAMP glTexParameteri
GL_TEXTURE_2D GL_TEXTURE_WRAP_T GL_CLAMP glTexParameteri
GL_TEXTURE_2D GL_TEXTURE_MAG_FILTER GL_NEAREST glTexParameteri
GL_TEXTURE_2D GL_TEXTURE_MIN_FILTER GL_NEAREST glTexParameteri
GL_TEXTURE_2D 0 r> r> first2 0 r> GL_UNSIGNED_BYTE f glTexImage2D ;
: (line-art-color-texture) ( dim -- texture )
GL_RGBA16F_ARB GL_RGBA (line-art-framebuffer-texture) ;
: (line-art-normal-texture) ( dim -- texture )
GL_RGBA16F_ARB GL_RGBA (line-art-framebuffer-texture) ;
: (line-art-depth-texture) ( dim -- texture )
GL_DEPTH_COMPONENT32 GL_DEPTH_COMPONENT (line-art-framebuffer-texture) ;
: (attach-framebuffer-texture) ( texture attachment -- )
swap >r >r GL_FRAMEBUFFER_EXT r> GL_TEXTURE_2D r> 0 glFramebufferTexture2DEXT gl-error ;
: (line-art-framebuffer) ( color-texture normal-texture depth-texture -- framebuffer )
3array gen-framebuffer dup [
swap GL_COLOR_ATTACHMENT0_EXT
GL_COLOR_ATTACHMENT1_EXT
GL_DEPTH_ATTACHMENT_EXT 3array [ (attach-framebuffer-texture) ] 2each
check-framebuffer
] with-framebuffer ;
: line-art-remake-framebuffer-if-needed ( gadget -- )
dup { rect-dim rect-dim line-art-gadget-framebuffer-dim } get-slots = [ 2drop ] [
swap >r
dup (line-art-color-texture) gl-error
swap dup (line-art-normal-texture) gl-error
swap dup (line-art-depth-texture) gl-error
swap >r
[ (line-art-framebuffer) ] 3keep
r> r> { set-line-art-gadget-framebuffer
set-line-art-gadget-color-texture
set-line-art-gadget-normal-texture
set-line-art-gadget-depth-texture
set-line-art-gadget-framebuffer-dim } set-slots
] if ;
M: line-art-gadget graft* ( gadget -- )
"2.0" { "GL_ARB_draw_buffers"
"GL_ARB_shader_objects"
"GL_ARB_multitexture"
"GL_ARB_texture_float" }
require-gl-version-or-extensions
{ "GL_EXT_framebuffer_object" } require-gl-extensions
GL_CULL_FACE glEnable
GL_DEPTH_TEST glEnable
(line-art-step1-program) over set-line-art-gadget-step1-program
(line-art-step2-program) swap set-line-art-gadget-step2-program ;
M: line-art-gadget ungraft* ( gadget -- )
dup line-art-gadget-framebuffer [
{ [ line-art-gadget-step1-program [ delete-gl-program ] when* ]
[ line-art-gadget-step2-program [ delete-gl-program ] when* ]
[ line-art-gadget-framebuffer [ delete-framebuffer ] when* ]
[ line-art-gadget-color-texture [ delete-texture ] when* ]
[ line-art-gadget-normal-texture [ delete-texture ] when* ]
[ line-art-gadget-depth-texture [ delete-texture ] when* ]
[ f swap set-line-art-gadget-framebuffer-dim ]
[ f swap set-line-art-gadget-framebuffer ] } call-with
] [ drop ] if ;
: line-art-draw-setup ( gadget -- gadget )
0.0 0.0 0.0 1.0 glClearColor
GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT bitor glClear
dup demo-gadget-set-matrices
dup line-art-remake-framebuffer-if-needed
gl-error ;
: line-art-clear-framebuffer ( -- )
GL_COLOR_ATTACHMENT0_EXT glDrawBuffer
0.2 0.2 0.2 1.0 glClearColor
GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT bitor glClear
GL_COLOR_ATTACHMENT1_EXT glDrawBuffer
0.0 0.0 0.0 0.0 glClearColor
GL_COLOR_BUFFER_BIT glClear ;
M: line-art-gadget draw-gadget* ( gadget -- )
line-art-draw-setup
dup line-art-gadget-framebuffer [
line-art-clear-framebuffer
{ GL_COLOR_ATTACHMENT0_EXT GL_COLOR_ATTACHMENT1_EXT } set-draw-buffers
dup line-art-gadget-step1-program dup [
"color" glGetUniformLocation 0.6 0.5 0.5 1.0 glUniform4f
0.0 -0.12 0.0 glTranslatef
dup line-art-gadget-model first3 draw-bunny
] with-gl-program
] with-framebuffer
init-matrices
dup line-art-gadget-color-texture GL_TEXTURE_2D GL_TEXTURE0 bind-texture-unit
dup line-art-gadget-normal-texture GL_TEXTURE_2D GL_TEXTURE1 bind-texture-unit
dup line-art-gadget-depth-texture GL_TEXTURE_2D GL_TEXTURE2 bind-texture-unit
line-art-gadget-step2-program dup [
{ [ "colormap" glGetUniformLocation 0 glUniform1i ]
[ "normalmap" glGetUniformLocation 1 glUniform1i ]
[ "depthmap" glGetUniformLocation 2 glUniform1i ]
[ "line_color" glGetUniformLocation 0.2 0.0 0.0 1.0 glUniform4f ] } call-with
{ -1.0 -1.0 } { 1.0 1.0 } rect-vertices
] with-gl-program ;
: line-art-window ( -- )
[ <line-art-gadget> "Line Art" open-window ] with-ui ;
MAIN: line-art-window

View File

@ -1,6 +1,6 @@
USING: arrays combinators.lib kernel math math.functions math.vectors namespaces USING: arrays combinators.lib kernel math math.functions math.vectors namespaces
opengl opengl.gl sequences ui ui.gadgets ui.gestures ui.render ; opengl opengl.gl sequences ui ui.gadgets ui.gestures ui.render ;
IN: opengl-demo-support IN: opengl.demo-support
: NEAR-PLANE 1.0 64.0 / ; inline : NEAR-PLANE 1.0 64.0 / ; inline
: FAR-PLANE 4.0 ; inline : FAR-PLANE 4.0 ; inline

View File

@ -444,8 +444,11 @@ PREDICATE: integer gl-program (gl-program?) ;
[ "Required GLSL version " % % " not supported (" % glsl-version % " available)" % ] [ "Required GLSL version " % % " not supported (" % glsl-version % " available)" % ]
(require-gl) ; (require-gl) ;
: has-gl-version-or-extensions? ( version extensions -- ? )
has-gl-extensions? swap has-gl-version? or ;
: require-gl-version-or-extensions ( version extensions -- ) : require-gl-version-or-extensions ( version extensions -- )
2array [ first2 has-gl-extensions? swap has-gl-version? or ] 2array [ first2 has-gl-version-or-extensions? ] [
[ dup first (make-gl-version-error) "\n" % dup first (make-gl-version-error) "\n" %
second (make-gl-extensions-error) "\n" % ] second (make-gl-extensions-error) "\n" %
(require-gl) ; ] (require-gl) ;