From BlenderWiki

Jump to: navigation, search
Note: This is an archived version of the Blender Developer Wiki. The current and active wiki is available on wiki.blender.org.

Shader System Docs

The Custom Shaders Panel

The panel for custom shaders
This is the new panel for custom shaders. Here are what the different options do:
  • Use External Shaders: Use shaders from an external file rather than an internal Text datablock
  • Vertex Shader: The vertex shader to use
  • Geometry Shader: The geometry shader to use
  • Fragment Shader: The fragment shader to use
  • Geometry shader input: The input type for the geometry shader
  • Geometry shader output: The output type for the geometry shader
  • Reload Shaders: Forces the material to be updated, which in turn recompiles the shaders
  • Custom Uniforms: Here users can add/delete/modify custom uniform values to be passed to their shaders


Custom Uniforms

The default values for a new custom uniform

These are the currently supported uniform types:

  • float
  • vec2, vec3, vec4
  • int
  • ivec2, ivec3, ivec4
  • sampler2D

To add a new uniform that will be passed the shader, just press the plus button. This will add uniform with the default name of Uniform and the default type of float.

There are three settings for uniforms:

  • Name: The name of the uniform as it will appear in the shader
  • Type: The datatype of the uniform (Note: changing the type will reset the current value back to 0)
  • Value: The value of the uniform


RNA Values in Shaders

Some properties in the Material's RNA can be accessed in GLSL shaders. To use them use the same name the property has in RNA. The following are currently supported and more can easily be added:
  • diffuse_color
  • specular_color
  • alpha
  • emit
Example fragment shader that uses the diffuse color and alpha values
uniform vec3 diffuse_color;
uniform float alpha;

void main()
{
    gl_FragColor = vec4(diffuse_color, alpha);
}

Setting up a Simple Toon Shader

Here is a quick tutorial on setting up a toon shader. First, we'll need two Text datablocks and a mesh with a material attached to it. For this tutorial I'll use the names "toon_vert" and "toon_frag" for the Text datablocks; however, you can use whatever names you wish.

Put the following code into toon_vert:


varying vec3 varnormal, varpos;

void main()
{
	gl_Position = ftransform();
	varnormal = (gl_NormalMatrix * gl_Normal);
	varpos = (gl_ModelViewMatrix * gl_Vertex).xyz;
}

Put the following code into toon_frag:


varying vec3 varnormal, varpos;

uniform vec3 diffuse_color;
uniform float alpha;

uniform float edge;
uniform float mid;

void main()
{
	vec3 n, lightDir;
	float intensity, factor;
	
	vec4 color = vec4(diffuse_color, alpha);
	
	n = normalize(varnormal);
	lightDir = normalize(gl_LightSource[0].position.xyz - varpos);
	intensity = max(dot(n, lightDir), 0.0);
	
	if (intensity > mid)
		factor = 1.0;
	else if (intensity > edge)
		factor = 0.7;
	else
		factor = 0.0;
	
	gl_FragColor = color *vec4(factor, factor, factor, 1);

}

Now we move onto the Custom Shader panel. For the Vertex Shader select toon_vert and for the Fragment Shader select toon_frag. We won't use a geometry shader in this tutorial. We'll also need the following uniforms:

  • Name: edge Type: float Value: 0.100
  • Name: mid Type: float Value: 0.600

And that should be it, your mesh should now be using a toon shader. If not, some problems could be:

  • Copied the shaders wrong: Check the console for errors
  • Wrong draw mode: Make sure you're in the Texture draw mode
  • Wrong material mode: Make sure you're using GLSL materials

Go ahead and play with the Diffuse and Alpha values in the material panel to adjust the color. You can also play with the edge and mid uniform values to adjust the edges on the toon shader.

Adding a Texture

If you want to take the toon shader example a bit further, you can add a texture into the mix. First, we'll need to make sure we have a UV Layer. You'll also want to make note of the name ("UVTex" by default) as it will be the name of the attribute we'll use in the vertex shader for texture coordinates. You will also need to setup an image texture with the image you want. After you have the image texture, create a new sampler2D custom uniform and set it to the newly created texture. Name it "img". If you want to change the name, make sure to change it in the script too.

