OpenGL ES-碎片着色器中的旋转纹理而不会失真



我正在使用gpuimage库来为Android应用一些效果。当然,GPUIMAGE接受位图并使用opengl es,将1 x 1个立方体渲染到位图大小的框架缓冲区中。用户可以编写自定义片段着色器来控制输出。

我试图编写一个碎片着色器,该着色器旋转位图,给定旋转角度。这是我到目前为止所拥有的:

varying vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform vec2 inputImageTextureSize;
uniform float angle;
const vec2 HALF = vec2(0.5);
void main()
{
    float aSin = sin(angle);
    float aCos = cos(angle);
    vec2 tc = textureCoordinate;
    tc -= HALF.xy;
    tc *= mat2(aCos, aSin, -aSin, aCos);
    tc += HALF.xy;
    vec3 tex = texture2D(inputImageTexture, tc).rgb;
    gl_FragColor = vec4(tex, 1.0);
}

它有效,但显然会扭曲位图(因为GPUIMAGE视口设置为映射1 x 1个立方体到实际的位图大小(。我不知道如何摆脱失真。我应该根据角度和inputimageTexturesize应用一些额外的缩放转换,但是我未能获得正确的方程式。在我的情况下,Stackoverflow上的答案实际上都没有。请帮助!

谢谢!

您已经考虑了视口(窗口(的方面评估。
如果窗口具有与图像相同的方面评分,则可以通过图像的大小来计算方面评分:

float aspect = inputImageTextureSize.x / inputImageTextureSize.y;

在旋转(* aspect(旋转之前,将纹理坐标的U分量缩放,并在旋转后按相互纵横比(* 1.0/aspect(缩放它:

tc -= HALF.xy;
tc.x *= aspect;
tc *= mat2(aCos, aSin, -aSin, aCos);
tc.x *= 1.0/aspect;
tc += HALF.xy;

为了澄清行为,可以用矩阵操作表示同样的行为:

float aSin = sin(angle);
float aCos = cos(angle);
float aspect = u_resolution.x / u_resolution.y;
mat2 rotMat      = mat2(aCos, -aSin, aSin, aCos);
mat2 scaleMat    = mat2(aspect, 0.0, 0.0, 1.0);
mat2 scaleMatInv = mat2(1.0/aspect, 0.0, 0.0, 1.0);
tc -= HALF.xy;
tc = scaleMatInv * rotMat * scaleMat * tc;
tc += HALF.xy;

作为对Rabbid76答案的补充,以防输入和输出宽高比不同:

float inputAspect = inputSize.x / inputSize.y;
float outputAspect = outputSize.x / outputSize.y;
float aspect = inputAspect / outputAspect;
// adjust aspect
tc.y *= aspect;
tc.y -= aspect * 0.5 - 0.5;
// rotate ...

这是一个示例:https://www.shadertoy.com/view/3dxbr7

最新更新