ProfilProfil
 Registrieren
 Login
Bild der WocheBild der Woche

(von Backslider)
Kommentare (0)
****

Weitere
User onlineBenutzer online
Gäste online: 8
Mitglieder online: Keine
Registrierte Mitglieder: 2116
Neustes Mitglied: onkel_keks

Vertex Shader Einführung - Rendern eines 3D Models

Neue Antwort erstellen
 

 

Autor Nachricht
 
 
Kevin
Member


Anmeldedatum: 24.10.2008
Beiträge: 882
Wohnort: Karlsruhe

Antworten mit Zitat
BeitragVerfasst am: 22.08.2009, 18:18    Titel: Vertex Shader Einführung - Rendern eines 3D Models

Einführung:
In diesem Tutorial werde ich euch zeigen, wie man ein 3D Model mit einem eigenen Shader rendert.
Ihr solltet dazu bereits die Grundlagen der 3D Programmierung kennen, und zumindest wissen wie man
ein 3D Model mit dem Basic Effect rendert.
Das Tutorial wird hauptsächlich erklären wie man Vertex Shader verwendet.
Die Hauptaufgabe eines Vertex Shaders ist es, die Vertices vom Local Space zum Screen Space zu transformieren.
Der Weg dahin sieht in etwa folgendermaßen aus:

Local Space (mit World Matrix multiplizieren) -> World Space (mit View Matrix multiplizieren) ->
View Space (mit Projection Matrix multiplizieren) -> Screen/Projection Space

Shader Code:

Wir werden als erstes einige Matrizen benötigen:

Code:

float4x4 World;         //beinhaltet die Transformation des Objekts
float4x4 View;         //die View Matrix der Camera
float4x4 Projection;      //die Projection Matrix der Camera


Die deklarierten Matrizen sind allesamt 4x4 Matrizen, die HLSL unterstützt aber z.B. auch 3x3
Matrizen, die dann beispielsweise nur die Rotation und Skalierung einer World Matrix enthalten würde.

Da wir unser 3D Model später auch texturiert rendern wollen, benötigen wir eine texture Variable und einen
entsprechenden Sampler:

Code:

texture Diffuse;      //die Diffuse Textur enthält die Farbinformationen
//Sampler speichern unsere Texturen, und erlauben uns, später darauf zuzugreifen.
sampler DiffuseSampler = sampler_state {
   Texture = <Diffuse>;   //Die Textur, die der Sampler beinhalten soll.
};


Nun zum Vertex Shader:
Der Vertex Shader hat natürlich so wie der Pixel Shader einen Input und einen Output.
In unserem Fall ist der Input einmal die Local Position und Textur Koordinate.
Der Output ist die Screen Position und die Textur Koordinate, da die Textur erst im Pixel Shader
angewendet wird.
Da wir mehrere Input und Output Parameter haben, packen wir sie der übersichtshalber in structs:

Code:

struct VertexShaderInput
{
    float4 Position : POSITION0;
    float2 TexCoord : TEXCOORD0;
};   //; nicht vergessen (für alle C#ler :) )!!!

struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float2 TexCoord : TEXCOORD0;
};


Unser leerer Vertex Shader würde nun folgendermaßen aussehen:

Code:

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;   //Unser Output struct

    return output;
}



Jetzt müssen wir nur noch die output Parameter setzen, was aber auch kein
Hexenwerk ist:

Code:

    float4 worldPosition = mul(input.Position, World);      //Local Space -> World Space
    float4 viewPosition = mul(worldPosition, View);      //World Space -> View Space
    output.Position = mul(viewPosition, Projection);   //View Space  -> Screen/Projection Space
    output.TexCoord = input.TexCoord;      //Die Textur Koordinaten werden direkt an den Pixelshader weitergereicht


Und das wars auch schon mit dem Vertex Shader!

Nun zum Pixel Shader:
Der Pixel Shader erhält als Input den VertexShaderOutput, und hat als Output eine float4 COLOR.
Deshalb sieht der Pixel Shader so aus:

Code:

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
    //Das liefert die entsprechende Farbe (abhängig von der Tex Coord) aus der Textur:
    float4 diffuseColor = tex2D(DiffuseSampler, input.TexCoord);
   
    //Hier könnte man noch Licht dazu berechnen, Normal Mapping und Parralax Mapping anwenden, etc.
   
    return diffuseColor;
}


Jetzt nur noch die Technique:

Code:

technique ModelRender
{
    pass Pass1
    {
        VertexShader = compile vs_1_1 VertexShaderFunction();
        PixelShader = compile ps_1_1 PixelShaderFunction();
    }
}



XNA/C# Code:
Zuerst benötigen wir die View und Projection Matrix, dazu verwendet ihr entweder eure eigene
Camera Klasse oder ihr nehmt den Code:

Code:

view = Matrix.CreateLookAt(new Vector3(-25, 15, -40), new Vector3(0, 0, 0), Vector3.Up);
proj = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, GraphicsDevice.Viewport.AspectRatio, 1.0f, 10000.0f);


Nun müsst ihr den Effect und ein 3D Model laden:
Code:

model = Content.Load<Model>("Ship");
myEffect = Content.Load<Effect>("ModelRender");


Das 3D Model hat standardgemäß immer Basic Effects, deshalb müssen wir das erstmal ändern (die elegantere Lösung
wäre das in einem Custom Content Processor zu tun):

Code:

