grass-lighting-model-vsh.glsl 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. #define PHONG
  2. varying vec3 vViewPosition;
  3. #include <common>
  4. #include <uv_pars_vertex>
  5. #include <displacementmap_pars_vertex>
  6. #include <envmap_pars_vertex>
  7. #include <color_pars_vertex>
  8. #include <fog_pars_vertex>
  9. #include <normal_pars_vertex>
  10. #include <morphtarget_pars_vertex>
  11. #include <skinning_pars_vertex>
  12. #include <shadowmap_pars_vertex>
  13. #include <logdepthbuf_pars_vertex>
  14. #include <clipping_planes_pars_vertex>
  15. varying vec3 vWorldNormal;
  16. varying vec3 vGrassColour;
  17. varying vec4 vGrassParams;
  18. varying vec3 vNormal2;
  19. varying vec3 vWorldPosition;
  20. uniform vec2 grassSize;
  21. uniform vec4 grassParams;
  22. uniform vec4 grassDraw;
  23. uniform float time;
  24. uniform sampler2D heightmap;
  25. uniform vec4 heightParams;
  26. uniform vec3 playerPos;
  27. uniform mat4 viewMatrixInverse;
  28. attribute float vertIndex;
  29. void main() {
  30. #include <uv_vertex>
  31. #include <color_vertex>
  32. #include <morphcolor_vertex>
  33. #include <beginnormal_vertex>
  34. #include <begin_vertex>
  35. vec3 grassOffset = vec3(position.x, 0.0, position.y);
  36. // Blade world position
  37. vec3 grassBladeWorldPos = (modelMatrix * vec4(grassOffset, 1.0)).xyz;
  38. vec2 heightmapUV = vec2(
  39. remap(grassBladeWorldPos.x, -heightParams.x * 0.5, heightParams.x * 0.5, 0.0, 1.0),
  40. remap(grassBladeWorldPos.z, -heightParams.x * 0.5, heightParams.x * 0.5, 1.0, 0.0));
  41. vec4 heightmapSample = texture2D(heightmap, heightmapUV);
  42. grassBladeWorldPos.y += heightmapSample.x * grassParams.z - grassParams.w;
  43. float heightmapSampleHeight = 1.0;//mix(0.5, 1.0, heightmapSample.y);
  44. vec4 hashVal1 = hash42(vec2(grassBladeWorldPos.x, grassBladeWorldPos.z));
  45. float highLODOut = smoothstep(grassDraw.x * 0.5, grassDraw.x, distance(cameraPosition, grassBladeWorldPos));
  46. // hack lod
  47. float lodFadeIn = smoothstep(grassDraw.x, grassDraw.y, distance(cameraPosition, grassBladeWorldPos));
  48. // Check terrain type, maybe don't allow grass blade
  49. float isSandy = linearstep(-11.0, -14.0, grassBladeWorldPos.y);
  50. float grassAllowedHash = hashVal1.w - isSandy;
  51. float isGrassAllowed = step(0.0, grassAllowedHash);
  52. float randomAngle = hashVal1.x * 2.0 * 3.14159;
  53. float randomShade = remap(hashVal1.y, -1.0, 1.0, 0.5, 1.0);
  54. float randomHeight = remap(hashVal1.z, 0.0, 1.0, 0.75, 1.5) * mix(1.0, 0.0, lodFadeIn) * isGrassAllowed * heightmapSampleHeight;
  55. float randomWidth = (1.0 - isSandy) * heightmapSampleHeight;
  56. float randomLean = remap(hashVal1.w, 0.0, 1.0, 0.1, 0.4);
  57. // HACK
  58. // randomHeight = 1.0;
  59. // randomShade = 1.0;
  60. // randomWidth = 1.0;
  61. vec2 hashGrassColour = hash22(vec2(grassBladeWorldPos.x, grassBladeWorldPos.z));
  62. float leanAnimation = noise12(vec2(time * 0.35) + grassBladeWorldPos.xz * 137.423) * 0.1;
  63. float GRASS_SEGMENTS = grassParams.x;
  64. float GRASS_VERTICES = grassParams.y;
  65. // Figure out vertex id, > GRASS_VERTICES is back side
  66. float vertID = mod(float(vertIndex), GRASS_VERTICES);
  67. // 1 = front, -1 = back
  68. float zSide = -(floor(vertIndex / GRASS_VERTICES) * 2.0 - 1.0);
  69. // 0 = left, 1 = right
  70. float xSide = mod(vertID, 2.0);
  71. float heightPercent = (vertID - xSide) / (GRASS_SEGMENTS * 2.0);
  72. float grassTotalHeight = grassSize.y * randomHeight;
  73. float grassTotalWidthHigh = easeOut(1.0 - heightPercent, 2.0);
  74. float grassTotalWidthLow = 1.0 - heightPercent;
  75. float grassTotalWidth = grassSize.x * mix(grassTotalWidthHigh, grassTotalWidthLow, highLODOut) * randomWidth;
  76. // hack lod
  77. // grassTotalWidth = grassSize.x * randomWidth;
  78. // Shift verts
  79. float x = (xSide - 0.5) * grassTotalWidth;
  80. float y = heightPercent * grassTotalHeight;
  81. float windDir = noise12(grassBladeWorldPos.xz * 0.05 + 0.05 * time);
  82. float windNoiseSample = noise12(grassBladeWorldPos.xz * 0.25 + time * 1.0);
  83. float windLeanAngle = remap(windNoiseSample, -1.0, 1.0, 0.25, 1.0);
  84. windLeanAngle = easeIn(windLeanAngle, 2.0) * 1.25;
  85. vec3 windAxis = vec3(cos(windDir), 0.0, sin(windDir));
  86. windLeanAngle *= heightPercent;
  87. float distToPlayer = distance(grassBladeWorldPos.xz, playerPos.xz);
  88. float playerFalloff = smoothstep(2.5, 1.0, distToPlayer);
  89. float playerLeanAngle = mix(0.0, 0.2, playerFalloff * linearstep(0.5, 0.0, windLeanAngle));
  90. vec3 grassToPlayer = normalize(vec3(playerPos.x, 0.0, playerPos.z) - vec3(grassBladeWorldPos.x, 0.0, grassBladeWorldPos.z));
  91. vec3 playerLeanAxis = vec3(grassToPlayer.z, 0, -grassToPlayer.x);
  92. // hack lod
  93. // randomLean = 0.0;
  94. // windLeanAngle = 0.0;
  95. // leanAnimation = 0.0;
  96. randomLean += leanAnimation;
  97. float easedHeight = mix(easeIn(heightPercent, 2.0), 1.0, highLODOut);
  98. float curveAmount = -randomLean * easedHeight;
  99. float ncurve1 = -randomLean * easedHeight;
  100. vec3 n1 = vec3(0.0, (heightPercent + 0.01), 0.0);
  101. n1 = rotateX(ncurve1) * n1;
  102. float ncurve2 = -randomLean * easedHeight * 0.9;
  103. vec3 n2 = vec3(0.0, (heightPercent + 0.01) * 0.9, 0.0);
  104. n2 = rotateX(ncurve2) * n2;
  105. vec3 ncurve = normalize(n1 - n2);
  106. mat3 grassMat = rotateAxis(playerLeanAxis, playerLeanAngle) * rotateAxis(windAxis, windLeanAngle) * rotateY(randomAngle);
  107. vec3 grassFaceNormal = vec3(0.0, 0.0, 1.0);
  108. grassFaceNormal = grassMat * grassFaceNormal;
  109. grassFaceNormal *= zSide;
  110. vec3 grassVertexNormal = vec3(0.0, -ncurve.z, ncurve.y);
  111. vec3 grassVertexNormal1 = rotateY(PI * 0.3 * zSide) * grassVertexNormal;
  112. vec3 grassVertexNormal2 = rotateY(PI * -0.3 * zSide) * grassVertexNormal;
  113. grassVertexNormal1 = grassMat * grassVertexNormal1;
  114. grassVertexNormal1 *= zSide;
  115. grassVertexNormal2 = grassMat * grassVertexNormal2;
  116. grassVertexNormal2 *= zSide;
  117. vec3 grassVertexPosition = vec3(x, y, 0.0);
  118. grassVertexPosition = rotateX(curveAmount) * grassVertexPosition;
  119. grassVertexPosition = grassMat * grassVertexPosition;
  120. grassVertexPosition += grassOffset;
  121. vec3 b1 = GAMMA_TO_LINEAR(vec3(0.02, 0.075, 0.01));
  122. vec3 b2 = GAMMA_TO_LINEAR(vec3(0.025, 0.1, 0.01));
  123. vec3 t1 = GAMMA_TO_LINEAR(vec3(0.25, 0.5, 0.15));
  124. vec3 t2 = GAMMA_TO_LINEAR(vec3(0.3, 0.6, 0.2));
  125. vec3 baseColour = mix(b1, b2, hashGrassColour.x);
  126. vec3 tipColour = mix(t1, t2, hashGrassColour.y);
  127. vec3 highLODColour = mix(baseColour, tipColour, easeIn(heightPercent, 4.0)) * randomShade;
  128. vec3 lowLODColour = mix(b1, t1, heightPercent);
  129. vGrassColour = mix(highLODColour, lowLODColour, highLODOut);
  130. vGrassParams = vec4(heightPercent, grassBladeWorldPos.y, highLODOut, xSide);
  131. const float SKY_RATIO = 0.25;
  132. // TODO: Grab terrain normal
  133. vec3 UP = vec3(0.0, 1.0, 0.0);
  134. // float skyFadeIn = smoothstep(grassDraw.x * 0.5, grassDraw.x, distance(cameraPosition, grassBladeWorldPos)) * SKY_RATIO;
  135. float skyFadeIn = (1.0 - highLODOut) * SKY_RATIO;
  136. vec3 normal1 = normalize(mix(UP, grassVertexNormal1, skyFadeIn));
  137. vec3 normal2 = normalize(mix(UP, grassVertexNormal2, skyFadeIn));
  138. transformed = grassVertexPosition;
  139. transformed.y += grassBladeWorldPos.y;
  140. vec3 cameraWorldLeft = (viewMatrixInverse * vec4(-1.0, 0.0, 0.0, 0.0)).xyz;
  141. vec3 viewDir = normalize(cameraPosition - grassBladeWorldPos);
  142. vec3 viewDirXZ = normalize(vec3(viewDir.x, 0.0, viewDir.z));
  143. vec3 grassFaceNormalXZ = normalize(vec3(grassFaceNormal.x, 0.0, grassFaceNormal.z));
  144. float viewDotNormal = saturate(dot(grassFaceNormal, viewDirXZ));
  145. float viewSpaceThickenFactor = easeOut(1.0 - viewDotNormal, 4.0) * smoothstep(0.0, 0.2, viewDotNormal);
  146. objectNormal = grassVertexNormal1;
  147. #include <morphnormal_vertex>
  148. #include <skinbase_vertex>
  149. #include <skinnormal_vertex>
  150. #include <defaultnormal_vertex>
  151. #include <normal_vertex>
  152. vNormal = normalize(normalMatrix * normal1);
  153. vNormal2 = normalize(normalMatrix * normal2);
  154. #include <morphtarget_vertex>
  155. #include <skinning_vertex>
  156. #include <displacementmap_vertex>
  157. // #include <project_vertex>
  158. vec4 mvPosition = vec4( transformed, 1.0 );
  159. #ifdef USE_INSTANCING
  160. mvPosition = instanceMatrix * mvPosition;
  161. #endif
  162. mvPosition = modelViewMatrix * mvPosition;
  163. // HACK
  164. mvPosition.x += viewSpaceThickenFactor * (xSide - 0.5) * grassTotalWidth * 0.5 * zSide;
  165. gl_Position = projectionMatrix * mvPosition;
  166. #include <logdepthbuf_vertex>
  167. #include <clipping_planes_vertex>
  168. vViewPosition = - mvPosition.xyz;
  169. #include <worldpos_vertex>
  170. #include <envmap_vertex>
  171. #include <shadowmap_vertex>
  172. #include <fog_vertex>
  173. vWorldPosition = worldPosition.xyz;
  174. }