2010年6月13日 星期日

Interface的力量!!(Cg Shader Language)


Dear All:
這幾天看了GPU Gems Ch32之後開始注意Cg裡Interface的功能,上網google了一下資料還真少,除了Cg User manual之外幾乎沒有甚麼進一步的Example,既然這麼少那就讓小弟稍微整理下這幾天將此功能整合進PackedGL的心得吧!

首先,甚麼是Interface?我們用C++裡的抽象類別來解釋,抽象類別就是定義介面而不實做,對於User來說它只需要知道怎麼用就好,而其中的實做就交由開發人員來負責,最常看到的地方可能是Library裡,舊版本的實作可能比較慢,給個範例:

class Basic
{
public:
    // User use this, no need to know how to implement.
    virtual int pow( int Base, int Power ) = 0;       
};

class A : public Basic
{
public:
    virtual int pow( int Base, int Power )
   {
         while(Power!=0) {  Base *= Base; Power--; }
         return Base ;
    }
};

class B : public Basic
{
public:
    virtual int pow( int Base, int Power ) { return std::pow(Base, Power); }
}

Interface這個概念讓Sahder code也可以有如同上述的功能,定意好整個Shade的framework(抽象類別)之後,再採取不同的實作方式,達到不同的Rendering的效果,來看範例:

uniform sampler texture;
interface Color
{
    float4 Cal( float4 color );
};

struct NegativeColor : Color
{
    float4 Cal( float4 color ) { return (1.0 - color); }
}

struct BrightnessColor : Color
{
    float4 Cal( float4 color )
   {
        float B = (0.2126*color.r) + (0.7152*color.g) + (0.0722*color.b);
        return float4( B, B, B, 1.0 );
    }
}

float4 PixelMain( VertexOUT In, uniform Color C ) : COLOR
{
    return C.Cal( tex2D( texture, In.texcoord ) );
}

當使用這個PixelShader的時,可以依據狀況選擇Rendering的結果是“負片效果”或者“灰階效果”,基本上使用的還是同一個PixelMain為Sahder的進入點。神奇吧!!說穿了其實Cg只是幫你做這件事:

//果是負片效果,source code會被替換成:
float4 PixelMain( VertexOUT In, uniform Color C ) : COLOR
{
    return (1.0 - color);
}

//如果是灰階效果,source code會被替換成:
float4 PixelMain( VertexOUT In, uniform Color C ) : COLOR
{
    float B = (0.2126*color.r) + (0.7152*color.g) + (0.0722*color.b);
    return float4( B, B, B, 1.0 );
}

只要將Sahder的架構定義好,根據物件上的Material屬性,隨時切換至實作模式,就可以達到所需的效果,這辦法在很多Shader系統中都看的到,差別在Cg提供了內建的方法幫你完成這件事,如果是使用HLSL或者GLSL,你必須自行對Shader code(文字檔)做操作,在適當的時間點做Sahder code的替換

至於要App中Cg提供了哪些API來達成這件事呢?首先必須先將Compile調成手動Compile模式,cgSetAutoCompile(context, CG_COMPILE_MANUAL);,因為在未選定實做模式前Shader code是不完整的,無法Cpmile成功是必然的,接下來透過:

CGtype nrmType = cgGetNamedUserType( prog, "NegativeColor " );
CGparameter stdNorm = cgCreateParameter( context, nrmType );

拿到NegativeColor的handler,接著將實做與Interface做連結:

CGparameter normIface = cgGetNamedParameter(prog, "Color");
cgConnectParameter(stdNorm, normIface);

完成以上動作後一個完整的Sahdre code就完成了,最後就手動呼叫cgCompileProgram(prog);

References:
GPU Gems: Chapter 32. An Introduction to Shader Interfaces
GPU Gems: Chapter 36. Integrating Shaders into Applications
GPU Gems2: Chapter 13. Implementing the mental images Phenomena Renderer on the GPU
ShaderX 6: 8.1 A Flexible Material System in Design by Maxime Beaudoin



沒有留言:

張貼留言

LinkWithin

Related Posts Plugin for WordPress, Blogger...