PlayStation Mobile Studio
 PlayStation(R)Mobile SDK 1.21.01

■Playstation Mobile フレームバッファの切り替え Prev Top Next
関連ページ:なし


今回はフレームバッファを切り替える処理のサンプル作成のために鮮鋭化フィルターをやります。
鮮鋭化フィルターは、あちこちのサイトで説明されているので説明は省略です。

Common.cs 共通クラスとか
Sprite.vcg バーテックスシェーダーのcgファイル
Sprite.fcg フラグメントシェーダーのcgファイル
Sprite.cs スプライトシェーダークラス
SpriteMesh.cs スプライトメッシュクラス
DebugFont.cs デバッグフォントクラス
Lambert.vcg ランバートシェーダーのバーテックスシェーダーのcgファイル
Lambert.fcg ランバートシェーダーのフラグメントシェーダーのcgファイル
Lambert.cs ランバートシェーダークラス
UnsharpFilter.vcg 鮮鋭化フィルターのバーテックスシェーダーのcgファイル
UnsharpFilter.fcg 鮮鋭化フィルターのフラグメントシェーダーのcgファイル
UnsharpFilter.cs 鮮鋭化フィルタークラス
F14Mesh.cs F14メッシュクラス
ValcanMesh.cs 弾メッシュクラス
AppMain.cs main関数があるソースファイル


---UnsharpFilter.vcg---  ↑

// *********************************************
// 鮮鋭化フィルタ
// *********************************************

// バーテックスシェーダー
void main( float3 in a_Position  : POSITION,
           float2 in a_Texel     : TEXCOORD,
           float4 out v_Position : POSITION,
           float2 out v_Texel    : TEXCOORD
                  )
{
   v_Position = float4( a_Position, 1 );
   v_Texel = float2( a_Texel );
}

---UnsharpFilter.fcg---  ↑


// *********************************************
// 鮮鋭化フィルタ
// *********************************************

// フラグメントシェーダー
void main( float2 in v_Texel  : TEXCOORD,
           uniform sampler2D s_Texture : TEXUNIT0,
           uniform float2 TexelSize,
           float4 out Color   : COLOR )
{
//   float w[] = { 0.0f, -1.0f,  0.0f,
//                -1.0f,  5.0f, -1.0f,
//                 0.0f, -1.0f,  0.0f };
   float w[] = {-1.0f, -1.0f, -1.0f,
                -1.0f,  9.0f, -1.0f,
                -1.0f, -1.0f, -1.0f };
   
   Color = 0;
   int index = 0;
   for( int i=-1; i<2; i++ )
   {
      for( int j=-1; j<2; j++ )
      {
         Color += tex2D( s_Texture, v_Texel + TexelSize * float2( i, j ) ) * w[index++];
      }
   }   
}

---UnsharpFilter.cs---  ↑


// *********************************************
// 鮮鋭化フィルタ
// *********************************************

using System;
using Sce.PlayStation.Core;
using Sce.PlayStation.Core.Graphics;

public class UnsharpFilter : IDisposable
{
   private ShaderProgram shader;
   private SpriteMesh sprite;
   private FrameBuffer frameBuffer;

   public UnsharpFilter ( GraphicsContext Graphics )
   {
      this.shader = new ShaderProgram("/Application/shaders/UnsharpFilter.cgx" );
      shader.SetAttributeBinding( 0, "a_Position" );
      shader.SetAttributeBinding( 1, "a_Texel" );
      shader.SetUniformBinding( 0, "TexelSize" );

      // フレームバッファ作成( Direct3Dで言うところのレンダーターゲット )
      frameBuffer = new FrameBuffer();
      Texture2D renderTexture = new Texture2D( Graphics.Screen.Width, Graphics.Screen.Height
                                   , false, PixelFormat.Rgba
                                   , PixelBufferOption.Renderable    // レンダリング可能なテクスチャーとして作成する
                                  );
      DepthBuffer depthBuffer = new DepthBuffer(Graphics.Screen.Width, Graphics.Screen.Height, PixelFormat.Depth16);
      frameBuffer.SetColorTarget(renderTexture, 0);
      frameBuffer.SetDepthTarget(depthBuffer);

      // スプライトメッシュ作成
      sprite = new SpriteMesh( new Vector2( 1, 1 ), renderTexture, true );

      renderTexture.Dispose();
      depthBuffer.Dispose();
   }

