Frage

Ich verwende die bikubische Filterung, um meine Höhenkarte zu glätten. Ich habe sie in GLSL implementiert:

Bikubische Interpolation: (sehen interpolate() Funktion unten)

float interpolateBicubic(sampler2D tex, vec2 t) 
{

vec2 offBot =   vec2(0,-1);
vec2 offTop =   vec2(0,1);
vec2 offRight = vec2(1,0);
vec2 offLeft =  vec2(-1,0);

vec2 f = fract(t.xy * 1025);

vec2 bot0 = (floor(t.xy * 1025)+offBot+offLeft)/1025;
vec2 bot1 = (floor(t.xy * 1025)+offBot)/1025;
vec2 bot2 = (floor(t.xy * 1025)+offBot+offRight)/1025;
vec2 bot3 = (floor(t.xy * 1025)+offBot+2*offRight)/1025;

vec2 mbot0 = (floor(t.xy * 1025)+offLeft)/1025;
vec2 mbot1 = (floor(t.xy * 1025))/1025;
vec2 mbot2 = (floor(t.xy * 1025)+offRight)/1025;
vec2 mbot3 = (floor(t.xy * 1025)+2*offRight)/1025;

vec2 mtop0 = (floor(t.xy * 1025)+offTop+offLeft)/1025;
vec2 mtop1 = (floor(t.xy * 1025)+offTop)/1025;
vec2 mtop2 = (floor(t.xy * 1025)+offTop+offRight)/1025;
vec2 mtop3 = (floor(t.xy * 1025)+offTop+2*offRight)/1025;

vec2 top0 = (floor(t.xy * 1025)+2*offTop+offLeft)/1025;
vec2 top1 = (floor(t.xy * 1025)+2*offTop)/1025;
vec2 top2 = (floor(t.xy * 1025)+2*offTop+offRight)/1025;
vec2 top3 = (floor(t.xy * 1025)+2*offTop+2*offRight)/1025;

float h[16];

h[0] = texture(tex,bot0).r;
h[1] = texture(tex,bot1).r;
h[2] = texture(tex,bot2).r;
h[3] = texture(tex,bot3).r;

h[4] = texture(tex,mbot0).r;
h[5] = texture(tex,mbot1).r;
h[6] = texture(tex,mbot2).r;
h[7] = texture(tex,mbot3).r;

h[8] = texture(tex,mtop0).r;
h[9] = texture(tex,mtop1).r;
h[10] = texture(tex,mtop2).r;
h[11] = texture(tex,mtop3).r;

h[12] = texture(tex,top0).r;
h[13] = texture(tex,top1).r;
h[14] = texture(tex,top2).r;
h[15] = texture(tex,top3).r;

float H_ix[4];

H_ix[0] = interpolate(f.x,h[0],h[1],h[2],h[3]);
H_ix[1] = interpolate(f.x,h[4],h[5],h[6],h[7]);
H_ix[2] = interpolate(f.x,h[8],h[9],h[10],h[11]);
H_ix[3] = interpolate(f.x,h[12],h[13],h[14],h[15]);

float H_iy = interpolate(f.y,H_ix[0],H_ix[1],H_ix[2],H_ix[3]);

return H_iy;
}

Dies ist meine Version davon, die Texturgröße (1025) ist immer noch fest codiert.Wenn man dies im Vertex-Shader und/oder im Tessellation-Evaluierungs-Shader verwendet, wirkt es sich sehr stark auf die Leistung aus (20–30 fps).Aber wenn ich die letzte Zeile dieser Funktion ändere in:

return 0;

Die Leistung steigt genau so, als ob ich bilinear oder nächste/ohne Filterung verwendet hätte.

Das Gleiche passiert mit:(Ich meine, die Leistung bleibt gut)

return h[...]; //...
return f.x; //...
return H_ix[...]; //...

Die Interpolationsfunktion:

