mylingo3d
Version:
Lingo3D is a React/Vue 3d game development framework that ships with a complete visual editor
105 lines (89 loc) • 3.51 kB
JavaScript
import { Clock, DoubleSide, InstancedMesh, Object3D, PlaneGeometry, ShaderMaterial, } from "three";
import { MeshSurfaceSampler } from "three/examples/jsm/math/MeshSurfaceSampler";
import Cube from "../display/primitives/Cube";
import { vector3, vector3_ } from "../display/utils/reusables";
import scene from "../engine/scene";
import { onBeforeRender } from "../events/onBeforeRender";
const leavesMaterial = new ShaderMaterial({
vertexShader: `
varying vec2 vUv;
uniform float time;
// 噪波
float N (vec2 st) {
return fract( sin( dot( st.xy, vec2(12.9898,78.233 ) ) ) * 43758.5453123);
}
float smoothNoise( vec2 ip ){
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 );
}
void main() {
vUv = uv;
float t = time * 2.;
// 顶点位置
vec4 mvPosition = vec4( position, 1.0 );
mvPosition = instanceMatrix * mvPosition;
// 移动
float noise = smoothNoise(mvPosition.xz * 0.5 + vec2(0., t));
noise = pow(noise * 0.5 + 0.5, 2.) * 2.;
// 叶片顶部晃动力度.
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: `
varying vec2 vUv;
void main() {
vec3 baseColor = vec3( 0.41, 1.0, 0.5 );
float clarity = ( vUv.y * 0.5 ) + 0.5;
gl_FragColor = vec4( baseColor * clarity, 1 );
}
`,
uniforms: {
time: {
value: 0
}
},
side: DoubleSide
});
const cube = new Cube();
cube.width = 1000;
cube.depth = 1000;
cube.height = 10;
const sampler = new MeshSurfaceSampler(cube.nativeObject3d).build();
const instanceNumber = 100;
const dummy = new Object3D();
const geometry = new PlaneGeometry(0.1, 1, 1, 4);
geometry.translate(0, 0.5, 0); // 吧草叶的最低点设置到0.
const instancedMesh = new InstancedMesh(geometry, leavesMaterial, instanceNumber);
scene.add(instancedMesh);
const _position = vector3;
const _normal = vector3_;
for (let i = 0; i < instanceNumber; i++) {
sampler.sample(_position, _normal);
_normal.add(_position);
dummy.position.set(_position.x, 0, _position.z);
dummy.scale.setScalar(0.5 + Math.random() * 0.5);
dummy.rotation.y = Math.random() * Math.PI;
dummy.updateMatrix();
instancedMesh.setMatrixAt(i, dummy.matrix);
}
export const clock = new Clock();
onBeforeRender(() => {
leavesMaterial.uniforms.time.value = clock.getElapsedTime();
leavesMaterial.uniformsNeedUpdate = true;
});
//# sourceMappingURL=testGrass.js.map