BS Contact VRML/X3D
 Release 7.0

DirectX9 Shader Support


Shader FX   Screen shot   Execute

BS Contact VRML/X3D 6.2 supports programmable shaders. The node implementation follows the first X3D Programmable Shaders Proposal. This proposal has been changed for the in progress X3D / AMD1 (shader fields added to Appearance). The basic ShaderNode concept in AMD1 is the same, so that content can easily be changed to X3D/AMD1 one this is finalized.

Shaders are supported with the BS Contact DirectX 9 renderer. The supported shader protocol is High Level Shader Language (HLSL):, the cg: protocol is treated as HLSL. Supported shader file extensions are : vhl phl and HLSL.

Shaders are tiny programs written in a javascript / c like language, which are running natively on the graphics card.
Vertex Shaders are called for each vertex data tuple (position, normal, vertexColor, texture coord 0 .. n). Their outputs are per vertex parameters which are linear interpolated across each pixel of each triangle of a mesh.
Likewise a Fragment Shader (or Pixel Shader in DirectX speak) gets executed on each pixel, the input is the interpolated set of parameters, the output is the final color to be passed on to the frame buffer.

Minimally the Vertex Shader needs to output the right screen position for a vertex, and the fragment shader a color value.

FX Support

In addition to the proposal, BS Contact VRML/X3D also supports the Direct X 9 FX file format. The FX script is specified in a VertexShader using the fx: protocol or the fx file extension. FX files may contain vertex and/or pixel shaders.


