threejs学习笔记-03

11.SphereGeometry球体与球体属性控制

<!DOCTYPE html>
<html>

<head>
    <title>threejs</title>
    <meta charset="UTF-8" />
    <style>
        body {
    
    
            margin: 0;
            overflow: hidden;
        }
    </style>

</head>

<body>
    <div id="webgl-output">

    </div>

    <div id="myStats"></div>

    <script type="module">
        import * as THREE from "../../libs/build/three.module.js"
        import {
    
     dat } from "../../libs/dat.gui/dat.gui.js"
        import {
    
     GLTFLoader } from "../../libs/three.js/jsm/loaders/GLTFLoader.js"
        import {
    
     OrbitControls } from "../../libs/three.js/jsm/controls/OrbitControls.js"


        var scene = new THREE.Scene();
        var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

        var render = new THREE.WebGLRenderer();
        render.setClearColor(new THREE.Color(0x000000));
        render.setSize(window.innerWidth, window.innerHeight);
        render.shadowMap.enabled = true;

        document.getElementById("webgl-output").appendChild(render.domElement);

        var axes = new THREE.AxesHelper(50);
        scene.add(axes);

        //loadModel();


        var planeGeometry = new THREE.PlaneGeometry(100, 100);
        var planeMaterial = new THREE.MeshLambertMaterial({
    
     color: 0xAAAAAA });
        var plane = new THREE.Mesh(planeGeometry, planeMaterial);

        plane.rotation.x = -0.5 * Math.PI;
        plane.position.set(15, 0, 0);
        plane.receiveShadow = true;

        //scene.add(plane);

        camera.position.x = -5;
        camera.position.y = 5;
        camera.position.z = 5;
        camera.lookAt(scene.position);
        scene.add(camera);

        var spotLight = new THREE.SpotLight(0xFFFFFF);
        spotLight.position.set(-60, 30, -65);
        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 ambienLight = new THREE.AmbientLight(0xcccccc);
        // scene.add(ambienLight); 


        const directionalLight = new THREE.DirectionalLight(0xffffff, 2);
        directionalLight.castShadow = true;
        directionalLight.shadow.mapSize.width = 2048;
        directionalLight.shadow.mapSize.height = 2048;
        directionalLight.position.set(20, 20, 20);
        scene.add(directionalLight);

        //下面介绍SphereGeometry球体,其非常灵活,可以用来创建所有和球体相关的集合
        //它有7个构造参数,第一个表示球体半径默认为1,第二个构造参数表示水平分段数默认为32最小为3,第三个表示垂直分段数默认值为16最小为2
        //第四个表示水平起始角度默认值为0,第五个表示水平扫描角度的大小默认值为2π,第六个表示垂直起始角度,默认值为0,第七个构造参数表示垂直扫描角度大小默认为π
        //看文字很难理解 我们还是用dat.GUI库来测试方便理解,同时让图形的wireframe属性为真,让图形渲染成线框更方便我理解
        var sphereGeo = new THREE.SphereGeometry();
        var sphereMat = new THREE.MeshBasicMaterial({
    
     color: 0xffffff, wireframe: true });
        var sphere = new THREE.Mesh(sphereGeo, sphereMat);
        scene.add(sphere);

        var ctrlObj = {
    
    //稳了更好的了解点球的属性,我们依然和之前一样通过dat.GUI来进行属性的控制
            radius: 3,
            widthSegments: 32,
            heightSegments: 16,
            phiStart: 0,
            phiLength: Math.PI * 2.0,
            thetaStart: 0,
            thetaLength: Math.PI,
        };

        var ctrl = new dat.GUI();//创建dat.GUI对象
        var sphereFolder = ctrl.addFolder("sphere");//通过该对象创建一个分组
        //这里注意不能直接修改球体的半径!!!需要在回调函数中删除原来的图形,再新建一个修改参数后的平面并添加到场景中就可以了!
        sphereFolder.add(ctrlObj, "radius", 1, 100).onChange(function (e) {
    
    
            scene.remove(sphere);
            sphereGeo = new THREE.SphereGeometry(ctrlObj.radius, ctrlObj.widthSegments, ctrlObj.heightSegments, ctrlObj.phiStart, ctrlObj.phiLength, ctrlObj.thetaStart, ctrlObj.thetaLength);
            sphere = new THREE.Mesh(sphereGeo, sphereMat);
            scene.add(sphere);
        });
        sphereFolder.add(ctrlObj, "widthSegments", 3, 100).onChange(function (e) {
    
    
            scene.remove(sphere);
            sphereGeo = new THREE.SphereGeometry(ctrlObj.radius, ctrlObj.widthSegments, ctrlObj.heightSegments, ctrlObj.phiStart, ctrlObj.phiLength, ctrlObj.thetaStart, ctrlObj.thetaLength);
            sphere = new THREE.Mesh(sphereGeo, sphereMat);
            scene.add(sphere);
        });
        sphereFolder.add(ctrlObj, "heightSegments", 2, 100).onChange(function (e) {
    
    
            scene.remove(sphere);
            sphereGeo = new THREE.SphereGeometry(ctrlObj.radius, ctrlObj.widthSegments, ctrlObj.heightSegments, ctrlObj.phiStart, ctrlObj.phiLength, ctrlObj.thetaStart, ctrlObj.thetaLength);
            sphere = new THREE.Mesh(sphereGeo, sphereMat);
            scene.add(sphere);
        });
        sphereFolder.add(ctrlObj, "phiStart", 0, Math.PI * 2.0).onChange(function (e) {
    
    
            scene.remove(sphere);
            sphereGeo = new THREE.SphereGeometry(ctrlObj.radius, ctrlObj.widthSegments, ctrlObj.heightSegments, ctrlObj.phiStart, ctrlObj.phiLength, ctrlObj.thetaStart, ctrlObj.thetaLength);
            sphere = new THREE.Mesh(sphereGeo, sphereMat);
            scene.add(sphere);
        });
        sphereFolder.add(ctrlObj, "phiLength", 0, Math.PI * 2.0).onChange(function (e) {
    
    
            scene.remove(sphere);
            sphereGeo = new THREE.SphereGeometry(ctrlObj.radius, ctrlObj.widthSegments, ctrlObj.heightSegments, ctrlObj.phiStart, ctrlObj.phiLength, ctrlObj.thetaStart, ctrlObj.thetaLength);
            sphere = new THREE.Mesh(sphereGeo, sphereMat);
            scene.add(sphere);
        });
        sphereFolder.add(ctrlObj, "thetaStart", 0, Math.PI).onChange(function (e) {
    
    
            scene.remove(sphere);
            sphereGeo = new THREE.SphereGeometry(ctrlObj.radius, ctrlObj.widthSegments, ctrlObj.heightSegments, ctrlObj.phiStart, ctrlObj.phiLength, ctrlObj.thetaStart, ctrlObj.thetaLength);
            sphere = new THREE.Mesh(sphereGeo, sphereMat);
            scene.add(sphere);
        });
        sphereFolder.add(ctrlObj, "thetaLength", 0, Math.PI).onChange(function (e) {
    
    
            scene.remove(sphere);
            sphereGeo = new THREE.SphereGeometry(ctrlObj.radius, ctrlObj.widthSegments, ctrlObj.heightSegments, ctrlObj.phiStart, ctrlObj.phiLength, ctrlObj.thetaStart, ctrlObj.thetaLength);
            sphere = new THREE.Mesh(sphereGeo, sphereMat);
            scene.add(sphere);
        });



        var controls = new OrbitControls(camera, render.domElement);
        controls.update();

        renderScene();

        function renderScene() {
    
    

            controls.update();

            requestAnimationFrame(renderScene);
            render.render(scene, camera);
        }

        window.addEventListener('resize', onWindowResize, false);

        function onWindowResize() {
    
    
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            render.setSize(window.innerWidth, window.innerHeight);
        }

        function loadModel() {
    
    
            new GLTFLoader().setPath("model/")
                .load("untitled.glb", function (gltf) {
    
    
                    gltf.scene.scale.set(0.01, 0.01, 0.01);
                    gltf.scene.traverse(function (object) {
    
    
                        if (object.isMesh)
                            object.castShadow = true;
                    });

                    scene.add(gltf.scene);
                })
        }
    </script>