   public void Dispose()
   {
      frameBuffer.Dispose();
      sprite.Dispose();
      shader.Dispose();
   }

   public void ChangeFrameBuffer( GraphicsContext Graphics )
   {
      // フレームバッファを切り替え
      Graphics.SetFrameBuffer( frameBuffer );
   }

   public void RestoreFrameBuffer( GraphicsContext Graphics )
   {
      // フレームバッファをデフォルトに戻す
      Graphics.SetFrameBuffer( Graphics.Screen );
   }

   public void Render( GraphicsContext Graphics )
   {
      Vector2 TexelSize = new Vector2( 1.0f / (float)Graphics.Screen.Width, 1.0f / (float)Graphics.Screen.Height );
      shader.SetUniformValue( 0, ref TexelSize );

      Graphics.SetShaderProgram( shader );

      sprite.Draw ( Graphics );
   }
}

---F14Mesh.cs---  ↑


using System;
using Sce.PlayStation.Core;
using Sce.PlayStation.Core.Graphics;
using Sce.PlayStation.Core.Input;
using Sce.PlayStation.HighLevel.Model;

public class F14Mesh : IDisposable
{
   //3Dメッシュ
   private BasicModel model;

   Vector3 speed;
   Vector3 position;
   float rotationZ;

   public F14Mesh ()
   {
      const float z = 50;

      speed = new Vector3( 0, 0, 0 );
      position = new Vector3( 0, 0, z );
      rotationZ = 0;

      // 3Dメッシュロード
      model = new BasicModel( "/Application/resources/F14.mdx", 0 );
   }

   public void Dispose()
   {
      model.Dispose();
   }

   public void Update( ValcanMesh valcan, Matrix4 viewMatrix, Matrix4 projMatrix )
   {
      // キーボード入力
      GamePadData gamePadData = GamePad.GetData(0);

      if((gamePadData.Buttons & GamePadButtons.Left) != 0)
      {
         speed.X -= 0.1f;
         rotationZ += 0.1f;
      }
      else if((gamePadData.Buttons & GamePadButtons.Right) != 0)
      {
         speed.X += 0.1f;
         rotationZ -= 0.1f;
      }

      if((gamePadData.Buttons & GamePadButtons.Up) != 0)
      {
         speed.Y += 0.1f;
      }
      else if((gamePadData.Buttons & GamePadButtons.Down) != 0)
      {
         speed.Y -= 0.1f;
      }

      // Shoot
      if((gamePadData.Buttons & GamePadButtons.Circle) != 0)
         valcan.Shoot ( position );

      speed = speed *= 0.9f;
      position += speed;

      if( rotationZ > (float)FMath.PI * 0.3f )
         rotationZ = (float)FMath.PI * 0.3f;
      else if( rotationZ < -(float)FMath.PI * 0.3f )
         rotationZ = -(float)FMath.PI * 0.3f;

      rotationZ *= 0.9f;

      // ビュー空間上でのZ値を取得
      float z = viewMatrix.Transform( new Vector4( 0, 0, -position.Z, -1 ) ).Z;
      // 視錐台のXY方向の最大値を計算。この値がF14の上下左右の移動可能範囲となる
      Vector2 XY = projMatrix.Inverse().Transform( new Vector4( z, z, 0, z ) ).Xy;

      if( position.X > XY.X )
         position.X = XY.X;
      else if( position.X < -XY.X )
         position.X = -XY.X;

      if( position.Y > XY.Y )
         position.Y = XY.Y;
      else if( position.Y < -XY.Y )
         position.Y = -XY.Y;

      // ワールド行列

      Matrix4 matScaling = Matrix4.Scale( new Vector3( 5.0f, 5.0f, 5.0f ) );
      Matrix4 matRotationZ = Matrix4.RotationZ( rotationZ );
      Matrix4 matTranslation = Matrix4.Translation( position );

      Matrix4 matWorld = matTranslation * matRotationZ * matScaling ;

      model.SetWorldMatrix( ref matWorld );
   }

   public Matrix4 GetWorldMatrix()
   {
      return model.WorldMatrix;
   }

