attributeMap texture shader

hey all,

im pretty new to panda and am trying to texture a terrain i made with l3dt.
l3dt generates an alpha-map for each texture used in the landscape…
it also can generate an color-coded attributemap which seems to be nearly the same as the alphamaps but in one image just using different colors…

i tried pro-rsofts shader for using multiple alpha-maps to apply the textures and extended it to be able to use 6 textures (and alpha-maps) since the l3dt-landscape uses 6 different textures.

result was, it didnt work with 6 textures (dont ask me why).
“not working” means here -> everywhere the same texture was used.

it did work with 5 textures though it looked pretty ugly… anyways… im only at the real basics here and want to understand how to texturize a landscape exactly as it looked in l3dt efficiently ,)

since it worked with 5 textures and i read pro-rsofts comment about it being very inefficient to store 5 alphamaps in 5 different files and so on i thought, ok: why not use the attributemap from l3dt, convert it to grayscale and select the texture to use in the shader based on the greyscale value…

problem is… i have no clue about shaders really and i have no idea how to debug them ,)

my concrete problem can be explained in the fshader shown below…

void fshader( in float4 l_position : POSITION,
              in float2 l_texcoord0 : TEXCOORD0,
              in float2 l_texcoord3 : TEXCOORD3,
	          in float  l_brightness, 
              in uniform sampler2D tex_0 : TEXUNIT0,
              in uniform sampler2D tex_1 : TEXUNIT1,
              in uniform sampler2D tex_2 : TEXUNIT2,
              in uniform sampler2D tex_3 : TEXUNIT3,
              in uniform sampler2D tex_4 : TEXUNIT4,
              in uniform sampler2D tex_5 : TEXUNIT5,
              in uniform sampler2D tex_6 : TEXUNIT6,
              out float4 o_color : COLOR )
{
  float4 tex1 = tex2D(tex_0,l_texcoord0);
  float4 tex2 = tex2D(tex_1,l_texcoord0);
  float4 tex3 = tex2D(tex_2,l_texcoord0);
  float4 tex4 = tex2D(tex_3,l_texcoord3);
  float4 tex5 = tex2D(tex_4,l_texcoord3);
  float4 tex6 = tex2D(tex_5,l_texcoord3);
  float attr  = tex2D(tex_6,l_texcoord3).z;

  // determine texture to use based on greyscale value.
  if (attr >= 0.0124 && attr <= 0.0126) o_color = tex1;
  else if (attr >= 0.00832 && attr <= 0.00834) o_color = tex2;
  else if (attr >= 0.00825 && attr <= 0.00827) o_color = tex3;
  else if (attr >= 0.00679 && attr <= 0.00681) o_color = tex4;
  else if (attr >= 0.00653 && attr <= 0.00655) o_color = tex5;
  else if (attr >= 0.00640 && attr <= 0.00642) o_color = tex6;
  o_color     = o_color*(l_brightness);
  o_color.a   = 1.0;
}

as you can see, i assumed (extending from the alpha-map example) that the greyscale-value is a vaue between 0 and 1… so i tried to divide 1 by the greyscale value i extracted using image.getcolors (PIL function) and use that as the criteria to determine which texture to use…

well… it didnt work… besides i did those >= and <= comparisons since i have no idea at which precision the float (attr) is being handled at that position… hoped to catch some higher precision by specifying a range that included this…

so… finally coming to the questions ,-))

  1. can it at all be done the way i thought ?

  2. what value would the variable “attr” have in this example if you feed it an greyscale.png-file

  3. is there any way to debug shaders ? ive seen the “throw” statement in cg-syntax-documentation but just couldnt find an example anywhere on how to use it… (was a desperate thought to somehow find out the values of “attr” ^^)

  4. actually (as i found out while doing image.getcolors()) the attributemap from l3dt contains more distinct colors than textures…
    there were 10 different colors but only 6 textures used…
    anybody has an explanation for this ?

if it really is something completely different than the alpha-maps i could write a program to combine the alpha-maps into one picture while giving each alpha-map a distinct greyscale-value in the resulting combined image…
so its not a stopper, if the attributemap isnt really what i expected. i simply used it due to lazyness so far…

i hope anybody can shed a little light on this, since im running out of thoughts where to look for more input on shaders / multitextured terrains and all this stuff, thats actually pretty new to me ^^

greets and thanks in advance, mooded :slight_smile:

L3DT’s attribute maps are 16-bits grayscale - keep that in mind, when you use a program like GIMP you lose 8 bpp of data.
The values in the attribute map are 16-bits integers and can be found by exporting the type list from L3DT.
So in the shader, I think you have to multiply the float value by 65535, make it an integer, and then compare it to the value from the type list.

However, I didn’t have much luck using the attribute map in my terrain shaders - especially since you can’t use any kind of filtering then, or smooth interpolations (I like to smooth my alphamaps).
Also, “if” tests are very slow on the GPU.

I’d rather recommend you to export all alpha maps from L3DT individually, and encode them into two textures, each channel an alpha map. (So the red, green, blue, alpha channels all store a different alpha map.)
This way, you can enable filtering, blur your alpha maps, replace those “if” tests with multiply commands, and it requires less coding. :slight_smile:

heya…

thanks for the quick reply… :slight_smile:

so ok… i feared that if-else-comparisons could be pretty slow… well… seems i better go your way with combining the alpha-maps in the different channels of an image…

especially the blurring you’re talking about sounds nice :slight_smile:
can the result be nearly as good as treeforms treeterrain.py ?

i thought the results looked pretty awesome but honestly i didnt get how exactly was determined where which texture goes…
(and how the images have to be named and and and… ) :wink:

furthermore, you dont happen to have a shader at hand, that deals with youre aforementioned “combined-alpha maps” (each map in a different channel) ?

greets and thanks again :slight_smile:

At least as good. I pre-blur the alpha maps though - less work for the GPU.

Here’s the basic idea for four textures. I didn’t test it, but this is the general idea.

void fshader( in float4 l_position : POSITION,
              in float2 l_texcoord0 : TEXCOORD0,
              in float2 l_texcoord3 : TEXCOORD3,
             in float  l_brightness,
              in uniform sampler2D tex_0 : TEXUNIT0,
              in uniform sampler2D tex_1 : TEXUNIT1,
              in uniform sampler2D tex_2 : TEXUNIT2,
              in uniform sampler2D tex_3 : TEXUNIT3,
              in uniform sampler2D k_detailmap : TEXUNIT4,
              out float4 o_color : COLOR )
{
  float4 tex1 = tex2D(tex_0,l_texcoord0);
  float4 tex2 = tex2D(tex_1,l_texcoord0);
  float4 tex3 = tex2D(tex_2,l_texcoord0);
  float4 tex4 = tex2D(tex_3,l_texcoord0);
  float4 detailmap  = tex2D(k_detailmap,l_texcoord3);

  o_color = float4(0, 0, 0, 0);
  o_color += tex1 * detailmap.r;
  o_color += tex2 * detailmap.g;
  o_color += tex3 * detailmap.b;
  o_color += tex4 * detailmap.a;
  o_color.a   = 1.0;
}