《Three.js 开发指南第 2 版》读书笔记 2

《Three.js 开发指南第 2 版》读书笔记 2

书本源码地址:https://github.com/josdirksen/learning-threejs

第 3 章 学习使用 Three.js 中的光源

不同种类的光源

名字描述
THREE. AmbientLight基本光源,该光源的颜色将会叠加到场景现有物体的颜色上
THREE. PointLight点光源,从空间的一个点向所有方向发射光线,点光源不能用来创建阴影
THREE. SpotLight光源有聚光的效果,类似台灯、天花板上的吊灯或手电筒,这种光源可以投射阴影
THREE. DirectionalLIght无线光,光源发出的光线可以看作是平行,类似太阳光,可创建阴影
THREE. HemisphereLight特殊光源,可通过模拟反光面和光线微弱的天空来创建更加自然的室外光线,不提供阴影相关功能
THREE. AreaLight可指定散发光线的平面,不是一个点,不投射阴影
THREE. LensFlare不是光源,可为场景中的光源家镜头光晕效果

THREE. AmbientLight

颜色将应用到全局,将场景中所有物体渲染为相同颜色

THREE. SpotLight 光源来产生阴影

THREE. Color

函数名描述
set(value)十六进制颜色值,可以是字符串,数值,THREE. Color
setHex(value)十六进制数字值
setRGB(r, g, b)RGB 值颜色,范围 0~1
setHSL(h, s, l)HSL 值颜色,范围 0~1
setStyle(style)css 颜色
copy(color)复制颜色对象
copyGammaToLinear(color)伽马色彩转换到线性色彩,内部使用
copyLinearToGamma(color)线性色彩转换到伽马色彩,内部使用
convertGammaToLinear(color)伽马色彩转换到线性色彩
convertLinearToGammacolor)线性色彩转换到伽马色彩
getHex()十六进制值
getHexString()十六进制字符串
getStyle()css 颜色
getHSL(optionalTarget)HSL 颜色值
offsetHSL(h, s, l)将 h, s, l 添加到当前颜色 h, s, l
add(color)将 r, g, b 添加到当前颜色
addColors(color1, color2)内部使用,color1, color2 相加
addScalar(s)内部使用,当前颜色 RGB 分量上
multiply(color)内部使用,当前颜色与 THREE.color 对象的 RGB 值相乘
multiplyScalar(s)内部使用,当前颜色与 RGB 值相乘
lerp(color, alpha)内部使用,找出介于对象和颜色和提供颜色之间的颜色,alpha 定义当前颜色与提供颜色的差距
lerp(color, alpha)内部使用,找出介于对象和颜色和提供颜色之间的颜色,alpha 定义当前颜色与提供颜色的差距
equals(color)THREE. Color 颜色对象的 RGB 值与当前值相等与否
fromArray(array)与 setRGB 方法具有相同的功能,只是 RGB 值通过数字数组传入
toArray返回三元素组[r, g, b]
clone()复制当前颜色

THREE. PointLight

THREE. PointLight 从特定的一点向所有方向发射光线,点光源

属性描述
color(颜色)光源颜色
distance(距离)光源照射的距离,默认 0,以为光的强度不会随距离增加而减少
intensity(强度)光源照射的强度, 默认 1
position(位置)光源在场景中的位置
visible(是否可见)true 光源打开,false 光源关闭
var pointColor = '#ccffcc';
var pointLight = new THREE.PointLight(pointColor);
pointLight.position.set(10, 10, 10);
pointLight.intensity = 2.4;
pointLight.distance = 100;
scene.add(pointLight);

THREE. SpotLight

从特定一点发射锥形光线,聚光灯光源
其他属性同 THREE. PointLight

