0


《Learn Three.js》学习(4) 材质

前言:

材质为scene中物体的皮肤,有着不同的特性和视觉效果。

材质的共有属性:

基础属性:

融合属性:

融合决定了我们渲染的颜色如何与它们后面的颜色交互

高级属性:

与WebGL内部有关

简单材质:

MeshBasicMaterial

创建材质:可以使用构造函数一次性传完所有参数;或先创建一个实例,再对实例的属性数据赋值

  1. var meshMaterial = new THREE.MeshBasicMaterial({color: 0x7777ff});

MeshDepthMaterial

不是由光照或者某个材质决定的,而是由相机距离决定的。不需要参数

wireframe 是否显示线框

wireframe 指定线框线宽度(该属性只对THRER.CanvasRender有效)

(方块再near和far之间的距离渲染)

  1. scene.overrideMaterial = new THREE.MeshLambertMaterial();

使用scene.overrideMaterial属性,保证场景中所有物体都使用该材质,而无需再每个THREE.Mesh对象上显示声明。

联合材质
  1. // 创建一个深度材质,这种材质可以用来渲染对象的深度信息,通常用于特效或者后期处理。
  2. var cubeMaterial = new THREE.MeshDepthMaterial();
  3. // 创建一个基本颜色材质,设置颜色为绿色(0x00ff00),并且使其透明,透明度为0.6。
  4. // blending 设置为 THREE.MultiplyBlending,这是一种混合模式,可以让颜色之间进行乘法混合,常用于创建透明或者半透明效果。
  5. var colorMaterial = new THREE.MeshBasicMaterial({
  6. color: 0x00ff00, // 绿色
  7. transparent: true, // 设置材质为透明
  8. opacity: 0.6, // 设置透明度为0.6
  9. blending: THREE.MultiplyBlending // 设置混合模式
  10. });
  11. // 使用 SceneUtils 的 createMultiMaterialObject 方法创建一个多材质对象。
  12. // 这个方法接受两个参数:几何体(cubeGeometry)和材质数组([cubeMaterial, colorMaterial])。
  13. // 这样,同一个几何体可以被多个材质覆盖,这里是一个深度材质和一个基本颜色材质。
  14. var cube = new THREE.SceneUtils.createMultiMaterialObject(cubeGeometry, [cubeMaterial, colorMaterial]);
  15. // 调整第二个材质(颜色材质)的缩放比例,使其稍微小于1,这样可以创建一种视觉效果,
  16. // 使得颜色材质看起来像是覆盖在深度材质之上的一层半透明膜。
  17. cube.children[1].scale.set(0.99, 0.99, 0.99);
  18. // 将创建的多材质立方体添加到场景中。
  19. scene.add(cube);

THREE.MultiplyBlending会将前景色和背景色相乘。

MeshNormalMaterial

每一个免得颜色是由从该面向外指的法向量计算得到

  1. for (var f = 0, fl = sphere.geometry.faces.length; f < fl; f++) {
  2. var face = sphere.geometry.faces[f];
  3. var centroid = new THREE.Vector3(0, 0, 0);
  4. centroid.add(sphere.geometry.vertices[face.a]);
  5. centroid.add(sphere.geometry.vertices[face.b]);
  6. centroid.add(sphere.geometry.vertices[face.c]);
  7. centroid.divideScalar(3);
  8. var arrow = new THREE.ArrowHelper(
  9. face.normal,
  10. centroid,
  11. 2,
  12. 0x3333FF,
  13. 0.5,
  14. 0.5);
  15. sphere.add(arrow);
  16. }

对于每个THREE.Face3的对象来说,把构成该面的顶点相加再除以3来计算质心

单几何体上使用多种材质

  1. // 多材质联合
  2. var group = new THREE.Mesh();
  3. var mats = [];
  4. mats.push(new THREE.MeshBasicMaterial({color: 0x009e60}));
  5. mats.push(new THREE.MeshBasicMaterial({color: 0x019e60}));
  6. mats.push(new THREE.MeshBasicMaterial({color: 0x029e60}));
  7. mats.push(new THREE.MeshBasicMaterial({color: 0x039e60}));
  8. mats.push(new THREE.MeshBasicMaterial({color: 0x049e60}));
  9. mats.push(new THREE.MeshBasicMaterial({color: 0x059e60}));
  10. for (var i = 0; i < 6; i++) {
  11. for (var j = 0; j < 6; j++) {
  12. for (var k = 0; k < 6; k++) {
  13. var cubeGeom = new THREE.BoxGeometry(2.9, 2.9, 2.9);
  14. var cube = new THREE.Mesh(cubeGeom, mats);
  15. cube.position.set(i * 3 - 3, j * 3 - 3, k * 3 - 3);
  16. group.add(cube);
  17. }
  18. }
  19. }

