Convert existing GLSL shaders to OGSFX format

The following sections use typical scenarios with simple examples to demonstrate how to convert your existing GLSL shaders to .ogsfx format. Equivalent code in GLSL versus OGSFX is provided for comparison for each example. It begins with the simplest case, and builds up to more complex scenarios.

NOTE:If you edit an effects file in an external text editor after you have already loaded it in your scene, you must reload the file by clicking the icon in order for the shader to recognize your latest changes.

A fixed solid color material

The shader takes a single input: the position stream.

In GLSL, each of the shader stages: the vertex shader and the pixel (or fragment) shader, must be compiled separately and linked to the same program. Therefore, the pixel and vertex shaders are usually saved in two different files, often with extensions .glslv and .glslf respectively.

An .ogsfx file encapsulates all the stages in a single file.

GLSL

fixed_solid_color.glslv:

// World-view-projection transformation.
uniform mat4 gWVPXf;

// The vertex shader input - coming from the application
in vec3 in_position;
 
// The vertex shader ouput - going to the pixel shader
// None
 
void main()
{
    gl_Position = gWVPXf*vec4(in_position, 1);
}

fixed_solid_color.glslf:

// The pixel shader input - coming from the vertex shader
// None
 
// The pixel shader output - going to the target
out vec4 out_color;
 
void main()
{
    out_color = vec4(1, 0, 0, 1);
}

OGSFX

fixed_solid_color.ogsfx:

// World-view-projection transformation.
uniform mat4 gWVPXf : WorldViewProjection;

// The vertex shader input - coming from the application
attribute vs_input
{
    vec3 in_position : POSITION;
};
 
// The vertex shader ouput and also the pixel shader input
attribute vs_to_ps
{
    // None
};
 
// The pixel shader output
attribute ps_output 
{
    vec4 out_color : COLOR0;
}
 
// All the functions or constants that will be used by the vertex shader
GLSLShader VS
{
    // Only the main function, which is the same as the main function of the .glslv
    void main() 
    {
        gl_Position = gWVPXf*vec4(in_position, 1);
    }
}
 
// All the functions or constants that will be used by the pixel shader
GLSLShader PS
{
    // Only the main function, which is the same as the main function of the .glslf
    void main()
    {
        out_color = vec4(1, 0, 0, 1);
    }
}
 
// Declaration of the techniques and passes - for this example, 1 technique with 1 pass
technique Main
{
    pass p0
    {
        // We have 1 vertex shader stage that uses :
        // - the vs_input attribute as input,
        // - the vs_to_ps attribute as output,
        // - all functions declared in the GLSLShader block VS - must contain main()
        VertexShader (in vs_input, out vs_to_ps) = VS;
 
        // We have 1 pixel shader stage that uses :
        // - the vs_to_ps attribute as input,
        // - the ps_output attribute as output,
        // - all functions declared in the GLSLShader block PS - must contain main()
        PixelShader (in vs_to_ps, out ps_output) = PS;
    }
}

An editable solid color material

The shader takes two inputs:

GLSL

editable_solid_color.glslv:

// World-view-projection transformation.
uniform mat4 gWVPXf;

// No uniform for the vertex shader

in vec3 in_position;
 
void main() 
{
    gl_Position = gWVPXf*vec4(in_position, 1);
}

editable_solid_color.glslf:

// The solid color uniform and its default value
uniform vec4 gSolidColor = vec4(1, 0, 0, 1);
 
out vec4 out_color;
 
void main()
{
    out_color = gSolidColor;
}

OGSFX

editable_solid_color.ogsfx:

// World-view-projection transformation.
uniform mat4 gWVPXf : WorldViewProjection;

