Pinecoast
 
Basic
Handbag
Cell Phone
Watch
 
Basic 3D Geometry
Messaging
Background
Butterflies
Fog
Color Interpolator
3D Shapes
2D Shapes
Textures
Material
IndexedFaceSet
Layering
Overlay
Shaders 1
Shaders 2
 
     


Using Shaders: 1 The Basics

In recent years, graphics cards have become programmable. The processing on the graphics card to prepare for display on the screen is referred to as the rendering pipeline. This pipeline can be changed at two key points in the process. The programs inserted at these points are referred to as a vertex shader and a fragment shader. This tutorial will give an overview of how shaders can be used within X3D. The code inside the main() program will be treated as a black box. For a more detailed discussion on shaders, the Orange OpenGL Shading Language book is good place to start. The SwirlX3D viewer and other programs support only the OpenGL GLSL shader language.

Shader Example

The following is an example of a vertex program. It's purpose is to set the value of gl_Position and to calculate the variables that will be used later by the fragment program. The three variables NdotL, ReflectVec, ViewVec all have declarations starting with the keyword "varying". This marks them as variables that will be used later by the fragment shader


uniform vec3 LightPosition;   // 0 10 4

varying float NdotL;
varying vec3 ReflectVec;
varying vec3 ViewVec;

void main()
{
    vec3 ecPos    = vec3(gl_ModelViewMatrix * gl_Vertex);
    vec3 tnorm    = normalize(gl_NormalMatrix * gl_Normal);
    vec3 lightVec = normalize(LightPosition - ecPos);
    ReflectVec    = normalize(reflect(-lightVec, tnorm));
    ViewVec       = normalize(-ecPos);
    NdotL         = (dot(lightVec, tnorm) + 1.0) * 0.5;
    gl_Position   = ftransform();
}

In the fragment shader below, the three varying variables from the vertex shader are declared again and used within the program.

uniform vec3 SurfaceColor;  // 0.75 0.75 0.75
uniform vec3 WarmColor;     // 0.6 0.6 0.0
uniform vec3 CoolColor;     // 0.0 0.0 0.6
uniform float DiffuseWarm;  // 0.45
uniform float DiffuseCool;  // 0.45

varying float NdotL;
varying vec3 ReflectVec;
varying vec3 ViewVec;

void main()
{
    vec3 kcool = min(CoolColor + DiffuseCool * SurfaceColor, 1.0);
    vec3 kwarm = min(WarmColor + DiffuseWarm * SurfaceColor, 1.0);
    vec3 kfinal = mix(kcool, kwarm, NdotL);
    vec3 nreflect = normalize(ReflectVec);
    vec3 nview    = normalize(ViewVec);

    float spec = max(dot(nreflect, nview), 0.0);
    spec = pow(spec, 32.0);
    gl_FragColor = vec4(min(kfinal + spec, 1.0), 1.0);
}

In the vertex and fragment programs there are variables declared using the "uniform" keyword. These variables are set within the program using the shaders. In this case that means that these variables are set within the X3D file.

The following is part of an X3D file that uses these two shader programs. Notice that the uniform variables are declared as fields of their respective shader programs. In this case the file extension used for the shader programs is ".txt", but this is not important and can be changed. The basic structure is that a ProgramShader node is placed within the shaders field of the Appearance, and the ProgramShader node contains two ShaderProgram nodes of type "VERTEX" and "FRAGMENT". "VERTEX" is the default value of the type field so it does need to appear in the X3D file.

appearance Appearance {
  shaders
    ProgramShader {
      language "GLSL"
      programs [
        ShaderProgram {
          field SFVec3f LightPosition 0 10 4
          url "vertshader.txt"
        }
        ShaderProgram {
          type "FRAGMENT"
          url "fragshader.txt"
          field SFVec3f SurfaceColor 0.75 0.75 0.75
          field SFVec3f WarmColor 0.6 0.6 0.0
          field SFVec3f CoolColor 0.0 0.0 0.6
          field SFFloat DiffuseWarm 0.45
	      field SFFloat DiffuseCool 0.45
        }
      ]
    }
}

The ComposedShader X3D node can also be used to specify the shader programs. The ComposedShader will have two ShaderPart nodes in its parts field. In this case all the fields corresponding to uniform variables are moved so that they are all fields of the ComposedShader nodes. Apart from this minor difference, the use of ProgramShader or ComposedShader nodes is equivalent. There is no advantage of one over the other.

appearance Appearance {
    shaders ComposedShader {
      language "GLSL"
      field SFVec3f LightPosition 0 10 4

      field SFVec3f SurfaceColor 0.75 0.75 0.75
      field SFVec3f WarmColor 0.6 0.6 0.0
      field SFVec3f CoolColor 0.0 0.0 0.6
      field SFFloat DiffuseWarm 0.45
      field SFFloat DiffuseCool 0.45
      parts [
        ShaderPart {
          url "vertshader.txt"
        }
        ShaderPart {
          type "FRAGMENT"
          url "fragshader.txt"
        }
      ]
    }
}

The previous excerpts are in classic Vrml format. The following shows how the same content looks in Xml style format. The choice of format is usually a matter of personal preference, although the Xml style allows for use within Xml aware programs.

<Appearance>
  <ProgramShader language="GLSL">
    <ShaderProgram url="vertshader.txt">
      <field name="LightPosition" type="SFVec3f" 
             accesstype="initializeOnly" value="0 10 4" /> 
    <ShaderProgram url="fragshader.txt" type="FRAGMENT">
      <field name="SurfaceColor" type="SFVec3f" 
             value="0.75 0.75 0.75" accesstype="initializeOnly"/>
      <field name="WarmColor type="SFVec3f" 
             value="0.6 0 0" accesstype="initializeOnly"/>
      <field name="CoolColor type="SFVec3f" 
             value="0 0.6 0.6" accesstype="initializeOnly"/>
      <field name="DiffuseWarm" type="SFFloat" 
             value="0.45" accesstype="initializeOnly"/>
      <field name="DiffuseCool" type="SFFloat" 
             value="0.45" accesstype="initializeOnly"/>
    </ShaderProgram>
  </ProgramShader>>
</Appearance>

Here is a list of common X3D variable types and their corresponding types within the shader program.

X3D Type
GLSL Type
SFBool
int
SFInt32
int
SFFloat
float
SFDouble
float
SFVec2f
vec2
SFVec2d
vec2
SFVec3f
vec3
SFVec3d
vec3
SFVec4f
vec4
SFVec4d
vec4
SFMat3f
mat3
SFMat3d
mat3
SFMat4f
mat4
SFMat4d
mat4
SFString
sampler1D
SFString
sampler2D
SFString
sampler3D
SFString
samplerCube
SFString
sampler1DShadow
SFString
sampler2DShadow















.

The sampler variable types are for various types of textures and will be discussed in the next tutorial. It may be a considerable challenge to learn about shaders, but they open up a great many possibilities.

Download tutorial files (same as previous tutorial)



     
 
 

SwirlX3D Viewer


The SwirlX3D Viewer is a free standalone application for viewing VRML, X3D. It also displays sw3d archives created by the SwPublish program.
The professional version also displays files from other formst such as Collada(DAE), 3DS, OBJ, PLY, STL and IGES (IGS).
For more details ...

 

SwTranslator for VRML, X3D and Collada


The SwTranslator can export VRML, X3D, Collada(DAE), 3DS, OBJ, PLY, STL or IGES files to VRML, X3D or Collada. For X3D this offers a migration path for importing high quality 3D models from a variety of sources. For Collada, it offers an opportunity to bring geometry and animation into this increasingly popular format.
For more details ...