2012年7月20日 星期五

我的Ogre 3D 折射程式到那兒去了(上)


之前寫折射的時候沒有記錄, 所以完全忘了怎麼寫了…
重新開始寫吧
To do list:
  • 整理 RzMaterial
  • 寫成 Compositor
  • Refraction ? Distortion?
RzApp::switchCompositor 為目前可以開關的機制
目前可用的 Compositor為
Example.compositor
  • Bloom
  • Glass
  • “Old TV"
  • B&W
  • Embossed
  • “Sharpen Edges"
  • Invert
  • Posterize
  • Laplace
  • Tiling
  • “Old Movie"
  • HDR
  • “Gaussian Blur"
  • TestMRT
  • “Radial Blur"
  • ASCII
  • Halftone
  • “Night Vision"
  • Dither
Rz.compositor
  • Rz/Compositor/GaussianBlurNoBG
其中HeatVision是完全寫在Code裏的
從Ogre Manual上看來的一些基礎知識做個筆記:

3.2.1 Techniques

compositor_logic 可以放一個名字 比如說 HDR, 到了程式中再把這個名字代換成真正物件的名稱

Ogre::CompositorManager& compMgr = Ogre::CompositorManager::getSingleton();

compMgr.registerCompositorLogic("HDR", new HDRLogic);

class HDRLogic : public ListenerFactoryLogic
{
protected:
virtual Ogre::CompositorInstance::Listener* createListener(Ogre::CompositorInstance* instance);
};
Target Pass 是一個Compositor中最重要的元件, 它可以有以下東西:
  • input
  • only_initial
  • visibility_mask
  • lod_bias
  • material_scheme
  • shadows
  • pass
其中最重要的, 又是這個叫pass的東西, 由先它的格式為:
‘pass’ (render_quad | clear | stencil | render_scene | render_custom) [custom name] { }
這裏來個最最簡單的compositor示範

compositor Rz/Compositor/SimplePixel
{
    technique
    {
        texture rt0 target_width target_height PF_A8R8G8B8
  
        target rt0
        {
            input previous
        }

        target_output
        {
            input none
   
            pass render_quad
            {
                material Rz/Compositor/Material/Invert
                input 0 rt0
            }
        }
    }
}

這裏用了一個material Rz/Compositor/Material/SimplePixel

讓我們繼續追踪下去:

material Rz/Compositor/Material/Invert
{
 technique
 {

  pass
  {
   cull_hardware none
   cull_software none
   depth_func always_pass

   vertex_program_ref Ogre/Compositor/StdQuad_Tex2a_vp
   {
   }

   fragment_program_ref Rz/Compositor/InvertFP
   {
   }

   texture_unit RT
   {
                          tex_coord_set 0
     tex_address_mode clamp
     filtering trilinear
   }

  }
 }
}



這個vertex shader很簡單, 是個公版
void StdQuad_Tex2a_vp
(
    in float4 inPos : POSITION,

    out float4 pos : POSITION,
    out float2 uv0 : TEXCOORD0,
    out float2 uv1 : TEXCOORD1,

    uniform float4x4 worldViewProj
)
{
    // Use standardise transform, so work accord with render system specific (RS depth, requires texture flipping, etc)
    pos = mul(worldViewProj, inPos);

    // The input positions adjusted by texel offsets, so clean up inaccuracies
    inPos.xy = sign(inPos.xy);

    // Convert to image-space
    uv0 = (float2(inPos.x, -inPos.y) + 1.0f) * 0.5f;
    uv1 = inPos.xy;
}


回到material來, 它的fragment program 是主要的shader程式
fragment_program Rz/Compositor/InvertFP cg
{
 source RzInvertFP.cg
 entry_point Invert_ps
 profiles ps_2_0 arbfp1
}

裏面是長這樣
sampler RT : register(s0);

float4 Invert_ps (float2 iTexCoord : TEXCOORD0) : COLOR
{
 return 1 - tex2D(RT, iTexCoord);
}

今天我們來試試其他簡單的pixel shader, 以下是參考網站(Facewound)

首先來個3倍亮度:
把 compositor裏的material
material Rz/Compositor/Material/Invert
改成
material Rz/Compositor/Material/TrippleColor
那麼我們也要新增一個相對應的material script (TrippleColor.material)給它:
fragment_program Rz/TrippleColorFP cg
{
 source TrippleColorFP.cg
 entry_point TrippleColor_ps
 profiles ps_2_0 arbfp1
}

material Rz/Compositor/Material/TrippleColor
{
 technique
 {

  pass
  {
   cull_hardware none
   cull_software none
   depth_func always_pass

   vertex_program_ref Ogre/Compositor/StdQuad_Tex2a_vp
   {
   }

   fragment_program_ref Rz/TrippleColorFP
   {
   }

   texture_unit RT
   {
                           tex_coord_set 0    
      tex_address_mode clamp
      filtering trilinear
   }

  }
 }
}

這麼一來, 又要新增一個 fragment_program (trippleColorFP.cg)給它
sampler RT : register(s0);

float4 TrippleColor_ps (float2 iTexCoord : TEXCOORD0) : COLOR
{
 return tex2D(RT, iTexCoord) * 3;
}
結果變成

同樣的原理, 我們可以嚐試很多不一樣的東西
比如改成 material Rz/Compositor/Material/GradientY
新增 GradientYFP.cg
sampler RT : register(s0);

float4 GradientY_ps (float2 iTexCoord : TEXCOORD0) : COLOR
{
 return tex2D(RT, iTexCoord) * iTexCoord.y;
}

畫面就會變成根據Y從0到1的漸層

再來, 試試將紅色變成2倍, 過程和細節就不再重覆
只寫出 pixel shader的部份
sampler RT : register(s0);

float4 DoubleRed_ps (float2 iTexCoord : TEXCOORD0) : COLOR
{
 float4 Color=tex2D(RT, iTexCoord);
 Color.r = Color.r * 2.0;
 return  Color;
}
結果如下:
哈哈
再試一個
  • CrazySin的效果吧
sampler g_samSrcColor : register(s0);

float4 CrazySin_ps (float2 Tex : TEXCOORD0) : COLOR
{
  float4 Color = tex2D( g_samSrcColor, Tex.xy);
  Color.r = Color.r*sin(Tex.y*100)*2;
  Color.g = Color.g*cos(Tex.y*200)*2;
  Color.b = Color.b*sin(Tex.y*300)*2;
  return Color;
}


是不是很Crazy
  • HalfU
sampler g_samSrcColor : register(s0);

float4 HalfU_ps (float2 Tex : TEXCOORD0) : COLOR
{
 Tex.x = Tex.x * 0.5;
 float4 Color = tex2D( g_samSrcColor, Tex.xy);
 return Color;
}


雖然名為HalfU 但圖看起變成橫幅兩倍大
  • SinusoidV
sampler g_samSrcColor : register(s0);

float4 SinusoidV_ps (float2 Tex : TEXCOORD0) : COLOR
{
 Tex.y = Tex.y + (sin(Tex.x * 200) * 0.01);
 float4 Color = tex2D( g_samSrcColor, Tex.xy);
 return Color;
}

沒有留言:

張貼留言