Procházet zdrojové kódy

Merge pull request #2323 from clayjohn/your_first_shader

Your first shader tutorial series
Max Hilbrunner před 6 roky
rodič
revize
e594f381f2
64 změnil soubory, kde provedl 1020 přidání a 369 odebrání
  1. binární
      tutorials/shading/img/vertex_displacement_cos.png
  2. binární
      tutorials/shading/img/vertex_displacement_cos_amplitude.png
  3. binární
      tutorials/shading/img/vertex_displacement_cos_scaled.png
  4. binární
      tutorials/shading/img/vertex_displacement_light1.png
  5. binární
      tutorials/shading/img/vertex_displacement_light2.png
  6. binární
      tutorials/shading/img/vertex_displacement_new_mesh.png
  7. binární
      tutorials/shading/img/vertex_displacement_new_shader.png
  8. binární
      tutorials/shading/img/vertex_displacement_new_shader_material.png
  9. binární
      tutorials/shading/img/vertex_displacement_noise1.png
  10. binární
      tutorials/shading/img/vertex_displacement_noise2.png
  11. binární
      tutorials/shading/img/vertex_displacement_noise3.png
  12. binární
      tutorials/shading/img/vertex_displacement_normal.png
  13. binární
      tutorials/shading/img/vertex_displacement_normal_detailed1.png
  14. binární
      tutorials/shading/img/vertex_displacement_normal_detailed2.png
  15. binární
      tutorials/shading/img/vertex_displacement_normal_detailed3.png
  16. binární
      tutorials/shading/img/vertex_displacement_planemesh.png
  17. binární
      tutorials/shading/img/vertex_displacement_shader_editor.png
  18. binární
      tutorials/shading/img/vertex_displacement_subdivided_mesh.png
  19. binární
      tutorials/shading/img/vertex_displacement_terrain.png
  20. binární
      tutorials/shading/img/vertex_displacement_uniform1.png
  21. binární
      tutorials/shading/img/vertex_displacement_uniform2.png
  22. binární
      tutorials/shading/img/vertex_displacement_viewport_settings.png
  23. binární
      tutorials/shading/img/vertex_displacement_wireframe1.png
  24. binární
      tutorials/shading/img/vertex_displacement_wireframe2.png
  25. 1 1
      tutorials/shading/index.rst
  26. 0 368
      tutorials/shading/vertex_displacement_with_shaders.rst
  27. binární
      tutorials/shading/your_first_shader/img/PBR.png
  28. binární
      tutorials/shading/your_first_shader/img/UV.png
  29. binární
      tutorials/shading/your_first_shader/img/albedo.png
  30. binární
      tutorials/shading/your_first_shader/img/blue-box.png
  31. binární
      tutorials/shading/your_first_shader/img/blue-tex.png
  32. binární
      tutorials/shading/your_first_shader/img/cos.png
  33. binární
      tutorials/shading/your_first_shader/img/cos4.png
  34. binární
      tutorials/shading/your_first_shader/img/dark-water.png
  35. binární
      tutorials/shading/your_first_shader/img/fresnel.png
  36. binární
      tutorials/shading/your_first_shader/img/iconuv.png
  37. binární
      tutorials/shading/your_first_shader/img/light.png
  38. binární
      tutorials/shading/your_first_shader/img/noise-flat.png
  39. binární
      tutorials/shading/your_first_shader/img/noise-low.png
  40. binární
      tutorials/shading/your_first_shader/img/noise-mesh.png
  41. binární
      tutorials/shading/your_first_shader/img/noise-normal-light.png
  42. binární
      tutorials/shading/your_first_shader/img/noise-normal-sub.png
  43. binární
      tutorials/shading/your_first_shader/img/noise-normal.png
  44. binární
      tutorials/shading/your_first_shader/img/noise-set.png
  45. binární
      tutorials/shading/your_first_shader/img/noise.png
  46. binární
      tutorials/shading/your_first_shader/img/normal-set.png
  47. binární
      tutorials/shading/your_first_shader/img/normal.png
  48. binární
      tutorials/shading/your_first_shader/img/normalmap.png
  49. binární
      tutorials/shading/your_first_shader/img/normalmap2.png
  50. binární
      tutorials/shading/your_first_shader/img/plane-sub-set.png
  51. binární
      tutorials/shading/your_first_shader/img/plane-sub.png
  52. binární
      tutorials/shading/your_first_shader/img/plane.png
  53. binární
      tutorials/shading/your_first_shader/img/plastic.png
  54. binární
      tutorials/shading/your_first_shader/img/rim.png
  55. binární
      tutorials/shading/your_first_shader/img/shader-error.png
  56. binární
      tutorials/shading/your_first_shader/img/specular-toon.png
  57. binární
      tutorials/shading/your_first_shader/img/wave1.png
  58. binární
      tutorials/shading/your_first_shader/img/wave2.png
  59. binární
      tutorials/shading/your_first_shader/img/wave3.png
  60. 26 0
      tutorials/shading/your_first_shader/index.rst
  61. 113 0
      tutorials/shading/your_first_shader/what_are_shaders.rst
  62. 220 0
      tutorials/shading/your_first_shader/your_first_canvasitem_shader.rst
  63. 340 0
      tutorials/shading/your_first_shader/your_first_spatial_shader.rst
  64. 320 0
      tutorials/shading/your_first_shader/your_second_spatial_shader.rst

binární
tutorials/shading/img/vertex_displacement_cos.png


binární
tutorials/shading/img/vertex_displacement_cos_amplitude.png


binární
tutorials/shading/img/vertex_displacement_cos_scaled.png


binární
tutorials/shading/img/vertex_displacement_light1.png


binární
tutorials/shading/img/vertex_displacement_light2.png


binární
tutorials/shading/img/vertex_displacement_new_mesh.png


binární
tutorials/shading/img/vertex_displacement_new_shader.png


binární
tutorials/shading/img/vertex_displacement_new_shader_material.png


binární
tutorials/shading/img/vertex_displacement_noise1.png


binární
tutorials/shading/img/vertex_displacement_noise2.png


binární
tutorials/shading/img/vertex_displacement_noise3.png


binární
tutorials/shading/img/vertex_displacement_normal.png


binární
tutorials/shading/img/vertex_displacement_normal_detailed1.png


binární
tutorials/shading/img/vertex_displacement_normal_detailed2.png


binární
tutorials/shading/img/vertex_displacement_normal_detailed3.png


binární
tutorials/shading/img/vertex_displacement_planemesh.png


binární
tutorials/shading/img/vertex_displacement_shader_editor.png


binární
tutorials/shading/img/vertex_displacement_subdivided_mesh.png


binární
tutorials/shading/img/vertex_displacement_terrain.png


