Texture Splatting Shader

Can anyone please give me some help with this shader? When using the alpha channel for blending the final texture on top all others, all others ‘shine’ through it, because its additive I guess. How can I negate the others from it?

Can anyone also help me to add lighting, atleast just ambient and directional, to this please? If I had torches all over the terrain with point lights, how would I add their lighting to this, automatically?

//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 float4x4 trans_model_to_world,
            out float2 l_texcoord0 : TEXCOORD0, 
            out float4 l_position : POSITION) 
    l_position = mul(mat_modelproj, vtx_position);
    l_texcoord0 = vtx_texcoord0;

void fshader( in float4 l_position : POSITION, 
              in float2 l_texcoord0 : TEXCOORD0, 
              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,
              out float4 o_color : COLOR,
              uniform float4 k_tile )
    float4 texelColor0 = tex2D(tex_0, l_texcoord0 * int(k_tile[0])); 
    float4 texelColor1 = tex2D(tex_1, l_texcoord0 * int(k_tile[0]/4)); 
    float4 texelColor2 = tex2D(tex_2, l_texcoord0 * int(k_tile[0]));
    float4 texelColor3 = tex2D(tex_3, l_texcoord0 * int(k_tile[0]));
    float4 blendColor = tex2D(tex_4, l_texcoord0); 
    float4 lightColor = tex2D(tex_5, l_texcoord0);
    o_color = (texelColor0 * blendColor.x) + (texelColor1 * blendColor.y) + (texelColor2 * blendColor.z) + (texelColor3 * blendColor.a);
    o_color *=lightColor;
    o_color.a = 1.0; 

Are you a python user? You can do splatting with python:

import direct.directbase.DirectStart
from pandac.PandaModules import *
from direct.interval.IntervalGlobal import *


# the terrain geometry
terrain = loader.loadModel("environment")

# Stage 1: the first texture
ts = TextureStage("stage-first")


terrain.setTexture(ts, loader.loadTexture("maps/envir-ground.jpg"))

# Stage 2: the second texture
ts = TextureStage("stage-second")
terrain.setTexture(ts, loader.loadTexture("maps/envir-treetrunk.jpg"))

# Stage 3: stencil
ts = TextureStage("stage-stencil")
ts.setCombineRgb(TextureStage.CMInterpolate, TextureStage.CSPrevious, TextureStage.COSrcColor, TextureStage.CSLastSavedResult, TextureStage.COSrcColor, TextureStage.CSTexture, TextureStage.COSrcColor)
terrain.setTexture(ts, loader.loadTexture("maps/panda_torso.rgb"))

# Stage 4: reapply vertex colour (lightning)
ts = TextureStage("stage-vertexcolour")
ts.setCombineRgb(TextureStage.CMModulate, TextureStage.CSPrevious, TextureStage.COSrcColor, TextureStage.CSPrimaryColor, TextureStage.COSrcColor)
terrain.setTexture(ts, "final")

# lightning
plight = PointLight('plight')
plnp = render.attachNewNode(plight)
plnp.setHpr(0, 0, 0)

render.setShaderAuto() # important


I was under the impression that tiling does not work correctly when using this method, because the blend map would also tile. Not so?


EDIT: Though you should have a different reference variable name for each texture stage I guess (ex: ts1, ts2, etc) and do nodePath.setTexScale(ts1, 1, 1)

Any idea why texture scale would not want to change? I’m testing with only this stage:

# Stage 1: the first texture 
tex1s = TextureStage("tex1") 
model.setTexture(tex1s, loader.loadTexture(tex1)) # tex1 is a Filename object

Not sure why.
I checked again and it works for me. Maybe you have panda3d 1.6.2 and can’t apply a texture transforms when shader generator is enabled? But this doesn’t quite work for me when I have it disabled: lightning doesn’t work (maybe you can’t have 4 texture stages in fixed function pipeline?)

Also note that if you want the texture to tile on the geometry, you should set the values higher than 1, not lower.

Aha! yes, I’m using the old physx wrapper with 1.6.2, had some problems with the new implemented physx. Guess its time to look into using it again.