Tutorial: Vertex Shader & Pixel Shader Unterstützung in DX9

Hier kannst du häufig gestellte Fragen/Antworten und Tutorials lesen und schreiben.
Benutzeravatar
Epyx
Beiträge: 247
Registriert: 29.08.2004 01:40
Computerausstattung: AMD64 X2 DualCore 6000+ , 3GB Ram , WinXP sp3
2x Ati Radeon HD4800 ~ CrossFireX
Kontaktdaten:

Re: Tutorial: Vertex Shader & Pixel Shader Unterstützung in

Beitrag von Epyx »

HI MPZ
Erstmal eine klasse Idee, ein Shader Tutorial zu schreiben. Ich hoffe du bleibst dabei und ziehst das gnadenlos durch auch wenn das Feedback hier ein wenig ausbleibt ^^
Im ersten Post meintest du ja man solle auch eigene Shader Posten, und da ich jetzt einen bestimmten Shader brauchte um mein derzeitiges Projekt zu testen stelle ich ihn hier mal zur verfügung.
Es ist ein Beispiel wie man 4 Texturen lädt und diese alle gleichzeitig auf seinem 3d Objekt unterschiedlich bewegen und übereinander gelegt darstellen kann. Ist jetzt nichts wirklich beeindruckendes aber vieleicht ja doch für den einen oder anderen Interessant!
Der Shader ist kommentiert und funktioniert einwandfrei mit deinem Shader Editor :)

Code: Alles auswählen

//-----------------------------------------------------------------------------
//      4 Texturen mischen und bewegen 
//-----------------------------------------------------------------------------


float    time;



texture texture0; // Texture 1 laden
sampler Sampler1 = sampler_state
{  texture   = <texture0>;  };

texture texture1; // Texture 2 laden
sampler Sampler2 = sampler_state
{  texture   = <texture1>;  };

texture texture2; // Texture 3 laden
sampler Sampler3 = sampler_state
{  texture   = <texture2>;  };

texture texture3; // Texture 4 laden
sampler Sampler4 = sampler_state
{  texture   = <texture3>;  };



float4 QuadTex(float2 Tex : TEXCOORD0) : COLOR0
{   float4  Color;   float4  Color2;   float4  Color3;   float4  Color4;
    Color    = tex2D(Sampler1,   float2(Tex.x+cos(time) ,  Tex.y + (2*sin(time) )  )  );    // Texture 1 bewegen
    Color2  = tex2D(Sampler2,   float2(Tex.x,  Tex.y  +  (1*sin(time) )  )  );                   // Texture 2
    Color3  = tex2D(Sampler3,   float2(Tex.x +  (1 *  sin(time)),  Tex.y  )  );                  // Texture 3
    Color4  = tex2D(Sampler4,   float2(Tex.x +  (3 *  sin(time)),  Tex.y  )  );                  // Texture 4
    float4 col = Color*Color2-Color3+Color4;  // Alle miteinander mischen / addieren / subtrahieren
 return  col;  }




technique QuadTexture
{
    pass p1  
    {
        PixelShader = compile ps_2_0 QuadTex();
    }
}
If you can't make it good, at least make it look good.
Bill Gates
Benutzeravatar
mpz
Beiträge: 497
Registriert: 14.06.2005 15:53
Computerausstattung: Win 10 Pro, 16 GB Ram, Intel I5 CPU und TI1070 Grafikkarte, PB 5.73 / 6.00 beta4
Wohnort: Berlin, Tempelhof

Re: Tutorial: Vertex Shader & Pixel Shader Unterstützung in

Beitrag von mpz »

Hi,

Danke erst einmal an Epyx. Der Shader ist gut gelungen und wird ein anderes Mal von mir als Tutorial erklärt.

Heute geht es an eine neues Tutorial dem erstellen von Texturen mit Shadern. Dazu haben ich einen neuen
Shadereditor fertig gemacht der die Cursor Position und FPS anzeigt und zu einem Fehlern springt wenn der
Shader nicht compiliert werden kann. Siehe ersten Beitrag.

Wir benutzen dazu length(x) was die Länge des angegebenen Gleitkomma-Vektors angibt. Dazu benutzen wir wieder
die Textur mit den Koodinaten Tex.xy

Code: Alles auswählen

//-----------------------------------------------------------------------------
//     Name: Circle_Shader_Post.fx
//     Author: Michael Paulwitz
//    Last Modified: 
//    Description: Create Circle
//-----------------------------------------------------------------------------

float4 PSCircle(float2 Tex : TEXCOORD0) : COLOR
{
    return float4(sin(length(Tex -0.5) * 100.0) * 0.5 + 0.5,0, 0, 1);
}

technique circle
{
    pass p1  
    {
        PixelShader = compile ps_2_0 PSCircle();
    }
}
Wie man aber bei der Texur sieht ist der Kreis nicht im Mittelpunkt und auch nicht rund sondern oval wenn man Ihn als Postprocessing Shader benutzt.
Hier wird jetzt angepasst:
Die Textur ist 933 * 511 gross
Das Fenster ist aber nur 470 * 470 breit + die Ränder mit 2 x 20 Punkte. Das heißt der y Wert muss nicht verschoben werden da 510 fast 511 ist

Code: Alles auswählen

Tex.y = Tex.y - 0.5;
aber der x Wert muss verschoben und verzerrt werden, dazu berechnen wir
Verzerrfaktor = 933 / 511 = 1.8
Verschoben = 470 + 2 x 20 = 510, davon der Mittelpunkt 255. D.h. wenn 933 = 1 ist (Tex.x geht von 0-1) muss 255 = 0.28 sein

Code: Alles auswählen

Tex.x = (Tex.x - 0.28)*1.8;
Mit unserer postfx variablen bedeutet das jetzt

Code: Alles auswählen

//-----------------------------------------------------------------------------
//     Name: Circle2_Shader_Post.fx
//     Author: Michael Paulwitz
//    Last Modified: 
//    Description: Create Circle with special post viewport
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Effect File Variables
//-----------------------------------------------------------------------------

float postfx;

float4 PSCircle(float2 Tex : TEXCOORD0) : COLOR
{
    
   if  (postfx == 0)
       return float4(sin(length(Tex -0.5) * 100.0) * 0.5 + 0.5,0, 0, 1);
    else
      Tex.y = Tex.y - 0.5;
      Tex.x = (Tex.x - 0.28)*1.8;
    return float4(sin(length(Tex) * 100.0) * 0.5 + 0.5,0, 0, 1);

}

technique circle
{
    pass p1  
    {
        PixelShader = compile ps_2_0 PSCircle();
    }
}



Gruß Michael
Working on - MP3D Engine -
Benutzeravatar
mpz
Beiträge: 497
Registriert: 14.06.2005 15:53
Computerausstattung: Win 10 Pro, 16 GB Ram, Intel I5 CPU und TI1070 Grafikkarte, PB 5.73 / 6.00 beta4
Wohnort: Berlin, Tempelhof