Now, here is the new vertex shader to make use of the texture:

// Replace UVTex with the name of the uv texture layer
attribute vec2 UVTex;

varying vec3 varnormal, varpos;
varying vec2 texcoord;

void main()
{
	gl_Position = ftransform();
	varnormal = (gl_NormalMatrix * gl_Normal);
	varpos = (gl_ModelViewMatrix * gl_Vertex).xyz;

	texcoord = UVTex;
}

And the new fragment shader:


varying vec3 varnormal, varpos;
varying vec2 texcoord;

uniform float edge;
uniform float mid;

uniform sampler2D img;

void main()
{
	vec3 n, lightDir;
	float intensity, factor;
	
	vec4 color = texture2D(img, texcoord);
	
	n = normalize(varnormal);
	lightDir = normalize(gl_LightSource[0].position.xyz - varpos);
	intensity = max(dot(n, lightDir), 0.0);
	
	if (intensity > mid)
		factor = 1.0;
	else if (intensity > edge)
		factor = 0.7;
	else
		factor = 0.0;
	
	gl_FragColor = color *vec4(factor, factor, factor, 1);

}

GLSL Crash Course

What follows is an explanation of the shaders available (vertex, fragment and geometry) and what they are used for. Each will also have a simple example. However, this isn't a tutorial on GLSL. You will have to look else where for that.

Support

GLSL vertex and fragment shaders require support for OpenGL 2.0. Wikipedia lists the following cards as supporting OpenGL 2.0:

Radeon 9650, Radeon 9500, Radeon 9500/9550/9600/9700/9800 (Pro, SE, XT), Radeon X1050, Radeon Xpress 200 / 1100, Radeon X300, Radeon X550, Radeon X600/Pro, Radeon X700, Radeon X800 (VE, SE, GT, Pro), Radeon X850, Radeon Xpress 1250, Radeon X1200, Radeon X1250, Radeon 2100, Radeon X1300, X1550, X1600, X1650, X1800, X1900, X1950 (Pro, XT, GT), GeForce 6800, Quadro 600, Qaudro FX 500, Quadro FX 700, Quadro FX 1000, FX 2000, FX 3000, Quadro FX 1400, Quadro FX 1500, Quadro FX 3450, Quadro FX 3500, Quadro FX 4500X2, Quadro FX4500 SDI, and all later cards.

Geometry shaders were introduced in GLSL 1.20, which was in OpenGL 2.1. Wikipedia lists the following cards as supporting OpenGL 2.1 (however, I don't know if they all support the Geometry shader extension):

Radeon HD 2350, GeForce FX (with driver 175.19), GeForce 6000 series, GeForce 7000 series, GeForce Go 7000 series, Quadro FX 4000, Quadro FX 350, Quadro FX 550, Quadro FX 560, Quadro FX 1400, Quadro FX 1500, Quadro FX 5500, and all later cards.

If in doubt, just look for the following strings when the BGE starts up:

Detected GL_ARB_vertex_shader
Detected GL_ARB_fragment_shader
Detected GL_EXT_geometry_shader4

Vertex Shaders

Vertex shaders do operations per vertex. This includes things such as scaling and gathering position information for the fragment shader.

Example (a simple pass-through):

void main()
{
	gl_Position = ftransform();
}

Geometry Shaders

After vertex shaders come geometry shaders. They also operate on the vertex level, however they have access to neighboring geometry and can also create new geometry.

Example (a simple pass-through):

#version 120
#extension GL_EXT_geometry_shader4: enable

void main()
{
	for(int i=0; i<gl_VerticesIn; ++i)
	{
		gl_Position = gl_PositionIn[i];
		EmitVertex();
	}
}

Fragment Shaders

The last shaders are fragment shaders (known as pixel shaders in HLSL). These operate on fragments/pixels. Here is where you'll change the color of your mesh.

Example (color the mesh blue):

void main()
{
	gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
}