本来说写unity里的,由于three测试方便,先试试three
这个图片是目标效果
可以看见草很矮,很密集,如果用instance来绘制的话,遭不住的
忽然发现这个效果很像绒毛效果
于是找了博客康康
https://zhuanlan.zhihu.com/p/256445252
大概就是叠alpha,性能比instance好多了,虽然效果其实比不得instance,他这个实际来说丢失了每一根草的渲染能力,只能调叠层的色彩和整体调色,可能要和一根一根的草混用吧
这是在three构建demo的代码
const geometry = new THREE.PlaneGeometry(20, 20);//new THREE.ConeGeometry( 10, 30, 20, 20 );geometry.rotateX(Math.PI * 0.5);// const material = new THREE.MeshPhongMaterial( { color: 0xffffff, wireframe: true } );const material = new THREE.ShaderMaterial({uniforms: {id: { value: 1 },iTime: { value: 0 },},vertexShader: `uniform float id;varying vec2 vUv;varying vec3 vColor;varying vec3 vNormal;varying vec3 pos;void main() {vUv = uv;vColor = vec3(1.0, 0.0, 0.0);pos = position.xyz;vNormal = normal;pos+=normal*0.1*id;gl_Position = projectionMatrix * modelViewMatrix * vec4(pos.xyz,1.0);}`,fragmentShader: `uniform float id;uniform float iTime;varying vec3 vColor;varying vec3 vNormal;varying vec3 pos;varying vec2 vUv;float random (in vec2 st) {return fract(sin(dot(st.xy,vec2(12.9898,78.233)))* 43758.5453123);
}// 2D Noise based on Morgan McGuire @morgan3d
// https://www.shadertoy.com/view/4dS3Wd
float noise (in vec2 st) {vec2 i = floor(st);vec2 f = fract(st);// Four corners in 2D of a tilefloat a = random(i);float b = random(i + vec2(1.0, 0.0));float c = random(i + vec2(0.0, 1.0));float d = random(i + vec2(1.0, 1.0));// Smooth Interpolation// Cubic Hermine Curve. Same as SmoothStep()vec2 u = f*f*(3.0-2.0*f);// u = smoothstep(0.,1.,f);// Mix 4 coorners percentagesreturn mix(a, b, u.x) +(c - a)* u.y * (1.0 - u.x) +(d - b) * u.x * u.y;}vec4 permute(vec4 x) {return mod((34.0 * x + 1.0) * x, 289.0);}// Cellular noise, returning F1 and F2 in a vec2.// Speeded up by using 2x2 search window instead of 3x3,// at the expense of some strong pattern artifacts.// F2 is often wrong and has sharp discontinuities.// If you need a smooth F2, use the slower 3x3 version.// F1 is sometimes wrong, too, but OK for most purposes.vec2 cellular2x2(vec2 P) {#define K 0.142857142857 // 1/7#define K2 0.0714285714285 // K/2#define jitter 0.8 // jitter 1.0 makes F1 wrong more oftenvec2 Pi = mod(floor(P), 289.0);vec2 Pf = fract(P);vec4 Pfx = Pf.x + vec4(-0.5, -1.5, -0.5, -1.5);vec4 Pfy = Pf.y + vec4(-0.5, -0.5, -1.5, -1.5);vec4 p = permute(Pi.x + vec4(0.0, 1.0, 0.0, 1.0));p = permute(p + Pi.y + vec4(0.0, 0.0, 1.0, 1.0));vec4 ox = mod(p, 7.0)*K+K2;vec4 oy = mod(floor(p*K),7.0)*K+K2;vec4 dx = Pfx + jitter*ox;vec4 dy = Pfy + jitter*oy;vec4 d = dx * dx + dy * dy; // d11, d12, d21 and d22, squared// Sort out the two smallest distances#if 0// Cheat and pick only F1d.xy = min(d.xy, d.zw);d.x = min(d.x, d.y);return d.xx; // F1 duplicated, F2 not computed#else// Do it right and find both F1 and F2d.xy = (d.x < d.y) ? d.xy : d.yx; // Swap if smallerd.xz = (d.x < d.z) ? d.xz : d.zx;d.xw = (d.x < d.w) ? d.xw : d.wx;d.y = min(d.y, d.z);d.y = min(d.y, d.w);return sqrt(d.xy);#endif}void main(){float test2 = (noise(vUv*30.0)*0.5+0.5)*0.5;vec2 F = cellular2x2((vUv + 0.0* test2 * 0.0025*(1.0 - id)* sin(test2*0.1*iTime) )*2000.);float test = noise(vUv*15.0);vec3 yellow = vec3(0.4,0.9,0.0)*0.85;vec3 green = vec3(0.2,1.0,0.0)*0.85;float n = 1.0-1.5*F.x;//gl_FragColor += vec4(0.1, 0.5 + (1.0 - id)*0.25, 0.0, n * id);gl_FragColor += vec4(mix(green,yellow, test)*0.5+(1.0 - id)*0.5, n * id );// if(gl_FragColor.a<0.21)discard; else {gl_FragColor.a=1.0;// }// gl_FragColor += vec4(n,n,n, n * id*0.5);}`,transparent: true,side: 2})let arr = [];const COUNT = 30;for (let i = 0; i < COUNT; i++) {let geo = geometry.clone();const materialClone = material.clone();materialClone.uniforms.id.value = 1.0 - (i / COUNT);arr.push(materialClone);const mesh = new THREE.Mesh(geo, materialClone);scene.add(mesh);}