Source file: /examples/camera/tone_mapping.js
import { GUI } from "dat.gui"
import Stats from "stats.js"
import {
ACESFilmicTonemapping,
AgXTonemapping,
AmbientLight,
Camera,
CameraPlugin,
CanvasTarget,
DirectionalLight,
GLTFLoader,
HableTonemapping,
KhronosPBRNeutralTonemapping,
LightPlugin,
MeshMaterialPlugin,
OrbitCameraControls,
PerspectiveProjection,
ReinhardToneMapping,
SkyBox,
SkyboxPlugin,
TextureLoader,
TextureType,
WebGLRenderDevice,
WebGLRenderer,
} from "chorama"
const canvas = document.createElement("canvas")
const renderTarget = new CanvasTarget(canvas)
const renderDevice = new WebGLRenderDevice(canvas)
const renderer = new WebGLRenderer({
plugins: [
new CameraPlugin(),
new LightPlugin(),
new SkyboxPlugin(),
new MeshMaterialPlugin(),
]
})
const camera = new Camera(renderTarget)
const cameraControls = new OrbitCameraControls(camera, canvas)
const textureLoader = new TextureLoader()
const gltfLoader = new GLTFLoader()
const day = textureLoader.load({
paths: [
"/images/skybox/miramar_right.png",
"/images/skybox/miramar_left.png",
"/images/skybox/miramar_top.png",
"/images/skybox/miramar_bottom.png",
"/images/skybox/miramar_back.png",
"/images/skybox/miramar_front.png",
],
type: TextureType.TextureCubeMap,
})
const skyBox = new SkyBox({
day
})
skyBox.transform.orientation.rotateY(Math.PI)
const model = gltfLoader.load({
paths: ["/models/gltf/flight_helmet/index.gltf"]
})
const ambientLight = new AmbientLight()
ambientLight.intensity = 0.18
const directionalLight = new DirectionalLight()
directionalLight.intensity = 28
directionalLight.transform.orientation
.rotateX(-Math.PI / 4)
.rotateZ(-Math.PI / 4)
const toneMappingOptions = {
None: "none",
Reinhard: "reinhard",
Hable: "hable",
"ACES Filmic": "aces_filmic",
AgX: "agx",
"Khronos PBR Neutral": "khronos_pbr_neutral",
}
const settings = {
toneMapping: toneMappingOptions.Reinhard,
exposure: 1,
ambientLight: ambientLight.intensity,
directionalLight: directionalLight.intensity,
}
cameraControls.distance = 0.8
cameraControls.offset.y = 0.5
applyToneMapping()
if (camera.projection instanceof PerspectiveProjection) {
camera.projection.fov = Math.PI / 180 * 75
camera.projection.aspect = innerWidth / innerHeight
}
document.body.append(canvas)
addEventListener("resize", updateView)
updateView()
createControls()
requestAnimationFrame(update)
function update() {
stats.begin()
cameraControls.update()
renderer.render([model, skyBox, ambientLight, directionalLight, camera], renderDevice)
stats.end()
requestAnimationFrame(update)
}
function updateView() {
canvas.style.width = innerWidth + "px"
canvas.style.height = innerHeight + "px"
canvas.width = innerWidth * devicePixelRatio
canvas.height = innerHeight * devicePixelRatio
if (camera.projection instanceof PerspectiveProjection) {
camera.projection.aspect = innerWidth / innerHeight
}
}
function createControls() {
const controls = new GUI()
const cameraFolder = controls.addFolder("Camera")
const lightingFolder = controls.addFolder("Lighting")
cameraFolder
.add(settings, "toneMapping", toneMappingOptions)
.name("Tone Mapping")
.onChange(applyToneMapping)
cameraFolder
.add(settings, "exposure", 0.1, 5, 0.01)
.name("Exposure")
.onChange(applyExposure)
cameraFolder.open()
lightingFolder
.add(settings, "ambientLight", 0, 2, 0.01)
.name("Ambient")
.onChange((value) => {
ambientLight.intensity = value
})
lightingFolder
.add(settings, "directionalLight", 0, 80, 0.1)
.name("Directional")
.onChange((value) => {
directionalLight.intensity = value
})
lightingFolder.open()
}
function applyToneMapping() {
switch (settings.toneMapping) {
case toneMappingOptions.None:
camera.toneMapping = undefined
break
case toneMappingOptions.Hable:
camera.toneMapping = new HableTonemapping({ exposure: settings.exposure })
break
case toneMappingOptions["ACES Filmic"]:
camera.toneMapping = new ACESFilmicTonemapping({ exposure: settings.exposure })
break
case toneMappingOptions.AgX:
camera.toneMapping = new AgXTonemapping({ exposure: settings.exposure })
break
case toneMappingOptions["Khronos PBR Neutral"]:
camera.toneMapping = new KhronosPBRNeutralTonemapping({ exposure: settings.exposure })
break
case toneMappingOptions.Reinhard:
default:
camera.toneMapping = new ReinhardToneMapping({ exposure: settings.exposure })
break
}
}
function applyExposure() {
if (camera.toneMapping) {
camera.toneMapping.exposure = settings.exposure
}
}
// demo-only performance monitor
const stats = new Stats()
stats.showPanel(1)
document.body.append(stats.dom)
stats.dom.removeAttribute("style")
stats.dom.classList.add("performance-monitor")