binární
tutorials/shading/img/vertex_displacement_uniform1.png


binární
tutorials/shading/img/vertex_displacement_uniform2.png


binární
tutorials/shading/img/vertex_displacement_viewport_settings.png


binární
tutorials/shading/img/vertex_displacement_wireframe1.png


binární
tutorials/shading/img/vertex_displacement_wireframe2.png


+ 1 - 1
tutorials/shading/index.rst

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

+ 0 - 368
tutorials/shading/vertex_displacement_with_shaders.rst

@@ -1,368 +0,0 @@
-.. _doc_vertex_displacement_with_shaders:
-
-Vertex displacement with shaders
-================================
-
-Introduction
-------------
-
-This tutorial will teach you how to displace the vertices of
-a :ref:`Plane Mesh<class_PlaneMesh>` inside a shader. Vertex displacement can be used
-for a wide variety of effects, but most commonly it is used
-as a quick way to turn a flat plane into a simple terrain. Typically
-this is done using a heightmap, but in order to keep everything self
-contained, in this tutorial, we will use noise in a shader. At the end
-of this tutorial, we will have a deformed plane that looks like a
-miniature terrain complete with dynamic lighting.
-
-By reading this tutorial, you should gain a basic understanding of:
-
-* How to create and subdivide a :ref:`Plane Mesh<class_PlaneMesh>`
-* How to create and assign a material to a :ref:`Mesh<class_MeshInstance>`
-* How to write a :ref:`Shader<class_Shader>` that displaces the vertices of a :ref:`Mesh<class_MeshInstance>`
-* How to pass values (Uniforms) into a :ref:`Shader<class_Shader>` to update the :ref:`Mesh<class_MeshInstance>` in realtime
-* How to approximate normals from a height function
-* How to use a light with a custom material
-
-The plane mesh
---------------
-
-First, add a :ref:`Spatial<class_Spatial>` node to the scene to act as the root. Next, add a :ref:`MeshInstance<class_MeshInstance>`
-as a child.
-
-.. image:: img/vertex_displacement_new_mesh.png
-
-Select the newly created :ref:`MeshInstance<class_MeshInstance>`. Then click on the button that says "null"
-next to the :ref:`Mesh<class_MeshInstance>` in the Inspector. This will bring up a list of :ref:`PrimitiveMeshes<class_PrimitiveMesh>`.
-Select "New PlaneMesh".
-
-.. image:: img/vertex_displacement_planemesh.png
-
-The button will change into a small image of a plane. Click on it to enter into
-the Inspector for the :ref:`Plane Mesh<class_MeshInstance>`.
-
-Then, in the viewport, click in the upper left corner where it says [Perspective].
-A menu will appear. In the middle of the menu are options for how to display the scene.
-Select 'Display Wireframe'.
-
-.. image:: img/vertex_displacement_viewport_settings.png
-
-This will allow you to see the triangles making up the plane.
-
-.. image:: img/vertex_displacement_wireframe1.png
-
-Now set the ``Subdivide Width`` and ``Subdivide Height`` to ``32``.
-
-.. image:: img/vertex_displacement_subdivided_mesh.png
-
-You can see that there are now many more triangles in the :ref:`Mesh<class_MeshInstance>`. This will give
-us more vertices to work with and thus allow us to add more detail.
-
-.. image:: img/vertex_displacement_wireframe2.png
-
-
-Shader magic
-------------
-
-Now that we have a :ref:`Plane Mesh<class_MeshInstance>` to draw, let's set up the material that will deform the :ref:`Mesh<class_MeshInstance>`.
-
-Click beside material in the :ref:`Plane Mesh<class_MeshInstance>` Menu and create a new :ref:`ShaderMaterial<class_ShaderMaterial>`.
-
-.. image:: img/vertex_displacement_new_shader_material.png
-
-Then click on the created :ref:`ShaderMaterial<class_ShaderMaterial>`.
-
-Then click beside 'shader' and create a new :ref:`Shader<class_Shader>`.
-
-.. image:: img/vertex_displacement_new_shader.png
-
-Click into the newly created :ref:`Shader<class_Shader>`. You should now see Godot's Shader editor.
-
-.. image:: img/vertex_displacement_shader_editor.png
-
-Notice how it is throwing an error? This is because the shader editor reloads shaders on
-the fly automatically. The first thing Godot shaders need is a declaration of what type of
-shader they are. Accordingly, we set the variable ``shader_type`` to ``spatial``. One more
-thing we will add is the ``render_mode``, we will set it to ``unshaded``. This means that
-Godot won't run the light shader on this object.
-
-::
-
-  shader_type spatial;
-  render_mode unshaded;
-
-This should remove the errors and your :ref:`Mesh<class_MeshInstance>` should turn white. If you were to comment out
-the ``render_mode``, the plane would appear blue because it would pick up the sky colors.
-
-Next we will define a vertex shader. The vertex shader determines where the vertices of your
-:ref:`Mesh<class_MeshInstance>` appear in the final scene. We will be using it to offset the height of each vertex and
-make our flat plane appear like a little terrain.
-
-We define the vertex shader like so:
-
-::
-
-  void vertex() {
-
-  }
-
-With nothing in the ``vertex`` function, Godot will use its default vertex shader. We can easily
-start to make changes by adding a single line:
-
-::
-
-  void vertex() {
-    VERTEX.y += cos(VERTEX.x) * sin(VERTEX.z);
-  }
-
-Adding this line, you should get an image like the one below.
-
-.. image:: img/vertex_displacement_cos.png
-
-Okay, let's unpack this. The ``y`` value of the ``VERTEX`` is being increased. And we are passing
-the ``x`` and ``z`` components of the ``VERTEX`` as arguments to ``cos`` and ``sin``; that gives us
-a wave-like appearance across the ``x`` and ``z`` axes.
-
-What we want to achieve is the look of little hills; after all. ``cos`` and ``sin`` already look kind of like
-hills. We do so by scaling the inputs to the ``cos`` and ``sin`` functions.
-
-::
-
-  void vertex() {
-    VERTEX.y += cos(VERTEX.x * 4.0) * sin(VERTEX.z * 4.0);
-  }
-
-.. image:: img/vertex_displacement_cos_scaled.png
-
-This looks better, but it is still too spiky. This is because ``cos`` and ``sin`` output values between ``-1`` and ``1``,
-so the range of the output is much too high. We correct this by multiplying the result by ``0.5`` to reduce the size.
-
-::
-
-  void vertex() {
-    VERTEX.y += cos(VERTEX.x * 4.0) * sin(VERTEX.z * 4.0) * 0.5;
-  }
-
-.. image:: img/vertex_displacement_cos_amplitude.png
-
-Looks much more hilly now. But ``cos`` and ``sin`` are boring. Let's move onto something more interesting.
-
-Noise
------
-
-Noise is a very popular tool for procedural generation. Think of it as similar to the cosine function
-where you have repeating hills except, with noise, each hill has a different height. Understanding
-noise is not necessary for this tutorial. There is nothing wrong with simply copying and pasting
-the code below.
-
-The first function we use to generate the noise is the ``hash`` function. It gives the random height
-for each of the hill tops.
-
-::
-
-  float hash(vec2 p) {
-    return fract(sin(dot(p * 17.17, vec2(14.91, 67.31))) * 4791.9511);
-  }
-
-You will find similar functions to this all over the internet. It is lovingly referred to as the
-'one-liner hash function'. It works well for simple noise, but there are many better alternatives
-floating around as well. For this tutorial, it will work fine.
-
-Next we define the ``noise`` function. It smoothly interpolates between the random heights.
-Again, if this code seems daunting, do not worry; just copy, paste and move on with the tutorial.
-
-::
-
-  float noise(vec2 x) {
-    vec2 p = floor(x);
-    vec2 f = fract(x);
-    f = f * f * (3.0 - 2.0 * f);
-    vec2 a = vec2(1.0, 0.0);
-    return mix(mix(hash(p + a.yy), hash(p + a.xy), f.x),
-           mix(hash(p + a.yx), hash(p + a.xx), f.x), f.y);
-  }
-
-Lastly, to add detail, we combine successive layers of noise using something called fractal
-brownian motion or FBM. Scary name aside, FBM noise just adds together layers of noise with
-increasing frequency and decreasing amplitude. To implement it, we run over a for loop where
-we increase the frequency each level, decrease the amplitude, and calculate a new layer of noise.
-
-::
-
-  float fbm(vec2 x) {
-    float height = 0.0;
-    float amplitude = 0.5;
-    float frequency = 3.0;
-    for (int i = 0; i < 6; i++){
-      height += noise(x * frequency) * amplitude;
-      amplitude *= 0.5;
-      frequency *= 2.0;
-    }
-    return height;
-  }
-
-We can now use this noise function in place of ``cos`` and ``sin`` in the previous section.
-
-::
-
-  float height = fbm(VERTEX.xz * 4.0);
-  VERTEX.y += height * 0.5;
-
-.. image:: img/vertex_displacement_noise1.png
-
-With the noise function in place, we already have something that looks kind of cool.
-There is a lot of detail, it kind of looks hilly or mountainous.
-
-Fragment shader
----------------
-
-The difference between a vertex shader and a fragment shader is that the vertex shader
-runs per vertex and sets properties such as ``VERTEX`` (position) and ``NORMAL``, while
-the fragment shader runs per pixel and, most importantly, sets the ``ALBEDO`` color of the :ref:`Mesh<class_MeshInstance>`.
-
-Now let's look at the :ref:`Mesh<class_MeshInstance>` with a regular shader instead of the wireframe. Set the
-viewport back to 'Display Normal'.
-
-.. image:: img/vertex_displacement_noise2.png
-
-The :ref:`Mesh<class_MeshInstance>` appears completely white because the fragment shader is coloring each pixel white;
-but if every pixel is white, we lose detail on the :ref:`Mesh<class_MeshInstance>`. So let's color each pixel based
-on the height calculated in the vertex shader. We do so by setting the ``COLOR`` variable
-in the vertex shader. And by setting the ``ALBEDO`` in the fragment shader to the calculated
-``COLOR`` variable.
-
-::
-
-  void vertex() {
-    ...
-    COLOR.xyz = vec3(height);
-  }
-
-  void fragment(){
-    ALBEDO = COLOR.xyz;
-  }
-
-With this change, we can see the detail of the :ref:`Mesh<class_MeshInstance>`, even without displaying the :ref:`Mesh<class_MeshInstance>`'s wireframe.
-
-.. image:: img/vertex_displacement_noise3.png
-
-Uniforms
---------
-
-Uniform variables allow you to pass data from the game into the shader. They can
-be very useful for controlling shader effects. Uniforms can be almost any
-datatype that can be used in the shader. To use a uniform, you declare it in
-your :ref:`Shader<class_Shader>` using the keyword ``uniform``.
-
-Let's make a uniform that changes the height of the terrain.
-
-::
-
-  uniform float height_scale = 0.5;
-
-
-Godot lets you initialize a uniform with a value; here, ``height_scale`` is set to
-``0.5``. You can set uniforms from GDScript by calling the function ``set_shader_param``
-on the material corresponding to the shader. The value passed from GDScript takes
-precedence over the value used to initialize it in the shader.
-
-::
-
-  material.set_shader_param("height_scale", 0.5)
-
-Remember that the string passed into ``set_shader_param`` must match the name
-of the uniform variable in the :ref:`Shader<class_Shader>`. You can use the uniform variable anywhere
-inside your :ref:`Shader<class_Shader>`. Here, we will use it to set the height value instead
-of arbitrarily multiplying by ``0.5``.
-
-::
-
-  VERTEX.y += height * height_scale;
-
-The terrain should look exactly the same, but now we have control over the height easily.
-Here is the same terrain with ``height_scale`` set to ``1``:
-
-.. image:: img/vertex_displacement_uniform1.png
-
-And here it is with ``height_scale`` set to ``0.2``:
-
-.. image:: img/vertex_displacement_uniform2.png
-
-Using uniforms, we can even change the value every frame to animate the height of the terrain.
-Combined with :ref:`Tweens<class_Tween>`, this can be especially useful for simple animations.
-
-Interacting with light
-----------------------
-
-As a final part of this tutorial, let's try to set up the terrain to interact with light.
-First, we will add an :ref:`OmniLight<class_OmniLight>` to the scene.
-
-
-.. image:: img/vertex_displacement_light1.png
-
-You should notice that nothing changes. That is because we set the ``render_mode`` to ``unshaded``
-at the beginning of this tutorial; let's remove that.
-
-::
-
-  shader_type spatial;
-  //render_mode unshaded;
-
-.. image:: img/vertex_displacement_light2.png
-
-It looks slightly better now; you can see the light affecting the terrain, and it has
-turned blue as a result of the sky. The problem is the light is affecting the terrain
-as if it were a flat plane. This is because the light shader uses the normals of the
-:ref:`Mesh<class_MeshInstance>` to calculate light. The normals are stored in the :ref:`Mesh<class_MeshInstance>`, but we are changing
-the shape of the :ref:`Mesh<class_MeshInstance>` in the shader, so the normals are no longer correct. To fix this,
-we need to recalculate the normals in the shader. Godot makes this easy for us; all we
-have to do is calculate the new normal and set ``NORMAL`` to that value in the vertex shader.
-With ``NORMAL`` set, Godot will do all the difficult lighting calculations for us.
-
-To calculate the normal from noise, we are going to use a technique called 'central differences'.
-This is used a lot, especially in places like Shadertoy, to calculate normals in shaders.
-What we will do is calculate the noise at four points surrounding the vertex in the ``x`` and ``z`` directions and then calculate
-the slope at the vertex from that. After all, a normal is just an indicator of the slope of the
-noise.
-
-We calculate the normal with one line in the vertex shader.
-
-::
-
-  vec2 e = vec2(0.01, 0.0);
-  vec3 normal = normalize(vec3(fbm(VERTEX.xz - e) - fbm(VERTEX.xz + e), 2.0 * e.x, fbm(VERTEX.xz - e.yx) - fbm(VERTEX.xz + e.yx)));
-  NORMAL = normal;
-
-The variable ``e`` just makes it easier to add and subtract the right value from the ``VERTEX``.
-Setting ``e`` to a lower number will increase the level of detail of the normal.
-
-With ``NORMAL`` calculated, the terrain now looks like:
-
-.. image:: img/vertex_displacement_normal.png
-
-This still does not look how we want it to. The issue here is that the noise changes
-faster than the vertices do. So when we calculate the normal at the point of the
-``VERTEX``, it does not align with what we see in the final :ref:`Mesh<class_MeshInstance>`. In order to fix
-this, we add more vertices. The below image is made with a :ref:`Mesh<class_MeshInstance>` with ``subdivision`` set
-to ``100``.
-
-.. image:: img/vertex_displacement_normal_detailed1.png
-
-Now, we can drag the light around and the lighting will update automatically.
-
-.. image:: img/vertex_displacement_normal_detailed2.png
-
-.. image:: img/vertex_displacement_normal_detailed3.png
-
-If you zoom the camera out, you can see that the :ref:`Mesh<class_MeshInstance>` now looks like a small terrain.
-
-.. image:: img/vertex_displacement_terrain.png
-
-That is everything for this tutorial. Hopefully, you now understand the basics of vertex
-shaders in Godot. As a further exercise, try changing the ``height_scale`` from gdscript,
-try using different :ref:`Primitive Meshes<class_PrimitiveMesh>`, and try making your
-own functions to calculate ``height``.
-
-For further information on how to use shaders in Godot,
-you should check out the :ref:`doc_shading_language` page.
-

