]> gitweb.factorcode.org Git - factor.git/commitdiff
move vertex-formats and vertex-arrays to gpu.shaders so we can use them for transform...
authorJoe Groff <arcata@gmail.com>
Sat, 25 Jul 2009 16:30:59 +0000 (11:30 -0500)
committerJoe Groff <arcata@gmail.com>
Sat, 25 Jul 2009 16:30:59 +0000 (11:30 -0500)
extra/gpu/render/render-docs.factor
extra/gpu/render/render.factor
extra/gpu/shaders/shaders-docs.factor
extra/gpu/shaders/shaders.factor
extra/gpu/util/util.factor

index f198558b06a0992c563fc16a265d18273739a3bc..187f08a7ea802349f4672fdd4011d6978af30b74 100755 (executable)
@@ -34,13 +34,6 @@ HELP: <multi-index-range>
 }
 { $description "Constructs a " { $link multi-index-range } " tuple." } ;
 
-HELP: <vertex-array>
-{ $values
-    { "program-instance" program-instance } { "vertex-formats" "a list of " { $link buffer-ptr } "/" { $link vertex-format } " pairs" }
-    { "vertex-array" vertex-array }
-}
-{ $description "Creates a new " { $link vertex-array } " to feed data to " { $snippet "program-instance" } " from the set of " { $link buffer } "s specified in " { $snippet "vertex-formats" } "." } ;
-
 HELP: UNIFORM-TUPLE:
 { $syntax <" UNIFORM-TUPLE: class-name
     { "slot" uniform-type dimension }
@@ -78,30 +71,9 @@ $nl
 "A value of a uniform tuple type is a standard Factor tuple. Uniform tuples are constructed with " { $link new } " or " { $link boa } ", and values are placed inside them using standard slot accessors."
 } ;
 
-HELP: VERTEX-FORMAT:
-{ $syntax <" VERTEX-FORMAT: format-name
-    { "attribute"/f component-type dimension normalize? }
-    { "attribute"/f component-type dimension normalize? }
-    ...
-    { "attribute"/f component-type dimension normalize? } ; "> }
-{ $description "Defines a new binary " { $link vertex-format } " for structuring vertex data stored in " { $link buffer } "s. Each " { $snippet "attribute" } " name either corresponds to an input parameter of a vertex shader, or is " { $link f } " to include padding in the vertex format. The " { $link component-type } " determines the format of the components, and the " { $snippet "dimension" } " determines the number of components. If the " { $snippet "component-type" } " is an integer type and " { $snippet "normalize?" } " is true, the component values will be scaled to the range 0.0 to 1.0 when fed to the vertex shader; otherwise, they will be cast to floats retaining their integral values." } ;
-
-HELP: VERTEX-STRUCT:
-{ $syntax <" VERTEX-STRUCT: struct-name format-name "> }
-{ $description "Defines a struct C type (like " { $link POSTPONE: C-STRUCT: } ") with the same binary format and component types as the given " { $link vertex-format } "." } ;
-
 HELP: bool-uniform
 { $class-description "This " { $link uniform-type } " indicates that a slot of a " { $link uniform-tuple } " corresponds to a boolean uniform parameter." } ;
 
-HELP: buffer>vertex-array
-{ $values
-    { "vertex-buffer" buffer } { "program-instance" program-instance } { "format" vertex-format }
-    { "vertex-array" vertex-array }
-}
-{ $description "Creates a new " { $link vertex-array } " from the entire contents of a single " { $link buffer } " in a single " { $link vertex-format } " for use with " { $snippet "program-instance" } "." } ;
-
-{ vertex-array <vertex-array> buffer>vertex-array } related-words
-
 HELP: bvec2-uniform
 { $class-description "This " { $link uniform-type } " indicates that a slot of a " { $link uniform-tuple } " corresponds to a two-component boolean vector uniform parameter." } ;
 
@@ -117,18 +89,6 @@ HELP: define-uniform-tuple
 }
 { $description "Defines a new " { $link uniform-tuple } " as a subclass of " { $snippet "superclass" } " with the slots specified by the " { $link uniform } " tuple values in " { $snippet "uniforms" } ". The runtime equivalent of " { $link POSTPONE: UNIFORM-TUPLE: } ". This word must be called inside a compilation unit." } ;
 
-HELP: define-vertex-format
-{ $values
-    { "class" class } { "vertex-attributes" sequence }
-}
-{ $description "Defines a new " { $link vertex-format } " with the binary format specified by the " { $link vertex-attribute } " tuple values in " { $snippet "vertex-attributes" } ". The runtime equivalent of " { $link POSTPONE: VERTEX-FORMAT: } ". This word must be called inside a compilation unit." } ;
-
-HELP: define-vertex-struct
-{ $values
-    { "struct-name" string } { "vertex-format" vertex-format }
-}
-{ $description "Defines a new struct C type from a " { $link vertex-format } ". The runtime equivalent of " { $link POSTPONE: VERTEX-STRUCT: } ". This word must be called inside a compilation unit." } ;
-
 HELP: float-uniform
 { $class-description "This " { $link uniform-type } " indicates that a slot of a " { $link uniform-tuple } " corresponds to a float uniform parameter." } ;
 