高级材质:

THREE.MeshLambertMaterial

可以用来创建暗淡的并不光亮的表面,材质易用,对光源有反应,支持线框绘制属性

emissive(自发光)该属性不使其成为光源,而是不受光源影响,default color Black

看起来较为暗淡 。

THREE.MeshPhongMaterial

Phong(冯氏(明暗处理算法的一种名称))

可以创建一种光亮材质,可以模拟塑料质感和金属质感

emissive的作用影响geometry的color属性

THREE.MeshStandardMaterial

更加正确的物理计算物体表面和光源的互动,更好表现塑料和金属材质

THREE.MeshPhysicalMaterial

提供更多对反光度的控制

THREE.ShaderMaterial

可以自定义着色器,直接再webgl环境下运行,将three.js中js像素转换为屏幕上的像素,且可以明确覆盖或修改或指定Three.js中的默认值

前两个即webgl中渲染基础,vertexShader顶点着色器,fragmentShader片元着色器

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Example 04.08 - Shader material - http://glsl.heroku.com/</title>
  5. <script type="text/javascript" src="../libs/three.js"></script>
  6. <script type="text/javascript" src="../libs/stats.js"></script>
  7. <script type="text/javascript" src="../libs/dat.gui.js"></script>
  8. <style>
  9. body {
  10. /* set margin to 0 and overflow to hidden, to go fullscreen */
  11. margin: 0;
  12. overflow: hidden;
  13. }
  14. </style>
  15. </head>
  16. <body>
  17. <script id="vertex-shader" type="x-shader/x-vertex">
  18. uniform float time;
  19. varying vec2 vUv;
  20. void main()
  21. {
  22. vec3 posChanged = position;
  23. posChanged.x = posChanged.x*(abs(sin(time*1.0)));
  24. posChanged.y = posChanged.y*(abs(cos(time*1.0)));
  25. posChanged.z = posChanged.z*(abs(sin(time*1.0)));
  26. //gl_Position = projectionMatrix * modelViewMatrix * vec4(position*(abs(sin(time)/2.0)+0.5),1.0);
  27. gl_Position = projectionMatrix * modelViewMatrix * vec4(posChanged,1.0);
  28. }
  29. </script>
  30. <script id="fragment-shader-1" type="x-shader/x-fragment">
  31. precision highp float;
  32. uniform float time;
  33. uniform float alpha;
  34. uniform vec2 resolution;
  35. varying vec2 vUv;
  36. void main2(void)
  37. {
  38. vec2 position = vUv;
  39. float red = 1.0;
  40. float green = 0.25 + sin(time) * 0.25;
  41. float blue = 0.0;
  42. vec3 rgb = vec3(red, green, blue);
  43. vec4 color = vec4(rgb, alpha);
  44. gl_FragColor = color;
  45. }
  46. #define PI 3.14159
  47. #define TWO_PI (PI*2.0)
  48. #define N 68.5
  49. void main(void)
  50. {
  51. vec2 center = (gl_FragCoord.xy);
  52. center.x=-10.12*sin(time/200.0);
  53. center.y=-10.12*cos(time/200.0);
  54. vec2 v = (gl_FragCoord.xy - resolution/20.0) / min(resolution.y,resolution.x) * 15.0;
  55. v.x=v.x-10.0;
  56. v.y=v.y-200.0;
  57. float col = 0.0;
  58. for(float i = 0.0; i < N; i++)
  59. {
  60. float a = i * (TWO_PI/N) * 61.95;
  61. col += cos(TWO_PI*(v.y * cos(a) + v.x * sin(a) + sin(time*0.004)*100.0 ));
  62. }
  63. col /= 5.0;
  64. gl_FragColor = vec4(col*1.0, -col*1.0,-col*4.0, 1.0);
  65. }
  66. </script>
  67. <script id="fragment-shader-2" type="x-shader/x-fragment">
  68. // from http://glsl.heroku.com/e#7906.0
  69. uniform float time;
  70. uniform vec2 resolution;
  71. // 2013-03-30 by @hintz
  72. #define CGFloat float
  73. #define M_PI 3.14159265359
  74. vec3 hsvtorgb(float h, float s, float v)
  75. {
  76. float c = v * s;
  77. h = mod((h * 6.0), 6.0);
  78. float x = c * (1.0 - abs(mod(h, 2.0) - 1.0));
  79. vec3 color;
  80. if (0.0 <= h && h < 1.0)
  81. {
  82. color = vec3(c, x, 0.0);
  83. }
  84. else if (1.0 <= h && h < 2.0)
  85. {
  86. color = vec3(x, c, 0.0);
  87. }
  88. else if (2.0 <= h && h < 3.0)
  89. {
  90. color = vec3(0.0, c, x);
  91. }
  92. else if (3.0 <= h && h < 4.0)
  93. {
  94. color = vec3(0.0, x, c);
  95. }
  96. else if (4.0 <= h && h < 5.0)
  97. {
  98. color = vec3(x, 0.0, c);
  99. }
  100. else if (5.0 <= h && h < 6.0)
  101. {
  102. color = vec3(c, 0.0, x);
  103. }
  104. else
  105. {
  106. color = vec3(0.0);
  107. }
  108. color += v - c;
  109. return color;
  110. }
  111. void main(void)
  112. {
  113. vec2 position = (gl_FragCoord.xy - 0.5 * resolution) / resolution.y;
  114. float x = position.x;
  115. float y = position.y;
  116. CGFloat a = atan(x, y);
  117. CGFloat d = sqrt(x*x+y*y);
  118. CGFloat d0 = 0.5*(sin(d-time)+1.5)*d;
  119. CGFloat d1 = 5.0;
  120. CGFloat u = mod(a*d1+sin(d*10.0+time), M_PI*2.0)/M_PI*0.5 - 0.5;
  121. CGFloat v = mod(pow(d0*4.0, 0.75),1.0) - 0.5;
  122. CGFloat dd = sqrt(u*u+v*v);
  123. CGFloat aa = atan(u, v);
  124. CGFloat uu = mod(aa*3.0+3.0*cos(dd*30.0-time), M_PI*2.0)/M_PI*0.5 - 0.5;
  125. // CGFloat vv = mod(dd*4.0,1.0) - 0.5;
  126. CGFloat d2 = sqrt(uu*uu+v*v)*1.5;
  127. gl_FragColor = vec4( hsvtorgb(dd+time*0.5/d1, sin(dd*time), d2), 1.0 );
  128. }
  129. </script>
  130. <script id="fragment-shader-3" type="x-shader/x-fragment">
  131. uniform vec2 resolution;
  132. uniform float time;
  133. vec2 rand(vec2 pos)
  134. {
  135. return fract( 0.00005 * (pow(pos+2.0, pos.yx + 1.0) * 22222.0));
  136. }
  137. vec2 rand2(vec2 pos)
  138. {
  139. return rand(rand(pos));
  140. }
  141. float softnoise(vec2 pos, float scale)
  142. {
  143. vec2 smplpos = pos * scale;
  144. float c0 = rand2((floor(smplpos) + vec2(0.0, 0.0)) / scale).x;
  145. float c1 = rand2((floor(smplpos) + vec2(1.0, 0.0)) / scale).x;
  146. float c2 = rand2((floor(smplpos) + vec2(0.0, 1.0)) / scale).x;
  147. float c3 = rand2((floor(smplpos) + vec2(1.0, 1.0)) / scale).x;
  148. vec2 a = fract(smplpos);
  149. return mix(
  150. mix(c0, c1, smoothstep(0.0, 1.0, a.x)),
  151. mix(c2, c3, smoothstep(0.0, 1.0, a.x)),
  152. smoothstep(0.0, 1.0, a.y));
  153. }
  154. void main(void)
  155. {
  156. vec2 pos = gl_FragCoord.xy / resolution.y;
  157. pos.x += time * 0.1;
  158. float color = 0.0;
  159. float s = 1.0;
  160. for(int i = 0; i < 8; i++)
  161. {
  162. color += softnoise(pos+vec2(i)*0.02, s * 4.0) / s / 2.0;
  163. s *= 2.0;
  164. }
  165. gl_FragColor = vec4(color);
  166. }
  167. </script>
  168. <script id="fragment-shader-4" type="x-shader/x-fragment">
  169. uniform float time;
  170. uniform vec2 resolution;
  171. vec2 rand(vec2 pos)
  172. {
  173. return
  174. fract(
  175. (
  176. pow(
  177. pos+2.0,
  178. pos.yx+2.0
  179. )*555555.0
  180. )
  181. );
  182. }
  183. vec2 rand2(vec2 pos)
  184. {
  185. return rand(rand(pos));
  186. }
  187. float softnoise(vec2 pos, float scale) {
  188. vec2 smplpos = pos * scale;
  189. float c0 = rand2((floor(smplpos) + vec2(0.0, 0.0)) / scale).x;
  190. float c1 = rand2((floor(smplpos) + vec2(1.0, 0.0)) / scale).x;
  191. float c2 = rand2((floor(smplpos) + vec2(0.0, 1.0)) / scale).x;
  192. float c3 = rand2((floor(smplpos) + vec2(1.0, 1.0)) / scale).x;
  193. vec2 a = fract(smplpos);
  194. return mix(mix(c0, c1, smoothstep(0.0, 1.0, a.x)),
  195. mix(c2, c3, smoothstep(0.0, 1.0, a.x)),
  196. smoothstep(0.0, 1.0, a.x));
  197. }
  198. void main( void ) {
  199. vec2 pos = gl_FragCoord.xy / resolution.y - time * 0.4;
  200. float color = 0.0;
  201. float s = 1.0;
  202. for (int i = 0; i < 6; ++i) {
  203. color += softnoise(pos + vec2(0.01 * float(i)), s * 4.0) / s / 2.0;
  204. s *= 2.0;
  205. }
  206. gl_FragColor = vec4(color,mix(color,cos(color),sin(color)),color,1);
  207. }
  208. </script>
  209. <script id="fragment-shader-5" type="x-shader/x-fragment">
  210. uniform float time;
  211. uniform vec2 resolution;
  212. // tie nd die by Snoep Games.
  213. void main( void ) {
  214. vec3 color = vec3(1.0, 0., 0.);
  215. vec2 pos = (( 1.4 * gl_FragCoord.xy - resolution.xy) / resolution.xx)*1.5;
  216. float r=sqrt(pos.x*pos.x+pos.y*pos.y)/15.0;
  217. float size1=2.0*cos(time/60.0);
  218. float size2=2.5*sin(time/12.1);
  219. float rot1=13.00; //82.0+16.0*sin(time/4.0);
  220. float rot2=-50.00; //82.0+16.0*sin(time/8.0);
  221. float t=sin(time);
  222. float a = (60.0)*sin(rot1*atan(pos.x-size1*pos.y/r,pos.y+size1*pos.x/r)+time);
  223. a += 200.0*acos(pos.x*2.0+cos(time/2.0))+asin(pos.y*5.0+sin(time/2.0));
  224. a=a*(r/50.0);
  225. a=200.0*sin(a*5.0)*(r/30.0);
  226. if(a>5.0) a=a/200.0;
  227. if(a<0.5) a=a*22.5;
  228. gl_FragColor = vec4( cos(a/20.0),a*cos(a/200.0),sin(a/8.0), 1.0 );
  229. }
  230. </script>
  231. <script id="fragment-shader-6" type="x-shader/x-fragment">
  232. uniform float time;
  233. uniform vec2 resolution;
  234. void main( void )
  235. {
  236. vec2 uPos = ( gl_FragCoord.xy / resolution.xy );//normalize wrt y axis
  237. //suPos -= vec2((resolution.x/resolution.y)/2.0, 0.0);//shift origin to center
  238. uPos.x -= 1.0;
  239. uPos.y -= 0.5;
  240. vec3 color = vec3(0.0);
  241. float vertColor = 2.0;
  242. for( float i = 0.0; i < 15.0; ++i )
  243. {
  244. float t = time * (0.9);
  245. uPos.y += sin( uPos.x*i + t+i/2.0 ) * 0.1;
  246. float fTemp = abs(1.0 / uPos.y / 100.0);
  247. vertColor += fTemp;
  248. color += vec3( fTemp*(10.0-i)/10.0, fTemp*i/10.0, pow(fTemp,1.5)*1.5 );
  249. }
  250. vec4 color_final = vec4(color, 1.0);
  251. gl_FragColor = color_final;
  252. }
  253. </script>
  254. <div id="Stats-output">
  255. </div>
  256. <!-- Div which will hold the Output -->
  257. <div id="WebGL-output">
  258. </div>
  259. <!-- Javascript code that runs our Three.js examples -->
  260. <script type="text/javascript">
  261. // once everything is loaded, we run our Three.js stuff.
  262. function init() {
  263. var stats = initStats();
  264. // create a scene, that will hold all our elements such as objects, cameras and lights.
  265. var scene = new THREE.Scene();
  266. // create a camera, which defines where we're looking at.
  267. var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
  268. // create a render and set the size
  269. var renderer = new THREE.WebGLRenderer();
  270. renderer.setClearColor(new THREE.Color(0x000000, 1.0));
  271. renderer.setSize(window.innerWidth, window.innerHeight);
  272. renderer.shadowMapEnabled = true;
  273. var cubeGeometry = new THREE.BoxGeometry(20, 20, 20);
  274. var meshMaterial1 = createMaterial("vertex-shader", "fragment-shader-1");
  275. var meshMaterial2 = createMaterial("vertex-shader", "fragment-shader-2");
  276. var meshMaterial3 = createMaterial("vertex-shader", "fragment-shader-3");
  277. var meshMaterial4 = createMaterial("vertex-shader", "fragment-shader-4");
  278. var meshMaterial5 = createMaterial("vertex-shader", "fragment-shader-5");
  279. var meshMaterial6 = createMaterial("vertex-shader", "fragment-shader-6");
  280. var material = new THREE.MeshFaceMaterial(
  281. [meshMaterial1,
  282. meshMaterial2,
  283. meshMaterial3,
  284. meshMaterial4,
  285. meshMaterial5,
  286. meshMaterial6]);
  287. // var material = new THREE.MeshFaceMaterial([meshMaterial2, meshMaterial2, meshMaterial1, meshMaterial1, meshMaterial1, meshMaterial1]);
  288. var cube = new THREE.Mesh(cubeGeometry, material);
  289. // add the sphere to the scene
  290. scene.add(cube);
  291. // position and point the camera to the center of the scene
  292. camera.position.x = 30;
  293. camera.position.y = 30;
  294. camera.position.z = 30;
  295. camera.lookAt(new THREE.Vector3(0, 0, 0));
  296. // add subtle ambient lighting
  297. var ambientLight = new THREE.AmbientLight(0x0c0c0c);
  298. scene.add(ambientLight);
  299. // add spotlight for the shadows
  300. var spotLight = new THREE.SpotLight(0xffffff);
  301. spotLight.position.set(-40, 60, -10);
  302. spotLight.castShadow = true;
  303. scene.add(spotLight);
  304. // add the output of the renderer to the html element
  305. document.getElementById("WebGL-output").appendChild(renderer.domElement);
  306. // call the render function
  307. var step = 0;
  308. var oldContext = null;
  309. var controls = new function () {
  310. this.rotationSpeed = 0.02;
  311. this.bouncingSpeed = 0.03;
  312. this.opacity = meshMaterial1.opacity;
  313. this.transparent = meshMaterial1.transparent;
  314. this.visible = meshMaterial1.visible;
  315. this.side = "front";
  316. this.wireframe = meshMaterial1.wireframe;
  317. this.wireframeLinewidth = meshMaterial1.wireframeLinewidth;
  318. this.selectedMesh = "cube";
  319. this.shadow = "flat";
  320. };
  321. render();
  322. function render() {
  323. stats.update();
  324. cube.rotation.y = step += 0.01;
  325. cube.rotation.x = step;
  326. cube.rotation.z = step;
  327. cube.material.materials.forEach(function (e) {
  328. e.uniforms.time.value += 0.01;
  329. });
  330. // render using requestAnimationFrame
  331. requestAnimationFrame(render);
  332. renderer.render(scene, camera);
  333. }
  334. function initStats() {
  335. var stats = new Stats();
  336. stats.setMode(0); // 0: fps, 1: ms
  337. // Align top-left
  338. stats.domElement.style.position = 'absolute';
  339. stats.domElement.style.left = '0px';
  340. stats.domElement.style.top = '0px';
  341. document.getElementById("Stats-output").appendChild(stats.domElement);
  342. return stats;
  343. }
  344. function createMaterial(vertexShader, fragmentShader) {
  345. var vertShader = document.getElementById(vertexShader).innerHTML;
  346. var fragShader = document.getElementById(fragmentShader).innerHTML;
  347. var attributes = {};
  348. var uniforms = {
  349. time: {type: 'f', value: 0.2},
  350. scale: {type: 'f', value: 0.2},
  351. alpha: {type: 'f', value: 0.6},
  352. resolution: {type: "v2", value: new THREE.Vector2()}
  353. };
  354. uniforms.resolution.value.x = window.innerWidth;
  355. uniforms.resolution.value.y = window.innerHeight;
  356. var meshMaterial = new THREE.ShaderMaterial({
  357. uniforms: uniforms,
  358. attributes: attributes,
  359. vertexShader: vertShader,
  360. fragmentShader: fragShader,
  361. transparent: true
  362. });
  363. return meshMaterial;
  364. }
  365. }
  366. window.onload = init;
  367. </script>
  368. </body>
  369. </html>