// The solid color uniform, its default value and several extra parameters
uniform vec4 gSolidColor : DIFFUSE
<
    // The UI name for this parameter in the Attribute Editor (AE)
    // If not set (or empty), the name of the uniform itself will be used
    string UIName = "Solid Color";
 
    // The group in which to put this parameter in the AE
    // If not set (or empty), the parameter will not be added to any named group
    string UIGroup = "Editable Parameters";
 
    // The value used to sort the parameters within the same group
    // If not set, the parameter will be placed in the same order as it appears
    // in the shader file, but after the parameters with a specified UIOrder 
    int UIOrder = 1;
 
    // Specify the widget used to control the uniform value in the AE
    // Currently only "None" - the parameter will not be visible in the AE -
    // and "ColorPicker" - use the color picked widget - are supported;
    // any other value such as "Color" below will be ignored.
    // The GLSLShader plug-in will try to find the proper widget
    // based on the name of the attribute and its semantic (here DIFFUSE).
    string UIWidget = "Color";
 
> = {1, 0, 0, 1};
 
attribute vs_input
{
    vec3 in_position : POSITION;
};
 
attribute vs_to_ps
{
    // None
};
 
attribute ps_output 
{
    vec4 out_color : COLOR0;
}
 
GLSLShader VS
{
    void main() 
    {
        gl_Position = gWVPXf*vec4(in_position, 1);
    }
}
 
GLSLShader PS
{
    void main()
    {
        out_color = gSolidColor;
    }
}
 
technique Main
{
    pass p0
    {
        VertexShader (in vs_input, out vs_to_ps) = VS;
        PixelShader (in vs_to_ps, out ps_output) = PS;
    }
}
NOTE:See also Semantics and annotations supported by the dx11Shader and glslShader plug-ins in Viewport 2.0 for more information regarding the semantics used above.

A textured material

The shader takes three inputs:

GLSL

textured.glslv:

// World-view-projection transformation.
uniform mat4 gWVPXf;

// No uniform for the vertex shader
 
in vec3 in_position;
in vec2 in_texcoord;
 
out vec2 out_texcoord;
 
void main() 
{
    gl_Position = gWVPXf*vec4(in_position, 1);
    out_texcoord = in_texcoord;
}

textured.glslf:

// The texture sampler uniform bound to the application's texture parameter
uniform sampler2D gTextureSampler;
 
in vec2 in_texcoord;
 
out vec4 out_color;
 
void main()
{
    out_color = texture2D(gTextureSampler, in_texcoord);
}

OGSFX - implementation version 1

textured.ogsfx:

// World-view-projection transformation.
uniform mat4 gWVPXf : WorldViewProjection;

// The texture parameter will be visible in the Attribute Editor (AE)
uniform texture2D gTexture
<
    string UIName = "Texture";
    string UIGroup = "Editable Parameters";
    int UIOrder = 1;
     
    // Default texture file to load
    string ResourceName = "default_texture.png";
 
    // Specify the type of texture : 1D, 2D, Cube ...
    string ResourceType = "2D";
>;
 
// The texture sampler linked to the texture parameter, will not be visible in the AE
uniform sampler2D gTextureSampler = sampler_state
{
    // This sample belongs to the texture "gTexture"
    Texture = <gTexture>;
};
 
attribute vs_input
{
    vec3 in_position : POSITION;
    vec2 in_texcoord : TEXCOORD0;
};
 
attribute vs_to_ps
{
    vec2 out_texcoord;
};
 
attribute ps_output 
{
    vec4 out_color : COLOR0;
}
 
GLSLShader VS
{
    void main() 
    {
        gl_Position = gWVPXf*vec4(in_position, 1);
        out_texcoord = in_texcoord;
    }
}
 
GLSLShader PS
{
    void main()
    {
        out_color = texture2D(gTextureSampler, out_texcoord);
    }
}
 
technique Main
{
    pass p0
    {
        VertexShader (in vs_input, out vs_to_ps) = VS;
        PixelShader (in vs_to_ps, out ps_output) = PS;
    }
}

OGSFX - implementation version 2

In the previous ogsfx implementation, the texture coordinate values are passed from the vertex shader to the pixel shader using the out_texcoord variable of the vs_to_ps attribute structure. While this is reasonable in the vertex shader stage, using the variable name out_texcoord as an input to the pixel shader may be inappropriate. It is possible to name the input and output structures of the shader stages (except for the vs input and ps output that should remain unnamed). For example, name the variable texcoord in the vs_to_ps attribute structure, and name the vs output structure vsOut and the ps input structure psIn.

