Three.js中基础材质的特殊属性案例应用(MeshBasicMaterial)

案例

结果

在这里插入图片描述

分析

💡 熟悉所有材质的共有属性和基本材质的特殊属性

  1. 上述场景中包含着地面、三个物体(页面只显示一个,通过GUI来选择哪个物体显示)、光源、性能插件、GUI

创建场景、摄像机、渲染器

创建两个渲染器,因为wireframeLinecap(线框线段端点)、wireframeLinejoin(线框线段连接点)两个属性,webGLRenderer不支持该属性

//场景
var scene;
function initScene() {
    scene = new THREE.Scene();
}

//摄像机
var camera;
function initCamera() {
    camera = new THREE.PerspectiveCamera(45,window.innerWidth / window.innerHeight,0.1,1000);
    camera.position.set(-20,50,40);
    camera.lookAt(new THREE.Vector3(10,0,0));
    scene.add(camera);
}
//渲染器
var webGLRenderer,canvasRenderer,renderer;
function initRenderer() {
    webGLRenderer = new THREE.WebGLRenderer();
    webGLRenderer.setClearColor(new THREE.Color(0x000000));
    webGLRenderer.setSize(window.innerWidth,window.innerHeight);
    webGLRenderer.shadowMap.enabled = true;

    canvasRenderer = new THREE.CanvasRenderer();
    canvasRenderer.setSize(window.innerWidth,window.innerHeight);

    renderer = webGLRenderer;
    //将渲染的结果添加到 HTML 框架中的div元素中 
    document.getElementById("webgl-output").appendChild(renderer.domElement);
}

添加性能插件、光源、摄像机控制器

//初始化性能插件
var stats;
function initStats(){
    stats = new Stats();
    document.getElementById("webgl-output").appendChild(stats.domElement);
}
//光源
function initLight(){
    var ambientLight = new THREE.AmbientLight(0x0c0c0c);
    scene.add(ambientLight);

    var spotLight = new THREE.SpotLight("#ffffff");
    spotLight.position.set(-40,60,-10);
    spotLight.castShadow = true;
    spotLight.shadow.mapSize = new THREE.Vector2(1024,1024);
    spotLight.shadow.camera.far = 130;
    spotLight.shadow.camera.near = 40;
    scene.add(spotLight);
}
//用户交互插件 鼠标左键按住旋转,右键按住平移,滚轮缩放
var controls;
function initControls() {
    controls = new THREE.OrbitControls( camera, renderer.domElement );
    //是否可以缩放
    controls.enableZoom = true;
    //是否自动旋转
    controls.autoRotate = true;
    //设置相机距离原点的最远距离
    controls.minDistance  = 1;
    //设置相机距离原点的最远距离
    controls.maxDistance  = 200;
    //是否开启右键拖拽
    controls.enablePan = true;
}

添加物体对象

//模型
var axes,cube,plane,meshMaterial,sphere,ground,selectedMesh;
function initModels(){
    //坐标轴
    axes = new THREE.AxesHelper(50);
    scene.add(axes);
    //材质
    meshMaterial = new THREE.MeshBasicMaterial({
        color:0x7777ff,
        name: "Basic Material",
        flatShading: true,
    });
    //地面
    var groundGeometry = new THREE.PlaneGeometry(100,100,4,4);
    var groundMaterial = new THREE.MeshBasicMaterial({
        color:0x777777,
    })
    ground = new THREE.Mesh(groundGeometry,groundMaterial);
    ground.rotation.x = -Math.PI / 2;
    ground.position.y = -20;
    ground.receiveShadow = true;
    scene.add(ground);

    //立方体
    var cubeGeometry = new THREE.CubeGeometry(15,15,15);
    cube = new THREE.Mesh(cubeGeometry,meshMaterial);
    cube.position.set(0,3,2);
    cube.castShadow = true;
    scene.add(cube);

    //球
    var sphereGeometry = new THREE.SphereGeometry(14,20,20);
    sphere = new THREE.Mesh(sphereGeometry,meshMaterial);
    sphere.position.set(0,3,2);
    sphere.castShadow = true;
    // scene.add(sphere);

    //平面
    var planeGeometry = new THREE.PlaneGeometry(14,14,4,4);
    plane = new THREE.Mesh(planeGeometry,meshMaterial);
    plane.position = sphere.position;

    selectedMesh = cube;

}

