【three.js学习笔记】02 物体材质 光 与 影

xiaoxiao2021-02-28  9

神说要有光,便有了光 神说光是好的,于是把光与暗分开了

在所有的3d游戏或者动画中,光与阴影都是非常重要的一部分,阴影可以影响到很多东西,一个游戏,阴影可以说是分辨一个游戏画面的好坏。 这一章中涉及到:

物体材质添加光源添加阴影添加阴影的受体

在前面已经介绍过怎么样创建场景添加相机与物体,那么就直接贴创建场景的代码了

<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <!--<script src="../three.min.js"></script>--><!--我发现我用的这个three.min.js本地版本没有辅助线--> <script src='https://threejs.org/build/three.js'></script> <title>场景</title> <style> body{ margin:0;padding:0; overflow:hidden; } </style> </head> <body> <div id="WebGL-output"></div> <script> //初始化函数。在加载three之后调用,初始化所有的东西 function init(){ //创建场景。所有的物体对象都在场景上相当于是一个舞台 var scene = new THREE.Scene(); //创建透视相机 var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); //辅助线 var axes = new THREE.AxesHelper(20); scene.add(axes); //渲染器 var renderer = new THREE.WebGLRenderer(); renderer.setClearColor(new THREE.Color(0xEEEEEE)); renderer.setSize(window.innerWidth,window.innerHeight); //THREE.PCFSoftShadowMap THREE.PCFShadowMap BasicShadowMap //创建平面 //材质种类:MeshLambertMaterial MeshPhongMaterial MeshBasicMaterial var planeGeometry = new THREE.PlaneGeometry(60, 30);//框架 var planeMaterial = new THREE.MeshBasicMaterial({color: 0xaaaaaa});//材质 var planeMaterial1 = new THREE.MeshPhongMaterial( { color: 0xaaaaaa, dithering: true } ); var plane = new THREE.Mesh(planeGeometry, planeMaterial);//填充 //更改平面位置 plane.rotation.x = -0.5 * Math.PI; plane.position.x = 15; plane.position.y = 0; plane.position.z = 0; scene.add(plane); //创建立方体 var cubeGeometry = new THREE.BoxGeometry(4,4,4); var cubeMaterial = new THREE.MeshBasicMaterial({color: 0xdd4444,wireframe: true}); //wireframe用于表现几何体的框架 默认为false var cube = new THREE.Mesh(cubeGeometry, cubeMaterial); //立方体位置 cube.position.x = -4; cube.position.y = 3; cube.position.z = 0; //将立方体添加进入场景 scene.add(cube); //添加球体 var sphereGeometry = new THREE.SphereGeometry(4, 20 ,20); var sphereMaterial = new THREE.MeshBasicMaterial({color:0xcc44cc}); var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial); //球体位置 sphere.position.x = 18; sphere.position.y = 4; sphere.position.z = 2; //将球体加入到场景中 scene.add(sphere); //柱体 var cylinderGeometry = new THREE.CylinderGeometry( 4, 4, 5, 5); var material = new THREE.MeshBasicMaterial({color:0xcccc33}); var cylinder = new THREE.Mesh(cylinderGeometry,material); //设定位置 cylinder.position.x = 2; cylinder.position.y = 2.5; cylinder.position.z = 6; //添加柱体 scene.add(cylinder); //变化相机位置以及方向 camera.position.x = -30; camera.position.y = 40; camera.position.z = 30; camera.lookAt(scene.position); //创建canvas document.getElementById("WebGL-output").appendChild(renderer.domElement); //渲染 renderer.render(scene,camera); } window.onload = init; </script> </body> </html>

相比起上一章的内容,我稍微变大了底部的plane 平台的面积,将柱体和球体的wireframe去掉了,这样就能看到基本材质的效果,效果如下: emm这个材质看起来非常渣,勉强能认出是一个立体的东西,各个面的颜色都是一样的 THREE.MeshBasicMaterial 这种材质并不会对光源产生反应,所以我们要先修改材质 修改平面的材质以及所有物体对象的材质,将其都变成 THREE.MeshLambertMaterial(朗伯材质) 这种材质会对光有反应,它不包括任何镜面属性,对粗糙物体来说,是非常有用的,它不会反射出周围的环境

... var planeMaterial = new THREE.MeshLambertMaterial({color: 0xaaaaaa});//平面材质 ... var cubeMaterial = new THREE.MeshLambertMaterial({color: 0xdd4444});//立方体材质 ... var sphereMaterial = new THREE.MeshLambertMaterial({color: 0xcc44cc});//球体材质 ... var material = new THREE.MeshLambertMaterial({color:0xcccc33});//无棱柱材质

材质都更改完毕之后,我们再刷新一下页面:

发现一片漆黑–。从辅助线被遮掉的部分可以隐约看出有黑色的东西。那是因为没有光-。- 添加光源

var spotLight = new THREE.SpotLight(0xffffff);//白色光线 spotLight.position.set(-40,80,-10);//位置 spotLight.castShadow = true;//会产生影子 scene.add(spotLight);//添加光源进入场景

此处添加的是聚光灯光源,是从一个点出发按照一定角度散开的光源 光源有很多类型,比如环境光源AmbientLight 就是在场景中的物体都有的光源,这个光源在所有的物体表面都是随机分布的, 平行光 DirectionalLight 太阳光对于地球来说就类似于平行光 点光源 PointLight 类似于小灯泡那样四散开来的光源 除此之外还有很多,请自行寻找 光源 添加光源之后的样子: 嗯好像有那么点回事了,但是为啥还是没有影子? 原因是,虽然光源已经写了有产生影子的可能性,但是还需要三点:

哪些物体能产生影子(比如吸血鬼就没有影子哈那是因为他自己是吸血鬼,他本身自带的属性)产生的影子放在哪(能接受影子的地方)渲染器允许产生影子

为啥这么复杂呢,因为产生影子是一个非常消耗资源的工作,我们得知道在什么地方要产生影子,这个影子可以投到什么地方上面。 添加下面的代码:

renderer.shadowMap.enabled = true;//渲染器将会渲染影子 plane.receiveShadow = true;//让平面能够接受影子 //让物体们能够有自己的影子 cube.castShadow = true; sphere.castShadow = true; cylinder.castShadow = true;

完成后发现:

有影子了,但是这影子咋是马赛克影子-,-,虽然站远一点的确看不出来 但是我还是希望影子能够真实一点啊 其实是:在默认情况下为了避免影子渲染过多,设置里面就是有这样的马赛克。同时本来几何体的大小设置的就比较小=。= 所以导致这样的状况出现了。 添加代码

spotLight.shadow.mapSize.width = 2000; // 默认512 spotLight.shadow.mapSize.height = 2000; // 默认512

影子在两个方向上的细致程度,越高表示越细致,到2000的时候感觉差不多可以用了 效果: 我觉得还行。嗯 下一章应该讲到动画与 dat.GUI 组件库便于测试不同数值对表现产生的影响嗯, (翻书。。。)

转载请注明原文地址: https://www.6miu.com/read-2650099.html

最新回复(0)