Pixi.js: PIXI falha ao criar um filtro a partir do código de sombreador personalizado

Criado em 22 nov. 2017  ·  30Comentários  ·  Fonte: pixijs/pixi.js

Estou lutando para obter um filtro personalizado com meu próprio código de sombreador funcionando com esta mensagem de erro:

VertexArrayObject.js:171 Uncaught TypeError: Cannot read property 'location' of undefined
    at VertexArrayObject.addAttribute (VM1006 pixi.js:2348)
    at Quad.initVao (VM1006 pixi.js:19874)
    at FilterManager.applyFilter (VM1006 pixi.js:18947)
    at Filter.apply (VM1006 pixi.js:18420)
    at FilterManager.popFilter (VM1006 pixi.js:18877)
    at Container.renderAdvancedWebGL (VM1006 pixi.js:9423)
    at Container.renderWebGL (VM1006 pixi.js:9360)
    at Container.renderWebGL (VM1006 pixi.js:9366)
    at WebGLRenderer.render (VM1006 pixi.js:17563)
    at Application.render (VM1006 pixi.js:8043)

Até mesmo o exemplo oficial está falhando com este bug:
http://pixijs.io/examples/#/filters/filter -mouse.js

Esta mensagem de erro foi relacionada a algumas otimizações do compilador onde o glslify removeu alguns uniformes não usados, que o pixi ainda tentou acessar. Mas isso ocorre até mesmo com um fragShader completamente estático, sem uniformes. gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0)

Todos 30 comentários

O exemplo funciona para mim, em qual navegador você está testando?

Google Chrome versão 62.0.3202.94 (versão oficial) (64 bits)
2017-11-23-143829_667x172_scrot

Firefox Quantum 57.0 (64 bits)
2017-11-23-143957_741x236_scrot

SO: Ubuntu 17.10 engenhoso

@doebi nice catch! Sim, a otimização removeu algo (aposto que é uma amostra) e esquecemos de verificar.

Por enquanto, você tem certeza de que precisa de um filtro sem o uso de amostrador? Em alguns casos, é melhor fazer um plug-in de renderizador como https://github.com/pixijs/pixi-plugin-example ?

Na segunda vez neste dia, sinto muito pela bagunça que o sombreador e os filtros estão na v4. Vamos consertar na v5.

Para ser honesto, ainda não me aprofundei nesse tópico. Só queria experimentar esse recurso outro dia. Farei alguns testes com a abordagem do plug-in de renderizador. Obrigado pela dica.

Já existe algum ETA para v5?

2 meses ou mais :)

Existem muitos truques sobre filtros, é por isso que fiz aquele artigo: https://github.com/pixijs/pixi.js/wiki/v4-Creating-Filters

@ivanpopelyshev Seguindo seu tutorial, encontrei o mesmo problema.
Eu apliquei um patch realmente hacky ao pixi.js para fazê-lo funcionar para mim.