Shape {
  appearance ShaderAppearance {
    vertexShader  VertexShader
      url "HLSL/BumpReflectHLSL.fx"
      exposedField SFNode normalMap ImageTexture { url "HLSL_textures/" }
      exposedField SFNode cubeMap   ImageTexture { url "HLSL_textures/" }

    # fallback
    material Material {
      ambientIntensity 0.416667
      diffuseColor 0.6 0.6 0.6
      specularColor 0.4 0.4 0.4
      shininess 0.2
  geometry  IndexedFaceSet {

Some benefits of FX files are :

For FX Files BS Contact VRML/X3D parses the semantic string associated with shader parameters and automatically fills in known parameters semantic with state runtime parameters. Most of the parameters of the NVidia FX-Composer / DirectX 9 EffectEdit example are supported. Here is the list of parameters.

If multiple techniques are declared in the FX script, the first supported by the hardware is selected.

The major drawback of FX files is that there is currently support in Direct X 9 only, and that no emulation for Open GL is provided. Some tools like Discreet 3D Studio Max 6 are supporting FX files.

Required Hardware

The latest DirectX 9 class hardware supports more advanced shader models, older hardware (DirectX 8 Level) much simpler profiles named vs_1_1 ps_1_3 / ps_1_4 with more limitations in the amount of instructions and capabilities. DirectX7 class hardware has no shader support.
BS Contact VRML/X3D tries to compile the shader script against the supported hardware level, but this compilation may fail. The author can give fallback less complex shader scripts. In FX fallback techniques can be provided. Finally the author can define the standard Appearance node fields as fallbacks.



The following nodes are providing the programmable Shader support

ShaderAppearance - replacement for the Appearance node

VertexShader - for setting the per vertex shader script

FragmentShader - for setting the per fragment (pixel) shader script

For the Node specification see the proposal:

Example: the VertexShader computes the basic lighting model, the FragmentShader applies a 2D texture:

ShaderAppearance {
  vertexShader  DEF VertexShader1 VertexShader
    field SFVec3f  lightDir 0.577 -0.577 0.577
    # any needed parameters can be mapped to fields here
    url "hlsl:

    // light intensity
    float4 I_a : LIGHTAMBIENT  = { 0.1f, 0.1f, 0.1f, 1.0f };    // ambient
    float4 I_d : LIGHTDIFFUSE  = { 1.0f, 1.0f, 1.0f, 1.0f };    // diffuse
    float4 I_s : LIGHTSPECULAR = { 1.0f, 1.0f, 1.0f, 1.0f };    // specular

    float3 lightDir : LIGHTDIRECTION = {0.577, -0.577, 0.577};

    // material reflectivity
    float4 k_a : MATERIALAMBIENT = { 1.0f, 1.0f, 1.0f, 1.0f };    // ambient
    float4 k_d : MATERIALDIFFUSE = { 1.0f, 1.0f, 1.0f, 1.0f };    // diffuse
    float4 k_s : MATERIALSPECULAR= { 0.0f, 0.0f, 1.0f, 1.0f };    // specular
    float  n   : MATERIALPOWER = 32.0f;                           // power

    // transformations

    // BS Contact VRML/X3D built-ins
	float4x4 modelViewProjectionT;
	float4x4 modelViewT;
	float4x4 modelT;

    struct VS_OUTPUT
      float4 Pos  : POSITION;
      float4 Diff : COLOR0;
      float4 Spec : COLOR1;
      float2 Tex  : TEXCOORD0;

    VS_OUTPUT main (
      float3 Pos  : POSITION,
      float3 Norm : NORMAL,
      float2 Tex  : TEXCOORD0
      VS_OUTPUT Out = (VS_OUTPUT)0;

      Out.Pos  = mul(float4(Pos, 1),modelViewProjectionT);   // position (projected)

      float3 L = -lightDir;
      float3 P = mul(float4(Pos, 1), (float4x3)modelViewT);  // position (view space)
      float3 N = normalize(mul(Norm, (float3x3)modelViewT)); // normal (view space)

      float3 R = normalize(2 * dot(N, L) * N - L);          // reflection vector (view space)
      float3 V = -normalize(P);                             // view direction (view space)

      Out.Diff = I_a * k_a + I_d * k_d * max(0.0f, dot(N, L)); // diffuse + ambient
      Out.Spec = I_s * k_s * pow(max(0, dot(R, V)), n/4);   // specular
      Out.Tex  = Tex;

      return Out;

  fragmentShader DEF FragmentShader1 FragmentShader
    field SFNode texture0 ImageTexture {
      url [ "../textures/maps/chromic.jpg" ]

    url "hlsl:
    const sampler2D texture0;

    float4  main(
      float4 Position : POSITION,
      float4 Diffuse  : COLOR0,
      float4 Specular : COLOR1,
      float2 Tex  : TEXCOORD0
    ) : COLOR
      return Diffuse*(0.5+0.5*tex2D(texture0,Tex))+Specular;

  # fallback
    texture ImageTexture {
      url [ "../textures/maps/chromic.jpg" ]

  material Material {
    ambientIntensity 0.416667
    diffuseColor 0.6 0.6 0.6
    specularColor 0.8 0.8 1
    shininess 0.4


If not done yet please activate the BS Contact DirectX 9 Renderer using right mouse click->Settings->Renderer->DirectX 9

The examples can be downloaded in one large zip file. (25 MB)

HLSL getting started

FX Examples

The following examples are using the DirectX 9 FX effect file format in the VertexShader.

Adapted NVIDIA FX Composer examples:
See the FX file for different per pixel lighting effects.', 'images/teapot_fx_plastic.jpg', 'fxcomposer/HLSL/PlasticDX9.fx'); ?> Tangents and Binormals are computed via TextureCoordGen node.', 'images/teapot_fx_bumpplastic.jpg', 'fxcomposer/HLSL/BumpPlastic.fx'); ?> Diffuse and Normal map. Tangents and Binormals are computed via TextureCoordGen node.", 'images/BumpPlastic.jpg', 'fxcomposer/HLSL/BumpPlastic.fx'); ?> Tangents and Binormals are computed via TextureCoordGen node.', 'images/teapot_fx_bumpreflect.jpg', 'fxcomposer/HLSL/BumpPlastic.fx'); ?> m17design.', 'images/m17_sml.jpg', 'M17_WaterShaderApp/waterRTT.fx'); ?>

Above shaders are reaching the pixelshader speed limit of today best graphics boards. One will notice the performance drop off if zooming close or making the window large.

Only minimal changes need to be done to fx files, the vertex format has been changed to use TEXCOORD channels for Tangents and Binormals, in Plastic the sign of the normal has been changed. It is important to specify the used textures as SFNode ImageTexture parameters in the shader interface. See below for more conversion tips.

Examples adapted from the DX9 SDK
Other examples:
/fur.fx">fur.fx computes 15 layers of transparent offsets using a VertexShader.', 'images/teapot_shader_fx_fur.jpg', 'fur.fx'); ?>
Volume Texture (ps 1.1 / vs 1.1)
3D Volume Texture (CT Scan of Head) on a stack of planes with control of layer blending. Run
Screenshot   Execute

volume_texture 3D Volume Texture (CT Scan of Head) on a stack of planes with control of layer blending.

Video Effects

The examples may need some time to download the used video. (Normal video)

Several Video shaders (ps 2.0)
Several video shaders. Run
Screen shot   Execute

Examples from the X3D proposal

Only some minor changes like matrix parameter naming have been applied:

/fred_part1.wrl">Fred from Protozoa with plastic per pixel lighting.', 'images/fredShaderOpt.jpg', NULL); ?>

Tips & Hints

Using VertexShaders means the author is responsible for doing Lighting (Lights & Material, vertex colors ), Transform, TextureTransform , TextureCoordGen and Fog. The ATI provided fixedfunc.fx file might help to study how to (re-)implement that functionality. The values of VRML Material node can now be passed to a FX Shader using the MATERIAL semantic on a Material structure.

Using FragmentShaders means the author is responsible for Coloring, Texturing and MultiTexture. Even worse on some type of typical hardware shaders might run slower than the fixed function pipeline.

Blending, Fog interpolation, Z-Test, Stencil, Color masking etc. happens after the output from the fragment shaders. However Pixelshader will benefit from early z-culling, e.g. by drawing close by objects earlier. (QuadTree, OctTree, BspTree). If using FOG the FOG coordinated value need to be computed in the VertexShader.

The option "verbose VRML Warnings" should be enabled in the Settings->General tab to see all warning and error messages from the shader compiler. Shader files can be edited with any text editor. Using EffectEdit FXComposer or Rendermonkey has the benefit off on the fly syntax check and compilation of the shader.

Using BS Contact VRML/X3D with VRMLPad gives also a quick turn around time during development.

Some techniques like per pixel Bump mapping are using Tangents and Binormals per Vertex vectors, these vectors can be generated as 3D TextureCoordinates using :

MultiTextureCoordinate {
    TextureCoordinate {point [ ... ] }
    TextureCoordGen { mode "TANGENT" parameter [ 0 2 ] }

This will compute Tangent vectors based on Texture coordinate channel 0, binormal vectors will be placed in texture coordinate channel 2 of the IFS. Another way is to directly set a VRML Normal node with pre computed Tangent vectors as a TextureCoordinate. Likewise using a Coordinate node to specify 3 component texture coordinates is supported.

BS Contact VRML/X3D 6.2 implements the SFVec4f field type for match with float4/half4 texture parameters and the SFMatrix field type.

The supported shader profiles can be queried from vrmlscript via:


There is currently no cross language standard for associating per shader parameters with a specific meaning. The proposal defines some strings. In HLSL a semantic value can be associated with parameters.

Writing Shaders for non DX9 class hardware is possible but very tricky. Usually Texture lookups are used instead computations like normalize. See papers / examples on the ATI and NVidia developer sites for tips and examples. (Often in Shader assembly language).

If using the same or similar procedural textures across several shaders resources it could be better to DEF & USE the texture resources. Examples could be normalization cube maps, noise volume maps. The fx file may generate large 3D noise textures, which can be slow at initialization time. A common 3D noise DDS volume could be shared across shaders.

If a Shader parameter need not to be tweaked from VRML it can be omitted from the Shader field interface, which minimizes runtime shader parameter setup. Even further the preprocessor can be used (DEFINE ) or parameters can be made static const, for possible shader compiler optimizations.

A good debugging technique is to early exit from a pixel shader using a partly evaluated result or some (normal) vectors for visual debugging.

The DirectX Shader compiler optimizes scripts, ie. the BS Contact VRML/X3D Warning : "Shader parameter field 'XXX' not found in shader : might occur beside of misspelling if the compiler has optimized away parameters because they not used in a shader. Contact currently does not verify if the associations of VRML shader field types matches the parameter data type (i.e. passing a string to a float4 parameter.)

The ShaderApperance node is allowing fallback implementation using the material, texture and textureTransform fields if a shader fails or is not present. In HLSL and DirectX9 a VertexShader and FragmentShader can be set independently and can be NULL. For a NULL VertexShader and a NON NULL FragmentShader a X3D MultiTextureTransform node for the textureTransform can be used to set the texture transformation.

In the default pipeline Contact does not draw fully transparent geometry, in the shader case Contact can not apply this optimization and the author may need to use a Switch node do disable geometry. If in the shader case the author needs the Contact transparency processing the transparent true hint should be set in the ShaderAppearance node, likewise DrawGroup with sortedAlpha FALSE can be used to manually sort Shapes for drawing order.

It should be noted that CompositeTexture (RenderToTexture) is fully supported for use with shaders. As well as using MovieTextures, something no other shader tool currently can do.

For NVidia Geforce FX class hardware study NVidia white papers and example to optimize shaders (e.g. using the half data type instead of float) to tweak performance.

Known Problems: Using HLSL the first parameter global seems to be lost sometimes, its unclear yet if this is a HLSL compiler bug.

Converting FX Composer Files

FX files can be previewed and edited in NVidia FX Composer. The FX files can be used directly in BS Contact VRML/X3D.

Some steps might be necessary:

All filename texture references need to be added as SFNode parameters to the Shader interface

FX File :

texture diffuseMap : DIFFUSE
   string ResourceName = "";
   string TextureType = "2D";

VRML File:

 Shape { appearance
   	vertexShader VertexShader
	   	url "HLSL/BumpPlastic.fx"
	   	exposedField SFNode diffuseMap ImageTexture { url ""    }

Parameters you want to tweak from VRML can be added:

	field SFVec4f LightPos 1 0.5 2 0
	field SFFloat Bumpy 5

If the Vertex shader requires Tangent / Binormal vertex attributes replace the declaration with TEXCOORD1 TEXCOORD 2


struct a2v {
   float4 Position : POSITION; //in object space
   float3 Normal : NORMAL; //in object space
   float3 TexCoord : TEXCOORD0;
   float3 Tangent : TANGENT0; //in object space
   float3 Binormal : BINORMAL0; //in object space
struct a2v {
   float4 Position : POSITION; //in object space
   float3 Normal : NORMAL; //in object space
   float3 TexCoord : TEXCOORD0;
   float3 Tangent : TEXCOORD1; // TANGENT0; //in object space
   float3 Binormal : TEXCOORD2; // BINORMAL0; //in object space

and add as texCoord field

MultiTextureCoordinate { 
coord [ TextureCoordinate { ** existing ones *** } TextureCoordGen { mode "TANGENT" parameter [ 0 2 ] } ]

to the IndexedFaceSet.

For compatibility with ATI cards the shader profiles in the FX file can be lowered if applicable from the Geforce FX supported ps_2_a and vs_2_a to ps_2_0 and vs_2_0.

Even if position is passed as float3 by BS Contact VRML/X3D using float4 Position in the vertex shader input declaration works fine.

If shader needs special input like Time a TimeSensor and a ROUTE need to be added to the VRML file, likewise for mouse positions a PlaneSensor etc.

#include is not supported (it works in the local file case), in an Internet context it would require downloading of HTTP resources, which is not implemented for include statements in FX files.


Parameter Mapping

There is currently no cross language standard for associating per shader parameters with a specific meaning. The X3D proposal defines some strings. In FX HLSL a semantic value can be associated with parameters as a string. For FX file Contact recognizes known semantic values, but in the HSLSL case unfortunately this string is not available from the Microsoft D3DX Shader runtime. Therefore in extension to the X3D proposed Shader parameter keywords strings BS Contact VRML/X3D uses the following state parameter values :

Variable name
FX semantic string
Data type Description Comments


the matrix transforming from local to global coordinates (named WORLDMATRIX in the DX world, modelMatrix in the Open GL world) transforms vertices from their model position to their position in world space (i.e. after effect of all Transform nodes has been applied).
view   the viewing matrix transforming from global (world) to view relative coordinates  
projection   the projection matrix transforming from viewing relative to clip space and includes the projective part.  
modelView   concatenation of model and view transforms vertices from their model position to their position in view space (i.e. after effect of all Transform nodes and current viewpoint has been applied).
viewProjection   concatenation of view and projection transforms vertices from world position to their final position in clip space
modelViewProjection   concatenation of model, view and projection transforms vertices from their model position to their final position in clip space
Suffixes :      
***I   Inverse of Matrix  
***T   Transpose of Matrix  
***IT   Inverse transpose of matrix  
Vectors float3
viewPosition   Position of the viewer in world coordinates
viewPositionLocal   Position of the viewer in local coordinates
viewTarget   Target position of camera  
viewUp   up direction vector (normalized vector)
viewDirection   view direction vector  
viewRight   right pointing vector  
viewFovY float field of view in Radians  
viewZRange float2 / float4 znear, zfar clipping values  
float the current pass index of an FX effect 0 for first pass
viewportPixelSize float2 size of viewport in pixels  
time float current event time  
lasttime float time of last frame  
random float random number in 0..1  
MATERIAL // define material structure
struct Material
{ // matches D3DMATERIAL9
float4 diffuseColor;
float4 ambientColor;
float4 specularColor;
float4 emissiveColor;
float power;
the values from the VRML Material node in the ShaderAppearance node converted to D3D convention, transparency alpha goes to diffuseColor[3]

Example material variable in shader

Material material : MATERIAL = {
float4(1.0f, 0.0f, 1.0f, 1.0f), //diffuse
float4(0.0f, 0.0f, 0.0f, 0.0f), //ambient
float4(0.0f, 0.0f, 0.0f, 0.0f), //specular
float4(0.0f, 0.0f, 0.0f, 0.0f), //Emissive

In addition Contact uses the equivalent NVidia FX Composer semantic values.

Matrices are normally passed in the transposed form because that fits the layout of the intrinsic mul(vector,matrix) multiplication macros. In the HLSL examples the parameter name modelViewProjectionT is used to transform a vertex from model space to clip space ("screen"). The transposed modelViewProjection matrix is passed by BS Contact VRML/X3D. In the cg examples using the intrinsic mul(matrix,vector) the standard non-transposed matrix is passed.

The paramName paramType in the Shader Node can be used to remap the semantic of parameters




This associates the meaning WVPMATRIX with the shader parameter view_proj_matrix.



More Info

Programmable HLSL Shaders in the Microsoft DirectX 9 SDK

HLSL Workshop

Web3d X3D Shaders Group



Shader X2, Wolfgang Engel

Useful tools


ATI Rendermonkey - a GUI tool for editing, previewing effects ( recommended)

In version 1.5 for RenderMonkey the FX export is improved. An RenderMonkey workspace may contain several different effect techniques, best is to export only a workspace with a single effect.

Goncalo Nuno M. de Carvalho is working on a C++ tool and an xslt transform transforming RenderMonkey rfx XML files to X3D.

NVidia FX Composer Shader tool using FX files directly ( recommended). BS Contact VRML/X3D supports most of the FX parameter semantic conventions. Porting of FX files to BS Contact VRML/X3D requires minimum effort.

Shaderworks - a great nice GUI tool for creating DX FX effects using a component editor, but currently in early alpha state (anyway recommended!)


NVidia tools for Maya - Nivida Site, Exchange on CG shaders, example shaders

cg Shaders org - the old NVIDA CG shaders site, example shaders

ATI Ahsli (Advanced Shading Language Interface ) - a tool for converting Renderman shaders to FX / HLSL/ASM, good for studying shader examples.

Microsoft DirectX 9 SDK - SDK Documentation contains HLSL/ASM references and related information

HLSL Workshop - SDK Documentation HLSL workshop

Discreet 3D Studio Max 6 has some FX support.

RT/Zen RT/shader a new Shader editor based on wiring building blocks writing fx files.

OpenGL Shader Designer from Thyphonlabs supporting the OpenGL Shading Language


Overview of graphics boards and Shader Versions

Board Vertex Shader Pixel Shader Remarks
ATI 9000 1.1 1.4  
ATI Radeon 9500 Pro 2.0 2.0  
ATI Radeon 9700 2.0 2.0  
ATI Radeon 9700 Pro 2.0 2.0  
ATI Radeon 9800 PRO 2.0 2.0  
ATI Radeon X800 2.0 2.0  
Nvidia Riva128/TNT2/GF 256/GF2 GTS - -  
Nvidia GF3 1.0 1.1  
Nvidia GeForce4 Ti 4600 1.1 1.3 DX8
Nvidia GeForce FX 2.0 / vs_2_a 2.0+ / ps_2_a  
Nvidia GeForce 6800 3.0 3.0  
Intel Integrated Graphics     DX7
DirectX9 REF Software Driver 3.0 3.0  

For a chip set table see Beyond 3D, for a DX Level table see tom's hardware.

Shader Parameter Semantics Used by Different Tools

Among different Shader "Editors" there is no common convention of associating parameters with runtime semantics. If porting shaders to BS Contact VRML/X3D the semantics strings or variable names in case of HLSL need to be adapted.

NVidia FX Composer

List of parameters


float4x4 projTM : WorldViewProjection;
float4x4 worldTM : World;
float4 eyePos : WorldEyePosition;


ATI Render Monkey

Render Monkey is using the following predefined variables:

See RmPredefinedVariables.txt in the RenderMonkey installation directory

"time_0_X" "RmFloatVariable"
"cos_time_0_X" "RmFloatVariable"
"sin_time_0_X" "RmFloatVariable"
"tan_time_0_X" "RmFloatVariable"
"time_cycle_period" "RmFloatVariable"
"time_0_1" "RmFloatVariable"
"time_0_2PI" "RmFloatVariable"
"cos_time_0_2PI" "RmFloatVariable"
"sin_time_0_2PI" "RmFloatVariable"
"tan_time_0_2PI" "RmFloatVariable"
"viewport_width" "RmFloatVariable"
"viewport_height" "RmFloatVariable"
"viewport_inv_width" "RmFloatVariable"
"viewport_inv_height" "RmFloatVariable"
"random_fraction_1" "RmFloatVariable"
"random_fraction_2" "RmFloatVariable"
"random_fraction_3" "RmFloatVariable"
"random_fraction_4" "RmFloatVariable"

"view_direction" "RmVectorVariable"
"view_position" "RmVectorVariable"

"view_proj_matrix" "RmMatrixVariable"
"view_matrix" "RmMatrixVariable"
"inv_view_matrix" "RmMatrixVariable"
"proj_matrix" "RmMatrixVariable"
"world_view_proj_matrix" "RmMatrixVariable"


Microsoft DirectX 9 SDK Sample EffectEdit

The following semantics are supported in fx files, semantics in red are not supported. Matrices are passed transposed.

Matrix parameters:

Parameters with the WORLD semantic will contain the world matrix
Parameters with the VIEW semantic will contain the view matrix
Parameters with the PROJECTION semantic will contain the projection matrix
Parameters with the WORLDVIEW semantic will contain the world*view matrix
Parameters with the VIEWPROJECTION semantic will contain the view*projection matrix
Parameters with the WORLDVIEWPROJECTION semantic will contain the
world*view*projection matrix

For sampler parameters:
Parameters with the NAME annotation will cause a texture with the given
name to be loaded - not recommeded, an absolute path is used, no HTTP download.

Parameters with the FUNCTION annotation will cause a procedural texture
with the given name to be loaded and used to initialize the texture
Parameters with the TARGET annotation will cause the procedural texture
to use the specified instruction set (Default is "tx_1_0")
Parameters with the WIDTH annotation will cause the texture to have the
specified width
Parameters with the HEIGHT annotation will cause the texture to have the
specified height

An integer parameter named "BCLR" will be used to define the background
color of the scene
A string parameter named "BIMG" will be used to define a background image
for the scene
A string parameter named "XFile" will be used to load an XFile containing
the object to be rendered
A float parameter with the TIME semantic will contain the app time, in seconds

A vector parameter with the CAMERAPOSITION semantic will contain the
camera position, in world space

For example, loading an .fx file with:
float4x4 MyWorld : WORLD;
would tell that the "MyWorld" parameter is the world matrix.

Vector parameters:

materialambient materialdiffuse materialspecular meshradius

Scalar parameters:

materialpower time


ATI, NVidia and Microsoft DirectX Team for providing developer examples and tools.

The X3D Shader Working Group for the node proposal.



© 2002 - 2013 Bitmanagement Software GmbH - All rights reserved.