属性描述
angle(角度)光源发射出的光速宽度,单位弧度, 默认值 Math. PI/3
caseShadow(投影)光源是否产生投影
exponent(光强衰减指数)光线强度递减的速度
onlyShadow(仅阴影)光源只生成阴影,不会再场景中添加任何光照
shadowBias(阴影偏移)偏置阴影的位置,默认 0
shadowCameraFar(投影远点)到距离光源光源那个位置可生成阴影,默认值为 5000
shadowCameraFov(投影视场)用于生成阴影的视场有多大,默认值为 50
shadowCameraNear(投影近点)到距离光源光源那个位置开始生成阴影,默认值为 50
shadowCameraVisible(阴影方式可见)光源阴影设置可见与否
shadowDarkness(阴影暗度)阴影渲染的暗度,在场景渲染后无法更改,默认 0.5
shadowMapWidth, shadowMapHeight(阴影映射宽度和高度)决定有多少像素用来生成阴影,若阴影锯齿状或不光滑,增加此值,渲染后无法更改,默认 512
target(目标)光源只想场景中的特定对象或位置
var pointColor = '#ffffff';
var spotLight = new THREE.spotLight(pointColor);
spotLight.position.set(-40, 60, -10);
spotLight.castShadow = true;
spotLight.target = plane;
var target = new THREE.Object3D();
target.position = new THREE.Vector3(5, 0, 0);
spotLight.target = target;

scene.add(spotLight);

阴影使用可能遇到的问题

  • 阴影模糊,增加 shadowMapWidth 和 shadowMapHeight,或保证用于计算阴影区域紧密包围在对象周围(shadowCameraNear, shadowCameraFar, shadowCameraFov)
  • 产生阴影与接收阴影设置,光源生成阴影,几何体是否接收或投射阴影 castShadow 和 receiveShadow
  • 薄对象渲染阴影时可能出现奇怪的渲染失真,可通过 shadowBias 轻微偏移阴影来修复
  • 调整 shadowDarkness 来改变阴影的暗度
  • 阴影更柔和,可在 THREE. WebGLRenderer 设置不同 shadowMapType。默认 THREE. PCFShadowMap, 柔和:PCFSoftShadowMap

THREE. DirectionalLisht

从而为平面发射光线,光线彼此平行,平行光源,光强是一样的
其他属性同 SpotLight

//阴影区域
directionalLight.shadowCameraNear = 2;
directionalLight.shadowCameraFar = 200;
directionalLight.shadowCameraLeft = -50;
directionalLight.shadowCameraRight = 50;
directionalLight.shadowCameraTop = 50;
directionalLight.shadowCameraBottom = -50;

//创建更好的阴影效果
directionalLight.shadowCascade = true;
//将阴影生成分裂,靠近摄像机十点会产生更具细节的阴影,远离摄像机十点阴影的细节更少
directionalLight.shadowCascadeCount;

shadowCascadeBias;
shadowCascadeWidth;
shadowCascadeHeight;
shadowCascadeNearZ;
shadowCascadeFarZ;

THREE. HemisphereLight

户外光照效果

var hemiLight = new THREE.HemisphereLight(0x0000ff, 0x00ff00, 0.6);
hemiLight.position.set(0, 500, 0);
scene.add(hemiLight);
属性描述
groundColor从地面发出的光线颜色
color从天空发出的光线颜色
intensity光线照射强度

THREE. AreaLight

长方体的发光区域
使用 WebGLDeferredRenderer

<script type="text/javascript" src="../libs/WebGLDeferredRenderer.js"></script>
<script type="text/javascript" src="../libs/ShaderDeferred.js"></script>
<script type="text/javascript" src="../libs/RenderPass.js"></script>
<script type="text/javascript" src="../libs/EffectComposer.js"></script>
<script type="text/javascript" src="../libs/CopyShader.js"></script>
<script type="text/javascript" src="../libs/ShaderPass.js"></script>
<script type="text/javascript" src="../libs/FXAAShader.js"></script>
<script type="text/javascript" src="../libs/MaskPass.js"></script>
var renderer = new THREE.WebGLDeferredRenderer({
  width: window.innerWidth,
  height: window.innerHeight,
  scale: 1,
  antialias: true,
  tonemapping: THREE.FilmicOperator,
  brightness: 2.5,
});
var areaLight1 = new THREE.AreaLight(0xff0000, 3);
areaLight1.position.set(-10, 10, -35);
areaLight1.rotation.set(-Math.PI / 2, 0, 0);
areaLight1.width = 4;
areaLight1.height = 9.9;
scene.add(areaLight1);