</body>

</html>

请添加图片描述
12.ConvexGeometry凸面几何体

<!DOCTYPE html>
<html>

<head>
    <title>threejs</title>
    <meta charset="UTF-8" />
    <style>
        body {
    
    
            margin: 0;
            overflow: hidden;
        }
    </style>

</head>

<body>
    <div id="webgl-output">

    </div>

    <div id="myStats"></div>

    <script type="module">
        import * as THREE from "../../libs/build/three.module.js"
        import {
    
     dat } from "../../libs/dat.gui/dat.gui.js"
        import {
    
     Stats } from "../../libs/Stats/Stats.js"
        import {
    
     GLTFLoader } from "../../libs/three.js/jsm/loaders/GLTFLoader.js"
        import {
    
     OrbitControls } from "../../libs/three.js/jsm/controls/OrbitControls.js"
        //导入ConvexGeometry
        import {
    
     ConvexGeometry } from "../../libs/three.js/jsm/geometries/ConvexGeometry.js"

        var scene = new THREE.Scene();
        var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

        var render = new THREE.WebGLRenderer();
        render.setClearColor(new THREE.Color(0x000000));
        render.setSize(window.innerWidth, window.innerHeight);
        render.shadowMap.enabled = true;

        document.getElementById("webgl-output").appendChild(render.domElement);

        var axes = new THREE.AxesHelper(500);
        scene.add(axes);

        //loadModel();

        var planeGeometry = new THREE.PlaneGeometry(100, 100);
        var planeMaterial = new THREE.MeshLambertMaterial({
    
     color: 0xAAAAAA });
        var plane = new THREE.Mesh(planeGeometry, planeMaterial);

        plane.rotation.x = -0.5 * Math.PI;
        plane.position.set(15, 0, 0);
        plane.receiveShadow = true;

        //scene.add(plane);

        camera.position.x = -5;
        camera.position.y = 5;
        camera.position.z = 5;
        camera.lookAt(scene.position);
        scene.add(camera);


        var ambienLight = new THREE.AmbientLight(0xcccccc);
        // scene.add(ambienLight); 

        const directionalLight = new THREE.DirectionalLight(0xffffff, 2);
        directionalLight.castShadow = true;
        directionalLight.shadow.mapSize.width = 2048;
        directionalLight.shadow.mapSize.height = 2048;
        directionalLight.position.set(20, 20, 20);
        scene.add(directionalLight);

        //学习一下ConvexGeometry凸面几何体,threejs标准库里没有包含这种高级几何体,我们需要import他们
        //通过ConvexGeometry,我们可以围绕一组点创建一个凸包,所谓凸包,就是包围这组点的最小图形,那么我们先要创建一组点
        var convexPoints = [];
        for (var i = 0; i < 20; i++) {
    
    //写个20次的循环,每次生成三个范围-20到20的随机数
            var x = Math.random() * 40 - 20;
            var y = Math.random() * 40 - 20;
            var z = Math.random() * 40 - 20;
            convexPoints.push(new THREE.Vector3(x, y, z));//并组成三维坐标放入点的数组中  
        };//为了能够直接看到这些点的位置,我们需要遍历数组,在每个点的位置创建一个红色的球体
        convexPoints.forEach(function (convexPoint) {
    
    
            var convexSphereGeo = new THREE.SphereGeometry(0.3);
            var convexSphereMat = new THREE.MeshBasicMaterial({
    
     color: 0xff0000 });
            var convexSphere = new THREE.Mesh(convexSphereGeo, convexSphereMat);
            convexSphere.position.copy(convexPoint);//位置对应点的位置
            scene.add(convexSphere);//把每个小球都添加到场景中
        })

        //我们现在创建一个ConvexGeometry凸面几何体,他只有一个构造参数,就是三维坐标数组,我们把刚才创建的数组传入它的构造函数中
        var convexGeo = new ConvexGeometry(convexPoints);
        var convexMat = new THREE.MeshBasicMaterial({
    
     color: 0x00ff00, wireframe: true });//材质设置为绿色,线框属性设置为真以便观察结构
        var convex = new THREE.Mesh(convexGeo, convexMat);
        scene.add(convex);//把凸面几何体添加到场景中,刷新一下看看效果
        //因为我们用的是随机的坐标,所以每次刷新生成的凸面几何体都不一样

        var controls = new OrbitControls(camera, render.domElement);
        controls.update();

        var stats = addStats();
        renderScene();

        function renderScene() {
    
    

            controls.update();
            stats.update();
            requestAnimationFrame(renderScene);
            render.render(scene, camera);
        }

        window.addEventListener('resize', onWindowResize, false);

        function onWindowResize() {
    
    
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            render.setSize(window.innerWidth, window.innerHeight);
        }

        function addStats() {
    
    
            var stats = new Stats();
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';
            stats.setMode(0);

            document.getElementById("myStats").appendChild(stats.domElement);
            return stats;
        }

    </script>

