【问题标题】:OpenGL ES - Rotating texture in fragment shader without distortionOpenGL ES - 在片段着色器中旋转纹理而不失真
【发布时间】:2019-07-06 13:28:11
【问题描述】:

我正在使用适用于 Android 的 GPUImage 库将一些效果应用于位图。本质上,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 上的所有答案都不适用于我的情况。请帮忙!

谢谢!

【问题讨论】:

    标签: android opengl-es glsl shader gpuimage


    【解决方案1】:

    您必须考虑视口(窗口)的纵横比。
    如果窗口与图像的纵横比相同,则可以通过图像的大小来计算纵横比:

    float aspect = inputImageTextureSize.x / inputImageTextureSize.y;
    

    将纹理坐标的u分量在旋转前按纵横比(* aspect)缩放,在旋转后按倒数纵横比(* 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;
    

    【讨论】:

    • omg,我没有注意这一行:“tc.x *= aspect”,对不起。缩放、旋转、反向缩放,这对我来说很有意义。
    • 终于试过了,它奏效了。谢谢,伙计,你拯救了我的一天!
    • 这里的旋转轴心点是什么?如果我们想改变旋转轴心点,我们需要做什么?
    • @ZeroOneZero 如果您有任何问题,请Ask a public question
    【解决方案2】:

    作为对 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-11-23
      • 2014-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多