4
$\begingroup$

I have a simple cube mesh, which I scale with modifying the model matrix.

Texture settings:

glGenTextures(1, &m_texture);
glBindTexture(GL_TEXTURE_2D, m_texture);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);

I set GL_REPEAT as wrap mode, but in my case it doesn't help, because the texture coordinates don't exceed [0...1].

For example from the unit cube I want to make a column whose dimensions are (1,10,1).

Just scaling this doesn't work because it textures the cube and then applies the scaling, which means that the texture will be stretched, instead of repeated along the y axis.

How can I implement this so I could set the length, width and depth of a cube dynamically and the texture will be repeated on it instead of stretched?

$\endgroup$
4
$\begingroup$

You need to set your texture coordinates appropriately. Let's look at one side of your cube. Let's say it's 100 x 100. If the user stretches the cube to be 100 x 150, you need to set the texture coordinates of the corner vertices to be:

lower left = <0.0, 0.0>
lower right = <1.5, 0.0>
upper right = <1.5, 1.0>
upper left = <0.0, 1.0>

That's the easiest way to handle it. Another way to handle it would be to pass either as scale factor or scale matrix into your fragment shader and apply that to your texture coordinates before doing any sampling.

To elaborate on the texture matrix idea, it's fairly simple. In your fragment shader, you'd have a uniform, say textureMatrix that's a mat4. It can contain any sort of transform you need - scale, rotation, translation, shear, etc. Before you sample any texture, you run the uv coordinates through the texture matrix, and then use the resulting values for your lookup. Something like this:

vec4 uv = gl_TexCoord[ 0 ]; // or whatever you called it coming from your vert. shader
vec4 newUV = textureMatrix * uv;
vec4 pixel = texture2D(texture, newUV.xy);

To do your non-uniform scaling, your matrix would be a scale matrix. For example if you wanted to scale the Y coordinate, you could use a matrix like this:

| 1 0 0 0 |
| 0 2 0 0 |
| 0 0 0 0 |
| 0 0 0 1 |
$\endgroup$
  • $\begingroup$ But the scale factor is 3 dimensional and the tex coordinate is 2 dimensional. $\endgroup$ – Tudvari Mar 6 '17 at 7:55
  • $\begingroup$ For example if the scaling factor is 1, 10, 1, then the texture coordinates of a face will be scaled based on which face we render currently. Like if we render the top quad it will be scaled x = 1 and z = 1. If we look at a side quad it will scaled by x = 1 and y = 10 or z = 1 and y = 10. How can I check which face are working on? Or do I overcomplicate it? $\endgroup$ – Tudvari Mar 6 '17 at 8:03
  • $\begingroup$ Without knowing more about your architecture and seeing more of your code, I don't have any way to answer that question. I would assume that you know which faces you're drawing when. You do need to know which face you're drawing and what the scale factors are in order to do this correctly. $\endgroup$ – user1118321 Mar 6 '17 at 17:17
  • $\begingroup$ @user1118321 Could you expand on the part about passing a scale matrix into the fragment shader? How do you use that to adjust U,V coords for non-uniform scaling? Is it possible? $\endgroup$ – Dan Mar 7 '17 at 13:59
  • $\begingroup$ OK, I've added an example above. $\endgroup$ – user1118321 Mar 7 '17 at 17:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.