your_first_canvasitem_shader.rst 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. .. _doc_your_first_canvasitem_shader:
  2. Your first CanvasItem shader
  3. ============================
  4. Introduction
  5. ------------
  6. Shaders are special programs that execute on the GPU and are used for rendering
  7. graphics. All modern rendering is done with shaders. For a more detailed description
  8. of what shaders are please see :ref:`doc_introduction_to_shaders`.
  9. This tutorial will focus on the practical aspects of writing shader programs by walking
  10. you through the process of writing a shader with both vertex and fragment functions.
  11. This tutorial targets absolute beginners to shaders.
  12. .. note:: If you have experience writing shaders and are just looking for
  13. an overview of how shaders work in Godot, see the :ref:`Shading Reference <toc-shading-reference>`.
  14. Setup
  15. -----
  16. :ref:`CanvasItem <doc_canvas_item_shader>` shaders are used to draw all 2D objects in Godot,
  17. while :ref:`Spatial <doc_spatial_shader>` shaders are used to draw all 3D objects.
  18. In order to use a shader it must be attached inside a :ref:`Material <class_material>`
  19. which must be attached to an object. Materials are a type of :ref:`Resource <doc_resources>`.
  20. To draw multiple objects with the same material, the material must be attached to each object.
  21. All objects derived from a :ref:`CanvasItem <class_canvasitem>` have a material property.
  22. This includes all :ref:`GUI elements <class_Control>`, :ref:`Sprites <class_sprite>`, :ref:`TileMaps <class_tilemap>`,
  23. :ref:`MeshInstance2Ds <class_meshinstance2d>` etc.
  24. They also have an option to inherit their parent's material. This can be useful if you have
  25. a large number of nodes that you want to use the same material.
  26. To begin, create a Sprite node. You can use any CanvasItem, but for this tutorial we will
  27. use a Sprite.
  28. In the Inspector, click beside "Texture" where it says "[empty]" and select "Load", then select
  29. "Icon.png". For new projects, this is the Godot icon. You should now see the icon in the viewport.
  30. Next, look down in the Inspector, under the CanvasItem section, click beside "Material" and select
  31. "New ShaderMaterial". This creates a new Material resource. Click on the sphere that appears. Godot currently
  32. doesn't know whether you are writing a CanvasItem Shader or a Spatial Shader and it previews the output
  33. of spatial shaders. So what you are seeing is the output of the default Spatial Shader.
  34. Click beside "Shader" and select "New Shader". Finally, click on the new shader resource and the shader
  35. editor will open. You are now ready to begin writing your first shader.
  36. Your first CanvasItem shader
  37. ----------------------------
  38. In Godot, all shaders start with a line specifying what type of shader they are. It uses
  39. the following format:
  40. .. code-block:: glsl
  41. shader_type canvas_item;
  42. Because we are writing a CanvasItem shader, we specify ``canvas_item`` in the first line. All our code will
  43. go beneath this declaration.
  44. This line tells the engine which built-in variables and functionality to supply you with.
  45. In Godot you can override three functions to control how the shader operates; ``vertex``, ``fragment``, and ``light``.
  46. This tutorial will walk you through writing a shader with both vertex and fragment functions. Light
  47. functions are significantly more complex than vertex and fragment functions and so will not be covered here.
  48. Your first fragment function
  49. ----------------------------
  50. The fragment function runs for every pixel in a Sprite and determines what color that pixel should be.
  51. They are restricted to the pixels covered by the Sprite, that means you cannot use one to, for example,
  52. create an outline around a Sprite.
  53. The most basic fragment function does nothing except assign a single color to every pixel.
  54. We do so by writing a ``vec4`` to the built-in variable ``COLOR``. ``vec4`` is shorthand for constructing
  55. a vector with 4 numbers. For more information about vectors see the :ref:`Vector math tutorial <doc_vector_math>`
  56. ``COLOR`` is both an input variable to the fragment function and the final output from it.
  57. .. code-block:: glsl
  58. void fragment(){
  59. COLOR = vec4(0.4, 0.6, 0.9, 1.0);
  60. }
  61. .. image:: img/blue-box.png
  62. Congratulations! You're done. You have successfully written your first shader in Godot.
  63. Now let's make things more complex.
  64. There are many inputs to the fragment function that you can use for calculating ``COLOR``.
  65. ``UV`` is one of them. UV coordinates are specified in your Sprite (without you knowing it!)
  66. and they tell the shader where to read from textures for each part of the mesh.
  67. In the fragment function you can only read from ``UV``, but you can use it in other functions
  68. or to assign values to ``COLOR`` directly.
  69. ``UV`` varies between 0-1 from left-right and from top-bottom.
  70. .. image:: img/iconuv.png
  71. .. code-block:: glsl
  72. void fragment() {
  73. COLOR = vec4(UV, 0.5, 1.0);
  74. }
  75. .. image:: img/UV.png
  76. Using ``TEXTURE`` built-in
  77. ^^^^^^^^^^^^^^^^^^^^^^^^^^
  78. When you want to adjust a color in a Sprite you cannot just adjust the color from the texture
  79. manually like in the code below.
  80. .. code-block:: glsl
  81. void fragment(){
  82. //this shader will result in an all white rectangle
  83. COLOR.b = 1.0;
  84. }
  85. The default fragment function reads from a texture and displays it. When you overwrite the default fragment function,
  86. you lose that functionality, so you have to implement it yourself. You read from textures using the
  87. ``texture`` function. Certain nodes, like Sprites, have a dedicated texture variable that can be accessed in the shader
  88. using ``TEXTURE``. Use it together with ``UV`` and ``texture`` to draw the Sprite.
  89. .. code-block:: glsl
  90. void fragment(){
  91. COLOR = texture(TEXTURE, UV); //read from texture
  92. COLOR.b = 1.0; //set blue channel to 1.0
  93. }
  94. .. image:: img/blue-tex.png
  95. Uniform input
  96. ^^^^^^^^^^^^^
  97. Uniform input is used to pass data into a shader that will be the same across the entire shader.
  98. You can use uniforms by defining them at the top of your shader like so:
  99. .. code-block:: glsl
  100. uniform float size;
  101. For more information about usage see the :ref:`Shading Language doc <doc_shading_language>`.
  102. Add a uniform to change the amount of blue in our Sprite.
  103. .. code-block:: glsl
  104. uniform float blue = 1.0; // you can assign a default value to uniforms
  105. void fragment(){
  106. COLOR = texture(TEXTURE, UV); //read from texture
  107. COLOR.b = blue;
  108. }
  109. Now you can change the amount of blue in the Sprite from the editor. Look back at the Inspector
  110. under where you created your shader. You should see a section called "Shader Param". Unfold that
  111. section and you will see the uniform you just declared. If you change the value in the editor, it
  112. will overwrite the default value you provided in the shader.
  113. Interacting with shaders from code
  114. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  115. You can change uniforms from code using the function ``set_shader_param()`` which is called on the node's
  116. material resource. With a Sprite node, the following code can be used to set the ``blue`` uniform.
  117. ::
  118. var blue_value = 1.0
  119. material.set_shader_param("blue", blue_value)
  120. Note that the name of the uniform is a string. The string must match exactly with how it is
  121. written in the shader, including spelling and case.
  122. Your first vertex function
  123. --------------------------
  124. Now that we have a fragment function, let's write a vertex function.
  125. Use the vertex function to calculate where on the screen each vertex should end up.
  126. The most important variable in the vertex function is ``VERTEX``. Initially, it specifies
  127. the vertex coordinates in your model, but you also write to it to determine where to actually
  128. draw those vertices. ``VERTEX`` is a ``vec2`` that is initially presented in local-space
  129. (i.e. not relative to the camera, viewport, or parent nodes).
  130. You can offset the vertices by directly adding to ``VERTEX``.
  131. .. code-block:: glsl
  132. void vertex() {
  133. VERTEX += vec2(10.0, 0.0);
  134. }
  135. Combined with the ``TIME`` built-in variable, this can be used for simple animation.
  136. .. code-block:: glsl
  137. void vertex() {
  138. // Animate Sprite moving in big circle around its location
  139. VERTEX += vec2(cos(TIME)*100.0, sin(TIME)*100.0);
  140. }
  141. Conclusion
  142. ----------
  143. At their core, shaders do what you have seen so far, they compute ``VERTEX`` and ``COLOR``. It is
  144. up to you to dream up more complex mathematical strategies for assigning values to those variables.
  145. For inspiration, take a look at some of the more advanced shader tutorials, and look at other sites
  146. like `Shadertoy <https://www.shadertoy.com/results?query=&sort=popular&from=10&num=4>`_ and `The Book of Shaders <https://thebookofshaders.com>`_.