binární
tutorials/shading/your_first_shader/img/PBR.png


binární
tutorials/shading/your_first_shader/img/UV.png


binární
tutorials/shading/your_first_shader/img/albedo.png


binární
tutorials/shading/your_first_shader/img/blue-box.png


binární
tutorials/shading/your_first_shader/img/blue-tex.png


binární
tutorials/shading/your_first_shader/img/cos.png


binární
tutorials/shading/your_first_shader/img/cos4.png


binární
tutorials/shading/your_first_shader/img/dark-water.png


binární
tutorials/shading/your_first_shader/img/fresnel.png


binární
tutorials/shading/your_first_shader/img/iconuv.png


binární
tutorials/shading/your_first_shader/img/light.png


binární
tutorials/shading/your_first_shader/img/noise-flat.png


binární
tutorials/shading/your_first_shader/img/noise-low.png


binární
tutorials/shading/your_first_shader/img/noise-mesh.png


binární
tutorials/shading/your_first_shader/img/noise-normal-light.png


binární
tutorials/shading/your_first_shader/img/noise-normal-sub.png


binární
tutorials/shading/your_first_shader/img/noise-normal.png


binární
tutorials/shading/your_first_shader/img/noise-set.png


binární
tutorials/shading/your_first_shader/img/noise.png