Re: Tutorial: Vertex Shader & Pixel Shader Unterstützung in

Beitrag von mpz »

Hallo,

hier eine kleine Auflockerung , einen Shader den ich zur Kunst erkläre. Einen prozeduralen Apfel mit Tisch, Softshadow und Glanz, konvertiert mit meinem GLSL to HLSL konverter

Code: Alles auswählen

float4x4 worldViewProjI; float postfx;
#ifdef GL_ES
// precision highp float;
#endif

uniform float2 resolution = float2(933,511) ; // Screensize;
uniform float time;

float3x3 m = float3x3( 0.00,  0.80,  0.60,
              -0.80,  0.36, -0.48,
              -0.60, -0.48,  0.64 );

float hash( float n )
{
    return frac(sin(n)*43758.5453);
}


float noise( in float3 x )
{
    float3 p = floor(x);
    float3 f = frac(x);

    f = f*f*(3.0-2.0*f);

    float n = p.x + p.y*57.0 + 113.0*p.z;

    float res = lerp(lerp(lerp( hash(n+  0.0), hash(n+  1.0),f.x),
                        lerp( hash(n+ 57.0), hash(n+ 58.0),f.x),f.y),
                    lerp(lerp( hash(n+113.0), hash(n+114.0),f.x),
                        lerp( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z);
    return res;
}

float fbm( float3 p )
{
    float f = 0.0;

    f += 0.5000*noise( p ); p = mul (m,p*2.02);
    f += 0.2500*noise( p ); p = mul(m,p*2.03);
    f += 0.1250*noise( p ); p = mul(m,p*2.01);
    f += 0.0625*noise( p );

    return f/0.9375;
}

float2 map( float3 p )
{
   float2 d2 = float2( p.y+0.55, 2.0 );

   p.y -= 0.75*pow(dot(p.xz,p.xz),0.2);
   float2 d1 = float2( length(p) - 1.0, 1.0 );

   if( d2.x<d1.x) d1=d2;
   return d1;
}


float3 appleColor( in float3 pos, in float3 nor, out float2 spe )
{
    spe.x = 1.0;
    spe.y = 1.0;

    float a = atan2(pos.x,pos.z);
    float r = length(pos.xz);

    // red
    float3 col = float3(1.0,0.0,0.0);

    // green
    float f = smoothstep( 0.1, 1.0, fbm(pos*1.0) );
    col = lerp( col, float3(0.8,1.0,0.2), f );

    // dirty
    f = smoothstep( 0.0, 1.0, fbm(pos*4.0) );
    col *= 0.8+0.2*f;

    // frekles
    f = smoothstep( 0.0, 1.0, fbm(pos*48.0) );
    f = smoothstep( 0.7,0.9,f);
    col = lerp( col, float3(0.9,0.9,0.6), f*0.5 );

    // stripes
    f = fbm( float3(a*7.0 + pos.z,3.0*pos.y,pos.x)*2.0);
    f = smoothstep( 0.2,1.0,f);
    f *= smoothstep(0.4,1.2,pos.y + 0.75*(noise(4.0*pos.zyx)-0.5) );
    col = lerp( col, float3(0.4,0.2,0.0), 0.5*f );
    spe.x *= 1.0-0.35*f;
    spe.y = 1.0-0.5*f;

    // top
    f = 1.0-smoothstep( 0.14, 0.2, r );
    col = lerp( col, float3(0.6,0.6,0.5), f );
    spe.x *= 1.0-f;


    float ao = 0.5 + 0.5*nor.y;
    col *= ao*1.2;

    return col;
}

float3 floorColor( in float3 pos, in float3 nor, out float2 spe )
{
    spe.x = 1.0;
    spe.y = 1.0;
    float3 col = float3(0.5,0.4,0.3)*1.7;

    float f = fbm( 4.0*pos*float3(6.0,0.0,0.5) );
    col = lerp( col, float3(0.3,0.2,0.1)*1.7, f );
    spe.y = 1.0 + 4.0*f;

    f = fbm( 2.0*pos );
    col *= 0.7+0.3*f;

    // frekles
    f = smoothstep( 0.0, 1.0, fbm(pos*48.0) );
    f = smoothstep( 0.7,0.9,f);
    col = lerp( col, float3(0.2,0.2,0.2), f*0.75 );

    // fake ao
    f = smoothstep( 0.1, 1.55, length(pos.xz) );
    col *= f*f*1.4;
    col.x += 0.1*(1.0-f);
    return col;
}

float2 intersect( in float3 ro, in float3 rd )
{
    float t=0.0;
    float dt = 0.06;
    float nh = 0.0;
    float lh = 0.0;
    float lm = -1.0;
    for(int i=0;i<100;i++)
    {
        float2 ma = map(ro+rd*t);
        nh = ma.x;
        if(nh>0.0) { lh=nh; t+=dt;  } lm=ma.y;
    }

    if( nh>0.0 ) return float2(-1.0,-1.0);
    t = t - dt*nh/(nh-lh);

    return float2(t,lm);
}

float softshadow( in float3 ro, in float3 rd, float mint, float maxt, float k )
{
    float res = 1.0;
    float dt = 0.1;
    float t = mint;
    for( int i=0; i<30; i++ )
    {
        float h = map(ro + rd*t).x;
        if( h>0.001 )
            res = min( res, k*h/t );
        else
            res = 0.0;
        t += dt;
    }
    return res;
}
float3 calcNormal( in float3 pos )
{
    float3  eps = float3(.001,0.0,0.0);
    float3 nor;
    nor.x = map(pos+eps.xyy).x - map(pos-eps.xyy).x;
    nor.y = map(pos+eps.yxy).x - map(pos-eps.yxy).x;
    nor.z = map(pos+eps.yyx).x - map(pos-eps.yyx).x;
    return normalize(nor);
}

float4 main(float2 gl_FragCoord: TEXCOORD0, float4 gl_FragColor: COLOR ) : COLOR
{
if (postfx == 1) gl_FragCoord.x = gl_FragCoord.x + 0.23;

gl_FragCoord.y = 1 - gl_FragCoord.y; gl_FragCoord = gl_FragCoord * resolution;

    float2 q = gl_FragCoord.xy / resolution.xy;
    float2 p = -1.0 + 2.0 * q;
    p.x *= resolution.x/resolution.y;

    // camera
    float3 ro = 2.5*normalize(float3(cos(0.2*time),1.15+0.4*cos(time*.11),sin(0.2*time)));
    float3 ww = normalize(float3(0.0,0.5,0.0) - ro);
    float3 uu = normalize(cross( float3(0.0,1.0,0.0), ww ));
    float3 vv = normalize(cross(ww,uu));
    float3 rd = normalize( p.x*uu + p.y*vv + 1.5*ww );

    // raymarch
    float3 col = float3(0.96,0.98,1.0);
    float2 tmat = intersect(ro,rd);
    if( tmat.y>0.5 )
    {
        // geometry
        float3 pos = ro + tmat.x*rd;
        float3 nor = calcNormal(pos);
        float3 ref = reflect(rd,nor);
        float3 lig = normalize(float3(1.0,0.8,-0.6));
     
        float con = 1.0;
        float amb = 0.5 + 0.5*nor.y;
        float dif = max(dot(nor,lig),0.0);
        float bac = max(0.2 + 0.8*dot(nor,float3(-lig.x,lig.y,-lig.z)),0.0);
        float rim = pow(1.0+dot(nor,rd),3.0);
        float spe = pow(clamp(dot(lig,ref),0.0,1.0),16.0);

        // shadow
        float sh = softshadow( pos, lig, 0.06, 4.0, 4.0 );

        // lights
        col  = 0.10*con*float3(0.80,0.90,1.00);
        col += 0.70*dif*float3(1.00,0.97,0.85)*float3(sh, (sh+sh*sh)*0.5, sh*sh );
        col += 0.15*bac*float3(1.00,0.97,0.85);
        col += 0.20*amb*float3(0.10,0.15,0.20);


        // color
        float2 pro;
        if( tmat.y<1.5 )
        col *= appleColor(pos,nor,pro);
        else
        col *= floorColor(pos,nor,pro);

        // rim and spec
        col += 0.60*rim*float3(1.0,0.97,0.85)*amb*amb;
        col += 0.60*pow(spe,pro.y)*float3(1,1,1)*pro.x*sh;

        col = 0.3*col + 0.7*sqrt(col);
    }

    col *= 0.25 + 0.75*pow( 16.0*q.x*q.y*(1.0-q.x)*(1.0-q.y), 0.15 );

    gl_FragColor = float4(col,1.0);
            return gl_FragColor;

}
// Vertex Shader
struct VS_INPUT
{
    float3 position	: POSITION;
    float2 texture0     : TEXCOORD0;
};

struct VS_OUTPUT
{
     float4 hposition : POSITION;
     float2 texture0  : TEXCOORD0;
};

VS_OUTPUT myvs( VS_INPUT IN )
{
    VS_OUTPUT OUT;
    if (postfx == 0) {
      OUT.hposition = mul( worldViewProjI, float4(IN.position.x ,IN.position.y ,IN.position.z, 1) ); 
    } else {
      OUT.hposition = float4(IN.position.x ,IN.position.y ,IN.position.z, 1);
    }    
    OUT.texture0 = IN.texture0;
    return OUT;
}
// ---------------------------------------------
technique Start
{
    pass p1  
    {
        VertexShader = compile vs_3_0 myvs();
        PixelShader = compile ps_3_0 main();
    }
}

Gruß Michael
Working on - MP3D Engine -
Benutzeravatar
mpz
Beiträge: 497
Registriert: 14.06.2005 15:53
Computerausstattung: Win 10 Pro, 16 GB Ram, Intel I5 CPU und TI1070 Grafikkarte, PB 5.73 / 6.00 beta4
Wohnort: Berlin, Tempelhof

Re: Tutorial: Vertex Shader & Pixel Shader Unterstützung in

Beitrag von mpz »

Hallo,

heute geht es um das verwenden von mehreren Texturen auf einem Mesh. Hier wollen wir einem Mesh verschiedene Texturen zuordnen
(wie schon in dem Shader von Epyx beschrieben wurde).

Dazu benötigen wir zwei Texturen die wir als texture(0) und texture(1) in dem Shadereditor laden (z.B. Demo_Texture_1.bmp und Demo_Texture_2.bmp)
Um eine zweite Textur in dem Shader zu laden benötigen wir im Shader eine zweite texture1:

Code: Alles auswählen

texture texture1;
sampler Sampler2 = sampler_state 
{ 
texture   = <texture1>;
};

jetzt benutzen wir den Var1 Regler um die Fade Effekte zu steuern

Vom Shadereditor übergeben Variablen:
texture0 -> geladene Textur, z.B. "Demo_Texture_1.bmp"
texture1 -> geladene Textur, z.B. "Demo_Texture_2.bmp"
Var1 -> Schieberegler Var1


Fade Effekt 1 ist Überblenden von texture0 zu texture1

Code: Alles auswählen

//-----------------------------------------------------------------------------
//     Name: Fade_Shader_Post.fx
//     Author: Michael Paulwitz
//    Last Modified:
//    Description: Texture Fade Shader
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Effect File Variables
//-----------------------------------------------------------------------------

texture texture0;
texture texture1;
float Var1;

sampler Sampler1 = sampler_state 
{ 
texture   = <texture0>;
};

sampler Sampler2 = sampler_state 
{ 
texture   = <texture1>;
};

float4 PSFade(float2 Tex : TEXCOORD0) : COLOR
{
    return (tex2D(Sampler1, Tex)*Var1) + ( tex2D(Sampler2, Tex)*(1-Var1));
}

technique main
{
    pass p1  
    {
        PixelShader = compile ps_2_0 PSFade();
    }
}

Fade Effekt 2 ist Überblenden von texture0 zu texture1 über Texturposition

Code: Alles auswählen

//-----------------------------------------------------------------------------
//     Name: Fade2_Shader_Post.fx
//     Author: Michael Paulwitz
//    Last Modified:
//    Description: Texture Fade2 Shader
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Effect File Variables
//-----------------------------------------------------------------------------

texture texture0;
texture texture1;
float Var1;

sampler Sampler1 = sampler_state 
{ 
texture   = <texture0>;
};

sampler Sampler2 = sampler_state 
{ 
texture   = <texture1>;
};

float4 PSFade(float2 Tex : TEXCOORD0) : COLOR
{
    if (Var1 > Tex.y) 
       return tex2D(Sampler1, Tex);
    else
       return  tex2D(Sampler2, Tex);


}

technique main
{
    pass p1  
    {
        PixelShader = compile ps_2_0 PSFade();
    }
}
Wenn man die Effekte als Postprocessing Shader verwendet wird allerdings als erste texture0 der Backbuffer des Renderscreens verwendet.
Um das zu umgehen muss man im Shadereditor texture1 und texture2 laden und dann im Shader anpassen.

Gruß Michael
Working on - MP3D Engine -
Benutzeravatar
mpz
Beiträge: 497
Registriert: 14.06.2005 15:53
Computerausstattung: Win 10 Pro, 16 GB Ram, Intel I5 CPU und TI1070 Grafikkarte, PB 5.73 / 6.00 beta4
Wohnort: Berlin, Tempelhof

Re: Tutorial: Vertex Shader & Pixel Shader Unterstützung in

Beitrag von mpz »

Hi,

heute stehen Matrix Berechnung im Vordergrund. Es gibt eine Standardshader den ich für die nächsten Shader Tutorials benötige. Dieser besteht aus einen Vertex und Pixelshader. Warum? Damit wir bald zu einfachen und komplizierteren Shadern wie LichtShader etc. kommen können. Ersteinmal ist die Matrix worldViewProj wichtig. Diese wird von mp3d berechnet. Es handelt sich hierbei um ein Multiplikation von Kameramatrix, der Weltmatrix und der Meshmatrix. Mit einer float4x4 matrix beschreibt man die Position, Ausrichtung, Verzerrung z.B. eines Objektes. Die Reihen und Spalten lassen sich mit Reihe 1: _11, _12, _13, _14 und _21, _22 ect. beschreiben. Vielfach findet man in den HLSL Shadern die Matrix worldViewProj und die (inverse worldViewProj) worldViewProjI Matrix. mp3d kann beides übergeben, aber beide kann man für den gleichen Zweck benutzen. Hier ein Beispiel mit den Positionen der Vertexpunkte die wir so im Shader beschrieben haben:

Code: Alles auswählen

float4x4 worldViewProjI; // This matrix will be loaded by the application
  ...
OUT.hposition = mul( worldViewProjI, float4(IN.position.x ,IN.position.y ,IN.position.z, 1) ); //
Man kann aber die gleiche Position mit der nicht inversen Matrix erhalten , man muss nur die mul(x,y) Routine auf mul(y,x) umstellen. Mit diese nicht inversen Darstellung werden wir der Einfachheit halber weiterabeiten.

Code: Alles auswählen

float4x4 worldViewProj; // This matrix will be loaded by the application
  ...
OUT.hposition = mul( float4(IN.position.x ,IN.position.y ,IN.position.z, 1) ,worldViewProj); //
Unser Standarshader für Mesh mit Texturen lautet demnach wie folgt:

Code: Alles auswählen

//-----------------------------------------------------------------------------
//     Name: Simple_VertexTexture_Shader.fx
//     Author: Michael Paulwitz
//    Last Modified:
//    Description: Easy Vertex Shader, Show only the texture of the mesh
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Effect File Variables
//-----------------------------------------------------------------------------

float4x4 worldViewProj : WorldViewProjection; // This matrix will be loaded by the application

texture texture0;

sampler Sampler1 = sampler_state 
{ 
texture   = <texture0>;
};

//-----------------------------------------------------------------------------
// Vertex Definitions
//-----------------------------------------------------------------------------

// Our sample application will send vertices
// down the pipeline laid-out like this...

struct VS_INPUT
{
    float3 position   : POSITION;
    float2 tex0       : TEXCOORD0;
};

struct VS_OUTPUT
{
    float4 hposition : POSITION;
    float2 tex0        : TEXCOORD0;
};

//-----------------------------------------------------------------------------
// Simple Vertex Shader
//-----------------------------------------------------------------------------

VS_OUTPUT myvs( VS_INPUT IN )
{
    VS_OUTPUT OUT;
    OUT.hposition = mul( float4(IN.position.x ,IN.position.y ,IN.position.z, 1),worldViewProj ); //
    OUT.tex0 = IN.tex0 ;
    return OUT;
}

float4 myps(float2 Tex : TEXCOORD0) : COLOR
{
    return tex2D(Sampler1, Tex);
}

technique inverse
{
    pass p1  
    {
        VertexShader = compile vs_2_0 myvs();
        PixelShader = compile ps_2_0 myps();
    }
}
Aber es gibt kein Tutorial mit irgendeinem Lerneffect, hier der einfachen Matrix manipulation

Bei eine float4 Matrix beschreibt die Reihe 4 Spalte 1-3 die x,y,z Position des Meshs

Code: Alles auswählen

float4 worldVP
worldVP._41 = worldVP._41 + sin(time); 
verändert damit ganz einfach die x Position des Meshs, hier als einfacher angepasster "Simple_VertexTexture_Shader".
Diese Art von Shadern kann man z.B. für bewegungsfolgen von Anim-Meshs machen, damit würde der Vogel wirklichkeitnaher fliegen,
der Baum im Wind richtiger bewegen. Und das ohne komplizierte Rechenalgoryhtmen die man vorberechnet.

Code: Alles auswählen

//-----------------------------------------------------------------------------
//     Name: Simple_VertexTexture_Shader_with_moving.fx
//     Author: Michael Paulwitz
//    Last Modified:
//    Description: Easy Vertex Shader, Show only the texture of the mesh
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Effect File Variables
//-----------------------------------------------------------------------------

float4x4 worldViewProj; // This matrix will be loaded by the application
float time;

texture texture0;

sampler Sampler1 = sampler_state 
{ 
texture   = <texture0>;
};

//-----------------------------------------------------------------------------
// Vertex Definitions
//-----------------------------------------------------------------------------

// Our sample application will send vertices
// down the pipeline laid-out like this...

struct VS_INPUT
{
    float3 position   : POSITION;
    float2 tex0       : TEXCOORD0;
};

struct VS_OUTPUT
{
    float4 hposition : POSITION;
    float2 tex0        : TEXCOORD0;
};

//-----------------------------------------------------------------------------
// Simple Vertex Shader
//-----------------------------------------------------------------------------

VS_OUTPUT myvs( VS_INPUT IN )
{
    VS_OUTPUT OUT;
    float4x4 worldVP = worldViewProj; // Wir klaue hier die Weltpotion

    worldVP._41 = worldVP._41 + sin(time);
    worldVP._42 = worldVP._42 + cos(time);
    worldVP._43 = worldVP._43 + sin(time)*cos(time);

    OUT.hposition = mul( float4(IN.position.x ,IN.position.y ,IN.position.z, 1),worldVP); //
    OUT.tex0 = IN.tex0 ;
    return OUT;
}

float4 myps(float2 Tex : TEXCOORD0) : COLOR
{
    return tex2D(Sampler1, Tex);
}

technique moving
{
    pass p1  
    {
        VertexShader = compile vs_2_0 myvs();
        PixelShader = compile ps_2_0 myps();
    }
}
Gruß Michael
Working on - MP3D Engine -
Benutzeravatar
mpz
Beiträge: 497
Registriert: 14.06.2005 15:53
Computerausstattung: Win 10 Pro, 16 GB Ram, Intel I5 CPU und TI1070 Grafikkarte, PB 5.73 / 6.00 beta4
Wohnort: Berlin, Tempelhof

Re: Tutorial: Vertex Shader & Pixel Shader Unterstützung in

Beitrag von mpz »

Hi liebe Leute oder wer auch immer das ließt,

heute wollen wir uns mit dem Licht beschäftigen. Da das Lichtsystem von DX9 bei Shadern nicht "automatisch" funktioniert müssen wir uns ein eigenes System "bauen". Dazu benötigen wir die "normals" der Vertexe und die folgenden Funktionen.

Code: Alles auswählen

float3 lightDir -> Richtung des Lichtes
float4x4 matWorld -> Die Meshmatrix die das Mesh beschreibt (z.B. Position, Ausrichtung, Verzerrung etc)

normalize(float3 vec) -> Limitiert die x,y,z Werte des Vectors auf x,y,z = (-1 bis 1) 
saturate(x) -> Limitiert den Wert (x) auf einem Wert von 0 bis 1
dot(float3 x, float3 y) -> Skalarprodukt von zwei Vektoren
Wir nehmen uns die "Normals" von den Eingangsvertexen

Code: Alles auswählen

struct VS_INPUT
{
    float3 position	: POSITION;
    float4 normal	: NORMAL0 ;
    float4 color	 : COLOR0;
};
Besonderheit hier 4 floats = (x,y,z,w) wobei wir nur x,y,z benötigen. Das begrenzen wir auf flaot3 mit IN.normal.xyz
Die Berechnung lautet also einfach der Lichtausfall Faktor ist das Skalarprodukt aus Normals und Lichtrichtung. Das gillt aber nur für Richtungslicht, zu Punklicht etc kommen wir später. Hier jetzt der Shader der die Vertexe mit Licht zeigen.
Besonderheit: Wenn man Ihn anwedet sieht man aber keinen Unterschied zu dem nicht gestartetem Shader.
Die Erklärung ist ganz einfach. Ohne aktiven Shader ist die Lichtberechnung von DX9 zuständig, mit Shader das Shaderlicht. Bedeutet hier: mein Shader funktioniert!

Code: Alles auswählen

//-----------------------------------------------------------------------------
//     Name: Simple_Vertex_Shader_with_light.fx
//     Author: Michael Pauwlitz
//    Last Modified: 
//    Description: Easy Vertex Shader with light, Show only the color of the Vertex
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Effect File Variables
//-----------------------------------------------------------------------------

float4x4 worldViewProj : WorldViewProjection; // This matrix will be loaded by the application
float4x4	matWorld       ; // For calculating normals
float3       	lightDir            ; // Our lights direction

//-----------------------------------------------------------------------------
// Vertex Definitions
//-----------------------------------------------------------------------------

// Our sample application will send vertices 
// down the pipeline laid-out like this...

struct VS_INPUT
{
    float3 position	: POSITION;
    float4 normal	: NORMAL0 ;
    float4 color	 : COLOR0;
};

// Once the vertex shader is finished, it will 
// pass the vertices on to the pixel shader like this...

struct VS_OUTPUT
{
    float4 hposition : POSITION;
    float4 color	 : COLOR0;
};

//-----------------------------------------------------------------------------
// Simple Vertex Shader
//-----------------------------------------------------------------------------

VS_OUTPUT myvs( VS_INPUT IN)
{
    VS_OUTPUT OUT;

	OUT.hposition = mul( float4(IN.position.x ,IN.position.y ,IN.position.z, 1) ,worldViewProj); //
	// normalize(a) returns a normalized version of a.
	// in this case, a = -vLightDirection
	float3 L = normalize(-lightDir);
	// transform our normal with matInverseWorld, and normalize it
	float3 N = normalize(mul(IN.normal.xyz, matWorld));
                OUT.color =  IN.color  * saturate(dot(L, N)); 
	return OUT;
}


//-----------------------------------------------------------------------------
// Simple Effect (1 technique with 1 pass)
//-----------------------------------------------------------------------------

technique Technique0
{
    pass Pass0
    {

                VertexShader = compile vs_2_0 myvs();
		PixelShader  = Null;
    }
}
Die Lichtwirklichkeit von Objekten ist aber eine andere. Durch Streulicht wird in der Regel auch die Rückseite eines Objektes beleuchtet. Das haben wir hier noch nicht berücksichtigt. Unter DX9 heißt das Ambient Light also Umgebungslicht. Hier verändern wir den Shader einfach mit ein 10 %tigen Umgebungslicht also:

Code: Alles auswählen

OUT.color =  IN.color  * (0.9*saturate(dot(L, N))+0.1);
Mit diesen Werten kann man auch farblich "rumspielen", z.B. mit einem reinem roten Umgebungslicht...

Code: Alles auswählen

float lichtwert = saturate(dot(L, N));
OUT.color =  IN.color  * (float4(0.6*lichtwert,1*lichtwert,1*lichtwert,1)+float4(0.4,0,0,0)); // float4 (r, g, b, a) -> Rotes umgebungslicht

Shader mit Ambientlight

Code: Alles auswählen

//-----------------------------------------------------------------------------
//     Name: Simple_Vertex_Shader_with_Ambientlight.fx
//     Author: Michael Pauwlitz
//    Last Modified: 
//    Description: Easy Vertex Shader with light, Show only the color of the Vertex
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Effect File Variables
//-----------------------------------------------------------------------------

float4x4 worldViewProj : WorldViewProjection; // This matrix will be loaded by the application
float4x4	matWorld       ; // For calculating normals
float3       	lightDir            ; // Our lights direction

//-----------------------------------------------------------------------------
// Vertex Definitions
//-----------------------------------------------------------------------------

// Our sample application will send vertices 
// down the pipeline laid-out like this...

struct VS_INPUT
{
    float3 position	: POSITION;
    float4 normal	: NORMAL0 ;
    float4 color	 : COLOR0;
};

// Once the vertex shader is finished, it will 
// pass the vertices on to the pixel shader like this...

struct VS_OUTPUT
{
    float4 hposition : POSITION;
    float4 color	 : COLOR0;
};

//-----------------------------------------------------------------------------
// Simple Vertex Shader
//-----------------------------------------------------------------------------

VS_OUTPUT myvs( VS_INPUT IN)
{
    VS_OUTPUT OUT;

	OUT.hposition = mul( float4(IN.position.x ,IN.position.y ,IN.position.z, 1) ,worldViewProj); //
	// normalize(a) returns a normalized version of a.
	// in this case, a = -vLightDirection
	float3 L = normalize(-lightDir);
	// transform our normal with matInverseWorld, and normalize it
	float3 N = normalize(mul(IN.normal.xyz,matWorld));
                OUT.color =  IN.color  * (0.9*saturate(dot(L, N))+0.1); 

	return OUT;
}


//-----------------------------------------------------------------------------
// Simple Effect (1 technique with 1 pass)
//-----------------------------------------------------------------------------

technique Technique0
{
    pass Pass0
    {

                VertexShader = compile vs_2_0 myvs();
		PixelShader  = Null;
    }
}

Gruß Michael
Working on - MP3D Engine -
Benutzeravatar
mpz
Beiträge: 497
Registriert: 14.06.2005 15:53
Computerausstattung: Win 10 Pro, 16 GB Ram, Intel I5 CPU und TI1070 Grafikkarte, PB 5.73 / 6.00 beta4
Wohnort: Berlin, Tempelhof

Re: Tutorial: Vertex Shader & Pixel Shader Unterstützung in

Beitrag von mpz »

Und weiter gehts.

Der Texturshader sieht eigentlich aus wie der Vertexshader, nur das wir die lightnormal dem Pixelshader quasi als fertige Berechnung übergeben müssen.
Das machen wir wie folgt, indem wir den VertexOut eine float4 Farbvariable verpassen und damit lightnormal übergeben können. Diese lightnormal kann dann der Pixelshader einfach auslesen und benutzen.

Code: Alles auswählen

struct VS_OUTPUT
{
    float4 hposition    : POSITION;
    float2 tex0           : TEXCOORD0;
    float4 lightnormal : COLOR0;
};
Danach muss man die Textur nur noch mit dem lightnormal multiplizieren, fertig ist die Beleuchtung

Code: Alles auswählen

//-----------------------------------------------------------------------------
//     Name: Simple_Textur_Shader_with_light.fx
//     Author: Michael Pauwlitz
//    Last Modified: 
//    Description: Easy Texture Shader with light
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Effect File Variables
//-----------------------------------------------------------------------------

float4x4 worldViewProj : WorldViewProjection; // This matrix will be loaded by the application
float4x4	matWorld      ; // For calculating normals
float3       	lightDir            ; // Our lights direction
texture texture0;

sampler Sampler1 = sampler_state 
{ 
texture   = <texture0>;
};

//-----------------------------------------------------------------------------
// Vertex Definitions
//-----------------------------------------------------------------------------

// Our sample application will send vertices 
// down the pipeline laid-out like this...

struct VS_INPUT
{
    float3 position	: POSITION;
    float4 normal	: NORMAL0 ;
    float2 tex0       : TEXCOORD0;
};

// Once the vertex shader is finished, it will 
// pass the vertices on to the pixel shader like this...

struct VS_OUTPUT
{
    float4 hposition    : POSITION;
    float2 tex0           : TEXCOORD0;
    float4 lightnormal : COLOR0;
};

//-----------------------------------------------------------------------------
// Simple Vertex Shader
//-----------------------------------------------------------------------------

VS_OUTPUT myvs( VS_INPUT IN)
{
    VS_OUTPUT OUT;

	OUT.hposition = mul( float4(IN.position.x ,IN.position.y ,IN.position.z, 1) ,worldViewProj); //
	// normalize(a) returns a normalized version of a.
	// in this case, a = vLightDirection
	float3 L = normalize(-lightDir);
	// transform our normal with matInverseWorld, and normalize it
	float3 N = normalize(mul(IN.normal.xyz,matWorld ));
                OUT.lightnormal =  saturate(dot(L, N)); 
                OUT.tex0 = IN.tex0;
	return OUT;
}

float4 myps(VS_OUTPUT IN) : COLOR
{
    return tex2D(Sampler1, IN.tex0 )*IN.lightnormal ;
}

//-----------------------------------------------------------------------------
// Simple Effect (1 technique with 1 pass)
//-----------------------------------------------------------------------------

technique Technique0
{
    pass Pass0
    {

                VertexShader = compile vs_2_0 myvs();
	PixelShader = compile ps_2_0 myps();
    }
}
Auch hier stehen wir dann wieder vor dem Problem des nicht vorhandenen Umgebungslicht. Entweder lösen wir das einfach durch unser 10% Umgebungslicht

Code: Alles auswählen

return tex2D(Sampler1, IN.tex0 )*(IN.lightnormal*0.9+0.1) ;
oder durch eine richtig schöne Formel:

Code: Alles auswählen

AmbientColor* AmbientIntensity + DiffuseIntensity* DiffuseColor* tex2D(Sampler1, IN.tex0 )*IN.lightnormal ;
Der Sinn liegt nur darin das ich dem Shader vorher genau sagen kann wie das Umgebungslicht wirken soll. Aber jeder wie er will...

Code: Alles auswählen

//-----------------------------------------------------------------------------
//     Name: Simple_Textur_Shader_with_light_Ambient.fx
//     Author: Michael Pauwlitz
//    Last Modified: 
//    Description: Easy Texture Shader with light
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Effect File Variables
//-----------------------------------------------------------------------------

float4x4 worldViewProj : WorldViewProjection; // This matrix will be loaded by the application
float4x4	matWorld      ; // For calculating normals
float3       	lightDir            ; // Our lights direction
texture texture0;

// Ambient light
float AmbientColor= 0.8f;
float4 AmbientIntensity= float4(0.075, 0.075, 0.2, 1.0);
	
// Diffuse light
float DiffuseIntensity= 1.0f;
float4 DiffuseColor= float4(1.0,1.0,1.0, 1.0);

sampler Sampler1 = sampler_state 
{ 
texture   = <texture0>;
};

//-----------------------------------------------------------------------------
// Vertex Definitions
//-----------------------------------------------------------------------------

// Our sample application will send vertices 
// down the pipeline laid-out like this...

struct VS_INPUT
{
    float3 position	: POSITION;
    float4 normal	: NORMAL0 ;
    float2 tex0            : TEXCOORD0;
};

// Once the vertex shader is finished, it will 
// pass the vertices on to the pixel shader like this...

struct VS_OUTPUT
{
    float4 hposition    : POSITION;
    float2 tex0           : TEXCOORD0;
    float4 lightnormal : COLOR0;
};

//-----------------------------------------------------------------------------
// Simple Vertex Shader
//-----------------------------------------------------------------------------

VS_OUTPUT myvs( VS_INPUT IN)
{
    VS_OUTPUT OUT;

	OUT.hposition = mul( float4(IN.position.x ,IN.position.y ,IN.position.z, 1) ,worldViewProj); //
	// normalize(a) returns a normalized version of a.
	// in this case, a = vLightDirection
	float3 L = normalize(-lightDir);
	// transform our normal with matInverseWorld, and normalize it
	float3 N = normalize(mul(IN.normal.xyz,matWorld ));
                OUT.lightnormal =  saturate(dot(L, N)); 
                OUT.tex0 = IN.tex0;
	return OUT;
}

float4 myps(VS_OUTPUT IN) : COLOR
{
   return AmbientColor* AmbientIntensity + DiffuseIntensity* DiffuseColor* tex2D(Sampler1, IN.tex0 )*IN.lightnormal ;
}

//-----------------------------------------------------------------------------
// Simple Effect (1 technique with 1 pass)
//-----------------------------------------------------------------------------

technique Technique0
{
    pass Pass0
    {

                VertexShader = compile vs_2_0 myvs();
	PixelShader = compile ps_2_0 myps();
    }
}


Gruß Michael
Working on - MP3D Engine -
Benutzeravatar
mpz
Beiträge: 497
Registriert: 14.06.2005 15:53
Computerausstattung: Win 10 Pro, 16 GB Ram, Intel I5 CPU und TI1070 Grafikkarte, PB 5.73 / 6.00 beta4
Wohnort: Berlin, Tempelhof

Re: Tutorial: Vertex Shader & Pixel Shader Unterstützung in

Beitrag von mpz »

Hi,

nach dem Ambiente Shader geht es an den Glanzlichtshader oder Specular Shader genannt. Dazu sollten wir uns aber erst einmal eine Kugel erzeugen, damit das Glanzlicht auch wirklich sichtbar ist.

Code: Alles auswählen

MP_Graphics3D (640,480,0,3)

;Create Sphere
Sphere1 = MP_CreateSphere(24)
max = MP_CountVertices(Sphere1)-1
For n = 0 To max
         color.f = MP_VertexGetV(Sphere1,  n) * 255
         MP_VertexSetColor(Sphere1, n, MP_ARGB(1,color,0,255-color))
Next
MP_SaveMesh("VertexSphere.x",Sphere1)
Hier die VertexSphere.x zum download
http://www.flasharts.de/mpz/VertexSphere.x

Jetzt kommen wir zu der Berechnung. Ein Glanzlicht ist ein Refelexionslicht. D.h. um es zu berechen benötigen wir noch die Blickrichtung der Kamera als Vector und auch noch die Farbe die leuchten soll die folgenden Funktionen
float4 vecEye -> Blickrichtung der Kamera
float4 SpecularColor -> Farbe des Glanzlichtes

Pow(float x, float y) -> Ergibt x mit dem Exponent y
Hier jetzt der Shader als Vertexshader:

Code: Alles auswählen

//-----------------------------------------------------------------------------
//     Name: Simple_Vertex_Shader_with_light_Specular.fx
//     Author: Michael Pauwlitz
//    Last Modified: 
//    Description: Easy Vertex Shader with light, Show only the color of the Vertex
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Effect File Variables
//-----------------------------------------------------------------------------

float4x4 worldViewProj : WorldViewProjection; // This matrix will be loaded by the application
float4x4	matWorld       ; // For calculating normals
float3       	lightDir            ; // Our lights direction
float4 vecEye;
float4 SpecularColor = float4(0,1,0,0);	// Specular color



//-----------------------------------------------------------------------------
// Vertex Definitions
//-----------------------------------------------------------------------------

// Our sample application will send vertices 
// down the pipeline laid-out like this...

struct VS_INPUT
{
    float3 position	: POSITION;
    float4 normal	: NORMAL0 ;
    float4 color	 : COLOR0;
};

// Once the vertex shader is finished, it will 
// pass the vertices on to the pixel shader like this...

struct VS_OUTPUT
{
    float4 hposition : POSITION;
    float4 color	 : COLOR0;
};

//-----------------------------------------------------------------------------
// Simple Vertex Shader
//-----------------------------------------------------------------------------

VS_OUTPUT myvs( VS_INPUT IN)
{
    VS_OUTPUT OUT;

	OUT.hposition = mul( float4(IN.position.x ,IN.position.y ,IN.position.z, 1) ,worldViewProj); //
	// normalize(a) returns a normalized version of a.
	// in this case, a = vLightDirection
	float3 L = normalize(-lightDir);
	// transform our normal with matInverseWorld, and normalize it
	float3 N = normalize(mul(IN.normal.xyz,matWorld));
               //
              
               float4 PosWorld = mul(OUT.hposition, matWorld);	
               float3 V = normalize(vecEye - PosWorld);

               float Diff = saturate(dot(L, N)); 
               float3 Reflect = normalize(2 * Diff * N - L);  
               float Specular = pow(saturate(dot(Reflect, V)), 20); 
               OUT.color =  IN.color  * Diff  + SpecularColor * Specular; 
               return OUT;
}


//-----------------------------------------------------------------------------
// Simple Effect (1 technique with 1 pass)
//-----------------------------------------------------------------------------

technique Technique0
{
    pass Pass0
    {

                VertexShader = compile vs_2_0 myvs();
	PixelShader  = Null;
    }
}

Gruß Michael
Working on - MP3D Engine -
Benutzeravatar
mpz
Beiträge: 497
Registriert: 14.06.2005 15:53
Computerausstattung: Win 10 Pro, 16 GB Ram, Intel I5 CPU und TI1070 Grafikkarte, PB 5.73 / 6.00 beta4
Wohnort: Berlin, Tempelhof

Re: Tutorial: Vertex Shader & Pixel Shader Unterstützung in

Beitrag von mpz »

Hallo,

hier jetzt die Texturberechnung zu dem Specular Shader. Hier müssen wir im Prinzip die Beleuchtung und die Glanzlichberechnung dem Pixelshader übergeben. Dazu erzeugen wir zwei float4 Color Werte im VS_OUTPUT. Dieser VS_OUTPUT dient dann als Input für den Pixelshader und wird dort weiterberechnet. Auch hier ist es wichtig die Kugel zu laden damit man das Glanzlich sieht...

Code: Alles auswählen

struct VS_OUTPUT
{
    float4 hposition : POSITION;
    float2 tex0           : TEXCOORD0;    
    float4 diff	 : COLOR0;
    float4 spec	 : COLOR1;

};
Im Pixelshader erfolgen dann die Berechnungen

Code: Alles auswählen

AmbientColor* AmbientIntensity = Hintergrundbeleuchtung
SpecularColor * IN.spec = Glanzlicht
DiffuseIntensity* DiffuseColor* tex2D(Sampler1, IN.tex0 )*IN.diff; = Objektbeleuchtung
das ergibt dann:

Code: Alles auswählen

return AmbientColor* AmbientIntensity + SpecularColor * IN.spec + DiffuseIntensity* DiffuseColor* tex2D(Sampler1, IN.tex0 )*IN.diff;
oder wer es einfacher mag:

Code: Alles auswählen

return tex2D(Sampler1, IN.tex0 )*(IN.diff*0.9+0.1) + SpecularColor * IN.spec ;
Und der ganze Shader:

Code: Alles auswählen

//-----------------------------------------------------------------------------
//     Name: Simple_Textur_Shader_with_light_Specular.fx
//     Author: Michael Pauwlitz
//    Last Modified: 
//    Description: Easy Texture Shader with light and specular//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Effect File Variables
//-----------------------------------------------------------------------------

float4x4 worldViewProj : WorldViewProjection; // This matrix will be loaded by the application
float4x4	matWorld       ; // For calculating normals
float3       	lightDir            ; // Our lights direction
float4 vecEye;
float4 SpecularColor = float4(0,1,0,0);	// Specular color
texture texture0;

sampler Sampler1 = sampler_state 
{ 
texture   = <texture0>;
};


//-----------------------------------------------------------------------------
// Vertex Definitions
//-----------------------------------------------------------------------------

// Our sample application will send vertices 
// down the pipeline laid-out like this...

struct VS_INPUT
{
    float3 position	: POSITION;
    float4 normal	: NORMAL0 ;
    float2 tex0            : TEXCOORD0;
};

// Once the vertex shader is finished, it will 
// pass the vertices on to the pixel shader like this...

struct VS_OUTPUT
{
    float4 hposition : POSITION;
    float2 tex0           : TEXCOORD0;    
    float4 diff	 : COLOR0;
    float4 spec	 : COLOR1;

};

//-----------------------------------------------------------------------------
// Simple Vertex Shader
//-----------------------------------------------------------------------------

VS_OUTPUT myvs( VS_INPUT IN)
{
    VS_OUTPUT OUT;

	OUT.hposition = mul( float4(IN.position.x ,IN.position.y ,IN.position.z, 1) ,worldViewProj); //
	// normalize(a) returns a normalized version of a.
	// in this case, a = vLightDirection
	float3 L = normalize(-lightDir);
	// transform our normal with matInverseWorld, and normalize it
	float3 N = normalize(mul(IN.normal.xyz,matWorld));
               //
              
               float4 PosWorld = mul(OUT.hposition, matWorld);	
               float3 V = normalize(vecEye - PosWorld);

               float Diff = saturate(dot(L, N)); 
               float3 Reflect = normalize(2 * Diff * N - L);  
               float Specular = pow(saturate(dot(Reflect, V)), 20); 

               OUT.diff =  Diff ;
               OUT.spec = Specular ;
               OUT.tex0 = IN.tex0;
               return OUT;
}

float4 myps(VS_OUTPUT IN) : COLOR
{
 
	// Ambient light
	float AmbientColor= 0.8f;
	float4 AmbientIntensity= float4(0.075, 0.075, 0.2, 1.0);
	
	// Diffuse light
	float DiffuseIntensity= 1.0f;
	float4 DiffuseColor= float4(1.0,1.0,1.0, 1.0);
              return AmbientColor* AmbientIntensity + SpecularColor * IN.spec + DiffuseIntensity* DiffuseColor* tex2D(Sampler1, IN.tex0 )*IN.diff;

}

//-----------------------------------------------------------------------------
// Simple Effect (1 technique with 1 pass)
//-----------------------------------------------------------------------------

technique Technique0
{
    pass Pass0
    {

                VertexShader = compile vs_2_0 myvs();
	PixelShader = compile ps_2_0 myps();
    }
}

Gruß Michael
Working on - MP3D Engine -
Benutzeravatar
mpz
Beiträge: 497
Registriert: 14.06.2005 15:53
Computerausstattung: Win 10 Pro, 16 GB Ram, Intel I5 CPU und TI1070 Grafikkarte, PB 5.73 / 6.00 beta4
Wohnort: Berlin, Tempelhof

Re: Tutorial: Vertex Shader & Pixel Shader Unterstützung in

Beitrag von mpz »

Hallo,

heute geht es um ein wichtiges Kapitel bei Shadern den Movment bzw den bewegten Shadern. Dazu benötigen wir erst einmal einen FlächenMesh mit einigen Dreiecksflächen. In MP3d schnell gemacht mit

Code: Alles auswählen

MP_Graphics3D (640,480,0,3) ; Erstelle ein WindowsFenster #Window = 0
;Create Plane
Plane1 = MP_Createplane (20,12)
MP_SaveMesh("Flagge.x",Plane1)
Danach etwas malen in Paint um eine Textur zu erzeugen, z.B. mit den Farben schwarz, rot und gelb.
Für Euch natürlich auch zum download

http://www.flasharts.de/mpz/flagge.x
http://www.flasharts.de/mpz/Flagge.JPG

im Shadereditor wird das Mesh Flagge.x geladen und als texture0 die flagge.jpg

Vom Shadereditor übergeben Variablen:
worldViewProj -> Weltposition vom Editor übergeben
texture0 -> geladene Textur, z.B. "flagge.jpg"
time -> die laufende Zeit in ms

Heute werden wir ein paar Dinge vereinfachen. Den Pixelshader reduzieren wir z.B. auf

Code: Alles auswählen

Sampler[0] = (Sampler1); // Needed by pixel shader
um den Mesh verändern zu können übergeben wir die Vertexkoordinaten einer float4 v Variablen

Code: Alles auswählen

float4 v = float4( IN.position.x, IN.position.y, IN.position.z, 1.0f );
v können wir jetzt ganz einfach manipulieren

Wenn man jetzt

Code: Alles auswählen

v = v + 1;
schreiben will kann man das auch

Code: Alles auswählen

v += 1 
schreiben.

Jetzt wollen wir als Erstes eine Sinuswelle über das Mesh laufen lassen. Dazu benutzen wir die Vertex x Koordinate um den Vertex z Wert (tiefe) zu verändern.
und los gehts:

Code: Alles auswählen

//-----------------------------------------------------------------------------
//           Name: MoveSin.fx
//         Author: Michael Paulwitz
//  Last Modified: 28.10.09
//    Description: move Mesh with sin
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Effect File Variables
//-----------------------------------------------------------------------------

float4x4 worldViewProj : WorldViewProjection; // This matrix will be loaded by the application
texture texture0;
float time;

sampler Sampler1 = sampler_state 
{ 
texture   = <texture0>;
};

//-----------------------------------------------------------------------------
// Vertex Definitions
//-----------------------------------------------------------------------------

// Our sample application will send vertices 
// down the pipeline laid-out like this...

struct VS_INPUT
{
    float3 position	: POSITION;
    float2 texture0     : TEXCOORD0;
};

// Once the vertex shader is finished, it will 
// pass the vertices on to the pixel shader like this...

struct VS_OUTPUT
{
    float4 hposition : POSITION;
    float2 texture0  : TEXCOORD0;
};


//-----------------------------------------------------------------------------
// Simple Vertex Shader
//-----------------------------------------------------------------------------

VS_OUTPUT myvs( VS_INPUT IN )
{
    VS_OUTPUT OUT;

        float4 v = float4( IN.position.x, IN.position.y, IN.position.z, 1.0f );

        v.z += sin( v.x+time) ;

        OUT.hposition = mul( v, worldViewProj   );
        OUT.texture0 = IN.texture0;
        return OUT;
}

//-----------------------------------------------------------------------------
// Simple Effect (1 technique with 1 pass)
//-----------------------------------------------------------------------------

technique flag
{
    pass Pass0
    {
		Sampler[0] = (Sampler1); // Needed by pixel shader
		VertexShader = compile vs_2_0 myvs();
    }
}
eine Bewegung von oben nach unten erreicht man durch

Code: Alles auswählen

v.z += sin( v.y+time) ;


man kann auch beide Bewegungen addieren um ein schönes Wellenmuster zu erzeugen

Code: Alles auswählen

v.z += sin( v.x+time) ;
v.z += sin( v.y+time) ;


Ihr seht diese Bewegungsfolgen lassen sich für viele Dinge der Umgebung anwenden:

Wellen, Fahne im Wind, Gras und Bäume und und und

Gruß Michael
Working on - MP3D Engine -
Antworten