Browse Source

initial commit for your first shader tutorial series

clayjohn 6 years ago
parent
commit
b0be2808d4

+ 1 - 0
tutorials/shading/index.rst

@@ -6,6 +6,7 @@ Shading
    :name: toc-learn-features-shading
    :name: toc-learn-features-shading
 
 
    shading_reference/index
    shading_reference/index
+   your_first_shader/index
    shader_materials
    shader_materials
    intro_to_shaders_water_workshop
    intro_to_shaders_water_workshop
    screen-reading_shaders
    screen-reading_shaders

BIN
tutorials/shading/your_first_shader/img/UV.png


BIN
tutorials/shading/your_first_shader/img/blue-box.png


BIN
tutorials/shading/your_first_shader/img/blue-tex.png


+ 27 - 0
tutorials/shading/your_first_shader/index.rst

@@ -0,0 +1,27 @@
+Your first shader
+=================
+
+This tutorial series will walk you through writing your first shader. It is intended
+for people who have very little prior experience with shaders and want to get started
+with the basics. This tutorial will not cover advanced topics and it is not
+comprehensive. For a comprehensive and detailed overview of shaders in godot see the
+:ref:`Shading Reference Page <toc-shading-reference>`.
+
+"What are shaders" gives a high-level overview of what shaders are and how they fit
+into the rendering pipeline.
+
+The "your first shader" tutorials walks you through the process of writing a shader
+step-by-step. 
+
+For a more general introduction into shaders and the OpenGL Shading Language, use
+`The Book of Shaders <https://thebookofshaders.com>`_.
+
+.. toctree::
+   :maxdepth: 1
+   :name: toc-your-first-shader
+
+   what_are_shaders
+   your_first_canvasitem_shader
+   your_first_spatial_shader
+   your_first_particles_shader
+   your_first_visual_shader

+ 61 - 0
tutorials/shading/your_first_shader/what_are_shaders.rst

@@ -0,0 +1,61 @@
+.. _doc_what_are_shaders:
+
+What are 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.
+
+But what are they
+-----------------
+
+Shaders are a special kind of program that runs on the GPU. 
+
+Objects are drawn using an associated shader. The output of the shader is the pixel colors drawn
+to the viewport. Shaders do not save their results, nor can they be used to draw outside their
+corresponding mesh. The lack of flexibility allows shaders to be incredibly fast. 
+
+What can they do
+----------------
+- position vertices very fast
+- compute color very fast
+- compute lighting very fast
+
+What can't they do
+------------------
+- cant draw outside mesh
+- cant access other pixels from current pixel (or vertices)
+- cant store previous iterations
+- update on the fly (they can, but they need to be compiled)
+ 
+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 hundreds. 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 10x10 block of pixels together. And 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 than 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.
+

+ 212 - 0
tutorials/shading/your_first_shader/your_first_canvasitem_shader.rst