var planeGeometry1 = new THREE.BoxGeometry(4, 10, 0);
var planeGeometry1Mat = new THREE.MeshBasicMaterial({
  color: 0xff0000
});
var plane1 = new THREE.Mesh(planeGeometry1, planeGeometry1Mat);
//在areaLight相同位置 防止对象来模拟光线照射的区域
plane1.position.copy(areaLight1.position);

scene.add(plane1);

THREE. LensFlare

镜头光晕

flare = new THREE.LensFlare(texture, size, distance, blending, color, opacity);
参数描述
texture(纹理)图片纹理,用来决定光晕的形状
size(尺寸)光晕大小,单位像素,值-1,使用纹理本身的尺寸
distance(距离)从光源 0 到摄像机 1 的距离,将镜头光晕防止在正确位置
blending(混合)为光晕提供多种材质,混合材质,默认 THREE. AdditiveBlending
color(颜色)光晕颜色
var textureFlare0 = THREE.ImageUtils.loadTexture('../assets/textures/lensflare/lensflare0.png');
var textureFlare3 = THREE.ImageUtils.loadTexture('../assets/textures/lensflare/lensflare3.png');

var flareColor = new THREE.Color(0xffaacc);
var lensFlare = new THREE.LensFlare(textureFlare0, 350, 0.0, THREE.AdditiveBlending, flareColor);

lensFlare.add(textureFlare3, 60, 0.6, THREE.AdditiveBlending);
lensFlare.add(textureFlare3, 70, 0.7, THREE.AdditiveBlending);
lensFlare.add(textureFlare3, 120, 0.9, THREE.AdditiveBlending);
lensFlare.add(textureFlare3, 70, 1.0, THREE.AdditiveBlending);

lensFlare.position.copy(spotLight.position);
scene.add(lensFlare);

第 4 章 使用 Three.js 的材质

名称描述
MeshBasicMaterial(网格基础材质)给几何体赋予一种简单颜色,可显示几何体线框
MeshDepthMaterial(网格深度材质)从摄像机到网格的距离决定如何给网格上色
MeshNormalMaterial(网格法向材质)根据法向量计算物体表面的颜色
MeshFaceMaterial(网格面材质)容器,可为几何体的各个表面指定不同的材质
MeshLambertMaterial(网格 Lambert 材质)考虑光照影响,用于创建暗淡、不光亮的物体
MeshPhongMaterial(网格 Phong 式材质)考虑光照影响,用于创建光亮的物体
ShaderMaterial(着色器材质)允许自定义的着色器程序,直接控制顶点的繁殖方式和像素的着色方式,与 THREE. BufferedGeometry 一起使用
LineBaseMaterial(直线基础材质)用于 THREE. Line 几何体,创建着色的直线
LineDashMaterial(虚线材质)同上,允许创建出虚线效果

分类

  • 基础属性:最常用,可控制物体的不透明度,是否可见以及被应用
  • 融合属性:每个物体都有一系列的融合属性,决定物体与背景的融合
  • 高级属性:可控制底层 WebGL 上下午对象渲染物体的方式

基础属性 THREE. Material