   public void Render( GraphicsContext graphics )
   {
      // 頂点バッファを設定
      graphics.SetVertexBuffer( 0, model.Parts[0].Arrays[0].VertexBuffer );

      // テクスチャーを設定する
      graphics.SetTexture( 0, model.Textures[0].Texture );

      // レンダリング
      graphics.DrawArrays( DrawMode.Triangles, 0, model.Parts[0].Arrays[0].VertexBuffer.IndexCount );
   }
}

---ValcanMesh.cs---  ↑


using System;
using Sce.PlayStation.Core;
using System.Collections.Generic;
using Sce.PlayStation.Core.Graphics;
using Sce.PlayStation.Core.Input;

public class ValcanMesh : IDisposable
{
   private enum MODE
   {
      StandBy = 0,
      Shoot = 1,
   };

   private class DataArray
   {
      public Vector3 position;
      public MODE mode;

      public DataArray( Vector3 position, MODE mode )
      {
         this.position = position;
         this.mode = mode;
      }
   };

   private SpriteMesh valcan;
   private int wait;
   private List<DataArray> dataArray;
   private int index;

   public ValcanMesh ()
   {
      dataArray = new List<DataArray>();

      // 弾の最大数はここで設定
      for( uint i=0; i<20; i++ )
      {
         dataArray.Add ( new DataArray( new Vector3( 0, 0, 0 ), MODE.StandBy ) );
      }

      Texture2D tex = new Texture2D( "/Application/resources/Valcan.png", false );
      valcan = new SpriteMesh( new Vector2( 1, 1 ), tex );
      tex.Dispose();

      wait = 0;
   }

   public void Dispose()
   {
      valcan.Dispose();
   }

   public void Shoot( Vector3 ParentPos )
   {
      if( wait == 0 )
      {
         for( int i=0; i<dataArray.Count; i++ )
         {
            // 未処理のため弾をアクティブにする
            if( dataArray[i].mode == MODE.StandBy )
            {
               dataArray[i].position = ParentPos;
               dataArray[i].position.Z -= 5.0f;
               dataArray[i].mode = MODE.Shoot;
               wait = 2;
               break;
            }
         }
      }
   }

   public void Update( Matrix4 viewMatrix, Matrix4 projMatrix )
   {
      if( wait > 0 )
         wait--;

      Matrix4 mat = projMatrix * viewMatrix;

      for( int i=0; i<dataArray.Count; i++ )
      {
         if( dataArray[i].mode == MODE.Shoot )
         {
            dataArray[i].position.Z -= 6.0f;

            Vector4 p = mat.TransformProjection( new Vector4( dataArray[i].position, 1 ) );

            if( p.Z >= 1.0f )
            {
               dataArray[i].mode = MODE.StandBy;
            }
         }
      }
   }

   public void Reset()
   {
      index = -1;
   }

   public int MoveNext()
   {
      index++;
      for( int i=index; i<dataArray.Count; i++ )
      {
         if( dataArray[i].mode == MODE.Shoot )
            return index = i;
      }

      return index = -1;
   }

   public Matrix4 GetWorldMatrix(int Index)
   {
      Matrix4 matTranslation = Matrix4.Translation ( dataArray[Index].position );
      return matTranslation;
   }

   public void Render( GraphicsContext graphics )
   {
      valcan.Draw( graphics );
   }
}

うっとうしいのでサウンド再生はずしました(笑)。

---AppMain.cs---  ↑


using System;
using System.Collections.Generic;

using Sce.PlayStation.Core;
using Sce.PlayStation.Core.Environment;
using Sce.PlayStation.Core.Graphics;
using Sce.PlayStation.Core.Imaging;

namespace PSM_Samples
{
   public class AppMain : IDisposable
   {
      private static GraphicsContext graphics;

      private static Lambert lambert;
      private static Sprite spriteShader;
      private static UnsharpFilter unsharpFilter;

      private static DebugFont debugFont;

      // メッシュ
      private static F14Mesh f14;
      private static ValcanMesh valcan;

      // 行列
      static Matrix4 projMatrix, viewMatrix;

      // 平行光源の方向ベクトル
      static Vector3 DirectionalLightDir;

