基于上一篇,创建一个正二十面体模型添加到场景中做材质和光照效果试验。
半透明效果
更改场景中的球体材质对象构造函数THREE.MeshLambertMaterial()的参数,添加opacity
和transparent
属性,opacity
的值是0~1
之间,transparent
表示是否开启透明度效果, 默认是false
表示透明度设置不起作用,值设置为true
,网格模型就会呈现透明的效果,使用下面的代码替换原来的球体网格模型的材质, 刷新浏览器,通过鼠标旋转操作场景,可以看到半透明的球体和立方体颜色叠加融合的效果。材质对象的一些属性可以在构造函数参数中设置,也可以访问材质对象的属性设置。
let material = new THREE.MeshNormalMaterial(
{
// 颜色
color:0xff0000,
}
);
material.opacity = 0.5;
material.transparent = true;
material.wireframe = false;
添加高光效果
处在光照条件下的物体表面会发生光的反射现象,不同的表面粗糙度不同,宏观上来看对光的综合反射效果,可以使用两个反射模型来概括,一个是漫反射,一个是镜面反射, 使用渲染软件或绘画的时候都会提到一个高光的概念,其实说的就是物理光学中镜面反射产生的局部高亮效果。实际生活中的物体都是镜面反射和漫反射同时存在,只是哪个占得比例大而已, 比如树皮的表面更多以漫反射为主基本没有体现出镜面反射,比如一辆轿车的外表面在阳光下你会看到局部高亮的效果,这很简单汽车表面经过抛光等表面处理粗糙度非常低, 镜面反射效果明显,对于three.js而言漫反射、镜面反射分别对应两个构造函数MeshLambertMaterial()、MeshPhongMaterial()。
var sphereMaterial = new THREE.MeshPhongMaterial({
color:0x00aaff,
specular:0x4488ee,
shininess:12
});
material = sphereMaterial;
常用的材质效果
材质类型 | 功能 |
---|---|
MeshBasicMaterial | 基础网格材质,不受光照影响的材质 |
MeshLambertMaterial | Lambert网格材质,与光照有反应,漫反射 |
MeshPhongMaterial | 高光Phong材质,与光照有反应 |
MeshStandardMaterial | PBR物理材质,相比较高光Phong材质可以更好的模拟金属、玻璃等效果 |
光照效果设置
// 点光源
var point = new THREE.PointLight(0xffffff);
// 点光源位置
point.position.set(400, 200, 300);
// 点光源添加到场景中
this.scene.add(point);
// 环境光
var ambient = new THREE.AmbientLight(0x444444);
this.scene.add(ambient);
常见光源类型
光源 | 简介 |
---|---|
AmbientLight | 环境光 |
PointLight | 点光源 |
DirectionalLight | 平行光,比如太阳光 |
SpotLight | 聚光源 |
完整代码:
<template>
<div class="geometry_02">
<button @click="upPage">返回</button>
<div id="container"></div>
</div>
</template>
<script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
export default {
data() {
return {
// 相机
camera: null,
// 场景
scene: null,
// 渲染器
renderer: null,
// 材质对象
mesh: null,
// 控件
controls: null,
};
},
mounted() {
this.init();
this.animate();
},
methods: {
//初始化
init: function () {
// 创建场景对象Scene
this.scene = new THREE.Scene();
// 网格模型添加到场景中
// 正二十面体
var geometry = new THREE.IcosahedronGeometry(50);
let material = null;
// // 1 点材质
// material = new THREE.PointsMaterial({
// color: 0x0000ff, //颜色
// size: 3, //点渲染尺寸
// });
// //点模型对象 参数:几何体 点材质
// var pt = new THREE.Points(geometry, material);
// this.scene.add(pt); //网格模型添加到场景中
// // 2 直线基础材质对象
// material = new THREE.LineBasicMaterial({
// color: 0x0000ff
// });
// var line = new THREE.Line(geometry, material); //线模型对象
// this.scene.add(line); //点模型添加到场景中
// // 3 虚线材质对象:产生虚线效果
// material = new THREE.LineDashedMaterial({
// color: 0x0000ff,
// dashSize: 10,//显示线段的大小。默认为3。
// gapSize: 5,//间隙的大小。默认为1
// });
// var line = new THREE.Line(geometry, material);
// // computeLineDistances方法 计算LineDashedMaterial所需的距离数组
// line.computeLineDistances();
// this.scene.add(line);
// // 4 网格材质-将法线向量映射到 RGB 颜色的材质。
// material = new THREE.MeshNormalMaterial();
// material.color = 0xff0000;
// material.opacity = 0.5;
// material.transparent = true;
// material.wireframe = false;
// // 5 网格材质-高光Phong材质,与光照有反应
// material = new THREE.MeshPhongMaterial({
// color:0x00aaff,
// specular:0x4488ee,
// shininess:12
// });
// // 6 网格材质-Lambert网格材质,与光照有反应,漫反射
// material = new THREE.MeshLambertMaterial({
// color: 0x00aaff,
// });
// // 7 网格材质-基础网格材质,不受光照影响的材质
// material = new THREE.MeshBasicMaterial({
// color: 0x0000ff,
// })
// // 8 按深度绘制几何图形的材料。深度基于相机近平面和远平面。白色最近,黑色最远
// material = new THREE.MeshDepthMaterial({})
// // 9 在内部用于使用PointLight实现阴影映射
// const texture = new THREE.CanvasTexture( this.generateTexture() );
// texture.magFilter = THREE.NearestFilter;
// texture.wrapT = THREE.RepeatWrapping;
// texture.wrapS = THREE.RepeatWrapping;
// texture.repeat.set( 1, 4.5 );
// material = new THREE.MeshPhongMaterial( {
// side: THREE.DoubleSide,
// alphaMap: texture,
// alphaTest: 0.5
// } );
// let sphere = new THREE.Mesh( geometry, material );
// sphere.castShadow = true;
// sphere.receiveShadow = true;
// const distanceMaterial = new THREE.MeshDistanceMaterial( {
// alphaMap: material.alphaMap,
// alphaTest: material.alphaTest
// } );
// sphere.customDistanceMaterial = distanceMaterial;
// // 10 不响应光照,因为 matcap 图像文件对烘焙光照进行编码。它会将阴影投射到接收阴影的对象上(并且阴影剪切有效),但它不会自身阴影或接收阴影。
// material = new THREE.MeshMatcapMaterial({})
// // 11 MeshStandardMaterial PBR物理材质,相比较高光Phong材质可以更好的模拟金属、玻璃等效果,使用 Metallic-Roughness 工作流程
// material = new THREE.MeshStandardMaterial(
// {
// color:0xCAA83F
// }
// );
// // 12 MeshStandardMaterial 的扩展,提供更高级的基于物理的渲染属性。opacity的一个限制是高度透明的材料反射率较低。基于物理的.transmission 为玻璃等薄而透明的表面提供了更逼真的选择。非金属材料的反射率更灵活。
// const numberOfSphersPerSide = 2;
// const stepSize = 1.0 / numberOfSphersPerSide;
// for ( let alpha = 0; alpha <= 1.0; alpha += stepSize ) {
// for ( let beta = 0; beta <= 1.0; beta += stepSize ) {
// for ( let gamma = 0; gamma <= 1.0; gamma += stepSize ) {
// const diffuseColor = new THREE.Color().setHSL( alpha, 0.5, 0.25 );
// material = new THREE.MeshPhysicalMaterial( {
// color: diffuseColor,
// metalness: 0,
// roughness: 0.5,
// clearcoat: 1.0 - alpha,
// clearcoatRoughness: 1.0 - beta,
// reflectivity: 1.0 - gamma
// } );
// const mesh = new THREE.Mesh( geometry, material );
// mesh.position.x = alpha * 400 - 200;
// mesh.position.y = beta * 400 - 200;
// mesh.position.z = gamma * 400 - 200;
// this.scene.add( mesh );
// }
// }
// }
// 13 MeshToonMaterial 卡通着色的材料
// material = new THREE.MeshToonMaterial(
// {
// color:0x05588F
// }
// );
// // 14 阴影材质 这种材质可以接收阴影,但除此之外是完全透明的
// material = new THREE.ShadowMaterial();
// material.opacity = 0.5;
// const plane = new THREE.Mesh( geometry, material );
// plane.position.y = -200;
// plane.receiveShadow = true;
// this.scene.add( plane );
const map = new THREE.TextureLoader().load('../../../assets/img/ag-4.png');
material = new THREE.SpriteMaterial( { map: map, color: 0xffffff } );
const sprite = new THREE.Sprite( material );
sprite.scale.set(200, 200, 1)
this.scene.add( sprite );
this.mesh = new THREE.Mesh(geometry, material);
this.mesh.position.set(0,0,0);
this.scene.add(this.mesh);
// 点光源
var point = new THREE.PointLight(0xffffff);
// 点光源位置
point.position.set(200, 300, 300);
//
// point.add( sphere );
// 点光源添加到场景中
this.scene.add(point);
// 环境光
var ambient = new THREE.AmbientLight(0x444444);
this.scene.add(ambient);
// 相机设置
let container = document.getElementById("container");
// 窗口宽度
let width = window.innerWidth;
// 窗口高度
let height = window.innerHeight;
// 窗口宽高比
let k = width / height;
// 三维场景显示范围控制系数,系数越大,显示的范围越大
let s = 100;
this.camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 0.1, 1000);
// 透视相机(视场角度,长宽比,近面,远面)
// this.camera = new THREE.PerspectiveCamera(70, container.clientWidth / container.clientHeight, 0.01, 10);
this.camera.position.set(200, 300, 200);
this.camera.lookAt(this.scene.position);
// 创建渲染器对象
this.renderer = new THREE.WebGLRenderer({ antialias: true });
this.renderer.setSize(container.clientWidth, container.clientHeight);
this.renderer.setClearColor(0x000, 1);
container.appendChild(this.renderer.domElement);
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
},
// 动画
animate: function () {
requestAnimationFrame(this.animate);
this.renderer.render(this.scene, this.camera);
},
//
generateTexture: function() {
const canvas = document.createElement( 'canvas' );
canvas.width = 2;
canvas.height = 2;
const context = canvas.getContext( '2d' );
context.fillStyle = 'white';
context.fillRect( 0, 1, 2, 1 );
return canvas;
},
upPage() {
this.$router.go(-1);
},
},
};
</script>
<style>
#container {
position: absolute;
width: 100%;
height: 100%;
}
</style>