Du bist nicht angemeldet.

Werbeanzeige

1

07.05.2014, 17:18

OpenGl - Shader mehrere Objekte

Hallo liebes Forum,

Habe mich neuerdings in OpenGl Shader eingearbeitet. Habe dazu auch ein Tutorial gemacht, in dem ein Dreieck gezeichnet und bewegt wird.
Nun habe ich folgende Fragen...

1. In den meisten Tutorial sehe ich nur ein Objekt (Dreieck) das durch den Vertex Shader bewegt wird.
Wie geht man bei mehreren Objekten vor? Eine eigene Matrix für jedes Objekt im Shader?

2. Die Shader laufen ja auf der GPU. Sollte man dort beim Programmieren auf die Performance achten?
Meine Grafikkartentemperatur geht deutlich hoch, wenn ich ein Shader programm laufen lasse.

3. Wie werden heutzutage indie games programmiert? Laufen die alle mit Shader oder Programmieren manche noch im immediate mode :).

Danke

BlueCobold

Community-Fossil

Beiträge: 10 859

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

07.05.2014, 17:21

Nicht im Immediate Mode zu arbeiten heißt nicht automatisch Shader zu verwenden. Im Immediate Mode sollte man allerdings keinsfalls mehr arbeiten.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

3

07.05.2014, 17:36

Mehrere Objekte bewegen.

Ja natürlich, aber mir ist es schleierhaft wie man ohne Matrix Stacks mehrere Objekte bewegen kann.
Wenn ich z.B. in einem Spiel einen Spieler, Gegner und das Level unabhängig voneinander bewegen will.

BlueCobold

Community-Fossil

Beiträge: 10 859

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

4

07.05.2014, 18:16

Wo ist denn das Problem des Verständnisses? Du kannst doch für jedes Objekt eine andere Transformation durchführen.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

5

07.05.2014, 18:17

Dafür gibt es mehrere Ansätze.

Der einfachste ist, für jedes Objekt während eines Shaderpasses, eine Draw Methode aufzurufen.
Pseudocode:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
BeginScene();
BeginShader();
for (int p = 0; p < NumPasses(); ++p)
{
    BeginPass(p);
    for (int i = 0; i < 500; ++i) // for each object
    {
        Matrix4x4 world = WorldMatrixFromPosition(objects[i].position);          
        SetShaderMatrix("WorldMatrix", world); // etc...
        DrawObject();
    }
    EndPass();
}
EndShader();
EndScene();


Dieser Ansatz ist jedoch unperformant, da jeder API Call (DrawObject()) warten muss, bis die GPU mit dem aktuellen Vorgang fertig ist.
Daher gibt es andere Ansätze, wie Geometry Instancing, was in etwa so aussieht (Pseudocode):

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
BeginScene();
BeginShader();
for (int p = 0; p < NumPasses(); ++p)
{
    BeginPass(p);
    SetInstanceData(instances, 500); // 500 = Anzahl der instances. Jeder Instance-Data Eintrag enhält Informationen zu Position und verwendeter Geometrie
    SetGeometryData(geometry);
    EndPass();
}
EndShader();
EndScene();
EnvisionGame(); EnableGame(); AchieveGame(); - Visionen kann man viele haben. Sie umzusetzen und auf das Ergebnis stolz zu sein ist die eigentliche Kunst.

DeKugelschieber

Community-Fossil

Beiträge: 2 664

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

6

07.05.2014, 18:38

Instanced rendering ist für den Anfang etwas übertrieben, du kannst hier anfangen:

Uniform
etwas weiter dann: UBO
und dann instanced...

7

07.05.2014, 20:36

Ahhhhhhhh ich volldepp... ich habe es jetzt glaub verstanden.

bei folgendem Shader

C-/C++-Quelltext

1
2
3
4
void main()
{
    gl_Position = transform * vec4(position, 1.0); // transform matrix4x4
}


mache ich die transform Matrix uniform und update sie immer vor dem zeichnen.

C-/C++-Quelltext

1
2
3
4
shader.Update(transform1);
mesh1.Draw();
shader.Update(transform2);
mesh2.Draw();



Ist das korrekt so?

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »DerUltraLord« (07.05.2014, 20:44)


8

07.05.2014, 20:55

Richtig. Beachte, dass du oben einen Punkt transformierst und Punkte eine w Koordinate von 0 haben sollte.
EnvisionGame(); EnableGame(); AchieveGame(); - Visionen kann man viele haben. Sie umzusetzen und auf das Ergebnis stolz zu sein ist die eigentliche Kunst.

9

07.05.2014, 21:11

Vielen Dank für die Hilfe!!!

SlinDev

Treue Seele

Beiträge: 143

Wohnort: Lübeck

Beruf: Programmierer

  • Private Nachricht senden

10

07.05.2014, 21:25

Das ist falsch, die w Koordinate von 1 ist korrekt, wenn da eine 0 steht, dann klappt das mit der Translation nicht mehr:

Quellcode

1
2
3
4
5
6
7
8
9
10
1 0 0 3     0      3
0 1 0 3  *  0  =   3
0 0 1 3     0      3
0 0 0 1     1      1


1 0 0 3     0      0
0 1 0 3  *  0  =   0
0 0 1 3     0      0
0 0 0 1     0      0



Nicht im Immediate Mode zu arbeiten heißt nicht automatisch Shader zu verwenden.

Der Immediate Mode hat nichts mit Shadern zu tun. Shader sind seit einigen Jahren fester Bestandteil der Renderpipeline, die alte fixed function pipeline gibt es schon lange nicht mehr. Wenn du nicht selbst explizit Shader nutzt dann müssen sich die Treiber darum kümmern das alte verhalten mithilfe von Shadern zu emulieren. Also indirekt nutzt man immer Shader, von daher wird man von neuerem DirectX und OpenGL auch dazu gezwungen immer explizit Shader anzugeben.

Werbeanzeige