Pixi.js: Não há como renderizar formas sem gráficos

Criado em 9 set. 2016  ·  18Comentários  ·  Fonte: pixijs/pixi.js

Ei, eu acho que deveria ser capaz de renderizar retângulos sem ter que desenhar objetos gráficos. Isso tornaria muito do meu código muito mais fácil! :)

Stale 💾 v4.x (Legacy) 📢 Accepting PRs 🥶 Low Priority

Comentários muito úteis

@GoodBoyDigital Claro. A equipe está atualmente empenhada na construção de uma rede social e infraestrutura de mensagens em tempo real para o aspecto de colaboração/comunidade/social de nosso aplicativo e, portanto, não sairemos da versão beta até dezembro, então não posso deixar alguém tem um jogo agora. Mas assim que estivermos estaremos montando um blog de desenvolvedores descrevendo nossa jornada, desafios e técnicas etc. Assim que terminar eu compartilho com vocês.

E assim que migrarmos para o PIXI versão 4, começaremos a ver o que podemos colocar de volta no PIXI em termos de plugins etc. Acho que o layout do texto e a renderização da fonte SDF seriam um grande benefício para vocês, para começar.

Todos 18 comentários

Certamente algo que poderíamos olhar :)

Bem, você pode usar a abordagem "Graphics._renderSpriteRect". Graphics usa renderTexture e sprites para retângulos sipmle, você pode fazer o mesmo: crie renderTexture, então use sprites.

var rect = this.graphicsData[0].shape;
    if(!this._spriteRect)
    {
        if(!Graphics._SPRITE_TEXTURE)
        {
            Graphics._SPRITE_TEXTURE = RenderTexture.create(10, 10);

            var currentRenderTarget = renderer._activeRenderTarget;
            renderer.bindRenderTexture(Graphics._SPRITE_TEXTURE);
            renderer.clear([1,1,1,1]);
            renderer.bindRenderTarget(currentRenderTarget);
        }

        this._spriteRect = new Sprite(Graphics._SPRITE_TEXTURE);
    }
    if (this.tint === 0xffffff) {
        this._spriteRect.tint = this.graphicsData[0].fillColor;
    } else {
        var t1 = tempColor1;
        var t2 = tempColor2;
        utils.hex2rgb(this.graphicsData[0].fillColor, t1);
        utils.hex2rgb(this.tint, t2);
        t1[0] *= t2[0];
        t1[1] *= t2[1];
        t1[2] *= t2[2];
        this._spriteRect.tint = utils.rgb2hex(t1);
    }
    this._spriteRect.alpha = this.graphicsData[0].fillAlpha;
    this._spriteRect.worldAlpha = this.worldAlpha * this._spriteRect.alpha;

    Graphics._SPRITE_TEXTURE._frame.width = rect.width;
    Graphics._SPRITE_TEXTURE._frame.height = rect.height;

    this._spriteRect.transform.worldTransform = this.transform.worldTransform;

    this._spriteRect.anchor.set(-rect.x / rect.width, -rect.y / rect.height);
    this._spriteRect.onAnchorUpdate();

    this._spriteRect._renderWebGL(renderer);

Renderizamos retângulos, triângulos e círculos usando apenas shaders personalizados. É muito mais rápido do que usar objetos Pixi Graphics e todas as bordas são completamente anti-alias devido ao uso de um cálculo de campo de distância no sombreador.

Adicionar contornos, brilhos, sombras e outros efeitos a essas formas é trivial. Simplesmente ajustamos cores, strokeWidth, strokeColor e vários uniformes de efeitos para os shaders.

Eu sugeriria examinar a renderização de formas/primitivas baseadas em shaders para uma versão futura do Pixi, pois é infinitamente superior à abordagem atual.

Sim, mas a coisa é que as texturas de renderização são muito mais pesadas em CPU do que primitivas simples (um retângulo é um quad sem textura com um sombreador) e se eu tiver que redimensionar muito essa forma (o que costumo fazer), então o desempenho será dê um golpe ou exigirá muito mais código.

