Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1577 connectés 

  FORUM HardWare.fr
  Programmation
  C#/.NET managed

  [XNA] Shader 2D HLSL

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[XNA] Shader 2D HLSL

n°2135356
Suzaku13
Posté le 08-04-2012 à 14:43:28  profilanswer
 

Salut,
Je suis actuellement en train de développer un petit jeu (mon premier) en 2D avec XNA 4.0. J'aimerais appliquer un flou gaussien post-processing (avec un masque 3x3) dont voici le code HLSL:
 
 
 
"
 
texture ScreenTexture;
 
sampler TextureSampler = sampler_state
{
Texture = <ScreenTexture>;
};
 
float GaussianMask[9] = {
0.05472157,
0.11098164,
0.05472157,
0.11098164,
0.22508352,
0.11098164,
0.05472157,
0.11098164,
0.05472157
};
 
 
float4 GaussianBlurPixelShaderFunction(float2 TextureCoordinate : TEXCOORD0) : COLOR
{
float4 color = tex2D(TextureSampler, TextureCoordinate);
float4 blurredColor = 0;
[unroll(5)]
for (int i = TextureCoordinate.x - 1; i <= TextureCoordinate.x + 1; i++) {
[unroll(5)]
for (int j = TextureCoordinate.y - 1; j <= TextureCoordinate.y + 1; j++) {
float2 pixelCoords = float2(i,j);
if (i >= 0 && i < 1280 && j >= 0 && j < 720) {
blurredColor += GaussianMask[i - TextureCoordinate.x + 1 + (j - TextureCoordinate.y + 1)*3]*tex2D(TextureSampler, pixelCoords);
}
}
}
return blurredColor;
}
 
//-------------------------- TECHNIQUES ----------------------------------------
technique Blur
{
pass gaussianBlur
{
PixelShader = compile ps_2_b GaussianBlurPixelShaderFunction();
}
}
 
 
 
 
 
Le problème est que quand je tente de compiler tout ça, j'obtiens l'erreur "maximum temp register index exceeded".
J'ai essayé de compiler avec ps_3_0 mais à de moment là il me trouve une exception lors de l'exécution me disant que je dois aussi spécifier l'utilisation de shader 3.0 pour le vertex shader (mais je suis en 2D donc je n'ai pas à en utiliser non ?).
 
 
 
 
 
Je ne sais pas si c'est lié à la manière dont j'utilise les shaders dans mon code xna : j'ai une méthode Draw qui procède à différents affichages via des "spriteBatch.Draw" et "spriteBatch.DrawString", et je l'appelle dans ce cadre là :
 
 
Dans le LoadContent : "_postProcessingShader = Content.Load<Effect>("Render/Shaders/Bloom" );"
 
"
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.AnisotropicClamp, DepthStencilState.Default, RasterizerState.CullNone, _postProcessingShader);
 
Draw(spriteBatch, gameTime);
 
spriteBatch.End();
 
"

mood
Publicité
Posté le 08-04-2012 à 14:43:28  profilanswer
 

n°2135358
bjone
Insert booze to continue
Posté le 08-04-2012 à 16:09:25  profilanswer
 

A mon avis il pète les plombs sur l'indexation de GaussianMask.
 
Refactorise en:
 

Code :
  1. float4 GaussianBlurPixelShaderFunction(float2 TextureCoordinate : TEXCOORD0) : COLOR
  2. {
  3. float4 blurredColor = 0;
  4. int index = 0;
  5. [unroll(5)]
  6. for (int i = TextureCoordinate.x - 1; i <= TextureCoordinate.x + 1; i++) {
  7. [unroll(5)]
  8. for (int j = TextureCoordinate.y - 1; j <= TextureCoordinate.y + 1; j++) {
  9. blurredColor += GaussianMask[index]*tex2D(TextureSampler, float2(i,j) );
  10. ++index;
  11. }
  12. }
  13. }
  14. return blurredColor;
  15. }


 
Ton if est un peu pourri:  
D'un ça alourdi le shader,  
De deux tu te retrouves dénormalisé sur les bords et t'aura un bord plus sombre.
 
Moi soit je capperai le quad en amont du drawcall, ou tu flagges un mode de clipping texture quvabien, ou tu fais le premier rendu avec une rendertarget plus large d'un pixel (classique aussi pour les effets screenspace, c'est le plus propre, rendre à la surface écran + rayon max de tout tes filtres de post-processing).
 
Gaffe aux for( int ) et au float2(i,j), si le centrage du pixel est en 0 ok, si c'est en 0.5, ça peut faire des trucs bizarres.
à la limite, des for( int xoffset = -1 ; xoffset <= 1 ; ++xoffset )
et des tex2D(TextureSampler, TextureCoordinate + float2(i,j) )
Ça peut limiter les blagues et le déroulement de la boucle doit être propre.
Compare la sortie asm de TextureCoordinate + float2(i,j) et float2( TextureCoordinate.x + i, TextureCoordinate.y + j ) aussi.
 
Ha ouais si TextureCoordinate est en espace normalisé et pas en coordonnées entières, c'est foireux vu que les offsets -1/+1 doivent être divisés par les dimensions de la texture ^^


Message édité par bjone le 08-04-2012 à 16:20:03
n°2135390
Suzaku13
Posté le 09-04-2012 à 10:44:45  profilanswer
 

