Shift right while scaling

I want a texture scaled to match the screen height while maintaining its own aspect ratio AND I want it shifted to hug the right side of the screen rather than the left.

#version 150

uniform sampler2D u_tex0;
uniform vec2 u_screenRes;
uniform vec2 u_imgRes0;
void main()
{    
    vec2 coord = (gl_FragCoord.xy - vec2(u_screenRes.x - u_imgRes0.x, 0.0)) / u_imgRes0; 
    coord /= u_screenRes.y / u_imgRes0.y;
    coord.y = 1.0 - coord.y;
    vec4 color = texture2D(u_tex0, coord);
    gl_FragColor = color;
}
void ofApp::draw() {
	m_shader1.begin();
	m_shader1.setUniformTexture("u_tex0", m_tex0, 0);
	m_shader1.setUniform2f("u_imgRes0", m_tex0.getWidth(), m_tex0.getHeight());
	m_shader1.setUniform2f("u_screenRes", ofGetWidth(), ofGetHeight());
	ofDrawRectangle(0, 0, ofGetWidth(), ofGetHeight());
	m_shader1.end();
}

This code isn’t working- the image gets pushed too far to the right and cut off. It seems the y-coord-based resizing is interfering with the positioning equation… any ideas? Even ChatGPT is stumped, but this doesn’t seem like it should be that hard.

Hey @s_e_p , I find it helpful to use normalized coordinates in shaders. I think this problem can be thought of in terms of the ratio (or scaling factor) of the aspect ratios between the window and the texture.

So, if the window has an aspect ratio of 16/9, and the texture is 4/3 (or 12/9), then the window (x-direction) is 16/12 (or 1.333) larger than the texture. So (I think) the normalized x coordinate can be offset by multiplying it 1.333 and then subtracting 0.333. The normalized y coordinate will be left alone since it doesn’t need to scale.

A quick study shader is below; I called ofDisableArbTex() in ofApp::setup(). Normally I pass thru texcoord instead of using gl_FragCoord.xy. The size of the ofFbo that I rendered into was 1920 x 1080, and tex1 was 640 x 480. The scaling factor could be passed in from OF as a uniform, rather than computed in the shader.

#version 330
uniform sampler2D tex1;
in vec2 vTexcoord;
out vec4 fragColor;

void main(){
//    vec2 tc = vTexcoord;
    vec2 tc = gl_FragCoord.xy / vec2(1920.0, 1080.0); // normalize 0.0 - 1.0
    tc *= vec2(1.333, 1.0); // x is 0.0 - 1.333; y is still 0.0 - 1.0
    tc += vec2(1.0 - 1.333, 0.0); // x is now -0.33 - 1.0
    
    vec3 color = vec3(0.0); // black out the edge-wrap
    if(tc.x >= 0.0){
        color = texture(tex1, tc).rgb;
    }
    fragColor = vec4(color, 1.0);
}
1 Like

Thank you, this works well! Using your method I can calculate the aspect difference like this:

float yRatio = u_screenRes.y / imgRes.y;
vec2 scaledRes = imgRes * yRatio;
float aspDiff = u_screenRes.x / scaledRes.x;

I guess it doesn’t matter if I do this inside or outside the shader.