Browse Source

Merge and edit intro to shader pages

Closes #4156
Nathan Lovato 4 years ago
parent
commit
2f93575f95

+ 1 - 1
about/docs_changelog.rst

@@ -174,7 +174,7 @@ Shading
 
 
 Shading Reference:
 Shading Reference:
 
 
-- :ref:`doc_shaders`
+- :ref:`doc_introduction_to_shaders`
 - :ref:`doc_shading_language`
 - :ref:`doc_shading_language`
 - :ref:`doc_spatial_shader`
 - :ref:`doc_spatial_shader`
 - :ref:`doc_canvas_item_shader`
 - :ref:`doc_canvas_item_shader`

+ 130 - 87
tutorials/shaders/introduction_to_shaders.rst

@@ -3,119 +3,162 @@
 Introduction to shaders
 Introduction to shaders
 =======================
 =======================
 
 
-Introduction
-------------
-
-So, you have decided to give shaders a try. You have likely heard that they can be used to
-create interesting effects that run incredibly fast. You have also likely heard that they
-are terrifying. Both are true.
-
-Shaders can be used to create a wide range of effects (in fact everything drawn in a modern
-rendering engine is done with shaders).
-
-Writing shaders can also be very difficult for people unfamiliar with them. Godot tries to make writing
-shaders a little easier by exposing many useful built-in features and handling some of the
-lower-level initialization work for you. However, GLSL (the OpenGL Shading Language, which Godot uses)
-is still unintuitive and restricting, especially for users who are used to GDScript.
+This page explains what shaders are and will give you an overview of how they
+work in Godot. For a detailed reference of the engine's shading language, see
+:ref:`doc_shading_language`.
 
 
-But what are they?
-------------------
+Shaders are a special kind of program that runs on Graphics Processing Units
+(GPUs). They were initially used to shade 3D scenes but can nowadays do much
+more. You can use them to control how the engine draws geometry and pixels on
+the screen, allowing you to achieve all sorts of effects.
 
 
-Shaders are a special kind of program that runs on Graphics Processing Units (GPUs). Most computers
-have some sort of GPU, either one integrated into their CPU or discrete (meaning it is a separate
-hardware component, for example, the typical graphics card). GPUs are especially useful for
-rendering because they are optimized for running thousands of instructions in parallel.
+Modern rendering engines like Godot draw everything with shaders: graphics cards
+can run thousands of instructions in parallel, leading to incredible rendering
+speed.
 
 
-The output of the shader is typically the colored pixels of the object drawn to the viewport. But some
-shaders allow for specialized outputs (this is especially true for APIs like Vulkan). Shaders operate
-inside the shader pipeline. The standard process is the vertex -> fragment shader pipeline. The vertex
-shader is used to decided where each vertex (point in a 3D model, or corner of a Sprite) goes and the
-fragment shader decides what color individual pixels receive.
+Because of their parallel nature, though, shaders don't process information the
+way a typical program does. Shader code runs on each vertex or pixel in
+isolation. You cannot store data between frames either. As a result, when
+working with shaders, you need to code and think differently from other
+programming languages.
 
 
-Suppose you want to update all the pixels in a texture to a given color, on the CPU you would write:
-
-::
+Suppose you want to update all the pixels in a texture to a given color. In
+GDScript, your code would use ``for`` loops::
 
 
   for x in range(width):
   for x in range(width):
     for y in range(height):
     for y in range(height):
       set_color(x, y, some_color)
       set_color(x, y, some_color)
 
 
-In a shader you are given access only to the inside of the loop so what you write looks like this:
+Your code is already part of a loop in a shader, so the corresponding code would
+look like this.
 
 
 .. code-block:: glsl
 .. code-block:: glsl
 
 
-  // function called for each pixel
   void fragment() {
   void fragment() {
     COLOR = some_color;
     COLOR = some_color;
   }
   }
 
 
