threejs 粒子系统和材质贴图
Posted qianbo_insist
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了threejs 粒子系统和材质贴图相关的知识,希望对你有一定的参考价值。
例子系统
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - buffer geometry custom attributes - particles</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body
color: #ffffff;
background-color: #000000;
margin: 0px;
overflow: hidden;
#info
position: absolute;
top: 0px;
width: 100%;
padding: 5px;
font-family: Monospace;
font-size: 13px;
text-align: center;
font-weight: bold;
a
color: #fff;
</style>
</head>
<body>
<div id="container"></div>
<script src="../build/three.js"></script>
<script type="x-shader/x-vertex" id="vertexshader">
attribute float size;
attribute vec3 customColor;
varying vec3 vColor;
void main()
vColor = customColor;
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
gl_PointSize = size * ( 300.0 / mvPosition.x );
gl_Position = projectionMatrix * mvPosition;
</script>
<script type="x-shader/x-fragment" id="fragmentshader">
uniform sampler2D texture;
varying vec3 vColor;
void main()
gl_FragColor = vec4( vColor, 1.0 );
gl_FragColor = gl_FragColor * texture2D( texture, gl_PointCoord );
</script>
<script>
var renderer, scene, camera, stats;
var particleSystem, uniforms, geometry;
var particles = 200;
var WIDTH = window.innerWidth;
var HEIGHT = window.innerHeight;
init();
animate();
function init()
camera = new THREE.PerspectiveCamera( 40, WIDTH / HEIGHT, 1, 10000 );
camera.position.z = 500;
scene = new THREE.Scene();
uniforms =
texture: value: new THREE.TextureLoader().load( "textures/sprites/spark1.png" )
;
var shaderMaterial = new THREE.ShaderMaterial(
uniforms: uniforms,
vertexShader: document.getElementById( 'vertexshader' ).textContent,
fragmentShader: document.getElementById( 'fragmentshader' ).textContent,
transparent: true
);
var radius = 400;
var geometry = new THREE.BufferGeometry();
var positions = new Float32Array( particles * 3 );
var colors = new Float32Array( particles * 3 );
var sizes = new Float32Array( particles );
for ( var i = 0, i3 = 0; i < particles; i ++, i3 += 3 )
positions[ i3 + 0 ] = ( Math.random() * 2 - 1 ) * radius;
positions[ i3 + 1 ] = ( Math.random() * 2 - 1 ) * radius;
positions[ i3 + 2 ] = 0;
colors[ i3 + 0 ] = 1;
colors[ i3 + 1 ] = 1;
colors[ i3 + 2 ] = 1;
sizes[ i ] = 10;
geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
geometry.addAttribute( 'customColor', new THREE.BufferAttribute( colors, 3 ) );
geometry.addAttribute( 'size', new THREE.BufferAttribute( sizes, 1 ) );
particleSystem = new THREE.Points( geometry, shaderMaterial );
scene.add( particleSystem );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( WIDTH, HEIGHT );
var container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
function onWindowResize()
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
function animate()
requestAnimationFrame( animate );
renderer.render( scene, camera );
</script>
</body>
</html>
材质贴图
高光网格材质 MeshPhongMaterial、标准网格材质MeshStandardMaterial、物理网格材质MeshPhysicalMaterial,次时代、PBR
次时代和 PBR
如果你想展示一个三维场景,比如一辆轿车,首先需要 3D 美术建模和烘培,然后程序员通过 Three.js 引擎加载解析显示出来。
对于3D美术来说烘培的时候有次时代、PBR 两种流程,这两种所谓的流程,对应的就是 Three.js 的高光网格材质 MeshPhongMaterial、基于物理的材质MeshStandardMaterial或MeshPhysicalMaterial。
对于程序员而言,如果你不想深入理解什么是高光网格材质,什么是基于物理的材质,每种材质对应的着色器代码应该如何编写,这种情况下,你只需要会选择使用哪种网格材质就可以。
如果3D美术烘培的时候是次时代流程,也就是贴图中你可以看到高光贴图 .specularMap,你需要选择高光网格材质 MeshPhongMaterial 渲染该模型,如果3D美术烘培的时候是PBR流程,也就是贴图中你可以看到金属度贴图 .metalnessMap 和粗糙度贴图 .roughnessMap,你需要选择基于物理的材质 MeshStandardMaterial或 MeshPhysicalMaterial 解析渲染。
质感
如果展示一个物体,需要很好的质感,比如轿车、珠宝等产品展示,可以让 3D 美术选择 PBR 流程烘培导出贴图,程序员使用基于物理的材质 MeshStandardMaterial 或 MeshPhysicalMaterial 进行解析渲染。
var scene, camera, renderer, envMap, phongMaterial, standardMaterial, params1, params2, faceNormalsHelper, vertexNormalsHelper;
init();
function init()
const assetPath = 'https://your path/';
envMap = new THREE.CubeTextureLoader().setPath(`$assetPathskybox3_`).load([
'px.jpg', 'nx.jpg',
'py.jpg', 'ny.jpg',
'pz.jpg', 'nz.jpg'
])
scene = new THREE.Scene();
scene.background = envMap;
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.set(0, 0, 10);
const ambient = new THREE.HemisphereLight(0xffffbb, 0x080820);
scene.add(ambient);
const light = new THREE.DirectionalLight(0xFFFFFF, 3);
light.position.set(0,4,4);
scene.add(light);
const albedoMap = new THREE.TextureLoader().load(`$assetPathTexturesCom_Orange_512_albedo.jpg`);
const normalMap = new THREE.TextureLoader().load(`$assetPathTexturesCom_Orange_512_normal.jpg`);
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
const controls = new THREE.OrbitControls( camera, renderer.domElement );
//Add meshes here
const geometry = new THREE.SphereGeometry(1, 30, 20);
phongMaterial = new THREE.MeshPhongMaterial();
standardMaterial = new THREE.MeshStandardMaterial();
const phongSphere = new THREE.Mesh( geometry, phongMaterial);
const standardSphere = new THREE.Mesh( geometry, standardMaterial);
for(let xPos=-3; xPos<3; xPos+=3)
const sphereA = phongSphere.clone();
sphereA.position.set(xPos, 1.5, 0);
scene.add(sphereA);
if (xPos==0)
faceNormalsHelper = new THREE.FaceNormalsHelper(sphereA, 0.25);
vertexNormalsHelper = new THREE.VertexNormalsHelper(sphereA, 0.25);
faceNormalsHelper.visible = false;
vertexNormalsHelper.visible = false;
scene.add(faceNormalsHelper);
scene.add(vertexNormalsHelper);
const sphereB = standardSphere.clone();
sphereB.position.set(xPos, -1.5, 0);
scene.add(sphereB);
params1 =
color: 0xffffff,
envMap: 'none',
reflectivity: 1,
albedoMap: 'none',
normalMap: 'none',
normalScale: 1,
shininess: 30,
facetted: false,
normals: 'none'
params2 =
color: 0xffffff,
emissive: 0,
envMap: 'none',
reflectivity: 1,
albedoMap: 'none',
normalMap: 'none',
normalScale: 1,
roughness: 0.5,
metalness: 0.5,
facetted: false
const gui = new dat.gui.GUI();
gui.add(params1, 'normals', ['none', 'face', 'vertex']).onChange(function(value)
faceNormalsHelper.visible = false;
vertexNormalsHelper.visible = false;
phongMaterial.wireframe = false;
switch(value)
case 'face':
faceNormalsHelper.visible = true;
phongMaterial.wireframe = true;
break;
case 'vertex':
vertexNormalsHelper.visible = true;
phongMaterial.wireframe = true;
break;
);
const f1 = gui.addFolder('Phong Material');
f1.addColor(params1, 'color').onChange( function() phongMaterial.color.set( params1.color ); );
f1.add(params1, 'envMap', ['none', 'cathedral']).onChange( function()
switch (params1.envMap)
case 'cathedral':
phongMaterial.envMap = envMap;
break;
default:
phongMaterial.envMap = null;
break;
phongMaterial.needsUpdate = true;
);
f1.add(params1, 'reflectivity').min(0).max(1).step(0.01).onChange( function() phongMaterial.reflectivity = params1.reflectivity );
f1.open();
f1.add(params1, 'albedoMap', ['none', 'orange']).onChange( function(value)
switch (value)
case 'orange':
phongMaterial.map = albedoMap;
break;
default:
phongMaterial.map = null;
break;
phongMaterial.needsUpdate = true;
);
f1.add(params1, 'normalMap', ['none', 'dimples']).onChange( function(value)
switch (value)
case 'dimples':
phongMaterial.normalMap = normalMap;
break;
default:
phongMaterial.normalMap = null;
break;
phongMaterial.needsUpdate = true;
);
f1.add(params1, 'normalScale').min(0).max(1).step(0.01).onChange( function(value) phongMaterial.normalScale.x = value;
phongMaterial.normalScale.y = value; );
f1.add(params1, 'shininess').min(0).max(255).step(0.5).onChange( 以上是关于threejs 粒子系统和材质贴图的主要内容,如果未能解决你的问题,请参考以下文章