I've come up with an idea that should work in multitexturing a terrain with more than 4 textures, up to a 64 if a supported ShaderModel is used.
I'm trying to use the RGBA color values as both values for blending and identifying which textures should be used.
I'm currently using 16 per textures. Each color has 256 values (R, G, B, A) so by identifying:
Texture 1 Red = 0-16, Blend = (Value / (16 - (16 * 0)) Texture 2 Red = 17-32, Blend = (Value / (16 - (16 * 1))
and by changing from 16 to 32 the blend is better because more rgba values can be included.
...and the closer that value is to 16 the higher blend value it gets with that texture.
All I'm stuck at is this calculation because no matter what I do I can't seem to convert the values correctly or get the values in the right way.
// VS_OUTPUT contains Position, TextureCoordinates and Color
float4 MultiTexturing_Pixel(VS_OUTPUT input) : COLOR
{
float4 color = float4(0,0,0,0);
int scale = 16;
float red = input.Color.r * 256;
// gets an index between 0~16, add +16 for each color after this
int redIndex = ceil(red / scale);
int redValue = 0;
if ( (red % scale) == 0)
{
redValue = 1.0;
}
else
{
redValue = (color % scale) / scale; // should give a value between 0.0 and 1.0
}
// function with alot of ifs that checks the index and returns the Texture Sampler
color += GetColor(index, value, input.TexCoord);
// and the same for blue, green, alpa
// but add blueIndex + 16, greenIndex + 32, alphaIndex + 48
return color;
}
The math is there, but converting values back and forth is really the problem and since HLSL is basic C it's weird that it doesn't support basic math calculations.
Since I'm not that good at how the calculations should work I hope someone can provide an answer on how to actually perform the calculations below.
I've tried every possible way, all day and I'm totally out of ideas.
UPDATE: Problems with the calculations:
As far as my math knowledge goes, this is how it should go.
A color value is 0~255 (256) In HLSL this translates to a value of 0.0-1.0, which means 32 = (32 / 256) = 0.125
Step 1 I set the Vertex color to:
new Color(32, 0, 0, 0)
Step 2 In the pixel shader this value would translate to the second texture this way:
float each = 16.0;
float max = 256.0;
float redIndex = (input.Color.r * max) / each;
At this point redIndex should be "2.0" if Color value is (32,0,0,0) But it's not. Why? This is the flow for me in any other programming language:
float each = 16.0;
float max = 256.0;
float redIndex = 0.125 * 256; // = 32
redIndex /= 16.0; // = 2.0
int index = redIndex; // = 2
int index = ceil(redIndex); // = 2
If I try to use ceil(redIndex) nothing better happens, it still can't get that "index" value. And this is basic MATH. And ceil (available from SM v1.1) takes the value up to the nearest integer, so if it's 1.9 == 2, 0.1 = 1 and so on. But it cannot do this. Because the values are wrong and the calculation is wrong.
Step 3 To get a value between 0-1 for texture, the closer you are to 16, 32, 48, 64 the more color from texture 1, 2, 3, 4 you get. So: 16 = 1, 8 = 0.5 4 = 0.25
float redValue = 0.0;
float red = input.Color.r * max;
if ( fmod(red, each) == 0.0) // or (16.0 % 16.0), which basically is 0.0
{
redValue = 1.0;
}
else
{
redValue = fmod(red, each) / each;
// or (8.0 % 16.0) / 16.0
// which is (8 % 16.0) = 8 and 8 / 16 = 0.5
// which means the texture should be blended 0.5 or 50%.
}
Step 4 And finally by using the function GetColor I collect colors for each texture.
color += GetColor(index, value, input.TexCoord);
// and then do the same for green, blue, alpha values only add + 16
// because colors at (0,16,0,0) would be 16 + 1
// and color (0,0,32,0) would be 32 + 2
// and color (0,0,0,64) would be 48 + 4