├── screenshot.png
├── public
├── favicon.ico
├── ogimage.png
├── favicon-16x16.png
├── favicon-32x32.png
├── mstile-150x150.png
├── apple-touch-icon.png
├── android-chrome-192x192.png
├── browserconfig.xml
├── site.webmanifest
└── index.html
├── sandbox.config.json
├── .prettierrc
├── README.md
├── .gitignore
├── src
├── index.js
├── data.js
├── Scene.js
└── ThinFilmFresnelMap.js
└── package.json
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emmelleppi/r3f-mirrors/HEAD/screenshot.png
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emmelleppi/r3f-mirrors/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/public/ogimage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emmelleppi/r3f-mirrors/HEAD/public/ogimage.png
--------------------------------------------------------------------------------
/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emmelleppi/r3f-mirrors/HEAD/public/favicon-16x16.png
--------------------------------------------------------------------------------
/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emmelleppi/r3f-mirrors/HEAD/public/favicon-32x32.png
--------------------------------------------------------------------------------
/public/mstile-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emmelleppi/r3f-mirrors/HEAD/public/mstile-150x150.png
--------------------------------------------------------------------------------
/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emmelleppi/r3f-mirrors/HEAD/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emmelleppi/r3f-mirrors/HEAD/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/sandbox.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "infiniteLoopProtection": false,
3 | "hardReloadOnChange": false,
4 | "view": "browser"
5 | }
6 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 160,
3 | "tabWidth": 2,
4 | "useTabs": false,
5 | "semi": false,
6 | "singleQuote": true,
7 | "trailingComma": "none",
8 | "bracketSpacing": true,
9 | "jsxBracketSameLine": true
10 | }
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Preview ◼️ https://r3f-mirrors.netlify.app/ ◼️
2 |
3 | 
4 |
5 | ```bash
6 | # using yarn
7 | yarn && yarn start
8 |
9 | # using npm
10 | npm install && npm run start
11 | ```
12 |
--------------------------------------------------------------------------------
/public/browserconfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | #da532c
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {
2 | "name": "",
3 | "short_name": "",
4 | "icons": [
5 | {
6 | "src": "/android-chrome-192x192.png",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "theme_color": "#ffffff",
12 | "background_color": "#ffffff",
13 | "display": "standalone"
14 | }
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import { render } from 'react-dom'
2 | import React, { Suspense } from 'react'
3 | import { Canvas } from 'react-three-fiber'
4 | import * as THREE from 'three'
5 |
6 | import Scene from './Scene'
7 |
8 | function App() {
9 | return (
10 |
17 | )
18 | }
19 |
20 | render(, document.querySelector('#root'))
21 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "use-r3f-assets",
3 | "version": "1.0.0",
4 | "description": "",
5 | "keywords": [],
6 | "main": "src/index.js",
7 | "dependencies": {
8 | "drei": "1.5.6",
9 | "react": "17.0.0-rc.1",
10 | "react-dom": "17.0.0-rc.1",
11 | "react-scripts": "3.4.3",
12 | "react-three-fiber": "5.0.0-beta.12",
13 | "three": "0.120.1"
14 | },
15 | "devDependencies": {},
16 | "scripts": {
17 | "start": "react-scripts start",
18 | "build": "react-scripts build",
19 | "test": "react-scripts test --env=jsdom",
20 | "eject": "react-scripts eject"
21 | },
22 | "browserslist": [
23 | ">0.2%",
24 | "not dead",
25 | "not ie <= 11",
26 | "not op_mini all"
27 | ]
28 | }
29 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
43 |
44 |
53 | Mirrors ◼️ A React Three Fiber demo
54 |
55 |
56 |
57 |
58 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/src/data.js:
--------------------------------------------------------------------------------
1 | export const mirrorsData = {
2 | mirrors: [
3 | {
4 | args: [2.87483173052424, 2.920755196190408, 0.05],
5 | position: [3.116376203948097, -2.1742814140991196, -7.998859699752443],
6 | rotation: [1.2536197471688286, -1.6683567077395978, -2.8428053193736256]
7 | },
8 | {
9 | args: [1.799233278635274, 1.9642524560408021, 0.05],
10 | position: [-3.325473394997085, 3.5307542721423446, -6.530151273151705],
11 | rotation: [1.3951213133257899, -0.2888432911308304, 0.7178380971731012]
12 | },
13 | {
14 | args: [2.8780801433198553, 2.9065216543855974, 0.05],
15 | position: [1.2839348832937714, 2.888947614684322, -6.467835086028824],
16 | rotation: [-1.3341775957580109, 2.8031736269533125, -0.18771283594857274]
17 | },
18 | {
19 | args: [2.2175936863874006, 1.3820832190972703, 0.05],
20 | position: [4.552400557892, 0.9814639517113943, -5.836395383986279],
21 | rotation: [-2.3299625953354437, 0.6139693063561498, -0.3902201705507059]
22 | },
23 | {
24 | args: [1.7446126775638997, 2.6211835436253392, 0.05],
25 | position: [-2.826056860647832, -3.0308788716782042, -5.4685371584057485],
26 | rotation: [-1.4052581815125295, 3.002812728418492, 2.54202362440499]
27 | },
28 | {
29 | args: [1.139549518339333, 1.8007363020629232, 0.05],
30 | position: [-0.041834072623521124, -1.351281881742426, -2.40411451302583],
31 | rotation: [1.2848394396618561, -0.310029190116405, -2.107987000676972]
32 | },
33 | {
34 | args: [2.2021865186914007, 2.610358395964105, 0.05],
35 | position: [-4.1542927375782015, -0.349560252979882, -2.489538720961452],
36 | rotation: [1.4401104979160235, 1.8179123712769852, -2.2157249608220475]
37 | },
38 | {
39 | args: [2.0964670262303393, 1.5750930602784585, 0.05],
40 | position: [6.571372497652996, -2.6457284555412066, -6.252562745592483],
41 | rotation: [1.1870955922970219, 0.5335941225301444, 0.4523391139946649]
42 | },
43 | {
44 | args: [1.3270056676441064, 1.5169873297208318, 0.05],
45 | position: [3.6761316187794724, -4.141729519755186, -4.39063863430271],
46 | rotation: [-0.7690386626408349, 1.4093151276977963, 2.0252977680762476]
47 | },
48 | {
49 | args: [5.1426105440458216, 4.416201863189162, 0.05],
50 | position: [0.646982562789564, 7.0909673302614196, -8.351518200349154],
51 | rotation: [-0.0692356415822184, 1.918047448701773, 0.5268942683942657]
52 | }
53 | ]
54 | }
55 |
56 | export const textData = [
57 | {
58 | position: [0, 0, -10],
59 | rotation: [0, 0, 0],
60 | scale: [1, 1, 1]
61 | },
62 | {
63 | position: [0, 0, 10],
64 | rotation: [0, 0, 0],
65 | scale: [-1, 1, 1]
66 | },
67 | {
68 | position: [-10, 0, 0],
69 | rotation: [0, Math.PI / 2, 0],
70 | scale: [1, 1, 1]
71 | },
72 | {
73 | position: [10, 0, 0],
74 | rotation: [0, -Math.PI / 2, 0],
75 | scale: [-1, 1, 1]
76 | },
77 | {
78 | position: [0, 10, 0],
79 | rotation: [Math.PI / 2, 0, 0],
80 | scale: [1, 1, 1]
81 | },
82 | {
83 | position: [0, -10, 0],
84 | rotation: [-Math.PI / 2, 0, 0],
85 | scale: [-1, 1, 1]
86 | }
87 | ]
88 |
--------------------------------------------------------------------------------
/src/Scene.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useMemo, useRef, useState } from 'react'
2 | import * as THREE from 'three'
3 | import { useFrame, useThree, useResource } from 'react-three-fiber'
4 | import { Text, Box, useMatcapTexture, Octahedron, OrbitControls } from 'drei'
5 |
6 | import { ThinFilmFresnelMap } from './ThinFilmFresnelMap'
7 | import { mirrorsData } from './data'
8 |
9 | const textProps = {
10 | fontSize: 3.9,
11 | font: 'https://fonts.gstatic.com/s/raleway/v17/1Ptxg8zYS_SKggPN4iEgvnHyvveLxVtzpbCIPrcVIT9d0c8.woff'
12 | }
13 |
14 | function Title({ layers = undefined, ...props }) {
15 | const group = useRef()
16 | useEffect(() => {
17 | group.current.lookAt(0, 0, 0)
18 | }, [])
19 |
20 | return (
21 |
22 |
23 | R
24 |
25 |
26 | 3
27 |
28 |
29 | F
30 |
31 |
32 | )
33 | }
34 |
35 | function Mirror({ sideMaterial, reflectionMaterial, args, ...props }) {
36 | const ref = useRef()
37 |
38 | useFrame(() => {
39 | ref.current.rotation.y += 0.001
40 | ref.current.rotation.z += 0.01
41 | })
42 |
43 | return
44 | }
45 |
46 | function Mirrors({ envMap }) {
47 | const sideMaterial = useResource()
48 | const reflectionMaterial = useResource()
49 | const [thinFilmFresnelMap] = useState(new ThinFilmFresnelMap())
50 |
51 | return (
52 |
53 |
54 |
55 |
56 | {mirrorsData.mirrors.map((mirror, index) => (
57 |
58 | ))}
59 |
60 | )
61 | }
62 |
63 | function TitleCopies({ layers }) {
64 | const vertices = useMemo(() => {
65 | const y = new THREE.IcosahedronGeometry(8)
66 | return y.vertices
67 | }, [])
68 |
69 | return (
70 |
71 | {vertices.map((vertex, i) => (
72 |
73 | ))}
74 |
75 | )
76 | }
77 |
78 | export default function Scene() {
79 | const renderTarget = useMemo(
80 | () => new THREE.WebGLCubeRenderTarget(1024, { format: THREE.RGBAFormat, generateMipmaps: true, minFilter: THREE.LinearMipmapLinearFilter }),
81 | []
82 | )
83 |
84 | const camera = useRef()
85 | const sphere = useRef()
86 |
87 | const [matcapTexture] = useMatcapTexture('C8D1DC_575B62_818892_6E747B', 1024)
88 |
89 | useFrame(({ gl, scene }) => {
90 | camera.current.update(gl, scene)
91 | })
92 |
93 | const group = useRef()
94 |
95 | const { viewport } = useThree()
96 |
97 | const [rotationEuler, rotationQuaternion] = useMemo(() => {
98 | return [new THREE.Euler(0, 0, 0), new THREE.Quaternion(0, 0, 0, 0)]
99 | }, [])
100 |
101 | useFrame(({ mouse }) => {
102 | const x = (mouse.x * viewport.width) / 100
103 | const y = (mouse.y * viewport.height) / 100
104 |
105 | rotationEuler.set(y, x, 0)
106 | rotationQuaternion.setFromEuler(rotationEuler)
107 |
108 | group.current.quaternion.slerp(rotationQuaternion, 0.1)
109 | })
110 |
111 | return (
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 | {window.location.search.indexOf('ctrl') > -1 && }
124 |
125 | )
126 | }
127 |
--------------------------------------------------------------------------------
/src/ThinFilmFresnelMap.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @classdesc
3 | * ThinFilmFresnelMap is a lookup texture containing the reflection colour. The texture index value
4 | * is dot(normal, view). The texture values are stored in approximated gamma space (power 2.0), so
5 | * the sampled value needs to be multiplied with itself before use. The sampled value should replace
6 | * the fresnel factor in a PBR material.
7 | *
8 | * @property filmThickness The thickness of the thin film layer in nanometers. Defaults to 380.
9 | * @property refractiveIndexFilm The refractive index of the thin film. Defaults to 2.
10 | * @property refractiveIndexBase The refractive index of the material under the film. Defaults to 3.
11 | *
12 | * @constructor
13 | * @param filmThickness The thickness of the thin film layer in nanometers. Defaults to 380.
14 | * @param refractiveIndexFilm The refractive index of the thin film. Defaults to 2.
15 | * @param refractiveIndexBase The refractive index of the material under the film. Defaults to 3.
16 | * @param size The width of the texture. Defaults to 64.
17 | *
18 | * @extends DataTexture
19 | *
20 | * @author David Lenaerts
21 | */
22 | import * as THREE from 'three'
23 |
24 | export function ThinFilmFresnelMap(filmThickness, refractiveIndexFilm, refractiveIndexBase, size) {
25 | this._filmThickness = filmThickness || 500.0
26 | this._refractiveIndexFilm = refractiveIndexFilm || 2
27 | this._refractiveIndexBase = refractiveIndexBase || 3
28 | this._size = size || 128
29 | this._data = new Uint8Array(this._size * 4)
30 |
31 | this._updateData()
32 |
33 | THREE.DataTexture.call(
34 | this,
35 | this._data,
36 | this._size,
37 | 1,
38 | THREE.RGBAFormat,
39 | THREE.UnsignedByteType,
40 | THREE.UVMapping,
41 | THREE.RepeatWrapping,
42 | THREE.RepeatWrapping,
43 | THREE.LinearFilter,
44 | THREE.LinearMipMapLinearFilter
45 | )
46 | this.generateMipmaps = true
47 | this.needsUpdate = true
48 | }
49 |
50 | ThinFilmFresnelMap.prototype = Object.create(THREE.DataTexture.prototype, {
51 | filmThickness: {
52 | get: function () {
53 | return this._filmThickness
54 | },
55 | set: function (value) {
56 | this._filmThickness = value
57 | this.updateSettings(this._filmThickness, this._refractiveIndexFilm, this._refractiveIndexBase)
58 | }
59 | },
60 | refractiveIndexFilm: {
61 | get: function () {
62 | return this._refractiveIndexFilm
63 | },
64 | set: function (value) {
65 | this._refractiveIndexFilm = value
66 | this.updateSettings(this._filmThickness, this._refractiveIndexFilm, this._refractiveIndexBase)
67 | }
68 | },
69 | refractiveIndexBase: {
70 | get: function () {
71 | return this._refractiveIndexBase
72 | },
73 | set: function (value) {
74 | this._refractiveIndexBase = value
75 | this.updateSettings(this._filmThickness, this._refractiveIndexFilm, this._refractiveIndexBase)
76 | }
77 | }
78 | })
79 |
80 | /**
81 | * Regenerates the lookup texture given new data.
82 | * @param filmThickness The thickness of the thin film layer in nanometers. Defaults to 380.
83 | * @param refractiveIndexFilm The refractive index of the thin film. Defaults to 2.
84 | * @param refractiveIndexBase The refractive index of the material under the film. Defaults to 3.
85 | */
86 | ThinFilmFresnelMap.prototype.updateSettings = function (filmThickness, refractiveIndexFilm, refractiveIndexBase) {
87 | this._filmThickness = filmThickness || 380
88 | this._refractiveIndexFilm = refractiveIndexFilm || 2
89 | this._refractiveIndexBase = refractiveIndexBase || 3
90 | this._updateData()
91 | }
92 |
93 | /**
94 | * @private
95 | */
96 | ThinFilmFresnelMap.prototype._fresnelRefl = function (refractiveIndex1, refractiveIndex2, cos1, cos2, R, phi) {
97 | // r is amplitudinal, R is power
98 | var sin1Sqr = 1.0 - cos1 * cos1 // = sin^2(incident)
99 | var refrRatio = refractiveIndex1 / refractiveIndex2
100 |
101 | if (refrRatio * refrRatio * sin1Sqr > 1.0) {
102 | // total internal reflection
103 | R.x = 1.0
104 | R.y = 1.0
105 |
106 | var sqrRefrRatio = refrRatio * refrRatio
107 | // it looks like glsl's atan ranges are different from those in JS?
108 | phi.x = 2.0 * Math.atan((-sqrRefrRatio * Math.sqrt(sin1Sqr - 1.0 / sqrRefrRatio)) / cos1)
109 | phi.y = 2.0 * Math.atan(-Math.sqrt(sin1Sqr - 1.0 / sqrRefrRatio) / cos1)
110 | } else {
111 | var r_p = (refractiveIndex2 * cos1 - refractiveIndex1 * cos2) / (refractiveIndex2 * cos1 + refractiveIndex1 * cos2)
112 | var r_s = (refractiveIndex1 * cos1 - refractiveIndex2 * cos2) / (refractiveIndex1 * cos1 + refractiveIndex2 * cos2)
113 |
114 | phi.x = r_p < 0.0 ? Math.PI : 0.0
115 | phi.y = r_s < 0.0 ? Math.PI : 0.0
116 |
117 | R.x = r_p * r_p
118 | R.y = r_s * r_s
119 | }
120 | }
121 |
122 | /**
123 | * @private
124 | */
125 | ThinFilmFresnelMap.prototype._updateData = function () {
126 | var filmThickness = this._filmThickness
127 | var refractiveIndexFilm = this._refractiveIndexFilm
128 | var refractiveIndexBase = this._refractiveIndexBase
129 | var size = this._size
130 |
131 | // approximate CIE XYZ weighting functions from: http://jcgt.org/published/0002/02/01/paper.pdf
132 | function xFit_1931(lambda) {
133 | var t1 = (lambda - 442.0) * (lambda < 442.0 ? 0.0624 : 0.0374)
134 | var t2 = (lambda - 599.8) * (lambda < 599.8 ? 0.0264 : 0.0323)
135 | var t3 = (lambda - 501.1) * (lambda < 501.1 ? 0.049 : 0.0382)
136 | return 0.362 * Math.exp(-0.5 * t1 * t1) + 1.056 * Math.exp(-0.5 * t2 * t2) - 0.065 * Math.exp(-0.5 * t3 * t3)
137 | }
138 |
139 | function yFit_1931(lambda) {
140 | var t1 = (lambda - 568.8) * (lambda < 568.8 ? 0.0213 : 0.0247)
141 | var t2 = (lambda - 530.9) * (lambda < 530.9 ? 0.0613 : 0.0322)
142 | return 0.821 * Math.exp(-0.5 * t1 * t1) + 0.286 * Math.exp(-0.5 * t2 * t2)
143 | }
144 |
145 | function zFit_1931(lambda) {
146 | var t1 = (lambda - 437.0) * (lambda < 437.0 ? 0.0845 : 0.0278)
147 | var t2 = (lambda - 459.0) * (lambda < 459.0 ? 0.0385 : 0.0725)
148 | return 1.217 * Math.exp(-0.5 * t1 * t1) + 0.681 * Math.exp(-0.5 * t2 * t2)
149 | }
150 |
151 | var data = this._data
152 | var phi12 = new THREE.Vector2()
153 | var phi21 = new THREE.Vector2()
154 | var phi23 = new THREE.Vector2()
155 | var R12 = new THREE.Vector2()
156 | var T12 = new THREE.Vector2()
157 | var R23 = new THREE.Vector2()
158 | var R_bi = new THREE.Vector2()
159 | var T_tot = new THREE.Vector2()
160 | var R_star = new THREE.Vector2()
161 | var R_bi_sqr = new THREE.Vector2()
162 | var R_12_star = new THREE.Vector2()
163 | var R_star_t_tot = new THREE.Vector2()
164 |
165 | var refrRatioSqr = 1.0 / (refractiveIndexFilm * refractiveIndexFilm)
166 | var refrRatioSqrBase = (refractiveIndexFilm * refractiveIndexFilm) / (refractiveIndexBase * refractiveIndexBase)
167 |
168 | // RGB is too limiting, so we use the entire spectral domain, but using limited samples (64) to
169 | // create more pleasing bands
170 | var numBands = 64
171 | var waveLenRange = 780 - 380 // the entire visible range
172 |
173 | for (var i = 0; i < size; ++i) {
174 | var cosThetaI = i / size
175 | var cosThetaT = Math.sqrt(1 - refrRatioSqr * (1.0 - cosThetaI * cosThetaI))
176 | var cosThetaT2 = Math.sqrt(1 - refrRatioSqrBase * (1.0 - cosThetaT * cosThetaT))
177 |
178 | // this is essentially the extra distance traveled by a ray if it bounds through the film
179 | var pathDiff = 2.0 * refractiveIndexFilm * filmThickness * cosThetaT
180 | var pathDiff2PI = 2.0 * Math.PI * pathDiff
181 |
182 | this._fresnelRefl(1.0, refractiveIndexFilm, cosThetaI, cosThetaT, R12, phi12)
183 | T12.x = 1.0 - R12.x
184 | T12.y = 1.0 - R12.y
185 | phi21.x = Math.PI - phi12.x
186 | phi21.y = Math.PI - phi12.y
187 |
188 | // this concerns the base layer
189 | this._fresnelRefl(refractiveIndexFilm, refractiveIndexBase, cosThetaT, cosThetaT2, R23, phi23)
190 | R_bi.x = Math.sqrt(R23.x * R12.x)
191 | R_bi.y = Math.sqrt(R23.y * R12.y)
192 | T_tot.x = Math.sqrt(T12.x * T12.x)
193 | T_tot.y = Math.sqrt(T12.y * T12.y)
194 | R_star.x = (T12.x * T12.x * R23.x) / (1.0 - R23.x * R12.x)
195 | R_star.y = (T12.y * T12.y * R23.y) / (1.0 - R23.y * R12.y)
196 | R_bi_sqr.x = R_bi.x * R_bi.x
197 | R_bi_sqr.y = R_bi.y * R_bi.y
198 | R_12_star.x = R12.x + R_star.x
199 | R_12_star.y = R12.y + R_star.y
200 | R_star_t_tot.x = R_star.x - T_tot.x
201 | R_star_t_tot.y = R_star.y - T_tot.y
202 | var x = 0,
203 | y = 0,
204 | z = 0
205 | var totX = 0,
206 | totY = 0,
207 | totZ = 0
208 |
209 | // TODO: we could also put the thickness in the look-up table, make it a 2D table
210 | for (var j = 0; j < numBands; ++j) {
211 | var waveLen = 380 + (j / (numBands - 1)) * waveLenRange
212 | var deltaPhase = pathDiff2PI / waveLen
213 |
214 | var cosPhiX = Math.cos(deltaPhase + phi23.x + phi21.x)
215 | var cosPhiY = Math.cos(deltaPhase + phi23.y + phi21.y)
216 | var valX = R_12_star.x + ((2.0 * (R_bi.x * cosPhiX - R_bi_sqr.x)) / (1.0 - 2 * R_bi.x * cosPhiX + R_bi_sqr.x)) * R_star_t_tot.x
217 | var valY = R_12_star.y + ((2.0 * (R_bi.y * cosPhiY - R_bi_sqr.y)) / (1.0 - 2 * R_bi.y * cosPhiY + R_bi_sqr.y)) * R_star_t_tot.y
218 | var v = 0.5 * (valX + valY)
219 |
220 | var wx = xFit_1931(waveLen)
221 | var wy = yFit_1931(waveLen)
222 | var wz = zFit_1931(waveLen)
223 |
224 | totX += wx
225 | totY += wy
226 | totZ += wz
227 |
228 | x += wx * v
229 | y += wy * v
230 | z += wz * v
231 | }
232 |
233 | x /= totX
234 | y /= totY
235 | z /= totZ
236 |
237 | var r = 3.2406 * x - 1.5372 * y - 0.4986 * z
238 | var g = -0.9689 * x + 1.8758 * y + 0.0415 * z
239 | var b = 0.0557 * x - 0.204 * y + 1.057 * z
240 |
241 | r = THREE.Math.clamp(r, 0.0, 1.0)
242 | g = THREE.Math.clamp(g, 0.0, 1.0)
243 | b = THREE.Math.clamp(b, 0.0, 1.0)
244 |
245 | // linear to gamma
246 | r = Math.sqrt(r)
247 | g = Math.sqrt(g)
248 | b = Math.sqrt(b)
249 |
250 | // CIE XYZ to linear rgb conversion matrix:
251 | // 3.2406 -1.5372 -0.4986
252 | // -0.9689 1.8758 0.0415
253 | // 0.0557 -0.2040 1.0570
254 |
255 | var k = i << 2
256 | data[k] = Math.floor(r * 0xff)
257 | data[k + 1] = Math.floor(g * 0xff)
258 | data[k + 2] = Math.floor(b * 0xff)
259 | data[k + 3] = 0xff
260 | }
261 |
262 | this.needsUpdate = true
263 | }
264 |
--------------------------------------------------------------------------------