属性描述
id(标识符)用来识别材质,并在材质创建时复制,第一个材质的值从 0 开始,每新增一个材质这个值加 1
uuid(通用唯一识别码)生成的唯一 ID, 内部使用
name(名称)给材质赋予名称,用于调试的目的
opacity(不透明度)定义物体的透明度,与 transparent 一起使用,范围 0~1
transparent(是否透明)true: 使用指定的不透明度的渲染物体,false: 物体不透明只是着色更加明亮,若使用 alpha 通道的纹理,设置为 true
overdraw(过度描绘)THREE. CanvasRender 时多边形会被渲染得稍微大一点,设 true
visible(是否可见)材质是否可见,false 场景中不见该物体
side(侧面)几何体的哪一面应用材质,默认 THREE. FrontSide(前面,外侧), THREE. BackSide(背面,内侧), THREE. DoubleSide(双侧)
needsUpdate(是否更新)true: 更新材质属性

混合属性

名称描述
blending(融合)物体上材质与背景如何融合,一般融合模式 THREE. NormalBlending,只显示材质上层
blendsrc(融合源)自定义融合模式,物体(源),背景(目标),默认 THREE. SrcAlphaFactor,使用 alpha 透明度通道融合
blenddst(融合目标)默认 THREE. OneMinusSrcAlphaFactor, 也是用透明度融合,值 1
blendequation(融合公式)默认相加 AddEquation

高级属性

名称描述
depthTest可打开 GL_DEPTH_TEST 参数,控制是否使用像素深度来计算心像素值
depthWrite内部属性,用来决定材质是否影响 WebGL 深度缓存,二维贴图时设 false
polygonOffset, polygonOffsetFactor, polygonOffsetUnits控制 WebGL 的 POLYGON_OFFSET_FILL 特性
alphatest范围 0~1,某个像素小于该值则不显示,移除一些与透明度相关的毛边

MeshBaseMaterial

var meshMaterial = new THREE.MeshBasicMaterial({
  color: 0x7777ff
});

var meshMaterial = new MeshBasicMaterial();
material.color = new THREE.Color(0xff0000);
名称描述
color(颜色)设置材质的颜色
wireframe(线框)将材质渲染成线框
wireframeLinewidth(线框线宽)线框中线的宽度
wireframeLinecap(线框线段端点)可选 butt 平, round 圆, square 方,默认 round,WebGLRenderer 不支持
wireframeLinejoin(线框线段连接点)同上
shading(着色)可选 THREE. SmoothShading(默认), THREE. NoShading, THREE. FlatShading
vertexColors(顶点颜色)默认 THREE. NoColors, 设置后采用 THREE. Geometry 对象的 colors 属性 CanvasRenderer 不起作用
fog(雾化)是否受全局雾化效果影响

THREE. MeshDepthMaterial

名称描述
wireframe(线框)是否显示线框
wireframeLinewidth(线框线宽)线框中线的宽度

联合材质

var cubeMaterial = new THREE.MeshDepthMaterial();
var colorMaterial = new THREE.MeshBasicMaterial({
  color: controls.color,
  transparent: true, //
  blending: THREE.MultiplyBlending, //混合模式,与背景相互作用
});
var cube = new THREE.SceneUtils.createMultiMaterialObject(cubeGeometry, [
  colorMaterial,
  cubeMaterial,
]);
cube.children[1].scale.set(0.99, 0.99, 0.99); //避免画面闪烁

THREE. MeshNormalMaterial

使用 THREE. ArrowHelper 添加法向量

for (var f = 0, fl = sphere.geometry.faces.length; f < fl; f++) {
  var face = sphere.geometry.faces[f];
  var centroid = new THREE.Vector3(0, 0, 0);
  centroid.add(sphere.geometry.vertices[face.a]);
  centroid.add(sphere.geometry.vertices[face.b]);
  centroid.add(sphere.geometry.vertices[face.c]);
  centroid.divideScalar(3);

  var arrow = new THREE.ArrowHelper(face.normal, centroid, 2, 0x3333ff, 0.5, 0.5);
  sphere.add(arrow);
}
名称描述
wireframe(线框)是否显示线框
wireframeLinewidth(线框线宽)线框中线的宽度
shading设置着色方法,THREE. FlatShading 平面着色, THREE. SmoothShadding 平滑着色

