How can I get a covered texture on a PlaneGeometry?

Hi everyone

I’m a novice to webgl and recently try to simply map a texture on a PlaneBufferGeometry.

It works but as you can see the image is squished on the plane, while I would like to get the same effect as a background-size: cover; css property.

My vertex shader is written like so

varying vec2 vUv;

void main() {
  vUv = uv;
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

And here is my fragment shader

uniform sampler2D uTexture;
varying vec2 vUv;

// Zoom on the texture
vec2 scaleUV(vec2 uv, float scale) {
  float center = 0.5;
  return ((uv - center) * scale) + center;
}

void main() {
  vec3 texture = texture2D(uTexture, scaleUV(vUv, 1.0)).rgb;
  gl_FragColor = vec4(texture, 1.0);
}

The scaleUV function zoom on the texture, but even by removing it I’ve got the same effect.

Can someone could explain me what I’m doing wrong with this shader ?

Thank you in advance

If you want to solve this in code - you have to compare the ratio between width and height of the plane and scale UV mapping to use only the greater of these values (so one dimension will use 0.0 to 1.0 mapping and the other will use something like 0.0 to (width / height).) Not 100% sure if this can be done straight in the shader, you’ll probably have to pass the ratio via a uniform.

If you want to solve it without falling into a deep depressive state after spending weeks figuring out shader code - just go to Blender and fix the UVs to match the image ratio. :’)

1 Like

Thank you for yout answer.
Wow I think I still have a lot to learn from shaders haha
I will continue to work on it and try to figure a solution based on your advice.

I will update this post when I have something new :wink:

Well, I spent my day wandering around on this problem which seemed pretty basic… :exploding_head:

I tried many solution by getting de ratio of my texture etc but the image is still squished.

I tried to know the value of uv by writing this
gl_FragColor = vec4(vUv.x, 0.0, 0.0, 1.0);

But the results lost me even more

I simplified my code as much as possible by completely removing the ScaleUv function

uniform sampler2D uTexture;
varying vec2 vUv;

void main() {
  vec3 texture = texture2D(uTexture, vUv).rgb;
  gl_FragColor = vec4(texture, 1.0);
}

I still can’t find a solution, I think it’s all about the value of vUv but i can’t get anything satisfactory at all.

Why? vUv.x changes from 0 to 1, from left to right. And you put its value in the red channel. So everything looks correct.
If you use vUv.y for the same channel, you’ll get color changing from black on bottom to red on top.

Just for reference: https://threejs.org/examples/textures/uv_grid_opengl.jpg

@prisoner849

Okay thank you for yout answer it’s clearer for me !
I’m not far from the truth, I’m just going to continue tp documenting myself and it should be good :slight_smile:

@rmonell
Feel free to search the forum: Responsive texture on resizable plane :slight_smile:
or Stackoverflow:

2 Likes

Hello @prisoner849

Thank you very much for this link which I had missed, it works perfectly !
Indeed the solution was not so complicated :sweat_smile:

1 Like