Pergunta

Estou usando filtragem bicúbica para suavizar meu mapa de altura, implementei em GLSL:

Interpolação bicúbica: (ver interpolate() função abaixo)

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

Esta é a minha versão, o tamanho da textura (1025) ainda está codificado.Usar isso no sombreador de vértice e/ou no sombreador de avaliação de tesselação afeta muito o desempenho (20-30fps).Mas quando mudo a última linha desta função para:

return 0;

o desempenho aumenta como se eu usasse bilinear ou mais próximo/sem filtragem.

O mesmo acontece com:(Quero dizer que o desempenho continua bom)

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

A função de interpolação:

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

O fps só diminui quando retorno o final, H_iy valor.Como o valor de retorno afeta o desempenho?

EDITAR Acabei de perceber que usei double no interpolate() função para declarar c1, c2...etc.Eu mudei para float, e o desempenho agora permanece bom com o valor de retorno adequado.Então a questão muda um pouco:

Como é que um double variável de precisão afeta o desempenho do hardware, e por que a outra função de interpolação não desencadeou essa perda de desempenho, apenas a última, já que o H_ix[] matriz era float também, assim como o H_iy?

Foi útil?

Solução

Uma coisa que você pode fazer para acelerar isso é usar texelFetch() em vez de floor()/texture(), para que o hardware não perca tempo fazendo nenhuma filtragem.Embora a filtragem de hardware seja bastante rápida, é em parte por isso que vinculei o gemas de GPU artigo.Há também agora um textureSize() função que salva a passagem dos valores para você mesmo.

O GLSL possui um otimizador muito agressivo, que joga fora tudo o que pode.Digamos que você gaste anos calculando um valor de iluminação muito caro, mas no final basta dizer colour = vec4(1), todo o seu cálculo será ignorado e executado muito rápido.Pode levar algum tempo para se acostumar ao tentar avaliar as coisas.Acredito que esse seja o problema que você vê ao retornar valores diferentes.Imagine que cada variável tenha uma árvore de dependências e se alguma variável não for usada em uma saída, incluindo uniformes e atributos e até mesmo nos estágios de shader, o GLSL a ignora completamente.Um lugar em que vi compiladores GLSL falharem aqui é copiar argumentos de função de entrada/saída quando não é necessário.

Quanto à dupla precisão, uma questão semelhante está aqui: https://superuser.com/questions/386456/why-does-a-geforce-card-perform-4x-slower-in-double-precision-than-a-tesla-card.Em geral, os gráficos precisam ser rápidos e quase sempre usam precisão única.Para aplicações de computação de uso mais geral, por exemplo, simulações científicas, é claro que as duplicações proporcionam maior precisão.Você provavelmente encontrará muito mais sobre isso em relação ao CUDA.

Outras dicas

você pode usar a interpolação bilinear por hardware a seu favor.a interpolação bicúbica pode ser basicamente escrita como interpolação bilinear a partir de pontos de entrada interpolados bilinearmente.Assim:

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 este é o resultado

  • a primeira imagem é uma interpolação Hradware padrão
  • a segunda imagem é uma interpolação bicúbica usando o código acima
  • a mesma interpolação bicúbica, mas com cores discretizadas para ver os contornos

First ima

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top