线性几何体材质:

THREE.LineBasicMaterial

  1. // 调用gosper函数生成一个4阶,长度为60的Gosper曲线的点集
  2. var points = gosper(4, 60);
  3. // 创建一个新的THREE.BufferGeometry对象,用于存储线条段的几何数据
  4. var lineWidth = new THREE.BufferGeometry();
  5. // 创建一个空数组来存储颜色值
  6. var colors = [];
  7. // 初始化一个计数器变量i,用于跟踪当前处理的点的索引
  8. var i = 0;
  9. // 遍历points数组中的每个点
  10. points.forEach(function(e){
  11. // 将每个点的坐标添加到LineSegments的顶点数组中
  12. LineSegments.vertices.push(new THREE.Vector3(e.x, e.y, e.z));
  13. // 为每个点设置一个颜色值,这里使用白色作为基础颜色
  14. colors[i] = new THREE.Color(0xffffff);
  15. // 根据点的x和y坐标计算HSL颜色值,并设置颜色
  16. // x坐标除以100后加上0.5作为色相,y坐标乘以20后除以300再加上0.5作为饱和度,亮度固定为0.8
  17. colors[i].setHSL(e.x / 100 + 0.5, (e.y * 20) / 300 + 0.5, 0.8);
  18. // 增加计数器i,以便为下一个点设置颜色
  19. i++;
  20. });
  21. // 定义一个基本的线条材质,其中包含不透明度、线宽和顶点颜色的设置
  22. var material = new THREE.LineBasicMaterial({
  23. opacity: 1.0, // 设置线条的不透明度为1.0(完全不透明)
  24. linewidth: 1, // 设置线条的宽度为1
  25. vertexColors: THREE.VertexColors // 启用顶点颜色,这意味着每个顶点可以有自己的颜色
  26. });
  27. // 将计算出的颜色数组赋值给LineSegments对象的colors属性
  28. LineSegments.colors = colors;

THREE.LineDashMaterial

在LineBasicMaterial的基础上有:scale(缩放dashSize和gapSize,scale < 1 dashSize和gapSize增大);dashSize 虚线端的长度; gapSize虚线间隔的宽度

  1. const material = new THREE.LineDashedMaterial( {
  2. color: 0xffffff,
  3. linewidth: 1,
  4. scale: 1,
  5. dashSize: 3,
  6. gapSize: 1,
  7. } );


本文转载自: https://blog.csdn.net/Ian1025/article/details/144049316
版权归原作者 Ian1025 所有, 如有侵权,请联系我们删除。

“《Learn Three.js》学习(4) 材质”的评论:

还没有评论