</body>

</html>

请添加图片描述
13.学习一下如何通过空间中的点构造曲线路径

     //学习一下如何通过空间中的点构造曲线路径
        var Points = [];//新建一组点构成路径
        for (var i = 0; i < 10; i++) {
    
    //
            Points.push(new THREE.Vector3(i * 3, Math.sin(i) * 5, i * 3));//组成三维坐标放入点的数组中  
        };//为了能够直接看到这些点的位置,我们需要遍历数组,在每个点的位置创建一个红色的球体
        Points.forEach(function (Point) {
    
    
            var SphereGeo = new THREE.SphereGeometry(0.2);
            var SphereMat = new THREE.MeshBasicMaterial({
    
     color: 0xff0000 });
            var Sphere = new THREE.Mesh(SphereGeo, SphereMat);
            Sphere.position.copy(Point);//位置对应点的位置
            scene.add(Sphere);//把每个小球都添加到场景中
        })//刷新一下浏览器发现点已经显示出来了

        //接下来我们用这些点创建一个路径,我们可以使用Three.CatmullRomCurve生成一条三维CarmullROM曲线路径
        var path = new THREE.CatmullRomCurve3(Points);
        var lineGeo = new THREE.BufferGeometry();//为了能够看到路径,我们在路径的位置创建一条曲线,新建一个BufferGeometry(自定义几何体)
        lineGeo.setFromPoints(path.getPoints(10));//在使用setFromPoints给它设置坐标,坐标可以用getPoints从路径上获得,getPoints参数表示获得点的数量
        var lineMat = new THREE.LineBasicMaterial({
    
     color: 0xff0000 });//线条的颜色设置为红色
        var line = new THREE.Line(lineGeo, lineMat);
        scene.add(line);//刷新浏览器,可以看到线条已经出线在场景中了
        //修改一下getPoints的参数,我们测试发现值越大曲线越平滑,当参数很小,几乎是由点连成的直线,当参数为100,几乎成光滑曲线

