簡體   English   中英

OpenGL ES - 在片段着色器中旋轉紋理而不會失真

[英]OpenGL ES - Rotating texture in fragment shader without distortion

我正在使用 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 上的所有答案都不適用於我的情況。 請幫忙!

謝謝!

您必須考慮視口(窗口)的縱橫比。
如果窗口與圖像具有相同的縱橫比,則可以通過圖像的大小來計算縱橫比:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM