GL ES: Fragment-Shader-Optimierung

8

Zusammenfassung: Ich bekomme eine FPS-Verlangsamung, sobald ich versuche, die Sprites zu tönen (dh: Textur mit Fragment im Fragment-Shader multiplizieren)

Einzelheiten:

Hardware: iPod touch 4

Ich zeichne 700 Sprites mit glDrawArrays auf dem Bildschirm. Und ja, ich staple all dies in einem einzigen Draw Call. Das Folgende zeigt die Vertex-Datenstruktur:

struct Vertex {
    float Position[2];
    float Color[4];
    float Texture[2];
};

Ja, ich sende Farbe mit jedem Scheitelpunkt, da ich einige Sprites selektiv tönen muss, andere jedoch nicht. Es folgt der Fragment-Shader, den ich verwende:

varying lowp vec2 TexCoord;
uniform sampler2D TextureSampler;

void main(void)
{
    gl_FragColor = texture2D( TextureSampler, TexCoord );
}

Bis jetzt funktioniert es großartig und gibt mir volle 60 FPS !!!

ABER

Sobald ich den Fragment-Shader auf Folgendes ändere (um das Abtönen zu ermöglichen):

varying lowp vec4 DestinationColor;
varying lowp vec2 TexCoord;
uniform sampler2D TextureSampler;

void main(void)
{
    gl_FragColor = texture2D( TextureSampler, TexCoord ) * DestinationColor;
}

Verwenden der folgenden 64x64-PNG-Textur mit Alphakanal, Rendern mit glEnable (GL_BLEND):

Geben Sie hier die Bildbeschreibung ein

Die Leistung sinkt auf 47 FPS nur aufgrund dieser einzigen Veränderung {nur durch Multiplikation mit ONE Vektor} (FPS gemessen Xcode Instrumente und OpenGL Detektiv verwenden). Irgendwelche Ideen, was los ist?

Vielen Dank.

Bearbeiten:

Ich habe auch versucht, pro Scheitelpunkt-Farbattribut abzustreifen:

struct Vertex {
    float Position[2];
    float Texture[2];
};

Ändern Sie den Fragment-Shader wie folgt:

precision lowp float;
varying lowp vec2 TexCoord;
uniform sampler2D TextureSampler;

void main(void)
{
    gl_FragColor = texture2D( TextureSampler, TexCoord ) * vec4(1.0,0.0,0.0,1.0);
}

Es läuft mit 52 FPS für 700 Sprites (ein Gewinn von nur 5 FPS). Das ist also keine Interpolation, die Multiplikation scheint extrem teuer zu sein. Nur diese EINE Multiplikation?

fakhir
quelle
Haben Sie vsync aktiviert? Die Zahlen könnten bedeuten, dass nach der Änderung jeder zweite vsync fehlt, was zu durchschnittlich 45 FPS führt.
Msell
Ich teste auf dem iPhone 4, ich nehme an, vsync ist bereits standardmäßig aktiviert. Es zeigt übrigens 47 FPS in xcode Instruments, also denke ich, dass vsync überhaupt kein Problem ist. Aber meine eigentliche Frage ist: Warum verlangsamt sich die Leistung und wie kann man sie verbessern?
Fakhir
1
Hat Ihre Textur einen Alphakanal? Wenn die Textur keinen Alphakanal hat und der RGB mit einem VEC3 multipliziert wird, zeichnet er dann wieder mit 60 fps?
Will
Ja, die Textur hat einen Alphakanal. Bitte beachten Sie die oben angehängte Textur.
Fakhir
2
Single Core SGX 535, hochauflösendes Display mit einer GPU, die niemals dafür gedacht war. Die Leistung von Grafiken in nativer Auflösung auf diesen Geräten war immer schrecklich. Sie sollten entweder die Auflösung verkleinern oder 30 fps oder neuere Hardware als Ziel festlegen. Sie erwarten Wunder von dieser GPU. Es braucht nicht viel, um es zu tanken.
Sean Middleditch

Antworten:

2

Ich glaube nicht, dass das Leistungsproblem bei der Multiplikation auftritt, sondern bei der Interpolation Ihrer DestinationColorDreiecke zwischen Scheitelpunkt- und Fragment-Shadern. Sie haben vier floatSekunden Zeit, um zwischen Baumscheitelpunkten für jedes Fragment für jedes Sprite zu interpolieren.

Für 700 Sprites mit jeweils 64 x 64 Pixel sind dies 11468800 zusätzliche Vorgänge pro Frame , die die GPU ausführen soll. Es ist durchaus möglich, dass Ihnen einige vsyncs fehlen und Sie daher auf 40 FPS fallen.

Wenn Sie möchten, dass jeder Scheitelpunkt eine andere Farbe hat, sodass Sie für jedes Sprite Farbverläufe haben können, haben Sie kein Glück. Es gibt auch einige andere Tricks, die Sie vielleicht ausprobieren möchten, aber ich denke, das ist nicht der Fall.

Da das, was Sie scheinen jeden Sprit zu tun ist , färbt, könnten Sie Ihre degradieren DestinationColorzu ein uniform, verwenden Sie es direkt im Fragment - Shader, und es für jeden Anruf ändern. Auf diese Weise finden keine Interpolationen statt. Sie verlieren die gesamte Stapelverarbeitung, können jedoch möglicherweise ein wenig stapeln, wenn Sie sie nach Farbe sortieren.

Panda Pyjama
quelle
Ich habe die Frage oben bearbeitet und einige Details hinzugefügt. Grundsätzlich habe ich versucht, pro Scheitelpunktfarbe abzustreifen und die Textur einfach mit einem KONSTANTEN Vektor zu multiplizieren, dh: gl_FragColor = texture2D (TextureSampler, TexCoord) * vec4 (1.0,0.0,0.0,1.0); . Erhielt 52 FPS, ein Gewinn von fast 5 FPS. Aber immer noch viel zu langsam im Vergleich zu keinem Farbton. Verlangsamung von 8 FPS nur aufgrund einer einzelnen Vektormultiplikation?
Fakhir
3
Aber es ist keine einzelne Multiplikation - es sind ~ 11 Millionen pro Frame.
Maximus Minimus
1
@fakhir Die Auflösung des iPod Touch 4-Displays beträgt 960 x 640 Pixel. Das sind insgesamt 614400 Pixel. Sie möchten 700 Sprites mit jeweils 64 x 64 Pixel rendern. Das sind 2867200 Pixel oder fast das Fünffache des gesamten Bildschirms. Sie haben wahrscheinlich Ihre ursprünglichen 60 fps erhalten, weil der Optimierer herausgefunden hat, was Sie getan haben, und das Bild möglicherweise nur einmal abgetastet hat, aber erwarten Sie nicht, dass dies in allen Fällen der Fall ist. Die mobile Grafikprogrammierung ist viel eingeschränkter als die Desktop-Programmierung. Handeln Sie daher entsprechend.
Panda Pyjama