跳到主要内容
← Grass

Grass

Grass - Wind

shader-learning 自学第 6 课:Grass - Wind

实时渲染 · 网格 GLSL

第 6 课:Grass - Wind

实现

uniform float iTime;

attribute int index;

out float vH;
out float vX;

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)
    );
}

mat3 rotationXMatrix(float angle) {
    float cosAngle = cos(angle);
    float sinAngle = sin(angle);
    return mat3(
      1.0, 0, 0,
      0, cosAngle, sinAngle,
      0, -sinAngle, cosAngle
    );
}

void main() {
  int   instance = index / 40;
  float instanceHash = random(float(instance));
  int   localIndex = index % 20;
  float 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.2;
  mat3  rotateY = rotationYMatrix(instanceHash * 3.14);
  vec2  worldPos = random2(vec2(instance)) * 3.0;

  float windStrength = sin(worldPos.y * 0.5 + iTime * 2.0);
  mat3 rotateX = rotationXMatrix(windStrength * h);
  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 = rotateX * pos;
  pos += vec3(worldPos.x, 0.0, worldPos.y);

  vH = h;
  vX = sideX;

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