Skip to content

Commit

Permalink
Examples: Add webgl_loader_gainmap (#27183)
Browse files Browse the repository at this point in the history
* initial work for adding gainmap loader example

* added tags

* better example with file size and resolution comparison

* updated example to latest gainmap-js release 2.0.3 which fixes some compatibility problems in some browsers and platforms + adds progress handler for separate gainmap data

* should solve test failing problems

* updated loader name to HDRJPGLoader

* renamed vars for clarity

* some more renaming

* restored magFilter configuration for HDR
  • Loading branch information
daniele-pelagatti authored Nov 19, 2023
1 parent 4c5c68f commit 0582b00
Show file tree
Hide file tree
Showing 9 changed files with 357 additions and 0 deletions.
1 change: 1 addition & 0 deletions examples/files.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
"webgl_loader_collada_skinning",
"webgl_loader_draco",
"webgl_loader_fbx",
"webgl_loader_gainmap",
"webgl_loader_fbx_nurbs",
"webgl_loader_gcode",
"webgl_loader_gltf",
Expand Down
Binary file added examples/screenshots/webgl_loader_gainmap.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions examples/tags.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"webgl_lines_fat": [ "gpu", "stats", "panel" ],
"webgl_lines_fat_raycasting": [ "gpu", "stats", "panel", "raycast" ],
"webgl_loader_ttf": [ "text", "font" ],
"webgl_loader_gainmap": [ "external", "hdr", "gainmap", "ultrahdr" ],
"webgl_loader_pdb": [ "molecules", "css2d" ],
"webgl_loader_ldraw": [ "lego" ],
"webgl_loader_ifc": [ "external" ],
Expand Down
Binary file added examples/textures/gainmap/spruit_sunrise_1k.hdr
Binary file not shown.
Binary file not shown.
Binary file added examples/textures/gainmap/spruit_sunrise_4k.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 29 additions & 0 deletions examples/textures/gainmap/spruit_sunrise_4k.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"gainMapMax": [
15.99929538702341,
15.99929538702341,
15.99929538702341
],
"gainMapMin": [
0,
0,
0
],
"gamma": [
1,
1,
1
],
"hdrCapacityMax": 15.99929538702341,
"hdrCapacityMin": 0,
"offsetHdr": [
0.015625,
0.015625,
0.015625
],
"offsetSdr": [
0.015625,
0.015625,
0.015625
]
}
Binary file added examples/textures/gainmap/spruit_sunrise_4k.webp
Binary file not shown.
326 changes: 326 additions & 0 deletions examples/webgl_loader_gainmap.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,326 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - gainmap hdr</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
<style>
.lbl {
color: #fff;
font-size: 16px;
font-weight: bold;
position: absolute;
bottom: 0px;
z-index: 100;
text-shadow: #000 1px 1px 1px;
background-color: rgba(0,0,0,0.85);
padding: 1em;
}

#lbl_left {
text-align:left;
left:0px;
}
</style>
</head>

<body>
<div id="info">
<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - gain map (ultra hdr) loader <br/>
Gain map images converted from hdr with <a href="https://gainmap-creator.mono-grid.com/" target="_blank" rel="noopener">Gain map converter</a>. <br />
See external <a href="https://github.com/MONOGRID/gainmap-js" target="_blank" rel="noopener">gainmap-js</a> for more information on how to use and create gain map images.
</div>

<div id="lbl_left" class="lbl"></div>

<script type="importmap">
{
"imports": {
"three": "../build/three.module.js",
"three/addons/": "./jsm/",
"@monogrid/gainmap-js": "https://unpkg.com/@monogrid/gainmap-js@2.0.5/dist/decode.js"
}
}
</script>

<script type="module">

import * as THREE from 'three';

import Stats from 'three/addons/libs/stats.module.js';

import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { RGBELoader } from 'three/addons/loaders/RGBELoader.js';

import { GainMapLoader, HDRJPGLoader } from '@monogrid/gainmap-js';

const params = {
envMap: 'HDR JPG',
roughness: 0.0,
metalness: 0.0,
exposure: 1.0,
debug: false
};

let container, stats;
let camera, scene, renderer, controls;
let torusMesh, planeMesh;
let hdrJpg, hdrJpgPMREMRenderTarget, hdrJpgEquirectangularMap;
let gainMap, gainMapPMREMRenderTarget, gainMapBackground;
let hdrPMREMRenderTarget, hdrEquirectangularMap;


const fileSizes = {};
const resolutions = {};

init();
animate();

function init() {

const lbl = document.getElementById( 'lbl_left' );

container = document.createElement( 'div' );
document.body.appendChild( container );

camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 0, 0, 120 );

scene = new THREE.Scene();
scene.background = new THREE.Color( 0x000000 );

renderer = new THREE.WebGLRenderer();
renderer.toneMapping = THREE.ACESFilmicToneMapping;

//

let geometry = new THREE.TorusKnotGeometry( 18, 8, 150, 20 );
// let geometry = new THREE.SphereGeometry( 26, 64, 32 );
let material = new THREE.MeshStandardMaterial( {
color: 0xffffff,
metalness: params.metalness,
roughness: params.roughness
} );

torusMesh = new THREE.Mesh( geometry, material );
scene.add( torusMesh );


geometry = new THREE.PlaneGeometry( 200, 200 );
material = new THREE.MeshBasicMaterial();

planeMesh = new THREE.Mesh( geometry, material );
planeMesh.position.y = - 50;
planeMesh.rotation.x = - Math.PI * 0.5;
scene.add( planeMesh );


const pmremGenerator = new THREE.PMREMGenerator( renderer );
pmremGenerator.compileEquirectangularShader();

THREE.DefaultLoadingManager.onLoad = function ( ) {

pmremGenerator.dispose();

};



