Questa pretestuosa prosecuzione del mio ultimo articolo su Silverlight 3 e le sue nuove features
ha lo scopo di introdurre e contestualizzare gli shader effects, di sicuro
uno strumento di notevole potenza in ottica Ux (User Experience).
Abbiamo visto come "attaccare", utilizzando le librerie di Blend 3, un semplice
Trackball behavior ad un UIElement. Ora proviamo - obiettivo del tutorial/articolo -
a far mutare l'aspetto dei pixels di tale elemento per ogni atto rotatorio
in relazione ad un'ipotetica sorgente luminosa all'interno della scena
(demo live cliccando sull'immagine sotto)...

Cosa fare (step-by-step)?
- Scrivere un file .fx in codice HLSL(anguage) che contenga la logica necessaria per
- ricevere una mappa di pixels come input;
- ricevere una coppia di parametri numerici con informazioni riguardo alla luce (incidenza e intensità);
- esporre l'algoritmo da utilizzare nel processo di manipolazione per pixel.
- Compilare il file .fx in un file .ps (pixel shader).
È necessario il tool fxc(ompiler) presente nel DirectX SDK, e recuperabile dalla cartella
«C:\Program Files\Microsoft DirectX SDK (_edition_)\Utilities\bin\x86».
- Includere il file .ps ottenuto all'interno del progetto Silverlight come risorsa.
- Wrappare lo shader in una classe che eredita da ShaderEffect e che espone
in maniera appropriata gli oggetti da passare allo shader stesso.
In primis quindi: il file .fx:
sampler2D input : register(s0);
float dotProduct : register(c0);
float lightIntensity : register(c1);
float4 main(float2 uv : TEXCOORD) : COLOR
{
float goal = dotProduct <= 0.0 ? 0.0 : 1.0;
float adjust = -lightIntensity * abs(dotProduct);
float4 clr = tex2D( input , uv.xy);
clr.r = clr.r + (goal - clr.r) * adjust;
clr.g = clr.g + (goal - clr.g) * adjust;
clr.b = clr.b + (goal - clr.b) * adjust;
return clr;
}
Ora la compilazione nel file .ps; si utilizza la seguente riga di comando:
fxc /T ps_2_0 /E main /Fo"specular.ps" "specular.fx"
Dove /T è il parametro target profile (deve "puntare" a pixel shader 2.0),
/E identifica l'entry point (funzione), mentre /Fo specifica il file output.
Successivamente: incapsulare il file .ps nel progetto Silverlight come risorsa.
Quindi lo shader wrapper, porrò enfasi su pochissime righe di codice (l'intero progetto
può essere scaricato dal link presente in fondo all'articolo).
public SpecularShader()
{
this.PixelShader = SpecularShader.pixelShader;
}
static SpecularShader()
{
pixelShader = new PixelShader();
pixelShader.UriSource = new Uri("RyoushinSamples;component/shaders/specular.ps", UriKind.Relative);
}
public static readonly DependencyProperty InputProperty =
ShaderEffect.RegisterPixelShaderSamplerProperty(
"Input",
typeof(SpecularShader),
0);
internal static readonly DependencyProperty LightIntensityProperty =
DependencyProperty.Register("LightIntensity", typeof(double), typeof(SpecularShader),
// !do not put default value in the metadata (it will make the whole thing not work!)
new PropertyMetadata(PixelShaderConstantCallback(1 )));
private static readonly DependencyProperty DotProductProperty =
DependencyProperty.Register("DotProduct", typeof(double), typeof(SpecularShader),
// !do not put default value in the metadata (it will make the whole thing not work!)
new PropertyMetadata(PixelShaderConstantCallback(0 )));
Il markup Xaml aggiornato permette di inserire in maniera dichiarativa le informazioni
necessarie sulla luce direzionale:
<Image Source="images/sample.jpg" x:Name="img" Width="420" Height="235"
HorizontalAlignment="Center" VerticalAlignment="Center">
<Image.Projection>
<PlaneProjection CenterOfRotationX="0.5"
CenterOfRotationY="0.5"
CenterOfRotationZ="0.5"
RotationY="30"/>
</Image.Projection>
<i:Interaction.Behaviors>
<ryoushin:TrackballBehavior x:Name="trackball"
LightIntensity="1"
LightVectorX=".25"
LightVectorY="-1"/>
</i:Interaction.Behaviors>
</Image>
Nota bene: demo e codice sono stati implementati con Silverlight 3 Beta1,
Non prevedo
né intendo
modificare questo articolo per aggiornarlo alle future versioni di Silverlight.
«
Silverlight TrackballBehavior+Shader
Take care. Bye.
Feedbacks
-
Re: Parametric Shader Effect in Silverlight 3 Beta1
Jose Luis (mercoledì 15 luglio 2009 13.06)
“Hi, Great article :)
When you execute it locally, it does not found the pixel Shader at the specified location component/shaders/specular.ps...
Any idea why?
The other issue I had converting it to SL3 was the change of the interactivity Library, now it is System.Windows.Interactivity and the
using clause is now using the using System.Windows.Interactivity; name instead of the old Microsoft.Expression.Interactivity;..
Best,
Jose”
-
Re: Shader Effect con Parametri in Silverlight 3 Beta1
Cristian Merighi (venerdì 17 luglio 2009 8.52)
“Sure JL,
it an issue - undocumented (or at least I didn't find anything about it yet) - about a subtle change in the format of a packaged resource:
add a "Slash" before the assembly name ("/RyoushinSamples;component/shaders/specular.ps")
Then it will get correctly the resource.”