Overview
When you display your 3D models with X_ITE, by default it will use the Gouraud shader. This is a versatile shader that can cover a lot of your rendering needs. If this is not enough there is also a Phong shader available, adjustable with the browser option »Shading« per scripting.
However, you will often want to perform special effects or special cases for your materials. To do this you will need to write a custom shader.
Example
Download ZIP Archive
Shaders and Shader Definition
WebGL uses the GLSL language to write shaders that can be run across all browsers. With X_ITE you create your own shader using ComposedShader and ShaderPart nodes and than attach the ComposedShader to the shader field of an Appearance node and that is a child’s play with Sunrize.
XML Encoding
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
| <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 4.0/EN" "https://www.web3d.org/specifications/x3d-4.0.dtd">
<X3D profile='Interchange' version='4.0' xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation='https://www.web3d.org/specifications/x3d-4.0.xsd'>
<head>
<component name='Shaders' level='1'/>
</head>
<Scene>
<Viewpoint
position='9.279771 8.706816 16.22163'
orientation='-0.83432609774564 0.526445494105168 0.163569876068002 0.712985187365762'
centerOfRotation='4.5 0 4.5'/>
<TimeSensor DEF='Timer'
loop='true'/>
<Transform>
<Shape>
<Appearance>
<ImageTexture
url='"image.png"'/>
<ComposedShader DEF='Shader'
language='GLSL'>
<field accessType='inputOnly' type='SFTime' name='set_time'/>
<ShaderPart>
<![CDATA[data:x-shader/x-vertex,#version 300 es
// Vertex Shader
...
uniform float set_time; // value from set_time field
...
]]>
</ShaderPart>
<ShaderPart
type='FRAGMENT'>
<![CDATA[data:x-shader/x-fragment,#version 300 es
// Fragment Shader
...
uniform sampler2D x3d_Texture2D [1]; // image from ImageTexture node
...
]]>
</ShaderPart>
</ComposedShader>
</Appearance>
<ElevationGrid
xDimension='10'
zDimension='10'/>
</Shape>
</Transform>
<ROUTE fromNode='Timer' fromField='elapsedTime' toNode='Shader' toField='set_time'/>
</Scene>
</X3D>
|
Classic VRML Encoding
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
| #X3D V4.0 utf8
PROFILE Interchange
COMPONENT Shaders : 1
Viewpoint {
position 9.279771 8.706816 16.22163
orientation -0.83432609774564 0.526445494105168 0.163569876068002 0.712985187365762
centerOfRotation 4.5 0 4.5
}
DEF Timer TimeSensor {
loop TRUE
}
Transform {
children Shape {
appearance Appearance {
texture ImageTexture {
url "image.png"
}
shaders DEF Shader ComposedShader {
inputOnly SFTime set_time
language "GLSL"
parts [
ShaderPart {
url "data:x-shader/x-vertex,#version 300 es
// Vertex Shader
...
uniform float set_time; // value from set_time field
...
"
}
ShaderPart {
type "FRAGMENT"
url "data:x-shader/x-fragment,#version 300 es
// Fragment Shader
...
uniform sampler2D x3d_Texture2D [1]; // image from ImageTexture node
...
"
}
]
}
}
geometry ElevationGrid {
xDimension 10
zDimension 10
}
}
}
ROUTE Timer.elapsedTime TO Shader.set_time
|
Once the X3D is defined we can now write the vertex and the fragment shader source. This is a simple example where a texture is applied to the geometry.
Vertex Shader
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| #version 300 es
precision mediump float;
// Specify build-in uniforms and ins:
uniform mat4 x3d_TextureMatrix [1];
uniform mat4 x3d_ModelViewMatrix;
uniform mat4 x3d_ProjectionMatrix;
in vec4 x3d_TexCoord0;
in vec4 x3d_Vertex;
// Out for fragment shader:
out vec4 texCoord;
// Uniforms from user-defined fields:
uniform float set_time; // value from set_time field
// main:
void
main ()
{
texCoord = x3d_TextureMatrix [0] * x3d_TexCoord0;
// Animate vertex along x-axis.
gl_Position = x3d_ProjectionMatrix * x3d_ModelViewMatrix * (x3d_Vertex + vec4 (set_time % 1.0, 0.0, 0.0, 0.0));
}
|
Fragment Shader
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| #version 300 es
precision mediump float;
// Specify build-in uniforms and ins:
uniform sampler2D x3d_Texture2D [1];
in vec4 texCoord;
// Specify build-in out:
out vec4 x3d_FragColor;
// main:
void
main ()
{
// Use color from texture.
x3d_FragColor = texture (x3d_Texture2D [0], vec2 (texCoord .s, 1.0 - texCoord .t));
}
|
Lighting and Transparency
Lighting is enabled if a Material node is used and some lights are on.
Normally the browser automatically determines the alpha treatment based on material, colors, and images, but you can force a alpha mode by setting the alphaMode field of a Appearance node.
Data Type Mapping
A ComposedShader node provides the capability to define custom fields like the Script node it does, these fields are then mapped to GLSL uniform variables. They are automatically updated and can be of any access type (initializeOnly, inputOnly, outputOnly or inputOutput).
Node fields
X3D texture type | GLSL variable type |
---|
X3DTexture2DNode | sampler2D |
X3DTexture3DNode | sampler3D |
X3DEnvironmentTextureNode | samplerCube |
X3D field types to GLSL data types
X3D field type | GLSL variable type | |
---|
SFBool | bool | |
SFColor | vec3 | |
SFColorRGBA | vec4 | |
SFDouble | float | |
SFFloat | float | |
SFImage | int [ ] | (width, height, comp, array) |
SFInt32 | int | |
SFMatrix3d | mat3 | |
SFMatrix3f | mat3 | |
SFMatrix4d | mat4 | |
SFMatrix4f | mat4 | |
SFNode | see node fields table | |
SFRotation | mat3 | 3×3 matrix representation |
SFString | not supported | |
SFTime | float | |
SFVec2d | vec2 | |
SFVec2f | vec2 | |
SFVec3d | vec3 | |
SFVec3f | vec3 | |
SFVec4d | vec4 | |
SFVec4f | vec4 | |
|
MFBool | bool [ ] | |
MFColor | vec3 [ ] | |
MFColorRGBA | vec4 [ ] | |
MFDouble | float [ ] | |
MFFloat | float [ ] | |
MFImage | int [ ] | (width, height, comp, array, width ...) |
MFInt32 | int [ ] | |
MFMatrix3d | mat3 [ ] | |
MFMatrix3f | mat3 [ ] | |
MFMatrix4d | mat4 [ ] | |
MFMatrix4f | mat4 [ ] | |
MFNode | see node fields table | |
MFRotation | mat3 [ ] | 3×3 matrix representation |
MFString | not supported | |
MFTime | float [ ] | |
MFVec2d | vec2 [ ] | |
MFVec2f | vec2 [ ] | |
MFVec3d | vec3 [ ] | |
MFVec3f | vec3 [ ] | |
MFVec4d | vec4 [ ] | |
MFVec4f | vec4 [ ] | |
Built-in Variables
A ComposedShader defines a number of special variables for the various shader stages. These built-in variables have special properties. They are usually for communicating with certain fixed-functionality. By convention, all predefined variables start with »x3d_«; no user-defined variables may start with this.
Type | Name | Comment |
---|
uniform float | x3d_LogarithmicFarFactor1_2 | this is a uniform value for logarithmic depth buffer computed as 1.0 / log2 (farPlane + 1.0). |
|
uniform vec4 | x3d_ClipPlane [x3d_MaxClipPlanes] | clip plane array |
uniform x3d_FogParameters | x3d_Fog | see table »Uniform Struct x3d_FogParameters« |
|
uniform x3d_LightSourceParameters | x3d_LightSource [x3d_MaxLights] | see table »Uniform Struct x3d_LightSourceParameters« |
|
uniform float | x3d_AlphaCutoff | alphaCutoff value from Appearance |
uniform x3d_PointPropertiesParameters | x3d_PointProperties | see table »Uniform Struct x3d_PointPropertiesParameters« |
uniform x3d_LinePropertiesParameters | x3d_LineProperties | see table »Uniform Struct x3d_LinePropertiesParameters« |
uniform x3d_FillPropertiesParameters | x3d_FillProperties | see table »Uniform Struct x3d_FillPropertiesParameters« |
|
uniform x3d_MaterialParameters | x3d_Material | see table »Uniform Struct x3d_MaterialParameters« |
|
uniform sampler2D | x3d_Texture2D [x3d_MaxTextures] | texture from Appearance texture field |
uniform samplerCube | x3d_TextureCube [x3d_MaxTextures] | texture from Appearance texture field |
uniform x3d_TextureCoordinateGeneratorParameters | x3d_TextureCoordinateGenerator [x3d_MaxTextures] | see table »Uniform Struct x3d_TextureCoordinateGeneratorParameters« |
|
uniform ivec4 | x3d_Viewport | viewport position and size |
uniform mat4 | x3d_ProjectionMatrix | projection matrix of the camera |
uniform mat4 | x3d_ModelViewMatrix | this is the product of object's transformation matrix and the inverse x3d_CameraSpaceMatrix |
uniform mat3 | x3d_NormalMatrix | object's normal matrix; this is the inverse transpose of the 3×3 submatrix of x3d_ModelViewMatrix |
uniform mat4 | x3d_TextureMatrix [x3d_MaxTextures] | object's texture transform matrix defined by nodes derived from X3DTextureTransformNode |
uniform mat4 | x3d_CameraSpaceMatrix | transformation matrix of the camera |
|
in float | x3d_FogDepth | fog depth of the vertex overriding Fog.visibilityRange; available if FogCoordinate is attached |
in vec4 | x3d_Color | color of the vertex; available if X3DColorNode is attached |
in vec4 | x3d_TexCoord0 | texture coordinate of the vertex from channel 0 |
in vec4 | x3d_TexCoord1 | texture coordinate of the vertex from channel 1 |
in vec4 | x3d_TexCoord2 | texture coordinate of the vertex from channel 2 |
in vec4 | x3d_TexCoord3 | texture coordinate of the vertex from channel 3 |
in vec3 | x3d_Normal | normal of the vertex |
in vec4 | x3d_Vertex | vertex coordinate, required |
Type | Name | Comment |
---|
vec3 | color | |
float | visibilityRange | |
mat3 | matrix | inverse fog space matrix, rotation and scale components |
Type | Name | Comment |
---|
int | type | x3d_DirectionalLight, x3d_PointLight, x3d_SpotLight |
vec3 | color | |
float | ambientIntensity | |
float | intensity | |
vec3 | attenuation | |
vec3 | location | location of light in view space coordinates |
vec3 | direction | |
float | beamWidth | |
float | cutOffAngle | |
float | radius | |
mat3 | matrix | inverse light space matrix, rotation and scale components |
Type | Name |
---|
float | ambientIntensity |
vec3 | diffuseColor |
vec3 | specularColor |
vec3 | emissiveColor |
float | shininess |
float | transparency |
Type | Name |
---|
float | pointSizeScaleFactor |
float | pointSizeMinValue |
float | pointSizeMaxValue |
vec3 | pointSizeAttenuation |
Type | Name |
---|
bool | applied |
int | linetype |
float | lineStippleScale |
sampler2D | texture |
Type | Name |
---|
bool | filled |
bool | hatched |
vec3 | hatchColor |
sampler2D | texture |
Uniform Struct x3d_TextureCoordinateGeneratorParameters
Type | Name |
---|
int | mode |
float | parameter [6] |
Instancing
ParticleSystem
If the shader node is part of a ParticleSystem node the following attributes and uniforms are available.
Type | Name | Comment |
---|
build-in | gl_InstanceId | available |
in vec4 | x3d_Particle | vec4 (int life, float lifetime, float elapsedTime, int texCoordIndex0) |
in vec3 | x3d_ParticleVelocity | velocity vector of particle |
in mat4 | x3d_ParticleMatrix | particle matrix, should be multiplied with x3d_Vertex |
uniform sampler2D | x3d_TexCoordRamp | texture coordinate ramp |
InstancedShape
If the shader node is part of a InstancedShape node the following attributes and uniforms are available.
Type | Name | Comment |
---|
build-in | gl_InstanceId | available |
in mat4 | x3d_InstanceMatrix | instance matrix, should be multiplied with x3d_Vertex |
in mat3 | x3d_InstanceNormalMatrix | instance normal matrix, should be multiplied with x3d_Normal |
Built-in Constants
Some built-in variables are enumerated and have special values and meanings. The following table list all of them and their corresponding values.
Constant | Type | Name | Value | Comment |
---|
X_ITE | | | | defined |
|
x3d_ClipPlane | int | x3d_MaxClipPlanes | 6 | |
|
| int | x3d_MaxLights | 8 | |
x3d_LightType | int | x3d_DirectionalLight | 1 | |
| int | x3d_PointLight | 2 | |
| int | x3d_SpotLight | 3 | |
|
| int | x3d_MaxTextures | 4 | |
Logarithmic Depth Buffer
I assume pretty much every 3D programmer runs into Z-buffer issues sooner or later. Especially when doing planetary rendering; the distant stuff can be a thousand kilometers away but you still would like to see fine details right in front of the camera. First enable the logarithmic depth buffer:
1
2
3
4
5
6
7
8
9
| Script {
url "ecmascript:
function initialize ()
{
Browser .setBrowserOption ('LogarithmicDepthBuffer', true);
}
"
}
|
To address the issue of the depth not being interpolated in perspectively-correct way, add to the fragment shader:
1
2
3
4
5
6
7
8
9
10
11
| #version 300 es
uniform float x3d_LogarithmicFarValue1_2;
void
main ()
{
...
//https://outerra.blogspot.com/2013/07/logarithmic-depth-buffer-optimizations.html
gl_FragDepth = log2 (1.0 + 1.0 / gl_FragCoord .w) * x3d_LogarithmicFarFactor1_2;
}
|
Note: Logarithmic depth buffer is automatically enabled if a GeoViewpoint node is bound.
See Also