设置GUI

var MBM,MaterialGui,gui;
function initMBM(){
    MBM = cube.material;
    MBM = new function(){
        this.id = cube.id;
        this.uuid = cube.uuid;
        this.name = "Basic Material";
        this.opacity = meshMaterial.opacity;
        this.transparent = meshMaterial.transparent;
        this.overdraw = meshMaterial.overdraw;
        this.visible = meshMaterial.visible;
        this.side = "FrontSide";
        this.colorWrite = meshMaterial.colorWrite;
        this.flatShading = meshMaterial.flatShading;
        this.premultipliedAlpha = meshMaterial.premultipliedAlpha;
        this.dithering = meshMaterial.dithering;
        this.shadowSide = "";
        this.vertexColors = "NoColors";
        this.fog = true;

        this.color = meshMaterial.color.getStyle();
        this.wireframe = meshMaterial.wireframe;
        this.wireframeLinewidth = 6.9;
        this.wireframeLinecap = "round";
        this.wireframeLinejoin = "round";

        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);
            }
        }
        this.selectedMesh = "cube";
    };
    gui = new dat.GUI();
    MaterialGui = gui.addFolder("THREE.Material");
    MaterialGui.add(MBM,'id');
    MaterialGui.add(MBM,'uuid');
    MaterialGui.add(MBM,'name');
    MaterialGui.add(MBM,'opacity',0,1,0.01).onChange(function (e){
        meshMaterial.opacity = e;
    });
    MaterialGui.add(MBM,'transparent').onChange(function (e){
        meshMaterial.transparent = e;
    });
    MaterialGui.add(MBM,'overdraw',0,1,0.01).onChange(function (e){
        meshMaterial.overdraw = e;
    });
    MaterialGui.add(MBM,'visible').onChange(function (e){
        meshMaterial.visible = e;
    });
    MaterialGui.add(MBM,'side',{FrontSide:0,BackSide:1,BothSides:2}).onChange(function (e){
        meshMaterial.side = parseInt(e);
    });
    MaterialGui.add(MBM,'colorWrite').onChange(function (e){
        meshMaterial.colorWrite = e;
    });
    MaterialGui.add(MBM,'flatShading').onChange(function (e){
        meshMaterial.flatShading = e;
        meshMaterial.needsUpdate = true;
    });
    MaterialGui.add(MBM,'premultipliedAlpha').onChange(function (e){
        meshMaterial.premultipliedAlpha = e;
    });
    MaterialGui.add(MBM,'dithering').onChange(function (e){
        meshMaterial.dithering = e;
    });
    MaterialGui.add(MBM,'shadowSide',{FrontSide:0,BackSide:1,BothSide:2}).onChange(function (e){
       meshMaterial.shadowSide = parseInt(e);
    });
    MaterialGui.add(MBM,'vertexColors', {NoColors: THREE.NoColors, FaceColors: THREE.FaceColors,
        VertexColors: THREE.VertexColors}).onChange(function (vertexColors) {
        meshMaterial.vertexColors = parseInt(vertexColors);
    });
    MaterialGui.add(MBM,'fog');
    //THREE.MeshBasicMaterialGUI
    var MeshBasicMaterialGUI = gui.addFolder("THREE.MeshBasicMaterial");

    MeshBasicMaterialGUI.addColor(MBM,'color').onChange(function (e) {
        meshMaterial.color.getStyle(e);
    });
    MeshBasicMaterialGUI.add(MBM,'wireframe').onChange(function (e) {
        meshMaterial.wireframe = e;
    });
    MeshBasicMaterialGUI.add(MBM,'wireframeLinewidth',0,20).onChange(function (e){
        meshMaterial.wireframeLinewidth = e;
    });
    MeshBasicMaterialGUI.add(MBM,'wireframeLinecap',['butt','round','square']).onChange(function (e) {
        meshMaterial.wireframeLinecap = e;
    });
    MeshBasicMaterialGUI.add(MBM,'wireframeLinejoin',['round','bevel','miter']).onChange(function (e) {
        meshMaterial.wireframeLinejoin = e;
    });

    gui.add(MBM,'switchRenderer');

    gui.add(MBM,'selectedMesh',['cube','sphere','plane']).onChange(function (e){
        scene.remove(cube);
        scene.remove(sphere);
        scene.remove(plane);

        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;
        }
    });
}

