PIXI.js спрайт теряет вращение после применения фильтра

#javascript #webgl #pixi.js

#javascript #webgl #pixi.js

Вопрос:

Сначала я поворачиваю спрайт, к которому применена текстура, затем применяю фильтр с фрагментным шейдером, который вызывает искажение спрайта. Однако, когда я добавляю фильтр к спрайту, он поворачивается в нормальное горизонтальное положение вместо положения под углом, которое у него было раньше.

Я попытался применить вращающуюся функцию внутри шейдера для поворота uv. Это поворачивает изображение, но изменяет изображение за пределами частей, которые поворачиваются. Вот несколько скриншотов.

Первоначальный вид спрайта после добавления и изменения угла:

введите описание изображения здесь

Как это выглядит после применения фильтра:

введите описание изображения здесь

Как вы можете видеть, вращение удалено.

Я попытался добавить матрицу вращения внутри шейдера, вот результат:

введите описание изображения здесь

Вращение правильное, но поворачивается только текстура, а не сам контейнер. Применение angle обратно к sprite ничего не дает.

Фактическим результатом должно быть первое второе изображение, чтобы фильтр применялся к повернутому спрайту.

Вот код, который добавляет фильтр к изображению:

 const filter = new PIXI.Filter(null, getTransitionFragmentShader(transition, 2), uniforms);
  filter.apply = function (filterManager, input, output, clear) {
      var matrix = new PIXI.Matrix();
      this.uniforms.mappedMatrix = filterManager.calculateNormalizedScreenSpaceMatrix(matrix);
      PIXI.Filter.prototype.apply.call(this, filterManager, input, output, clear);
  };

  sprite.filters = [filter];  

 vec2 rotate(vec2 v, float a) {
                  float s = sin(a);
                  float c = cos(a);
                  mat2 m = mat2(c, -s, s, c);
                  return m * v;
                }

                vec4 transition (vec2 p) {
                  float dt = parabola(progress,1.);
                  float border = 1.;
                  vec2 newUV = rotate(p, angle);
                  vec4 color1 = vec4(0, 0, 0, 0);
                  if (fromNothing) {
                    color1 = vec4(0, 0, 0, 0);
                  } else {
                    color1 = texture2D(uTexture1, newUV);
                  }
                  vec4 color2 = texture2D(uTexture2, newUV);
                  vec4 d = texture2D(displacement,vec2(newUV.x*scaleX,newUV.y*scaleY));
                  float realnoise = 0.5*(cnoise(vec4(newUV.x*scaleX    0.*time/3., newUV.y*scaleY,0.*time/3.,0.))  1.);
                  float w = width*dt;
                  float maskvalue = smoothstep(1. - w,1.,p.x   mix(-w/2., 1. - w/2., progress));
                  float maskvalue0 = smoothstep(1.,1.,p.x   progress);
                  float mask = maskvalue   maskvalue*realnoise;
                  float final = smoothstep(border,border 0.01,mask);
                  return mix(color1, color2, final);
                }  

Это код шейдера с опущенными функциями для краткости.

Спасибо!

Ответ №1:

Вместо этого я использовал вершинный шейдер для вращения следующим образом:

 attribute vec2 aVertexPosition;

      uniform mat3 projectionMatrix;
      
      varying vec2 vTextureCoord;
      
      uniform vec4 inputSize;
      uniform vec4 outputFrame;
      uniform vec2 rotation;

      vec4 filterVertexPosition( void )
      {
          vec2 position = aVertexPosition * max(outputFrame.zw, vec2(0.))   outputFrame.xy;
          vec2 rotatedPosition = vec2(
            position.x * rotation.y   position.y * rotation.x,
            position.y * rotation.y - position.x * rotation.x
          );
      
          return vec4((projectionMatrix * vec3(rotatedPosition, 1.0)).xy, 0.0, 1.0);
      }
      
      vec2 filterTextureCoord( void )
      {
          return aVertexPosition * (outputFrame.zw * inputSize.zw);
      }
      
      void main(void)
      {
          gl_Position = filterVertexPosition();
          vTextureCoord = filterTextureCoord();
      }  

Вращение передается как пара синус, косинус угла [синус (радианы), косинус (радианы)].