Reputation: 19
I have this geometry: Picture
I want to add the same effect that mountains are with snow texture and so on:
Texture splatting with Three.js
Little background what info I give to shaders from Three.js:
//importing grass and snow textures:
var grassTexture = new THREE.ImageUtils.loadTexture( 'images/grass-512.jpg' );
grassTexture.wrapS = grassTexture.wrapT = THREE.RepeatWrapping;
var snowTexture = new THREE.ImageUtils.loadTexture( 'images/snow-512.jpg' );
snowTExture.wrapS = snowTExture.wrapT = THREE.RepeatWrapping;
this.customUniforms = {
grassTexture: { value: grassTexture },
snowTexture: { value: snowTexture },
};
var customMaterial = new THREE.ShaderMaterial({
uniforms: customUniforms,
side: THREE.DoubleSide,
vertexShader: document.getElementById( 'vertexShader' ).textContent,
fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
});
//creating mesh, geometry is the model in picture.
mesh = new THREE.Mesh(geometry, customMaterial);
Vertex and fragment shaders:
//vertexShader:
varying vec2 vUV;
void main(){
vUV = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
I get full red model with this:
//fragmentShader:
void main(){
gl_FragColor = vec4(1, 0.0, 0.0, 1.0) ;
}
I want textures that are higher with snowTexture and lower with grassTexture.
uniform sampler2D grassTexture;
uniform sampler2D snowTexture;
varying vec2 vUV;
//Something like this?:
vec4 grass = texture2D( grassTexture, vUV);
vec4 snow = texture2D( snowTexture, vUV);
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0) + grass + snow;
Upvotes: 0
Views: 709
Reputation: 1735
This really not that hard to understand, let me walk you through the logic.
In your case, you don't want to use a displacement map. So, you need to set up a varying height
on your vertexShader to map your vertices up-coordinates [0,1] to your fragmentShader.
//vertexShader:
varying vec2 vUV;
varying float height;
void main() {
vUV = uv;
float maxPosition = 30.0; // this is an example value.
height = max( 0.0, min(1.0, position.y/maxPosition ) ); // assuming +y is up
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
Now you can access height
from your fragmentShader and use that information to select where you want your transitions to occur.
uniform sampler2D grassTexture;
uniform sampler2D snowTexture;
varying vec2 vUV;
varying float height;
void main(){
vec4 grass = (1.0 - smoothstep( 0.48, 0.52, height)) * texture2D( grassTexture, vUV);
vec4 snow = (smoothstep(0.48, 0.52, height) - 0.0) * texture2D( snowTexture, vUV);
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0) + grass + snow;
}
The link provided uses function smoothstep to make a gradual transition between the textures. We can create transitions using the follow pattern ( a - b ) * textureColor
.
In this case, a
controls when the texture starts to contribute to the fragment color.
b
controls when the texture stops contributing.
In other words, your grass texture will have already started contributing at every height, so we map a
to 1.0. It stops contributing around 0.5, so we give b
a smooth fade-out as it approaches that 0.5.
Your snow texture, on the other hand, will only start contributing around 0.5. So, we give a
a smooth fade-in as it approaches 0.5. It will never stop contributing, so we set b
as 0.0.
Hope this clears things up for you.
Upvotes: 1