foreach (ModelMesh mesh in model.Meshes) {
   //Jedes MeshPart hat seinen eigenen Effect.
   foreach (ModelMeshPart part in mesh.MeshParts) {
      //Der neue Effect wird von unserem geladenen Effect geklont.
      Effect newEffect = myEffect.Clone(GraphicsDevice);
      //Wir müssen uns die Textur des Basic Effects merken.
      Texture2D texture = ((BasicEffect)part.Effect).Texture;
      //Nun können wir unseren Diffuse Textur Parameter setzen.
      newEffect.Parameters["Diffuse"].SetValue(texture);
      //Und schließlich noch den neuen Effect als Standard Effect für den Mesh Part
      //setzen.
      part.Effect = newEffect;
   }
}


So, nun ist das rendern aber auch nicht mehr schwer:

Code:

foreach (ModelMesh mesh in model.Meshes) {
   foreach (Effect effect in mesh.Effects) {
      effect.Parameters["World"].SetValue(Matrix.Identity);
      effect.Parameters["View"].SetValue(view);
      effect.Parameters["Projection"].SetValue(proj);
   }
   mesh.Draw();
}


Das Resultat sollte ein texturiertes 3D Model sein. Falls ihr irgendwo schwarze Stellen am 3D Model
seht, liegt das daran, dass es an dieser Stelle wahrscheinlich keine Textur gab, sondern lediglich eine
Vertex Color, die wir in unserem Shader aber nicht beachtet haben.

Kommentare erwünscht Very Happy
_________________
Mein Youtube Kanal
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden


Levitas
Member


Anmeldedatum: 25.08.2008
Beiträge: 417

Antworten mit Zitat
BeitragVerfasst am: 22.08.2009, 21:58    Titel:

Cooles tut, danke kevin! Sollte in die Artikel rein, oder nicht?

Mfg Marc
_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen ICQ-Nummer


Kevin
Member


Anmeldedatum: 24.10.2008
Beiträge: 882
Wohnort: Karlsruhe

Antworten mit Zitat
BeitragVerfasst am: 22.08.2009, 22:33    Titel:

Levitas hat Folgendes geschrieben:
Cooles tut, danke kevin! Sollte in die Artikel rein, oder nicht?

Mfg Marc


Danke,
wenn die Moderatoren Lust dazu haben, können sie es gerne machen, ich habe das Tutorial geschrieben, da das Vertex Shader Tutorial
ja hier sonst gar nicht mehr erscheint Very Happy

MfG
Kevin
_________________
Mein Youtube Kanal
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden


denjo303
Member


Anmeldedatum: 04.07.2009
Beiträge: 175
Wohnort: Stuttgart

Antworten mit Zitat
BeitragVerfasst am: 23.08.2009, 09:40    Titel:

!!!!!!!!!!!!!!!! GENAU sowas such ich seit wochen Very Happy Very Happy Very Happy

Echt Super, ich hatte immer ein weig probleme mit texturen

EDIT: Noch ne frage??

Hier der Code:
Code:
texture Diffuse;     

sampler DiffuseSampler = sampler_state {
   Texture = <Diffuse>; 
};

struct VertexShaderInput
{
    float4 Position : POSITION0;
    float2 TexCoord : TEXCOORD0;
};

struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float2 TexCoord : TEXCOORD0;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;
    float4 worldPosition = mul(input.Position, World);     
    float4 viewPosition = mul(worldPosition, View);     
    output.Position = mul(viewPosition, Projection);
    output.TexCoord = input.TexCoord;     
    return output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
   
    float4 diffuseColor = tex2D(DiffuseSampler, input.TexCoord);
   
    return diffuseColor;
}
technique ModelRender
{
    pass Pass1
    {
        VertexShader = compile vs_1_1 VertexShaderFunction();
        PixelShader = compile ps_1_1 PixelShaderFunction();
    }
}


Ich bekomm jetzt beim Compilieren folgendes
Zitat:

Content\VertexShader.fx(23,1): error : Errors compiling D:\Projekte C#\tGame\tGame\Content\VertexShader.fx:
Content\VertexShader.fx(23,1): error : D:\Projekte C#\tGame\tGame\Content\VertexShader.fx(23): error X3004: undeclared identifier 'World'


Was hab ich falsch gemacht. Confused

Ich bin in diesen Shader Geschichten noch ein blutiger Anfänger... wollt ich nur kurz sagen
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden MSN Messenger


pdelvo
Member


Anmeldedatum: 21.02.2009
Beiträge: 231

Antworten mit Zitat
BeitragVerfasst am: 23.08.2009, 11:54    Titel:

Ist doch ganz klar. Laut der Fehlermeldung kann er keine Variable 'World' finden. Siehst du eine? Du must eine definieren und dann bevor du den Shader benutz setzen.

Gruß pdelvo
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden


denjo303
Member


Anmeldedatum: 04.07.2009
Beiträge: 175
Wohnort: Stuttgart

Antworten mit Zitat
BeitragVerfasst am: 23.08.2009, 12:27    Titel:

ohhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh, ok, ich hab vor lauter lesen die ersten zeilen "vergesen"....lol

alles klar, danke
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden MSN Messenger


Beiträge der letzten Zeit anzeigen:   
 
Neue Antwort erstellen Alle Zeiten sind GMT + 1 Stunde
Seite 1 von 1

 
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.


Powered by phpBB © 2001, 2005 phpBB Group
Deutsche Übersetzung von phpBB.de