@@ -254,9 +214,10 @@ HELP: render-set
 { "The " { $snippet "uniforms" } " slot contains a " { $link uniform-tuple } " with values for the shader program's uniform parameters." }
 { "The " { $snippet "indexes" } " slot contains one of the " { $link vertex-indexes } " types and selects elements from the vertex array to be rendered." }
 { "The " { $snippet "instances" } " slot, if not " { $link f } ", instructs the GPU to render several instances of the same set of vertexes. Instancing requires OpenGL 3.1 or one of the " { $snippet "GL_EXT_draw_instanced" } " or " { $snippet "GL_ARB_draw_instanced" } " extensions." }
-{ "The " { $snippet "framebuffer" } " slot determines the target for the rendering output. Either the " { $link system-framebuffer } " or a user-created " { $link framebuffer } " object can be specified. User-created framebuffers require OpenGL 3.0 or one of the " { $snippet "GL_EXT_framebuffer_object" } " or " { $snippet "GL_ARB_framebuffer_object" } " extensions." }
-{ "The " { $snippet "output-attachments" } " slot specifies which of the framebuffer's " { $link color-attachment-ref } "s to write the fragment shader's color output to. If the shader uses " { $snippet "gl_FragColor" } " or " { $snippet "gl_FragData[n]" } " to write its output, then " { $snippet "output-attachments" } " should be an array of " { $link color-attachment-ref } "s, and the output to color attachment binding is determined positionally. If the shader uses named output values, then " { $snippet "output-attachments" } " should be a list of string/" { $link color-attachment-ref } " pairs, mapping output names to color attachments. Named output values are available in GLSL 1.30 or later, and GLSL 1.20 and earlier using the " { $snippet "GL_EXT_gpu_shader4" } " extension." }
-} } ;
+{ "The " { $snippet "framebuffer" } " slot determines the target for the rendering output. Either the " { $link system-framebuffer } " or a user-created " { $link framebuffer } " object can be specified. " { $link f } " can also be specified to disable rasterization and only run the vertex transformation rendering stage." }
+{ "The " { $snippet "output-attachments" } " slot specifies which of the framebuffer's " { $link color-attachment-ref } "s to write the fragment shader's color output to. If the shader uses " { $snippet "gl_FragColor" } " or " { $snippet "gl_FragData[n]" } " to write its output, then " { $snippet "output-attachments" } " should be an array of " { $link color-attachment-ref } "s, and the output to color attachment binding is determined positionally. If the shader uses named output values, then " { $snippet "output-attachments" } " should be a list of string/" { $link color-attachment-ref } " pairs, mapping output names to color attachments." }
+} }
+{ $notes "User-created framebuffers require OpenGL 3.0 or one of the " { $snippet "GL_EXT_framebuffer_object" } " or " { $snippet "GL_ARB_framebuffer_object" } " extensions. Disabling rasterization requires OpenGL 3.0 or the " { $snippet "GL_EXT_transform_feedback" } " extension. Named output-attachment values are available in GLSL 1.30 or later, and GLSL 1.20 and earlier using the " { $snippet "GL_EXT_gpu_shader4" } " extension." } ;
 
 { render render-set } related-words
 
@@ -313,29 +274,6 @@ HELP: vec3-uniform
 HELP: vec4-uniform
 { $class-description "This " { $link uniform-type } " indicates that a slot of a " { $link uniform-tuple } " corresponds to a four-component float vector uniform parameter." } ;
 
