当前位置:   article > 正文

Cesium自定义shader材质实现逼真水面,支持uniforms属性实时修改_cesium 水面

cesium 水面

水的shader代码参考的是Shader - Shadertoy BETA

本文主要解决在cesium的shader中如何实时修改时间变量iTime,从而实现材质的动态变化。

MaterialAppearance.fragmentShaderSource与vertexShaderSource可以自定义shader材质,但是不支持uniforms传参,于是加入fabric,在fabric.source中可以获取uniforms中的属性,然后我直接在fabric中处理片元的着色,而fragmentShaderSource中只是直接调用fabric的结果。

源码地址:https://gitee.com/changjiuxiong/Cesium-1.62Test/blob/master/Apps/shaderMaterial_uniforms.html

仓库地址:

https://gitee.com/changjiuxiong/Cesium-1.62Test

版权所有,请勿用于商业用途。

附源码

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <!-- Use correct character set. -->
  5. <meta charset="utf-8">
  6. <!-- Tell IE to use the latest, best version. -->
  7. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  8. <!-- Make the application on mobile take up the full browser screen and disable user scaling. -->
  9. <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
  10. <title>Hello World!</title>
  11. <script src="../Build/Cesium/Cesium.js"></script>
  12. <style>
  13. @import url(../Build/Cesium/Widgets/widgets.css);
  14. html, body, #cesiumContainer {
  15. width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
  16. }
  17. </style>
  18. </head>
  19. <body>
  20. <div id="cesiumContainer"></div>
  21. <script>
  22. // Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJmNjJjMzY0OS1hZGQxLTRiZmYtYWYwNS03NmIyM2MwMDgwZDAiLCJpZCI6MTIzMTgsInNjb3BlcyI6WyJhc3IiLCJnYyJdLCJpYXQiOjE1NjA4NDQ3Mjd9.OLTL_rs2gAi2R9zoztBHcJPDHnVl2Q7OZxRtZhoCeZE';
  23. var viewer = new Cesium.Viewer('cesiumContainer');
  24. var box = new Cesium.BoxGeometry({
  25. vertexFormat : Cesium.VertexFormat.POSITION_NORMAL_AND_ST,
  26. maximum : new Cesium.Cartesian3(250000.0, 250000.0, 250000.0),
  27. minimum : new Cesium.Cartesian3(-250000.0, -250000.0, -250000.0)
  28. });
  29. var geometry = Cesium.BoxGeometry.createGeometry(box);
  30. let inst = new Cesium.GeometryInstance({
  31. geometry: geometry
  32. });
  33. // 自定义材质
  34. let aper = new Cesium.MaterialAppearance({
  35. material: new Cesium.Material({
  36. fabric: {
  37. uniforms: {
  38. iTime: 0,
  39. },
  40. source:`
  41. const int NUM_STEPS = 8;
  42. const float PI = 3.141592;
  43. const float EPSILON = 1e-3;
  44. //#define EPSILON_NRM (0.1 / iResolution.x)
  45. #define EPSILON_NRM (0.1 / 200.0)
  46. // sea
  47. const int ITER_GEOMETRY = 3;
  48. const int ITER_FRAGMENT = 5;
  49. const float SEA_HEIGHT = 0.6;
  50. const float SEA_CHOPPY = 4.0;
  51. const float SEA_SPEED = 1.8;
  52. const float SEA_FREQ = 0.16;
  53. const vec3 SEA_BASE = vec3(0.1,0.19,0.22);
  54. const vec3 SEA_WATER_COLOR = vec3(0.8,0.9,0.6);
  55. //#define SEA_TIME (1.0 + iTime * SEA_SPEED)
  56. const mat2 octave_m = mat2(1.6,1.2,-1.2,1.6);
  57. // math
  58. mat3 fromEuler(vec3 ang) {
  59. vec2 a1 = vec2(sin(ang.x),cos(ang.x));
  60. vec2 a2 = vec2(sin(ang.y),cos(ang.y));
  61. vec2 a3 = vec2(sin(ang.z),cos(ang.z));
  62. mat3 m;
  63. m[0] = vec3(a1.y*a3.y+a1.x*a2.x*a3.x,a1.y*a2.x*a3.x+a3.y*a1.x,-a2.y*a3.x);
  64. m[1] = vec3(-a2.y*a1.x,a1.y*a2.y,a2.x);
  65. m[2] = vec3(a3.y*a1.x*a2.x+a1.y*a3.x,a1.x*a3.x-a1.y*a3.y*a2.x,a2.y*a3.y);
  66. return m;
  67. }
  68. float hash( vec2 p ) {
  69. float h = dot(p,vec2(127.1,311.7));
  70. return fract(sin(h)*43758.5453123);
  71. }
  72. float noise( in vec2 p ) {
  73. vec2 i = floor( p );
  74. vec2 f = fract( p );
  75. vec2 u = f*f*(3.0-2.0*f);
  76. return -1.0+2.0*mix( mix( hash( i + vec2(0.0,0.0) ),
  77. hash( i + vec2(1.0,0.0) ), u.x),
  78. mix( hash( i + vec2(0.0,1.0) ),
  79. hash( i + vec2(1.0,1.0) ), u.x), u.y);
  80. }
  81. // lighting
  82. float diffuse(vec3 n,vec3 l,float p) {
  83. return pow(dot(n,l) * 0.4 + 0.6,p);
  84. }
  85. float specular(vec3 n,vec3 l,vec3 e,float s) {
  86. float nrm = (s + 8.0) / (PI * 8.0);
  87. return pow(max(dot(reflect(e,n),l),0.0),s) * nrm;
  88. }
  89. // sky
  90. vec3 getSkyColor(vec3 e) {
  91. e.y = max(e.y,0.0);
  92. return vec3(pow(1.0-e.y,2.0), 1.0-e.y, 0.6+(1.0-e.y)*0.4);
  93. }
  94. // sea
  95. float sea_octave(vec2 uv, float choppy) {
  96. uv += noise(uv);
  97. vec2 wv = 1.0-abs(sin(uv));
  98. vec2 swv = abs(cos(uv));
  99. wv = mix(wv,swv,wv);
  100. return pow(1.0-pow(wv.x * wv.y,0.65),choppy);
  101. }
  102. float map(vec3 p) {
  103. float freq = SEA_FREQ;
  104. float amp = SEA_HEIGHT;
  105. float choppy = SEA_CHOPPY;
  106. vec2 uv = p.xz; uv.x *= 0.75;
  107. float d, h = 0.0;
  108. float SEA_TIME = 1.0 + iTime * SEA_SPEED;
  109. for(int i = 0; i < ITER_GEOMETRY; i++) {
  110. d = sea_octave((uv+SEA_TIME)*freq,choppy);
  111. d += sea_octave((uv-SEA_TIME)*freq,choppy);
  112. h += d * amp;
  113. uv *= octave_m; freq *= 1.9; amp *= 0.22;
  114. choppy = mix(choppy,1.0,0.2);
  115. }
  116. return p.y - h;
  117. }
  118. float map_detailed(vec3 p) {
  119. float freq = SEA_FREQ;
  120. float amp = SEA_HEIGHT;
  121. float choppy = SEA_CHOPPY;
  122. vec2 uv = p.xz; uv.x *= 0.75;
  123. float SEA_TIME = 1.0 + iTime * SEA_SPEED;
  124. float d, h = 0.0;
  125. for(int i = 0; i < ITER_FRAGMENT; i++) {
  126. d = sea_octave((uv+SEA_TIME)*freq,choppy);
  127. d += sea_octave((uv-SEA_TIME)*freq,choppy);
  128. h += d * amp;
  129. uv *= octave_m; freq *= 1.9; amp *= 0.22;
  130. choppy = mix(choppy,1.0,0.2);
  131. }
  132. return p.y - h;
  133. }
  134. vec3 getSeaColor(vec3 p, vec3 n, vec3 l, vec3 eye, vec3 dist) {
  135. float fresnel = clamp(1.0 - dot(n,-eye), 0.0, 1.0);
  136. fresnel = pow(fresnel,3.0) * 0.65;
  137. vec3 reflected = getSkyColor(reflect(eye,n));
  138. vec3 refracted = SEA_BASE + diffuse(n,l,80.0) * SEA_WATER_COLOR * 0.12;
  139. vec3 color = mix(refracted,reflected,fresnel);
  140. float atten = max(1.0 - dot(dist,dist) * 0.001, 0.0);
  141. color += SEA_WATER_COLOR * (p.y - SEA_HEIGHT) * 0.18 * atten;
  142. color += vec3(specular(n,l,eye,60.0));
  143. return color;
  144. }
  145. // tracing
  146. vec3 getNormal(vec3 p, float eps) {
  147. vec3 n;
  148. n.y = map_detailed(p);
  149. n.x = map_detailed(vec3(p.x+eps,p.y,p.z)) - n.y;
  150. n.z = map_detailed(vec3(p.x,p.y,p.z+eps)) - n.y;
  151. n.y = eps;
  152. return normalize(n);
  153. }
  154. float heightMapTracing(vec3 ori, vec3 dir, out vec3 p) {
  155. float tm = 0.0;
  156. float tx = 1000.0;
  157. float hx = map(ori + dir * tx);
  158. if(hx > 0.0) return tx;
  159. float hm = map(ori + dir * tm);
  160. float tmid = 0.0;
  161. for(int i = 0; i < NUM_STEPS; i++) {
  162. tmid = mix(tm,tx, hm/(hm-hx));
  163. p = ori + dir * tmid;
  164. float hmid = map(p);
  165. if(hmid < 0.0) {
  166. tx = tmid;
  167. hx = hmid;
  168. } else {
  169. tm = tmid;
  170. hm = hmid;
  171. }
  172. }
  173. return tmid;
  174. }
  175. vec4 czm_getMaterial(vec2 vUv)
  176. {
  177. vec2 uv = vUv;
  178. uv = vUv * 2.0 - 1.0;
  179. float time = iTime * 0.3 + 0.0*0.01;
  180. // ray
  181. vec3 ang = vec3(0, 1.2, 0.0);
  182. vec3 ori = vec3(0.0,3.5,0);
  183. vec3 dir = normalize(vec3(uv.xy,-2.0)); dir.z += length(uv) * 0.15;
  184. dir = normalize(dir) * fromEuler(ang);
  185. // tracing
  186. vec3 p;
  187. heightMapTracing(ori,dir,p);
  188. vec3 dist = p - ori;
  189. vec3 n = getNormal(p, dot(dist,dist) * EPSILON_NRM);
  190. vec3 light = normalize(vec3(0.0,1.0,0.8));
  191. // color
  192. vec3 color = mix(
  193. getSkyColor(dir),
  194. getSeaColor(p,n,light,dir,dist),
  195. pow(smoothstep(0.0,-0.05,dir.y),0.3));
  196. return vec4( pow(color,vec3(0.75)), 1.0 );
  197. }
  198. `,
  199. }
  200. }),
  201. translucent: true,
  202. vertexShaderSource: `
  203. attribute vec3 position3DHigh;
  204. attribute vec3 position3DLow;
  205. attribute float batchId;
  206. attribute vec2 st;
  207. attribute vec3 normal;
  208. varying vec2 v_st;
  209. varying vec3 v_positionEC;
  210. varying vec3 v_normalEC;
  211. void main() {
  212. v_st = st;
  213. vec4 p = czm_computePosition();
  214. v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates
  215. v_normalEC = czm_normal * normal; // normal in eye coordinates
  216. gl_Position = czm_modelViewProjectionRelativeToEye * p;
  217. }
  218. `,
  219. fragmentShaderSource: `
  220. varying vec2 v_st;
  221. varying vec3 v_positionEC;
  222. varying vec3 v_normalEC;
  223. void main() {
  224. vec3 positionToEyeEC = -v_positionEC;
  225. vec3 normalEC = normalize(v_normalEC);
  226. czm_materialInput materialInput;
  227. materialInput.normalEC = normalEC;
  228. materialInput.positionToEyeEC = positionToEyeEC;
  229. materialInput.st = v_st;
  230. vec4 color = czm_getMaterial(v_st);
  231. gl_FragColor = color;
  232. }
  233. `,
  234. });
  235. let modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
  236. Cesium.Cartesian3.fromDegrees(110, 40, 10)
  237. );
  238. viewer.scene.primitives.add(new Cesium.Primitive({
  239. geometryInstances: inst,
  240. appearance: aper,
  241. modelMatrix: modelMatrix,
  242. }));
  243. viewer.camera.flyToBoundingSphere(new Cesium.BoundingSphere(
  244. Cesium.Cartesian3.fromDegrees(110, 40, 10), 950000,
  245. ),{
  246. duration: 0.1,
  247. });
  248. function renderLoop(timestamp){
  249. aper.material.uniforms.iTime = timestamp/1000;
  250. requestAnimationFrame(renderLoop);
  251. }
  252. renderLoop();
  253. </script>
  254. </body>
  255. </html>

