VS85 Team 的个人资料XNALearners日志列表留言簿 工具 帮助

日志


2009/1/22

SpriteBatch per effetti speciali - parte 3

By Davide Luzzu – Webcast by Giuseppe Maggiore

Il codice C#

 

Effect fx = null;

Texture2D controlPoints;

const int numControlPoints = 256;

protected override void LoadContent()

{

  /// Costruiamo il renderer 2D.

  spriteBatch = new SpriteBatch(GraphicsDevice);

  /// Costruiamo la texture di control points, in cui carichiamo interi

  /// unsigned a 16 bit. La texture é una matrice numControlPoints × 1,

  /// cioè 256 colonne e una riga.

  controlPoints = new Texture2D(GraphicsDevice, numControlPoints, 1, 1,

        TextureUsage.None, SurfaceFormat.Luminance16);

 

  // Carichiamo lo shader HLSL.

fx = Content.Load<Effect>("snake shader");

}

 

La prima operazione da compiere è ottenere la configurazione grafica ( GraphicsDevice ) e applicarla ad uno SpriteBatch. Il GraphicsDevice ci permette di ottenere informazioni riguardo alla risoluzione grafica con cui si sta eseguendo l’applicazione, e, di conseguenza, impostare il Pixel Shader. Lo SpriteBatch è il render 2D che ci consentirà di disegnare il nostro serpente.

Il secondo passaggio fondamentale è creare una Texture2D che contiene dei punti di controllo (256), che daranno la forma al nostro “serpente”. Questi punti di controllo possono essere concettualmente associati ai key frames di una animazione; cioè definiamo quali sono le posizioni per cui la nostra animazione dovrà assolutamente passare, il resto viene fatto per interpolazione. Sarebbe, infatti, impensabile dover inserire tutti e 25 i frames ( riferito ad un video in formato PAL) di ogni secondo della animazione, poiché, per ottenere un minuto di animazione, servirebbe agire su 1500 singoli frames! Allo stesso modo quello che facciamo noi è definire dei “frames” (detti anche nodi o punti di controllo ) e nessun dato nella Texture 2D, in modo da avere la possibilità di inserirli a nostro piacimento. Per poter manipolare una elevata quantità di informazioni di illuminazione sulla texture, indichiamo che il formato della superficie è Luminance16; è un formato che comprende 16 bit di dati solo per illuminazione, cioè potremo manipolare 216 combinazioni di colore.!

L’ultima operazione da effettuare è il caricamento dello Shader. Si fa riferimento alla classe Content che contiene il metodo ad accesso statico Load. Tale metodo riceve in input una stringa che designa il percorso di accesso al file (*.fx ) che contiene il codice dello Shader. Ricordiamo che il nome dello Shader va indicato senza l’estensione. Il metodo Load è parametrizzato con un tipo Effect; ciò indica che la variabile di ritorno conterrà dati di tipo Effect.

 

protected override void Draw(GameTime gameTime)

{

      //Resettiamo lo sfondo dell'applicazione ad azzurro.

      graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

 

      // Alcuni piccoli helper trigonometrici e non.

      Func<float, float> sin = x => (float)Math.Sin((double)x);

      Func<float, float> sigmoid = x =>

                             (float)MathHelper.SmoothStep(0.5f, 0.1f, x);

 

      var pi = (float)Math.PI;

 

      // Da quanti secondi l'applicazione é in esecuzione?

      var t = (float)gameTime.TotalGameTime.TotalSeconds;

 

      // Helper di attivazione/disattivazione di un passo dello shader HLSL.

      Action<int, Action<EffectPass>> pass = (i, a) =>

                                                a(fx.CurrentTechnique.Passes[i]);

 

Eseguiamo l’override del metodo Draw di default, dove scriviamo tutto il codice per effettuare il disegno, senza demandare nulla ad altri metodi.

Definiamo innanzitutto due funzioni per aiutarci nei calcoli, una (sin) che calcolerà il seno per definire la forma del serpente, e l’altra (sigmoid) per interpolare i dati.

Di particolare interesse, in questa porzione di codice, è la definizione dei passi dello Shader HLSL.

 

Action<int, Action<EffectPass>> pass=(i, a) => a(fx.CurrentTechnique.Passes[i]);

 

Quello che intendiamo fare è definire in modo elegante l’attivazione e la disattivazione del passo dello Shader. Il codice ML-style ci viene incontro in questo senso, poiché creiamo una labda expression. Diremo che l’azione pass deve compiere una certa azione ad un determinato indice. L’azione che pass eseguirà la chiameremo (a), e (a) effettua un passo della tecnica dello Shader; dato che la tecnica può contenere più di un passo, dovremo indicare quale è l’indice del passo che (a) deve effettuare, e lo indichiamo con (i). Come abbiamo visto, la nostra tecnica contiene un singolo passo, quindi non dovremo aggiornare l’indice ( che sarà sempre zero ). In altre parole piuttosto che scrivere

 

fx.Begin();

fx.CurrentTechnique.Passes[0].Begin();

 

//…code…

 

fx.CurrentTechnique.Passes[0].End();

fx.End();

 

avremo una espressione decisamente più elegante

 

fx.Begin();

pass(0, p => p.Begin());

 

//…code…

 

pass(0, p => p.End());

fx.End();

 

L’azione che (a) esegue è di tipo EffectPass, cioè un tipo di effetto derivante dalla tecnica dello shader in uso.

 

评论

请稍候...
很抱歉,您输入的评论太长。请缩短您的评论。
您没有输入任何内容,请重试。
很抱歉,我们当前无法添加您的评论。请稍后重试。
若要添加评论,需要您的家长授予您相应权限。请求权限
您的家长禁用了评论功能。
很抱歉,我们当前无法删除您的评论。请稍后重试。
您已超过了一天之内允许提供的评论数上限。请在 24 小时后重试。
因为我们的系统表明您可能在向其他用户提供垃圾评论,您的帐户已禁用了评论功能。如果您认为我们错误地禁用了您的帐户,请联系 Windows Live 支持部门
完成下面的安全检查,您提供评论的过程才能完成。
您在安全检查中键入的字符必须与图片或音频中的字符一致。

若要添加评论,请使用您的 Windows Live ID 登录(如果您使用过 Hotmail、Messenger 或 Xbox LIVE,您就拥有 Windows Live ID)。登录


还没有 Windows Live ID 吗?请注册

引用通告

此日志的引用通告 URL 是:
http://vs85team.spaces.live.com/blog/cns!B49FFA0EB319A219!552.trak
引用此项的网络日志