Generating texture depending on height above ground plane

I’ve been going around in circles for a few days now…
Jut thought i’d ask here to see if i’m missing anything obvious.

I’m trying to colour a mesh according to height (Y axis) and a few other parameters to get varying terrain across my maps.

I can do this with RawTexture.CreateRGBTexture(...) or similar:


but it’s not a great fit; The resolution of the texture i need to generate is many times larger than the mesh if i want to avoid the pixelated boundaries visible where the snowline meets the grass in that image.

I tried playing with custom shaders:


but i loose shadows and diffuse coloring; Note the colouring of the mountain top does not take light into account so you just end up with a flat colour.
It does solve the pixelation issue though.
Both the issues are fixable with work…
but reading there doesn’t appear to be anything “out of the box” that will work here and fixing shadows seems like a lot of work that maybe i can avoid.
It’s interesting to note the reason shadows are usually an issue here is that shaders might be altering the vertex positions, so changing the shadow, whereas i am only altering the pixel color.

Next i tried playing with CustomProceduralTexture(...).
It seems like a good fit; It’s a nice mix of textures and custom shaders allowing me to just write a fragment shader but let Babylon do the shadows, defuse lighting, etc.
Unfortunately i don’t have access to the Y axis data; CustomProceduralTexture(...) uses the src/Shaders/procedural.vertex.fx vertex shader that only passes the X and Z axis to the fragment shader. (varying vec2 vPosition;)

I poked around in CustomProceduralTexture(...) source code and don’t see any obvious ways to change the default vertex shader.

Options i’m currently considering:

  1. Use custom shaders. Fix shadows and diffuse lighting. It can be done but seems un-necesary.

  2. Use CustomProceduralTexture and pass in /all/ my vertex data as a uniform parameter or texture and extrapolate to find Y axis for any given X,Z. This would work but seems like a lot of work for the GPU for nothing.

  3. Make a local copy of CustomProceduralTexture(...) and ProceduralTexture(...) which allows me to specify my own vertex shader at run time. There is already a CustomProceduralTexture.setFragment(...) method. adding setVertex(...) would be fairly straight forward. (Any interest in me submitting a PR for something like this or is it too niche?)

Anyway,
i’ve had fun so far.
It’s the first time i’ve played with shaders. You can do some interesting things with them…

Hmm.
Thinking about this some more,
I wonder what the difference between my attempts at using custom shaders (ShaderMaterial(...)) and CustomProceduralTexture(...) are?

I had presumed that it was the shader adding diffuse lighting effects and shadows from a separate texture map but looking at the shaders used buy CustomProceduralTexture(...) this is not the case.

Either multiple shaders are applied or i’m missing something in the config when playing with custom shaders.
Either way, that should be reproducible for custom shaders.

And more rambling:
Is it possible my issue with CustomProceduralTexture(...) is a bug?

seems to suggest the attribute position in a shader program should always be a vec3.
That’s for regular shaders (rather than procedural textures) though…
Maybe the mapping for textures “unwraps” the position attribute into a 2d plane?
That would make some sense but rule out my idea to simply replace the vertex shader with my own…

Anyway, looks like i have some code reading to do.

I tried to do the same thing. I think the answer to this question addresses the issue - Dynamic terrain with height-dependent textures? - Questions - Babylon.js. Everything seems to work fine

1 Like

oh cool.
I’d missed that forum thread.

Poking around on Github, looking at commit dates, implies that CustomProceduralTexture pre-dates WorldMonger.
Since WorldMonger uses custom shaders, it implies that is the right path.

Looks like handling diffuse lighting is indeed done in the shader program.
Do you know if shadows work with this? I don’t see any reference to them in the code and from the WorldMonger demo, i don’t see why they would be required…

This looks like a sane template for implementing what i want:

It seems to already have a fully featured material; Shadows, lighting, etc.
I can probably just hack in the extra functionality i need there.

CustomProceduralTexture is for generating textures, you only write a fragment shader that generates the data for the texture.

ShaderMaterial is a class that will let you write shaders (vertex/fragment) to be applied on a mesh. It can use a texture (generated by CustomProceduralTexture for eg) to generate pixels displayed on screen.

You can try to use the NME to create your material instead of writing GLSL code. The advantage is that shadows/lighting will work as expected (as long as you use the Lighting block in your node material).

1 Like

CustomProceduralTexture is for generating textures, you only write a fragment shader that generates the data for the texture.

Oh yes, i get that.
the problem is i don’t have the data i need within the fragment shader because the vertex shader does not pass it on.
I need all 3 axis of the position attribute.
I could imagine some use cases for having the normals as well. (I don’t need normals, i’m just trying to think of other edge cases.)

You can’t have it.

The custom procedural texture is like a post process (or a shader from ShaderToy), it’s a 2D quad that is rasterized and for which you write the fragment shader. So, you can only get a 2D position, which is really a 2D uv coordinate.

To illustrate, here’s the vertex shader used by the procedural texture:

// Attributes
attribute vec2 position;

// Output
varying vec2 vPosition;
varying vec2 vUV;

const vec2 madd = vec2(0.5, 0.5);

void main(void) {	
	vPosition = position;
	vUV = position * madd + madd;
	gl_Position = vec4(position, 0.0, 1.0);
}

What you want to do must be done with a regular shader material, so either with ShaderMaterial, CustomMaterial (PBRCustomMaterial for PBR) or a node material.

1 Like

ack.
That’s where i though this was going.
Thanks for confirming.

Yup. Going to look into the materialsLibrary/src/simple example next.
Looks like it has everything i need.

I really should explore this option too but i don’t find the web UI particularly intuitive. (that’s a reflection of me, not NME.)
Code suits me better.

Thanks for the input!

So the materialsLibrary/src/simple/ boilerplate worked out well.
It does everything i need out of the box.
All i had to do was add my code to colour the faces in the fragment shader.
I’ve still got a bit of tidy-up to do but this is starting to look nice:

Next up: get those rivers looking a bit more organic.

Thanks for the support folks!

2 Likes