我觉得我可能不得不介绍着色器,但是我对Three.js的了解还不够. 解决方案基于uvs的简单渐变着色器: var scene = new THREE.Scene();var camera = new THREE.PerspectiveCamera(60, 1, 1, 1000);camera.position.set(13, 25, 38);camera.lookAt(scene.position);var renderer = new THREE.WebGLRenderer({ antialias: true});var canvas = renderer.domElementdocument.body.appendChild(canvas);var controls = new THREE.OrbitControls(camera, renderer.domElement);var geometry = new THREE.CylinderBufferGeometry(2, 5, 20, 32, 1, true);var material = new THREE.ShaderMaterial({ uniforms: { color1: { value: new THREE.Color("red") }, color2: { value: new THREE.Color("purple") } }, vertexShader: ` varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0); } `, fragmentShader: ` uniform vec3 color1; uniform vec3 color2; varying vec2 vUv; void main() { gl_FragColor = vec4(mix(color1, color2, vUv.y), 1.0); } `, wireframe: true});var mesh = new THREE.Mesh(geometry, material);scene.add(mesh);render();function resize(renderer) { const canvas = renderer.domElement; const width = canvas.clientWidth; const height = canvas.clientHeight; const needResize = canvas.width !== width || canvas.height !== height; if (needResize) { renderer.setSize(width, height, false); } return needResize;}function render() { if (resize(renderer)) { camera.aspect = canvas.clientWidth / canvas.clientHeight; camera.updateProjectionMatrix(); } renderer.render(scene, camera); requestAnimationFrame(render);} html,body { height: 100%; margin: 0; overflow: hidden;}canvas { width: 100%; height: 100%; display; block;} <script src="https://threejs.org/build/three.min.js"></script><script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>基于坐标的简单渐变着色器: var scene = new THREE.Scene();var camera = new THREE.PerspectiveCamera(60, 1, 1, 1000);camera.position.set(13, 25, 38);camera.lookAt(scene.position);var renderer = new THREE.WebGLRenderer({ antialias: true});var canvas = renderer.domElementdocument.body.appendChild(canvas);var controls = new THREE.OrbitControls(camera, renderer.domElement);var geometry = new THREE.CylinderBufferGeometry(2, 5, 20, 16, 4, true);geometry.computeBoundingBox();var material = new THREE.ShaderMaterial({ uniforms: { color1: { value: new THREE.Color("red") }, color2: { value: new THREE.Color("purple") }, bboxMin: { value: geometry.boundingBox.min }, bboxMax: { value: geometry.boundingBox.max } }, vertexShader: ` uniform vec3 bboxMin; uniform vec3 bboxMax; varying vec2 vUv; void main() { vUv.y = (position.y - bboxMin.y) / (bboxMax.y - bboxMin.y); gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0); } `, fragmentShader: ` uniform vec3 color1; uniform vec3 color2; varying vec2 vUv; void main() { gl_FragColor = vec4(mix(color1, color2, vUv.y), 1.0); } `, wireframe: true});var mesh = new THREE.Mesh(geometry, material);scene.add(mesh);render();function resize(renderer) { const canvas = renderer.domElement; const width = canvas.clientWidth; const height = canvas.clientHeight; const needResize = canvas.width !== width || canvas.height !== height; if (needResize) { renderer.setSize(width, height, false); } return needResize;}function render() { if (resize(renderer)) { camera.aspect = canvas.clientWidth / canvas.clientHeight; camera.updateProjectionMatrix(); } renderer.render(scene, camera); requestAnimationFrame(render);} html,body { height: 100%; margin: 0; overflow: hidden;}canvas { width: 100%; height: 100%; display: block;} <script src="https://threejs.org/build/three.min.js"></script><script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>具有顶点颜色的渐变: var scene = new THREE.Scene();var camera = new THREE.PerspectiveCamera(60, 1, 1, 1000);camera.position.set(0, 0, 10);var renderer = new THREE.WebGLRenderer({ antialias: true});var canvas = renderer.domElementdocument.body.appendChild(canvas);var geom = new THREE.TorusKnotGeometry(2.5, .5, 100, 16);var rev = true;var cols = [{ stop: 0, color: new THREE.Color(0xf7b000)}, { stop: .25, color: new THREE.Color(0xdd0080)}, { stop: .5, color: new THREE.Color(0x622b85)}, { stop: .75, color: new THREE.Color(0x007dae)}, { stop: 1, color: new THREE.Color(0x77c8db)}];setGradient(geom, cols, 'z', rev);function setGradient(geometry, colors, axis, reverse) { geometry.computeBoundingBox(); var bbox = geometry.boundingBox; var size = new THREE.Vector3().subVectors(bbox.max, bbox.min); var vertexIndices = ['a', 'b', 'c']; var face, vertex, normalized = new THREE.Vector3(), normalizedAxis = 0; for (var c = 0; c < colors.length - 1; c++) { var colorDiff = colors[c + 1].stop - colors[c].stop; for (var i = 0; i < geometry.faces.length; i++) { face = geometry.faces[i]; for (var v = 0; v < 3; v++) { vertex = geometry.vertices[face[vertexIndices[v]]]; normalizedAxis = normalized.subVectors(vertex, bbox.min).divide(size)[axis]; if (reverse) { normalizedAxis = 1 - normalizedAxis; } if (normalizedAxis >= colors[c].stop && normalizedAxis <= colors[c + 1].stop) { var localNormalizedAxis = (normalizedAxis - colors[c].stop) / colorDiff; face.vertexColors[v] = colors[c].color.clone().lerp(colors[c + 1].color, localNormalizedAxis); } } } }}var mat = new THREE.MeshBasicMaterial({ vertexColors: THREE.VertexColors, wireframe: true});var obj = new THREE.Mesh(geom, mat);scene.add(obj);render();function resize(renderer) { const canvas = renderer.domElement; const width = canvas.clientWidth; const height = canvas.clientHeight; const needResize = canvas.width !== width || canvas.height !== height; if (needResize) { renderer.setSize(width, height, false); } return needResize;}function render() { if (resize(renderer)) { camera.aspect = canvas.clientWidth / canvas.clientHeight; camera.updateProjectionMatrix(); } renderer.render(scene, camera); obj.rotation.y += .01; requestAnimationFrame(render);} html,body { height: 100%; margin: 0; overflow: hidden;}canvas { width: 100%; height: 100%; display; block;} <script src="https://threejs.org/build/three.min.js"></script>实际上,取决于您使用哪种方法:着色器,顶点颜色,纹理等.I have an STL file loaded into my scene with a single colour applied to a phong materialI'd like a way of applying two colours to this mesh's material with a gradient effect applied on the Z axis a like the example below.Gradient Vase]1I have a feeling I may have to introduce shaders but I've not gotten this far with three.js. 解决方案 Simple gradient shader, based on uvs:var scene = new THREE.Scene();var camera = new THREE.PerspectiveCamera(60, 1, 1, 1000);camera.position.set(13, 25, 38);camera.lookAt(scene.position);var renderer = new THREE.WebGLRenderer({ antialias: true});var canvas = renderer.domElementdocument.body.appendChild(canvas);var controls = new THREE.OrbitControls(camera, renderer.domElement);var geometry = new THREE.CylinderBufferGeometry(2, 5, 20, 32, 1, true);var material = new THREE.ShaderMaterial({ uniforms: { color1: { value: new THREE.Color("red") }, color2: { value: new THREE.Color("purple") } }, vertexShader: ` varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0); } `, fragmentShader: ` uniform vec3 color1; uniform vec3 color2; varying vec2 vUv; void main() { gl_FragColor = vec4(mix(color1, color2, vUv.y), 1.0); } `, wireframe: true});var mesh = new THREE.Mesh(geometry, material);scene.add(mesh);render();function resize(renderer) { const canvas = renderer.domElement; const width = canvas.clientWidth; const height = canvas.clientHeight; const needResize = canvas.width !== width || canvas.height !== height; if (needResize) { renderer.setSize(width, height, false); } return needResize;}function render() { if (resize(renderer)) { camera.aspect = canvas.clientWidth / canvas.clientHeight; camera.updateProjectionMatrix(); } renderer.render(scene, camera); requestAnimationFrame(render);}html,body { height: 100%; margin: 0; overflow: hidden;}canvas { width: 100%; height: 100%; display; block;}<script src="https://threejs.org/build/three.min.js"></script><script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>Simple gradient shader, based on coordinates:var scene = new THREE.Scene();var camera = new THREE.PerspectiveCamera(60, 1, 1, 1000);camera.position.set(13, 25, 38);camera.lookAt(scene.position);var renderer = new THREE.WebGLRenderer({ antialias: true});var canvas = renderer.domElementdocument.body.appendChild(canvas);var controls = new THREE.OrbitControls(camera, renderer.domElement);var geometry = new THREE.CylinderBufferGeometry(2, 5, 20, 16, 4, true);geometry.computeBoundingBox();var material = new THREE.ShaderMaterial({ uniforms: { color1: { value: new THREE.Color("red") }, color2: { value: new THREE.Color("purple") }, bboxMin: { value: geometry.boundingBox.min }, bboxMax: { value: geometry.boundingBox.max } }, vertexShader: ` uniform vec3 bboxMin; uniform vec3 bboxMax; varying vec2 vUv; void main() { vUv.y = (position.y - bboxMin.y) / (bboxMax.y - bboxMin.y); gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0); } `, fragmentShader: ` uniform vec3 color1; uniform vec3 color2; varying vec2 vUv; void main() { gl_FragColor = vec4(mix(color1, color2, vUv.y), 1.0); } `, wireframe: true});var mesh = new THREE.Mesh(geometry, material);scene.add(mesh);render();function resize(renderer) { const canvas = renderer.domElement; const width = canvas.clientWidth; const height = canvas.clientHeight; const needResize = canvas.width !== width || canvas.height !== height; if (needResize) { renderer.setSize(width, height, false); } return needResize;}function render() { if (resize(renderer)) { camera.aspect = canvas.clientWidth / canvas.clientHeight; camera.updateProjectionMatrix(); } renderer.render(scene, camera); requestAnimationFrame(render);}html,body { height: 100%; margin: 0; overflow: hidden;}canvas { width: 100%; height: 100%; display: block;}<script src="https://threejs.org/build/three.min.js"></script><script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>Gradient with vertex colours:var scene = new THREE.Scene();var camera = new THREE.PerspectiveCamera(60, 1, 1, 1000);camera.position.set(0, 0, 10);var renderer = new THREE.WebGLRenderer({ antialias: true});var canvas = renderer.domElementdocument.body.appendChild(canvas);var geom = new THREE.TorusKnotGeometry(2.5, .5, 100, 16);var rev = true;var cols = [{ stop: 0, color: new THREE.Color(0xf7b000)}, { stop: .25, color: new THREE.Color(0xdd0080)}, { stop: .5, color: new THREE.Color(0x622b85)}, { stop: .75, color: new THREE.Color(0x007dae)}, { stop: 1, color: new THREE.Color(0x77c8db)}];setGradient(geom, cols, 'z', rev);function setGradient(geometry, colors, axis, reverse) { geometry.computeBoundingBox(); var bbox = geometry.boundingBox; var size = new THREE.Vector3().subVectors(bbox.max, bbox.min); var vertexIndices = ['a', 'b', 'c']; var face, vertex, normalized = new THREE.Vector3(), normalizedAxis = 0; for (var c = 0; c < colors.length - 1; c++) { var colorDiff = colors[c + 1].stop - colors[c].stop; for (var i = 0; i < geometry.faces.length; i++) { face = geometry.faces[i]; for (var v = 0; v < 3; v++) { vertex = geometry.vertices[face[vertexIndices[v]]]; normalizedAxis = normalized.subVectors(vertex, bbox.min).divide(size)[axis]; if (reverse) { normalizedAxis = 1 - normalizedAxis; } if (normalizedAxis >= colors[c].stop && normalizedAxis <= colors[c + 1].stop) { var localNormalizedAxis = (normalizedAxis - colors[c].stop) / colorDiff; face.vertexColors[v] = colors[c].color.clone().lerp(colors[c + 1].color, localNormalizedAxis); } } } }}var mat = new THREE.MeshBasicMaterial({ vertexColors: THREE.VertexColors, wireframe: true});var obj = new THREE.Mesh(geom, mat);scene.add(obj);render();function resize(renderer) { const canvas = renderer.domElement; const width = canvas.clientWidth; const height = canvas.clientHeight; const needResize = canvas.width !== width || canvas.height !== height; if (needResize) { renderer.setSize(width, height, false); } return needResize;}function render() { if (resize(renderer)) { camera.aspect = canvas.clientWidth / canvas.clientHeight; camera.updateProjectionMatrix(); } renderer.render(scene, camera); obj.rotation.y += .01; requestAnimationFrame(render);}html,body { height: 100%; margin: 0; overflow: hidden;}canvas { width: 100%; height: 100%; display; block;}<script src="https://threejs.org/build/three.min.js"></script>Actually, it's up to you which approach to use: shaders, vertex colours, textures etc. 这篇关于将颜色渐变应用于网格上的材质-three.js的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
08-23 16:48