binární
tutorials/shading/your_first_shader/img/normal-set.png


binární
tutorials/shading/your_first_shader/img/normal.png


binární
tutorials/shading/your_first_shader/img/normalmap.png


binární
tutorials/shading/your_first_shader/img/normalmap2.png


binární
tutorials/shading/your_first_shader/img/plane-sub-set.png


binární
tutorials/shading/your_first_shader/img/plane-sub.png


binární
tutorials/shading/your_first_shader/img/plane.png


binární
tutorials/shading/your_first_shader/img/plastic.png


binární
tutorials/shading/your_first_shader/img/rim.png


binární
tutorials/shading/your_first_shader/img/shader-error.png


binární
tutorials/shading/your_first_shader/img/specular-toon.png


binární
tutorials/shading/your_first_shader/img/wave1.png


binární
tutorials/shading/your_first_shader/img/wave2.png


binární
tutorials/shading/your_first_shader/img/wave3.png


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

@@ -0,0 +1,26 @@
+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 you a high-level overview of what shaders are and how they fit
+into the rendering pipeline.
+
+The "your first shader" tutorials walk 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_second_spatial_shader

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

@@ -0,0 +1,113 @@
+.. _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 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.
+
+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. 
+
+Suppose you want to update all the pixels in a texture to a given color, on the CPU you would write:
+
+:: 
+
+  for x in range(width):
+    for y in range(height):
+      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:
+
+.. code-block:: glsl
+
+  // function called for each pixel
+  void fragment() {
+    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.
+
+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. 
+
+What can they do
+^^^^^^^^^^^^^^^^
+
+- position vertices very fast
+- compute color very fast
+- compute lighting very fast
+- lots and lots of math
+
+What can't they do
+^^^^^^^^^^^^^^^^^^
+
+- 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)
+ 
+Structure of a shader
+---------------------
+
+In Godot, shaders are made up of 3 main functions: the ``vertex()`` function, the ``fragment()``
+function and the ``light()`` function. 
+
+The ``vertex()`` function runs over all the vertices in the mesh and sets their positions as well
+as some other per-vertex variables.
+
+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.
+
+The ``light()`` function runs for every pixel and for every light. It takes variables from the 
+``fragment()`` function and from previous runs of itself. 
+
+For more information about how shaders operate specifically in Godot see the :ref:`Shaders <doc_shaders>` doc.
+
+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 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.
+

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

