3D Framework gesucht

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von jvbsl.

    3D Framework gesucht

    Hi,
    ​ich habe mir ein Tool gebaut um einige 3D Modelle aus einem alten PS1 Spiel zu extrahieren. Diese haben auch Animationen (Vertexanimationen). Es gibt also N Frames und für jedes Frame gibt es ein 3D Modell. Die Anzahl der Vertices ist immer gleich nur die Positionen nicht. Mein Ziel ist es so eine Animation als schickes transparentes Gif zu rendern.
    ​Da das Ganze aber einen eigenen Shader braucht komm ich mit Blender nicht klar. Kann mir jemand ein möglichst einfaches Framework empfehlen mit dem ich mit nem eigenen Shader auf eine Textur rendern kann? Ggf. auch ein paar Links zu Tutorials und Doku?

    ​Grüße
    Versucht hatte ichs aber es will nicht ^^ Im Grunde gibt es einmal Vertexcolour, Texture, Normals und ein Alphamode. Hat ein Dreieck Uvs dann wird die Farbe so berechnet: VertexColour*TextureColour*2. Ansonsten ist es nur VertexColour. Als Alphamode gibt es Solid, Invert, Alpha und etwas was Glasähnlich aussieht. Wie die Normals gerendert werden muss ich nochmal untersuchen. Schwarze Pixel sind immer transparent. Es gibt auch noch diverse Sonderfälle. Das müsste ich auch alles in irgendeinem Dateiformat in Blender importieren können. Monogame klappt aber ganz gut im Moment. Ich hänge gerade beim Rendern der Textur, aber ich glaube das wird die Lösung.
    Wenn du so fragst ja 8o . Ich hole mal etwas aus: Die Daten lese ich mit meinem Exporter in diese Klasse, serialisiere die und lade die dann ins Game
    Spoiler anzeigen

    C#-Quellcode

    1. [Serializable]
    2. public class Model3D
    3. {
    4. public Model3D()
    5. {
    6. Vertices = new List<Point3D>();
    7. Polygons = new List<Polygon>();
    8. Colours = new List<Point3D>();
    9. Uvs = new List<Point>();
    10. Normals = new List<Vector3D>();
    11. Uvs.Add(new Point(0, 0));
    12. }
    13. public List<Point3D> Vertices { get; set; }
    14. public List<Point3D> Colours { get; set; }
    15. public List<Polygon> Polygons { get; set; }
    16. public List<Point> Uvs { get; set; }
    17. public List<Vector3D> Normals { get; set; }
    18. }
    19. [Serializable]
    20. public struct Polygon
    21. {
    22. public int P1, P2, P3;
    23. public int C1, C2, C3;
    24. public int Uv1, Uv2, Uv3;
    25. public int N;
    26. public bool Overlap;
    27. public AlphaModes Alpha;
    28. }

    Polygon hat jeweils Indizes für Uvs, Vertices, Colours und Normals aus Model3D. Das Ganze packe ich dann in einen VertexBuffer.Hier ist mein Shader
    Spoiler anzeigen

    Quellcode

    1. float4x4 World;
    2. float4x4 View;
    3. float4x4 Projection;
    4. struct VertexShaderInput
    5. {
    6. float4 vertex : POSITION0;
    7. float3 colour : COLOR0;
    8. float2 uv : TEXCOORD0;
    9. };
    10. struct VertexShaderOutput
    11. {
    12. float4 vertex : POSITION0;
    13. float4 colour : COLOR0;
    14. float2 uv : TEXCOORD0;
    15. };
    16. texture ModelTexture;
    17. sampler2D textureSampler = sampler_state
    18. {
    19. Texture = (ModelTexture);
    20. MinFilter = Linear;
    21. MagFilter = Linear;
    22. AddressU = Clamp;
    23. AddressV = Clamp;
    24. };
    25. VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
    26. {
    27. VertexShaderOutput output;
    28. float4 worldPosition = mul(input.vertex, World);
    29. float4 viewPosition = mul(worldPosition, View);
    30. output.vertex = mul(viewPosition, Projection);
    31. output.colour = float4(input.colour.rgb, 1);
    32. output.uv = input.uv;
    33. return output;
    34. }
    35. float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
    36. {
    37. float4 textureColour = tex2D(textureSampler, input.uv);
    38. if (input.uv.x <= 0 && input.uv.y <= 0)
    39. {
    40. return input.colour;
    41. }
    42. else
    43. {
    44. return textureColour*input.colour*2.0f;
    45. }
    46. }
    47. technique Ambient
    48. {
    49. pass Pass1
    50. {
    51. VertexShader = compile vs_4_0_level_9_1 VertexShaderFunction();
    52. PixelShader = compile ps_4_0_level_9_1 PixelShaderFunction();
    53. }
    Im Anhang befindet sich das Ergebnis. Ist der Shader so korrekt um meine Textur zu rendern? Nur VertexColour sieht gut aus. Texture allerdings nicht so ganz.
    Bilder
    • Texture.gif

      7,77 MB, 816×518, 127 mal angesehen
    • VertexColour.gif

      8,09 MB, 816×518, 140 mal angesehen
    Hi:
    Wieso

    C#-Quellcode

    1. if (input.uv.x <= 0 && input.uv.y <= 0)
    2. {
    3. return input.colour;
    4. }
    5. else
    6. {
    7. return textureColour*input.colour*2.0f;
    8. }

    ?

    Apropos: Wieso lädst du die Normalen hoch, wenn du sie gar nicht verwendest?
    Meine Vorgehensweise bei sowas ist immer, Stück für Stück eine Vertex-Deklaration aufzubauen und die Effekte dann zu beobachten.
    Quasi "Shader-Debugging".

    Darf ich mal schauen wie deine Deklaration aussieht?
    Und Gott alleine weiß alles am allerbesten und besser.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „φConst“ ()

    Die Normalen lade ich auch noch garnicht in den Shader. Ich hatte es erst nur mit Vertexcolour probiert, nachdem das dann geklappt hat, hab ich's mit Texture versucht.
    Nicht jedes Vertex hat eine UV-Koordinate. Ist keine da, soll nur die Vertexcolour benutzt werden. Falls UVs da sind, wird Vertexcolour*TextureColour*2 genommen.

    Spoiler anzeigen

    C#-Quellcode

    1. public static VertexBuffer GetBuffer(Frame f, GraphicsDevice dev, out double max, out double hx, out double hy, out double hz)
    2. {
    3. VertexBuffer buffer = new VertexBuffer(dev, typeof(VertexPositionColorTexture), f.Data.Vertices.Count, BufferUsage.WriteOnly);
    4. List<VertexPositionColorTexture> data = new List<VertexPositionColorTexture>(f.Data.Vertices.Count);
    5. var verts = ScaleVerts(f, out max, out hx, out hy, out hz); // Hier werden die Vertices nur skaliert
    6. for(int i = 0; i < f.Data.Vertices.Count; ++i)
    7. {
    8. VertexPositionColorTexture v = new VertexPositionColorTexture();
    9. var pos = verts[i];
    10. int cIndex = GetColourIndex(i, f);
    11. int uvIndex = GetUvIndex(i, f);
    12. if(cIndex != -1)
    13. {
    14. var c = f.Data.Colours[cIndex];
    15. v.Color = new Color((float)c.X, (float)c.Y, (float)c.Z, 1.0f);
    16. }
    17. else
    18. {
    19. v.Color = new Color(0, 0, 0, 255);
    20. }
    21. if (uvIndex != -1)
    22. v.TextureCoordinate = new Vector2((float)f.Data.Uvs[uvIndex].X, (float)f.Data.Uvs[uvIndex].Y);
    23. else
    24. v.TextureCoordinate = new Vector2(-1, -1);
    25. v.Position = new Vector3((float)pos.X, (float)pos.Y, (float)pos.Z);
    26. data.Add(v);
    27. }
    28. buffer.SetData(data.ToArray());
    29. return buffer;
    30. }
    31. private static int GetUvIndex(int vert, Frame f)
    32. {
    33. foreach (Polygon p in f.Data.Polygons)
    34. {
    35. if (p.P1 == vert)
    36. return p.Uv1;
    37. if (p.P2 == vert)
    38. return p.Uv2;
    39. if (p.P3 == vert)
    40. return p.Uv3;
    41. }
    42. return -1;
    43. }

    So versuche ich die Daten zu übersetzen. Blöd ist, dass die ganzen Vertexattribute bezogen auf die Faces sind. Jetzt versuche ich mit GetUvIndex() alle Faces zu durchlaufen und wenn ein Face == Vertex ist, dann nimmt er sich die UV-Koordinate aus dem Face. Hier vermute ich noch irgendwo einen Fehler.
    So, ich hab neue Erkenntnisse. Zuerst habe ich den Shader geändert, ohne Änderung. Danach hab ich die Funktion zum schreiben der UVs in den VertexBuffer erneuert. Leider auch ohne Änderung. Dann hab ich den Bock aber gefunden!

    C#-Quellcode

    1. [Serializable]
    2. public class Model3D
    3. {
    4. public Model3D
    5. {
    6. Vertices = new List<Point3D>();
    7. Colours = new List<Point3D>();
    8. Polygons = new List<Polygons>();
    9. Uvs = new List<Point>();
    10. Normals = new List<Vector3D>();
    11. Uvs.Add(new Point(0, 0));
    12. }
    13. public List<Point3D> Vertices { get; set; }
    14. public List<Point3D> Colours { get; set; }
    15. public List<Polygon> Polygons { get; set; }
    16. public List<Point> Uvs { get; set; }
    17. public List<Vector3D> Normals { get; set; }
    18. }

    Ich hatte die Klasse einach per C&P aus meinem Exporter kopiert. Nach dem Deserialisieren wird aber dummerweise im Konstruktor ein (0, 0) UV hinzugefügt. Konstruktor entfernt und direkt sah es ganz anders aus ^^
    Seltsamerweise muss ich die V-Koordinate noch invertieren, aber dann klappt es wie gewollt :thumbup:
    Hier ist nochmal der Shader
    Spoiler anzeigen

    C-Quellcode

    1. float4x4 World;
    2. float4x4 View;
    3. float4x4 Projection;
    4. float4 BaseColour = float4(1, 1, 1, 1);
    5. struct VertexShaderInput
    6. {
    7. float4 vertex : POSITION0;
    8. float3 colour : COLOR0;
    9. float2 uv : TEXCOORD0;
    10. };
    11. struct VertexShaderOutput
    12. {
    13. float4 vertex : POSITION0;
    14. float4 colour : COLOR0;
    15. float2 uv : TEXCOORD0;
    16. };
    17. Texture2D Texture : register(t0);
    18. sampler2D textureSampler : register(s0)
    19. {
    20. Texture = (Texture);
    21. };
    22. VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
    23. {
    24. VertexShaderOutput output;
    25. float4 worldPosition = mul(input.vertex, World);
    26. float4 viewPosition = mul(worldPosition, View);
    27. output.vertex = mul(viewPosition, Projection);
    28. output.colour = float4(input.colour.rgb, 1);
    29. output.uv = input.uv;
    30. return output;
    31. }
    32. float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
    33. {
    34. float4 textureColour = tex2D(textureSampler, input.uv);
    35. if (input.uv.x < 0 && input.uv.y < 0)
    36. {
    37. return BaseColour*input.colour;
    38. }
    39. else
    40. {
    41. if (textureColour.x == 0 && textureColour.y == 0 && textureColour.z == 0)
    42. discard;
    43. return BaseColour*textureColour*input.colour*2.0f;
    44. }
    45. }
    46. technique
    47. {
    48. pass Pass
    49. {
    50. VertexShader = compile vs_4_0_level_9_1 VertexShaderFunction();
    51. PixelShader = compile ps_4_0_level_9_1 PixelShaderFunction();
    52. }
    53. }
    Bilder
    • Texture Neu.gif

      7,05 MB, 816×518, 108 mal angesehen
    in OpenGL sind Texturkoordinaten auf der Y-Achse gedreht(also näher an der Mathematik, aber nicht so wie für programmierer inzwischen gewohnt). MonoGame verwendet aber die Richtung von XNA/DirectX und es scheint das exportierte Format scheint eben auch gleich wie OpenGL zu arbeiten oder zumindest so abgespeichert haben.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---