@@ -0,0 +1,212 @@
+.. _doc_your_first_canvasitem_shader:
+
+Your first CanvasItem shader
+============================
+
+Introduction
+------------
+
+Shaders are special programs that execute on the GPU and are used for rendering 
+graphics. All modern rendering is done with shaders. For a more detailed description
+of what shaders are please see :ref:`What are shaders <doc_what_are_shaders>`.
+
+This tutorial will focus on the practical aspects of writing shader programs by walking
+readers through the process of writing a shader with both vertex and fragment functions.
+This tutorial targets absolute beginners to shaders.
+
+.. note:: If you have experience writing shaders and are just looking for 
+          an overview of how shaders work in Godot, see the :ref:`Shading Reference <toc-shading-reference>`.
+
+Setup
+-----
+
+:ref:`CanvasItem <doc_canvas_item_shader>` shaders are used to draw all 2D objects in Godot, 
+while :ref:`Spatial <doc_spatial_shader>` shaders are used to draw all 3D objects.
+
+In order to use a shader it must be attached inside a :ref:`Material <class_material>` 
+which must be attached to an object. To draw multiple objects with the same material, 
+the material must be attached to each object.
+
+All objects derived from a :ref:`CanvasItem <class_canvasitem>` have a material property.
+This includes all gui elements, sprites, TileMaps, MeshInstance2Ds etc.
+They also have an option to inherit their parent's material. This can be useful if you have
+a large number of nodes that you want to use the same material.
+
+To begin, create a Sprite node. You can use any CanvasItem, but for this tutorial we will
+use a Sprite.
+
+In the Inspector, click beside "Texture" where it says "[empty]" and select "Load", then select
+"Icon.png". For new projects, this is the Godot icon. You should now see the icon in the viewport.
+
+Next, look down in the Inspector, under the CanvasItem section, click beside "Material" and select
+"new ShaderMaterial". This creates a new Material. Click on the sphere that appears. Godot currently
+doesn't know whether you are writing a CanvasItem Shader or a Spatial Shader and it previews the output
+of spatial shaders. So what you are seeing is the output of the default Spatial Shader.
+
+Click beside "Shader" and select "new Shader". Finally, click on the new shader resource and the shader
+editor will open. You are now ready to begin writing your first shader.
+
+Your first CanvasItem shader
+----------------------------
+
+In Godot, all shaders start with a line specifying what type of shader they are. It uses
+the following format:
+
+.. code-block:: glsl
+  
+  shader_type canvas_item
+
+Becuase we are writing a CanvasItem shader, we specify ``canvas_item`` in the first line. All our code will
+go beneath this declaration.
+
+This line tells the engine which built-in variables and functionality to supply you with.
+
+In Godot you can override three functions to control how the shader operates; ``vertex``, ``fragment``, and ``light``.
+This tutorial will walk you through writing a shader with both vertex and fragment functions. Light 
+functions are significantly more complex than vertex and fragment functions and so will not be covered here.
+
+Your first fragment function
+----------------------------
+
+The fragment function runs for every pixel covered by a triangle and determine what color that pixel should be
+based on information passed in from the vertex function.
+
+They are restricted to the pixels covered by the triangle, that means you cannot use one to, for example, 
+create an outline around a sprite. 
+
+The most basic fragment function does nothing except assign a single color to every pixel. 
+
+.. code-block:: glsl
+
+  void fragment(){
+    COLOR = vec4(0.4, 0.6, 0.9, 1.0);
+  }
+
+.. image:: img/blue-box.png
+
+Congratulations! You're done. You have successfully written your first shader in Godot.
+
+Now let's make things more complex.
+
+There are many inputs to the fragment function that you can use for calculating ``COLOR``.
+``UV`` is one of them. Uv coordinates are specified in your mesh and they tell the shader
+where to read from textures for each part of the mesh.
+
+In the fragment function you can only read from ``UV``, but you can use it in other functions
+or to assign values to ``COLOR`` directly.
+
+.. code-block:: glsl
+
+  void fragment() {
+    COLOR = vec4(UV, 0.5, 1.0);
+  }
+
+.. image:: img/UV.png
+
+Using ``TEXTURE`` built-in
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+When you want to adjust a color in a sprite you cannot just adjust the color from the texture
+manually like in the code below.
+
+.. code-block:: glsl
+
+  void fragment(){
+    //this shader will result in an all white rectangle
+    COLOR.b = 1.0;
+  }
+
+The default fragment function reads from a texture and displays it. When you overwrite the default fragment function, 
+you lose that functionality, so you have to implement it yourself. You read from textures using the
+``texture`` function. Certain nodes, like Sprites, have a dedicated texture variable that can be accessed in the shader
+using ``TEXTURE``. Use it together with ``UV`` and ``texture`` to draw the sprite.
+
+.. code-block:: glsl
+
+  void fragment(){
+    COLOR = texture(TEXTURE, UV); //read from texture
+    COLOR.b = 1.0; //set blue channel to 1.0
+  }
+
+.. image:: img/blue-tex.png
+
+Uniform input
+^^^^^^^^^^^^^
+
+Uniform input is used to pass data into a shader that will be the same across the entire shader.
+
+You can use uniforms by defining them at the top of your shader like so:
+
+.. code-block:: glsl
+
+  uniform float size;
+
+For more information about usage see the :ref:`Shading Language doc <doc_shading_language>`.
+
+Add a uniform to change the amount of blue in our sprite.
+
+.. code-block:: glsl
+
+  uniform float blue = 1.0; // you can assign a default value to uniforms
+
+  void fragment(){
+    COLOR = texture(TEXTURE, UV); //read from texture
+    COLOR.b = blue;
+  }
+
+Now you can change the amount of blue in the sprite from the editor. Look back at the Inspector
+under where you created your shader. You should see a section called "Shader Param". Unfold that 
+section and you will see the uniform you just declared. If you change the value in the editor, it
+will overwrite the default value you provided in the shader.
+
+Interacting with shaders from code
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+You can change uniforms from code using the function ``set_shader_param`` which is called on the nodes
+material resource. With a sprite node, the following code can be used to set the ``blue`` uniform.
+
+::
+
+  var blue_value = 1.0
+  material.set_shader_param("blue", blue_value)
+
+Note that the name of the uniform is a string. The string must match exactly with how it is 
+written in the shader, including spelling and case.
+
+Your first vertex function
+--------------------------
+
+Now that we have a fragment function, let's write a vertex function.
+
+Use the vertex function to calculate where on the screen each vertex should end up.
+
+The most important variable in the vertex function is ``VERTEX``. Initially, it specifies
+the vertex coordinates in your model, but you also write to it to determine where to actually
+draw those vertices. ``VERTEX`` is a ``vec2`` that is initially presented in local-space 
+(i.e. not relative to the camera, viewport, or parent nodes).
+
+You can offset the vertices by directly adding to ``VERTEX``.
+
+.. code-block:: glsl
+
+  void vertex() {
+    VERTEX += vec2(10.0, 0.0);
+  } 
+
+Combined with the ``TIME`` built-in variable, this can be used for simple animation.
+
+.. code-block:: glsl
+
+  void vertex() {
+    // Animate sprite moving in big circle around its location
+    VERTEX += vec2(cos(TIME)*100.0, sin(TIME)*100.0);
+  }
+
+Conclusion
+----------
+
+At their core, shaders do what you have seen so far, they compute ``VERTEX`` and ``COLOR``. It is
+up to you to dream up more complex mathematical strategies for assigning values to those variables. 
+
+For inspiration, take a look at some of the more advanced shader tutorials, and look at other sites
+like `Shadertoy <https://www.shadertoy.com>`_ and `The Book of Shaders <https://thebookofshaders.com>`_. 

+ 9 - 0
tutorials/shading/your_first_shader/your_first_particles_shader.rst

@@ -0,0 +1,9 @@
+.. _doc_your_first_particles_shader:
+
+Your first Particles shader
+===========================
+
+Introduction
+------------
+
+

+ 9 - 0
tutorials/shading/your_first_shader/your_first_spatial_shader.rst

@@ -0,0 +1,9 @@
+.. _doc_your_first_spatial_shader:
+
+Your first Spatial shader
+============================
+
+Introduction
+------------
+
+

+ 9 - 0
tutorials/shading/your_first_shader/your_first_visual_shader.rst

@@ -0,0 +1,9 @@
+.. _doc_your_first_visual_shader:
+
+Your first visual shader
+========================
+
+Introduction
+------------
+
+