Py API Docs: Restructure gpu module introduction
authorJacques Lucke <mail@jlucke.com>
Mon, 12 Nov 2018 11:14:07 +0000 (12:14 +0100)
committerJacques Lucke <mail@jlucke.com>
Mon, 12 Nov 2018 11:14:18 +0000 (12:14 +0100)
doc/python_api/examples/gpu.1.py

index 1ffa0a58856e96b387f6816f67609e9dd43ef60d..cd83d31386da79b4cf5badbbab7ebdd2438dca3c 100644 (file)
@@ -2,53 +2,23 @@
 Geometry Batches
 ++++++++++++++++
 
-To draw geometry using the gpu module you need to create a :class:`gpu.types.GPUBatch` object.
-Batches contain a sequence of points, lines or triangles and associated geometry attributes.
-
-A batch can be drawn multiple times, so they should be cached whenever possible.
-This makes them much faster than using the legacy `glBegin` and `glEnd` method, which would recreate the geometry data every time.
-
-Every batch has a so called `Vertex Buffer`.
-It contains the attributes for every vertex.
-Typical attributes are `position`, `color` and `uv`.
-Which attributes the vertex buffer of a batch contains, depends on the shader that will be used to process the batch. The best way to create a new batch is to use the :class:`gpu_extras.batch.batch_for_shader` function.
-
-Furthermore, when creating a new batch, you have to specify the draw type.
-The most used types are ``POINTS``, ``LINES`` and ``TRIS``.
-
-Shaders
-+++++++
-
-A shader is a small program that tells the GPU how to draw batch geometry.
-There are a couple of built-in shaders for the most common tasks.
-Built-in shaders can be accessed with :class:`gpu.shader.from_builtin`.
-Every built-in shader has an identifier (e.g. `2D_UNIFORM_COLOR` and `3D_FLAT_COLOR`).
-
-Custom shaders can be used as well.
-The :class:`gpu.types.GPUShader` takes the shader code as input and compiles it.
-Every shader has at least a vertex and a fragment shader.
-Optionally a geometry shader can be used as well.
-
-.. note::
-   A `GPUShader` is actually a `program` in OpenGL terminology.
-
-Shaders define a set of `uniforms` and `attributes`.
-**Uniforms** are properties that are constant for every vertex in a batch.
-They have to be set before the batch but after the shader has been bound.
-**Attributes** are properties that can be different for every vertex.
-
-The attributes and uniforms used by built-in shaders are listed here: :class:`gpu.shader`
-
-A batch can only be processed/drawn by a shader when it provides all the attributes that the shader specifies.
+Geometry is drawn in batches.
+A batch contains the necessary data to perform the drawing.
+That includes a obligatory *Vertex Buffer* and an optional *Index Buffer*, each of which is described in more detail in the following sections.
+A batch also defines a draw type.
+Typical draw types are `POINTS`, `LINES` and `TRIS`.
+The draw type determines how the data will be interpreted and drawn.
 
 Vertex Buffers
 ++++++++++++++
 
-A vertex buffer is an array that contains the attributes for every vertex.
-To create a new vertex buffer (:class:`gpu.types.GPUVertBuf`) you have to provide two things: 1) the amount of vertices in the buffer and 2) the format of the buffer.
+A *Vertex Buffer Object* (VBO) (:class:`gpu.types.GPUVertBuf`) is an array that contains the vertex attributes needed for drawing using a specific shader.
+Typical vertex attributes are *location*, *normal*, *color*, and *uv*.
+Every vertex buffer has a *Vertex Format* (:class:`gpu.types.GPUVertFormat`) and a length corresponding to the number of vertices in the buffer.
+A vertex format describes which attributes are stored per vertex and their types.
 
-The format (:class:`gpu.types.GPUVertFormat`) describes which attributes are stored in the buffer.
-E.g. to create a vertex buffer that contains 6 vertices, each with a position and a normal could look like so::
+The following code demonstrates the creation of a vertex buffer that contains 6 vertices.
+For each each vertex 2 attributes will be stored: The position and the normal::
 
     import gpu
     vertex_positions = [(0, 0, 0), ...]
@@ -62,46 +32,71 @@ E.g. to create a vertex buffer that contains 6 vertices, each with a position an
     vbo.attr_fill(id="pos", data=vertex_positions)
     vbo.attr_fill(id="normal", data=vertex_normals)
 
-    batch = gpu.types.GPUBatch(type='TRIS', buf=vbo)
-
-This batch contains two triangles now.
-Vertices 0-2 describe the first and vertices 3-5 the second triangle.
-
-.. note::
-    The recommended way to create batches is to use the :class:`gpu_extras.batch.batch_for_shader` function. It makes sure that you provide all the vertex attributes that are necessary to be able to use a specific shader.
+This vertex buffer could be used to draw 6 points, 3 separate lines, 5 consecutive lines, 2 separate triangles, ...
+E.g. in the case of lines, each two consecutive vertices define a line.
+The type that will actually be drawn is determined when the batch is created later.
 
 Index Buffers
 +++++++++++++
 