请添加图片描述
14.Material的基本属性和材质贴图方法

<!DOCTYPE html>
<html>

<head>
    <title>threejs</title>
    <meta charset="UTF-8" />
    <style>
        body {
    
    
            margin: 0;
            overflow: hidden;
        }
    </style>

</head>

<body>
    <div id="webgl-output">

    </div>

    <div id="myStats"></div>

    <script type="module">
        import * as THREE from "../../libs/build/three.module.js"
        import {
    
     dat } from "../../libs/dat.gui/dat.gui.js"
        import {
    
     Stats } from "../../libs/Stats/Stats.js"
        import {
    
     GLTFLoader } from "../../libs/three.js/jsm/loaders/GLTFLoader.js"
        import {
    
     OrbitControls } from "../../libs/three.js/jsm/controls/OrbitControls.js"

        var scene = new THREE.Scene();
        var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

        var render = new THREE.WebGLRenderer();
        render.setClearColor(new THREE.Color(0xffffff));
        render.setSize(window.innerWidth, window.innerHeight);
        render.shadowMap.enabled = true;

        document.getElementById("webgl-output").appendChild(render.domElement);

        var axes = new THREE.AxesHelper(500);
        scene.add(axes);

        //loadModel();

        camera.position.x = 50;
        camera.position.y = 50;
        camera.position.z = 50;
        camera.lookAt(scene.position);
        scene.add(camera);


        var ambienLight = new THREE.AmbientLight(0xcccccc);
        // scene.add(ambienLight); 

        const directionalLight = new THREE.DirectionalLight(0xffffff, 2);
        directionalLight.castShadow = true;
        directionalLight.shadow.mapSize.width = 2048;
        directionalLight.shadow.mapSize.height = 2048;
        directionalLight.position.set(20, 20, 20);
        scene.add(directionalLight);

        //本节课我们学习材质的几种属性,这几种属性是所有材质最常用的,所有的材质都有一个共同的基类,Material,今天学习的几个属性便是这个基类中常用的属性
        var planeGeometry = new THREE.PlaneGeometry(200, 200, 4, 4);//首先用PlaneGeometry几何体创建一个地板
        //材质的构造参数是一个用于定义材质外观的对象,具有一个或多个属性,材质的任何属性都可以从此处传入,包括从Material继承的任何属性,所以本节课对Material中属性讲解都通过MeshBasicMaterial来表达
        var planeMaterial = new THREE.MeshBasicMaterial({
    
     color: 0x777777 });
        var plane = new THREE.Mesh(planeGeometry, planeMaterial);

        plane.rotation.x = -0.5 * Math.PI;//调整一下网格位置
        plane.position.y = -20;
        scene.add(plane);//场景中有一个对照的地步了,我们再来创建一个几何体对象,用于显示我们的属性效果

        var cubeGeom = new THREE.BoxGeometry(15, 15, 15);
        var cubeMaterial = new THREE.MeshBasicMaterial({
    
     color: 0x7777ff });
        var cubeMesh = new THREE.Mesh(cubeGeom, cubeMaterial);
        scene.add(cubeMesh);
        //为了更好的学习Material中的属性,我们依旧选择dat.GUI库
        var ctrlObj = {
    
    
            visible: true,//该属性默认为true,表示材质可见
            transparent: false,//该属性表示此材质是否透明,设置为true时,可以通过设置材质的opacity属性来控制材质透明程度
            opacity: 1,//opacity范围是0到1的浮点数默认为1,0表示完全透明,1表示完全不透明,若transparent未设置为true,则材质保持完全不透明,此值仅影响其颜色
            side: "front",//side表示需要渲染哪一面,该值有三个可选,分别是THREE.FrontSide、BackSide、DoubleSide
            depthTest: true,//这个属性表示在渲染此材质时是否启用深度测试,默认为true
            depthWrite: true,//这个属性表示在渲染此材质时是否对深度缓冲区有影响,默认为true
            apphaTest: 1,//该属性表示如果不透明度低于此值,则不会渲染材质

        }
        var control = new dat.GUI();
        const folder = control.addFolder("基础属性");
        folder.add(ctrlObj, "visible").onChange(function (e) {
    
    
            cubeMaterial.visible = e;//材质不同于几何体 可以直接修改
        });
        folder.add(ctrlObj, "transparent").onChange(function (e) {
    
    
            cubeMaterial.transparent = e;
        });
        folder.add(ctrlObj, "opacity", 0, 1).onChange(function (e) {
    
    
            cubeMaterial.opacity = e;
        });
        folder.add(ctrlObj, "depthTest").onChange(function (e) {
    
    
            cubeMaterial.depthTest = e;
        });
        folder.add(ctrlObj, "depthWrite").onChange(function (e) {
    
    
            cubeMaterial.depthWrite = e;

        });
        folder.add(ctrlObj, "apphaTest", 0, 1).onChange(function (e) {
    
    
            cubeMaterial.apphaTest = e;
        });
        //这边的side属性,我们需要传入一个数组,来让我们选择side的值
        folder.add(ctrlObj, "side", ["front", "back", "double"]).onChange(function (e) {
    
    
            switch (e) {
    
    //然后通过 switch case来对不同的值进行不同的属性赋值
                case "front":
                    cubeMaterial.side = THREE.FrontSide;
                    break;
                case "back":
                    cubeMaterial.side = THREE.BackSide;
                    break;
                case "double":
                    cubeMaterial.side = THREE.DoubleSide;
                    break;
                default:
                    break;
            }
            //cubeMaterial.needsUpdate = true;//然后我们可以在此回调函数中对此材质进行重新编译
        });
        //为了让这些属性的效果看起来更清楚,我们可以为该正方体材质添加贴图
        const textureLoader = new THREE.TextureLoader();//先创建一个TextureLoader对象用于对贴图的加载
        const bricks = textureLoader.load("./textures/1.jpg");//然后通过该对象的load方法将指定路径的贴图加载到变量中
        cubeMaterial.map = bricks;//再将加载好的贴图设置给材质的map贴图属性
        //刷新浏览器可发现我们的贴图已经应用到正方体上了

        var controls = new OrbitControls(camera, render.domElement);
        controls.update();

        var stats = addStats();
        renderScene();

        function renderScene() {
    
    

            controls.update();
            stats.update();
            requestAnimationFrame(renderScene);
            render.render(scene, camera);
        }

        window.addEventListener('resize', onWindowResize, false);

        function onWindowResize() {
    
    
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            render.setSize(window.innerWidth, window.innerHeight);
        }

        function addStats() {
    
    
            var stats = new Stats();
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';
            stats.setMode(0);

            document.getElementById("myStats").appendChild(stats.domElement);
            return stats;
        }

    </script>