THREE. MeshFaceMaterial

材质容器,允许集合体的每个面指定不同的材质

var mats = [];
mats.push(new THREE.MeshBasicMaterial({
  color: 0x009e60
}));
mats.push(new THREE.MeshBasicMaterial({
  color: 0x009e60
}));
mats.push(new THREE.MeshBasicMaterial({
  color: 0x0051ba
}));
mats.push(new THREE.MeshBasicMaterial({
  color: 0x0051ba
}));
mats.push(new THREE.MeshBasicMaterial({
  color: 0xffd500
}));
mats.push(new THREE.MeshBasicMaterial({
  color: 0xffd500
}));
mats.push(new THREE.MeshBasicMaterial({
  color: 0xff5800
}));
mats.push(new THREE.MeshBasicMaterial({
  color: 0xff5800
}));
mats.push(new THREE.MeshBasicMaterial({
  color: 0xc41e3a
}));
mats.push(new THREE.MeshBasicMaterial({
  color: 0xc41e3a
}));
mats.push(new THREE.MeshBasicMaterial({
  color: 0xffffff
}));
mats.push(new THREE.MeshBasicMaterial({
  color: 0xffffff
}));

var faceMaterial = new THREE.MeshFaceMaterial(mats);

//魔方
for (var x = 0; x < 3; x++) {
  for (var y = 0; y < 3; y++) {
    for (var z = 0; z < 3; z++) {
      var cubeGeom = new THREE.BoxGeometry(2.9, 2.9, 2.9);
      var cube = new THREE.Mesh(cubeGeom, faceMaterial);
      cube.position.set(x * 3 - 3, y * 3, z * 3 - 3);

      group.add(cube);
    }
  }
}

THREE. MeshPhongMaterial

创建光亮材质,属性与暗淡材质 THREE. MeshLambertMaterial 基本属性一样

名称描述
ambient环境色,颜色与环境色相乘,默认白色
emissive材质发射的颜色,默认黑色,不收其他光照影响的颜色
specular指定材质光亮程度及高光部分的颜色,设为与color相同颜色,类似金属材质,设为灰色grey则更像塑料
shininess镜面高光部分的亮度,默认值30
metaltrue金属效果,效果微弱
wrapAroundtrue启用办lambert光照技术,光下降更微妙,网格粗糙黑暗地区莹阴影柔和且分布更加均匀
wrapRGBtrue可使用THREE. Vector3控制光下降的速度

THREE. ShaderMaterial 创建自己的着色器

着色器可讲Three.js中的JavaScript网格转换为屏幕上的像素,可指定对象如何渲染,如何覆盖或修改Three.js库中的默认值

名称描述
wireframe是否显示线框
wireframeLinewidth线框中线的宽度
shading设置着色方法,THREE. FlatShading 平面着色, THREE. SmoothShadding 平滑着色
vertexColors给每个顶点定义不同的颜色,对CanvasRenderer不起作用,对WebGLRenderer起作用
fog是否受全局无话效果影响
名称描述
fragmentShader定义的每个传入像素的颜色(必传)
vertexShader允许你修改传入的定点位置(必传)
uniforms可想你的着色器发信息,同样的信息会发送给每一个顶点和片段
defines转换成#define代码片段,这些片段可以设置着着色程序里的额外全局变量
attributes可修改每个顶点和片段,用来传递每个位置数据和法向量相关的数据
lights定义光照数据是否传递给着色器,默认false
  • vertexShader:它会在几何体的每个顶点上执行,可用这个着色器改变顶点的位置来对集合体进行变换

  • fragmentShader: 它会在集合体的每一个片段上执行,在VertexShader里,会返回这个特定片段应该显示的颜色

