hiccLoghicc log by wccHipo日志

Threejs材质

toc

Intro

Theree.js中,材质和THREE.Geometry对象就构成了THREE.Mesh对象。材质就像物体的皮肤,决定了几何体的外表。

Threejs材质
MeshBasicMaterial (网格基础材质)基础材质,用户给几何体赋予一种简单的颜色,可用于几何体线框
MeshDepthMaterial(网格深度材质)从摄像机到网格的记录来决定如何给网格上色
MeshNormalMaterial(网格法线材质)根据法向量计算物体表面的颜色
MeshLambertMaterial(网格 Lambert 材质)考虑光照影响的材质,用于创建暗淡的、不光亮的物体
MeshPhongMaterial(网格 Phong 材质)考虑光照影响的材质,用于创建光亮的物体
MeshStandardMaterial(网格标准材质)这种标准材质使用“基于物理的渲染(PBR)” 算法来绘制物体的表面。 它能够计算出表面与光线的正确互动关系,从而使渲染出的物体看起来更加真实
MeshPhysicalMaterial(网格物理材质)MeshStandardMaterial的扩展材质,他为光线反射计算模拟提供了更多控制
MeshToonMaterial (网格卡通材质)MeshPhongMaterial的扩展材质,它使得物理渲染更加卡通化
ShadowMaterial (阴影材质)一个专门用户接受阴影图的特殊材质。在该材质中只有阴影图先,非阴影部分为完全透明的区域
ShaderMaterial (着色器材质)这种材质容许使用自定义的着色程序, 直接控制顶点的放置方式以及像素的着色方式
LineBasicMaterial (直线基础材质)可以用于THREE.Line(直线)几何体,用来创建着色的直线
LineDashMaterialLineBasicMaterial一样,但是可以创建出一种虚线的效果

材质的共有属性

基础属性

融合属性

高级属性

网格材质

THREE.MeshBasicMaterial