-You have no control over how this function is called. So you have to design your shaders
-differently from how you would design programs on the CPU.
+.. note::
 
 
-A consequence of the shader pipeline is that you cannot access the results from a previous
-run of the shader, you cannot access other pixels from the pixel being drawn, and you cannot
-write outside of the current pixel being drawn. This enables the GPU to execute the shader
-for different pixels in parallel, as they do not depend on each other. This lack of
-flexibility is designed to work with the GPU which allows shaders to be incredibly fast.
+   The graphics card calls the ``fragment()`` function once or more for each pixel it has to draw. More on that below.
 
 
-What can they do
-^^^^^^^^^^^^^^^^
+Shaders in Godot
+----------------
 
 
-- position vertices very fast
-- compute color very fast
-- compute lighting very fast
-- lots and lots of math
+Godot provides a shading language based on the popular OpenGL Shading Language
+(GLSL) but simplified. The engine handles some of the lower-level initialization
+work for you, making it easier to write complex shaders.
 
 
-What can't they do
-^^^^^^^^^^^^^^^^^^
+In Godot, shaders are made up of three main functions: ``vertex()``,
+``fragment()``, and ``light()``.
+
+1. The ``vertex()`` function runs over all the vertices in the mesh and sets
+   their positions and some other per-vertex variables.
 
 
-- draw outside mesh
-- access other pixels from current pixel (or vertices)
-- store previous iterations
-- update on the fly (they can, but they need to be compiled)
+2. The ``fragment()`` function runs for every pixel covered by the mesh. It uses
+   values output by the ``vertex()`` function, interpolated between the
+   vertices.
 
 
-Structure of a shader
----------------------
+3. The ``light()`` function runs for every pixel and for every light. It takes
+   variables from the ``fragment()`` function and from its previous runs.
 
 
-In Godot, shaders are made up of 3 main functions: the ``vertex()`` function, the ``fragment()``
-function and the ``light()`` function.
+.. warning::
 
 
-The ``vertex()`` function runs over all the vertices in the mesh and sets their positions as well
-as some other per-vertex variables.
+    The ``light()`` function won't run if the ``vertex_lighting`` render mode is
+    enabled, or if **Rendering > Quality > Shading > Force Vertex Shading** is
+    enabled in the Project Settings. It's enabled by default on mobile
+    platforms.
 
 
-The ``fragment()`` function runs for every pixel that is covered by the mesh. It uses the variables
-from the ``vertex()`` function to run. The variables from the ``vertex()`` function are interpolated
-between the vertices to provide the values for the ``fragment()`` function.
+Shader types
+------------
 
 
-The ``light()`` function runs for every pixel and for every light. It takes variables from the
-``fragment()`` function and from previous runs of itself.
+Instead of supplying a general-purpose configuration for all uses (2D, 3D,
+particles), you must specify the type of shader you're writing. Different types
+support different render modes, built-in variables, and processing functions.
 
 
-For more information about how shaders operate specifically in Godot, see the :ref:`Shaders <doc_shaders>` doc.
+In Godot, all shaders need to specify their type in the first line, like so:
 
 
-.. warning::
+.. code-block:: glsl
+
+    shader_type spatial;
+
+Here are the available types:
+
+* :ref:`spatial <doc_spatial_shader>` for 3D rendering.
+* :ref:`canvas_item <doc_canvas_item_shader>` for 2D rendering.
+* :ref:`particles <doc_particle_shader>` for particle systems.
+* :ref:`sky <doc_sky_shader>` to render :ref:`Skies <class_Sky>`.
+
+Render modes
+------------
+
+Shaders have optional render modes you can specify on the second line, after the
+shader type, like so:
+
+.. code-block:: glsl
+
+    shader_type spatial;
+    render_mode unshaded, cull_disabled;
+
+Render modes alter the way Godot applies the shader. For example, the
+``unshaded`` mode makes the engine skip the built-in light processor function.
+
+Each shader type has different render modes. See the reference for each shader
+type for a complete list of render modes.
+
+Processor functions
+-------------------
+
+Depending on the shader type, you can override different processor functions.
+For ``spatial`` and ``canvas_item``, you have access to ``vertex()``,
+``fragment()``, and ``light()``. For ``particles``, you only have access to
+``vertex()``.
+
+Vertex processor
+^^^^^^^^^^^^^^^^
+
+The ``vertex()`` processing function is called once for every vertex in
+``spatial`` and ``canvas_item`` shaders. For ``particles`` shaders, it is called
+once for every particle.
+
+Each vertex in your world's geometry has properties like a position and color.
+The function modifies those values and passes them to the fragment function. You
+can also use it to send extra data to the fragment function using varyings.
+
+By default, Godot transforms your vertex information for you, which is necessary
+to project geometry onto the screen. You can use render modes to transform the
+data yourself; see the :ref:`Spatial shader doc <doc_spatial_shader>` for an
+example.
+
+Fragment processor
+^^^^^^^^^^^^^^^^^^
 
 
-    The ``light()`` function won't be run if the ``vertex_lighting`` render mode
-    is enabled, or if
-    **Rendering > Quality > Shading > Force Vertex Shading** is enabled in the
-    Project Settings. (It's enabled by default on mobile platforms.)
-
-Technical overview
-------------------
-
-GPUs are able to render graphics much faster than CPUs for a few reasons, but most notably,
-because they are able to run calculations massively in parallel. A CPU typically has 4 or 8 cores
-while a GPU typically has thousands. That means a GPU can do hundreds of tasks at once. GPU architects
-have exploited this in a way that allows for doing many calculations very quickly, but only when
-many or all cores are doing the same calculation at once, but with different data.
-
-That is where shaders come in. The GPU will call the shader a bunch of times simultaneously, and then
-operate on different bits of data (vertices, or pixels). These bunches of data are often called wavefronts.
-A shader will run the same for every thread in the wavefront. For example, if a given GPU can handle 100
-threads per wavefront, a wavefront will run on a 10×10 block of pixels together. It will continue to
-run for all pixels in that wavefront until they are complete. Accordingly, if you have one pixel slower
-than the rest (due to excessive branching), the entire block will be slowed down, resulting in massively
-slower render times.
-
-This is different from CPU-based operations. On a CPU, if you can speed up even one
-pixel, the entire rendering time will decrease. On a GPU, you have to speed up the entire wavefront
-to speed up rendering.
+The ``fragment()`` processing function is used to set up the Godot material
+
+parameters per pixel. This code runs on every visible pixel the object or
+primitive draws. It is only available in ``spatial`` and ``canvas_item`` shaders.
+
+The standard use of the fragment function is to set up material properties used
+to calculate lighting. For example, you would set values for ``ROUGHNESS``,
+``RIM``, or ``TRANSMISSION``, which would tell the light function how the lights
+respond to that fragment. This makes it possible to control a complex shading
+pipeline without the user having to write much code. If you don't need this
+built-in functionality, you can ignore it and write your own light processing
+function, and Godot will optimize it away. For example, if you do not write a
+value to ``RIM``, Godot will not calculate rim lighting. During compilation,
+Godot checks to see if ``RIM`` is used; if not, it cuts all the corresponding
+code out. Therefore, you will not waste calculations on the effects that you do
+not use.
+
+Light processor
+^^^^^^^^^^^^^^^
+
+The ``light()`` processor runs per pixel too, and it runs once for every light
+that affects the object. It does not run if no lights affect the object. It
+exists as a function called inside the ``fragment()`` processor and typically
+operates on the material properties setup inside the ``fragment()`` function.
+
+The ``light()`` processor works differently in 2D than it does in 3D; for a
+description of how it works in each, see their documentation, :ref:`CanvasItem
+shaders <doc_canvas_item_shader>` and :ref:`Spatial shaders
+<doc_spatial_shader>`, respectively.

+ 0 - 1
tutorials/shaders/shader_reference/index.rst

@@ -5,7 +5,6 @@ Shading reference
    :maxdepth: 1
    :maxdepth: 1
    :name: toc-shading-reference
    :name: toc-shading-reference
 
 
-   shaders
    shading_language
    shading_language
    spatial_shader
    spatial_shader
    canvas_item_shader
    canvas_item_shader

+ 0 - 112
tutorials/shaders/shader_reference/shaders.rst

@@ -1,112 +0,0 @@
-.. _doc_shaders:
-
-Shaders
-=======
-
-Introduction
-------------
-
-Shaders are unique programs that run on the GPU. They are used to specify how to take mesh
-data (vertex positions, colors, normals, etc.) and draw them to the screen. Shaders do not process
-information the same way a normal program does because they are optimized for running on the GPU.
-One consequence of this is that shaders do not retain their data after they run; they output a final
-color to the screen and then move on. Accordingly, there is no way of accessing the color output from
-the last run of the shader.
-
-Godot uses a shader language very similar to GLSL, but with added functionality and slightly less
-flexibility. The reason for doing this is that Godot integrates built-in functionality to make
-writing complex shaders substantially easier. Godot wraps the user-written shader code in code
-of its own. That way, Godot handles a lot of the low-level stuff that the user doesn't need to
-worry about, and it is able to parse your shader code and use it to affect the rendering pipeline.
-For more advanced shaders, you can turn this functionality off using a render_mode.
-
-This document provides you with some information about shaders, specific to Godot. For a detailed
-reference of the shading language in Godot see the :ref:`Godot shading language doc<doc_shading_language>`.
-
-Shader types
-------------
-
-Instead of supplying a general purpose configuration for all uses (2D, 3D, particles),
-Godot shaders must specify what they are intended for. Different types support different
-render modes, built-in variables, and processing functions.
-
-All shaders need to specify their type in the first line, in the following format:
-
-.. code-block:: glsl
-
-    shader_type spatial;
-
-Valid types are:
-
-* :ref:`spatial <doc_spatial_shader>`: For 3D rendering.
-* :ref:`canvas_item <doc_canvas_item_shader>`: For 2D rendering.
-* :ref:`particles <doc_particle_shader>`: For particle systems.
-
-For detailed information on each shading type, see the corresponding reference document.
-
-Render modes
-------------
-
-Different shader types support different render modes. They are optional and, if specified, must
-be after the *shader_type*. Render modes are used to alter the way built-in functionality is handled.
-For example, it is common to use the render mode ``unshaded`` to skip the built-in light processor
-function.
-
-Render modes are specified underneath the shader type:
-
-.. code-block:: glsl
-
-    shader_type spatial;
-    render_mode unshaded, cull_disabled;
-
-Each shader type has a different list of render modes available. See the document for each shader
-type for a complete list of render modes.
-
-Processor functions
--------------------
-
-Depending on the shader type, different processor functions may be optionally overridden.
-For "spatial" and "canvas_item", it is possible to override ``vertex``, ``fragment``, and ``light``.
-For "particles", only ``vertex`` can be overridden.
-
-Vertex processor
-^^^^^^^^^^^^^^^^
-
-The ``vertex`` processing function is called once for every vertex in "spatial" and "canvas_item" shaders.
-For "particles" shaders, it is called once for every particle.
-
-The ``vertex`` function is used to modify per-vertex information that will be passed on to the fragment
-function. It can also be used to establish variables that will be sent to the fragment function by using
-varyings(see other doc).
-
-By default, Godot will take your vertex information and transform it accordingly to be drawn. If this is
-undesirable, you can use render modes to transform the data yourself; see the
-:ref:`Spatial shader doc <doc_spatial_shader>` for an example of this.
-
-Fragment processor
-^^^^^^^^^^^^^^^^^^
-
-The ``fragment`` processing function is used to set up the Godot material parameters per pixel. This code
-runs on every visible pixel the object or primitive draws. It is only available in "spatial" and
-"canvas_item" shaders.
-
-The standard use of the fragment function is to set up material properties that will be used to calculate
-lighting. For example, you would set values for ``ROUGHNESS``, ``RIM``, or ``TRANSMISSION`` which would
-tell the light function how the lights respond to that fragment. This makes it possible to control a complex
-shading pipeline without the user having to write much code. If you don't need this built-in functionality,
-you can ignore it and write your own light processing function and Godot will optimize it away. For example,
-if you do not write a value to ``RIM``, Godot will not calculate rim lighting. During compilation, Godot checks
-to see if ``RIM`` is used; if not, it cuts all the corresponding code out. Therefore, you will not
-waste calculations on effects that you do not use.
-
-Light processor
-^^^^^^^^^^^^^^^
-
-The ``light`` processor runs per pixel too, but also runs for every light that affects the object
-(and does not run if no lights affect the object). It exists as a function called inside the
-``fragment`` processor and typically operates on the material properties setup inside the ``fragment``
-function.
-
-The ``light`` processor works differently in 2D than it does in 3D; for a description of how it works
-in each, see their documentation, :ref:`CanvasItem shaders <doc_canvas_item_shader>` and
-:ref:`Spatial shaders <doc_spatial_shader>`, respectively.