ground multitexturing- combine textures of different stages?

That looks better, but you’ve still got MReplace instead of MModulate.

David

:slight_smile:

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

terrain = loader.loadModel('terrain')
terrain.reparentTo(render)


# Stage 1: the first texture
ts = TextureStage("stage-first")
ts.setSort(0)
ts.setMode(TextureStage.MModulate)

ts.setSavedResult(True)

terrain.setTexture(ts, loader.loadTexture("dirt.png"))

# Stage 2: the second texture
ts = TextureStage("stage-second")
ts.setSort(1)
ts.setMode(TextureStage.MModulate)
terrain.setTexture(ts, loader.loadTexture("grass.png"))

# Stage 3: stencil
ts = TextureStage("stage-stencil")
ts.setSort(2)
ts.setCombineRgb(TextureStage.CMInterpolate, TextureStage.CSPrevious, TextureStage.COSrcColor,
				TextureStage.CSLastSavedResult, TextureStage.COSrcColor, 
				TextureStage.CSTexture, TextureStage.COSrcColor) 
terrain.setTexture(ts, loader.loadTexture("stencil.png"))


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

# just to make sure it is working
lightInterval = LerpPosInterval(plnp, 3, (0,0,5),startPos=(0,0,-5)).loop()

terrain.setShaderAuto()
render.setLight(slnp)


run()

This works. Thanks again.

Can someone show an example showing 5 or 6, or even more textures?

I can get the first 4 or so, but it always errors when I go more or start adding lights. This is with setShaderAuto.

Don’t know about that, but this code isn’t actually what I wanted,


The top one is the result I want to achieve.
The below one is what I get.

Ah, you’re right. The MModulate is applying the green onto the dirt. You’d have to go back to MReplace, and then if you want the vertex color, you’d have to reapply that afterwards, using yet another TextureStage.

I’m not 100% sure it’s possible to define what you’re looking for with the fixed-function modes. At this point, it’s probably better to write a custom shader.

David

Yeah, like the ‘Multiply’ mode for layers in image editors.

Um, how to get the vertex colour then?

I sure hope I don’t need to. I think what I want is pretty common thing.

IIRC There’s a CSPrimaryColor source, you can use this to re-apply the original colour after the rest of the stages.

Like this?

# Stage 4: reapply vertex colour
ts = TextureStage("stage-vertexcolour")
ts.setSort(3)
ts.setCombineRgb(TextureStage.CMModulate,TextureStage.CSPrevious,TextureStage.COSrcColor, TextureStage.CSPrimaryColor,TextureStage.COSrcColor)

bump

Yes, that seems like the right approach. Does it work?

David

Just write a custom shader its not that hard…

I beg to differ on that. Writing a custom shader was one of my most frustrating programming experiences so far.

Right…

@drwr: So this is supposed to work?

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

base.cam.setPos(0,-15,0)


# the terrain geometry
terrain = loader.loadModel('terrain')
terrain.reparentTo(render)
terrain.setHpr(0,90,0)


# Stage 1: the first texture
ts = TextureStage("stage-first")
ts.setSort(0)
ts.setMode(TextureStage.MReplace)

ts.setSavedResult(True)

terrain.setTexture(ts, loader.loadTexture("dirt.png"))

# Stage 2: the second texture
ts = TextureStage("stage-second")
ts.setSort(1)
ts.setMode(TextureStage.MReplace)
terrain.setTexture(ts, loader.loadTexture("grass.png"))

# Stage 3: stencil
ts = TextureStage("stage-stencil")
ts.setSort(2)
ts.setCombineRgb(TextureStage.CMInterpolate, TextureStage.CSPrevious, TextureStage.COSrcColor, TextureStage.CSLastSavedResult, TextureStage.COSrcColor, TextureStage.CSTexture, TextureStage.COSrcColor) 
terrain.setTexture(ts, loader.loadTexture("stencil.png"))

# Stage 4: reapply vertex colour
ts = TextureStage("stage-vertexcolour")
ts.setSort(3)
ts.setCombineRgb(TextureStage.CMModulate, TextureStage.CSPrevious, TextureStage.COSrcColor, TextureStage.CSPrimaryColor, TextureStage.COSrcColor)


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


lightIval = LerpPosInterval(plnp, 3, (0,0,10), startPos=(0,0,-10)).loop()

terrain.setShaderAuto()
render.setLight(plnp)


run()

Also it is very hard to notice but in the very first frame of the application the dirt texture is white in this case, for some reason.

Say again… ??? :unamused:

I don’t know. It looks like the right idea. Why are you asking me–does it work, or does it not?

That sounds like it is due to the shader being compiled and applied the first frame. I bet it won’t flash if you remove setShaderAuto().

David

I asked is it ‘supposed’ to work. Because it doesn’t

Then only the 1st texture will get lit

Well, now that you tell me it doesn’t work, I look more closely and see that you haven’t applied your “Stage 4” TextureStage onto the geometry. You’ve only created the TextureStage, you haven’t done anything with it. You still need to apply it with a terrain.setTexture(), like you are doing with the above textures.

Since this TextureStage doesn’t use its own texture’s colors, you can use any texture you like–it doesn’t matter.

I’m not sure what you mean here. Since you’re using only fixed-function controls, the look of the textures should be pretty much the same with and with the shader, except that the shader enables per-pixel lighting which means your point light will illuminate a circular region properly, instead of illuminating only the nearest vertices.

David

:angry:
lol

Well I’m not sure if I’m forgetting something obvious again, but commenting render.setShaderAuto() will make the terrain not react to the light.
Thanks for the patience.

If the light isn’t near any vertices, it will look like it’s not affecting the terrain at all. Try positioning the light directly above a vertex.

David

I don’t see any difference, even with spotlights, but I’m using perpixel lightning for the terrain so this isn’t a real problem for me. Just curious.