doc: Add "User-Defined Shader Types" section.
authorDavid Thompson <dthompson2@worcester.edu>
Wed, 8 Apr 2020 21:05:58 +0000 (17:05 -0400)
committerDavid Thompson <dthompson2@worcester.edu>
Wed, 8 Apr 2020 21:07:38 +0000 (17:07 -0400)
doc/api.texi

index 99e225d..9cfa26a 100644 (file)
@@ -3234,6 +3234,29 @@ Return a hash table of uniforms for @var{shader}.
 Return a hash table of attributes for @var{shader}.
 @end deffn
 
+@deffn {Procedure} shader-uniform-set! shader uniform value
+@end deffn
+
+@subsubsection Attributes
+
+@deffn {Procedure} attribute? obj
+Return @code{#t} if @var{obj} is an attribute.
+@end deffn
+
+@deffn {Procedure} attribute-name attribute
+Return the variable name of @var{attribute}.
+@end deffn
+
+@deffn {Procedure} attribute-location attribute
+Return the binding location of @var{attribute}.
+@end deffn
+
+@deffn {Procedure} attribute-type attribute
+Return the data type of @var{attribute}.
+@end deffn
+
+@subsubsection Uniforms
+
 @deffn {Procedure} uniform? obj
 Return @code{#t} if @var{obj} is a uniform.
 @end deffn
@@ -3250,24 +3273,128 @@ Return the data type of @var{uniform}.
 Return the current value of @var{uniform}.
 @end deffn
 
-@deffn {Procedure} uniform-default-value uniform
-Return the default value of @var{uniform}.
-@end deffn
+@subsubsection User-Defined Shader Types
 
-@deffn {Procedure} attribute? obj
-Return @code{#t} if @var{obj} is an attribute.
-@end deffn
+The shader examples in this manual thus far have only shown uniforms
+defined using primitive types.  However, GLSL shaders support
+user-defined compound structs, such as this one:
 
-@deffn {Procedure} attribute-name attribute
-Return the variable name of @var{attribute}.
-@end deffn
+@example
+@verbatim
+struct DirectionalLight {
+    vec3 direction;
+    vec3 ambient;
+    vec3 diffuse;
+    vec3 specular;
+};
+
+uniform DirectionalLight light;
+@end verbatim
+@end example
+
+While @code{light} is declared as a single uniform in the shader code,
+OpenGL translates this into @emph{four} uniforms in this case: One
+uniform each member of the @code{DirectionalLight} struct.  This poses
+a problem for sending Scheme data to the GPU.  How can compound Scheme
+data translate into compound uniform data on the GPU?  The answer is
+with shader types.  Shader types are a special kind of Guile struct
+that provide a one-to-one mapping between a Scheme data structure and
+a shader struct.
+
+Some example code will explain this concept best.  Here is the Scheme
+equivalent of the @code{DirectionalLight} struct:
+
+@example
+(define-shader-type <directional-light>
+  make-directional-light
+  directional-light?
+  (float-vec3 direction directional-light-direction)
+  (float-vec3 ambient directional-light-ambient)
+  (float-vec3 diffuse directional-light-diffuse)
+  (float-vec3 specular directional-light-specular)
+  (float shininess directional-light-shininess))
+@end example
+
+The macro @code{define-shader-type} closely resembles the familiar
+@code{define-record-type} from SRFI-9, but with one notable
+difference: Each struct field contains type information.  The type
+must be one of several primitive types (documented below) or another
+shader type in the case of a nested structure.
+
+It is important to note that the names of the shader type fields
+@emph{must} match the names of the struct members in the GLSL code,
+otherwise Chickadee will be unable to perform the proper translation.
+
+As of this writing, this interface is new and experimental.  It
+remains to be seen if this model is robust enough for all use-cases.
+
+Primitive data types:
+
+@defvar bool
+Either @code{#t} or @code{#f}.
+@end defvar
+
+@defvar int
+An integer.
+@end defvar
+
+@defvar unsigned-int
+An unsigned integer.
+@end defvar
+
+@defvar float
+A floating point number.
+@end defvar
+
+@defvar float-vec2
+A 2D vector (@pxref{Vectors}.)
+@end defvar
+
+@defvar float-vec3
+A 3D vector (@pxref{Vectors}.)
+@end defvar
+
+@defvar float-vec4
+A color.
+@end defvar
+
+@defvar mat4
+A matrix (@pxref{Matrices}.)
+@end defvar
+
+@defvar sampler-2d
+A texture (@pxref{Textures}.)
+@end defvar
+
+@defvar local-field
+A special type that means that the data is for the client-side
+(Scheme-side) only and should not be sent to the GPU.  Any object may
+be stored in a local field.
+@end defvar
+
+@deffn {Syntax} define-shader-type <name> constructor predicate @
+                (field-type field-name [field-getter] [field-setter]) @dots{}
+
+Define a new shader data type called @var{<name>}.
+
+Instances of this data type are created by calling the
+@var{constructor} procedure.  This procedure maps each field to a
+keyword argument.  A shader data type with the fields @code{foo},
+@code{bar}, and @code{baz} would have a constructor that accepts the
+keyword arguments @code{#:foo}, @code{#:bar}, and @code{#:baz}.
+
+A procedure named @var{predicate} will test if an object is a
+@var{<name>} shader data type.
+
+Fields follow the format @code{(field-type field-name [field-getter]
+[field-setter])}.  @var{field-type} and @var{field-name} are required
+for each field, but @var{field-getter} and @var{field-setter} are
+optional.
 
-@deffn {Procedure} attribute-location attribute
-Return the binding location of @var{attribute}.
 @end deffn
 
-@deffn {Procedure} attribute-type attribute
-Return the data type of @var{attribute}.
+@deffn {Procedure} shader-data-type? obj
+Return @code{#t} if @var{obj} is a shader data type object.
 @end deffn
 
 @node Audio