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.
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.
// 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); }
// 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); }
// 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; } }
// 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); }
// 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; }
// 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; } }
The shader takes three inputs:
// 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; }
// 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); }
// 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; } }
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; } }
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.
// World-view-projection transformation. uniform mat4 gWVPXf; in vec3 in_position; void main() { gl_Position = gWVPXf*vec4(in_position, 1); }
out vec4 out_color; void main() { // red with some transparency out_color = vec4(1, 0, 0, 0.3); }
out vec4 out_color; void main() { // green with some transparency out_color = vec4(0, 1, 0, 0.3); }
// 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; } }