1
\$\begingroup\$

I'm making a game in C# with XNA. I'm now applying textures to models. However if I change the scale of the model, the texture stretches with it. How can I make the texture tile over the model instead of stretching? I'm using UV mapping to load the texture onto the model. This only has to work for a cube so I'm not worried about UV mapping issues. I have just been using the basic effect class in XNA because I haven't needed anything more yet.

Is there a way to set the texture to draw in a tiled manor?

Can this be done in C#? Maybe by changing the GraphicsDevice.SamplerStates?

Can this maybe be done with a HLSL shader? I know very little about HLSL.

This is the first 3D game I'm making so everything is very new to me. Please keep that in mind when answering. Thanks in advance.

EDIT:

So I did some testing with the GraphicsDevice.SamplerStates Here is my UV map: uv model

Here is my texture: texture

Here are the results:

                GraphicsDevice.SamplerStates[0] = SamplerState.PointWrap;

enter image description here

                GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;

enter image description here

                GraphicsDevice.SamplerStates[0] = SamplerState.AnisotropicWrap;

enter image description here

                var samState = new SamplerState();
                samState.Filter = TextureFilter.Point;
                samState.AddressU = TextureAddressMode.Wrap;
                samState.AddressV = TextureAddressMode.Wrap;
                samState.AddressW = TextureAddressMode.Wrap;
                GraphicsDevice.SamplerStates[0] = samState;

enter image description here

                var samState = new SamplerState();
                samState.Filter = TextureFilter.Point;
                samState.AddressU = TextureAddressMode.Mirror;
                samState.AddressV = TextureAddressMode.Mirror;
                samState.AddressW = TextureAddressMode.Mirror;
                GraphicsDevice.SamplerStates[0] = samState;

enter image description here

                var samState = new SamplerState();
                samState.Filter = TextureFilter.Linear;
                samState.AddressU = TextureAddressMode.Wrap;
                samState.AddressV = TextureAddressMode.Wrap;
                samState.AddressW = TextureAddressMode.Wrap;
                GraphicsDevice.SamplerStates[0] = samState;

enter image description here

                var samState = new SamplerState();
                samState.Filter = TextureFilter.Linear;
                samState.AddressU = TextureAddressMode.Mirror;
                samState.AddressV = TextureAddressMode.Mirror;
                samState.AddressW = TextureAddressMode.Mirror;
                GraphicsDevice.SamplerStates[0] = samState;

enter image description here

None of them seem to have tiled the image. So does that mean I need to use the HLSL shader as well?

EDIT: This is what I'm trying to achieve: enter image description here OR enter image description here

\$\endgroup\$
  • \$\begingroup\$ Well you need to have the valid texture-coordinates which tile across the cube. Then if you set a mirror or a wrap sampler the texture gets sampled by the mirror or the wrap function. For a cube's faces the coordinates could look like this: for the first face use coords in (0,1) range, for the second face have coords in the (1,2) range, for the third in the (2,3) range and so on. \$\endgroup\$ – János Turánszki Jun 15 '14 at 11:06
  • \$\begingroup\$ @János Turánszki. So does that mean I must draw the shape using primitives? As done here. \$\endgroup\$ – Nathan Jun 15 '14 at 11:57
  • \$\begingroup\$ I don't know any other way you could draw a mesh but with primitives - in this case triangles. But you also draw it using primitives if you load your model via the content manager. You just have to modify the texture coordinates. If it is a model file then you have to mod them in the modelling software then re-export (or you can modify the model file by hand if it is a text file). Or you specify the texcoords while creating the model in the code as shown in the link you provided. \$\endgroup\$ – János Turánszki Jun 15 '14 at 12:42
3
\$\begingroup\$

Yes you can do it by changing the sampler state, for example:

game.device.SamplerStates[0] = SamplerState.PointWrap;

This one means it will "wrap" your texture around the model and sample from the nearest texel. You should try out the other sampler states too. Mirror will mirror your texture if the texture coordinates are outside the (0,1) bounds. Clamp will not tile your texture.


You can also do it in the shader while you are declaring your sampler:

Texture xTexture0;
sampler TextureSampler0 = sampler_state { 
                                        texture = <xTexture0>; 
                                        magfilter = linear; 
                                        minfilter = anisotropic; 
                                        mipfilter = point; 
                                        AddressU = wrap; 
                                        AddressV = mirror;
                                       };

With these samplers you also need to have texture coordinates which are outside of the (0,1) range.

\$\endgroup\$
  • 1
    \$\begingroup\$ This will only give the OP's desired effect if their model's UVs extend beyond the 0-1 range. To get tiling without modifying the model, you'd need to also multiply UVs in the pixel shader, to get them to the desired range. \$\endgroup\$ – Andrew Russell Jun 15 '14 at 2:05
  • \$\begingroup\$ It's true I've added this. \$\endgroup\$ – János Turánszki Jun 15 '14 at 9:38
  • \$\begingroup\$ @János Turánszki. I added some results above. \$\endgroup\$ – Nathan Jun 15 '14 at 10:58
  • \$\begingroup\$ @János Turánszki. So does that mean I must draw the shape using primitives? As done here \$\endgroup\$ – Nathan Jun 15 '14 at 12:12

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.