hdrJpg = new HDRJPGLoader( renderer )
.load( 'textures/gainmap/spruit_sunrise_4k.jpg', function ( ) {

resolutions[ 'HDR JPG' ] = hdrJpg.width + 'x' + hdrJpg.height;
displayStats( 'HDR JPG' );

hdrJpgPMREMRenderTarget = pmremGenerator.fromEquirectangular( hdrJpg.renderTarget.texture );

hdrJpgEquirectangularMap = hdrJpg.toDataTexture();
hdrJpgEquirectangularMap.mapping = THREE.EquirectangularReflectionMapping;
hdrJpgEquirectangularMap.minFilter = THREE.LinearFilter;
hdrJpgEquirectangularMap.magFilter = THREE.LinearFilter;
hdrJpgEquirectangularMap.generateMipmaps = false;

hdrJpgEquirectangularMap.needsUpdate = true;

}, function ( progress ) {

fileSizes[ 'HDR JPG' ] = humanFileSize( progress.total );

} );

gainMap = new GainMapLoader( renderer )
.load( [
'textures/gainmap/spruit_sunrise_4k.webp',
'textures/gainmap/spruit_sunrise_4k-gainmap.webp',
'textures/gainmap/spruit_sunrise_4k.json'
], function ( ) {

resolutions[ 'Webp Gain map (separate)' ] = gainMap.width + 'x' + gainMap.height;

gainMapPMREMRenderTarget = pmremGenerator.fromEquirectangular( gainMap.renderTarget.texture );

gainMapBackground = gainMap.toDataTexture();
gainMapBackground.mapping = THREE.EquirectangularReflectionMapping;
gainMapBackground.minFilter = THREE.LinearFilter;
gainMapBackground.magFilter = THREE.LinearFilter;
gainMapBackground.generateMipmaps = false;

gainMapBackground.needsUpdate = true;

}, function ( progress ) {

fileSizes[ 'Webp Gain map (separate)' ] = humanFileSize( progress.total );

} );

hdrEquirectangularMap = new RGBELoader()
.load( 'textures/gainmap/spruit_sunrise_1k.hdr', function ( ) {

resolutions[ 'HDR' ] = hdrEquirectangularMap.image.width + 'x' + hdrEquirectangularMap.image.height;

hdrPMREMRenderTarget = pmremGenerator.fromEquirectangular( hdrEquirectangularMap );

hdrEquirectangularMap.mapping = THREE.EquirectangularReflectionMapping;
hdrEquirectangularMap.minFilter = THREE.LinearFilter;
hdrEquirectangularMap.magFilter = THREE.LinearFilter;
hdrEquirectangularMap.needsUpdate = true;

}, function ( progress ) {

fileSizes[ 'HDR' ] = humanFileSize( progress.total );

} );

renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );

stats = new Stats();
container.appendChild( stats.dom );

controls = new OrbitControls( camera, renderer.domElement );
controls.minDistance = 50;
controls.maxDistance = 300;

window.addEventListener( 'resize', onWindowResize );

const gui = new GUI();

gui.add( params, 'envMap', [ 'HDR JPG', 'Webp Gain map (separate)', 'HDR' ] ).onChange( displayStats );
gui.add( params, 'roughness', 0, 1, 0.01 );
gui.add( params, 'metalness', 0, 1, 0.01 );
gui.add( params, 'exposure', 0, 2, 0.01 );
gui.add( params, 'debug' );
gui.open();

function displayStats( value ) {

lbl.innerHTML = value + ' size : ' + fileSizes[ value ] + ', Resolution: ' + resolutions[ value ];

}

}


function humanFileSize( bytes, si = true, dp = 1 ) {

const thresh = si ? 1000 : 1024;

if ( Math.abs( bytes ) < thresh ) {

return bytes + ' B';

}

const units = si
? [ 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB' ]
: [ 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB' ];
let u = - 1;
const r = 10 ** dp;

do {

bytes /= thresh;
++ u;

} while ( Math.round( Math.abs( bytes ) * r ) / r >= thresh && u < units.length - 1 );

return bytes.toFixed( dp ) + ' ' + units[ u ];

}


function onWindowResize() {

const width = window.innerWidth;
const height = window.innerHeight;

camera.aspect = width / height;
camera.updateProjectionMatrix();

renderer.setSize( width, height );

}

function animate() {

requestAnimationFrame( animate );

stats.begin();
render();
stats.end();

}

function render() {

torusMesh.material.roughness = params.roughness;
torusMesh.material.metalness = params.metalness;

let pmremRenderTarget, equirectangularMap;

switch ( params.envMap ) {

case 'HDR JPG':
pmremRenderTarget = hdrJpgPMREMRenderTarget;
equirectangularMap = hdrJpgEquirectangularMap || hdrJpg.renderTarget.texture;
break;
case 'Webp Gain map (separate)':
pmremRenderTarget = gainMapPMREMRenderTarget;
equirectangularMap = gainMapBackground || gainMap.renderTarget.texture;
break;
case 'HDR':
pmremRenderTarget = hdrPMREMRenderTarget;
equirectangularMap = hdrEquirectangularMap;
break;

}

const newEnvMap = pmremRenderTarget ? pmremRenderTarget.texture : null;

if ( newEnvMap && newEnvMap !== torusMesh.material.envMap ) {

torusMesh.material.envMap = newEnvMap;
torusMesh.material.needsUpdate = true;

planeMesh.material.map = newEnvMap;
planeMesh.material.needsUpdate = true;

}

torusMesh.rotation.y += 0.005;
planeMesh.visible = params.debug;

scene.background = equirectangularMap;
renderer.toneMappingExposure = params.exposure;

renderer.render( scene, camera );

}

</script>

</body>
</html>

0 comments on commit 0582b00

Please sign in to comment.