既存の GLSL シェーダを OGSFX 形式に変換する

このセクションでは、簡単な例による一般的なシナリオを使って、既存の GLSL シェーダを .ogsfx 形式に変換する方法を説明します。それぞれのサンプルでは、比較のために、GLSL と OGSFX における同等のコードを示します。ごく簡単な例で開始し、次第に複雑なシナリオへと進みます。

注:シーンにエフェクト ファイルをロードした後で外部テキスト エディタを使ってエフェクト ファイルを編集した場合は、行った変更をシェーダに認識させるために、 アイコンをクリックしてファイルを再ロードする必要があります。

固定されたソリッド カラー マテリアル

シェーダは位置ストリームという単一の入力を取得します。

GLSL では、頂点シェーダとピクセル(またはフラグメント)シェーダはシェーダ ステージごとに個別にコンパイルされ、同一のプログラムにリンクされる必要があります。そのため、ピクセル シェーダと頂点シェーダは通常はそれぞれ .glslv および .glslf という拡張子で 2 つの異なるファイルに保存されます。

一方、.ogsfx ファイルには、1 つのファイルにすべてのステージが格納されます。

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;
    }
}

編集可能なソリッド カラー マテリアル

シェーダは 2 つの入力値を受け取ります。

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;
    }
}
注:上記で使用されているセマンティックに関する情報は、「ビューポート 2.0 の dx11Shader および glslShader プラグインでサポートされるセマンティックと注釈」も参照してください。

テクスチャ付きのマテリアル

シェーダは 3 つの入力値を受け取ります。

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 - 実装バージョン 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 - 実装バージョン 2

前の ogsfx の実装では、テクスチャの座標値は、vs_to_ps アトリビュート構造の out_texcoord 変数を使って、頂点シェーダからピクセル シェーダに渡されました。これは頂点シェーダのステージでは適切ですが、ピクセル シェーダに対する入力として変数名 out_texcoord を使用することは不適切な場合があります。シェーダ ステージの入力構造と出力構造に名前を付けることができます(vs 入力と ps 出力を除く。これらは名前を付けないままにしておく必要があります)。たとえば、vs_to_ps アトリビュート構造内で変数 texcoord に名前を付け、vs 出力構造 vsOut と ps 入力構造 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;
    }
}

同じジオメトリに 2 つのピクセル シェーダを適用する

1 つのジオメトリに赤のソリッド カラーを適用してから緑のソリッド カラーを適用する場合は、2 つの異なるピクセル シェーダを使用できます。

GLSL では、3 つのファイルを使用します。1 つは頂点シェーダ用で、もう 1 つは各ピクセル シェーダ用です。

.ogsfx では、次に示すように、1 つのファイルにすべてが含まれています。

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;
    }
}