diff --git a/js/pixi.js b/js/pixi.js
index 363f09c..d0a321b 100644
--- a/js/pixi.js
+++ b/js/pixi.js
@@ -2344,6 +2344,9 @@ VertexArrayObject.prototype.activate = function()
  */
 VertexArrayObject.prototype.addAttribute = function(buffer, attribute, type, normalized, stride, start)
 {
+  if (!attribute) {
+    return this;
+  }
     this.attributes.push({
         buffer:     buffer,
         attribute:  attribute,

Eu sei que isso não é uma solução, mas me permite brincar com códigos de sombreador na v4 até que a v5 seja lançada. (possivelmente com uma correção melhor) :)

Esse é um bom hack!

Você pode movê-lo para um arquivo js separado:

PIXI.glCore.VertexArrayObject.prototype.addAttribute = ...

Eu tenho o mesmo problema. Também com Ubuntu 17.10 astuto. Os shaders são estáveis ​​no Pixi.js? Posso usá-los na produção? Como faço para importar um sombreador de pixel?

Tanto como filtro quanto como plugin de renderização. Eles são estáveis, mas requerem um conhecimento sério tanto sobre webgl quanto sobre arquitetura pixi.

https://github.com/pixijs/pixi.js/wiki/v4-Creating-Filters
https://github.com/pixijs/pixi-plugin-example/

Pela enésima vez, garanto às pessoas que será mais fácil na v5.

const filterCode = `void main(){
   gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}`;
const filter = new PIXI.Filter(null, filterCode);
someSprite.filters = [filter];

Essa quantidade de código leva a esse erro. Talvez eu deva ir para um construtor diferente do Filtro? Ou devo substituir null por algo?

Para um filtro, você deve usar a coordenação de textura e o amostrador, caso contrário, o FilterManager não consegue obter a localização do atributo.

O plugin de renderização não tem esse requisito, experimente. Sim, é um grande clichê.

Experimente isso: https://github.com/TazOen/createShaderPlugin . No entanto, ele ignora a textura, não há bindTexture ali. Se você precisar de textura, pegue o exemplo inteiro do plugin do pixi.

Você diz que precisa de coords de textura e "amostrador". Foi amostra ou amostrador? Um erro de digitação?
Consegui fazer funcionar com a ajuda do exemplo. Obrigado, mas. Por que esta página não menciona esses detalhes?
http://pixijs.io/examples/#/basics/custom -filter.js

Sampler. No entanto é uniforme e acho que ninguém vai sentir falta dele. Nosso problema é sobre atributos.

Graças a você, ele faz :) https://github.com/pixijs/pixi.js/wiki/v4-Creating-Filters#cannot -read-property-location-of-undefined

Oh, então era onde estava. Eu perdi o wiki.

Graças a você faz

Eu adicionei agora.

Também foi adicionado um aviso na demonstração do mouse com filtro. Não podemos corrigir o problema na v4. Faremos algo sobre isso na v5.

Isso aparece quando algumas das propriedades exigidas pelo FilterManager não são usadas no sombreador.

Que tal listar essas propriedades aí?

apenas o atributo, aTextureCoord -> vTextureCoord

Isso está ficando muito estranho.
Este código funciona bem:

varying vec2 vTextureCoord;
varying vec4 vColor;

uniform sampler2D uSampler;
uniform vec4 uTextureClamp;
uniform vec4 uColor;

void main(void)
{
    gl_FragColor = texture2D(uSampler, vTextureCoord);
    gl_FragColor.r = 0.0;
    gl_FragColor.g = 0.0;
    gl_FragColor.b = 0.0;
}

Mas se eu adicionar gl_FragColor.a = 0.0; ao final, então diz Cannot read property 'location' of undefined . Parece que só posso mudar 3 coords de 4, no máximo. O que é isso? O que está errado?

@ germansokolov13 este comportamento faz todo o sentido. Basta pensar nisso:
Como mencionei no post original, esse erro ocorre devido ao glsify otimizar o código do shader.

Se você adicionar gl_FragColor.a = 0.0; ele pode otimizar sua chamada para texture2D , porque ele é totalmente sobrescrito, mas até então leva o canal alfa de texture2D

Se glsify otimiza a chamada para texture2D, webgl não aloca memória para uSampler , portanto, quando pixi quer fazer upload de dados para aquele uniforme, ele falha, porque simplesmente não há espaço alocado para isso.

Você tem algumas opções:

  • Aplique o mesmo hack que eu fiz (por enquanto), que basicamente verifica se um atributo está alocado antes de enviar dados para ele.
  • Use o uSampler, para que o glsify não o otimize.
  • Ou apenas espere pela v5.

Esperançosamente, isso ajuda.

Boa pegada, @doebi!

Ou use o plugin de renderização.

Oh, agora entendi! Talvez devêssemos adicionar o patch do Doebi para a próxima versão secundária do Pixi.js? Devo criar um PR?

Olá,
Estou tendo um problema semelhante com meu código de sombreador. É uma variação do código de sombreador BlurYFilter padrão apenas com um kernel maior e uma pequena variação na variável gaussiana, então não tenho certeza de por que não está funcionando.

Está funcionando bem no Windows, MacOS e Android, pelo que testei, só tenho problemas no iOS.
Este é o código do shader:
vértice:

attribute vec2 aVertexPosition;
attribute vec2 aTextureCoord;
uniform float strength;
uniform mat3 projectionMatrix;
varying vec2 vBlurTexCoords[15];
void main(void){
   gl_Position = vec4((projectionMatrix * vec3((aVertexPosition), 1.0)).xy, 0.0, 1.0);
   vBlurTexCoords[0] = aTextureCoord + vec2(0.0, -7.0 * strength);
   vBlurTexCoords[1] = aTextureCoord + vec2(0.0, -6.0 * strength);
   vBlurTexCoords[2] = aTextureCoord + vec2(0.0, -5.0 * strength);
   vBlurTexCoords[3] = aTextureCoord + vec2(0.0, -4.0 * strength);
   vBlurTexCoords[4] = aTextureCoord + vec2(0.0, -3.0 * strength);
   vBlurTexCoords[5] = aTextureCoord + vec2(0.0, -2.0 * strength);
   vBlurTexCoords[6] = aTextureCoord + vec2(0.0, -1.0 * strength);
   vBlurTexCoords[7] = aTextureCoord + vec2(0.0, 0.0 * strength);
   vBlurTexCoords[8] = aTextureCoord + vec2(0.0, 1.0 * strength);
   vBlurTexCoords[9] = aTextureCoord + vec2(0.0, 2.0 * strength);
   vBlurTexCoords[10] = aTextureCoord + vec2(0.0, 3.0 * strength);
   vBlurTexCoords[11] = aTextureCoord + vec2(0.0, 4.0 * strength);
   vBlurTexCoords[12] = aTextureCoord + vec2(0.0, 5.0 * strength);
   vBlurTexCoords[13] = aTextureCoord + vec2(0.0, 6.0 * strength);
   vBlurTexCoords[14] = aTextureCoord + vec2(0.0, 7.0 * strength);
}

fragmento:

varying vec2 vBlurTexCoords[15];
uniform sampler2D uSampler;
void main(void){
   gl_FragColor = vec4(0.0);
   gl_FragColor += texture2D(uSampler, vBlurTexCoords[0]) * 0.013068780984604511;
   gl_FragColor += texture2D(uSampler, vBlurTexCoords[1]) * 0.013907007172070673;
   gl_FragColor += texture2D(uSampler, vBlurTexCoords[2]) * 0.017439264394216315;
   gl_FragColor += texture2D(uSampler, vBlurTexCoords[3]) * 0.028762309061254498;
   gl_FragColor += texture2D(uSampler, vBlurTexCoords[4]) * 0.05603114255667656;
   gl_FragColor += texture2D(uSampler, vBlurTexCoords[5]) * 0.10421702583793174;
   gl_FragColor += texture2D(uSampler, vBlurTexCoords[6]) * 0.163461199220823;
   gl_FragColor += texture2D(uSampler, vBlurTexCoords[7]) * 0.2062265415448454;
   gl_FragColor += texture2D(uSampler, vBlurTexCoords[8]) * 0.163461199220823;
   gl_FragColor += texture2D(uSampler, vBlurTexCoords[9]) * 0.10421702583793174;
   gl_FragColor += texture2D(uSampler, vBlurTexCoords[10]) * 0.05603114255667656;
   gl_FragColor += texture2D(uSampler, vBlurTexCoords[11]) * 0.028762309061254498;
   gl_FragColor += texture2D(uSampler, vBlurTexCoords[12]) * 0.017439264394216315;
   gl_FragColor += texture2D(uSampler, vBlurTexCoords[13]) * 0.013907007172070673;
   gl_FragColor += texture2D(uSampler, vBlurTexCoords[14]) * 0.013068780984604511;
}

para comparação, aqui estão os shaders do BlurYFilter padrão:
vert:

attribute vec2 aVertexPosition;
attribute vec2 aTextureCoord;
uniform float strength;
uniform mat3 projectionMatrix;
varying vec2 vBlurTexCoords[5];
void main(void)
{
  gl_Position = vec4((projectionMatrix * vec3((aVertexPosition), 1.0)).xy, 0.0, 1.0);
  vBlurTexCoords[0] = aTextureCoord + vec2(0.0, -2.0 * strength);
  vBlurTexCoords[1] = aTextureCoord + vec2(0.0, -1.0 * strength);
  vBlurTexCoords[2] = aTextureCoord + vec2(0.0, 0.0 * strength);
  vBlurTexCoords[3] = aTextureCoord + vec2(0.0, 1.0 * strength);
  vBlurTexCoords[4] = aTextureCoord + vec2(0.0, 2.0 * strength);

}

frag:

varying vec2 vBlurTexCoords[5];
uniform sampler2D uSampler;
void main(void)
{
    gl_FragColor = vec4(0.0);
    gl_FragColor += texture2D(uSampler, vBlurTexCoords[0]) * 0.153388;
    gl_FragColor += texture2D(uSampler, vBlurTexCoords[1]) * 0.221461;
    gl_FragColor += texture2D(uSampler, vBlurTexCoords[2]) * 0.250301;
    gl_FragColor += texture2D(uSampler, vBlurTexCoords[3]) * 0.221461;
    gl_FragColor += texture2D(uSampler, vBlurTexCoords[4]) * 0.153388;

}

Alguém tem alguma ideia de por que isso pode dar errado?

@tyleet tem certeza de que é o mesmo problema? O que você vê no console?

EDITAR:
Esqueça, eu encontrei o problema, parece que o tamanho do kernel de 15 é demais para iOS, se eu reduzir o tamanho do kernel para 7 funciona bem.

<----- Postagem original --------->
Oi,
desculpe pela resposta tardia, não consegui fazer algumas capturas de tela no fim de semana. Parece-me que falha na mesma linha. "attribute" é indefinido. Aqui estão as capturas de tela do console remoto:
image
image

@ivanpopelyshev devemos encerrar este problema para evitar que outras pessoas o
Eu não consideraria mais um problema, já que cumpri sua promessa de que será corrigido na v5.

fechamento @doebi .

@tyleet o número de amostras retiradas da textura pode ser limitado em diferentes sistemas.

Este tópico foi bloqueado automaticamente, pois não houve nenhuma atividade recente depois que ele foi fechado. Abra um novo problema para bugs relacionados.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

finscn picture finscn  ·  3Comentários

lucap86 picture lucap86  ·  3Comentários

SebastienFPRousseau picture SebastienFPRousseau  ·  3Comentários

lunabunn picture lunabunn  ·  3Comentários

Makio64 picture Makio64  ·  3Comentários