diff options
Diffstat (limited to 'manuals/chickadee/Buffers.html')
-rw-r--r-- | manuals/chickadee/Buffers.html | 473 |
1 files changed, 473 insertions, 0 deletions
diff --git a/manuals/chickadee/Buffers.html b/manuals/chickadee/Buffers.html new file mode 100644 index 0000000..00e3cfe --- /dev/null +++ b/manuals/chickadee/Buffers.html @@ -0,0 +1,473 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<!-- Copyright (C) 2017, 2018, 2019 David Thompson davet@gnu.org + +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.3 +or any later version published by the Free Software Foundation; +with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. +A copy of the license is included in the section entitled "GNU +Free Documentation License". + +A copy of the license is also available from the Free Software +Foundation Web site at http://www.gnu.org/licenses/fdl.html. + + +* Chickadee: (chickadee). Game programming toolkit for Guile. + +The document was typeset with +http://www.texinfo.org/ (GNU Texinfo). + --> +<!-- Created by GNU Texinfo 6.5, http://www.gnu.org/software/texinfo/ --> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> +<title>Buffers (The Chickadee Game Toolkit)</title> + +<meta name="description" content="Buffers (The Chickadee Game Toolkit)"> +<meta name="keywords" content="Buffers (The Chickadee Game Toolkit)"> +<meta name="resource-type" content="document"> +<meta name="distribution" content="global"> +<meta name="Generator" content="makeinfo"> +<link href="index.html#Top" rel="start" title="Top"> +<link href="Index.html#Index" rel="index" title="Index"> +<link href="index.html#SEC_Contents" rel="contents" title="Table of Contents"> +<link href="Graphics.html#Graphics" rel="up" title="Graphics"> +<link href="Shaders.html#Shaders" rel="next" title="Shaders"> +<link href="Rendering-Engine.html#Rendering-Engine" rel="prev" title="Rendering Engine"> +<style type="text/css"> +<!-- +a.summary-letter {text-decoration: none} +blockquote.indentedblock {margin-right: 0em} +blockquote.smallindentedblock {margin-right: 0em; font-size: smaller} +blockquote.smallquotation {font-size: smaller} +div.display {margin-left: 3.2em} +div.example {margin-left: 3.2em} +div.lisp {margin-left: 3.2em} +div.smalldisplay {margin-left: 3.2em} +div.smallexample {margin-left: 3.2em} +div.smalllisp {margin-left: 3.2em} +kbd {font-style: oblique} +pre.display {font-family: inherit} +pre.format {font-family: inherit} +pre.menu-comment {font-family: serif} +pre.menu-preformatted {font-family: serif} +pre.smalldisplay {font-family: inherit; font-size: smaller} +pre.smallexample {font-size: smaller} +pre.smallformat {font-family: inherit; font-size: smaller} +pre.smalllisp {font-size: smaller} +span.nolinebreak {white-space: nowrap} +span.roman {font-family: initial; font-weight: normal} +span.sansserif {font-family: sans-serif; font-weight: normal} +ul.no-bullet {list-style: none} +@media (min-width: 1140px) { + body { + margin-left: 14rem; + margin-right: 4rem; + max-width: 52rem; + } +} + +@media (min-width: 800px) and (max-width: 1140px) { + body { + margin-left: 6rem; + margin-right: 4rem; + max-width: 52rem; + } +} + +@media (max-width: 800px) { + body { + margin: 1rem; + } +} + +--> +</style> +<link rel="stylesheet" type="text/css" href="https://dthompson.us/css/dthompson.css"> + + +</head> + +<body lang="en"> +<a name="Buffers"></a> +<div class="header"> +<p> +Next: <a href="Shaders.html#Shaders" accesskey="n" rel="next">Shaders</a>, Previous: <a href="Rendering-Engine.html#Rendering-Engine" accesskey="p" rel="prev">Rendering Engine</a>, Up: <a href="Graphics.html#Graphics" accesskey="u" rel="up">Graphics</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Index.html#Index" title="Index" rel="index">Index</a>]</p> +</div> +<hr> +<a name="Buffers-1"></a> +<h4 class="subsection">2.3.11 Buffers</h4> + +<p>Alright, let’s brush aside all of those pretty high level abstractions +and discuss what is going on under the hood. The GPU exists as a +discrete piece of hardware separate from the CPU. In order to make it +draw things, we must ship lots of data out of our memory space and +into the GPU. The <code>(chickadee render buffer</code>) module provides an +API for manipulating GPU buffers. +</p> +<p>In OpenGL terminology, a chunk of data allocated on the GPU is a +“vertex buffer object” or VBO. For example, here is a bytevector +that could be transformed into a GPU buffer that packs together vertex +position and texture coordinates: +</p> +<div class="example"> +<pre class="example">(use-modules (chickadee render buffer) (srfi srfi-4)) +(define data + (f32vector -8.0 -8.0 ; 2D vertex + 0.0 0.0 ; 2D texture coordinate + 8.0 -8.0 ; 2D vertex + 1.0 0.0 ; 2D texture coordinate + 8.0 8.0 ; 2D vertex + 1.0 1.0 ; 2D texture coordinate + -8.0 8.0 ; 2D vertex + 0.0 1.0)) ; 2D texture coordinate +</pre></div> + +<p>This data represents a textured 16x16 square centered on the +origin. To send this data to the GPU, the <code>make-buffer</code> procedure +is needed: +</p> +<div class="example"> +<pre class="example">(define buffer (make-buffer data #:stride 16)) +</pre></div> + +<p>The <code>#:stride</code> keyword argument indicates how many bytes make up +each element of the buffer. In this case, there are 4 floats per +element: 2 for the vertex, and 2 for the texture coordinate. A 32-bit +float is 4 bytes in length, so the buffer’s stride is 16. +</p> +<p>Within a VBO, one or more “attributes”, as OpenGL calls them, may be +present. Attributes are subregions within the buffer that have a +particular data type. In this case, there are two attributes packed +into the buffer. To provided a typed view into a buffer, the +<code>make-buffer-view</code> procedure is needed: +</p> +<div class="example"> +<pre class="example">(define vertices + (make-buffer-view #:buffer buffer + #:type 'vec2 + #:component-type 'float + #:length 4)) +(define texcoords + (make-buffer-view #:buffer buffer + #:type 'vec2 + #:component-type 'float + #:length 4 + #:offset 8)) +</pre></div> + +<p>To render a square, the GPU needs to draw two triangles, which means +we need 6 vertices in total. However, the above buffer only contains +data for 4 vertices. This is becase there are only 4 unique vertices +for a square, but 2 of them must be repeated for each triangle. To +work with deduplicated vertex data, an “index buffer” must be +created. +</p> +<div class="example"> +<pre class="example">(define index-buffer + (make-buffer (u32vector 0 3 2 0 2 1) + #:target 'index) +(define indices + (make-buffer-view #:type 'scalar + #:component-type 'unsigned-int + #:buffer index-buffer)) +</pre></div> + +<p>Note the use of the <code>#:target</code> keyword argument. It is required +because the GPU treats index data in a special way and must be told +which data is index data. +</p> +<p>Now that the buffer views representing each attribute have been +created, all that’s left is to bind them all together in a “vertex +array object”, or VAO. Vertex arrays associate each buffer view +with an attribute index on the GPU. The indices that are chosen must +correspond with the indices that the shader (see <a href="Shaders.html#Shaders">Shaders</a>) expects +for each attribute. +</p> +<div class="example"> +<pre class="example">(define vertex-array + (make-vertex-array #:indices indices + #:attributes `((0 . ,vertices) + (1 . ,texcoords)))) +</pre></div> + +<p>With the vertex array created, the GPU is now fully aware of how to +interpret the data that it has been given in the original buffer. +Actually rendering this square is left as an exercise to the reader. +See the <a href="Shaders.html#Shaders">Shaders</a> section and the <code>gpu-apply</code> procedure in +<a href="Rendering-Engine.html#Rendering-Engine">Rendering Engine</a> for the remaining pieces of a successful draw +call. Additionally, consider reading the source code for sprites, +shapes, or particles to see GPU buffers in action. +</p> +<p>Without further ado, the API reference: +</p> +<dl> +<dt><a name="index-make_002dbuffer"></a>Procedure: <strong>make-buffer</strong> <em>data [#:name "anonymous"] [#:length] [#:offset 0] [#:stride 0] [#:target <code>vertex</code>] [#:usage <code>static</code>]</em></dt> +<dd> +<p>Upload <var>data</var>, a bytevector, to the GPU. By default, the entire +bytevector is uploaded. A subset of the data may be uploaded by +specifying the <var>offset</var>, the index of the first byte to be +uploaded, and <var>length</var>, the number of bytes to upload. +</p> +<p>If <var>data</var> is <code>#f</code>, allocate <var>length</var> bytes of fresh GPU +memory instead. +</p> +<p><var>target</var> and <var>usage</var> are hints that tell the GPU how the +buffer is intended to be used. +</p> +<p><var>target</var> may be: +</p> +<ul> +<li> <code>vertex</code> +Vertex attribute data. + +</li><li> <code>index</code> +Index buffer data. + +</li></ul> + +<p><var>usage</var> may be: +</p> +<ul> +<li> <code>static</code> +The buffer data will not be modified after creation. + +</li><li> <code>stream</code> +The buffer data will be modified frequently. + +</li></ul> + +<p><var>name</var> is simply an arbitrary string for debugging purposes that +is never sent to the GPU. +</p></dd></dl> + +<dl> +<dt><a name="index-buffer_003f"></a>Procedure: <strong>buffer?</strong> <em>obj</em></dt> +<dd><p>Return <code>#t</code> if <var>obj</var> is a GPU buffer. +</p></dd></dl> + +<dl> +<dt><a name="index-index_002dbuffer_003f"></a>Procedure: <strong>index-buffer?</strong> <em>buffer</em></dt> +<dd><p>Return <code>#t</code> if <var>buffer</var> is an index buffer. +</p></dd></dl> + +<dl> +<dt><a name="index-null_002dbuffer"></a>Variable: <strong>null-buffer</strong></dt> +<dd><p>Represents the absence of a buffer. +</p></dd></dl> + +<dl> +<dt><a name="index-buffer_002dname"></a>Procedure: <strong>buffer-name</strong> <em>buffer</em></dt> +<dd><p>Return the name of <var>buffer</var>. +</p></dd></dl> + +<dl> +<dt><a name="index-buffer_002dlength"></a>Procedure: <strong>buffer-length</strong> <em>buffer</em></dt> +<dd><p>Return the length of <var>buffer</var>. +</p></dd></dl> + +<dl> +<dt><a name="index-buffer_002dstride"></a>Procedure: <strong>buffer-stride</strong> <em>buffer</em></dt> +<dd><p>Return the amount of space, in bytes, between each element in +<var>buffer</var>. +</p></dd></dl> + +<dl> +<dt><a name="index-buffer_002dtarget"></a>Procedure: <strong>buffer-target</strong> <em>buffer</em></dt> +<dd><p>Return the the intended usage of <var>buffer</var>, either <code>vertex</code> or +<code>index</code>. +</p></dd></dl> + +<dl> +<dt><a name="index-buffer_002dusage"></a>Procedure: <strong>buffer-usage</strong> <em>buffer</em></dt> +<dd><p>Return the intended usage of <var>buffer</var>, either <code>static</code> for +buffer data that will not change once sent to the GPU, or +<code>stream</code> for buffer data that will be frequently updated from the +client-side. +</p></dd></dl> + +<dl> +<dt><a name="index-buffer_002ddata"></a>Procedure: <strong>buffer-data</strong> <em>buffer</em></dt> +<dd><p>Return a bytevector containing all the data within <var>buffer</var>. If +<var>buffer</var> has not been mapped (see <code>with-mapped-buffer</code>) then +this procedure will return <code>#f</code>. +</p></dd></dl> + +<dl> +<dt><a name="index-with_002dmapped_002dbuffer"></a>Syntax: <strong>with-mapped-buffer</strong> <em>buffer body …</em></dt> +<dd><p>Evaluate <var>body</var> in the context of <var>buffer</var> having its data +synced from GPU memory to RAM. In this context, <code>buffer-data</code> +will return a bytevector of all the data stored in <var>buffer</var>. When +program execution exits this form, the data (including any +modifications) is synced back to the GPU. +</p> +<p>This form is useful for streaming buffers that need to update their +contents dynamically, such as a sprite batch. +</p></dd></dl> + +<dl> +<dt><a name="index-make_002dbuffer_002dview"></a>Procedure: <strong>make-buffer-view</strong> <em>#:buffer #:type #:component-type #:length [#:offset <code>0</code>] [#:divisor <code>1</code>] [#:name <code>"anonymous"</code>]</em></dt> +<dd> +<p>Return a new buffer view for <var>buffer</var> starting at byte index +<var>offset</var> of <var>length</var> elements, where each element is of +<var>type</var> and composed of <var>component-type</var> values. +</p> +<p>Valid values for <var>type</var> are: +</p> +<ul> +<li> <code>scalar</code> +single number + +</li><li> <code>vec2</code> +2D vector + +</li><li> <code>vec3</code> +3D vector + +</li><li> <code>vec4</code> +4D vector + +</li><li> <code>mat2</code> +2x2 matrix + +</li><li> <code>mat3</code> +3x3 matrix + +</li><li> <code>mat4</code> +4x4 matrix +</li></ul> + +<p>Valid values for <var>component-type</var> are: +</p> +<ul> +<li> <code>byte</code> +</li><li> <code>unsigned-byte</code> +</li><li> <code>short</code> +</li><li> <code>unsigned-short</code> +</li><li> <code>int</code> +</li><li> <code>unsigned-int</code> +</li><li> <code>float</code> +</li><li> <code>double</code> + +</li></ul> + +<p><var>divisor</var> is only needed for instanced rendering applications (see +<code>gpu-apply/instanced</code> in <a href="Rendering-Engine.html#Rendering-Engine">Rendering Engine</a>) and represents +how many instances each vertex element applies to. A divisor of 0 +means that a single element is used for every instance and is used for +the data being instanced. A divisor of 1 means that each element is +used for 1 instance. A divisor of 2 means that each element is used +for 2 instances, and so on. +</p></dd></dl> + +<dl> +<dt><a name="index-buffer_002dview_003f"></a>Procedure: <strong>buffer-view?</strong> <em>obj</em></dt> +<dd><p>Return <code>#t</code> if <var>obj</var> is a buffer view. +</p></dd></dl> + +<dl> +<dt><a name="index-buffer_002dview_002d_003ebuffer"></a>Procedure: <strong>buffer-view->buffer</strong> <em>buffer-view</em></dt> +<dd><p>Return the buffer that <var>buffer-view</var> is using. +</p></dd></dl> + +<dl> +<dt><a name="index-buffer_002dview_002dname"></a>Procedure: <strong>buffer-view-name</strong> <em>buffer-view</em></dt> +<dd><p>Return the name of <var>buffer-view</var>. +</p></dd></dl> + +<dl> +<dt><a name="index-buffer_002dview_002doffset"></a>Procedure: <strong>buffer-view-offset</strong> <em>buffer-view</em></dt> +<dd><p>Return the byte offset of <var>buffer-view</var>. +</p></dd></dl> + +<dl> +<dt><a name="index-buffer_002dview_002dtype"></a>Procedure: <strong>buffer-view-type</strong> <em>buffer-view</em></dt> +<dd><p>Return the data type of <var>buffer-view</var>. +</p></dd></dl> + +<dl> +<dt><a name="index-buffer_002dview_002dcomponent_002dtype"></a>Procedure: <strong>buffer-view-component-type</strong> <em>buffer-view</em></dt> +<dd><p>Return the component data type of <var>buffer-view</var> +</p></dd></dl> + +<dl> +<dt><a name="index-buffer_002dview_002ddivisor"></a>Procedure: <strong>buffer-view-divisor</strong> <em>buffer-view</em></dt> +<dd><p>Return the instance divisor for <var>buffer-view</var>. +</p></dd></dl> + +<dl> +<dt><a name="index-with_002dmapped_002dbuffer_002dview"></a>Syntax: <strong>with-mapped-buffer-view</strong> <em>buffer-view body …</em></dt> +<dd> +<p>Evaluate <var>body</var> in the context of <var>buffer-view</var> having its +data synced from GPU memory to RAM. See <code>with-mapped-buffer</code> for +more information. +</p></dd></dl> + +<dl> +<dt><a name="index-make_002dvertex_002darray"></a>Procedure: <strong>make-vertex-array</strong> <em>#:indices #:attributes [#:mode <code>triangles</code>]</em></dt> +<dd> +<p>Return a new vertex array using the index data within the buffer view +<var>indices</var> and the vertex attribute data within <var>attributes</var>. +</p> +<p><var>attributes</var> is an alist mapping shader attribute indices to typed +buffers containing vertex data: +</p> +<div class="example"> +<pre class="example">`((1 . ,buffer-view-a) + (2 . ,buffer-view-b) + …) +</pre></div> + +<p>By default, the vertex array is interpreted as containing a series of +triangles. If another primtive type is desired, the <var>mode</var> +keyword argument may be overridden. The following values are +supported: +</p> +<ul> +<li> <code>points</code> +</li><li> <code>lines</code> +</li><li> <code>line-loop</code> +</li><li> <code>line-strip</code> +</li><li> <code>triangles</code> +</li><li> <code>triangle-strip</code> +</li><li> <code>triangle-fan</code> +</li></ul> + +</dd></dl> + +<dl> +<dt><a name="index-null_002dvertex_002darray"></a>Variable: <strong>null-vertex-array</strong></dt> +<dd><p>Represents the absence of a vertex array. +</p></dd></dl> + +<dl> +<dt><a name="index-vertex_002darray_003f"></a>Procedure: <strong>vertex-array?</strong> <em>obj</em></dt> +<dd><p>Return <code>#t</code> if <var>obj</var> is a vertex array. +</p></dd></dl> + +<dl> +<dt><a name="index-vertex_002darray_002dindices"></a>Procedure: <strong>vertex-array-indices</strong> <em>vertex-array</em></dt> +<dd><p>Return the buffer view containing index data for <var>vertex-array</var>. +</p></dd></dl> + +<dl> +<dt><a name="index-vertex_002darray_002dattributes"></a>Procedure: <strong>vertex-array-attributes</strong> <em>vertex-array</em></dt> +<dd><p>Return the attribute index -> buffer view mapping of vertex attribute +data for <var>vertex-array</var>. +</p></dd></dl> + +<dl> +<dt><a name="index-vertex_002darray_002dmode"></a>Procedure: <strong>vertex-array-mode</strong> <em>vertex-array</em></dt> +<dd><p>Return the primitive rendering mode for <var>vertex-array</var>. +</p></dd></dl> + +<hr> +<div class="header"> +<p> +Next: <a href="Shaders.html#Shaders" accesskey="n" rel="next">Shaders</a>, Previous: <a href="Rendering-Engine.html#Rendering-Engine" accesskey="p" rel="prev">Rendering Engine</a>, Up: <a href="Graphics.html#Graphics" accesskey="u" rel="up">Graphics</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Index.html#Index" title="Index" rel="index">Index</a>]</p> +</div> + + + +</body> +</html> |