-HELP: vertex-array
-{ $class-description "A " { $snippet "vertex-array" } " object associates a shader " { $link program-instance } " with vertex attribute data from one or more " { $link buffer } "s. The format of the binary data inside these buffers is described using " { $link vertex-format } "s. " { $snippet "vertex-array" } "s are constructed using the " { $link <vertex-array> } " or " { $link buffer>vertex-array } " words." } ;
-
-HELP: vertex-array-buffer
-{ $values
-    { "vertex-array" vertex-array }
-    { "vertex-buffer" buffer }
-}
-{ $description "Returns the first " { $link buffer } " object comprised in " { $snippet "vertex-array" } "." } ;
-
-HELP: vertex-attribute
-{ $class-description "This tuple type is passed to " { $link define-vertex-format } " to define a new " { $link vertex-format } " type." } ;
-
-HELP: vertex-format
-{ $class-description "This class encompasses all vertex formats defined by " { $link POSTPONE: VERTEX-FORMAT: } ". A vertex format defines the binary layout of vertex attribute data in a " { $link buffer } " for use as part of a " { $link vertex-array } ". See the " { $link POSTPONE: VERTEX-FORMAT: } " documentation for details on how vertex formats are defined." } ;
-
-HELP: vertex-format-size
-{ $values
-    { "format" vertex-format }
-    { "size" integer }
-}
-{ $description "Returns the size in bytes of a set of vertex attributes in " { $snippet "format" } "." } ;
-
 HELP: vertex-indexes
 { $class-description "This class is a union of the following tuple types, any of which can be used as the " { $snippet "indexes" } " slot of a " { $link render-set } " to select elements from a " { $link vertex-array } " for rendering."
 { $list
@@ -349,11 +287,6 @@ ARTICLE: "gpu.render" "Rendering"
 "The " { $vocab-link "gpu.render" } " vocabulary contains words for organizing and submitting data to the GPU for rendering."
 { $subsection render }
 { $subsection render-set }
-"Render data inside GPU " { $link buffer } "s is organized into " { $link vertex-array } "s for consumption by shader code:"
-{ $subsection vertex-array }
-{ $subsection <vertex-array> }
-{ $subsection buffer>vertex-array }
-{ $subsection POSTPONE: VERTEX-FORMAT: }
 { $link uniform-tuple } "s provide Factor types for containing and submitting shader uniform parameters:"
 { $subsection POSTPONE: UNIFORM-TUPLE: }
 ;
index 51bd549b7a82c67ad78b92eb97a66b8324765674..3d2fef3807383e266a1dc0b25bdeb14b9a459604 100644 (file)
@@ -3,24 +3,17 @@ USING: accessors alien alien.c-types alien.structs arrays
 assocs classes classes.mixin classes.parser classes.singleton
 classes.tuple classes.tuple.private combinators combinators.tuple destructors fry
 generic generic.parser gpu gpu.buffers gpu.framebuffers
-gpu.framebuffers.private gpu.shaders gpu.state gpu.textures
-gpu.textures.private half-floats images kernel lexer locals
-math math.order math.parser namespaces opengl opengl.gl parser
-quotations sequences slots sorting specialized-arrays.alien
-specialized-arrays.float specialized-arrays.int
+gpu.framebuffers.private gpu.shaders gpu.shaders.private gpu.state
+gpu.textures gpu.textures.private half-floats images kernel
+lexer locals math math.order math.parser namespaces opengl
+opengl.gl parser quotations sequences slots sorting
+specialized-arrays.alien specialized-arrays.float specialized-arrays.int
 specialized-arrays.uint strings tr ui.gadgets.worlds variants
 vocabs.parser words ;
 IN: gpu.render
 
-UNION: ?string string POSTPONE: f ;
 UNION: ?integer integer POSTPONE: f ;
 
-TUPLE: vertex-attribute
-    { name            ?string        read-only initial: f }
-    { component-type  component-type read-only initial: float-components }
-    { dim             integer        read-only initial: 4 }
-    { normalize?      boolean        read-only initial: f } ;
-
 VARIANT: uniform-type
     bool-uniform
     bvec2-uniform
@@ -111,52 +104,12 @@ VARIANT: primitive-mode
     triangle-strip-mode
     triangle-fan-mode ;
 
-MIXIN: vertex-format
-
 TUPLE: uniform-tuple ;
 
-GENERIC: vertex-format-size ( format -- size )
-
 ERROR: invalid-uniform-type uniform ;
 
 <PRIVATE
 
-: gl-vertex-type ( component-type -- gl-type )
-    {
-        { ubyte-components          [ GL_UNSIGNED_BYTE  ] }
-        { ushort-components         [ GL_UNSIGNED_SHORT ] }
-        { uint-components           [ GL_UNSIGNED_INT   ] }
-        { half-components           [ GL_HALF_FLOAT     ] }
-        { float-components          [ GL_FLOAT          ] }
-        { byte-integer-components   [ GL_BYTE           ] }
-        { short-integer-components  [ GL_SHORT          ] }
-        { int-integer-components    [ GL_INT            ] }
-        { ubyte-integer-components  [ GL_UNSIGNED_BYTE  ] }
-        { ushort-integer-components [ GL_UNSIGNED_SHORT ] }
-        { uint-integer-components   [ GL_UNSIGNED_INT   ] }
-    } case ;
-
-: vertex-type-size ( component-type -- size ) 
-    {
-        { ubyte-components          [ 1 ] }
-        { ushort-components         [ 2 ] }
-        { uint-components           [ 4 ] }
-        { half-components           [ 2 ] }
-        { float-components          [ 4 ] }
-        { byte-integer-components   [ 1 ] }
-        { short-integer-components  [ 2 ] }
-        { int-integer-components    [ 4 ] }
-        { ubyte-integer-components  [ 1 ] }
-        { ushort-integer-components [ 2 ] }
-        { uint-integer-components   [ 4 ] }
-    } case ;
-
-: vertex-attribute-size ( vertex-attribute -- size )
-    [ component-type>> vertex-type-size ] [ dim>> ] bi * ;
-
-: vertex-attributes-size ( vertex-attributes -- size )
-    [ vertex-attribute-size ] [ + ] map-reduce ;
-
 : gl-index-type ( index-type -- gl-index-type )
     {
         { ubyte-indexes  [ GL_UNSIGNED_BYTE  ] }
@@ -210,56 +163,6 @@ M: multi-index-elements render-vertex-indexes
 : (bind-texture-unit) ( texture texture-unit -- )
     swap [ GL_TEXTURE0 + glActiveTexture ] [ bind-texture drop ] bi* ; inline
 
-:: [bind-vertex-attribute] ( stride offset vertex-attribute -- stride offset' quot )
-    vertex-attribute name>>                 :> name
-    vertex-attribute component-type>>       :> type
-    type gl-vertex-type                     :> gl-type
-    vertex-attribute dim>>                  :> dim
-    vertex-attribute normalize?>> >c-bool   :> normalize?
-    vertex-attribute vertex-attribute-size  :> size
-
-    stride offset size +
-    {
-        { [ name not ] [ [ 2drop ] ] }
-        {
-            [ type unnormalized-integer-components? ]
-            [
-                {
-                    name attribute-index [ glEnableVertexAttribArray ] keep
-                    dim gl-type stride offset
-                } >quotation :> dip-block
-                
-                { dip-block dip <displaced-alien> glVertexAttribIPointer } >quotation
-            ]
-        }
-        [
-            {
-                name attribute-index [ glEnableVertexAttribArray ] keep
-                dim gl-type normalize? stride offset
-            } >quotation :> dip-block
-
-            { dip-block dip <displaced-alien> glVertexAttribPointer } >quotation
-        ]
-    } cond ;
-
-:: [bind-vertex-format] ( vertex-attributes -- quot )
-    vertex-attributes vertex-attributes-size :> stride
-    stride 0 vertex-attributes [ [bind-vertex-attribute] ] { } map-as 2nip :> attributes-cleave
-    { attributes-cleave 2cleave } >quotation :> with-block
-
-    { drop vertex-buffer with-block with-buffer-ptr } >quotation ; 
-
-GENERIC: bind-vertex-format ( program-instance buffer-ptr format -- )
-
-: define-vertex-format-methods ( class vertex-attributes -- )
-    [
-        [ \ bind-vertex-format create-method-in ] dip
-        [bind-vertex-format] define
-    ] [
-        [ \ vertex-format-size create-method-in ] dip
-        [ \ drop ] dip vertex-attributes-size [ ] 2sequence define
-    ] 2bi ;
-
 GENERIC: bind-uniform-textures ( program-instance uniform-tuple -- )
 GENERIC: bind-uniforms ( program-instance uniform-tuple -- )
 
@@ -510,12 +413,6 @@ padding-no [ 0 ] initialize
     "(" ")" surround
     padding-no inc ;
 
-: vertex-attribute>c-type ( vertex-attribute -- {type,name} )
-    [
-        [ component-type>> component-type>c-type ]
-        [ dim>> c-array-dim ] bi append
-    ] [ name>> [ padding-name ] unless* ] bi 2array ;
-
 : (define-uniform-tuple) ( class superclass uniforms -- )
     {
         [ [ uniform>slot ] map define-tuple-class ]
@@ -536,55 +433,12 @@ padding-no [ 0 ] initialize
 
 PRIVATE>
 
-: define-vertex-format ( class vertex-attributes -- )
-    [
-        [
-            [ define-singleton-class ]
-            [ vertex-format add-mixin-instance ]
-            [ ] tri
-        ] [ define-vertex-format-methods ] bi*
-    ]
-    [ "vertex-format-attributes" set-word-prop ] 2bi ;
-
-SYNTAX: VERTEX-FORMAT:
-    CREATE-CLASS parse-definition
-    [ first4 vertex-attribute boa ] map
-    define-vertex-format ;
-
-: define-vertex-struct ( struct-name vertex-format -- )
-    [ current-vocab ] dip
-    "vertex-format-attributes" word-prop [ vertex-attribute>c-type ] map
-    define-struct ;
-
-SYNTAX: VERTEX-STRUCT:
-    scan scan-word define-vertex-struct ;
-
 : define-uniform-tuple ( class superclass uniforms -- )
     (define-uniform-tuple) ; inline
 
 SYNTAX: UNIFORM-TUPLE:
     parse-uniform-tuple-definition define-uniform-tuple ;
 
-TUPLE: vertex-array < gpu-object
-    { program-instance program-instance read-only }
-    { vertex-buffers sequence read-only } ;
-
-M: vertex-array dispose
-    [ [ delete-vertex-array ] when* f ] change-handle drop ;
-
-: <vertex-array> ( program-instance vertex-formats -- vertex-array )
-    gen-vertex-array
-    [ glBindVertexArray [ first2 bind-vertex-format ] with each ]
-    [ -rot [ first buffer>> ] map vertex-array boa ] 3bi
-    window-resource ;
-
-: buffer>vertex-array ( vertex-buffer program-instance format -- vertex-array )
-    [ swap ] dip
-    [ 0 <buffer-ptr> ] dip 2array 1array <vertex-array> ; inline
-
-: vertex-array-buffer ( vertex-array -- vertex-buffer )
-    vertex-buffers>> first ;
-
 <PRIVATE 
 
 : bind-vertex-array ( vertex-array -- )
@@ -606,13 +460,15 @@ M: vertex-array dispose
 
 PRIVATE>
 
+UNION: ?any-framebuffer any-framebuffer POSTPONE: f ;
+
 TUPLE: render-set
     { primitive-mode primitive-mode read-only }
     { vertex-array vertex-array read-only }
     { uniforms uniform-tuple read-only }
     { indexes vertex-indexes initial: T{ index-range } read-only } 
     { instances ?integer initial: f read-only }
-    { framebuffer any-framebuffer initial: system-framebuffer read-only }
+    { framebuffer ?any-framebuffer initial: system-framebuffer read-only }
     { output-attachments sequence initial: { default-attachment } read-only } ;
 
 : <render-set> ( x quot-assoc -- render-set )
@@ -631,7 +487,11 @@ TUPLE: render-set
             [ vertex-array>> program-instance>> ] [ uniforms>> ] bi
             [ bind-uniform-textures ] [ bind-uniforms ] 2bi
         ]
-        [ GL_DRAW_FRAMEBUFFER swap framebuffer>> framebuffer-handle glBindFramebuffer ]
+        [
+            framebuffer>> 
+            [ GL_DRAW_FRAMEBUFFER swap framebuffer-handle glBindFramebuffer ]
+            [ GL_RASTERIZER_DISCARD glEnable ] if*
+        ]
         [
             [ vertex-array>> program-instance>> ]
             [ framebuffer>> ]
@@ -644,5 +504,6 @@ TUPLE: render-set
             [ render-vertex-indexes-instanced ]
             [ render-vertex-indexes ] if*
         ]
+        [ framebuffer>> [ GL_RASTERIZER_DISCARD glDisable ] unless ]
     } cleave ; inline
 
index cac61114d68e6f14962fecd45dad43d8bf24cd6c..456a76e5ce93070bdd71700dff05368ee8eed702 100755 (executable)
@@ -1,5 +1,6 @@
 ! (c)2009 Joe Groff bsd license
-USING: help.markup help.syntax kernel math multiline quotations strings ;
+USING: alien.syntax classes gpu.buffers help.markup help.syntax
+images kernel math multiline quotations sequences strings ;
 IN: gpu.shaders
 
 HELP: <program-instance>
@@ -16,6 +17,13 @@ HELP: <shader-instance>
 }
 { $description "Compiles an instance of " { $snippet "shader" } " for the current graphics context. If an instance already exists for " { $snippet "shader" } " in the current context, it is reused." } ;
 
+HELP: <vertex-array>
+{ $values
+    { "program-instance" program-instance } { "vertex-formats" "a list of " { $link buffer-ptr } "/" { $link vertex-format } " pairs" }
+    { "vertex-array" vertex-array }
+}
+{ $description "Creates a new " { $link vertex-array } " to feed data to " { $snippet "program-instance" } " from the set of " { $link buffer } "s specified in " { $snippet "vertex-formats" } "." } ;
+
 HELP: GLSL-PROGRAM:
 { $syntax "GLSL-PROGRAM: program-name shader shader ... shader ;" }
 { $description "Defines a new " { $link program } " named " { $snippet "program-name" } ". When the program is instantiated with " { $link <program-instance> } ", it will link together instances of all of the specified " { $link shader } "s to create the program instance." } ;
@@ -32,6 +40,18 @@ shader source
 ; "> }
 { $description "Defines a new " { $link shader } " of kind " { $link shader-kind } " named " { $snippet "shader-name" } ". The shader will read its source code from the current Factor source file between the " { $snippet "GLSL-SHADER:" } " line and the first subsequent line with a single semicolon on it." } ;
 
+HELP: VERTEX-FORMAT:
+{ $syntax <" VERTEX-FORMAT: format-name
+    { "attribute"/f component-type dimension normalize? }
+    { "attribute"/f component-type dimension normalize? }
+    ...
+    { "attribute"/f component-type dimension normalize? } ; "> }
+{ $description "Defines a new binary " { $link vertex-format } " for structuring vertex data stored in " { $link buffer } "s. Each " { $snippet "attribute" } " name either corresponds to an input parameter of a vertex shader, or is " { $link f } " to include padding in the vertex format. The " { $link component-type } " determines the format of the components, and the " { $snippet "dimension" } " determines the number of components. If the " { $snippet "component-type" } " is an integer type and " { $snippet "normalize?" } " is true, the component values will be scaled to the range 0.0 to 1.0 when fed to the vertex shader; otherwise, they will be cast to floats retaining their integral values." } ;
+
+HELP: VERTEX-STRUCT:
+{ $syntax <" VERTEX-STRUCT: struct-name format-name "> }
+{ $description "Defines a struct C type (like " { $link POSTPONE: C-STRUCT: } ") with the same binary format and component types as the given " { $link vertex-format } "." } ;
+
 { POSTPONE: GLSL-PROGRAM: POSTPONE: GLSL-SHADER-FILE: POSTPONE: GLSL-SHADER: } related-words
 
 HELP: attribute-index
@@ -41,6 +61,15 @@ HELP: attribute-index
 }
 { $description "Returns the numeric index of the vertex attribute named " { $snippet "attribute-name" } " in " { $snippet "program-instance" } "." } ;
 
+HELP: buffer>vertex-array
+{ $values
+    { "vertex-buffer" buffer } { "program-instance" program-instance } { "format" vertex-format }
+    { "vertex-array" vertex-array }
+}
+{ $description "Creates a new " { $link vertex-array } " from the entire contents of a single " { $link buffer } " in a single " { $link vertex-format } " for use with " { $snippet "program-instance" } "." } ;
+
+{ vertex-array <vertex-array> buffer>vertex-array } related-words
+
 HELP: compile-shader-error
 { $class-description "An error compiling the source for a " { $link shader } "."
 { $list
@@ -48,6 +77,18 @@ HELP: compile-shader-error
 { "The " { $snippet "log" } " slot contains the error string from the GLSL compiler." }
 } } ;
 
+HELP: define-vertex-format
+{ $values
+    { "class" class } { "vertex-attributes" sequence }
+}
+{ $description "Defines a new " { $link vertex-format } " with the binary format specified by the " { $link vertex-attribute } " tuple values in " { $snippet "vertex-attributes" } ". The runtime equivalent of " { $link POSTPONE: VERTEX-FORMAT: } ". This word must be called inside a compilation unit." } ;
+
+HELP: define-vertex-struct
+{ $values
+    { "struct-name" string } { "vertex-format" vertex-format }
+}
+{ $description "Defines a new struct C type from a " { $link vertex-format } ". The runtime equivalent of " { $link POSTPONE: VERTEX-STRUCT: } ". This word must be called inside a compilation unit." } ;
+
 HELP: fragment-shader
 { $class-description "This " { $link shader-kind } " indicates that a " { $link shader } " is a fragment shader." } ;
 
@@ -103,6 +144,29 @@ HELP: uniform-index
 HELP: vertex-shader
 { $class-description "This " { $link shader-kind } " indicates that a " { $link shader } " is a vertex shader." } ;
 
+HELP: vertex-array
+{ $class-description "A " { $snippet "vertex-array" } " object associates a shader " { $link program-instance } " with vertex attribute data from one or more " { $link buffer } "s. The format of the binary data inside these buffers is described using " { $link vertex-format } "s. " { $snippet "vertex-array" } "s are constructed using the " { $link <vertex-array> } " or " { $link buffer>vertex-array } " words." } ;
+
+HELP: vertex-array-buffer
+{ $values
+    { "vertex-array" vertex-array }
+    { "vertex-buffer" buffer }
+}
+{ $description "Returns the first " { $link buffer } " object comprised in " { $snippet "vertex-array" } "." } ;
+
+HELP: vertex-attribute
+{ $class-description "This tuple type is passed to " { $link define-vertex-format } " to define a new " { $link vertex-format } " type." } ;
+
+HELP: vertex-format
+{ $class-description "This class encompasses all vertex formats defined by " { $link POSTPONE: VERTEX-FORMAT: } ". A vertex format defines the binary layout of vertex attribute data in a " { $link buffer } " for use as part of a " { $link vertex-array } ". See the " { $link POSTPONE: VERTEX-FORMAT: } " documentation for details on how vertex formats are defined." } ;
+
+HELP: vertex-format-size
+{ $values
+    { "format" vertex-format }
+    { "size" integer }
+}
+{ $description "Returns the size in bytes of a set of vertex attributes in " { $snippet "format" } "." } ;
+
 ARTICLE: "gpu.shaders" "Shader objects"
 "The " { $vocab-link "gpu.shaders" } " vocabulary supports defining, compiling, and linking " { $link shader } "s into " { $link program } "s that run on the GPU and control rendering."
 { $subsection POSTPONE: GLSL-PROGRAM: }
@@ -111,6 +175,11 @@ ARTICLE: "gpu.shaders" "Shader objects"
 "A program must be instantiated for each graphics context it is used in:"
 { $subsection <program-instance> }
 "Program instances can be updated on the fly, allowing for interactive development of shaders:"
-{ $subsection refresh-program } ;
+{ $subsection refresh-program }
+"Render data inside GPU " { $link buffer } "s is organized into " { $link vertex-array } "s for consumption by shader code:"
+{ $subsection vertex-array }
+{ $subsection <vertex-array> }
+{ $subsection buffer>vertex-array }
+{ $subsection POSTPONE: VERTEX-FORMAT: } ;
 
 ABOUT: "gpu.shaders"
index e11fa639b4a5a1e435c19f9d667410536bbe7c43..e3b4482c24aa3e75f3c3b6127df475d27e2a15cb 100755 (executable)
@@ -1,17 +1,29 @@
 ! (c)2009 Joe Groff bsd license
-USING: accessors arrays assocs combinators
-combinators.short-circuit definitions destructors gpu
-io.encodings.ascii io.files io.pathnames kernel lexer
-locals math math.parser memoize multiline namespaces
-opengl.gl opengl.shaders parser sequences
+USING: accessors alien alien.c-types alien.structs arrays
+assocs classes.mixin classes.parser classes.singleton
+combinators combinators.short-circuit definitions destructors
+generic.parser gpu gpu.buffers hashtables
+images io.encodings.ascii io.files io.pathnames kernel lexer
+locals math math.parser memoize multiline namespaces opengl
+opengl.gl opengl.shaders parser quotations sequences
 specialized-arrays.int splitting strings ui.gadgets.worlds
-variants hashtables vectors vocabs vocabs.loader words
+variants vectors vocabs vocabs.loader vocabs.parser words
 words.constant ;
 IN: gpu.shaders
 
 VARIANT: shader-kind
     vertex-shader fragment-shader ;
 
+UNION: ?string string POSTPONE: f ;
+
+TUPLE: vertex-attribute
+    { name            ?string        read-only initial: f }
+    { component-type  component-type read-only initial: float-components }
+    { dim             integer        read-only initial: 4 }
+    { normalize?      boolean        read-only initial: f } ;
+
+MIXIN: vertex-format
+
 TUPLE: shader
     { name word read-only initial: t }
     { kind shader-kind read-only }
@@ -25,6 +37,7 @@ TUPLE: program
     { filename read-only }
     { line integer read-only }
     { shaders array read-only }
+    { feedback-format vertex-format read-only }
     { instances hashtable read-only } ;
 
 TUPLE: shader-instance < gpu-object
@@ -35,8 +48,136 @@ TUPLE: program-instance < gpu-object
     { program program }
     { world world } ;
 
+GENERIC: vertex-format-size ( format -- size )
+
+MEMO: uniform-index ( program-instance uniform-name -- index )
+    [ handle>> ] dip glGetUniformLocation ;
+MEMO: attribute-index ( program-instance attribute-name -- index )
+    [ handle>> ] dip glGetAttribLocation ;
+MEMO: output-index ( program-instance output-name -- index )
+    [ handle>> ] dip glGetFragDataLocation ;
+
 <PRIVATE
 
+: gl-vertex-type ( component-type -- gl-type )
+    {
+        { ubyte-components          [ GL_UNSIGNED_BYTE  ] }
+        { ushort-components         [ GL_UNSIGNED_SHORT ] }
+        { uint-components           [ GL_UNSIGNED_INT   ] }
+        { half-components           [ GL_HALF_FLOAT     ] }
+        { float-components          [ GL_FLOAT          ] }
+        { byte-integer-components   [ GL_BYTE           ] }
+        { short-integer-components  [ GL_SHORT          ] }
+        { int-integer-components    [ GL_INT            ] }
+        { ubyte-integer-components  [ GL_UNSIGNED_BYTE  ] }
+        { ushort-integer-components [ GL_UNSIGNED_SHORT ] }
+        { uint-integer-components   [ GL_UNSIGNED_INT   ] }
+    } case ;
+
+: vertex-type-size ( component-type -- size ) 
+    {
+        { ubyte-components          [ 1 ] }
+        { ushort-components         [ 2 ] }
+        { uint-components           [ 4 ] }
+        { half-components           [ 2 ] }
+        { float-components          [ 4 ] }
+        { byte-integer-components   [ 1 ] }
+        { short-integer-components  [ 2 ] }
+        { int-integer-components    [ 4 ] }
+        { ubyte-integer-components  [ 1 ] }
+        { ushort-integer-components [ 2 ] }
+        { uint-integer-components   [ 4 ] }
+    } case ;
+
+: vertex-attribute-size ( vertex-attribute -- size )
+    [ component-type>> vertex-type-size ] [ dim>> ] bi * ;
+
+: vertex-attributes-size ( vertex-attributes -- size )
+    [ vertex-attribute-size ] [ + ] map-reduce ;
+
+:: [bind-vertex-attribute] ( stride offset vertex-attribute -- stride offset' quot )
+    vertex-attribute name>>                 :> name
+    vertex-attribute component-type>>       :> type
+    type gl-vertex-type                     :> gl-type
+    vertex-attribute dim>>                  :> dim
+    vertex-attribute normalize?>> >c-bool   :> normalize?
+    vertex-attribute vertex-attribute-size  :> size
+
+    stride offset size +
+    {
+        { [ name not ] [ [ 2drop ] ] }
+        {
+            [ type unnormalized-integer-components? ]
+            [
+                {
+                    name attribute-index [ glEnableVertexAttribArray ] keep
+                    dim gl-type stride offset
+                } >quotation :> dip-block
+                
+                { dip-block dip <displaced-alien> glVertexAttribIPointer } >quotation
+            ]
+        }
+        [
+            {
+                name attribute-index [ glEnableVertexAttribArray ] keep
+                dim gl-type normalize? stride offset
+            } >quotation :> dip-block
+
+            { dip-block dip <displaced-alien> glVertexAttribPointer } >quotation
+        ]
+    } cond ;
+
+:: [bind-vertex-format] ( vertex-attributes -- quot )
+    vertex-attributes vertex-attributes-size :> stride
+    stride 0 vertex-attributes [ [bind-vertex-attribute] ] { } map-as 2nip :> attributes-cleave
+    { attributes-cleave 2cleave } >quotation :> with-block
+
+    { drop vertex-buffer with-block with-buffer-ptr } >quotation ; 
+
+GENERIC: bind-vertex-format ( program-instance buffer-ptr format -- )
+
+: define-vertex-format-methods ( class vertex-attributes -- )
+    [
+        [ \ bind-vertex-format create-method-in ] dip
+        [bind-vertex-format] define
+    ] [
+        [ \ vertex-format-size create-method-in ] dip
+        [ \ drop ] dip vertex-attributes-size [ ] 2sequence define
+    ] 2bi ;
+
+: component-type>c-type ( component-type -- c-type )
+    {
+        { ubyte-components [ "uchar" ] }
+        { ushort-components [ "ushort" ] }
+        { uint-components [ "uint" ] }
+        { half-components [ "half" ] }
+        { float-components [ "float" ] }
+        { byte-integer-components [ "char" ] }
+        { ubyte-integer-components [ "uchar" ] }
+        { short-integer-components [ "short" ] }
+        { ushort-integer-components [ "ushort" ] }
+        { int-integer-components [ "int" ] }
+        { uint-integer-components [ "uint" ] }
+    } case ;
+
+: c-array-dim ( dim -- string )
+    dup 1 = [ drop "" ] [ number>string "[" "]" surround ] if ;
+
+SYMBOL: padding-no
+padding-no [ 0 ] initialize
+
+: padding-name ( -- name )
+    "padding-"
+    padding-no get number>string append
+    "(" ")" surround
+    padding-no inc ;
+
+: vertex-attribute>c-type ( vertex-attribute -- {type,name} )
+    [
+        [ component-type>> component-type>c-type ]
+        [ dim>> c-array-dim ] bi append
+    ] [ name>> [ padding-name ] unless* ] bi 2array ;
+
 : shader-filename ( shader/program -- filename )
     dup filename>> [ nip ] [ name>> where first ] if* file-name ;
 
@@ -69,6 +210,49 @@ TUPLE: program-instance < gpu-object
 
 PRIVATE>
 
+: define-vertex-format ( class vertex-attributes -- )
+    [
+        [
+            [ define-singleton-class ]
+            [ vertex-format add-mixin-instance ]
+            [ ] tri
+        ] [ define-vertex-format-methods ] bi*
+    ]
+    [ "vertex-format-attributes" set-word-prop ] 2bi ;
+
+SYNTAX: VERTEX-FORMAT:
+    CREATE-CLASS parse-definition
+    [ first4 vertex-attribute boa ] map
+    define-vertex-format ;
+
+: define-vertex-struct ( struct-name vertex-format -- )
+    [ current-vocab ] dip
+    "vertex-format-attributes" word-prop [ vertex-attribute>c-type ] map
+    define-struct ;
+
+SYNTAX: VERTEX-STRUCT:
+    scan scan-word define-vertex-struct ;
+
+TUPLE: vertex-array < gpu-object
+    { program-instance program-instance read-only }
+    { vertex-buffers sequence read-only } ;
+
+M: vertex-array dispose
+    [ [ delete-vertex-array ] when* f ] change-handle drop ;
+
+: <vertex-array> ( program-instance vertex-formats -- vertex-array )
+    gen-vertex-array
+    [ glBindVertexArray [ first2 bind-vertex-format ] with each ]
+    [ -rot [ first buffer>> ] map vertex-array boa ] 3bi
+    window-resource ;
+
+: buffer>vertex-array ( vertex-buffer program-instance format -- vertex-array )
+    [ swap ] dip
+    [ 0 <buffer-ptr> ] dip 2array 1array <vertex-array> ; inline
+
+: vertex-array-buffer ( vertex-array -- vertex-buffer )
+    vertex-buffers>> first ;
+
 TUPLE: compile-shader-error shader log ;
 TUPLE: link-program-error program log ;
 
@@ -82,13 +266,6 @@ TUPLE: link-program-error program log ;
 
 DEFER: <shader-instance>
 
-MEMO: uniform-index ( program-instance uniform-name -- index )
-    [ handle>> ] dip glGetUniformLocation ;
-MEMO: attribute-index ( program-instance attribute-name -- index )
-    [ handle>> ] dip glGetAttribLocation ;
-MEMO: output-index ( program-instance output-name -- index )
-    [ handle>> ] dip glGetFragDataLocation ;
-
 <PRIVATE
 
 : valid-handle? ( handle -- ? )
index 5b7719d06b039a9f8b4545444c76904175c0d7ab..512cea4a17cdf65f24549b999b1ce970dcbcff50 100644 (file)
@@ -1,5 +1,5 @@
 ! (c)2009 Joe Groff bsd license
-USING: gpu.buffers gpu.render gpu.textures images kernel
+USING: gpu.buffers gpu.render gpu.shaders gpu.textures images kernel
 specialized-arrays.float ;
 IN: gpu.util