@@ -0,0 +1,220 @@
+.. _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
+you 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. Materials are a type of :ref:`Resource <doc_resources>`.
+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 :ref:`GUI elements <class_Control>`, :ref:`Sprites <class_sprite>`, :ref:`TileMaps <class_tilemap>`,
+:ref:`MeshInstance2Ds <class_meshinstance2d>` 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 resource. 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 in a Sprite and determines what color that pixel should be.
+
+They are restricted to the pixels covered by the Sprite, 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. 
+
+We do so by writing a ``vec4`` to the built-in variable ``COLOR``. ``vec4`` is shorthand for constructing
+a vector with 4 numbers. For more information about vectors see the :ref:`Vector math tutorial <doc_vector_math>` 
+``COLOR`` is both an input variable to the fragment function and the final output from it. 
+
+.. 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 Sprite (without you knowing it!)
+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.
+
+``UV`` varies between 0-1 from left-right and from top-bottom.
+
+.. image:: img/iconuv.png
+
+.. 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 node's
+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>`_. 

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

@@ -0,0 +1,340 @@
+.. _doc_your_first_spatial_shader:
+
+Your first Spatial shader
+============================
+
+You have decided to start writing your own custom Spatial shader. Maybe you saw a cool trick 
+online that was done with shaders, or you have found that the 
+:ref:`SpatialMaterial <class_SpatialMaterial>` isn't quite meeting your needs. Either way, 
+you have decided to write your own and now you need figure out where to start.
+
+This tutorial will explain how to write a Spatial shader and will cover more topics than the
+:ref:`CanvasItem <doc_your_first_canvasitem_shader>` tutorial.
+
+Spatial shaders have more built-in functionality than CanvasItem shaders. The expectation with
+spatial shaders is that Godot has already provided the functionality for common use cases and all
+the user needs to do in the shader is set the proper parameters. This is especially true for a 
+PBR (physically based rendering) workflow.
+
+This is a two-part tutorial. In this first part we are going to go through how to make a simple terrain
+using vertex displacement from a heightmap in the vertex function. In the :ref:`second part <doc_your_second_spatial_shader>` 
+we are going to take the concepts from this tutorial and walk through how to set up custom materials 
+in a fragment shader by writing an ocean water shader.
+
+.. note:: This tutorial assumes some basic shader knowledge such as types (``vec2``, ``float``,
+          ``sampler2D``), and functions. If you are uncomfortable with these concepts it is 
+          best to get a gentle introduction from `The Book of Shaders 
+          <https://thebookofshaders.com>`_ before completing this tutorial.
+          
+Where to assign my material
+---------------------------
+
+In 3D, objects are drawn using :ref:`Meshes <class_Mesh>`. Meshes are a resource type that store geometry
+(the shape of your object) and materials (the color and how the object reacts to light) in units called
+"surfaces". A Mesh can have multiple surfaces, or just one. Typically, you would
+import a mesh from another program (e.g. Blender). But Godot also has a few :ref:`PrimitiveMeshes <class_primitivemesh>`
+that allow you to add basic geometry to a scene without importing Meshes. 
+
+There are multiple node types that you can use to draw a mesh. The main one is :ref:`MeshInstance <class_meshinstance>`,
+but you can also use :ref:`Particles <class_particles>`, :ref:`MultiMeshes <class_MultiMesh>` (with a
+:ref:`MultiMeshInstance <class_multimeshinstance>`), or others.
+
+Typically, a material is associated with a given surface in a mesh, but some nodes, like MeshInstance, allow
+you to override the material for a specific surface, or for all surfaces. 
+
+If you set a material on the surface or mesh itself, then all MeshInstances that share that mesh will share that material. 
+However, if you want to reuse the same mesh across multiple mesh instances, but have different materials for each 
+instance then you should set the material on the Meshinstance.
+
+For this tutorial we will set our material on the mesh itself rather than taking advantage of the MeshInstance's 
+ability to override materials. 
+
+Setting up
+----------
+
+Add a new :ref:`MeshInstance <class_meshinstance>` node to your scene. 
+
+In the inspector tab beside "Mesh" click "[empty]" and select "New PlaneMesh".
+Then click on the image of a plane that appears.
+
+This adds a :ref:`PlaneMesh <class_planemesh>` to our scene.
+
+Then, in the viewport, click in the upper left corner on the button that says "Perspective".
+A menu will appear. In the middle of the menu are options for how to display the scene.
+Select 'Display Wireframe'.
+
+This will allow you to see the triangles making up the plane.
+
+.. image:: img/plane.png
+
+Now set ``Subdivide Width`` and ``Subdivide Depth`` to ``32``.
+
+.. image:: img/plane-sub-set.png
+
+You can see that there are now many more triangles in the :ref:`Mesh<class_MeshInstance>`. This will give
+us more vertices to work with and thus allow us to add more detail.
+
+.. image:: img/plane-sub.png
+
+:ref:`PrimitiveMeshes <class_primitivemesh>`, like PlaneMesh, only have one surface, so instead of 
+an array of materials there is only one. Click beside "Material" where it says "[empty]" and 
+select "New ShaderMaterial". Then click the sphere that appears. 
+
+Now click beside "Shader" where it says "[empty]" and select "New Shader". 
+
+The shader editor should now pop up and you are ready to begin writing your first Spatial shader!
+
+Shader magic
+------------
+
+.. image:: img/shader-error.png
+
+Notice how there is already error? This is because the shader editor reloads shaders on
+the fly. The first thing Godot shaders need is a declaration of what type of shader they are.
+We set the variable ``shader_type`` to ``spatial`` becuase this is a spatial shader.
+
+.. code-block:: glsl
+
+  shader_type spatial;
+
+Next we will define the ``vertex()`` function. The ``vertex()`` function determines where 
+the vertices of your :ref:`Mesh<class_MeshInstance>` appear in the final scene. We will be 
+using it to offset the height of each vertex and make our flat plane appear like a little terrain.
+
+We define the vertex shader like so:
+
+.. code-block:: glsl
+
+  void vertex() {
+
+  }
+
+With nothing in the ``vertex()`` function, Godot will use its default vertex shader. We can easily
+start to make changes by adding a single line:
+
+.. code-block:: glsl
+
+  void vertex() {
+    VERTEX.y += cos(VERTEX.x) * sin(VERTEX.z);
+  }
+
+Adding this line, you should get an image like the one below.
+
+.. image:: img/cos.png
+
+Okay, let's unpack this. The ``y`` value of the ``VERTEX`` is being increased. And we are passing
+the ``x`` and ``z`` components of the ``VERTEX`` as arguments to ``cos`` and ``sin``; that gives us
+a wave-like appearance across the ``x`` and ``z`` axes.
+
+What we want to achieve is the look of little hills; after all. ``cos`` and ``sin`` already look kind of like
+hills. We do so by scaling the inputs to the ``cos`` and ``sin`` functions.
+
+.. code-block:: glsl
+
+  void vertex() {
+    VERTEX.y += cos(VERTEX.x * 4.0) * sin(VERTEX.z * 4.0);
+  }
+
+.. image:: img/cos4.png
+
+This looks better, but it is still too spiky and repetitive, let's make it a little more interesting.
+
+Noise heightmap
+---------------
+
+Noise is a very popular tool for faking the look of terrain. Think of it as similar to the cosine function
+where you have repeating hills except, with noise, each hill has a different height.
+
+Godot provides the :ref:`NoiseTexture <class_noisetexture>` resource for generating a noise texture
+that can be accessed from a shader.
+
+To access a texture in a shader add the following code near the top of your shader, outside the
+``vertex()`` function.
+
+.. code-block:: glsl
+
+  uniform sampler2D noise;
+
+This will allow you to send a noise texture to the shader. Now look in the inspecter under your material.
+You should see a section called "Shader Params". If you open it up you will see a section called "noise".
+
+Click beside it where it says "[empty]" and select "New NoiseTexture". Then in your NoiseTexture click beside
+where it says "Noise" and select "New OpenSimplexNoise".
+
+:ref:`OpenSimplexNoise <class_opensimplexnoise>` is used by the NoiseTexture to generate a heightmap.
+
+Once you set it up and should look like this.
+
+.. image:: img/noise-set.png
+
+Now, access the noise texture using the ``texture()`` function. ``texture()`` takes the texture as a first
+argument and the position on the texture as the second. We use the ``x`` and ``z`` channels of ``VERTEX`` to 
+determine where on the texture to look up. 
+
+.. code-block:: glsl
+
+  float height = texture(noise, VERTEX.xz / 2.0 ); //divide by the size of the PlaneMesh
+  VERTEX.y += height;
+
+Using this code you can see the texture creates random looking hills.
+
+.. image:: img/noise.png
+
+Right now it is too spiky, we want to soften the hills a bit. To do that we will use a uniform.
+You already used a uniform above to pass in the noise texture, now let's learn how they work.
+
+Uniforms
+--------
+
+Uniform variables allow you to pass data from the game into the shader. They are
+very useful for controlling shader effects. Uniforms can be almost any
+datatype that can be used in the shader. To use a uniform, you declare it in
+your :ref:`Shader<class_Shader>` using the keyword ``uniform``.
+
+Let's make a uniform that changes the height of the terrain.
+
+.. code-block:: glsl
+
+  uniform float height_scale = 0.5;
+
+
+Godot lets you initialize a uniform with a value; here, ``height_scale`` is set to
+``0.5``. You can set uniforms from GDScript by calling the function ``set_shader_param()``
+on the material corresponding to the shader. The value passed from GDScript takes
+precedence over the value used to initialize it in the shader.
+
+::
+
+  # called from the MeshInstance
+  mesh.material.set_shader_param("height_scale", 0.5)
+
+.. note:: Changing uniforms from Spatial nodes is different than in CanvasItem nodes. Here, 
+          we set the material inside the PlaneMesh resource. In other mesh resources you may
+          need to first access the material by calling ``surface_get_material()``. While in
+          the MeshInstance you would access the material using ``get_surface_material()`` or
+          ``material_override``.
+
+Remember that the string passed into ``set_shader_param()`` must match the name
+of the uniform variable in the :ref:`Shader<class_Shader>`. You can use the uniform variable anywhere
+inside your :ref:`Shader<class_Shader>`. Here, we will use it to set the height value instead
+of arbitrarily multiplying by ``0.5``.
+
+.. code-block:: glsl
+
+  VERTEX.y += height * height_scale;
+
+Now it looks  much better.
+
+.. image:: img/noise-low.png
+
+Using uniforms, we can even change the value every frame to animate the height of the terrain.
+Combined with :ref:`Tweens <class_Tween>`, this can be especially useful for simple animations.
+
+Interacting with light
+----------------------
+
+First, turn wireframe off. To do so, click in the upper-left of the Viewport again, where it says
+"Perspective", and select "Display Normal".
+
+.. image:: img/normal.png
+
+Note how the mesh color goes flat. This is because the lighting on it is flat. Let's add a light!
+
+First, we will add an :ref:`OmniLight<class_OmniLight>` to the scene.
+
+.. image:: img/light.png
+
+You can see the light affecting the terrain, but it looks odd. The problem is the light
+is affecting the terrain as if it were a flat plane. This is because the light shader uses 
+the normals from the :ref:`Mesh <class_mesh>` to calculate light. 
+
+The normals are stored in the Mesh, but we are changing the shape of the Mesh in the 
+shader, so the normals are no longer correct. To fix this, we can recalculate the normals 
+in the shader or use a normal texture that corresponds to our noise. Godot makes both easy for us. 
+
+You can calculate the new normal manually in the vertex function and then just set ``NORMAL``.
+With ``NORMAL`` set, Godot will do all the difficult lighting calculations for us. We will cover 
+this method in the next part of this tutorial, for now we will read normals from a texture.
+
+Instead we will rely on the NoiseTexture again to calculate normals for us. We do that by passing in
+a second noise texture.
+
+.. code-block:: glsl
+
+  uniform sampler2D normalmap;
+
+Set this second uniform texture to another NoiseTexture with another OpenSimplexNoise. But this time, check
+off "As Normalmap".
+
+.. image:: img/normal-set.png
+
+Now, becuase this is a normalmap and not a per-vertex normal. We are going to assign it in the ``fragment()``
+function. The ``fragment()`` function will be explained in more detail in the next part of this tutorial.
+
+.. code-block:: glsl
+
+  void fragment() {
+  }
+
+When we have normals that correspond to a specific vertex we set ``NORMAL``, but if you have a normalmap
+that comes from a texture, set the normal using ``NORMALMAP``. This way Godot will handle the wrapping the
+texture around the mesh automatically. 
+
+Lastly, in order to ensure that we are reading from the same places on the noise texture and the normalmap
+texture, we are going to pass the ``VERTEX.xz`` position from the ``vertex()`` function to the ``fragment()``
+function. We do that with varyings. 
+
+Above the ``vertex()`` define a ``vec2`` called ``vertex_position``. And inside the ``vertex()`` function
+assign ``VERTEX.xz`` to ``vertex_position``.
+
+.. code-block:: glsl
+
+  varying vec2 vertex_position;
+
+  void vertex() {
+    ...
+    vertex_position = VERTEX.xz / 2.0;
+  }
+
+And now we can access ``vertex_position`` from the ``fragment()`` function.
+
+.. code-block:: glsl
+
+  void fragment() {
+    NORMALMAP = texture(normalmap, vertex_position).xyz;
+  }
+
+With the normals in place the light now reacts to the height of the mesh dynamically.
+
+.. image:: img/normalmap.png
+
+We can even drag the light around and the lighting will update automatically.
+
+.. image:: img/normalmap2.png
+
+Here is the full code for this tutorial. You can see it is not very long as Godot handles
+most of the difficult stuff for you. 
+
+.. code-block:: glsl
+
+  shader_type spatial;
+
+  uniform float height_scale = 0.5;
+  uniform sampler2D noise;
+  uniform sampler2D normalmap;
+
+  varying vec2 vertex_position;
+
+  void vertex() {
+    vertex_position = VERTEX.xz / 2.0;
+    float height = texture(noise, vertex_position).x * height_scale;
+  }
+
+  void fragment() {
+    NORMALMAP = texture(normalmap, vertex_position).xyz;
+  }
+
+That is everything for this part. Hopefully, you now understand the basics of vertex
+shaders in Godot. In the next part of this tutorial we will write a fragment function 
+to accompany this vertex function and we will cover a more advanced technique to turn
+this terrain into an ocean of moving waves. 

