Bladeren bron

Rename your first shader pages

Also filled paragraphs at 80 characters

Closes #4157
Nathan Lovato 4 jaren geleden
bovenliggende
commit
708f952dbf

+ 3 - 3
tutorials/shading/your_first_shader/index.rst

@@ -21,6 +21,6 @@ For a more general introduction into shaders and the OpenGL Shading Language, us
    :name: toc-your-first-shader
 
    what_are_shaders
-   your_first_canvasitem_shader
-   your_first_spatial_shader
-   your_second_spatial_shader
+   your_first_2d_shader
+   your_first_3d_shader
+   your_second_3d_shader

+ 249 - 0
tutorials/shading/your_first_shader/your_first_2d_shader.rst

@@ -0,0 +1,249 @@
+.. _doc_your_first_canvasitem_shader:
+
+Your first 2D 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;
+
+Because 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/results?query=&sort=popular&from=10&num=4>`_ and `The
+Book of Shaders <https://thebookofshaders.com>`_.

+ 388 - 0
tutorials/shading/your_first_shader/your_first_3d_shader.rst

@@ -0,0 +1,388 @@
+.. _doc_your_first_spatial_shader:
+
+Your first 3D 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:`StandardMaterial3D <class_StandardMaterial3D>` 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``
+because 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'll 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 a texture as the first argument and a ``vec2`` for the position on the
+texture as the second argument. We use the ``x`` and ``z`` channels of
+``VERTEX`` to determine where on the texture to look up. Note that the PlaneMesh
+coordinates are within the [-1,1] range (for a size of 2), while the texture
+coordinates are within [0,1], so to normalize we divide by the size of the
+PlaneMesh 2.0 and add 0.5. ``texture()`` returns a ``vec4`` of the ``r, g, b,
+a`` channels at the position. Since the noise texture is grayscale, all of the
+values are the same, so we can use any one of the channels as the height. In
+this case we'll use the ``r``, or ``x`` channel.
+
+.. code-block:: glsl
+
+  float height = texture(noise, VERTEX.xz / 2.0 + 0.5).x;
+  VERTEX.y += height;
+
+Note: ``xyzw`` is the same as ``rgba`` in GLSL, so instead of ``texture().x``
+above, we could use ``texture().r``. See the `OpenGL documentation
+<https://www.khronos.org/opengl/wiki/Data_Type_(GLSL)#Vectors>`_ for more
+details.
+
+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 in Spatial-based nodes is different from
+          CanvasItem-based 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, because 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 ``tex_position``. And inside the
+``vertex()`` function assign ``VERTEX.xz`` to ``tex_position``.
+
+.. code-block:: glsl
+
+  varying vec2 tex_position;
+
+  void vertex() {
+    ...
+    tex_position = VERTEX.xz / 2.0 + 0.5;
+    float height = texture(noise, tex_position).x;
+    ...
+  }
+
+And now we can access ``tex_position`` from the ``fragment()`` function.
+
+.. code-block:: glsl
+
+  void fragment() {
+    NORMALMAP = texture(normalmap, tex_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 tex_position;
+
+  void vertex() {
+    tex_position = VERTEX.xz / 2.0 + 0.5;
+    float height = texture(noise, tex_position).x;
+    VERTEX.y += height * height_scale;
+  }
+
+  void fragment() {
+    NORMALMAP = texture(normalmap, tex_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.

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

@@ -1,220 +0,0 @@
-.. _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;
-
-Because 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/results?query=&sort=popular&from=10&num=4>`_ and `The Book of Shaders <https://thebookofshaders.com>`_.

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

@@ -1,350 +0,0 @@
-.. _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`` because 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'll 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 a texture as the first
-argument and a ``vec2`` for the position on the texture as the second argument. We use the ``x`` and ``z``
-channels of ``VERTEX`` to determine where on the texture to look up. Note that the PlaneMesh coordinates are
-within the [-1,1] range (for a size of 2), while the texture coordinates are within [0,1], so to normalize
-we divide by the size of the PlaneMesh 2.0 and add 0.5. ``texture()`` returns a ``vec4`` of the
-``r, g, b, a`` channels at the position. Since the noise texture is grayscale, all of the values are the same,
-so we can use any one of the channels as the height. In this case we'll use the ``r``, or ``x`` channel.
-
-.. code-block:: glsl
-
-  float height = texture(noise, VERTEX.xz / 2.0 + 0.5).x;
-  VERTEX.y += height;
-
-Note: ``xyzw`` is the same as ``rgba`` in GLSL, so instead of ``texture().x`` above, we could use ``texture().r``.
-See the `OpenGL documentation <https://www.khronos.org/opengl/wiki/Data_Type_(GLSL)#Vectors>`_ for more details.
-
-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 in Spatial-based nodes is different from CanvasItem-based 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 **As Normalmap**.
-
-.. image:: img/normal-set.png
-
-Now, because 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 ``tex_position``. And inside the ``vertex()`` function
-assign ``VERTEX.xz`` to ``tex_position``.
-
-.. code-block:: glsl
-
-  varying vec2 tex_position;
-
-  void vertex() {
-    ...
-    tex_position = VERTEX.xz / 2.0 + 0.5;
-    float height = texture(noise, tex_position).x;
-    ...
-  }
-
-And now we can access ``tex_position`` from the ``fragment()`` function.
-
-.. code-block:: glsl
-
-  void fragment() {
-    NORMALMAP = texture(normalmap, tex_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 tex_position;
-
-  void vertex() {
-    tex_position = VERTEX.xz / 2.0 + 0.5;
-    float height = texture(noise, tex_position).x;
-    VERTEX.y += height * height_scale;
-  }
-
-  void fragment() {
-    NORMALMAP = texture(normalmap, tex_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.

+ 126 - 99
tutorials/shading/your_first_shader/your_second_spatial_shader.rst → tutorials/shading/your_first_shader/your_second_3d_shader.rst

@@ -1,51 +1,58 @@
 .. _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 second 3D shader
+=====================
+
+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.
+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``:
+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:
+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.
+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>`.
+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.
+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``.
 
@@ -61,30 +68,33 @@ Let's set it to a nice shade of blue.
 
 .. 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.
+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``.
+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.
+``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.
+``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.
+``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.
+.. 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 its ``METALLIC`` property to ``0.0``. Water is also highly
-reflective, so we will set its ``ROUGHNESS`` property to be quite low as well.
+Water is not a metal, so we will set its ``METALLIC`` property to ``0.0``. Water
+is also highly reflective, so we will set its ``ROUGHNESS`` property to be quite
+low as well.
 
 .. code-block:: glsl
 
@@ -96,15 +106,18 @@ reflective, so we will set its ``ROUGHNESS`` property to be quite low as well.
 
 .. 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.
+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.
+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
 
@@ -112,10 +125,10 @@ mode for specular to toon because the toon render mode has larger specular highl
 
 .. 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.
+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
 
@@ -140,9 +153,10 @@ when you are looking at the surface head-on or at a glancing angle.
 
   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.
+And mix it into both ``ROUGHNESS`` and ``ALBEDO``. This is the benefit of
+ShaderMaterials over StandardMaterial3Ds. With StandardMaterial3D, 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
@@ -157,23 +171,26 @@ number. But with shaders we can set them based on any mathematical function that
 
 .. 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)``.
+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 animate the waves using the built-in variable ``TIME``.
+Going back to the vertex function, we can animate the waves using the built-in
+variable ``TIME``.
 
-``TIME`` is a built-in variable that is accessible from the vertex and fragment functions.
+``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()``.
+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
 
@@ -198,18 +215,18 @@ And make sure to correctly pass it in inside the vertex function.
     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.
+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.
+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``.
+Now, we are going to make the ``height()`` function a little more complicated by
+offsetting ``position`` by the cosine of ``TIME``.
 
 .. code-block:: glsl
 
@@ -218,20 +235,23 @@ by the cosine of ``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.
+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()``.
+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()``.
+``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.
+We are going to call ``wave()`` multiple times in ``height()`` in order to fake
+the way waves look.
 
 .. code-block:: glsl
 
@@ -254,17 +274,18 @@ they won't be straight lines completely aligned with the grid.
 
     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.
+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.
+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()``.
 
@@ -279,7 +300,8 @@ 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``.
+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
 
@@ -293,11 +315,13 @@ 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).
+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.
+Here is an example for how you could layer the four waves to achieve nicer
+looking waves.
 
 .. code-block:: glsl
 
@@ -309,15 +333,18 @@ Here is an example for how you could layer the four waves to achieve nicer looki
     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.
+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 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.
+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.