<script id="vertex-shader" type="x-shader/x-vertex">
  uniform float time;
    varying vec2 vUv;

    void main()
    {
    vec3 posChanged = position;
    posChanged.x = posChanged.x*(abs(sin(time*1.0)));
    posChanged.y = posChanged.y*(abs(cos(time*1.0)));
    posChanged.z = posChanged.z*(abs(sin(time*1.0)));
    //gl_Position = projectionMatrix * modelViewMatrix * vec4(position*(abs(sin(time)/2.0)+0.5),1.0);
    gl_Position = projectionMatrix * modelViewMatrix * vec4(posChanged,1.0);
    }

</script>
function createMaterial(vertexShader, fragmentShader) {
  var vertShader = document.getElementById(vertexShader).innerHTML;
  var fragShader = document.getElementById(fragmentShader).innerHTML;

  var attributes = {};
  var uniforms = {
    time: {
      type: 'f',
      value: 0.2
    },
    scale: {
      type: 'f',
      value: 0.2
    },
    alpha: {
      type: 'f',
      value: 0.6
    },
    resolution: {
      type: "v2",
      value: new THREE.Vector2()
    }
  };

  uniforms.resolution.value.x = window.innerWidth;
  uniforms.resolution.value.y = window.innerHeight;

  var meshMaterial = new THREE.ShaderMaterial({
    uniforms: uniforms,
    attributes: attributes,
    vertexShader: vertShader,
    fragmentShader: fragShader,
    transparent: true

  });

  return meshMaterial;
}

var cubeGeometry = new THREE.BoxGeometry(20, 20, 20);

var meshMaterial1 = createMaterial("vertex-shader", "fragment-shader-1");
var meshMaterial2 = createMaterial("vertex-shader", "fragment-shader-2");
var meshMaterial3 = createMaterial("vertex-shader", "fragment-shader-3");
var meshMaterial4 = createMaterial("vertex-shader", "fragment-shader-4");
var meshMaterial5 = createMaterial("vertex-shader", "fragment-shader-5");
var meshMaterial6 = createMaterial("vertex-shader", "fragment-shader-6");

var material = new THREE.MeshFaceMaterial(
  [meshMaterial1,
    meshMaterial2,
    meshMaterial3,
    meshMaterial4,
    meshMaterial5,
    meshMaterial6
  ]);

var cube = new THREE.Mesh(cubeGeometry, material);

THREE. LineBaseMaterial

用于线段的基础材质

名称描述
color线的颜色,指定vertexColors该属性会被忽略
linewidth线的宽度
linecap线段端点,可选只butt(平),round(圆),square(方),默认round
linejoin线段连接,可选只butt(平),round(圆),square(方),默认round
vertexColor每个顶点指定一种颜色
fog当前材质是否受全局无话效果影响
var points = gosper(4, 60); //gosper曲线

var lines = new THREE.Geometry();
var colors = [];
var i = 0;
points.forEach(function(e) {
  lines.vertices.push(new THREE.Vector3(e.x, e.z, e.y));
  colors[i] = new THREE.Color(0xffffff);
  colors[i].setHSL(e.x / 100 + 0.5, (e.y * 20) / 300, 0.8);
  i++;
});

lines.colors = colors;
var material = new THREE.LineBasicMaterial({
  opacity: 1.0,
  linewidth: 1,
  vertexColors: THREE.VertexColors
});

var line = new THREE.Line(lines, material);

THREE. LineDashMaterial

属性与THREE. LineBaseMaterial一样,可指定虚线与空白间隙的长度来创建出虚线效果

名称描述
scale放缩dashSize和gapSize
dashSize虚线长度
gapSize虚线间隔宽度
 lines.computeLineDistances();
 var material = new THREE.LineDashedMaterial({
   vertexColors: true,
   color: 0xffffff,
   dashSize: 2,
   gapSize: 2,
   scale: 0.1
 });
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值