Isso parece muito interessante @GordoRank ! Adoraria ver sua implementação!

@Dadibom - Os retângulos gráficos são super otimizados no pixi no momento em que são agrupados no sistema de sprite. Isso tudo é feito nos bastidores :)

Eu acho que o que você está pedindo é uma maneira curta de criar um retângulo?

Sim, mas ainda tenho que limpar uma textura e redesenhá-la a cada quadro, em vez de apenas mover os retângulos individuais

Como é que você precisa limpá-los a cada quadro?

@Dadibom usa vários gráficos, muda de posição todas as vezes.

Quanto aos seus primitivos, se você tiver algo personalizado, faça um plugin. Especialmente se suas coisas estão ligadas a tramas. https://github.com/pixijs/pixi-plugin-example . Vai ajudar os outros também.

Não funciona se eu quiser mudar o tamanho :(

Claro, eu posso usar escala. Mas é muito mais código do que tem que ser

Basicamente, temos um aplicativo completo de editoração eletrônica baseado em PIXI (renderização / formatação de texto SDF baseado em sombreador, edição de fotos, layout de página, desenho, curvas bezier etc.) Simplesmente estendemos muito o PIXI para atender às nossas necessidades.

Esta é uma versão antiga do PIXI 3.0 de um sombreador de círculo / elipse que permite definir a largura, altura, opacidade, strokeWidth, fillColor e strokeColor.

É um pouco confuso e poderia ser melhorado, mas funciona perfeitamente para nós. Temos shaders semelhantes para retângulos, triângulos e estrelas pontiagudas.

Esses shaders são aplicados a um renderizador Pixi personalizado que simplesmente aplica os shaders a um quad sem textura.

PIXI.filters.CircleShader = function(shaderManager) {


    PIXI.Shader.call(this,
        shaderManager,
        // vertex shader
        [
            'precision lowp float;',
            'attribute vec2 aVertexPosition;',
            'attribute vec2 aTextureCoord;',
            'attribute vec4 aColor;',

            'uniform mat3 projectionMatrix;',

            'varying vec2 vTextureCoord;',
            'varying vec4 vColor;',

            'void main(void){',
            '   gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);',
            '   vTextureCoord = aTextureCoord;',
            '   vColor = vec4(aColor.rgb * aColor.a, aColor.a);',
            '}'
        ].join('\n'),
        // fragment shader
        [
            '#extension GL_OES_standard_derivatives : enable',
            'precision mediump float;',

            'varying vec2 vTextureCoord;',

            'uniform float width;',
            'uniform float height;',
            'uniform float opacity;',
            'uniform vec4 fillColor;', 
            'uniform vec4 strokeColor;', 
            'uniform float strokeWidth;',

            'float texelSizeX = 1.0 / width;',
            'float texelSizeY = 1.0 / height;',

            'vec2 px = vec2(texelSizeX, texelSizeY);',
            'vec2 ab = vec2(width, height) / 2.0;',
            'vec2 center = vec2(0.5, 0.5);',


            'void main(void){',

            'vec2 pos = (vTextureCoord - center) / px;',
            'pos *= pos;',

            'float outerDist = dot(pos, 1.0 / (ab * ab));',

            'ab -= strokeWidth;',
            'float innerDist = dot(pos, 1.0 / (ab * ab));',

            'float outerDelta = length(vec2(dFdx(outerDist), dFdy(outerDist))) * 0.70710678118654757;',

            'float innerDelta = length(vec2(dFdx(innerDist), dFdy(innerDist))) * 0.70710678118654757;',

            'float innerAlpha = smoothstep(1.0 - innerDelta, 1.0 + innerDelta, innerDist);',
            'float outerAlpha = smoothstep(1.0 - outerDelta, 1.0 + outerDelta, outerDist);',


            'vec4 stroke = mix(strokeColor, vec4(0, 0, 0, 0), outerAlpha);',
            'vec4 fill = mix(fillColor, vec4(0, 0, 0, 0), innerAlpha);',

            'gl_FragColor = mix(vec4(0.0, 0.0, 0.0, 0.0), mix(fill, stroke, innerAlpha), opacity);',

            '}'
        ].join('\n'),
        // custom uniforms
        {
            dimensions: {
                type: '4fv',
                value: new Float32Array([0, 0, 0, 0])
            },
            projectionMatrix: { type: 'mat3', value: new Float32Array(9) },
            strokeWidth: {
                type: '1f',
                value: 0.0
            },
            strokeColor : { type: '4fv', value: new Float32Array([0, 0, 0, 0]) },
            fillColor : { type: '4fv', value: new Float32Array([0, 0, 0, 0]) },
            width : { type : '1f', value: 1.0},
            height : { type : '1f', value: 1.0},
            opacity : { type : '1f', value: 1.0}
        },
        // custom attributes
        {
            aTextureCoord:0,
            aVertexPosition:0,
            aColor:0
        }

    );


    this.strokeWidth = 0.0;
    this.strokeColor = new Float32Array([0, 0, 0, 0]);
    this.fillColor = new Float32Array([0, 0, 0, 0]);
    this.opacity = 1.0;


};

PIXI.filters.CircleShader.prototype = Object.create(PIXI.Shader.prototype);
PIXI.filters.CircleShader.prototype.constructor = PIXI.filters.CircleShader;

PIXI.ShaderManager.registerPlugin('circleShader', PIXI.filters.CircleShader);

Eu retirei as definições de propriedade para manter este comentário conciso.

@GoodBoyDigital porque preciso me livrar do retângulo antigo

@Dadibom bom. Você está no meio do caminho para ser o plugin oficial do pixi.

Para v4 você pode remover o parâmetro "args" do shader, os argumentos serão extraídos automaticamente. Além disso, você não pode definir nada para uniformes, a menos que o shader esteja vinculado. Quando o renderizador define valor para uniformes, deve ser algo assim:

myShader.bind();
myShader.uniforms.strokeWidth = ...;

Veja o exemplo de renderizador.

Além disso, o código do sombreador pode ser separado em arquivos "frag" e "vert", usando glsify, exemplo também.

@GordoRank Isso é realmente emocionante! Você consideraria compartilhar o que você tem - acho que muitos usuários do pixi achariam o que vocês criaram realmente incrível :)

