<!DOCTYPE html> <html lang="en"> <head> <title>three.js webgl - materials - HDR texture loader</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> <style> body { color: #fff; font-family:Monospace; font-size:13px; text-align:center; font-weight: bold; background-color: #000; margin: 0px; overflow: hidden; } #info { color:#fff; position: absolute; top: 0px; width: 100%; padding: 5px; } a { color: red; } </style> </head> <body> <div id="container"></div> <div id="info"> <a href="http://threejs.org" target="_blank">three.js</a> - webgl HDR texture loader example - based on <a href="http://spidergl.org/example.php?id=13" target="_blank">SpiderGL</a> </div> <script src="../build/three.min.js"></script> <script src="js/loaders/RGBELoader.js"></script> <script src="js/Detector.js"></script> <script src="js/libs/stats.min.js"></script> <!-- HDR fragment shader --> <script id="fs-hdr" type="x-shader/x-fragment"> uniform sampler2D tDiffuse; uniform float exposure; uniform float brightMax; varying vec2 vUv; vec3 decode_pnghdr( const in vec4 color ) { vec4 rgbcolor = vec4( 0.0, 0.0, 0.0, 0.0 ); if ( color.w > 0.0 ) { float f = pow(2.0, 127.0*(color.w-0.5)); rgbcolor.xyz = color.xyz * f; } return rgbcolor.xyz; /* // remove gamma correction vec4 res = color * color; // decoded RI float ri = pow( 2.0, res.w * 32.0 - 16.0 ); // decoded HDR pixel res.xyz = res.xyz * ri; return res.xyz; */ } void main() { vec4 color = texture2D( tDiffuse, vUv ); color.xyz = decode_pnghdr( color ); // apply gamma correction and exposure //gl_FragColor = vec4( pow( exposure * color.xyz, vec3( 0.474 ) ), 1.0 ); // Perform tone-mapping float Y = dot(vec4(0.30, 0.59, 0.11, 0.0), color); float YD = exposure * (exposure/brightMax + 1.0) / (exposure + 1.0); color *= YD; gl_FragColor = vec4( color.xyz, 1.0 ); } </script> <!-- HDR vertex shader --> <script id="vs-hdr" type="x-shader/x-vertex"> varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); } </script> <script> if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); var container, stats; var camera, scene, renderer; var materialHDR, quad, gamma, exposure; var sign = 1, rate = 1; var clock = new THREE.Clock(); init(); function init() { container = document.getElementById( 'container' ); camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 10000 ); camera.position.z = 900; scene = new THREE.Scene(); var loader = new THREE.RGBELoader(); var texture = loader.load( "textures/miranda_uncropped.hdr", function( texture, textureData ){ console.log( textureData.header ); // header string console.log( [textureData.width, textureData.height] ); // dimensions materialHDR = new THREE.ShaderMaterial( { uniforms: { tDiffuse: { type: "t", value: texture }, exposure: { type: "f", value: textureData.exposure }, brightMax: { type: "f", value: textureData.gamma } }, vertexShader: getText( 'vs-hdr' ), fragmentShader: getText( 'fs-hdr' ) } ); quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( textureData.width, textureData.height ), materialHDR ); quad.position.z = -100; scene.add( quad ); animate(); } ); texture.minFilter = THREE.LinearFilter; texture.magFilter = THREE.NearestFilter; renderer = new THREE.WebGLRenderer(); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); container.appendChild( renderer.domElement ); stats = new Stats(); stats.domElement.style.position = 'absolute'; stats.domElement.style.top = '0px'; container.appendChild( stats.domElement ); // window.addEventListener( 'resize', onWindowResize, false ); } function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize( window.innerWidth, window.innerHeight ); } function getText( id ) { return document.getElementById( id ).textContent; } // function animate() { requestAnimationFrame( animate ); render(); stats.update(); } function render() { delta = clock.getDelta() * 5; if ( materialHDR.uniforms.exposure.value > 0 || materialHDR.uniforms.exposure.value < 1 ) { rate = 0.25; } else { rate = 1; } if ( materialHDR.uniforms.exposure.value > 5 || materialHDR.uniforms.exposure.value <= 0 ) { sign *= -1; } materialHDR.uniforms.exposure.value += sign * rate * delta; renderer.render( scene, camera ); } </script> </body> </html>