| |
Kevin Member
Anmeldedatum: 24.10.2008 Beiträge: 882 Wohnort: Karlsruhe
|
Verfasst 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  _________________ Mein Youtube Kanal |
|
| Nach oben |
|

|
Levitas Member
Anmeldedatum: 25.08.2008 Beiträge: 417
|
Verfasst am: 22.08.2009, 21:58 Titel: |
|
Cooles tut, danke kevin! Sollte in die Artikel rein, oder nicht?
Mfg Marc _________________
|
|
| Nach oben |
|

|
Kevin Member
Anmeldedatum: 24.10.2008 Beiträge: 882 Wohnort: Karlsruhe
|
Verfasst 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
MfG
Kevin _________________ Mein Youtube Kanal |
|
| Nach oben |
|

|
denjo303 Member
Anmeldedatum: 04.07.2009 Beiträge: 175 Wohnort: Stuttgart
|
Verfasst am: 23.08.2009, 09:40 Titel: |
|
!!!!!!!!!!!!!!!! GENAU sowas such ich seit wochen
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.
Ich bin in diesen Shader Geschichten noch ein blutiger Anfänger... wollt ich nur kurz sagen |
|
| Nach oben |
|

|
pdelvo Member
Anmeldedatum: 21.02.2009 Beiträge: 231
|
Verfasst 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 |
|

|
denjo303 Member
Anmeldedatum: 04.07.2009 Beiträge: 175 Wohnort: Stuttgart
|
Verfasst am: 23.08.2009, 12:27 Titel: |
|
ohhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh, ok, ich hab vor lauter lesen die ersten zeilen "vergesen"....lol
alles klar, danke |
|
| Nach oben |
|

|
|
|
|