@GoodBoyDigital Claro. A equipe está atualmente empenhada na construção de uma rede social e infraestrutura de mensagens em tempo real para o aspecto de colaboração/comunidade/social de nosso aplicativo e, portanto, não sairemos da versão beta até dezembro, então não posso deixar alguém tem um jogo agora. Mas assim que estivermos estaremos montando um blog de desenvolvedores descrevendo nossa jornada, desafios e técnicas etc. Assim que terminar eu compartilho com vocês.

E assim que migrarmos para o PIXI versão 4, começaremos a ver o que podemos colocar de volta no PIXI em termos de plugins etc. Acho que o layout do texto e a renderização da fonte SDF seriam um grande benefício para vocês, para começar.

Incrível! Eu (e tenho certeza que o resto da comunidade pixi) estou ansioso para dezembro :)
Boa sorte com sua versão beta!

Este problema foi marcado automaticamente como obsoleto porque não teve atividade recente. Será fechado se não ocorrer mais nenhuma atividade. Obrigado por suas contribuições.

Dando vida a esse tópico antigo, pois estou interessado em dois aspectos que o @GordoRank menciona.

  1. renderização de texto SDF baseada em sombreador
  2. renderização de formas baseadas em shader

Você já publicou algum de seus trabalhos para o público?

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

Questões relacionadas

lucap86 picture lucap86  ·  3Comentários

YuryKuvetski picture YuryKuvetski  ·  3Comentários

neciszhang picture neciszhang  ·  3Comentários

Darker picture Darker  ·  3Comentários

gigamesh picture gigamesh  ·  3Comentários