正确渲染以及窗口自适应函数

function render() {
    renderer.render(scene,camera);
}

function animate(){
    stats.update();

    selectedMesh.rotation.y +=0.02;
    render();

    requestAnimationFrame(animate);
}

//窗口自适应
function windowOnresize(){
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth,window.innerHeight);
}

完整代码

<!DOCTYPE html>
<html lang="zh">
<head>
	<meta charset="UTF-8">
	<meta name=viewport
		  content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no,minimal-ui">
	<script type="text/javascript" src="../libs/three/three.js"></script>
	<script type="text/javascript" src="../libs/three/controls/OrbitControls.js"></script>
	<script type="text/javascript" src="../libs/three/renderers/CanvasRenderer.js"></script>
	<script type="text/javascript" src="../libs/three/renderers/Projector.js"></script>
	<script type="text/javascript" src="../libs/util/dat.gui.js"></script>
	<script type="text/javascript" src="../libs/util/Stats.js"></script>
	<script type="text/javascript" src="js/MeshBasicMaterial.js"></script>
	<link rel="stylesheet" href="../css/default.css">
	<title>Title</title>
	<style></style>
	<script></script>
</head>
<body>
	<div id="webgl-output">

	</div>
	<script type="text/javascript">
		(function (){
			draw()
		})();
	</script>
</body>
</html>
//场景
var scene;
function initScene() {
    scene = new THREE.Scene();
}

//摄像机
var camera;
function initCamera() {
    camera = new THREE.PerspectiveCamera(45,window.innerWidth / window.innerHeight,0.1,1000);
    camera.position.set(-20,50,40);
    camera.lookAt(new THREE.Vector3(10,0,0));
    scene.add(camera);
}
//渲染器
var webGLRenderer,canvasRenderer,renderer;
function initRenderer() {
    webGLRenderer = new THREE.WebGLRenderer();
    webGLRenderer.setClearColor(new THREE.Color(0x000000));
    webGLRenderer.setSize(window.innerWidth,window.innerHeight);
    webGLRenderer.shadowMap.enabled = true;

    canvasRenderer = new THREE.CanvasRenderer();
    canvasRenderer.setSize(window.innerWidth,window.innerHeight);

    renderer = webGLRenderer;
    //将渲染的结果添加到 HTML 框架中的div元素中 
    document.getElementById("webgl-output").appendChild(renderer.domElement);
}
//初始化性能插件
var stats;
function initStats(){
    stats = new Stats();
    document.getElementById("webgl-output").appendChild(stats.domElement);
}
//光源
function initLight(){
    var ambientLight = new THREE.AmbientLight(0x0c0c0c);
    scene.add(ambientLight);

    var spotLight = new THREE.SpotLight("#ffffff");
    spotLight.position.set(-40,60,-10);
    spotLight.castShadow = true;
    spotLight.shadow.mapSize = new THREE.Vector2(1024,1024);
    spotLight.shadow.camera.far = 130;
    spotLight.shadow.camera.near = 40;
    scene.add(spotLight);
}

