|
Tile-ing Textures
#399546
04/17/12 00:23
04/17/12 00:23
|
Joined: Oct 2008
Posts: 513
Carlos3DGS
OP
User
|
OP
User
Joined: Oct 2008
Posts: 513
|
I started a thread in the "starting with gamestudio" section, but since I am going the shader route I decided it would be best to continue here. Some backround on what I am trying to achieve with this shader: Hard to describe this clearly in the title, so let me try get the idea across in more detailed explanation: I have lots of square cube blocks in my game, the player can place and scale the height of these blocks, kind of like a simplified minecraft. These blocks all have tileable textures so they look contiguos side by side. To build a castle-looking structure you could try to achieve it by scaleing a block to a height of x12, the block beside to height x10, and continue altering heights of your blocks between x12 and x10 till you have built the complete structure of the castle out of different height blocks.
My problem is this: When scaling the height of a block, the texture on the sides (walls) are streched, so the tileable textures on the sides (wall) no longer match the wall textures of the blocks beside it.
My question is, to avoid this "stretching" problem on the textures... Is there any way to tile the texture on the objects depending on it's size instead of stretching it? I have started to think on how to achieve this and so far I have this pseudo-code planning out the shader logic:
//THIS FIRST PART WORKS FOR HORIZONTAL PLANES (TOP OF BLOCK)
float3 object_world_pos = my object's origin;
float3 pixel_local_pos = position relative to object's origin;
float3 pixel_world_pos = object_world_pos + pixellocal__pos;
float2 texture_pos = (pixel_world_pos.x, pixel_world_pos.y);//texcoord
//THIS PART ALSO TAKES INTO ACCOUNT VERTICAL WALLS (SIDES OF THE CUBES)
float3 normal = pixel surface's normal;
texture_pos.x += pixel_world_pos.z * normal.x;
texture_pos.y += pixel_world_pos.z * normal.y;
float4 pixel = texture_sampler(texture_pos);//wrap?
So how does the logic look so far? Am I heading in the right direction? Any help would be great.
|
|
|
Re: Tile-ing Textures
[Re: Carlos3DGS]
#399569
04/17/12 11:15
04/17/12 11:15
|
Joined: Jun 2007
Posts: 1,337 Hiporope and its pain
txesmi
Serious User
|
Serious User
Joined: Jun 2007
Posts: 1,337
Hiporope and its pain
|
Hello, You can multiply the texture coords by the scale factor into the shader, and I think that is all what you need. tiling.fx
float4x4 matWorld;
float4x4 matWorldViewProj;
float4 vecSkill41;
texture entSkin1;
sampler TexSampler = sampler_state
{
Texture = <entSkin1>;
MipFilter = Linear;
AddressU = Wrap;
Addressv = Wrap;
};
struct out_tiling
{
float4 Pos : POSITION;
float2 Tex0 : TEXCOORD0;
};
out_tiling vs_20
(
in float4 inPos : POSITION,
in float2 inTex0 : TEXCOORD0
)
{
out_tiling Out;
Out.Pos = mul(inPos,matWorldViewProj);
Out.Tex0 = inTex0;
return Out;
}
float4 ps_20 ( out_tiling In ): COLOR
{
float2 Coord;
Coord.x = In.Tex0.x * vecSkill41.x;
Coord.y = In.Tex0.y * vecSkill41.y;
return tex2D ( TexSampler, Coord );
}
technique TexTile
{
pass one
{
VertexShader = compile vs_2_0 vs_20();
PixelShader = compile ps_2_0 ps_20();
}
}
main.c
#include <acknex.h>
#include <default.c>
MATERIAL *mtl_tiling =
{
effect = "tiling.fx";
}
function main ()
{
wait (2);
level_load ( "" );
wait(3);
camera.x = -500;
you = ent_create ( "cube.mdl", nullvector, NULL );
you.material = mtl_tiling;
you.skill41 = floatv(2);
you.skill42 = floatv(2);
while ( !key_esc )
{
wait(1);
}
sys_exit ( NULL );
}
Salud!
|
|
|
Re: Tile-ing Textures
[Re: Superku]
#399612
04/17/12 17:53
04/17/12 17:53
|
Joined: Jun 2007
Posts: 1,337 Hiporope and its pain
txesmi
Serious User
|
Serious User
Joined: Jun 2007
Posts: 1,337
Hiporope and its pain
|
I had a nailed thorn and needed take it off. I found a better way, but the box has to be perfectly aligned to the system planes and all the cube faces has to be detached from each other, otherwise it will not work. Save box scales into x->skill41, y->skill42 and z->skill43 tiled.fx
float4x4 matWorld;
float4x4 matWorldViewProj;
float4 vecSkill41;
texture entSkin1;
sampler TexSampler = sampler_state
{
Texture = <entSkin1>;
MipFilter = Linear;
AddressU = Wrap;
Addressv = Wrap;
};
struct out_tiling
{
float4 Pos : POSITION;
float2 Tex0 : TEXCOORD0;
};
out_tiling vs_20
(
in float4 inPos : POSITION,
in float3 inNormal : NORMAL,
in float2 inTex0 : TEXCOORD0
)
{
out_tiling Out;
Out.Pos = mul(inPos,matWorldViewProj);
Out.Tex0.x = inTex0.x * ( (vecSkill41.y*inNormal.x) + (vecSkill41.x*inNormal.y) + (vecSkill41.x*inNormal.z) );
Out.Tex0.y = inTex0.y * ( (vecSkill41.z*inNormal.x) + (vecSkill41.y*inNormal.y) + (vecSkill41.z*inNormal.z) );
return Out;
}
float4 ps_20 ( out_tiling In ): COLOR
{
return tex2D ( TexSampler, In.Tex0 );
}
technique TexTile
{
pass one
{
VertexShader = compile vs_2_0 vs_20();
PixelShader = compile ps_2_0 ps_20();
}
}
Salud!
|
|
|
Re: Tile-ing Textures
[Re: Carlos3DGS]
#399663
04/18/12 08:37
04/18/12 08:37
|
Joined: Jun 2007
Posts: 1,337 Hiporope and its pain
txesmi
Serious User
|
Serious User
Joined: Jun 2007
Posts: 1,337
Hiporope and its pain
|
Instead of a cube I have to make it out of 6 separate faces (but still all in the same model)? That is it. It has to be this way because the normals of the vertex of a merged cube are not perpendicular to the faces that they are part of, instead, every vertex has a normal that is an average of the normals of the three faces that it is part of. To make this shader work, every face has to be independent and share no vertex with the other faces. Can you explain how the second shader works?
Of course. The normal of a plane aligned to any of the orthogonal planes (XY, XZ or YZ) has one of its coords fullfilled (1 or -1) and the other two are empty (0). XY: 0,0,1 - XZ: 0,1,0 - YZ: 1,0,0 The shader computes the texture coords with this values, so only multiplies one of those three elements of the summation to each coordinate. That is why it does not work with not aligned faces. Hope I explained enough and sorry for my english xP Salud!
|
|
|
Re: Tile-ing Textures
[Re: txesmi]
#399723
04/18/12 20:58
04/18/12 20:58
|
Joined: Oct 2008
Posts: 513
Carlos3DGS
OP
User
|
OP
User
Joined: Oct 2008
Posts: 513
|
Don't appologize for your english, it is quite good. By the way I checked the links in your signature and found they lead to spanish Lite-C sites. Are you spanish? If so, what a coincidence! I am spanish too! Back on topic: After revising your code again carefully with your explanation I think I understand it now. Thanks! I am now in the process of adapting it, so it can tile textures withought caring about scale or if the blocks are snapped on a grid (or abrirtarily sized med models withought having to calculate the relative size compared with a "standard" block). So there can be half-width blocks or whatever and still continue to be perfectly tiled (or even bigger more complex structures withought having to calculate what the corresponding scale is. For this i am trying to take into account normals like you do, and taking into account global position instead of modifying local UV coordinates. It helps me alot to have your shader to work on, It is generally hard for me to get the structure of a shader right from scratch but am pretty good at modifying one. This is an example of what I am trying to achieve, thats why I am trying to modify your code to use world coordinates instead of local UV coordinates+scale. This is what I have so far:
float4x4 matWorld;
float4x4 matWorldViewProj;
float4 vecSkill41;
texture entSkin1;
sampler TexSampler = sampler_state
{
Texture = <entSkin1>;
MipFilter = Linear;
AddressU = Wrap;
Addressv = Wrap;
};
struct out_tiling
{
float4 Pos : POSITION;
float2 Tex0 : TEXCOORD0;
};
out_tiling vs_20
(
in float4 inPos : POSITION,
in float3 inNormal : NORMAL,
in float2 inTex0 : TEXCOORD0
)
{
out_tiling Out;
Out.Pos = mul(inPos,matWorldViewProj);
Out.Tex0.x = Out.Pos.x + (Out.Pos.y*inNormal.z);
Out.Tex0.y = Out.Pos.z + (Out.Pos.y*inNormal.x);
return Out;
}
float4 ps_20 ( out_tiling In ): COLOR
{
return tex2D ( TexSampler, In.Tex0 );
}
technique TexTile
{
pass one
{
VertexShader = compile vs_2_0 vs_20();
PixelShader = compile ps_2_0 ps_20();
}
}
One thing... If I remeber correctly, in shaders y and z axis are swappped, right? (It's been a long time since I played around with shaders)
|
|
|
|