problem with textures in 1.5

Hello !

I’m finally upgrading to panda 1.5 ! ( in fact i was still in panda 1.32 !! )

but i have a problem.
now my terrain have a strange behavior. it doesn’t seems to use my shader ( no shader compilation error ) and just display one of his textures, randomly ( always the same for the same heightfield )

        vertex_format = GeomVertexFormat.getV3n3t2()
        index_buffer  = GeomTriangles(Geom.UHStatic)
        vertex_buffer = GeomVertexData('hf_vertices', vertex_format, Geom.UHStatic)

        geom = Geom(vertex_buffer)
        geom.addPrimitive(index_buffer)
geomNode = GeomNode('heightfield')
geomNode.addGeom(geom)
 node = NodePath(geomNode)
 for ts, tex, priority in tex_ts_priority : # 7 tex used
          node.setTexture(ts, tex,priority))

node.setShader(loader.loadShader('terrain.sha'))
node.setShaderInput('lightvec1', _lightvec1 )
[...]

post the shader i think its the culprit here.

it’s a blend between 3 texture/normal map:

//Cg
//Cg profile arbvp1 arbfp1

void vshader( in float4 vtx_position  : POSITION,
              in float3 vtx_normal    : NORMAL,
              in float2 vtx_texcoord0 : TEXCOORD0,

              in uniform float4x4 mat_modelproj,
              in uniform float4 k_lightvec1,
              in uniform float4 k_lightvec2,
              in uniform float4 k_lightvec3,

              out float2 l_texcoord0 : TEXCOORD0,
              out float3 l_light1    : TEXCOORD1,
              out float3 l_light2    : TEXCOORD2,
              out float3 l_light3    : TEXCOORD3,
              out float4 l_position  : POSITION)
{
    l_position  = mul( mat_modelproj, vtx_position );
    l_texcoord0 = vtx_texcoord0;

    //transpose to textureplace ( already in object space )
    l_light1 = -normalize(k_lightvec1.xyz);
    l_light2 = -normalize(k_lightvec2.xyz);
    l_light3 = -normalize(k_lightvec3.xyz);
}

void fshader( in float4 l_position : POSITION,
              in float2 l_texcoord0 : TEXCOORD0,
              in float3 l_light1 :TEXCOORD1,
              in float3 l_light2 :TEXCOORD2,
              in float3 l_light3 :TEXCOORD3,

              in uniform float4 k_hfsize,

              in uniform sampler2D tex_0 : TEXUNIT0, // tex low
              in uniform sampler2D tex_1 : TEXUNIT1, // tex middle
              in uniform sampler2D tex_2 : TEXUNIT2, // tex high
              in uniform sampler2D tex_3 : TEXUNIT3, // normal low
              in uniform sampler2D tex_4 : TEXUNIT4, // normal middle
              in uniform sampler2D tex_5 : TEXUNIT5, // normal high
              in uniform sampler2D tex_6 : TEXUNIT6, // blend

              out float4 o_color : COLOR )
{
    float2 g_texcoord;
    float2 loc_texcoord2;
    loc_texcoord2  = l_texcoord0;

    g_texcoord.x   = loc_texcoord2.x / k_hfsize.x;
    g_texcoord.y   = loc_texcoord2.y / k_hfsize.y;

    float4 B       = tex2D( tex_6, g_texcoord );

    loc_texcoord2 *= 0.01f;

    float4 c0 = tex2D( tex_0, loc_texcoord2 );
    float4 c1 = tex2D( tex_1, loc_texcoord2 );
    float4 c2 = tex2D( tex_2, loc_texcoord2 );

    float4 n0 = tex2D( tex_3, loc_texcoord2 );
    float4 n1 = tex2D( tex_4, loc_texcoord2 );
    float4 n2 = tex2D( tex_5, loc_texcoord2 );


    // texture blending
    // scale the total color to the range [0, 1].
    float totalInverse = 1.0f / (B.x + B.y + B.z);
    c0 *= B.x * totalInverse;
    c1 *= B.y * totalInverse;
    c2 *= B.z * totalInverse;

    n0 *= B.x * totalInverse;
    n1 *= B.y * totalInverse;
    n2 *= B.z * totalInverse;

    float3 normal =n0;// n0 + n1 + n2 ;
 
    float light1 = max(0,dot(normal,0.7 *l_light1.xyz));
    float light2 = max(0,dot(normal,0.25*l_light2.xyz));
    float light3 = max(0,dot(normal,0.25*l_light3.xyz));
    float ambiant1 = 0.1;
    
    float brightness = ambiant1 + light1 + light2 + light3; 
    o_color = brightness * ( c0 + c1 + c2 );
    o_color.w = 1.0f;
}

I’m also getting really odd behavior of my shaders (each time I run my game the texturing on my terrain looks different)
It seems to be grabbing a random texture each time indeed. Maybe this has to do with texture ordering? I really hope this could be fixed soon, I was planned to release a techdemo of my game this week but now it is delayed.

Haha, I first thought it was my terrain class which did it all wrong… I totally rewrote it from scratch but the problem still occurs…

EDIT: Treeform pointed me on the IRC to the fact that I had to set the texture priorities, but that still didn’t work…

i 've put priorities on my setTexture to check this, with no change

I’ve experienced this too… Was going to post it but I wanted to isolate the error first.

I’m was using PGMM in 1.5 but didn’t have time to debug it so I went back to 1.4.2 and didn’t think about it more.

