FreeX3D User Programmable Shaders

Last update: 11 August 2013


The X3D Specification has given users the ability to define their own Shaders.

As great as this may seem, this facility has introduced issues with platform compatibility.

Below are examples that run on Android and Desktop machines, and below that are some comments on how to write portable code that runs on all FreeWRL library-based platforms.

Specific Examples

There are 4 examples here, showing differing functionality, on different X3D encoding schemes. The X3D files (with shader source code embedded) are available for download - see the comments beside each model for a link.

Click on the images for a full size screenshot captured on a Google Nexus-7.

Image Description
STL 1 Toon Shader.

This is the old SGI Teapot, with a Shader that takes light intensity, and assigns colours based on ranges of intensity. The model is available here for your enjoyment.

To see what the model looks like without the shader, you can get the model here.

STL 1 Fragment Lighting vs. Vertex Lighting

Two Cylinders, rotating around each other, one with per-fragment lighting, the other lit on a per-vertex basis.

Fragment lighting is more time consuming, but sometimes the results are worth it. (run the test to really see the differences in action)

The Android FreeX3D App allows you to set "best" or "fast" rendering; feel free to play around with the settings when viewing your own models so you see for yourself what the trade-offs are for each style of rendering. here is this model.

STL 1 Vertex Deformer

A flat IndexedFaceSet, 20x20 vertices per side, is deformed in the Vertex shader. A TimeSensor feeds in a floating point number, and the Shader moves the vertices according to an algorithm running on the GPU.

This example is in two formats, a "ProgramShader" format here, or written as a "ComposedShader" here.

STL 1 Sobel Edge Detector

An industry-standard image ("Lenna", or "Lena", depending on the reference) used as input to a Sobel Operator for edge finding. The image size (512x512) is hard-coded into the Shader, but it could be passed in as a field.

Here is the file for you to try.

Shader Completeness

ComposedShader, ProgramShader are supported. PackagedShader is not yet supported - it does not fit well with the concepts of OpenGL shaders. However, PackagedShader may make a good way of sending in OpenCL or OpenGL Compute Shaders in a future expansion of this codebase.

Mobile GPUS are very limited in performance as compared to desktop GPUs. As such, much work was expended trying to get shaders running quickly and reliably for almost all scenes on Mobile Devices. There are, however, known holes for uses that are not common amongst X3D programs found in the wild - some MultiTexturing options, for example, are ignored.

GLSL Version Support

GLSL has changed dramatically over the years. The FreeWRL library does its own thing with regards to getting data to/from a running Shader, but there are some hooks that allow on-line (or in-book) examples to work.

On Desktop systems, GLSL Version 1.2 is the target version for user defined Shaders.

On Mobile, using OpenGL ES 2.0 and above, GLSL Version 1.0 for Mobile is targeted. Also on mobile, if "best" rendering is selected, high precision floating point shaders are used, otherwise medium presision is used.

There are #defines for most of the common GLSL variables and functions, such as

	vec4 ftransform() {return vec4 (fw_ProjectionMatrix*fw_ModelViewMatrix*fw_Vertex);}
	#define gl_ModelViewProjectionMatrix (fw_ProjectionMatrix*fw_ModelViewMatrix)
	#define gl_NormalMatrix fw_NormalMatrix
	#define gl_ProjectionMatrix fw_ProjectionMatrix
	#define gl_ModelViewMatrix fw_ModelViewMatrix
	#define gl_Vertex fw_Vertex
	#define gl_Normal fw_Normal
	#define gl_LightSource fw_LightSource
but it is possible that some are not defined, which brings us to:

Behind the Scenes

This section attempts to define how the FreeWRL rendering library uses GLSL for all rendering.

You will note that quite often, a "gl_" uniform will be replaced with a "fw_" uniform; this is to allow the FreeWRL library to work on a wide variety of OpenGL versions, without overloading the built-in Uniforms and functions.

A series of Uniform variables are queried when a Shader is compiled. Here is the current list of queries:

Material Properties:

These fills the following structure:
struct fw_MaterialParameters {
  vec4 emission;
  vec4 ambient;
  vec4 diffuse;
  vec4 specular;
  float shininess;

Matrix Uniforms:

These should be familiar, with "fw_" rather than the usually found "gl_".

uniform mat4 fw_ModelViewMatrix
uniform mat4 fw_ProjectionMatrix
uniform mat3 fw_NormalMatrix
uniform mat4 fw_TextureMatrix


The number of lights differ between desktop and mobile; for desktop system, MAX_LIGHTS is defined as 8, whilst mobile is currently set at 2.

The Headlight is ALWAYS the last light; on desktops with MAX_LIGHTS set to 8, you can use lights 0-6, the Headlight is light 7. Mobile, you can use use light 0; light 1 is the Headlight.

struct fw_LightSourceParameters { 
  vec4 ambient;  
  vec4 diffuse;   
  vec4 specular; 
  vec4 position;   
  vec4 halfVector;  
  vec4 spotDirection; 
  float spotExponent; 
  float spotCutoff; 
  float spotCosCutoff; 
  float constantAttenuation; 
  float linearAttenuation;  
 float quadraticAttenuation; };

uniform fw_LightSourceParameters fw_LightSource[MAX_LIGHTS] /* gl_MaxLights */ ;

For turning lights on/off, or setting the type:


LightState is either "true" or "false", lightType is 0 for PointLight, 1 for SpotLight, and 2 for DirectionalLight. LightRadius is simply the cutoff distance for lights.


Single unit texturing and multi-texturing are handled similarly.

A compile-time constant lets the system determine how many textures can be layered. For mobile devices, it is set quite low, but rarely will one map more than 3 textures together.

So we have:

fw_Texture_unit0 to fw_Texture_unit{n}
fw_Texture_mode0 to fw_Texture_mode{n}

For textureCoordinateGenerators,

which accepts the values of 3 for "Sphere" or 0 for "Reflection". Anything else is currently treated like a CubeMap.

Misc Uniforms

The following lists some others used for points and lines, so are not as useful as those shown above.


FreeX3D History

FreeX3D is a value-added version of FreeWRL. STL layering and model manipulation has been overlaid on the FreeWRL X3D engine.

From circa 1999 to April 2010, the FreeWRL project was managed by John A. Stewart.

There is absolutely no warranty, express or implied for this software. For details on the conditions of use, see the FreeWRL distribution.

FreeWRL is Copyright (C) 1998, 1999...2009 Tuomas J. Lukka, John Stewart and others.

The FreeWRL library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

The FreeWRL library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. Logo