2

I'm trying to handle the transform of texture in fragment shader. the resolution of window is (640,360), the rotation is 30 degree, and the scale is vec2(0.5,0.5).

this is what I want: correct result here is my fragment shader:

precision mediump float;                            
varying vec2 v_texCoord;                           
uniform sampler2D s_texture;                       
mat3 makeTranslation(vec2 t) {  
    mat3 m = mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, t.x, t.y, 1.0);
    return m;
}   
mat3 makeRotation( float angleInRadians ){
    float c = cos(angleInRadians);
    float s = sin(angleInRadians);
    mat3 m = mat3(c, -s, 0, s, c, 0, 0, 0, 1);
    return m;
}
mat3 makeScale(vec2 s) {
   mat3 m = mat3( s.x, 0, 0, 0, s.y, 0, 0, 0, 1);
    return m;
}

void main(){
    vec2 position = vec2(0.0,0.0);  
    vec2 scale = vec2(0.5,0.5);  
    float rotation = 30.0;  
    float r = rotation/180.0*3.14159; 
    vec2 size = vec2(640.0,480.0);

    mat3 mt = makeTranslation( translation );
    mat3 mr = makeRotation( r ); 
    mat3 ms = makeScale( 1.0/scale ); 

    //transform
    vec3 newCoord = vec3(v_texCoord.xy,1.0);                
    newCoord = mt*newCoord; 
    newCoord = mr*ms*vec3(newCoord.x - 0.5, newCoord.y - 0.5,0.0) + vec3(0.5, 0.5, 0.0);

    gl_FragColor = texture2D(s_texture, vec2(newCoord.x, newCoord.y) ); 
} 

the result is: result1
As you can see, the result is incorrect.

so, I apply a ratio of rectangle size to the texcoord.y:

//transform
float fy = 0.5*(1.0 - size.y*1.0/size.x);
newCoord.y = (newCoord.y-0.5)*size.y/size.x+fy;
newCoord = mt*newCoord; \n"
newCoord = mr*ms*vec3(newCoord.x - 0.5, newCoord.y - 0.5,0.0) + vec3(0.5, 0.5, 0.0);
newCoord.y = (newCoord.y+0.5)*size.x/size.y-fy;

what I've got: result the rectangle is correct, but the position of center point is incorrect.

So, how to get the right result? thanks.

here is the origin texture: origin texture

thrillerist
  • 111
  • 1
  • 2
  • 6

2 Answers2

1

Getting the right order of operations is very important.

When you receive your texture coordinates, they are in the range [0, 1]. However, you need to translate them, so that they are in [-0.5, 0.5], before you rotate them, so that you are rotating around the center of the texture. Then apply your scale, and finally your translation.

Andrew Williamson
  • 8,299
  • 3
  • 34
  • 62
  • thanks for reply, you're right, I should apply the translation int the end. but in this case the translation is (0.0f, 0.0f), so the the center of texture is still on the center of screen, as you can see in the second image. so the question is how to make the texture from second image to the first one. ( the rectangle is distorted in second image ) – thrillerist Apr 25 '16 at 08:54
1

you dont include screen and texture size proportions

Shadertoy code: (iChannel0 is texture, or BufA then uncomment line 26)

mat3 makeTranslation(vec2 t) {  
    mat3 m = mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, t.x, t.y, 1.0);
    return m;
}   
mat3 makeRotation( float angleInRadians ){
    float c = cos(angleInRadians);
    float s = sin(angleInRadians);
    mat3 m = mat3(c, -s, 0, s, c, 0, 0, 0, 1);
    return m;
}
mat3 makeScale(vec2 s) {
   mat3 m = mat3( s.x, 0, 0, 0, s.y, 0, 0, 0, 1);
    return m;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord ){
vec2 screen_res = iResolution.xy/iResolution.y;
vec2 uv = fragCoord/iResolution.y-0.5*screen_res;

    vec2 position = vec2(0.0,0.0);  
    vec2 scale = vec2(0.5,0.5);  
    float rotation = 180.*iMouse.x/iResolution.x;  
    float r = rotation/180.0*3.14159; 
    vec2 size = vec2(640.0,480.0);
    
//vec2 target_res = vec2(textureSize(iChannel0,0).xy)/float(textureSize(iChannel0,0).y);
vec2 target_res = vec2(1.,.5);
    
    mat3 mt = makeTranslation( vec2(0.5*target_res) );
    mat3 mr = makeRotation( r ); 
    mat3 ms = makeScale( 1.0/scale ); 

    //transform
    vec3 newCoord = vec3(uv.xy,1.0);                
    newCoord = mt*newCoord; 
    
    newCoord = mr*ms*vec3(newCoord.x - 0.5*target_res.x, newCoord.y - 0.5*target_res.y,0.0) + vec3(0.5*target_res, 0.0);
    newCoord.xy*= 1./target_res;

    fragColor = texture(iChannel0, vec2(newCoord.x, newCoord.y) ); 
} 

img

Danil S
  • 67
  • 7