I’m not 100% sure what was happening but it seemed like the order of the textures for shaders was getting mixed up.
Nodepaths were even getting textures they weren’t suppoed to use, for example ocean was receiving my terrain textures, etc.

Is there any texture caching mechanism in Panda3D? Maybe it’s something with that.

A temporary solution which might actually work:
instead of just doing setTexture, assign your textures using the shader inputs, and access them using k_texname. Of course, this is just a hacky solution, and I’d really like to have this fixed soon.

:frowning:
that’s don’t seems to change anything. nice try ! :smiley:

Treeform suggested on IRC I’d also do setSort on my TextureStages apart from just the texture priorities, and everything works now! Yay! Looks like the old again!

A lot of people have mentioned this bug before, but nobody has ever sent me a reproducible example. I can’t fix it if I can’t reproduce it.

Send me the code, and I’ll fix it.

I really don’t like how the texture stage system works and resorted to always setting shader inputs precisely for weirdness like this:

1 random ordering ( fixed with setOrder )
fix: each texture stage gets added with priority lower (last index +1) then the one before it.

2 parent texture bleeds into the children:
fix: when adding a new texture stage check if there is a texture stage with that name already then replace it instead of just adding

3 model with texture metal and metal bump has text attach to it but the metal bump (being second texture) bleeds into the TextNode as second texture so you get both characters and metal bump rendered:
fix: add ability to specify “null” texture that would turn off that texture stage.

Then why bother fixing the texture stage system when the setShader input works great? I hacked my nodepath and setTexture use set shader inputs so i never see it causing problems any more :slight_smile:

Using the system that was causes one problem - egg files. Can we get shader inputs instructions into the egg files and I guess load shader itself? - that will be great

Here’s example code.
Note that it does work when i supply the textures directly to the pandaActor.

Python file:

from direct.directbase import DirectStart
from pandac.PandaModules import TextureStage
from direct.actor import Actor

dummy=render.attachNewNode('tmpnode')

#Load the panda actor, and loop its animation
pandaActor = Actor.Actor("models/panda-model",{"walk":"models/panda-walk4"})
pandaActor.setScale(0.005,0.005,0.005)
pandaActor.reparentTo(dummy)
pandaActor.loop("walk")

#set the second and third texture
dummy.setTexture(TextureStage("blah"), loader.loadTexture("maps/noise.rgb"), 20)
dummy.setTexture(TextureStage("werh"), loader.loadTexture("maps/envir-treetrunk.jpg"), 30)

pandaActor.setShader(loader.loadShader("test.sha"))

run()

test.sha:

//Cg

void vshader(float4 vtx_position : POSITION, 
             float2 vtx_texcoord0 : TEXCOORD0,
             out float4 l_position : POSITION,
             out float2 l_texcoord0 : TEXCOORD0,
             uniform float4x4 mat_modelproj)
{
  l_position=mul(mat_modelproj, vtx_position);
  l_texcoord0=vtx_texcoord0;
}

void fshader(in float4 l_position : POSITION,
             in float2 l_texcoord0 : TEXCOORD0,
             uniform sampler2D tex_0 : TEXUNIT0,
             uniform sampler2D tex_1 : TEXUNIT1,
             uniform sampler2D tex_2 : TEXUNIT2,
             out float4 o_color:COLOR)
{
  o_color = tex2D(tex_1, l_texcoord0);
}

pro-rsoft: when this renders on my computer, I see a bear that looks sort of brown and swirly. As far as I can tell, this is correct behavior given the code.

The code is nondeterministic - the TextureStages all have the same sort order, which means that the system is allowed to apply them in any order. Therefore, tex_0, tex_1, tex_2 will be the three textures, but in no predictable order.

Is this what you’re seeing (ie, a brown swirly bear?)

That might be… However, in Panda 1.4.2 it’s been deterministic… Textures were always sent to the shader in the order they are assigned to the node, even if no sorting is done.

It was never intended to be deterministic. Actually, as it happens, it used to be very nearly deterministic, especially for simple scenes where the same textures always appeared together always in the same context. But it’s important to remember that this previous apparently-deterministic behavior was just accidental.

It was in the edge conditions of this old behavior that was causing some other, more serious problems with graphics state confusion. We fixed these problems recently, and one (also accidental) side-effect of the fix is that the texture order is now more likely to be obviously random.

We haven’t technically changed the API, though; we just made some indeterminate code more obvious. We never noticed the change here, because we didn’t have any code that triggered it.

It could be argued that it would be desirable to support some deterministic sorting in the absence of an explicit texture order, and I’d be inclined to agree. However, it’s not at all clear how this would be implemented. Which texture would come first when you have texture A on a parent node and textures B and C together on the same child node?

Note that RenderAttrib priorities have nothing to do with texture sorting order. Texture sorting order is entirely controlled via TextureStage.setSort(), as described in the manual.

david

I think the problem is that bjarnia didn’t know about the sort-order field in the TextureStage. Not knowing about sort-order numbers, he made a reasonable but incorrect assumption about how TextureStages were sorted.

May I make a suggestion? Perhaps we should add an explicit nonoptional sort-order parameter to the TextureStage constructor.

Difficult to do that without invalidating tons of already-existing Python code.

David

What about having a config variable for backwards compatibility, but if the config variable isn’t set, require an explicit sort order?

Josh Yelon, run the thing again, and again, and again – does the texture look different?

At least it does here. The shader is written to always output the second texture – though it seems to be picking a random texture each time.

– at least that’s what it does here.

PS. An ability to supply the sort order in the texturestage’s constructor itself would be great. Maybe an optional parameter?