新版本Cesium 1.105,默认使用GLSL3.0语法,稍微修改vertexShaderSource和fragmentShaderSource,注意片元默认输出变量为out_FragColor

  1. vertexShaderSource: `
  2. in vec3 position3DHigh;
  3. in vec3 position3DLow;
  4. in float batchId;
  5. in vec2 st;
  6. in vec3 normal;
  7. out vec2 v_st;
  8. out vec3 v_positionEC;
  9. out vec3 v_normalEC;
  10. void main() {
  11. v_st = st;
  12. vec4 p = czm_computePosition();
  13. v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates
  14. v_normalEC = czm_normal * normal; // normal in eye coordinates
  15. gl_Position = czm_modelViewProjectionRelativeToEye * p;
  16. }
  17. `,
  18. fragmentShaderSource: `
  19. in vec2 v_st;
  20. in vec3 v_positionEC;
  21. in vec3 v_normalEC;
  22. void main() {
  23. vec3 positionToEyeEC = -v_positionEC;
  24. vec3 normalEC = normalize(v_normalEC);
  25. czm_materialInput materialInput;
  26. materialInput.normalEC = normalEC;
  27. materialInput.positionToEyeEC = positionToEyeEC;
  28. materialInput.st = v_st;
  29. vec4 color = czm_getMaterial(v_st);
  30. out_FragColor = color;
  31. }
  32. `,

然后新版中Primitive加上asynchronous: false,不然报错

  1. viewer.scene.primitives.add(new Cesium.Primitive({
  2. geometryInstances: inst,
  3. appearance: aper,
  4. asynchronous: false,
  5. modelMatrix: modelMatrix,
  6. }));

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/99783
推荐阅读
相关标签
  

闽ICP备14008679号