GLSL Programming/Blender/Minimal Shader

From Wikibooks, open books for an open world
Jump to: navigation, search
Screen shot of the Blender 2.5 user interface. The large window is a 3D View with an opened Tool Shelf. Above it is a small Info window. In the bottom, right corner is a Properties window. The type of each window can be changed with the icon in its bottom left or top left corner.

This tutorial covers the basic steps to create a minimal GLSL shader in Blender 2.6.

Creating a GLSL Shader[edit]

The steps to specify and run a GLSL vertex and fragment shader are, for example:

  • First, start Blender:
    • Under Windows, start Blender like any other application. Then click in an Info window (by default the top-most line): Window > Toggle System Console in order to see error messages.
    • Under GNU/Linux, start it from a console or terminal, such that you can see error messages. For example, click on Applications > Accessories > Terminal, then type blender and press Return.
    • Under MacOS X, start Blender by right-clicking the application package and select Show Package Contents. Then go to Contents > MacOS and start the blender executable there in order to see error messages.
  • In the Text Editor (click the icon in the bottom left or top left corner of any Blender window to change its type), choose Text > Create Text Block, copy the Python script from below, and give it a name.
  • In the Info window, click Add > Mesh > Cube (or another mesh, or use the default cube).
  • In the 3D View, select the mesh by right-clicking it.
  • For some meshes it makes sense to use smooth shading: in the 3D View choose View > Tool Shelf from the menu (or press t) and click on Object Tools > Shading > Smooth.
  • For some GLSL shaders it is necessary to set Viewport shading to Textured: in the 3D View select Textured in the widget next but one to the right of the menu.
  • For some GLSL shaders it is necessary to activate GLSL shading: in the 3D View choose View > Properties from the menu (or press n) and choose Display > Shading > GLSL.
  • In the Logic Editor (with the mesh still being selected), click Add Sensor > Always and give it a name.
  • In the Logic Editor, click Add Controller > Python, give it a name, and set the Script to the name of the Python script that you chose in the Text Editor.
  • In the Logic Editor, connect the sensor to the controller by dragging and dropping a connection from the small disk to the right of the sensor to the small disk to the left of the controller.
  • In the 3D View, press p (for “play”) to start the game engine and see the effect of the shader, which should render the object in full red.
    Alternatively, you could also go to the Info window and choose “Blender Game” (instead of “Blender Render”) as engine; and then go to the Properties window, select the Render tab (the camera icon) and click the Start button under Embedded Player.
  • If the GLSL program didn't compile or link, error messages are printed to the console.
  • Press Esc to stop the game engine.
  • Be happy about your first GLSL shader!

And here is the Python script:

import bge
 
cont = bge.logic.getCurrentController()
 
VertexShader = """
   void main() // all vertex shaders define a main() function
   {
      gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
         // this line transforms the predefined attribute gl_Vertex 
         // of type vec4 with the predefined uniform 
         // gl_ModelViewProjectionMatrix of type mat4 and stores 
         // the result in the predefined output variable gl_Position 
         // of type vec4. (gl_ModelViewProjectionMatrix combines 
         // the viewing transformation, modeling transformation and 
         // projection transformation in one matrix.)
   }
"""
 
FragmentShader = """
   void main()
   {   
      gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
         // this fragment shader just sets the output color to opaque
         // red (red = 1.0, green = 0.0, blue = 0.0, alpha = 1.0)
   }
"""
 
mesh = cont.owner.meshes[0]
for mat in mesh.materials:
    shader = mat.getShader()
    if shader != None:
        if not shader.isValid():
            shader.setSource(VertexShader, FragmentShader, 1)

(If you are aware of easier ways to set the shaders for individual objects, please feel free to edit this page.)

Editing Shaders[edit]

This would be a good time to play with the shader; in particular, you can easily change the computed fragment color. Try neon green by opening the Python script in the Text Editor and replacing the fragment shader with this code:

   // this fragment shader should be assigned 
   // to "FragmentShader" in the script above
 
   void main()
   {   
      gl_FragColor = vec4(0.6, 1.0, 0.0, 1.0); 
         // red, green, blue, alpha
   }

You have to start the game engine again to apply the new shader; see above. The color should now be green. You could also try to modify the red, green, and blue components to find the warmest orange or the darkest blue. (Actually, there is a movie about finding the warmest orange and another about dark blue that is almost black.)

You could also play with the vertex shader, e.g. try this vertex shader:

   // this vertex shader should be assigned 
   // to "VertexShader" in the script above
 
   void main() 
   {
      gl_Position = gl_ModelViewProjectionMatrix * 
         (vec4(1.0, 0.1, 1.0, 1.0) * gl_Vertex);
   }

This flattens any input geometry by multiplying the y coordinate with 0.1. (This is a component-wise vector product; for more information on vectors and matrices in GLSL see the discussion in “Vector and Matrix Operations”.)

In case the shader does not compile, Blender displays an error message in a console as described above:

Blender Game Engine Started
---- Vertex Shader Error ----
0:4(83): error: syntax error, unexpected ')', expecting ',' or ';'

---- Vertex shader failed to compile ----
Blender Game Engine Finished


Saving Your Work in a Scene[edit]

There is one more thing: you should save you work in a Blender file (the extension is .blend). Choose File > Save As ... from the menu of an Info window. (Remember that you can change the type of any Blender window with the icon in the top left or bottom left corner of the window).

One More Note about Terminology[edit]

It might be good to clarify the terminology. In GLSL, a “shader” is either a vertex shader or a fragment shader. The combination of both is called a “program”.

Unfortunately, Blender refers to this kind of program as a “shader” while a vertex shader is called a “vertex program” and a fragment shader is called a “fragment program”.

To make the confusion perfect, I'm going to use the word “shader” for a GLSL program, i.e. the combination of a vertex and a fragment shader. However, I will use the GLSL terms “vertex shader” and “fragment shader” instead of “vertex program” and “fragment program”.

Summary[edit]

Congratulations, you have reached the end of this tutorial. A few of the things you have seen are:

  • How to create a Python script that specifies a GLSL shader in Blender.
  • How to activate that Python script for specific objects.
  • How to manipulate the ouput color gl_FragColor in the fragment shader.
  • How to transform the input attribute gl_Vertex in the vertex shader.

Actually, this was quite a lot of stuff.

Further Reading[edit]

If you still want to know more


< GLSL Programming/Blender

Unless stated otherwise, all example source code on this page is granted to the public domain.