[英]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.