// World-view-projection transformation.
uniform mat4 gWVPXf : WorldViewProjection;

uniform texture2D gTexture
<
    string UIName = "Texture";
    string UIGroup = "Editable Parameters";
    int UIOrder = 1;
    string ResourceName = "default_texture.png";
    string ResourceType = "2D";
>;
 
uniform sampler2D gTextureSampler = sampler_state
{
    Texture = <gTexture>;
};
 
attribute vs_input
{
    vec3 in_position : POSITION;
    vec2 in_texcoord : TEXCOORD0;
};
 
attribute vs_to_ps
{
    vec2 texcoord;
};
 
attribute ps_output 
{
    vec4 out_color : COLOR0;
}
 
GLSLShader VS
{
    void main() 
    {
        gl_Position = gWVPXf*vec4(in_position, 1);
        // Use the texcoord variable of the output structure
        vsOut.texcoord = in_texcoord;
    }
}
 
GLSLShader PS
{
    void main()
    {
        // Use the texcoord variable of the input structure
        out_color = texture2D(gTextureSampler, psIn.texcoord);
    }
}
 
technique Main
{
    pass p0
    {
        VertexShader (in vs_input, out vs_to_ps vsOut) = VS;
        PixelShader (in vs_to_ps psIn, out ps_output) = PS;
    }
}

Applying two pixel shaders to the same geometry

In order to apply a red solid color and then a green solid color to the same geometry, you can use two different pixel shaders.

In GLSL, you have 3 files : one for the vertex shader and one for each of the pixel shaders.

For .ogsfx, all is included in a single file as follows.

GLSL

two_pixel_shaders.glslv:

// World-view-projection transformation.
uniform mat4 gWVPXf;

in vec3 in_position;
 
void main() 
{
    gl_Position = gWVPXf*vec4(in_position, 1);
}

two_pixel_shaders_ps1.glslf:

out vec4 out_color;
 
void main()
{
    // red with some transparency
    out_color = vec4(1, 0, 0, 0.3);
} 

two_pixel_shaders_ps2.glslf:

out vec4 out_color;
 
void main()
{
    // green with some transparency
    out_color = vec4(0, 1, 0, 0.3);
}

OGSFX

two_pixel_shaders.ogsfx:

// World-view-projection transformation.
uniform mat4 gWVPXf : WorldViewProjection;

attribute vs_input
{
    vec3 in_position : POSITION;
};
 
attribute vs_to_ps
{
    // None
};
 
attribute ps_output 
{
    vec4 out_color : COLOR0;
}
 
GLSLShader VS
{
    void main() 
    {
        gl_Position = gWVPXf*vec4(in_position, 1);
    }
}
 
// The pixel shader that draws the red color
GLSLShader PS_red
{
    void main()
    {
        out_color = vec4(1, 0, 0, 0.3);
    }
}
 
// The pixel shader that draws the green color
GLSLShader PS_green
{
    void main()
    {
        out_color = vec4(0, 1, 0, 0.3);
    }
}
 
// Declare the technique with two passes,
// one for the red color and another for the green
technique Main
{
    pass p_red
    {
        VertexShader (in vs_input, out vs_to_ps) = VS;
        PixelShader (in vs_to_ps, out ps_output) = PS_red;
    }
 
    pass p_green
    {
        VertexShader (in vs_input, out vs_to_ps) = VS;
        PixelShader (in vs_to_ps, out ps_output) = PS_green;
    }
}
 
// It is also possible to declare another technique
// that can be selected via the GLSLShader Attribute Editor
// or when loading the effect using the API
// MHWRender::MShaderManager::getEffectsFileShader(fileName, techniqueName, ...)
// For this technique, the order of the passes is inverted.
technique Inverse
{
    pass p_green
    {
        VertexShader (in vs_input, out vs_to_ps) = VS;
        PixelShader (in vs_to_ps, out ps_output) = PS_green;
    }
 
    pass p_red
    {
        VertexShader (in vs_input, out vs_to_ps) = VS;
        PixelShader (in vs_to_ps, out ps_output) = PS_red;
    }
}