forked from doodlewind/beam
-
Notifications
You must be signed in to change notification settings - Fork 0
/
material-ball.js
147 lines (131 loc) · 4.49 KB
/
material-ball.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import { Beam, ResourceTypes, GLTypes as GL } from '../../../src/index.js'
import { PBRLighting } from '../../shaders/pbr-lighting-shader.js'
import { createBall } from '../../utils/graphics-utils.js'
import { loadImages, loadEnvMaps } from '../../utils/image-loader.js'
import {
rendererConfig,
createMaterialImages,
computeModelMat,
computeEye,
computeMVPMat,
createPointLights
} from './pbr-utils.js'
const { VertexBuffers, IndexBuffer, Uniforms, Textures } = ResourceTypes
const canvas = document.querySelector('canvas')
canvas.height = document.body.offsetHeight
canvas.width = document.body.offsetWidth
const beam = new Beam(canvas, rendererConfig)
const shader = beam.shader(PBRLighting)
// Resources: vertex buffers and index buffer
const ball = createBall()
const ballBuffers = [
beam.resource(VertexBuffers, ball.vertex),
beam.resource(IndexBuffer, ball.index)
]
// Resources: camera and model matrices
const baseEye = [0, 0, 10]
const center = [0, 0, 0]
const modelMat = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
const matrices = beam.resource(Uniforms, {
uCamera: baseEye,
uModelMatrix: modelMat,
uMVPMatrix: computeMVPMat(modelMat, baseEye, center, canvas)
})
// Resources: point light states
const pointLights = beam.resource(Uniforms, createPointLights())
pointLights
.set(`uLights[0].direction`, [1, 1, 1])
.set(`uLights[0].strength`, 1)
// Resources: material images
const materialMaps = beam.resource(Textures, createMaterialImages())
// Resources: environment maps and BRDF map
let brdfMap
let envMaps
// Resourecs: other options
const pbrOptions = beam.resource(Uniforms, {
uMetallicRoughnessValues: [0, 0]
})
const render = () => {
const resources = [
...ballBuffers,
brdfMap,
envMaps,
materialMaps,
matrices,
pointLights,
pbrOptions
]
beam.clear().draw(shader, ...resources)
}
const base = '../../assets/'
Promise.all([
loadEnvMaps(base + 'ibl/helipad'), loadImages(base + 'ibl/brdfLUT.png')
]).then(([[diffuseState, specularState], [brdf]]) => {
diffuseState.minFilter = GL.Linear
diffuseState.space = GL.SRGB
specularState.minFilter = GL.LinearMipmapLinear
specularState.space = GL.SRGB
brdfMap = beam.resource(Textures, {
uBrdfLUT: { image: brdf, wrapS: GL.ClampToEdge, wrapT: GL.ClampToEdge }
})
envMaps = beam.resource(Textures, {
uDiffuseEnvSampler: diffuseState,
uSpecularEnvSampler: specularState
})
render()
})
// Update Rotates
const $xRotate = document.getElementById('x-rotate')
const $yRotate = document.getElementById('y-rotate')
const $zRotate = document.getElementById('z-rotate')
const $cameraRotate = document.getElementById('camera-rotate')
const updateMats = () => {
const [rx, ry, rz] = [$xRotate.value, $yRotate.value, $zRotate.value]
const cameraRotate = $cameraRotate.value
const modelMat = computeModelMat(rx, ry, rz)
const eye = computeEye(baseEye, cameraRotate)
matrices
.set('uModelMatrix', modelMat)
.set('uCamera', eye)
.set('uMVPMatrix', computeMVPMat(modelMat, eye, center, canvas))
render()
}
;[$xRotate, $yRotate, $zRotate, $cameraRotate].forEach($input => {
$input.addEventListener('input', updateMats)
})
// Update Metalness Roughness
const $metallic = document.getElementById('metallic')
const $roughness = document.getElementById('roughness')
const updateMetalRoughness = () => {
const mr = [$metallic.value, $roughness.value]
pbrOptions.set('uMetallicRoughnessValues', mr)
render()
}
$metallic.addEventListener('input', updateMetalRoughness)
$roughness.addEventListener('input', updateMetalRoughness)
// Update Lights
for (let i = 0; i < 1; i++) {
const $lightX = document.getElementById(`light-${i}-x`)
const $lightY = document.getElementById(`light-${i}-y`)
const $lightZ = document.getElementById(`light-${i}-z`)
const $lightStrength = document.getElementById(`light-${i}-strength`)
const $lightColor = document.getElementById(`light-${i}-color`)
const updatePointLights = () => {
const direction = [$lightX.value, $lightY.value, $lightZ.value]
const hex = $lightColor.value
const rgb = [
parseInt(hex.slice(1, 3), 16) / 256,
parseInt(hex.slice(3, 5), 16) / 256,
parseInt(hex.slice(5, 7), 16) / 256
]
pointLights
.set(`uLights[${i}].direction`, direction)
.set(`uLights[${i}].strength`, $lightStrength.value)
.set(`uLights[${i}].color`, rgb)
render()
}
;[$lightX, $lightY, $lightZ, $lightStrength, $lightColor].forEach($input => {
$input.addEventListener('input', updatePointLights)
})
}
window.beam = beam