Hi so I have some grass that uses shader materials and they are instance meshes … in my scene I have a light that cast shadows, so far so good but It doesn’t work for the grass so I wondering how i can apply shadows to it? to recieve shadows and cast them any idea’s?
code:
const vertexShader = `
varying vec2 vUv;
uniform float time;
${simpleNoise}
void main() {
vUv = uv;
float t = time * 2.;
// VERTEX POSITION
vec4 mvPosition = vec4( position, 1.0 );
#ifdef USE_INSTANCING
mvPosition = instanceMatrix * mvPosition;
#endif
// DISPLACEMENT
float noise = smoothNoise(mvPosition.xz * 0.5 + vec2(0., t));
noise = pow(noise * 0.5 + 0.5, 2.) * 2.;
// here the displacement is made stronger on the blades tips.
float dispPower = 1. - cos( uv.y * 3.1416 * 0.5 );
float displacement = noise * ( 0.3 * dispPower );
mvPosition.z -= displacement;
//
vec4 modelViewPosition = modelViewMatrix * mvPosition;
gl_Position = projectionMatrix * modelViewPosition;
}
`;
const fragmentShader = `
varying vec2 vUv;
void main() {
vec3 baseColor = vec3( 0.41, 1.0, 0.5 );
float clarity = ( vUv.y * 0.875 ) + 0.125;
gl_FragColor = vec4( baseColor * clarity, 1 );
}
`;
const uniforms = {
time: {
value: 0
}
}
this.leavesMaterial = new THREE.ShaderMaterial({
vertexShader,
fragmentShader,
uniforms,
side: THREE.DoubleSide,
castShadow: true,
recieveShadow: true,
});
const instanceNumber = 50000;
const dummy = new THREE.Object3D();
const geometry = new THREE.PlaneGeometry( 0.1, 1, 1, 4 );
geometry.translate( 0, 0.5, 0 ); // move grass blade geometry lowest point at 0.
const instancedMesh = new THREE.InstancedMesh( geometry, this.leavesMaterial, instanceNumber );
this.scene_.add( instancedMesh );
// Position and scale the grass blade instances randomly.
for ( let i=0 ; i<instanceNumber ; i++ ) {
dummy.position.set(
( Math.random() - 0.3 ) * 300,
0,
( Math.random() - 0.3 ) * 300
);
dummy.scale.setScalar( 1.0 + Math.random() * 2.6 );
dummy.scale.y = 1.0 + Math.random() * 5.5;
dummy.rotation.y = Math.random() * Math.PI;
dummy.updateMatrix();
instancedMesh.setMatrixAt( i, dummy.matrix );
}
thanks for any help
1 Like
tried this but didn’t work:
import { mergeUniforms } from 'three/src/renderers/shaders/UniformsUtils.js'
import { UniformsLib } from 'three/src/renderers/shaders/UniformsLib.js'
uniforms: mergeUniforms([
UniformsLib.lights,
UniformsLib.fog,
]);
const vertexShader = `
#include <common>
#include <fog_pars_vertex>
#include <shadowmap_pars_vertex>
varying vec2 vUv;
uniform float time;
${simpleNoise}
void main() {
#include <begin_vertex>
#include <project_vertex>
#include <worldpos_vertex>
#include <shadowmap_vertex>
#include <fog_vertex>
vUv = uv;
float t = time * 2.;
// VERTEX POSITION
vec4 mvPosition = vec4( position, 1.0 );
#ifdef USE_INSTANCING
mvPosition = instanceMatrix * mvPosition;
#endif
// DISPLACEMENT
float noise = smoothNoise(mvPosition.xz * 0.5 + vec2(0., t));
noise = pow(noise * 0.5 + 0.5, 2.) * 2.;
// here the displacement is made stronger on the blades tips.
float dispPower = 1. - cos( uv.y * 3.1416 * 0.5 );
float displacement = noise * ( 0.3 * dispPower );
mvPosition.z -= displacement;
//
vec4 modelViewPosition = modelViewMatrix * mvPosition;
gl_Position = projectionMatrix * modelViewPosition;
}
`;
const fragmentShader = `
#include <common>
#include <packing>
#include <fog_pars_fragment>
#include <bsdfs>
#include <lights_pars_begin>
#include <shadowmap_pars_fragment>
#include <shadowmask_pars_fragment>
#include <dithering_pars_fragment>
varying vec2 vUv;
void main() {
vec3 baseColor = vec3( 0.41, 1.0, 0.5 );
float clarity = ( vUv.y * 0.875 ) + 0.125;
vec3 shadowColor = vec3(0, 0, 0);
float shadowPower = 0.5;
gl_FragColor = vec4( mix(baseColor * clarity, shadowColor, (1.0 - getShadowMask() ) * shadowPower), 1.0);
#include <fog_fragment>
#include <dithering_fragment>
}
`;
const uniforms = {
time: {
value: 0
}
}
this.leavesMaterial = new THREE.ShaderMaterial({
vertexShader,
fragmentShader,
uniforms,
fog: true,
lights: true,
dithering: true,
side: THREE.DoubleSide,
});
tried it this way simplexNoise not defined
import { mergeUniforms } from './three/src/renderers/shaders/UniformsUtils.js'
import { UniformsLib } from './three/src/renderers/shaders/UniformsLib.js'
export default {
uniforms: mergeUniforms([
UniformsLib.lights,
UniformsLib.fog,
]),
simpleNoise: `
float N (vec2 st) { // https://thebookofshaders.com/10/
return fract( sin( dot( st.xy, vec2(12.9898,78.233 ) ) ) * 43758.5453123);
}
float smoothNoise( vec2 ip ){ // https://www.youtube.com/watch?v=zXsWftRdsvU
vec2 lv = fract( ip );
vec2 id = floor( ip );
lv = lv * lv * ( 3. - 2. * lv );
float bl = N( id );
float br = N( id + vec2( 1, 0 ));
float b = mix( bl, br, lv.x );
float tl = N( id + vec2( 0, 1 ));
float tr = N( id + vec2( 1, 1 ));
float t = mix( tl, tr, lv.x );
return mix( b, t, lv.y );
}
`,
vertexShader: `
#include <common>
#include <fog_pars_vertex>
#include <shadowmap_pars_vertex>
varying vec2 vUv;
uniform float time;
${simpleNoise}
void main() {
#include <begin_vertex>
#include <project_vertex>
#include <worldpos_vertex>
#include <shadowmap_vertex>
#include <fog_vertex>
vUv = uv;
float t = time * 2.;
// VERTEX POSITION
vec4 mvPosition = vec4( position, 1.0 );
#ifdef USE_INSTANCING
mvPosition = instanceMatrix * mvPosition;
#endif
// DISPLACEMENT
float noise = smoothNoise(mvPosition.xz * 0.5 + vec2(0., t));
noise = pow(noise * 0.5 + 0.5, 2.) * 2.;
// here the displacement is made stronger on the blades tips.
float dispPower = 1. - cos( uv.y * 3.1416 * 0.5 );
float displacement = noise * ( 0.3 * dispPower );
mvPosition.z -= displacement;
//
vec4 modelViewPosition = modelViewMatrix * mvPosition;
gl_Position = projectionMatrix * modelViewPosition;
}
`,
fragmentShader: `
#include <common>
#include <packing>
#include <fog_pars_fragment>
#include <bsdfs>
#include <lights_pars_begin>
#include <shadowmap_pars_fragment>
#include <shadowmask_pars_fragment>
#include <dithering_pars_fragment>
varying vec2 vUv;
void main() {
// CHANGE THAT TO YOUR NEEDS
// ------------------------------
vec3 baseColor = vec3( 0.41, 1.0, 0.5 );
float clarity = ( vUv.y * 0.875 ) + 0.125;
vec3 shadowColor = vec3(0, 0, 0);
float shadowPower = 0.5;
// ------------------------------
// it just mixes the shadow color with the frag color
gl_FragColor = vec4( mix( (baseColor * clarity, 1), shadowColor, (1.0 - getShadowMask() ) * shadowPower), 1.0);
#include <fog_fragment>
#include <dithering_fragment>
}
`
};
main:
const uniforms = {
time: {
value: 0
}
}
this.leavesMaterial = new THREE.ShaderMaterial({
...BasicCustomShader,
uniforms,
side: THREE.DoubleSide,
fog: true,
lights: true,
dithering: true,
});