#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();
}
Вращение передается как пара синус, косинус угла [синус (радианы), косинус (радианы)].