function init() { // use the defaults var stats = initStats(); var camera = initCamera(); // create a scene, that will hold all our elements such as objects, cameras and lights. var scene = new THREE.Scene(); // create a render and set the size var webGLRenderer = new THREE.WebGLRenderer(); webGLRenderer.setClearColor(new THREE.Color(0x000000)); webGLRenderer.setSize(window.innerWidth, window.innerHeight); webGLRenderer.shadowMapEnabled = true; var canvasRenderer = new THREE.CanvasRenderer(); canvasRenderer.setSize(window.innerWidth, window.innerHeight); renderer = webGLRenderer; var groundGeom = new THREE.PlaneGeometry(100, 100, 4, 4); var groundMesh = new THREE.Mesh(groundGeom, new THREE.MeshBasicMaterial({ color: 0x777777 })); groundMesh.rotation.x = -Math.PI / 2; groundMesh.position.y = -20; scene.add(groundMesh); var sphereGeometry = new THREE.SphereGeometry(14, 20, 20); var cubeGeometry = new THREE.BoxGeometry(15, 15, 15); var planeGeometry = new THREE.PlaneGeometry(14, 14, 4, 4); var meshMaterial = new THREE.MeshBasicMaterial({ color: 0x7777ff, name: 'Basic Material', flatShading: true }); var sphere = new THREE.Mesh(sphereGeometry, meshMaterial); var cube = new THREE.Mesh(cubeGeometry, meshMaterial); var plane = new THREE.Mesh(planeGeometry, meshMaterial); // position the sphere sphere.position.x = 0; sphere.position.y = 3; sphere.position.z = 2; cube.position = sphere.position; plane.position = sphere.position; // add the sphere to the scene scene.add(cube); // position and point the camera to the center of the scene camera.position.x = -20; camera.position.y = 50; camera.position.z = 40; camera.lookAt(new THREE.Vector3(10, 0, 0)); // add subtle ambient lighting var ambientLight = new THREE.AmbientLight(0x0c0c0c); scene.add(ambientLight); // add spotlight for the shadows var spotLight = new THREE.SpotLight(0xffffff); spotLight.position.set(-40, 60, -10); spotLight.castShadow = true; scene.add(spotLight); // add the output of the renderer to the html element document.getElementById("webgl-output").appendChild(renderer.domElement); // call the render function var step = 0; var oldContext = null; var controls = new function () { this.rotationSpeed = 0.02; this.bouncingSpeed = 0.03; this.color = meshMaterial.color.getStyle(); this.selectedMesh = "cube"; this.switchRenderer = function () { if (renderer instanceof THREE.WebGLRenderer) { renderer = canvasRenderer; document.getElementById("webgl-output").innerHTML = ""; document.getElementById("webgl-output").appendChild(renderer.domElement); } else { renderer = webGLRenderer; document.getElementById("webgl-output").innerHTML = ""; document.getElementById("webgl-output").appendChild(renderer.domElement); } } }; var gui = new dat.GUI(); var selectedMesh = cube; addBasicMaterialSettings(gui, controls, meshMaterial); var spGui = gui.addFolder("THREE.MeshBasicMaterial"); spGui.addColor(controls, 'color').onChange(function (e) { meshMaterial.color.setStyle(e) }); spGui.add(meshMaterial, 'wireframe'); spGui.add(meshMaterial, 'wireframeLinewidth', 0, 20); spGui.add(meshMaterial, 'wireframeLinejoin', ['round', 'bevel', 'miter']).onChange(function (e) { meshMaterial.wireframeLinejoin = e }); spGui.add(meshMaterial, 'wireframeLinecap', ['butt', 'round', 'square']).onChange(function (e) { meshMaterial.wireframeLinecap = e }); loadGopher(meshMaterial).then(function(gopher) { gopher.scale.x = 4; gopher.scale.y = 4; gopher.scale.z = 4; gui.add(controls, 'selectedMesh', ["cube", "sphere", "plane", "gopher"]).onChange(function (e) { scene.remove(plane); scene.remove(cube); scene.remove(sphere); scene.remove(gopher); switch (e) { case "cube": scene.add(cube); selectedMesh = cube; break; case "sphere": scene.add(sphere); selectedMesh = sphere; break; case "plane": scene.add(plane); selectedMesh = plane; break; case "gopher": scene.add(gopher); selectedMesh = gopher; break; } }); }); gui.add(controls, 'switchRenderer'); render(); function render() { stats.update(); selectedMesh.rotation.y = step += 0.01; // render using requestAnimationFrame requestAnimationFrame(render); renderer.render(scene, camera); } }

THREE.MeshDepthMaterial

function init() { // use the defaults var stats = initStats(); var renderer = initRenderer(); // create a scene, that will hold all our elements such as objects, cameras and lights. var scene = new THREE.Scene(); scene.overrideMaterial = new THREE.MeshDepthMaterial(); var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 50, 110); camera.position.set(-50, 40, 50); camera.lookAt(scene.position); // call the render function var step = 0; var controls = new function () { this.cameraNear = camera.near; this.cameraFar = camera.far; this.rotationSpeed = 0.02; this.numberOfObjects = scene.children.length; this.removeCube = function () { var allChildren = scene.children; var lastObject = allChildren[allChildren.length - 1]; if (lastObject instanceof THREE.Mesh) { scene.remove(lastObject); this.numberOfObjects = scene.children.length; } }; this.addCube = function () { var cubeSize = Math.ceil(3 + (Math.random() * 3)); var cubeGeometry = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize); var cubeMaterial = new THREE.MeshLambertMaterial({ color: Math.random() * 0xffffff }); var cube = new THREE.Mesh(cubeGeometry, cubeMaterial); cube.castShadow = true; // position the cube randomly in the scene cube.position.x = -60 + Math.round((Math.random() * 100)); cube.position.y = Math.round((Math.random() * 10)); cube.position.z = -100 + Math.round((Math.random() * 150)); // add the cube to the scene scene.add(cube); this.numberOfObjects = scene.children.length; }; this.outputObjects = function () { console.log(scene.children); } }; var gui = new dat.GUI(); addBasicMaterialSettings(gui, controls, scene.overrideMaterial); var spGui = gui.addFolder("THREE.MeshDepthMaterial"); spGui.add(scene.overrideMaterial, 'wireframe'); spGui.add(scene.overrideMaterial, 'wireframeLinewidth', 0, 20); gui.add(controls, 'rotationSpeed', 0, 0.5); gui.add(controls, 'addCube'); gui.add(controls, 'removeCube'); gui.add(controls, 'cameraNear', 0, 100).onChange(function (e) { camera.near = e; camera.updateProjectionMatrix(); }); gui.add(controls, 'cameraFar', 50, 200).onChange(function (e) { camera.far = e; camera.updateProjectionMatrix(); }); var i = 0; while (i < 10) { controls.addCube(); i++; } render(); function render() { stats.update(); // rotate the cubes around its axes scene.traverse(function (e) { if (e instanceof THREE.Mesh) { e.rotation.x += controls.rotationSpeed; e.rotation.y += controls.rotationSpeed; e.rotation.z += controls.rotationSpeed; } }); // render using requestAnimationFrame requestAnimationFrame(render); renderer.render(scene, camera); } }

联合材质

function init() { // use the defaults var stats = initStats(); var renderer = initRenderer(); // create a scene, that will hold all our elements such as objects, cameras and lights. var scene = new THREE.Scene(); // create a camera, which defines where we're looking at. var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 50, 110); camera.position.set(-50, 40, 50); camera.lookAt(scene.position); // call the render function var step = 0; var controls = new function () { this.cameraNear = camera.near; this.cameraFar = camera.far; this.rotationSpeed = 0.02; this.numberOfObjects = scene.children.length; this.color = 0x00ff00; this.removeCube = function () { var allChildren = scene.children; var lastObject = allChildren[allChildren.length - 1]; if (lastObject instanceof THREE.Group) { scene.remove(lastObject); this.numberOfObjects = scene.children.length; } }; this.addCube = function () { var cubeSize = Math.ceil(3 + (Math.random() * 3)); var cubeGeometry = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize); //var cubeMaterial = new THREE.MeshLambertMaterial({color: Math.random() * 0xffffff }); var cubeMaterial = new THREE.MeshDepthMaterial(); var colorMaterial = new THREE.MeshBasicMaterial({ color: controls.color, transparent: true, blending: THREE.MultiplyBlending }); var cube = new THREE.SceneUtils.createMultiMaterialObject(cubeGeometry, [colorMaterial, cubeMaterial ]); cube.children[1].scale.set(0.99, 0.99, 0.99); cube.castShadow = true; // position the cube randomly in the scene cube.position.x = -60 + Math.round((Math.random() * 100)); cube.position.y = Math.round((Math.random() * 10)); cube.position.z = -100 + Math.round((Math.random() * 150)); // add the cube to the scene scene.add(cube); this.numberOfObjects = scene.children.length; }; this.outputObjects = function () { console.log(scene.children); } }; var gui = new dat.GUI(); gui.addColor(controls, 'color'); gui.add(controls, 'rotationSpeed', 0, 0.5); gui.add(controls, 'addCube'); gui.add(controls, 'removeCube'); gui.add(controls, 'cameraNear', 0, 50).onChange(function (e) { camera.near = e; camera.updateProjectionMatrix(); }); gui.add(controls, 'cameraFar', 50, 200).onChange(function (e) { camera.far = e; camera.updateProjectionMatrix(); }); var i = 0; while (i < 10) { controls.addCube(); i++; } render(); function render() { stats.update(); // rotate the cubes around its axes scene.traverse(function (e) { if (e instanceof THREE.Group) { e.rotation.x += controls.rotationSpeed; e.rotation.y += controls.rotationSpeed; e.rotation.z += controls.rotationSpeed; } }); // render using requestAnimationFrame requestAnimationFrame(render); renderer.render(scene, camera); } }

THREE.MeshNormalMaterial

function init() { // use the defaults var stats = initStats(); var camera = initCamera(); // create a scene, that will hold all our elements such as objects, cameras and lights. var scene = new THREE.Scene(); // create a camera, which defines where we're looking at. var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.set(-20, 30, 40); camera.lookAt(new THREE.Vector3(10, 0, 0)); // create a render and set the size var renderer; var webGLRenderer = new THREE.WebGLRenderer(); webGLRenderer.setClearColor(new THREE.Color(0x000000)); webGLRenderer.setSize(window.innerWidth, window.innerHeight); var canvasRenderer = new THREE.CanvasRenderer(); canvasRenderer.setSize(window.innerWidth, window.innerHeight); renderer = webGLRenderer; var groundGeom = new THREE.PlaneGeometry(100, 100, 4, 4); var groundMesh = new THREE.Mesh(groundGeom, new THREE.MeshBasicMaterial({ color: 0x777777 })); groundMesh.rotation.x = -Math.PI / 2; groundMesh.position.y = -20; scene.add(groundMesh); var sphereGeometry = new THREE.SphereGeometry(14, 20, 20); var cubeGeometry = new THREE.BoxGeometry(15, 15, 15); var planeGeometry = new THREE.PlaneGeometry(14, 14, 4, 4); var meshMaterial = new THREE.MeshNormalMaterial(); var sphere = new THREE.Mesh(sphereGeometry, meshMaterial); var cube = new THREE.Mesh(cubeGeometry, meshMaterial); var plane = new THREE.Mesh(planeGeometry, meshMaterial); var selectedMesh = cube; // position the sphere sphere.position.x = 0; sphere.position.y = 3; sphere.position.z = 2; for (var f = 0, fl = sphere.geometry.faces.length; f < fl; f++) { var face = sphere.geometry.faces[f]; var centroid = new THREE.Vector3(0, 0, 0); centroid.add(sphere.geometry.vertices[face.a]); centroid.add(sphere.geometry.vertices[face.b]); centroid.add(sphere.geometry.vertices[face.c]); centroid.divideScalar(3); var arrow = new THREE.ArrowHelper( face.normal, centroid, 2, 0x3333FF, 0.5, 0.5); // sphere.add(arrow); } cube.position = sphere.position; plane.position = sphere.position; // add the sphere to the scene scene.add(cube); // add subtle ambient lighting var ambientLight = new THREE.AmbientLight(0x0c0c0c); scene.add(ambientLight); // add spotlight for the shadows var spotLight = new THREE.SpotLight(0xffffff); spotLight.position.set(-40, 60, -10); spotLight.castShadow = true; scene.add(spotLight); // add the output of the renderer to the html element document.getElementById("webgl-output").appendChild(renderer.domElement); // call the render function var step = 0; var oldContext = null; var controls = new function () { this.rotationSpeed = 0.02; this.bouncingSpeed = 0.03; this.selectedMesh = "cube"; }; var gui = new dat.GUI(); addBasicMaterialSettings(gui, controls, meshMaterial); loadGopher(meshMaterial).then(function(gopher) { gopher.scale.x = 4; gopher.scale.y = 4; gopher.scale.z = 4; gui.add(controls, 'selectedMesh', ["cube", "sphere", "plane", "gopher"]).onChange(function (e) { scene.remove(plane); scene.remove(cube); scene.remove(sphere); scene.remove(gopher); switch (e) { case "cube": scene.add(cube); selectedMesh = cube; break; case "sphere": scene.add(sphere); selectedMesh = sphere; break; case "plane": scene.add(plane); selectedMesh = plane; break; case "gopher": scene.add(gopher); selectedMesh = gopher; break; } }); }); render(); function render() { stats.update(); selectedMesh.rotation.y = step += 0.01; // render using requestAnimationFrame requestAnimationFrame(render); renderer.render(scene, camera); } }

在单几何体上使用多种材质

function init() { // use the defaults var stats = initStats(); var renderer = initRenderer(); var camera = initCamera(); // create a scene, that will hold all our elements such as objects, cameras and lights. var scene = new THREE.Scene(); // create a camera, which defines where we're looking at. // var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); // create a render and set the size // var renderer = new THREE.WebGLRenderer(); // renderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0)); // renderer.setSize(window.innerWidth, window.innerHeight); // renderer.shadowMapEnabled = false; // position and point the camera to the center of the scene // camera.position.x = -40; // camera.position.y = 40; // camera.position.z = 40; // camera.lookAt(scene.position); // add subtle ambient lighting // var ambientLight = new THREE.AmbientLight(0x0c0c0c); // scene.add(ambientLight); // add spotlight for the shadows var spotLight = new THREE.SpotLight(0xffffff); spotLight.position.set(-40, 60, -10); spotLight.castShadow = true; scene.add(spotLight); var group = new THREE.Mesh(); // add all the rubik cube elements var mats = []; mats.push(new THREE.MeshBasicMaterial({ color: 0x009e60 })); // mats.push(new THREE.MeshBasicMaterial({ // color: 0x009e60 // })); mats.push(new THREE.MeshBasicMaterial({ color: 0x0051ba })); // mats.push(new THREE.MeshBasicMaterial({ // color: 0x0051ba // })); mats.push(new THREE.MeshBasicMaterial({ color: 0xffd500 })); // mats.push(new THREE.MeshBasicMaterial({ // color: 0xffd500 // })); mats.push(new THREE.MeshBasicMaterial({ color: 0xff5800 })); // mats.push(new THREE.MeshBasicMaterial({ // color: 0xff5800 // })); mats.push(new THREE.MeshBasicMaterial({ color: 0xC41E3A })); // mats.push(new THREE.MeshBasicMaterial({ // color: 0xC41E3A // })); mats.push(new THREE.MeshBasicMaterial({ color: 0xffffff })); // mats.push(new THREE.MeshBasicMaterial({ // color: 0xffffff // })); for (var x = 0; x < 3; x++) { for (var y = 0; y < 3; y++) { for (var z = 0; z < 3; z++) { var cubeGeom = new THREE.BoxGeometry(2.9, 2.9, 2.9); var cube = new THREE.Mesh(cubeGeom, mats); cube.position.set(x * 3 - 3, y * 3 - 3, z * 3 - 3); group.add(cube); } } } group.scale.copy(new THREE.Vector3(2,2,2)) // call the render function scene.add(group); var step = 0; var controls = new function () { this.rotationSpeed = 0.01; this.numberOfObjects = scene.children.length; }; var gui = new dat.GUI(); gui.add(controls, 'rotationSpeed', 0, 0.5); render(); debugger; function render() { stats.update(); group.rotation.y = step += controls.rotationSpeed; group.rotation.z = step -= controls.rotationSpeed; group.rotation.x = step += controls.rotationSpeed; // render using requestAnimationFrame requestAnimationFrame(render); renderer.render(scene, camera); } }

高级材质

THREE.meshLambertMaterial

function init() { // use the defaults var stats = initStats(); var renderer = initRenderer(); var camera = initCamera(); // create a scene, that will hold all our elements such as objects, cameras and lights. var scene = new THREE.Scene(); // create a scene, that will hold all our elements such as objects, cameras and lights. var scene = new THREE.Scene(); var groundGeom = new THREE.PlaneGeometry(100, 100, 4, 4); var groundMesh = new THREE.Mesh(groundGeom, new THREE.MeshBasicMaterial({ color: 0x555555 })); groundMesh.rotation.x = -Math.PI / 2; groundMesh.position.y = -20; scene.add(groundMesh); var sphereGeometry = new THREE.SphereGeometry(14, 20, 20); var cubeGeometry = new THREE.BoxGeometry(15, 15, 15); var planeGeometry = new THREE.PlaneGeometry(14, 14, 4, 4); var meshMaterial = new THREE.MeshLambertMaterial({ color: 0x7777ff }); var sphere = new THREE.Mesh(sphereGeometry, meshMaterial); var cube = new THREE.Mesh(cubeGeometry, meshMaterial); var plane = new THREE.Mesh(planeGeometry, meshMaterial); var selectedMesh = cube; // position the sphere sphere.position.x = 0; sphere.position.y = 3; sphere.position.z = 2; cube.position = sphere.position; plane.position = sphere.position; // add the sphere to the scene scene.add(cube); // add subtle ambient lighting var ambientLight = new THREE.AmbientLight(0x0c0c0c); scene.add(ambientLight); // add spotlight for the shadows var spotLight = new THREE.SpotLight(0xffffff); spotLight.position.set(-30, 60, 60); spotLight.castShadow = true; scene.add(spotLight); // call the render function var step = 0; var controls = new function () { this.rotationSpeed = 0.02; this.bouncingSpeed = 0.03; this.opacity = meshMaterial.opacity; this.transparent = meshMaterial.transparent; this.overdraw = meshMaterial.overdraw; this.visible = meshMaterial.visible; this.emissive = meshMaterial.emissive.getHex(); // this.ambient = meshMaterial.ambient.getHex(); this.side = "front"; this.color = meshMaterial.color.getStyle(); this.wrapAround = false; this.wrapR = 1; this.wrapG = 1; this.wrapB = 1; this.selectedMesh = "cube"; }; var gui = new dat.GUI(); addBasicMaterialSettings(gui, controls, meshMaterial); var spGui = gui.addFolder("THREE.MeshLambertMaterial"); spGui.addColor(controls, 'color').onChange(function (e) { meshMaterial.color.setStyle(e) }); spGui.addColor(controls, 'emissive').onChange(function (e) { meshMaterial.emissive = new THREE.Color(e); }); spGui.add(meshMaterial, 'wireframe'); spGui.add(meshMaterial, 'wireframeLinewidth', 0, 20); loadGopher(meshMaterial).then(function(gopher) { gopher.scale.x = 4; gopher.scale.y = 4; gopher.scale.z = 4; gui.add(controls, 'selectedMesh', ["cube", "sphere", "plane", "gopher"]).onChange(function (e) { scene.remove(plane); scene.remove(cube); scene.remove(sphere); scene.remove(gopher); switch (e) { case "cube": scene.add(cube); selectedMesh = cube; break; case "sphere": scene.add(sphere); selectedMesh = sphere; break; case "plane": scene.add(plane); selectedMesh = plane; break; case "gopher": scene.add(gopher); selectedMesh = gopher; break; } }); }); render() function render() { stats.update(); selectedMesh.rotation.y = step += 0.01; // render using requestAnimationFrame requestAnimationFrame(render); renderer.render(scene, camera); } }

THREE.MeshPhongMaterial

function init() { // use the defaults var stats = initStats(); var renderer = initRenderer(); var camera = initCamera(); // create a scene, that will hold all our elements such as objects, cameras and lights. var scene = new THREE.Scene(); addLargeGroundPlane(scene); // add spotlight for the shadows var spotLight = new THREE.SpotLight(0xffffff); spotLight.position.set(-0, 30, 60); spotLight.castShadow = true; spotLight.intensity = 0.6; scene.add(spotLight); // call the render function var step = 0; var material = new THREE.MeshPhongMaterial({color: 0x7777ff}) var controls = new function () { this.color = material.color.getStyle(); this.emissive = material.emissive.getStyle(); this.specular = material.specular.getStyle(); }; var gui = new dat.GUI(); addBasicMaterialSettings(gui, controls, material); addMeshSelection(gui, controls, material, scene); var spGui = gui.addFolder("THREE.MeshPhongMaterial"); spGui.addColor(controls, 'color').onChange(function (e) { material.color.setStyle(e) }); spGui.addColor(controls, 'emissive').onChange(function (e) { material.emissive = new THREE.Color(e); }); spGui.addColor(controls, 'specular').onChange(function (e) { material.specular = new THREE.Color(e); }); spGui.add(material, 'shininess', 0, 100, ) spGui.add(material, 'wireframe'); spGui.add(material, 'wireframeLinewidth', 0, 20); camera.lookAt(controls.selected.position); render(); function render() { stats.update(); if (controls.selected) controls.selected.rotation.y = step += 0.01; // render using requestAnimationFrame requestAnimationFrame(render); renderer.render(scene, camera); } }

THREE.MeshToonMaterial

function init() { // use the defaults var stats = initStats(); var renderer = initRenderer(); var camera = initCamera(); // create a scene, that will hold all our elements such as objects, cameras and lights. var scene = new THREE.Scene(); addLargeGroundPlane(scene); // add spotlight for the shadows var spotLight = new THREE.SpotLight(0xffffff); spotLight.position.set(-0, 30, 60); spotLight.castShadow = true; spotLight.intensity = 0.6; scene.add(spotLight); // call the render function var step = 0; var material = new THREE.MeshToonMaterial({color: 0x7777ff}) var controls = new function () { this.color = material.color.getStyle(); this.emissive = material.emissive.getStyle(); this.specular = material.specular.getStyle(); }; var gui = new dat.GUI(); addBasicMaterialSettings(gui, controls, material); addMeshSelection(gui, controls, material, scene); var spGui = gui.addFolder("THREE.MeshToonMaterial"); spGui.addColor(controls, 'color').onChange(function (e) { material.color.setStyle(e) }); spGui.addColor(controls, 'emissive').onChange(function (e) { material.emissive = new THREE.Color(e); }); spGui.addColor(controls, 'specular').onChange(function (e) { material.specular = new THREE.Color(e); }); spGui.add(material, 'shininess', 0, 100, ) spGui.add(material, 'wireframe'); spGui.add(material, 'wireframeLinewidth', 0, 20); camera.lookAt(controls.selected.position); render(); function render() { stats.update(); if (controls.selected) controls.selected.rotation.y = step += 0.01; // render using requestAnimationFrame requestAnimationFrame(render); renderer.render(scene, camera); } }

THREE.MeshStandardMaterial

function init() { // use the defaults var stats = initStats(); var renderer = initRenderer(); var camera = initCamera(); // create a scene, that will hold all our elements such as objects, cameras and lights. var scene = new THREE.Scene(); addLargeGroundPlane(scene); // add spotlight for the shadows var spotLight = new THREE.SpotLight(0xffffff); spotLight.position.set(-0, 30, 60); spotLight.castShadow = true; spotLight.intensity = 0.6; scene.add(spotLight); // call the render function var step = 0; var material = new THREE.MeshStandardMaterial({color: 0x7777ff}) var controls = new function () { this.color = material.color.getStyle(); this.emissive = material.emissive.getStyle(); }; var gui = new dat.GUI(); addBasicMaterialSettings(gui, controls, material); addMeshSelection(gui, controls, material, scene); var spGui = gui.addFolder("THREE.MeshStandardMaterial"); spGui.addColor(controls, 'color').onChange(function (e) { material.color.setStyle(e) }); spGui.addColor(controls, 'emissive').onChange(function (e) { material.emissive = new THREE.Color(e); }); spGui.add(material, 'metalness', 0, 1, 0.01); spGui.add(material, 'roughness', 0, 1, 0.01); spGui.add(material, 'wireframe'); spGui.add(material, 'wireframeLinewidth', 0, 20); camera.lookAt(controls.selected.position); render(); function render() { stats.update(); if (controls.selected) controls.selected.rotation.y = step += 0.01; // render using requestAnimationFrame requestAnimationFrame(render); renderer.render(scene, camera); } }

THREE.MeshPhysicalMaterial

function init() { // use the defaults var stats = initStats(); var renderer = initRenderer(); var camera = initCamera(); // create a scene, that will hold all our elements such as objects, cameras and lights. var scene = new THREE.Scene(); addLargeGroundPlane(scene); // add spotlight for the shadows var spotLight = new THREE.SpotLight(0xffffff); spotLight.position.set(-0, 30, 60); spotLight.castShadow = true; spotLight.intensity = 0.6; scene.add(spotLight); // call the render function var step = 0; var material = new THREE.MeshPhysicalMaterial({color: 0x7777ff}) var controls = new function () { this.color = material.color.getStyle(); this.emissive = material.emissive.getStyle(); }; var gui = new dat.GUI(); addBasicMaterialSettings(gui, controls, material); addMeshSelection(gui, controls, material, scene); var spGui = gui.addFolder("THREE.MeshPhysicalMaterial"); spGui.addColor(controls, 'color').onChange(function (e) { material.color.setStyle(e) }); spGui.addColor(controls, 'emissive').onChange(function (e) { material.emissive = new THREE.Color(e); }); spGui.add(material, 'metalness', 0, 1, 0.01); spGui.add(material, 'roughness', 0, 1, 0.01); spGui.add(material, 'clearCoat', 0, 1, 0.01); spGui.add(material, 'clearCoatRoughness', 0, 1, 0.01); spGui.add(material, 'reflectivity', 0, 1, 0.01); spGui.add(material, 'wireframe'); spGui.add(material, 'wireframeLinewidth', 0, 20); camera.lookAt(controls.selected.position); render(); function render() { stats.update(); if (controls.selected) controls.selected.rotation.y = step += 0.01; // render using requestAnimationFrame requestAnimationFrame(render); renderer.render(scene, camera); } }

THREE.ShaderMaterial创建自己的着色器

<script id="vertex-shader" type="x-shader/x-vertex"> uniform float time; varying vec2 vUv; void main() { vec3 posChanged = position; posChanged.x = posChanged.x*(abs(sin(time*1.0))); posChanged.y = posChanged.y*(abs(cos(time*1.0))); posChanged.z = posChanged.z*(abs(sin(time*1.0))); //gl_Position = projectionMatrix * modelViewMatrix * vec4(position*(abs(sin(time)/2.0)+0.5),1.0); gl_Position = projectionMatrix * modelViewMatrix * vec4(posChanged,1.0); } </script> <script id="fragment-shader-1" type="x-shader/x-fragment"> precision highp float; uniform float time; uniform float alpha; uniform vec2 resolution; varying vec2 vUv; void main2(void) { vec2 position = vUv; float red = 1.0; float green = 0.25 + sin(time) * 0.25; float blue = 0.0; vec3 rgb = vec3(red, green, blue); vec4 color = vec4(rgb, alpha); gl_FragColor = color; } #define PI 3.14159 #define TWO_PI (PI*2.0) #define N 68.5 void main(void) { vec2 center = (gl_FragCoord.xy); center.x=-10.12*sin(time/200.0); center.y=-10.12*cos(time/200.0); vec2 v = (gl_FragCoord.xy - resolution/20.0) / min(resolution.y,resolution.x) * 15.0; v.x=v.x-10.0; v.y=v.y-200.0; float col = 0.0; for(float i = 0.0; i < N; i++) { float a = i * (TWO_PI/N) * 61.95; col += cos(TWO_PI*(v.y * cos(a) + v.x * sin(a) + sin(time*0.004)*100.0 )); } col /= 5.0; gl_FragColor = vec4(col*1.0, -col*1.0,-col*4.0, 1.0); } </script> <script id="fragment-shader-2" type="x-shader/x-fragment"> // from http://glsl.heroku.com/e#7906.0 uniform float time; uniform vec2 resolution; // 2013-03-30 by @hintz #define CGFloat float #define M_PI 3.14159265359 vec3 hsvtorgb(float h, float s, float v) { float c = v * s; h = mod((h * 6.0), 6.0); float x = c * (1.0 - abs(mod(h, 2.0) - 1.0)); vec3 color; if (0.0 <= h && h < 1.0) { color = vec3(c, x, 0.0); } else if (1.0 <= h && h < 2.0) { color = vec3(x, c, 0.0); } else if (2.0 <= h && h < 3.0) { color = vec3(0.0, c, x); } else if (3.0 <= h && h < 4.0) { color = vec3(0.0, x, c); } else if (4.0 <= h && h < 5.0) { color = vec3(x, 0.0, c); } else if (5.0 <= h && h < 6.0) { color = vec3(c, 0.0, x); } else { color = vec3(0.0); } color += v - c; return color; } void main(void) { vec2 position = (gl_FragCoord.xy - 0.5 * resolution) / resolution.y; float x = position.x; float y = position.y; CGFloat a = atan(x, y); CGFloat d = sqrt(x*x+y*y); CGFloat d0 = 0.5*(sin(d-time)+1.5)*d; CGFloat d1 = 5.0; CGFloat u = mod(a*d1+sin(d*10.0+time), M_PI*2.0)/M_PI*0.5 - 0.5; CGFloat v = mod(pow(d0*4.0, 0.75),1.0) - 0.5; CGFloat dd = sqrt(u*u+v*v); CGFloat aa = atan(u, v); CGFloat uu = mod(aa*3.0+3.0*cos(dd*30.0-time), M_PI*2.0)/M_PI*0.5 - 0.5; // CGFloat vv = mod(dd*4.0,1.0) - 0.5; CGFloat d2 = sqrt(uu*uu+v*v)*1.5; gl_FragColor = vec4( hsvtorgb(dd+time*0.5/d1, sin(dd*time), d2), 1.0 ); } </script> <script id="fragment-shader-3" type="x-shader/x-fragment"> uniform vec2 resolution; uniform float time; vec2 rand(vec2 pos) { return fract( 0.00005 * (pow(pos+2.0, pos.yx + 1.0) * 22222.0)); } vec2 rand2(vec2 pos) { return rand(rand(pos)); } float softnoise(vec2 pos, float scale) { vec2 smplpos = pos * scale; float c0 = rand2((floor(smplpos) + vec2(0.0, 0.0)) / scale).x; float c1 = rand2((floor(smplpos) + vec2(1.0, 0.0)) / scale).x; float c2 = rand2((floor(smplpos) + vec2(0.0, 1.0)) / scale).x; float c3 = rand2((floor(smplpos) + vec2(1.0, 1.0)) / scale).x; vec2 a = fract(smplpos); return mix( mix(c0, c1, smoothstep(0.0, 1.0, a.x)), mix(c2, c3, smoothstep(0.0, 1.0, a.x)), smoothstep(0.0, 1.0, a.y)); } void main(void) { vec2 pos = gl_FragCoord.xy / resolution.y; pos.x += time * 0.1; float color = 0.0; float s = 1.0; for(int i = 0; i < 8; i++) { color += softnoise(pos+vec2(i)*0.02, s * 4.0) / s / 2.0; s *= 2.0; } gl_FragColor = vec4(color); } </script> <script id="fragment-shader-4" type="x-shader/x-fragment"> uniform float time; uniform vec2 resolution; vec2 rand(vec2 pos) { return fract( ( pow( pos+2.0, pos.yx+2.0 )*555555.0 ) ); } vec2 rand2(vec2 pos) { return rand(rand(pos)); } float softnoise(vec2 pos, float scale) { vec2 smplpos = pos * scale; float c0 = rand2((floor(smplpos) + vec2(0.0, 0.0)) / scale).x; float c1 = rand2((floor(smplpos) + vec2(1.0, 0.0)) / scale).x; float c2 = rand2((floor(smplpos) + vec2(0.0, 1.0)) / scale).x; float c3 = rand2((floor(smplpos) + vec2(1.0, 1.0)) / scale).x; vec2 a = fract(smplpos); return mix(mix(c0, c1, smoothstep(0.0, 1.0, a.x)), mix(c2, c3, smoothstep(0.0, 1.0, a.x)), smoothstep(0.0, 1.0, a.x)); } void main( void ) { vec2 pos = gl_FragCoord.xy / resolution.y - time * 0.4; float color = 0.0; float s = 1.0; for (int i = 0; i < 6; ++i) { color += softnoise(pos + vec2(0.01 * float(i)), s * 4.0) / s / 2.0; s *= 2.0; } gl_FragColor = vec4(color,mix(color,cos(color),sin(color)),color,1); } </script> <script id="fragment-shader-5" type="x-shader/x-fragment"> uniform float time; uniform vec2 resolution; // tie nd die by Snoep Games. void main( void ) { vec3 color = vec3(1.0, 0., 0.); vec2 pos = (( 1.4 * gl_FragCoord.xy - resolution.xy) / resolution.xx)*1.5; float r=sqrt(pos.x*pos.x+pos.y*pos.y)/15.0; float size1=2.0*cos(time/60.0); float size2=2.5*sin(time/12.1); float rot1=13.00; //82.0+16.0*sin(time/4.0); float rot2=-50.00; //82.0+16.0*sin(time/8.0); float t=sin(time); float a = (60.0)*sin(rot1*atan(pos.x-size1*pos.y/r,pos.y+size1*pos.x/r)+time); a += 200.0*acos(pos.x*2.0+cos(time/2.0))+asin(pos.y*5.0+sin(time/2.0)); a=a*(r/50.0); a=200.0*sin(a*5.0)*(r/30.0); if(a>5.0) a=a/200.0; if(a<0.5) a=a*22.5; gl_FragColor = vec4( cos(a/20.0),a*cos(a/200.0),sin(a/8.0), 1.0 ); } </script> <script id="fragment-shader-6" type="x-shader/x-fragment"> uniform float time; uniform vec2 resolution; void main( void ) { vec2 uPos = ( gl_FragCoord.xy / resolution.xy );//normalize wrt y axis //suPos -= vec2((resolution.x/resolution.y)/2.0, 0.0);//shift origin to center uPos.x -= 1.0; uPos.y -= 0.5; vec3 color = vec3(0.0); float vertColor = 2.0; for( float i = 0.0; i < 15.0; ++i ) { float t = time * (0.9); uPos.y += sin( uPos.x*i + t+i/2.0 ) * 0.1; float fTemp = abs(1.0 / uPos.y / 100.0); vertColor += fTemp; color += vec3( fTemp*(10.0-i)/10.0, fTemp*i/10.0, pow(fTemp,1.5)*1.5 ); } vec4 color_final = vec4(color, 1.0); gl_FragColor = color_final; } </script> <script> function init() { // use the defaults var stats = initStats(); var renderer = initRenderer(); var camera = initCamera(); // create a scene, that will hold all our elements such as objects, cameras and lights. var scene = new THREE.Scene(); var cubeGeometry = new THREE.BoxGeometry(20, 20, 20); var meshMaterial1 = createMaterial("vertex-shader", "fragment-shader-1"); var meshMaterial2 = createMaterial("vertex-shader", "fragment-shader-2"); var meshMaterial3 = createMaterial("vertex-shader", "fragment-shader-3"); var meshMaterial4 = createMaterial("vertex-shader", "fragment-shader-4"); var meshMaterial5 = createMaterial("vertex-shader", "fragment-shader-5"); var meshMaterial6 = createMaterial("vertex-shader", "fragment-shader-6"); var material = [meshMaterial1, meshMaterial2, meshMaterial3, meshMaterial4, meshMaterial5, meshMaterial6]; var cube = new THREE.Mesh(cubeGeometry, material); // add the sphere to the scene scene.add(cube); // add subtle ambient lighting var ambientLight = new THREE.AmbientLight(0x0c0c0c); scene.add(ambientLight); // add spotlight for the shadows var spotLight = new THREE.SpotLight(0xffffff); spotLight.position.set(-40, 60, -10); spotLight.castShadow = true; scene.add(spotLight); // call the render function var step = 0; var oldContext = null; var controls = new function () { this.rotationSpeed = 0.02; this.bouncingSpeed = 0.03; this.opacity = meshMaterial1.opacity; this.transparent = meshMaterial1.transparent; this.visible = meshMaterial1.visible; this.side = "front"; this.wireframe = meshMaterial1.wireframe; this.wireframeLinewidth = meshMaterial1.wireframeLinewidth; this.selectedMesh = "cube"; this.shadow = "flat"; }; render(); function render() { stats.update(); cube.rotation.y = step += 0.01; cube.rotation.x = step; cube.rotation.z = step; cube.material.forEach(function (e) { e.uniforms.time.value += 0.01; }); // render using requestAnimationFrame requestAnimationFrame(render); renderer.render(scene, camera); } function createMaterial(vertexShader, fragmentShader) { var vertShader = document.getElementById(vertexShader).innerHTML; var fragShader = document.getElementById(fragmentShader).innerHTML; var attributes = {}; var uniforms = { time: { type: 'f', value: 0.2 }, scale: { type: 'f', value: 0.2 }, alpha: { type: 'f', value: 0.6 }, resolution: { type: "v2", value: new THREE.Vector2() } }; uniforms.resolution.value.x = window.innerWidth; uniforms.resolution.value.y = window.innerHeight; var meshMaterial = new THREE.ShaderMaterial({ uniforms: uniforms, vertexShader: vertShader, fragmentShader: fragShader, transparent: true }); return meshMaterial; } } </script>

线性几何体的材质

THREE.LineBasicMaterial

function init() { // use the defaults var stats = initStats(); var renderer = initRenderer(); var camera = initCamera(); // create a scene, that will hold all our elements such as objects, cameras and lights. var scene = new THREE.Scene(); var stats = initStats(); // add subtle ambient lighting var ambientLight = new THREE.AmbientLight(0x0c0c0c); scene.add(ambientLight); // add spotlight for the shadows var spotLight = new THREE.SpotLight(0xffffff); spotLight.position.set(-40, 60, -10); spotLight.castShadow = true; scene.add(spotLight); // get the turtle var points = gosper(4, 60); var lines = new THREE.Geometry(); var colors = []; var i = 0; points.forEach(function (e) { lines.vertices.push(new THREE.Vector3(e.x, e.z, e.y)); colors[i] = new THREE.Color(0xffffff); colors[i].setHSL(e.x / 100 + 0.5, (e.y * 20) / 300, 0.8); i++; }); lines.colors = colors; var material = new THREE.LineBasicMaterial({ opacity: 1.0, linewidth: 1, vertexColors: THREE.VertexColors }); var line = new THREE.Line(lines, material); line.position.set(25, -30, -60); scene.add(line); // call the render function var step = 0; render(); function render() { stats.update(); line.rotation.z = step += 0.01; requestAnimationFrame(render); renderer.render(scene, camera); } function gosper(a, b) { var turtle = [0, 0, 0]; var points = []; var count = 0; rg(a, b, turtle); return points; function rt(x) { turtle[2] += x; } function lt(x) { turtle[2] -= x; } function fd(dist) { // ctx.beginPath(); points.push({ x: turtle[0], y: turtle[1], z: Math.sin(count) * 5 }); // ctx.moveTo(turtle[0], turtle[1]); var dir = turtle[2] * (Math.PI / 180); turtle[0] += Math.cos(dir) * dist; turtle[1] += Math.sin(dir) * dist; points.push({ x: turtle[0], y: turtle[1], z: Math.sin(count) * 5 }); // ctx.lineTo(turtle[0], turtle[1]); // ctx.stroke(); } function rg(st, ln, turtle) { st--; ln = ln / 2.6457; if (st > 0) { // ctx.strokeStyle = '#111'; rg(st, ln, turtle); rt(60); gl(st, ln, turtle); rt(120); gl(st, ln, turtle); lt(60); rg(st, ln, turtle); lt(120); rg(st, ln, turtle); rg(st, ln, turtle); lt(60); gl(st, ln, turtle); rt(60); } if (st == 0) { fd(ln); rt(60); fd(ln); rt(120); fd(ln); lt(60); fd(ln); lt(120); fd(ln); fd(ln); lt(60); fd(ln); rt(60) } } function gl(st, ln, turtle) { st--; ln = ln / 2.6457; if (st > 0) { // ctx.strokeStyle = '#555'; lt(60); rg(st, ln, turtle); rt(60); gl(st, ln, turtle); gl(st, ln, turtle); rt(120); gl(st, ln, turtle); rt(60); rg(st, ln, turtle); lt(120); rg(st, ln, turtle); lt(60); gl(st, ln, turtle); } if (st == 0) { lt(60); fd(ln); rt(60); fd(ln); fd(ln); rt(120); fd(ln); rt(60); fd(ln); lt(120); fd(ln); lt(60); fd(ln); } } } }

THREE.LineDashedMaterial

function init() { // use the defaults var stats = initStats(); var renderer = initRenderer(); var camera = initCamera(); // create a scene, that will hold all our elements such as objects, cameras and lights. var scene = new THREE.Scene(); // add subtle ambient lighting var ambientLight = new THREE.AmbientLight(0x0c0c0c); scene.add(ambientLight); // add spotlight for the shadows var spotLight = new THREE.SpotLight(0xffffff); spotLight.position.set(-40, 60, -10); spotLight.castShadow = true; scene.add(spotLight); // get the turtle var points = gosper(4, 60); var lines = new THREE.Geometry(); var colors = []; var i = 0; points.forEach(function (e) { lines.vertices.push(new THREE.Vector3(e.x, e.z, e.y)); colors[i] = new THREE.Color(0xffffff); colors[i].setHSL(e.x / 100 + 0.5, (e.y * 20) / 300, 0.8); i++; }); lines.colors = colors; var material = new THREE.LineDashedMaterial({ vertexColors: true, color: 0xffffff, dashSize: 2, gapSize: 2, scale: 0.1 }); var line = new THREE.Line(lines, material); line.computeLineDistances(); line.position.set(25, -30, -60); scene.add(line); // call the render function var step = 0; render(); function render() { stats.update(); line.rotation.z = step += 0.01; requestAnimationFrame(render); renderer.render(scene, camera); } function gosper(a, b) { var turtle = [0, 0, 0]; var points = []; var count = 0; rg(a, b, turtle); return points; function rt(x) { turtle[2] += x; } function lt(x) { turtle[2] -= x; } function fd(dist) { // ctx.beginPath(); points.push({ x: turtle[0], y: turtle[1], z: Math.sin(count) * 5 }); // ctx.moveTo(turtle[0], turtle[1]); var dir = turtle[2] * (Math.PI / 180); turtle[0] += Math.cos(dir) * dist; turtle[1] += Math.sin(dir) * dist; points.push({ x: turtle[0], y: turtle[1], z: Math.sin(count) * 5 }); // ctx.lineTo(turtle[0], turtle[1]); // ctx.stroke(); } function rg(st, ln, turtle) { st--; ln = ln / 2.6457; if (st > 0) { // ctx.strokeStyle = '#111'; rg(st, ln, turtle); rt(60); gl(st, ln, turtle); rt(120); gl(st, ln, turtle); lt(60); rg(st, ln, turtle); lt(120); rg(st, ln, turtle); rg(st, ln, turtle); lt(60); gl(st, ln, turtle); rt(60); } if (st == 0) { fd(ln); rt(60); fd(ln); rt(120); fd(ln); lt(60); fd(ln); lt(120); fd(ln); fd(ln); lt(60); fd(ln); rt(60) } } function gl(st, ln, turtle) { st--; ln = ln / 2.6457; if (st > 0) { // ctx.strokeStyle = '#555'; lt(60); rg(st, ln, turtle); rt(60); gl(st, ln, turtle); gl(st, ln, turtle); rt(120); gl(st, ln, turtle); rt(60); rg(st, ln, turtle); lt(120); rg(st, ln, turtle); lt(60); gl(st, ln, turtle); } if (st == 0) { lt(60); fd(ln); rt(60); fd(ln); fd(ln); rt(120); fd(ln); rt(60); fd(ln); lt(120); fd(ln); lt(60); fd(ln); } } } }