      public static void Main (string[] args)
      {
         Initialize ();

         while (true) 
         {
            SystemEvents.CheckEvents ();
            Update ();
            Render ();
         }
      }

      // 初期化
      public static void Initialize ()
      {
         // フレームバッファの解像度はウィンドウの解像度と同じサイズにする
         graphics = new GraphicsContext( 0, 0, PixelFormat.Rgba, PixelFormat.Depth16, MultiSampleMode.None );

         // シェーダーの作成
         lambert = new Lambert();
         spriteShader = new Sprite();
         unsharpFilter = new UnsharpFilter( graphics );

         // デバッグフォントの作成
         debugFont = new DebugFont();

         // 3Dメッシュの作成
         f14 = new F14Mesh();
         valcan = new ValcanMesh();

         // 射影行列
         projMatrix = Matrix4.Perspective( (float)FMath.PI / 5.0f
                                          , (float)graphics.Screen.Width / (float)graphics.Screen.Height
                                          , 10.0f, 500.0f );

         // ビュー行列
         viewMatrix = Matrix4.LookAt( new Vector3( 0, 0, 70 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 1, 0 ) );

         // 平行光源の方向ベクトル
         DirectionalLightDir = new Vector3( 0, -1, -1 );
      }

      public void Dispose()
      {
         valcan.Dispose();
         f14.Dispose();
         debugFont.Dispose();
         unsharpFilter.Dispose();
         spriteShader.Dispose();
         lambert.Dispose();
         graphics.Dispose();
      }

      // フレーム更新処理
      public static void Update ()
      {
         f14.Update(valcan, viewMatrix, projMatrix);
         valcan.Update(viewMatrix, projMatrix);
      }

      // レンダリング
      public static void Render ()
      {
         // カリングモードを有効にする
         graphics.Enable( EnableMode.CullFace, true );
         // 反時計回りで裏面となるポリゴンを描画しない
         graphics.SetCullFace( CullFaceMode.Back, CullFaceDirection.Ccw );
         // アルファブレンド無効
         AlphaBlend.SetAlphaBlend( graphics, AlphaBlend.BLEND_TYPE.NONE );
         // 深度テスト有効
         graphics.Enable( EnableMode.DepthTest, true );


         // レンダーターゲット切り替え
         unsharpFilter.ChangeFrameBuffer( graphics );
         // クリア
         graphics.SetClearColor (0.2f, 0.2f, 1, 1 );
         graphics.SetClearDepth( 1 );
         graphics.Clear ();
         {
            // Lambertシェーダー
            lambert.Begin( graphics, projMatrix, viewMatrix, DirectionalLightDir );
            {
               lambert.BeginPass( f14.GetWorldMatrix() );
               {
                  // F14レンダリング
                  f14.Render( graphics );
               }lambert.EndPass();
            }lambert.End( graphics );

            // 線形合成
            AlphaBlend.SetAlphaBlend( graphics, AlphaBlend.BLEND_TYPE.ALIGNMENT );
   
            // スプライトシェーダー
            spriteShader.Begin( graphics, projMatrix, viewMatrix );
            {
               int index;
               valcan.Reset ();
               while( ( index = valcan.MoveNext() ) >= 0 )
               {
                  // 弾レンダリング
                  spriteShader.BeginPass( valcan.GetWorldMatrix( index ) );
                  {
                     valcan.Render( graphics );
                  }spriteShader.EndPass ();
               }
            }spriteShader.End( graphics );
         }unsharpFilter.RestoreFrameBuffer( graphics );  // フレームバッファをデフォルトに戻す

         // アルファブレンド無効
         AlphaBlend.SetAlphaBlend( graphics, AlphaBlend.BLEND_TYPE.NONE );
         // 深度テスト無効
         graphics.Enable( EnableMode.DepthTest, false );

         // 鮮鋭化フィルター
         unsharpFilter.Render ( graphics );

         // デバッグ情報出力
         debugFont.Draw( graphics, "D:Shoot\rArrow Key:Move" );

         // スワップ
         graphics.SwapBuffers();
      }
   }
}

GraphicsContextオブジェクトのインスタンス作成時に指定するスクリーンサイズはデフォルトサイズにします。

追記.
 Vita上で実行するとFPSが20になりました。だめだこりゃ。


Prev Top Next
inserted by FC2 system