+ 320 - 0
tutorials/shading/your_first_shader/your_second_spatial_shader.rst

@@ -0,0 +1,320 @@
+.. _doc_your_second_spatial_shader:
+
+Your first Spatial shader: part 2
+=================================
+
+From a high-level, what Godot does is give the user a bunch of parameters that can be optionally set
+(``AO``, ``SSS_Strength``, ``RIM``, etc.). These parameters correspond to different complex effects
+(Ambient Occlusion, SubSurface Scattering, Rim Lighting, etc.). When not written to, the code is thrown
+out before it is compiled and so the shader does not incur the cost of the extra feature. This makes it
+easy for users to have complex PBR-correct shading, without writing complex shaders. Of course, Godot
+also allows you to ignore all these parameters and write a fully customized shader.
+
+For a full list of these parameters see the :ref:`spatial shader <doc_spatial_shader>` reference doc.
+
+A difference between the vertex function and a fragment function is that the vertex function
+runs per vertex and sets properties such as ``VERTEX`` (position) and ``NORMAL``, while
+the fragment shader runs per pixel and, most importantly, sets the ``ALBEDO`` color of the :ref:`Mesh<class_MeshInstance>`.
+
+Your first spatial fragment function
+------------------------------------
+
+As mentioned in the previous part of this tutorial. The standard use of the fragment function
+in Godot is to set up different material properties and let Godot handle the rest. In order
+to provide even more flexibility, Godot also provides things called render modes. Render
+modes are set at the top of the shader, directly below ``shader_type``, and they specify
+what sort of functionality you want the built-in aspects of the shader to have. 
+
+For example, if you do not want to have lights affect an object, set the render mode to 
+``unshaded``:
+
+.. code-block:: glsl
+
+  render_mode unshaded;
+
+You can also stack multiple render modes together. For example, if you want to use toon 
+shading instead of more-realistic PBR shading, set the diffuse mode and specular mode to toon:
+
+.. code-block:: glsl
+
+  render_mode diffuse_toon, specular_toon;
+
+This model of built-in functionality allows you to write complex custom shaders by changing
+only a few parameters.
+
+For a full list of render modes see the :ref:`Spatial shader reference <doc_spatial_shader>`.
+
+In this part of the tutorial, we will walk through how to take the bumpy terrain from the 
+previous part and turn it into an ocean.  
+
+First let's set the color of the water. We do that by setting ``ALBEDO``.
+
+``ALBEDO`` is a ``vec3`` that contains the color of the object.
+
+Let's set it to a nice shade of blue.
+
+.. code-block:: glsl
+
+  void fragment() {
+    ALBEDO = vec3(0.1, 0.3, 0.5);
+  }
+
+.. image:: img/albedo.png
+
+We set it to a very dark shade of blue because most of the blueness of the water will
+come from reflections from the sky.
+
+The PBR model that Godot uses relies on two main parameters: ``METALLIC`` and ``ROUGHNESS``.
+
+``ROUGHNESS`` specifies how smooth/rough the surface of a material is. A low ``ROUGHNESS`` will
+make a material appear like a shiny plastic, while a high roughness makes the material appear 
+more solid in color.
+
+``METALLIC`` specifies how much like a metal the object is. It is better set close to ``0`` or ``1``.
+Think of ``METALLIC`` as changing the balance between the reflection and the ``ALBEDO`` color. A 
+high ``METALLIC`` almost ignores ``ALBEDO`` altogether, and looks like a mirror of the sky. While
+a low ``METALLIC`` has a more equal representation of sky color and ``ALBEDO`` color. 
+
+``ROUGHNESS`` increases from ``0`` to ``1`` from left to right while ``METALLIC`` increase from
+``0`` to ``1`` from top to bottom.
+
+.. image:: img/PBR.png
+
+.. note:: ``METALLIC`` should be close to ``0`` or ``1`` for proper PBR shading. Only set it between
+          them for blending between materials.
+
+Water is not a metal, so we will set it's ``METALLIC`` property to ``0.0``. But, water is also highly
+reflective, so we will set it's ``ROUGHNESS`` property to by quite low as well.
+
+.. code-block:: glsl
+
+  void fragment() {
+    METALLIC = 0.0;
+    ROUGHNESS = 0.01;
+    ALBEDO = vec3(0.1, 0.3, 0.5);
+  }
+
+.. image:: img/plastic.png
+
+Now we have a smooth plastic looking surface. It is time to think about some particular properties of 
+water that we want to emulate. There are two main ones that will take this from a weird plastic surface 
+to nice stylized water. The first is specular reflections. Specular reflections are those bright spots
+you see from where the sun reflects directly into your eye. The second is fresnel reflectance.
+Fresnel reflectance is the property of objects to become more reflective at shallow angles. It is the 
+reason why you can see into water below you, but farther away it reflects the sky.
+
+In order to increase the specular reflections, we will do two things. First, we will change the render 
+mode for specular to toon because the toon render mode has larger specular highlights. 
+
+.. code-block:: glsl
+
+  render_mode specular_toon;
+
+.. image:: img/specular-toon.png
+
+Second we will
+add rim lighting. Rim lighting increases the effect of light at glancing angles. Usually it is used
+to emulate the way light passes through fabric on the edges of an object, but we will use it here to 
+help achieve a nice watery effect.
+
+.. code-block:: glsl
+
+  void fragment() {
+    RIM = 0.2;  
+    METALLIC = 0.0;
+    ROUGHNESS = 0.01;
+    ALBEDO = vec3(0.1, 0.3, 0.5);
+  }
+
+.. image:: img/rim.png
+
+In order to add fresnal reflectance we will compute a fresnel term in our fragment shader.
+We are not going to use a real fresnel term, instead we will approximate it using the dot
+product of the ``NORMAL`` and ``VIEW`` vectors. The ``NORMAL`` vector points away from a 
+surface of the, while the ``VIEW`` vector is the direction between your eye and that point
+on the surface. The dot product between them is a handy way to tell when you are looking
+at the surface head-on your at a glancing angle.
+
+.. code-block:: glsl
+
+  float fresnel = sqrt(1.0 - dot(NORMAL, VIEW));
+
+And mix it into both ``ROUGHNESS`` and ``ALBEDO``. This is the benefit of ShaderMaterials over 
+SpatialMaterials. With SpatialMaterials we could set these properties with a texture, or to a flat
+number. But with shaders we can set them based on any mathematical function that we can dream up.
+
+
+.. code-block:: glsl
+
+  void fragment() {
+    float fresnel = sqrt(1.0 - dot(NORMAL, VIEW));
+    RIM = 0.2;  
+    METALLIC = 0.0;
+    ROUGHNESS = 0.01 * (1.0 - fresnel);
+    ALBEDO = vec3(0.1, 0.3, 0.5) + (0.1 * fresnel);
+  }
+
+.. image:: img/fresnel.png
+
+And now, with only 5 lines of code, you can have complex looking water. Now that we have
+lighting, this water is looking too bright. Let's darken it. This is done easily by 
+decreasing the values of the ``vec3`` we pass into ``ALBEDO``. Let's set them to 
+``vec3(0.01, 0.03, 0.05)``.
+
+.. image:: img/dark-water.png
+
+Animating with ``TIME``
+-----------------------
+
+Going back to the vertex function, we can animated the waves using the built-in variable ``TIME``.
+
+``TIME`` is a built-in variable that is accessible from the vertex and fragment functions. 
+
+
+In the last tutorial we calculated height by reading from a heightmap. For this tutorial, 
+we will do the same. Put the heightmap code in a function called ``height()``.
+
+.. code-block:: glsl
+
+  float height(vec2 position) {
+    return texture(noise, position / 10.0).x; //scaling factor is based on mesh size (This PlanMesh is 10x10)
+  }
+
+In order to use ``TIME`` in the ``height()`` function we need to pass it in. 
+
+.. code-block:: glsl
+
+  float height(vec2 position, float time) {
+  }
+
+And make sure to correctly pass it in inside the vertex function.
+
+.. code-block:: glsl
+
+  void vertex() {
+    vec2 pos = VERTEX.xz;
+    float k = height(pos, TIME);
+    VERTEX.y = k;
+  }
+
+Instead of using a normalmap to calculate normals. We are going to compute them manually in the 
+``vertex()`` function. To do so use the following line of code.
+
+.. code-block:: glsl
+
+  NORMAL = normalize(vec3(k - height(pos + vec2(0.1, 0.0), TIME), 0.1, k - height(pos + vec2(0.0, 0.1), TIME)));
+
+We need to compute ``NORMAL`` manually because in the next section we will be using math to create
+complex-looking waves.
+
+Now, we are going to make the ``height()`` function a little more complicated by offsetting ``position``
+by the cosine of ``TIME``.
+
+.. code-block:: glsl
+
+  float height(vec2 position, float time) {
+    vec2 offset = 0.01 * cos(position + time);
+    return texture(noise, (position / 10.0) - offset).x;
+  }
+
+This results in waves that move slowly, but not in a very natural way. The next section will dig deeper
+into using shaders to create more complex effects, in this case realistic waves, by adding a few
+more mathematical functions.
+
+Advanced effects: waves
+-----------------------
+
+What makes shaders so powerful is that you can achieve complex effects by using math. To illustrate
+this, we are going to take our waves to the next level by modifying the ``height()`` function and
+by introducing a new function called ``wave()``.
+
+``wave()`` has one parameter, ``position``, which is the same as it is in ``height()``. 
+
+We are going to call ``wave()`` multiple times in ``height()`` in order to fake the way waves look.
+
+.. code-block:: glsl
+
+  float wave(vec2 position){
+    position += texture(noise, position / 10.0).x * 2.0 - 1.0;
+    vec2 wv = 1.0 - abs(sin(position));
+    return pow(1.0 - pow(wv.x * wv.y, 0.65), 4.0);
+  }
+
+At first this looks complicated. So let's go through it line-by-line.
+
+.. code-block:: glsl
+
+    position += texture(noise, position / 10.0).x * 2.0 - 1.0;
+
+Offset the position by the ``noise`` texture. This will make the waves curve so they are not straight lines
+completely aligned with the grid.
+
+.. code-block:: glsl
+
+    vec2 wv = 1.0 - abs(sin(position));
+
+Define a wave-like function using ``sin()`` and ``position``. Normally ``sin()`` waves are very round.
+We use ``abs()`` to absolute to give them a sharp ridge and constrain them to the 0-1 range. And then we
+subtract it from ``1.0`` to put the peak on top. 
+
+.. code-block:: glsl
+
+    return pow(1.0 - pow(wv.x * wv.y, 0.65), 4.0);
+
+Multiply the x-directional wave by the y-directional wave and raise it to a power to sharpen the peaks. 
+Then subtract that from ``1.0`` so that the ridges become peaks and raise that to a power to sharpen the 
+ridges. 
+
+We can now replace the contents of our ``height()`` function with ``wave()``. 
+
+.. code-block:: glsl
+
+  float height(vec2 position, float time) {
+    float h = wave(position);
+  }
+
+Using this you get:
+
+.. image:: img/wave1.png
+
+The shape of the sin wave is too obvious. So let's spread the waves out a bit. We do this by scaling ``position``.
+
+.. code-block:: glsl
+
+  float height(vec2 position, float time) {
+    float h = wave(position*0.4);
+  }
+  
+Now it looks much better.
+
+.. image:: img/wave2.png
+
+We can do even better if we layer multiple waves on top of each other at varying
+frequencies and amplitudes. What this means is that we are going to scale position for each one to make
+the waves thinner or wider (frequency). And we are going to multiply the output of the wave to make them shorter
+or taller (amplitude).
+
+Here is an example for how you could layer the four waves to achieve nicer looking waves.
+
+.. code-block:: glsl
+
+  float height(vec2 position, float time) {
+    float d = wave((position + time) * 0.4, 8.0) * 0.3;
+    d += wave((position - time) * 0.3, 8.0) * 0.3;
+    d += wave((position + time) * 0.5, 4.0) * 0.2;
+    d += wave((position - time) * 0.6, 4.0) * 0.2;
+    return d;
+  }
+
+Note that we add time to two and subtract it from the other two. This makes the waves move in different directions
+creating a complex effect. Also note that the amplitudes (the number the result is multiplied by) all 
+add up to ``1.0``. This keeps the wave in the 0-1 range.
+
+With this code you should end up with more complex looking waves and all you had to do was add a little bit
+of math! 
+
+.. image:: img/wave3.png
+
+For more information about Spatial shaders read the :ref:`Shading Language <doc_shading_language>` 
+doc and the :ref:`Spatial Shaders <doc_spatial_shader>` doc. Also look at more advanced tutorials 
+in the :ref:`Shading section <toc-learn-features-shading>` and the :ref:`3D <toc-learn-features-3d>` sections.