-The main reason why index buffers exist is to reduce the amount of memory required to store and send geometry.
-E.g. often the same vertex is used by multiple triangles in a mesh.
-Instead of vertex attributes multiple times to the gpu, an index buffer can be used.
-An index buffer is an array of integers that describes in which order the vertex buffer should be read.
-E.g. when you have a vertex buffer ``[a, b, c]`` and an index buffer ``[0, 2, 1, 2, 1, 0]`` it is like if you just had the vertex buffer ``[a, c, b, c, b, a]``.
-Using an index buffer saves memory because usually a single integer is smaller than all attributes for one vertex combined.
+Often triangles and lines share one or more vertices.
+With only a vertex buffer one would have to store all attributes for the these vertices multiple times.
+This is very inefficient because in a connected triangle mesh every vertex is used 6 times on average.
+A more efficient approach would be to use an *Index Buffer* (IBO) (:class:`gpu.types.GPUIndexBuf`), sometimes referred to as *Element Buffer*.
+An *Index Buffer* is an array that references vertices based on their index in the vertex buffer.
+For instance, to draw a rectangle composed of two triangles, one could use an index buffer::
+
+    positions = (
+        (-1,  1), (1,  1),
+        (-1, -1), (1, -1))
+
+    indices = ((0, 1, 2), (2, 1, 3))
+
+    ibo = gpu.types.GPUIndexBuf(type='TRIS', seq=indices)
+
+Here the first tuple in `indices` describes which vertices should be used for the first vertex (same for the second tuple).
+Note how the diagonal vertices 1 and 2 are shared between both triangles.
+
+Shaders
++++++++
+
+A shader is a program that runs on the GPU (written in GLSL in our case).
+There are multiple types of shaders.
+The most important ones are *Vertex Shaders* and *Fragment Shaders*.
+Typically multiple shaders are linked together into a *Program*.
+However, in the Blender Python API the term *Shader* refers to an OpenGL Program.
+Every :class:`gpu.types.GPUShader` consists of a vertex shader, a fragment shader and an optional geometry shader.
+For common drawing tasks there are some built-in shaders accessible from :class:`gpu.shader.from_builtin` with an identifier such as `2D_UNIFORM_COLOR` or `3D_FLAT_COLOR`.
 
-Index buffers can be used like so::
+Every shader defines a set of attributes and uniforms that have to be set in order to use the shader.
+Attributes are properties that are set using a vertex buffer and can be different for individual vertices.
+Uniforms are properties that are constant per draw call.
+They can be set using the `shader.uniform_*` functions after the shader has been bound.
 
-    indices = [(0, 1), (2, 0), (2, 3), ...]
-    ibo = gpu.types.GPUIndexBuf(type='LINES', seq=indices)
-    batch = gpu.types.GPUBatch(type='LINES', buf=vbo, elem=ibo)
+Batch Creation
+++++++++++++++
+
+Batches can be creates by first manually creating VBOs and IBOs.
+However, it is recommended to use the :class:`gpu_extras.batch.batch_for_shader` function.
+It makes sure that all the vertex attributes necessary for a specific shader are provided.
+Consequently, the shader has to be passed to the function as well.
+When using this function one rarely has to care about the vertex format, VBOs and IBOs created in the background.
+This is still something one should know when drawing stuff though.
 
-.. note::
-    Instead of creating index buffers object manually, you can also just use the optional `indices` parameter of the :class:`gpu_extras.batch.batch_for_shader` function.
+Since batches can be drawn multiple times, they should be cached and reused whenever possible.
 
 Offscreen Rendering
 +++++++++++++++++++
 
-Everytime something is drawn, the result is written into a framebuffer.
-Usually this buffer will later be displayed on the screen.
-However, sometimes you might want to draw into a separate "texture" and use it further.
-E.g. you could use the render result as a texture on another object or save the rendered result on disk.
-Offscreen Rendering is done using the :class:`gpu.types.GPUOffScreen` type.
+What one can see on the screen after rendering is called the *Front Buffer*.
+When draw calls are issued, batches are drawn on a *Back Buffer* that will only be displayed when all drawing is done and the current back buffer will become the new front buffer.
+Sometimes, one might want to draw the batches into a distinct buffer that could be used as texture to display on another object or to be saved as image on disk.
+This is called Offscreen Rendering.
+In Blender Offscreen Rendering is done using the :class:`gpu.types.GPUOffScreen` type.
 
 .. warning::
-    ``GPUOffScreen`` objects are bound to the opengl context they have been created in.
-    This also means that once Blender discards this context (i.e. a window is closed) the offscreen instance will also be freed.
-
+    `GPUOffScreen` objects are bound to the OpenGL context they have been created in.
+    This means that once Blender discards this context (i.e. the window is closed), the offscreen instance will be freed.
 
 Examples
 ++++++++