From 40a2a9e39fc26f851891502bcb6c85abd7627439 Mon Sep 17 00:00:00 2001 From: David Thompson Date: Thu, 23 Sep 2021 08:36:13 -0400 Subject: doc: Expand documentation of 3D graphics API. --- doc/api.texi | 442 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 417 insertions(+), 25 deletions(-) diff --git a/doc/api.texi b/doc/api.texi index 6358732..ca44492 100644 --- a/doc/api.texi +++ b/doc/api.texi @@ -1613,7 +1613,9 @@ blocks to implement additional rendering techniques. * Vector Paths:: Draw filled and stroked paths. * Particles:: Pretty little flying pieces! * Tile Maps:: Draw 2D tile maps. -* 3D Models:: Spinning teapots everywhere. +* Models:: Load 3D models from disk. +* Lights:: Dynamic lighting. +* Meshes:: 3D meshes and materials. * Blending:: Control how pixels are combined. * Framebuffers:: Render to texture. * Viewports:: Restrict rendering to a particular area. @@ -2876,41 +2878,34 @@ Return @code{#t} if @var{obj} is a polygon. Return the list of points that form @var{polygon}. @end deffn -@node 3D Models -@subsection 3D Models +@node Models +@subsection Models @emph{Disclaimer: Chickadee is alpha software, but 3D model support is even more alpha than that. There are many missing features in both the model loading and rendering components, so set your expectations accordingly!} -Chickadee can load and render 3D models in the classic OBJ and more -modern glTF 2.0 formats. +The @code{(chickadee graphics model)} module provides procedures to +load and render 3D models in the classic OBJ and more modern glTF 2.0 +formats. Here's some basic boilerplate to render a 3D model: @example -(use-modules (chickadee) - (chickadee math) - (chickadee math matrix) - (chickadee graphics model)) - -(define model #f) -(define projection-matrix - (perspective-projection (/ pi 3.0) (/ 4.0 3.0) 0.1 500.0)) -;; Adjust these 2 matrices so that you can actually see the model. -(define view-matrix (make-identity-matrix4)) -(define model-matrix (make-identity-matrix4)) +(use-modules (chickadee graphics light) + (chickadee graphics model) + (chickadee graphics skybox)) -(define (load) - (set! model (load-obj "model.obj")) +(define model (load-gltf "Suzanne.gltf")) +(define camera-position (vec3 0.0 0.0 3.0)) +(define world (make-identity-matrix4)) +(define view (look-at camera-position (vec3 0.0 0.0 0.0) (vec3 0.0 1.0 0.0))) +(define projection (perspective-projection (/ pi 3.0) (/ 4.0 3.0) 0.1 5.0)) (define (draw alpha) - (with-projection projection-matrix - (with-depth-test #t - (draw-model model model-matrix view-matrix)))) - -(run-game #:load load #:draw draw) + (with-projection projection + (draw-model model world view camera-position @end example @deffn {Procedure} load-obj file-name @@ -2933,9 +2928,406 @@ which is currently a stub to be implemented later. Return @code{#t} if @var{obj} is a 3D model. @end deffn -@deffn {Procedure} draw-model model model-matrix view-matrix +@deffn {Procedure} draw-model model [#:model-matrix] [#:view-matrix] @ + [#:camera-position (vec3 0 0 0)] [#:skybox] [#:lights '()] + Render @var{model} with the transformation matrices @var{model-matrix} -and @var{view-matrix} applied. +and @var{view-matrix} applied. @var{camera-position} is the world +position of the camera, for correct specular lighting calculations. +@var{skybox} is used to apply ambient lighting to the model. +@var{lights} contains all of the dynamic lights (@pxref{Lights}) that +should have an effect on the model. +@end deffn + +Models are composed of simpler data types: meshes, primitives, and +materials. Let's start with materials. A material controls the +appearance of a 3D object. Is the object a rough stone? Or maybe a +smooth metal? Materials control all of this and more. + +There are two types of materials in Chickadee: Phong and PBR. + +@node Lights +@subsection Lights + +The @code{(chickadee graphics light)} module provides a data type for +dynamic lights that can be used to light 3D objects (such as +@ref{Models} or @ref{Meshes}.) + +There are 3 types of dynamic lights: + +@itemize +@item point light: +Emits light in all directions from a specific point in space, like a +light bulb. +@item directional light: +Emits light of a constant intensity in a direction, like sunlight. +@item spot light: +Emits a cone of light in a direction, like a flashlight. +@end itemize + +@deffn {Procedure} make-point-light [#:position (vec3 0 0 0)] [#:color black] +Return a new point light located at @var{position} that emits +@var{color} light. +@end deffn + +@deffn {Procedure} make-directional-light [#:direction (vec3 0 -1 0)] @ + [#:color black] + +Return a new directional light that emits @var{color} light in +@var{direction}. +@end deffn + +@deffn {Procedure} make-spot-light [#:position (vec3 0 0 0)] @ + [#:direction (vec3 0 -1 0)] [#:color black] [#:cut-off @math{π/4}] + +Return a new spot light located at @var{position} that emits +@var{color} light in @var{direction} in a cone that cuts off at +@var{cut-off} radians. +@end deffn + +@deffn {Procedure} point-light? obj +Return @code{#t} if @var{obj} is a point light. +@end deffn + +@deffn {Procedure} directional-light? obj +Return @code{#t} if @var{obj} is a directional light. +@end deffn + +@deffn {Procedure} spot-light? obj +Return @code{#t} if @var{obj} is a spot light. +@end deffn + +@deffn {Procedure} light-type light +Return the type of @var{light}, one of: + +@itemize +@item point +@item directional +@item spot +@end itemize + +@end deffn + +@deffn {Procedure} light-color light +Return the color of @var{light}. +@end deffn + +@deffn {Procedure} light-position light +Return the position of @var{light}. The value is irrelevant for +directional lights. +@end deffn + +@deffn {Procedure} light-direction light +Return the direction of @var{light}. The value is irrelevant for +point lights. +@end deffn + +@deffn {Procedure} light-cut-off light +Return the cut off angle of @var{light}. The value is only relevant +for spot lights. +@end deffn + +@deffn {Procedure} set-light-color! light color +Set the color of @var{light} to @var{color}. +@end deffn + +@deffn {Procedure} set-light-position! light position +Set the position of @var{light} to @var{position}. +@end deffn + +@deffn {Procedure} set-light-direction! light direction +Set the direction of @var{light} to @var{direction}. +@end deffn + +@deffn {Procedure} set-light-cut-off! light cut-off +Set the cut off angle of @var{light} to @var{cut-off}. +@end deffn + +@node Meshes +@subsection Meshes + +The @code{(chickadee graphics mesh)} modules provides procedures for +programmatically creating 3D objects (to load 3D models from a file on +disk, @pxref{Meshes}.) + +@subsubsection Materials + +Before we talk about meshes themselves, let's discuss ``materials.'' +Materials control the appearance of 3D objects. Whether an object +appears like a rough rock, a smooth and shiny metal, etc. depends on +the material that is applied to it. Different types of materials use +different lighting models. Chickadee supports two lighting models: +The classic Blinn-Phong model and a more modern physically based +rendering (PBR) model. + +All materials share some common data: + +@deffn {Procedure} material? obj +Return @code{#t} if @var{obj} is a material. +@end deffn + +@deffn {Procedure} material-name material +Return the name of @var{material}. +@end deffn + +@deffn {Procedure} material-shader material +Return the shader of @var{material}. +@end deffn + +@deffn {Procedure} material-blend-mode material +Return the blend mode of @var{material}. +@end deffn + +@deffn {Procedure} material-polygon-mode material +Return the polygon mode of @var{material}. +@end deffn + +@deffn {Procedure} material-cull-face-mode material +Return the cull face mode of @var{material}. +@end deffn + +@deffn {Procedure} material-depth-test material +Return the depth test of @var{material}. +@end deffn + +@deffn {Procedure} material-stencil-test material +Return the stencil test of @var{material}. +@end deffn + +@deffn {Procedure} material-multisample? material +Return @code{#t} if @var{material} uses multisampling. +@end deffn + +Materials support 5 textures. What each texture is used for depends +on the lighting model. + +@deffn {Procedure} material-texture-0 material +Return the first texture of @var{material}. +@end deffn + +@deffn {Procedure} material-texture-1 material +Return the second texture of @var{material}. +@end deffn + +@deffn {Procedure} material-texture-2 material +Return the third texture of @var{material}. +@end deffn + +@deffn {Procedure} material-texture-3 material +Return the fourth texture of @var{material}. +@end deffn + +@deffn {Procedure} material-texture-4 material +Return the fifth texture of @var{material}. +@end deffn + +For all data that is specific to the lighting model, materials have a +``properties'' field. + +@deffn {Procedure} material-properties material +Return the lighting model specific properties of @var{material}. +@end deffn + +@subsubsection Blinn-Phong Materials + +The @code{(chickadee graphics phong)} module has the Blinn-Phong +lighting model: + +@deffn {Procedure} make-phong-material [#:name "anonymous"] [#:blend-mode] @ + [#:polygon-mode] [#:cull-face-mode] [#:depth-test] [#:stencil-test] @ + [#:multisample? #f] [#:ambient-factor (vec3 1 1 1)] @ + [#:diffuse-factor (vec3 1 1 1)] [#:specular-factor (vec3 1 1 1)] @ + [#:shininess 32] [#:ambient-texture] [#:diffuse-texture] @ + [#:specular-texture] [#:normal-texture] + +Return a new Blinn-Phong material. +@end deffn + +@deffn {Procedure} make-phong-properties [#:ambient] [#:diffuse] [#:specular] @ + [#:shininess] + +Return a new Blinn-Phong properties object. +@end deffn + +@deffn {Procedure} phong-properties? obj +Return @code{#t} if @var{obj} is a Blinn-Phong properties object. +@end deffn + +@deffn {Procedure} phong-properties-ambient properties +Return the ambient factor of @var{properties}. +@end deffn + +@deffn {Procedure} phong-properties-diffuse properties +Return the diffuse factor of @var{properties}. +@end deffn + +@deffn {Procedure} phong-properties-specular properties +Return the specular factor of @var{properties}. +@end deffn + +@deffn {Procedure} phong-properties-shininess properties +Return the shininess factor of @var{properties}. +@end deffn + +@subsubsection PBR Materials + +The @code{(chickadee graphics pbr)} module has the PBR lighting model: + +@deffn {Procedure} make-pbr-material [#:name "anonymous"] [#:blend-mode] @ + [#:polygon-mode] [#:cull-face-mode] [#:depth-test] [#:stencil-test] @ + [#:multisample? #f] [#:base-color-factor (vec3 1 1 1)] @ + [#:base-color-texcoord 0] [#:metallic-factor 1.0] @ + [#:roughness-factor 1.0] [#:metallic-roughness-texcoord 0] @ + [#:normal-texcoord 0] [#:occlusion-texcoord 0] @ + [#:emissive-factor (vec3 1 1 1)] [#:emissive-texcoord 0] @ + [#:alpha-mode opaque] [#:alpha-cutoff 0.5] @ + [#:base-color-texture] [#:metallic-roughness-texture] @ + [#:normal-texture] [#:occlusion-texture] [#:emissive-texture] + +Return a new PBR material. +@end deffn + +@deffn {Procedure} make-pbr-properties [#:base-color-factor] @ + [#:base-color-texcoord] [#:metallic-factor] [#:roughness-factor] @ + [#:metallic-roughness-texcoord] [#:normal-texcoord] @ + [#:occlusion-texcoord] [#:emissive-factor] [#:emissive-texcoord] @ + [#:alpha-mode] [#:alpha-cutoff] + +Return a new PBR properties object. +@end deffn + +@deffn {Procedure} pbr-properties? obj +Return @code{#t} if @var{obj} is a PBR properties object. +@end deffn + +@deffn {Procedure} pbr-properties-base-color-factor properties +Return the base color factor of @var{properties}. +@end deffn + +@deffn {Procedure} pbr-properties-base-color-texcoord properties +Return the base color texture coordinate attribute index of +@var{properties}. +@end deffn + +@deffn {Procedure} pbr-properties-metallic-factor properties +Return the metallic factor of @var{properties}. +@end deffn + +@deffn {Procedure} pbr-properties-roughness properties +Return the roughness factor of @var{properties}. +@end deffn + +@deffn {Procedure} pbr-properties-metallic-roughness-texcoord properties +Return the metallic-roughness texture coordinate attribute index of +@var{properties}. +@end deffn + +@deffn {Procedure} pbr-properties-normal-texcoord properties +Return the normal texture coordinate attribute index of +@var{properties}. +@end deffn + +@deffn {Procedure} pbr-properties-occlusion-texcoord properties +Return the ambient occlusion texture coordinate attribute index of +@var{properties}. +@end deffn + +@deffn {Procedure} pbr-properties-emissive-factor properties +Return the emissive factor of @var{properties}. +@end deffn + +@deffn {Procedure} pbr-properties-emissive-texcoord properties +Return the emissive texture coordinate attribute index of +@var{properties}. +@end deffn + +@deffn {Procedure} pbr-properties-alpha-mode properties +Return the alpha mode of @var{properties}. +@end deffn + +@deffn {Procedure} pbr-properties-alpha-cutoff properties +Return the alpha cutoff threshold of @var{properties}. +@end deffn + +@subsubsection Primitives and Meshes + +A mesh is a collection of ``primitives,'' so we should discuss those +next. A primitive contains vertex data and a material. + +@deffn {Procedure} make-primitive name vertex-array material +Return a new primitive named @var{name} that renders +@var{vertex-array} (@pxref{Buffers}) using @var{material}. +@end deffn + +@deffn {Procedure} primitive? obj +Return @code{#t} if @var{obj} is a primitive. +@end deffn + +@deffn {Procedure} primitive-name primitive +Return the name of @var{primitive}. +@end deffn + +@deffn {Procedure} primitive-vertex-array primitive +Return the vertex array of @var{primitive}. +@end deffn + +@deffn {Procedure} primitive-material primitive +Return the material of @var{primitive}. +@end deffn + +Okay, now we can talk about meshes, which are just a glorified list of +primitive objects. + +@deffn {Procedure} make-mesh name primitives +Return a new mesh named @var{name} that is composed of the list +@var{primitives}. +@end deffn + +@deffn {Procedure} mesh? obj +Return @code{#t} if @var{obj} is a mesh. +@end deffn + +@deffn {Procedure} mesh-name mesh +Return the name of @var{mesh}. +@end deffn + +@deffn {Procedure} mesh-primitives mesh +Return the list of primitives for @var{mesh}. +@end deffn + +The mesh module also conveniently provides procedures to build several +basic 3D shapes. + +@deffn {Procedure} make-plane length width material +Return a new mesh that forms a flat plane on the XZ axis that is +@var{width} units long along the X axis and @var{length} units long +along the Z axis. +@end deffn + +@deffn {Procedure} make-tesselated-plane length width resolution material +Return a new mesh that forms a tesselated plane on the XZ axis that is +@var{width} units long along the X axis and @var{length} units long +along the Z axis. + +A regular plane is a single rectangle, but a tesselated plane is +subdivided into many smaller rectangles by @var{resolution}. This +allows for transforming the vertices in a shader to achieve effects +such as waves in water or mountainous terrain. +@end deffn + +@deffn {Procedure} make-cube size material +Return a new mesh that forms a cube that is @var{size} units big. +@end deffn + +@deffn {Procedure} make-sphere radius material [#:quality 2] +Return a new mesh that forms a sphere that has a radius of +@var{radius} units. Since 3D models are composed of triangles, the +quality of a sphere is entirely dependent upon how many triangles are +used to appromixate the shape. The higher the value of @var{quality}, +the better the appromixation, but the more time it will take to +generate and the more expensive it will be to draw. The number of +triangles in the resulting sphere increases exponentially with each +increment to @var{quality}. @end deffn @node Blending -- cgit v1.2.3