</body>

</html>

请添加图片描述
15.MeshBasicMaterial的基本属性以及环境贴图和灰度纹理贴图

<!DOCTYPE html>
<html>

<head>
    <title>threejs</title>
    <meta charset="UTF-8" />
    <style>
        body {
    
    
            margin: 0;
            overflow: hidden;
        }
    </style>

</head>

<body>
    <div id="webgl-output">

    </div>

    <div id="myStats"></div>

    <script type="module">
        import * as THREE from "../../libs/build/three.module.js"
        import {
    
     dat } from "../../libs/dat.gui/dat.gui.js"
        import {
    
     Stats } from "../../libs/Stats/Stats.js"
        import {
    
     GLTFLoader } from "../../libs/three.js/jsm/loaders/GLTFLoader.js"
        import {
    
     OrbitControls } from "../../libs/three.js/jsm/controls/OrbitControls.js"

        var scene = new THREE.Scene();
        var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

        var render = new THREE.WebGLRenderer();
        render.setClearColor(new THREE.Color(0xffffff));
        render.setSize(window.innerWidth, window.innerHeight);
        render.shadowMap.enabled = true;

        document.getElementById("webgl-output").appendChild(render.domElement);

        var axes = new THREE.AxesHelper(500);
        scene.add(axes);

        //loadModel();

        camera.position.set(30, 30, 30);//调整一下相机位置
        camera.lookAt(scene.position);
        scene.add(camera);


        var ambienLight = new THREE.AmbientLight(0xcccccc);
        // scene.add(ambienLight); 

        const directionalLight = new THREE.DirectionalLight(0xffffff, 2);
        directionalLight.castShadow = true;
        directionalLight.shadow.mapSize.width = 2048;
        directionalLight.shadow.mapSize.height = 2048;
        directionalLight.position.set(20, 20, 20);
        scene.add(directionalLight);

        //本节课我们沿用上节课案例来学习本节课的MeshBasicMaterial基础网格材质,这是一种非常简单的材质,不需要考虑场景中光照的影响,使用这种材质的网格会被渲染成简单的平面多边形,也可以显示几何体线框
        var planeGeometry = new THREE.PlaneGeometry(200, 200, 4, 4);
        var planeMaterial = new THREE.MeshBasicMaterial({
    
     color: 0x777777 });
        var plane = new THREE.Mesh(planeGeometry, planeMaterial);

        plane.rotation.x = -0.5 * Math.PI;
        plane.position.y = -20;
        scene.add(plane);

        var cubeGeom = new THREE.BoxGeometry(15, 15, 15);
        var cubeMaterial = new THREE.MeshBasicMaterial({
    
     color: 0x7777ff });
        var cubeMesh = new THREE.Mesh(cubeGeom, cubeMaterial);
        scene.add(cubeMesh);

        var ctrlObj = {
    
    
            visible: true,
            transparent: false,
            opacity: 1,
            side: "front",
            depthTest: true,
            depthWrite: true,
            apphaTest: 1,//我们将学习的属性保存在上节课对象中
            color: 0x7777ff,//材质颜色默认白色
            wireframe: false,//线框属性,该属性能将几何体渲染成线框,默认值false
            map: true,//为了能够将后面的效果显示更加清楚,我们需要定义一个map属性,该属性设置材质中map颜色贴图是否存在
            reflectivity: 1,//该属性表示环境贴图对表面的影响程度,默认为1,范围0到1,0表示无反射,1表示完全反射
            refractionRatio: 0.98,//该属性表示空气的折射率除以材质的折射率,默认0.98
            combine: "Multiply",//该属性表示如何将表面颜色的结果与环境贴图结合起来,默认MultiplyOperation,可选值MixOperation和AddOperation
            alphaMap: true,表示该图形是否存在灰度纹理,用于控制整个表面的不透明度
        }
        var control = new dat.GUI();
        const folder = control.addFolder("基础属性");
        folder.add(ctrlObj, "visible").onChange(function (e) {
    
    
            cubeMaterial.visible = e;
        });
        folder.add(ctrlObj, "transparent").onChange(function (e) {
    
    
            cubeMaterial.transparent = e;
        });
        folder.add(ctrlObj, "opacity", 0, 1).onChange(function (e) {
    
    
            cubeMaterial.opacity = e;
        });
        folder.add(ctrlObj, "depthTest").onChange(function (e) {
    
    
            cubeMaterial.depthTest = e;
        });
        folder.add(ctrlObj, "depthWrite").onChange(function (e) {
    
    
            cubeMaterial.depthWrite = e;

        });
        folder.add(ctrlObj, "apphaTest", 0, 1).onChange(function (e) {
    
    
            cubeMaterial.apphaTest = e;
        });
        folder.add(ctrlObj, "side", ["front", "back", "double"]).onChange(function (e) {
    
    
            switch (e) {
    
    
                case "front":
                    cubeMaterial.side = THREE.FrontSide;
                    break;
                case "back":
                    cubeMaterial.side = THREE.BackSide;
                    break;
                case "double":
                    cubeMaterial.side = THREE.DoubleSide;
                    break;
                default:
                    break;
            }
            cubeMaterial.needsUpdate = true;
        });
        const textureLoader = new THREE.TextureLoader();
        const bricks = textureLoader.load("./textures/1.jpg");
        cubeMaterial.map = bricks;


        const Basicfolder = control.addFolder("MeshBasicMaterial");//再来为这次学习的MeshBasicMaterial材质属性,创建一个分组,我们会将今天学习的几种属性添加到该分组里
        Basicfolder.addColor(ctrlObj, "color").onChange(function (e) {
    
    
            cubeMaterial.color = new THREE.Color(e);
        });//添加完成后,刷新浏览器,调整颜色值,可以发现材质的颜色和颜色贴图的效果进行了混合
        Basicfolder.add(ctrlObj, "wireframe").onChange(function (e) {
    
    
            cubeMaterial.wireframe = e;
        });//添加后我们设置wireframe为true,正方体渲染成了线框,这种效果非常适用于调试
        Basicfolder.add(ctrlObj, "map").onChange(function (e) {
    
    //当值为真时,我们将颜色贴图设置为对应纹理否则不设置颜色贴图
            cubeMaterial.map = e ? bricks : null;
            cubeMaterial.needsUpdate = true;//设置完成后我们需要使用基类中的needsUpdate属性来重新编译材质
        });
        Basicfolder.add(ctrlObj, "reflectivity", 0, 1).onChange(function (e) {
    
    
            cubeMaterial.reflectivity = e;
        });//正方体没有任何变化 是因为我们没有设置环境贴图,因此我们需要将对应贴图加载到项目中,我们在下面封装一个加载环境贴图的方法,并在下面调用这个方法给正方体设置环境贴图
        //在给正方形设置环境贴图之后,我们在控制菜单将正方体的颜色贴图去除,可以清晰的看到环境贴图效果,再来对reflectivity进行修改,可以看到正方体的变化

        var textureCube = creatEnv();//在这里调用加载环境贴图的方法,将返回出来的纹理放到一个变量中
        cubeMaterial.envMap = textureCube;//给正方形设置环境贴图

        Basicfolder.add(ctrlObj, "refractionRatio", 0, 1).onChange(function (e) {
    
    
            cubeMaterial.refractionRatio = e;
        });//修改refractionRatio,可以看到正方体反射的场景距离发生变化
        Basicfolder.add(ctrlObj, "combine", ["Multiply", "Mix", "Add"]).onChange(function (e) {
    
    
            switch (e) {
    
    
                case "Multiply":
                    cubeMaterial.combine = THREE.MultiplyOperation;
                    break;
                case "Mix":
                    cubeMaterial.combine = THREE.MixOperation;
                    break;
                case "Add":
                    cubeMaterial.combine = THREE.AddOperation;
                    break;
                default:
                    break;
            }
            cubeMaterial.needsUpdate = true;
        });
        const alphaMapTx = textureLoader.load("./textures/2.jpg");//现在我们加载一张纹理贴图
        cubeMaterial.alphaMap = alphaMapTx;//为MeshBasicMaterial设置alphaMap属性,该属性表示alpha贴图是一张灰度纹理,用于控制整个表面的不透明度
        Basicfolder.add(ctrlObj, "alphaMap").onChange(function (e) {
    
    //当值为真时,我们将该灰度纹理贴图设置为对应纹理否则不设置灰度纹理贴图
            cubeMaterial.alphaMap = e ? alphaMapTx : null;
            cubeMaterial.needsUpdate = true;//设置完成后我们需要使用基类中的needsUpdate属性来重新编译材质
        });//刷新浏览器,将transparent设置为真,该纹理贴图显示了

        var controls = new OrbitControls(camera, render.domElement);
        controls.update();

        var stats = addStats();
        renderScene();

        function renderScene() {
    
    

            controls.update();
            stats.update();
            requestAnimationFrame(renderScene);
            render.render(scene, camera);
        }

        window.addEventListener('resize', onWindowResize, false);

        function onWindowResize() {
    
    
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            render.setSize(window.innerWidth, window.innerHeight);
        }

        function addStats() {
    
    
            var stats = new Stats();
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';
            stats.setMode(0);

            document.getElementById("myStats").appendChild(stats.domElement);
            return stats;
        }

        //环境贴图也叫反射贴图,可以在几何体上反射周围环境,实现模型表面对周围环境的反射效果
        function creatEnv() {
    
    //加载环境贴图,首先我们需要创建一个数组用于存放环境贴图的路径
            //该数组长度为6,分别用于正方体的每一侧,
            var path = "./textures/";
            var format = '.jpg';
            var urls = [//这里图方便用一张图了
                path + '4' + format, path + '4' + format,
                path + '4' + format, path + '4' + format,
                path + '4' + format, path + '4' + format
            ];
            const cubeTxLoader = new THREE.CubeTextureLoader();//再新建一个CubeTextureLoader加载器对象
            const refCube = cubeTxLoader.load(urls);//然后通过创建的加载器对象将我们的所有贴图加载到一个变量中
            refCube.mapping = THREE.CubeRefractionMapping;//接着再设置纹理贴图的映射模式,此处设置是为了配合后面的refractionRatio属性
            refCube.format = THREE.RGBFormat;//接着再设置纹理贴图的格式,对于JPG贴图,我们通常需要设置为RGBFormat格式
            return refCube;//最后将我们的贴图返回,以便后续使用
        }//这里图片加载容易有错误,环境纹理贴图要求图片长宽相等而其他纹理贴图不需要,不知道是不是因为几何体是正方形的原因
    </script>

</body>

</html>

渲染效果图:
请添加图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43739821/article/details/124028837