//模型
var axes,cube,plane,meshMaterial,sphere,ground,selectedMesh;
function initModels(){
    //坐标轴
    axes = new THREE.AxesHelper(50);
    scene.add(axes);
    //材质
    meshMaterial = new THREE.MeshBasicMaterial({
        color:0x7777ff,
        name: "Basic Material",
        flatShading: true,
    });
    //地面
    var groundGeometry = new THREE.PlaneGeometry(100,100,4,4);
    var groundMaterial = new THREE.MeshBasicMaterial({
        color:0x777777,
    })
    ground = new THREE.Mesh(groundGeometry,groundMaterial);
    ground.rotation.x = -Math.PI / 2;
    ground.position.y = -20;
    ground.receiveShadow = true;
    scene.add(ground);

    //立方体
    var cubeGeometry = new THREE.CubeGeometry(15,15,15);
    cube = new THREE.Mesh(cubeGeometry,meshMaterial);
    cube.position.set(0,3,2);
    cube.castShadow = true;
    scene.add(cube);

    //球
    var sphereGeometry = new THREE.SphereGeometry(14,20,20);
    sphere = new THREE.Mesh(sphereGeometry,meshMaterial);
    sphere.position.set(0,3,2);
    sphere.castShadow = true;
    // scene.add(sphere);

    //平面
    var planeGeometry = new THREE.PlaneGeometry(14,14,4,4);
    plane = new THREE.Mesh(planeGeometry,meshMaterial);
    plane.position = sphere.position;

    selectedMesh = cube;

}

//用户交互插件 鼠标左键按住旋转,右键按住平移,滚轮缩放
var controls;
function initControls() {

    controls = new THREE.OrbitControls( camera, renderer.domElement );

    // 如果使用animate方法时,将此函数删除
    //controls.addEventListener( 'change', render );
    // 使动画循环使用时阻尼或自转 意思是否有惯性
    controls.enableDamping = true;
    //动态阻尼系数 就是鼠标拖拽旋转灵敏度
    //controls.dampingFactor = 0.25;
    //是否可以缩放
    controls.enableZoom = true;
    //是否自动旋转
    controls.autoRotate = true;
    //设置相机距离原点的最远距离
    controls.minDistance  = 1;
    //设置相机距离原点的最远距离
    controls.maxDistance  = 200;
    //是否开启右键拖拽
    controls.enablePan = true;
}

function render() {
    renderer.render(scene,camera);
}

function animate(){
    stats.update();

    selectedMesh.rotation.y +=0.02;
    render();

    requestAnimationFrame(animate);
}

//窗口自适应
function windowOnresize(){
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth,window.innerHeight);
}

