1. 回顾
初中的时候我们学过“三基色”的概念,其主要表达的是世界的颜色是由红,绿,蓝组成的。今天我们以计算机或者说数学的角度进行分析,为什么会是这个样子?
2. 预备知识:
2.1 颜色的基本表达
在计算机中基础的颜色的表达如下:
// 红色
let red = 0xff0000;
// 绿色
let green = 0x00ff00;
// 蓝色
let blue = 0x0000ff;
// 黑色
let black = 0x000000;
// 白色
let white = 0xffffff;
// 黄色
let yellow = 0xffff00;
// 青色
let cyan = 0x00ffff;
// 紫色
let purple =0xff00ff;
2.2 js代码封装
由于js没有原生方法用于十六进制的计算,所以需要自己封装一个方法,用于计算颜色值。
function calcColors(color1,color2){
return '0x'+(color1|color2).toString(16).padStart(6,0)
}
3. 开始分析
红色 + 绿色 = 黄色 ???
let val = calcColors(red,green);
// 输出:'0xffff00' -> 黄色
绿色 + 蓝色 = 紫色 ???
let val = calcColors(green,blue);
// 输出:'0x00ffff' -> 青色
红色 + 蓝色 = 紫色 ???
let val = calcColors(red,blue);
// 输出:'0xff00ff' -> 紫色
红色 + 蓝色 = 紫色 ???
let val = calcColors(red,blue);
// 输出:'0xff00ff' -> 紫色
红色+蓝色+紫色 = 白色 ???
let val = calcColors(green,calcColors(red,blue));
// 输出:'0xffffff' -> 白色
3. 现实世界的物体
现实世界的物体的性质是:物体本身是什么颜色,就会反射什么光,其他的光就会被物体吸收。
4. 计算机模拟物体的反射
物体的反射计算
function calcColors(color1,color2){
return '0x'+(color1&color2).toString(16).padStart(6,0)
}
4.1 分析
物体颜色:红色 光 : 白色 看到的颜色:红色
let val = calcColors(red,white)
// 输出=> '0xff0000' 红色
物体颜色:红 光:绿色 看到的颜色:黑色
let val = calcColors(red,green)
// 输出=> '0x000000' 黑色
5. 案例
光的反射案例:案例
5.1 代码实现
基于 threejs实现
import gsap from "gsap";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import * as dat from "dat.gui";
// scene
let scene = new THREE.Scene();
/**
* 创建一个球体
*/
let sphereBufferGeometry = new THREE.SphereBufferGeometry(1, 20, 20)
let standardMaterial = new THREE.MeshStandardMaterial({
color: 0xff0000
})
let sphere = new THREE.Mesh(sphereBufferGeometry, standardMaterial)
sphere.castShadow = true;
scene.add(sphere);
// 增加光源
// 环境光
let ambientLight = new THREE.AmbientLight(0xffffff, 1.0);
scene.add(ambientLight)
let params = {
color: 0xff0000,
lightColor: 0xffffff,
}
let gui = new dat.GUI();
let c = gui.addFolder('颜色设置')
c.open();
c.addColor(params, "color")
.onChange(() => {
console.log(params.color);
sphere.material.color = new THREE.Color(params.color);
}).name('物体颜色');
c.addColor(params, "lightColor")
.onChange(() => {
console.log(params.lightColor)
ambientLight.color = new THREE.Color(params.lightColor);
}).name('光的颜色');
/**
* 相机设置
*/
var width = window.innerWidth; //窗口宽度
var height = window.innerHeight; //窗口高度
var k = width / height; //窗口宽高比
var camera = new THREE.PerspectiveCamera(75, k, 0.1, 1000);
camera.position.z = 10;
camera.position.y = 10;
camera.position.x = 10;
let axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
/**
* 渲染器
*/
const renderer = new THREE.WebGLRenderer();
renderer.shadowMap.enabled = true;
renderer.setSize(width, height);
// camera.lookAt(0, 0, 0)
renderer.render(scene, camera);
document.body.appendChild(renderer.domElement);
const controls = new OrbitControls(camera, renderer.domElement)
controls.listenToKeyEvents(document.body)
// 如果不重新绘制,物体会禁止就会不动
function render(time: number) {
renderer.render(scene, camera);
requestAnimationFrame(render);
}
window.requestAnimationFrame(render);
// 监听画面变化,更新渲染画面
window.addEventListener("resize", () => {
// console.log("画面变化了");
// 更新摄像头
camera.aspect = window.innerWidth / window.innerHeight;
// 更新摄像机的投影矩阵
camera.updateProjectionMatrix();
// 更新渲染器
renderer.setSize(window.innerWidth, window.innerHeight);
// 设置渲染器的像素比
renderer.setPixelRatio(window.devicePixelRatio);
});
示例如下:
代码仓库: github.com/hpstream/th…