float interpolate(float x, float v0, float v1, float v2,float v3)
{
    double c1,c2,c3,c4; //changed to float, see EDITs

    c1 = spline_matrix[0][1]*v1;
    c2 = spline_matrix[1][0]*v0 + spline_matrix[1][2]*v2;
    c3 = spline_matrix[2][0]*v0 + spline_matrix[2][1]*v1 + spline_matrix[2][2]*v2 + spline_matrix[2][3]*v3;
    c4 = spline_matrix[3][0]*v0 + spline_matrix[3][1]*v1 + spline_matrix[3][2]*v2 + spline_matrix[3][3]*v3;

    return(c4*x*x*x + c3*x*x +c2*x + c1);
};

Die fps nehmen nur ab, wenn ich das Finale zurückgebe, H_iy Wert.Wie wirkt sich der Rückgabewert auf die Leistung aus?

BEARBEITEN Ich habe gerade gemerkt, dass ich verwendet habe double im interpolate() Funktion zu deklarieren c1, c2...ect.Ich habe es geändert in float, und die Leistung bleibt jetzt mit dem richtigen Rückgabewert gut.Die Frage ändert sich also etwas:

Wie funktioniert a double Die Präzisionsvariable beeinflusst die Leistung der Hardware und warum hat nicht die andere Interpolationsfunktion diesen Leistungsverlust ausgelöst, sondern nur den letzten, seit dem H_ix[] Array war float auch, genau wie die H_iy?

War es hilfreich?

Lösung

Eine Möglichkeit, dies zu beschleunigen, ist die Nutzung texelFetch() anstatt floor()/texture(), sodass die Hardware keine Zeit mit der Filterung verschwendet.Allerdings ist die Hardware-Filterung ziemlich schnell, was teilweise der Grund dafür ist, dass ich das verlinkt habe GPU-Juwelen Artikel.Es gibt jetzt auch eine textureSize() Funktion, die die Übergabe der Werte an Sie selbst erspart.

GLSL verfügt über einen sehr aggressiven Optimierer, der alles Mögliche wegwirft.Nehmen wir also an, Sie verbringen eine ganze Weile damit, einen wirklich teuren Beleuchtungswert zu berechnen, aber am Ende sagen Sie es einfach colour = vec4(1), Ihre gesamte Berechnung wird ignoriert und sie läuft sehr schnell.Dies kann etwas gewöhnungsbedürftig sein, wenn man versucht, Dinge zu vergleichen.Ich glaube, das ist das Problem, das man sieht, wenn man unterschiedliche Werte zurückgibt.Stellen Sie sich vor, jede Variable hat einen Abhängigkeitsbaum und wenn eine Variable nicht in einer Ausgabe verwendet wird, einschließlich Uniformen und Attributen und sogar über die Shader-Stufen hinweg, ignoriert GLSL sie vollständig.Ein Punkt, an dem ich gesehen habe, dass GLSL-Compiler hier zu kurz kommen, ist das Ein-/Auskopieren von Funktionsargumenten, wenn es nicht nötig ist.

Was die doppelte Genauigkeit betrifft, gibt es hier eine ähnliche Frage: https://superuser.com/questions/386456/why-does-a-geforce-card-perform-4x-slower-in-double-precision-than-a-tesla-card.Im Allgemeinen müssen Grafiken schnell sein und verwenden fast immer nur einfache Genauigkeit.Für allgemeinere Computeranwendungen, z. B. wissenschaftliche Simulationen, liefern Verdoppelungen natürlich eine höhere Genauigkeit.Im Zusammenhang mit CUDA werden Sie wahrscheinlich noch viel mehr darüber erfahren.

Andere Tipps

Sie können eine bilineare Interpolation mit Hardware zu Ihrem Vorteil verwenden.Die bicubische Interpolation kann grundsätzlich als bilineare Interpolation von bilinear interpolierten Eingabepunkten geschrieben werden.Wie folgt:

generasacodicetagpre.

und das ist das Ergebnis

  • Erstes Bild ist Standard-Hradware-Interpolation
  • Das zweite Bild ist eine bicubische Interpolation mit dem Code oben
  • die gleiche bicubische Interpolation, aber mit diskretisierter Farbe, um Konturlinien zu sehen

erster iMa

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top