Browse Source

Rename your first shader pages

Also filled paragraphs at 80 characters

Closes #4157
Nathan Lovato 4 years ago
parent
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
    :name: toc-your-first-shader
 
 
    what_are_shaders
    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:
 .. _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
 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
 .. code-block:: glsl
 
 
   render_mode unshaded;
   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
 .. code-block:: glsl
 
 
   render_mode diffuse_toon, specular_toon;
   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``.
 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
 .. 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
 .. 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
 .. 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
 .. 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
 .. 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
 .. 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
 .. 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));
   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
 .. 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
 .. 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
 .. image:: img/dark-water.png
 
 
 Animating with ``TIME``
 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
 .. code-block:: glsl
 
 
@@ -198,18 +215,18 @@ And make sure to correctly pass it in inside the vertex function.
     VERTEX.y = k;
     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
 .. 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)));
   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
 .. code-block:: glsl
 
 
@@ -218,20 +235,23 @@ by the cosine of ``TIME``.
     return texture(noise, (position / 10.0) - offset).x;
     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
 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
 .. 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));
     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
 .. code-block:: glsl
 
 
     return pow(1.0 - pow(wv.x * wv.y, 0.65), 4.0);
     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()``.
 We can now replace the contents of our ``height()`` function with ``wave()``.
 
 
@@ -279,7 +300,8 @@ Using this, you get:
 
 
 .. image:: img/wave1.png
 .. 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
 .. code-block:: glsl
 
 
@@ -293,11 +315,13 @@ Now it looks much better.
 .. image:: img/wave2.png
 .. image:: img/wave2.png
 
 
 We can do even better if we layer multiple waves on top of each other at varying
 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
 .. 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;
     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
 With this code you should end up with more complex looking waves and all you had
 to do was add a bit of math!
 to do was add a bit of math!
 
 
 .. image:: img/wave3.png
 .. 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.