跳到主要内容
← Grass

Grass

Grass - Color

shader-learning 自学第 5 课:Grass - Color

实时渲染 · 网格 GLSL

第 5 课:Grass - Color

实现

uniform float iTime;

attribute int index;

varying float instanceHash;
varying float h;
varying float distanceToBladeCenter;

vec3 bezier3D(vec3 p0, vec3 p1, vec3 p2, float t) {
    float u = 1.0 - t;
    float tt = t * t;
    float uu = u * u;

    vec3 p = uu * p0;
    p += 2.0 * u * t * p1;
    p += tt * p2;

    return p;
}

vec2 random2(vec2 st){
  float d1 = dot(st, vec2(12.3, 32.1));
  float d2 = dot(st, vec2(45.6, 65.4));

  st = vec2(d1, d2);
  return fract(sin(st) * 78.9) * 2.0 - 1.0;
}

float random(float x) {
  float r = fract(sin(x * 12.34) * 1234.5678);
  return r * 2.0 - 1.0;
}

mat3 rotationYMatrix(float angle) {
    float cosAngle = cos(angle);
    float sinAngle = sin(angle);
    return mat3(
      vec3(cosAngle, 0, -sinAngle),
      vec3(0, 1, 0),
      vec3(sinAngle, 0, cosAngle)
    );
}

void main() {
  int   instance = index / 40;
  instanceHash = random(float(instance));
  int   localIndex = index % 20;
  h = float(localIndex / 2) / 9.0;
  float sideX = mod(float(localIndex), 2.0) * 2.0 - 1.0;
  float bend = sin(iTime + instanceHash * 3.14) * 0.3;
  vec2  worldPos = random2(vec2(instance)) * 3.0;
  mat3  rotateY = rotationYMatrix(instanceHash * 3.14);

  vec3 curve = bezier3D(
    vec3(0.0, 0.0, 0.0),
    vec3(0.0, 0.5, 0.0),
    vec3(0.0, cos(bend), sin(bend)),
    h
  );

  vec3 pos = curve;
  pos.x += sideX * mix(0.05, 0.0, h * h);
  pos = rotateY * pos;
  pos += vec3(worldPos.x, 0.0, worldPos.y);

  gl_Position = projectionMatrix * viewMatrix * vec4(pos, 1.0);

  distanceToBladeCenter = sideX;
}