var MBM,MaterialGui,gui;
function initMBM(){
    MBM = cube.material;
    MBM = new function(){
        this.id = cube.id;
        this.uuid = cube.uuid;
        this.name = "Basic Material";
        this.opacity = meshMaterial.opacity;
        this.transparent = meshMaterial.transparent;
        this.overdraw = meshMaterial.overdraw;
        this.visible = meshMaterial.visible;
        this.side = "FrontSide";
        this.colorWrite = meshMaterial.colorWrite;
        this.flatShading = meshMaterial.flatShading;
        this.premultipliedAlpha = meshMaterial.premultipliedAlpha;
        this.dithering = meshMaterial.dithering;
        this.shadowSide = "";
        this.vertexColors = "NoColors";
        this.fog = true;

        this.color = meshMaterial.color.getStyle();
        this.wireframe = meshMaterial.wireframe;
        this.wireframeLinewidth = 6.9;
        this.wireframeLinecap = "round";
        this.wireframeLinejoin = "round";

        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);
            }
        }
        this.selectedMesh = "cube";
    };
    gui = new dat.GUI();
    MaterialGui = gui.addFolder("THREE.Material");
    MaterialGui.add(MBM,'id');
    MaterialGui.add(MBM,'uuid');
    MaterialGui.add(MBM,'name');
    MaterialGui.add(MBM,'opacity',0,1,0.01).onChange(function (e){
        meshMaterial.opacity = e;
    });
    MaterialGui.add(MBM,'transparent').onChange(function (e){
        meshMaterial.transparent = e;
    });
    MaterialGui.add(MBM,'overdraw',0,1,0.01).onChange(function (e){
        meshMaterial.overdraw = e;
    });
    MaterialGui.add(MBM,'visible').onChange(function (e){
        meshMaterial.visible = e;
    });
    MaterialGui.add(MBM,'side',{FrontSide:0,BackSide:1,BothSides:2}).onChange(function (e){
        meshMaterial.side = parseInt(e);
    });
    MaterialGui.add(MBM,'colorWrite').onChange(function (e){
        meshMaterial.colorWrite = e;
    });
    MaterialGui.add(MBM,'flatShading').onChange(function (e){
        meshMaterial.flatShading = e;
        meshMaterial.needsUpdate = true;
    });
    MaterialGui.add(MBM,'premultipliedAlpha').onChange(function (e){
        meshMaterial.premultipliedAlpha = e;
    });
    MaterialGui.add(MBM,'dithering').onChange(function (e){
        meshMaterial.dithering = e;
    });
    MaterialGui.add(MBM,'shadowSide',{FrontSide:0,BackSide:1,BothSide:2}).onChange(function (e){
       meshMaterial.shadowSide = parseInt(e);
    });
    MaterialGui.add(MBM,'vertexColors', {NoColors: THREE.NoColors, FaceColors: THREE.FaceColors,
        VertexColors: THREE.VertexColors}).onChange(function (vertexColors) {
        meshMaterial.vertexColors = parseInt(vertexColors);
    });
    MaterialGui.add(MBM,'fog');
    //THREE.MeshBasicMaterialGUI
    var MeshBasicMaterialGUI = gui.addFolder("THREE.MeshBasicMaterial");

    MeshBasicMaterialGUI.addColor(MBM,'color').onChange(function (e) {
        meshMaterial.color.getStyle(e);
    });
    MeshBasicMaterialGUI.add(MBM,'wireframe').onChange(function (e) {
        meshMaterial.wireframe = e;
    });
    MeshBasicMaterialGUI.add(MBM,'wireframeLinewidth',0,20).onChange(function (e){
        meshMaterial.wireframeLinewidth = e;
    });
    MeshBasicMaterialGUI.add(MBM,'wireframeLinecap',['butt','round','square']).onChange(function (e) {
        meshMaterial.wireframeLinecap = e;
    });
    MeshBasicMaterialGUI.add(MBM,'wireframeLinejoin',['round','bevel','miter']).onChange(function (e) {
        meshMaterial.wireframeLinejoin = e;
    });

    gui.add(MBM,'switchRenderer');

    gui.add(MBM,'selectedMesh',['cube','sphere','plane']).onChange(function (e){
        scene.remove(cube);
        scene.remove(sphere);
        scene.remove(plane);

        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;
        }
    });
    // gui.domElement.style.position = 'absolute';
    // gui.domElement.style.right = "300px";
}


function draw(){
    initScene();
    initCamera();
    initRenderer();
    initStats();
    initLight();
    initModels();
    initControls();
    initMBM();

    animate();
    window.onresize = windowOnresize;
}

注意事项

💡这个例子里可以设置side属性,通过这个属性可以指定THREE.Geometry对象的哪个面应用材质。

  • 可以通过选择plane(平面)网格验证该属性。
  • side属性设置为FrontSide或者BackSide时,平面旋转时会有一半的时间看不见。
  • side属性设置为BothSides时,这个平面始终都能看见(因为几何体两面都有材质)。
  • 设置为BothSides时,由于两面都有材质,所以渲染需要做更多的工作,对场景的性能会有影响。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值