}
{ $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 }
"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." } ;
}
{ $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." } ;
{ "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
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
"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: }
;
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
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 ] }
: (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 -- )
"(" ")" 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 ]
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 -- )
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 )
[ 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>> ]
[ render-vertex-indexes-instanced ]
[ render-vertex-indexes ] if*
]
+ [ framebuffer>> [ GL_RASTERIZER_DISCARD glDisable ] unless ]
} cleave ; inline
! (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>
}
{ $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." } ;
; "> }
{ $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
}
{ $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
{ "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." } ;
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: }
"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"
! (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 }
{ 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
{ 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 ;
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 ;
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 -- ? )
! (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