Domanda

Sto usando il filtraggio bicubico per sfruttare il mio altimemap, l'ho implementato in GLSL:

Interpolazione BICUBICA: (Vedi interpolate() Function Bellow)

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;
}
.

Questa è la mia versione di esso, la dimensione della trama (1025) è ancora hardcoded. Usando questo in Vertex Shader e / o nell'allenamento della valutazione di Tessellation, influisce sulle prestazioni molto male (20-30 fps). Ma quando cambio l'ultima riga di questa funzione per:

return 0;
.

Le prestazioni aumentano proprio come se ho usato Bilinear o più vicino / senza filtraggio.

Lo stesso accade con: (intendo che le prestazioni rimangono buone)

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

La funzione di interpolazione:

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);
};
.

I FPS diminuiscono solo quando restituisco il valore finale, H_iy. In che modo il valore di ritorno influisce sulle prestazioni?

Modifica Mi sono appena reso conto di aver usato double nella funzione interpolate() per dichiarare c1, c2 ... ECT. L'ho cambiato in float e la prestazione ora rimane buona con il valore di ritorno appropriato. Quindi la domanda cambia un po ':

In che modo una variabile di precisione generacodictagcode influisce sulle prestazioni dell'hardware e perché l'altra funzione di interpolazione attiva questa perdita di prestazione, solo l'ultima, poiché l'array di double è stato H_ix[], proprio come il float ?

È stato utile?

Soluzione

Una cosa che potresti fare per velocizzare questo è utilizzare texelFetch() anziché floor() / texture(), quindi l'hardware non perde tempo a fare alcun filtro. Sebbene il filtraggio dell'hardware sia abbastanza veloce che è in parte il motivo per cui ho collegato il Gems GPU Articolo . Ora c'è anche una funzione textureSize() che salva il passaggio dei valori in te stesso.

GLSL ha un ottimizzatore molto aggressivo, che lancia tutto il possibile. Quindi diciamo che spendi le età calcolando un valore di illuminazione davvero costoso, ma alla fine solo dire colour = vec4(1), tutto il tuo calcolo viene ignorato e funziona davvero velocemente. Questo può prenderne un po 'di abituarsi quando si cerca di apportare le cose. Credo che questo sia il problema che vedi quando si restituisce valori diversi. Immagina che ogni variabile abbia un albero di dipendenza e se qualsiasi variabile non viene utilizzata in un'uscita, incluse uniformi e attributi e persino attraverso le fasi di shader, GLSL lo ignora completamente. Un posto che ho visto i compilatori GLSL a breve arrivare qui è in copia di argomenti di funzione / out quando non deve.

Per quanto riguarda la doppia precisione, una domanda simile è qui: https://superusor.com/questions/386456/why-does-a-geforce-card-perform-4x-Lower-in-Double-precision-Han-a -Tesla-card . In generale, la grafica deve essere veloce e quasi sempre utilizza una singola precisione. Per le applicazioni di calcolo più generiche, ad es. Simulazioni scientifiche, doppie, danno una maggiore precisione. Probabilmente troverai molto di più su questo in relazione a CUDA.

Altri suggerimenti

È possibile utilizzare l'interpolazione bilineare da hardware a tuo vantaggio.L'interpolazione BICUBIC può essere fondamentalmente scritta come interpolazione bilineare da punti di input interpolati in modo bilinearly.In questo modo:

uniform sampler2D texture;
uniform sampler2D mask;
uniform vec2 texOffset;
varying vec4 vertColor;
varying vec4 vertTexCoord;
void main() {
  vec4 p0 = texture2D(texture, vertTexCoord.st).rgba;
  vec2 d  = texOffset * 0.125;
  vec4 p1 = texture2D(texture, vertTexCoord.st+vec2( d.x, d.y)).rgba;
  vec4 p2 = texture2D(texture, vertTexCoord.st+vec2(-d.x, d.y)).rgba;
  vec4 p3 = texture2D(texture, vertTexCoord.st+vec2( d.x,-d.y)).rgba;
  vec4 p4 = texture2D(texture, vertTexCoord.st+vec2(-d.x,-d.y)).rgba;
  gl_FragColor = (  2.0*p0   + p1 + p2 + p3 + p4)/6.0;
 }
.

E questo è il risultato

    .
  • la prima immagine è standard Hradware Interpolation
  • Seconda immagine è un'interpolazione bicubica utilizzando il codice sopra
  • la stessa interpolazione bicubica ma con colori discretizzati per vedere i contorni

First IMA

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top