En effet, en enlevant le "if (i >= 0 && i < 1280 && j >= 0 && j < 720)" ça ne me met plus l'erreur "maximum temp register index exceeded".
En utilisant ton code j'obtiens cependant l'erreur "Compiled shader code uses too many instructions slots (460). Max allowed by the target (ps_2_x) is 96.".

n°2135402
bjone
Insert booze to continue
Posté le 09-04-2012 à 14:18:44  profilanswer
 

les unroll ce serait plutôt une limite à 3.
au pire tu fais un essai avec les 9 samplings fait à la mano.

n°2135632
Suzaku13
Posté le 10-04-2012 à 20:55:58  profilanswer
 

Merci ! J'ai mis les unroll à 1 et ça compile ^^ !
 
Par contre il me met un écran tout bleu :( .
En programmant GaussianBlurPixelShaderFunction pour qu'il renvoie simplement "tex2D(TextureSampler, TextureCoordinate)" ou "tex2D(TextureSampler, float2(TextureCoordinate.x,TextureCoordinate.y)" l'affichage est bien normal, mais si je mets à la place "tex2D(TextureSampler, float2(TextureCoordinate.x+1,TextureCoordinate.y+1)" ça me renvoie un écran gris (avec quelques rectangles noirs) donc je pense pouvoir affirmer sans trop me tromper que c'est le tex2D qui ne semble pas accepter des coordonnées autres que celles entrées en argument de la fonction.

n°2135732
bjone
Insert booze to continue
Posté le 11-04-2012 à 14:41:32  profilanswer
 

les coordonnées doivent être en espace normalisé donc 1/dimensions pour choper l'espace entre les pixels.
essaye des 1/1280 et 1/720 pour vérifier à l'arrache.  


Message édité par bjone le 11-04-2012 à 14:43:45
n°2135793
Suzaku13
Posté le 11-04-2012 à 20:47:22  profilanswer
 

J'ai essayé rapidement :
 

Code :
  1. float4 GaussianBlurPixelShaderFunction(float2 TextureCoordinate : TEXCOORD0) : COLOR
  2. {
  3.     float4 blurredColor = 0;
  4.     int index = 0;
  5.     [unroll(1)]
  6.     for (int i = -2; i <= 2; i++) {
  7.  [unroll(1)]
  8.  for (int j = -2; j <= 2; j++) {
  9.  float xcoord = TextureCoordinate.x*1280.0 + i;
  10.  float ycoord = TextureCoordinate.y*720.0 + j;
  11.   if (xcoord >= 0 && xcoord < 1280 && ycoord >= 0 && ycoord < 720) {
  12.    blurredColor += GaussianMask[index]*tex2D(TextureSampler, float2(xcoord/1280.0, ycoord/720.0) );
  13.   }
  14.   index++;
  15.  }
  16.     }
  17.     return blurredColor;
  18. }


 
Toujours un écran bleu :( ...

n°2135794
Terminapor
I'll see you rise.
Posté le 11-04-2012 à 20:50:25  profilanswer
 

Fais ton gaussian blur en deux passes, c'est plus optimisé, si tu connais le GLSL et que tu peux traduire en HLSL j'ai le code tiré de jenesaispuquelsite.


---------------
Perhaps you don't deserve to breathe
n°2135956
bjone
Insert booze to continue
Posté le 12-04-2012 à 16:00:17  profilanswer
 

bah t'as surtout la solution qui utilise le filtrage de texture pour éjecter des opérations:
http://rastergrid.com/blog/2010/09 [...] -sampling/
 
par contre, je comprends pas tes itérations -2 à +2, c'est un kernel 3x3 que tu veux (tu sors de la table de constantes) ?
vire tes unroll()  
et déroule les boucles à la main, ça prendra 20 secondes.


Message édité par bjone le 12-04-2012 à 16:05:32
n°2136552
Suzaku13
Posté le 14-04-2012 à 14:20:16  profilanswer
 

Le -2 et +2 c'est parce que j'avais essayé un masque 5x5.
 
En fait je cherche à créer un effet de bloom en effectuant 2 passes : d'abord un Tone Mapping puis un Gaussian Blur.
Le ToneMapping marche bien mais pas le flou.
 
Je ne l'ai pas précisé (mais vous avez dû vous en doutez), mais je suis un débutant en shader. Dans le cadre de mes études j'ai été amené à travailler un court moment sur des shaders en GLSL mais en ce qui concerne le HLSL nada.
 
Dérouler les boucles à la main comment je fais ?
Je cherche surtout pour l'instant à faire marcher le shader de flou gaussien, j'optimiserais sûrement après ^^.


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C#/.NET managed

  [XNA] Shader 2D HLSL

 

Sujets relatifs
pointeur de tableau 2D d'entiers...convertir des coordonnées GPS sur un plan 2D
[Android] Widget perso : Une grille 2D avec 3 Scrollviews[C++/SMFL] Recrutement Jeu Action/ Infiltration 2D
Shadow mapping en XNAPaperVision3D : passer de la 2d a la 3d = problème de coordonnées :-/
Optimisation 2dMoteur physique/collisions 2D existant?
tableau 2D dynamiquejava et jeux vidéo 2D
Plus de sujets relatifs à : [XNA] Shader 2D HLSL


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR