├── .gitignore ├── 100-intro.md ├── 200-setup-and-gamma-notes.md ├── 200-setup-and-gamma.md ├── 201-init └── main.js ├── 202-lambert-diffuse ├── Material.frag ├── Material.vert └── main.js ├── 203-gamma ├── Material.frag ├── Material.vert └── main.js ├── 204-gamma-color ├── Material.frag ├── Material.vert └── main.js ├── 205-gamma-texture ├── Material.frag ├── Material.vert └── main.js ├── 206-gamma-ext-srgb ├── Material.frag ├── Material.vert └── main.js ├── 300-cubemap-anim └── main.js ├── 300-hdr-histogram └── main.js ├── 300-hdr.md ├── 301-load-cubemap ├── Reflection.frag ├── Reflection.vert ├── Skybox.frag ├── Skybox.vert ├── main.js └── mainNoDebug.js ├── 301-reflections └── main.js ├── 302-load-equirect ├── Reflection.frag ├── Reflection.vert ├── Skybox.frag ├── Skybox.vert └── main.js ├── 303-fullscreenquad-skybox ├── Reflection.frag ├── Reflection.vert ├── SkyboxQuad.frag ├── SkyboxQuad.vert ├── SkyboxQuadDebug.vert └── main.js ├── 304-load-hdr ├── Reflection.frag ├── Reflection.vert ├── SkyboxQuad.frag ├── SkyboxQuad.vert └── main.js ├── 305-exposure-basic ├── Reflection.frag ├── Reflection.vert ├── SkyboxQuad.frag ├── SkyboxQuad.vert └── main.js ├── 306-tonemap-reinhard ├── Reflection.frag ├── Reflection.vert ├── SkyboxQuad.frag ├── SkyboxQuad.vert └── main.js ├── 307-tonemap-compare ├── Reflection.frag ├── Reflection.vert ├── SkyboxQuad.frag ├── SkyboxQuad.vert ├── main.js └── mainObj.js ├── 308-exposure-camera ├── Reflection.frag ├── Reflection.vert ├── SkyboxQuad.frag ├── SkyboxQuad.vert └── main.js ├── 400-hammersley-point-set └── main.js ├── 400-realtime-filtering ├── README.md ├── Reflection.frag ├── Reflection.vert ├── SkyboxQuad.frag ├── SkyboxQuad.vert ├── hammersley.js ├── hammersleyTest.js ├── main.js └── rays.js ├── 500-pbr ├── PBRImportanceSampled.js ├── PBRMaterial.js ├── UberMaterial.js ├── glsl │ ├── PBR.frag │ ├── PBR.vert │ ├── PBRImportanceSampled.frag │ ├── PBRImportanceSampled.vert │ ├── ShowColors.frag │ ├── ShowColors.vert │ ├── ShowNormals.frag │ ├── ShowNormals.vert │ ├── SkyboxQuad.frag │ ├── SkyboxQuad.vert │ ├── SolidColor.frag │ ├── SolidColor.vert │ ├── SpecularCookTorrance.frag │ ├── SpecularCookTorrance.vert │ ├── SpecularGGX.frag │ ├── SpecularGGX.vert │ ├── SpecularPhong.frag │ ├── SpecularPhong.vert │ ├── UberShader.frag │ └── UberShader.vert └── main.js ├── 501-pbr-textured ├── PBR.frag ├── PBR.vert ├── PBRMaterial.js ├── ShowColors.frag ├── ShowColors.vert ├── SkyboxQuad.frag ├── SkyboxQuad.vert └── main.js ├── README.md ├── assets ├── brdf │ └── lut.png ├── envmaps │ ├── pisa.txt │ ├── pisa_latlong_256.hdr │ ├── pisa_negx.jpg │ ├── pisa_negy.jpg │ ├── pisa_negz.jpg │ ├── pisa_posx.jpg │ ├── pisa_posy.jpg │ ├── pisa_posz.jpg │ ├── pisa_preview.jpg │ ├── test.jpg │ ├── test.txt │ ├── test_nx.png │ ├── test_ny.png │ ├── test_nz.png │ ├── test_px.png │ ├── test_py.png │ └── test_pz.png ├── glsl │ ├── Basic.frag │ ├── Basic.vert │ ├── ShowColors.frag │ ├── ShowColors.vert │ ├── ShowNormals.frag │ └── ShowNormals.vert ├── html │ └── index.template.html ├── models │ ├── blob.obj │ ├── dragon.obj │ └── dragon.txt └── textures │ ├── Pink_tile_pxr128.jpg │ └── Pink_tile_pxr128.txt ├── build_all.sh ├── img ├── 100_bunny_env3.jpg ├── 100_demo_exposure.jpg ├── 100_demo_materials.jpg ├── 100_demo_mixing.jpg ├── 100_dielectric_roughness_sml.jpg ├── 100_exploded_cube.jpg ├── 100_exploded_cube_thumb.jpg ├── 100_frame_stages.jpg ├── 100_materials3x2.jpg ├── 100_metal_roughness_sml.jpg ├── 200.jpg ├── 201.jpg ├── 202.jpg ├── 202_angles.jpg ├── 202_lambert_diffuse.jpg ├── 202_transformation_spaces.jpg ├── 203.jpg ├── 203_gamma_graph.png ├── 203_gamma_graph.txt ├── 203_gamma_moon.png ├── 203_gamma_moon.txt ├── 203_gamma_video.jpg ├── 204.jpg ├── 204_comparison.jpg ├── 205.jpg ├── 205_pixar_textures.jpg ├── 205_pixar_textures.txt ├── 206_incorrect.jpg ├── 300.jpg ├── 300_hdr.jpg ├── 301_cube_anim.gif ├── 301_cube_cross_and_debug.jpg ├── 301_cube_faces.jpg ├── 301_cube_faces_debug.png ├── 301_cube_orientation.png ├── 301_load_cubemap.jpg ├── 301_pisa_streetview.jpg ├── 301_reflection_angle.png ├── 301_reflections.png ├── 302_latlong_and_debug.jpg ├── 302_latlong_sampler.png ├── 303_fullscreen_quad.jpg ├── 304_banding.jpg ├── 304_load_hdr.jpg ├── 305_exposure_basic.jpg ├── 306_tonemap.jpg ├── 306_tonemap_func.png ├── 306_tonemap_reinhard.jpg ├── 307_tonemap_compare.jpg └── 308_exposure_camera.jpg ├── local_modules ├── convolve-cubemap │ ├── glsl │ │ ├── convolve.frag │ │ └── convolve.vert │ ├── index.js │ └── package.json ├── cubemap-to-octmap │ ├── glsl │ │ ├── CubemapToOctmap.frag │ │ └── CubemapToOctmap.vert │ ├── index.js │ └── test.js ├── downsample-cubemap │ ├── glsl │ │ ├── downsample.frag │ │ └── downsample.vert │ ├── index.js │ └── package.json ├── envmap-to-cubemap │ ├── glsl │ │ ├── SkyboxQuad.frag │ │ └── SkyboxQuad.vert │ ├── index.js │ └── package.json ├── geom-center-and-resize │ ├── .gitignore │ ├── .npmignore │ ├── LICENSE.md │ ├── README.md │ ├── index.js │ └── package.json ├── geom-compute-normals │ ├── index.js │ └── package.json ├── geom-parse-obj │ └── index.js ├── geom-subdivide-triangles │ └── index.js ├── geom-to-flat-geometry │ └── index.js ├── geom-triangulate │ ├── index.js │ └── package.json ├── glsl-envmap-cube │ └── index.glsl ├── glsl-envmap-equirect │ └── index.glsl ├── glsl-rgbe2rgb │ └── index.glsl ├── glsl-sky │ └── index.glsl ├── glsl-tonemap-filmic │ └── index.glsl ├── glsl-tonemap-reinhard │ └── index.glsl ├── glsl-tonemap-uncharted2 │ └── index.glsl ├── parse-hdr │ ├── package.json │ └── parse-hdr.js ├── prefilter-cubemap │ ├── glsl │ │ ├── prefilter.frag │ │ └── prefilter.vert │ ├── index.js │ └── package.json ├── prefilter-octmap │ ├── glsl │ │ ├── PrefilterOctmap.frag │ │ └── PrefilterOctmap.vert │ └── index.js ├── primitive-icosahedron │ └── index.js ├── primitive-octahedron │ └── index.js └── render-to-cubemap │ └── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | .atom-build.json 4 | index.html 5 | main.web.js 6 | *-orig 7 | *-old 8 | temp 9 | -------------------------------------------------------------------------------- /200-setup-and-gamma-notes.md: -------------------------------------------------------------------------------- 1 | # Gamma correction and linear space 2 | 3 | #### [The Importance of Being Linear](http://http.developer.nvidia.com/GPUGems3/gpugems3_ch24.html) from GPU Gems 3 4 | 5 | > The automatic sRGB corrections are free and are preferred to performing the corrections manually in a shader after each texture access, as shown in Listing 24-1, because each pow instruction is scalar and expanded to two instructions. Also, manual correction happens after filtering, which is incorrectly performed in a nonlinear space. 6 | 7 | #### [Linear-Space Lighting (i.e. Gamma)](http://filmicgames.com/archives/299) 2010 8 | 9 | #### [EXT_sRGB](https://www.khronos.org/registry/webgl/extensions/EXT_sRGB) 10 | 11 | > The sRGB color space is based on typical (non-linear) 12 | 13 | According to [WebGL Report](http://webglreport.com/?v=1) supported in: 14 | 15 | - [x] Chrome 43+ on OSX 16 | - [x] Firefox 39+ on OSX 17 | - [x] Webkit Nighly r186719 on OSX 18 | - [ ] Safari 8.0.7 on OSX 19 | 20 | EXT_sRGB will be in core WebGL 2.0 21 | 22 | #### [Udacity Interactive 3D Graphics: Gamma Correction ](https://www.udacity.com/course/viewer#!/c-cs291/l-124106597/m-176585829) 2013? 23 | 24 | ``` 25 | renderer.gammaInput = true 26 | renderer.gammaOutput = true 27 | ``` 28 | 29 | 30 | #### [ThreeJS: Improving correctness of gamma application](https://github.com/mrdoob/three.js/issues/5838) 2014 31 | #### [ThreeJS: Texture encoding example code, and thoughts on a correct implementation](https://github.com/mrdoob/three.js/issues/6593) 2015 32 | 33 | ``` 34 | THREE.Linear = 3000; 35 | THREE.sRGB = 3001; 36 | THREE.RGBE = 3002; 37 | THREE.LogLuv = 3003; 38 | ``` 39 | 40 | # sRGB 41 | 42 | SRGB in WebGL (core in WebGL 2.0) is enabled through 43 | [EXT_sRGB](https://www.khronos.org/registry/gles/extensions/EXT/EXT_sRGB.txt) 44 | 45 | Which is based on 46 | [ARB_framebuffer_sRGB](https://www.opengl.org/registry/specs/ARB/framebuffer_sRGB.txt) 47 | [EXT_texture_sRGB](https://www.opengl.org/registry/specs/EXT/texture_sRGB.txt) 48 | 49 | 50 | # Other 51 | 52 | http://www.pauldebevec.com/Probes/ 53 | http://gl.ict.usc.edu/Data/HighResProbes/ 54 | 55 | [Gamma correct and HDR rendering in a 32 bits buffer](http://lousodrome.net/blog/light/tag/rgbm/) 56 | 57 | 58 | http://renderwonk.com/blog/index.php/archive/adventures-with-gamma-correct-rendering/ ?? 59 | http://d.hatena.ne.jp/hanecci/20120108 ?? 60 | -------------------------------------------------------------------------------- /201-init/main.js: -------------------------------------------------------------------------------- 1 | var Window = require('pex-sys/Window'); 2 | 3 | var frame = 0; 4 | 5 | Window.create({ 6 | settings: { 7 | width: 1024, 8 | height: 576 9 | }, 10 | draw: function() { 11 | var ctx = this.getContext(); 12 | frame++; 13 | var r = 0.5 + 0.5 * Math.sin(frame/10); 14 | var g = 0.5 + 0.5 * Math.cos(frame/10 + Math.PI/2); 15 | var b = 0.5 + 0.5 * Math.sin(frame/10 + Math.PI/4); 16 | ctx.setClearColor(r, g, b, 1.0); 17 | ctx.clear(ctx.COLOR_BIT); 18 | } 19 | }) 20 | -------------------------------------------------------------------------------- /202-lambert-diffuse/Material.frag: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | //require the lambert diffuse formula from a module via glslify 6 | #pragma glslify: lambert = require(glsl-diffuse-lambert) 7 | 8 | //vertex position, normal and light position in the eye/view space 9 | varying vec3 ecPosition; 10 | varying vec3 ecNormal; 11 | varying vec3 ecLightPos; 12 | 13 | 14 | void main() { 15 | //normalize the normal, we do it here instead of vertex 16 | //shader for smoother gradients 17 | vec3 N = normalize(ecNormal); 18 | 19 | //calculate direction towards the light 20 | vec3 L = normalize(ecLightPos - ecPosition); 21 | 22 | //diffuse intensity 23 | float Id = lambert(L, N); 24 | 25 | //surface and light color, full white 26 | vec4 baseColor = vec4(1.0); 27 | vec4 lightColor = vec4(1.0); 28 | 29 | vec4 finalColor = vec4(baseColor.rgb * lightColor.rgb * Id, 1.0); 30 | gl_FragColor = finalColor; 31 | } 32 | -------------------------------------------------------------------------------- /202-lambert-diffuse/Material.vert: -------------------------------------------------------------------------------- 1 | //vertex position in the model space 2 | attribute vec4 aPosition; 3 | //vertex normal in the model space 4 | attribute vec3 aNormal; 5 | 6 | //current transformation matrices coming from the Context 7 | uniform mat4 uProjectionMatrix; 8 | uniform mat4 uViewMatrix; 9 | uniform mat4 uModelMatrix; 10 | uniform mat3 uNormalMatrix; 11 | 12 | //user supplied light position 13 | uniform vec3 uLightPos; 14 | 15 | //vertex position in the eye coordinates (view space) 16 | varying vec3 ecPosition; 17 | //normal in the eye coordinates (view space) 18 | varying vec3 ecNormal; 19 | //light position in the eye coordinates (view space) 20 | varying vec3 ecLightPos; 21 | 22 | void main() { 23 | //transform vertex into the eye space 24 | vec4 pos = uViewMatrix * uModelMatrix * aPosition; 25 | ecPosition = pos.xyz; 26 | ecNormal = uNormalMatrix * aNormal; 27 | 28 | ecLightPos = vec3(uViewMatrix * uModelMatrix * vec4(uLightPos, 1.0)); 29 | 30 | //project the vertex, the rest is handled by WebGL 31 | gl_Position = uProjectionMatrix * pos; 32 | } 33 | -------------------------------------------------------------------------------- /202-lambert-diffuse/main.js: -------------------------------------------------------------------------------- 1 | //Import all the dependencies 2 | var Window = require('pex-sys/Window'); 3 | var Mat4 = require('pex-math/Mat4'); 4 | var Vec3 = require('pex-math/Vec3'); 5 | var glslify = require('glslify-promise'); 6 | var createSphere = require('primitive-sphere'); 7 | 8 | //Create window - in the borwser this will: 9 | //- create new Canvas element with width/height specified in the `settings` 10 | //- append it to
11 | //- get WebGL context 12 | //- add event listeners for mouse and keyboard events 13 | //- load all requested resources 14 | //- call init() 15 | //- keep calling draw() using Window.requestAnimationFrame() 16 | Window.create({ 17 | //Window / canvas properties 18 | settings: { 19 | width: 1024, 20 | height: 576 21 | }, 22 | //Files (text, json, glsl vis glslify, images) to load before init 23 | resources: { 24 | vert: { glsl: glslify(__dirname + '/Material.vert') }, 25 | frag: { glsl: glslify(__dirname + '/Material.frag') } 26 | }, 27 | //Init is called after creating WebGL context and successfuly loading all the resources 28 | init: function() { 29 | //pex-context/Context object - the pex's WebGL context wrapper 30 | var ctx = this.getContext(); 31 | 32 | //Model transformation matrix 33 | //An Array with 16 numbers initialized to an identity matrix 34 | this.model = Mat4.create(); 35 | 36 | //Camera projection matrix 37 | this.projection = Mat4.perspective( 38 | Mat4.create(), //new matrix 39 | 45, //45' deg fov 40 | this.getAspectRatio(), //window aspect ratio width/height 41 | 0.001, //near clipping plane 42 | 10.0 //far clipping plane 43 | ); 44 | 45 | //Camera view matrix 46 | this.view = Mat4.create(); 47 | //[0,1,5] - eye position 48 | //[0,0,0] - target position 49 | //[0,1,0] - camera up vector 50 | Mat4.lookAt(this.view, [0, 1, 5], [0, 0, 0], [0, 1, 0]); 51 | 52 | //The Context keeps a separate matrix stack for the projection, 53 | //view and model matrix. Additionaly it will compute normal matrix 54 | //and inverse view matrix whenever view matrix changes 55 | ctx.setProjectionMatrix(this.projection); 56 | ctx.setViewMatrix(this.view); 57 | ctx.setModelMatrix(this.model); 58 | 59 | //Get reference to all loaded resources 60 | var res = this.getResources(); 61 | 62 | //Each resource of type `glsl` will be replace by string with the loaded GLSL code 63 | //We can use that code to create a WebGL Program object 64 | this.program = ctx.createProgram(res.vert, res.frag); 65 | 66 | //Create sphere geometry - an object with positions, normals and cells/faces 67 | var g = createSphere(); 68 | 69 | //Define mesh attribute layout 70 | //ATTRIB_POSITION and ATTRIB_NORMAL are slot numbers 71 | //matching attributes in the shader aPosition and aNormal 72 | var attributes = [ 73 | { data: g.positions, location: ctx.ATTRIB_POSITION }, 74 | { data: g.normals, location: ctx.ATTRIB_NORMAL } 75 | ]; 76 | 77 | //Define vertices data 78 | var indices = { data: g.cells }; 79 | 80 | //Create mesh to be rendered as a list of TRIANGLEs 81 | this.mesh = ctx.createMesh(attributes, indices, ctx.TRIANGLES); 82 | }, 83 | //This function is called as close as possible to 60fps via requestAnimationFrame 84 | draw: function() { 85 | var ctx = this.getContext(); 86 | 87 | //Set gl clear color to dark grey 88 | ctx.setClearColor(0.2, 0.2, 0.2, 1); 89 | 90 | //Clear the color and depth buffers 91 | ctx.clear(ctx.COLOR_BIT | ctx.DEPTH_BIT); 92 | 93 | //Enable depth testing 94 | ctx.setDepthTest(true); 95 | 96 | //Activate our GLSL program 97 | ctx.bindProgram(this.program); 98 | 99 | //Set the light's position uniform 100 | //There is no need to set matrix uniforms like uProjectionMatrix as 101 | //these are handled by the context. List of all handled uniforms is 102 | //in pex-context/ProgramUniform.js 103 | this.program.setUniform('uLightPos', [10, 10, 10]) 104 | 105 | //Activate the sphere mesh 106 | ctx.bindMesh(this.mesh); 107 | 108 | //Draw the currently active mesh (sphere in this example) 109 | ctx.drawMesh(); 110 | } 111 | }) 112 | -------------------------------------------------------------------------------- /203-gamma/Material.frag: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | //require the lambert diffuse formula from a module via glslify 6 | #pragma glslify: lambert = require(glsl-diffuse-lambert) 7 | 8 | //glsl-gamma module exports two functions that we can import separately 9 | #pragma glslify: toLinear = require(glsl-gamma/in) 10 | #pragma glslify: toGamma = require(glsl-gamma/out) 11 | 12 | //vertex position, normal and light position in the eye/view space 13 | varying vec3 ecPosition; 14 | varying vec3 ecNormal; 15 | varying vec3 ecLightPos; 16 | 17 | float PI = 3.14159265; 18 | 19 | void main() { 20 | vec3 N = normalize(ecNormal); 21 | vec3 L = normalize(ecLightPos - ecPosition); 22 | 23 | //diffuse intensity 24 | float Id = lambert(L, N); 25 | 26 | //surface and light color, full white 27 | vec4 baseColor = toLinear(vec4(1.0)); 28 | vec4 lightColor = toLinear(vec4(1.0)); 29 | 30 | vec4 finalColor = vec4(baseColor.rgb * lightColor.rgb * Id, 1.0); 31 | gl_FragColor = toGamma(finalColor); 32 | } 33 | -------------------------------------------------------------------------------- /203-gamma/Material.vert: -------------------------------------------------------------------------------- 1 | attribute vec4 aPosition; 2 | attribute vec3 aNormal; 3 | 4 | uniform mat4 uProjectionMatrix; 5 | uniform mat4 uViewMatrix; 6 | uniform mat4 uModelMatrix; 7 | uniform mat3 uNormalMatrix; 8 | 9 | uniform vec3 uLightPos; 10 | 11 | //vertex position, normal and light position in the eye/view space 12 | varying vec3 ecPosition; 13 | varying vec3 ecNormal; 14 | varying vec3 ecLightPos; 15 | 16 | void main() { 17 | vec4 pos = uViewMatrix * uModelMatrix * aPosition; 18 | ecPosition = pos.xyz; 19 | ecNormal = uNormalMatrix * aNormal; 20 | 21 | ecLightPos = vec3(uViewMatrix * uModelMatrix * vec4(uLightPos, 1.0)); 22 | 23 | gl_Position = uProjectionMatrix * pos; 24 | } 25 | -------------------------------------------------------------------------------- /203-gamma/main.js: -------------------------------------------------------------------------------- 1 | var Window = require('pex-sys/Window'); 2 | var Mat4 = require('pex-math/Mat4'); 3 | var Vec3 = require('pex-math/Vec3'); 4 | var glslify = require('glslify-promise'); 5 | var createSphere = require('primitive-sphere'); 6 | 7 | Window.create({ 8 | settings: { 9 | width: 1024, 10 | height: 576 11 | }, 12 | resources: { 13 | vert: { glsl: glslify(__dirname + '/Material.vert') }, 14 | frag: { glsl: glslify(__dirname + '/Material.frag') } 15 | }, 16 | init: function() { 17 | var ctx = this.getContext(); 18 | 19 | this.model = Mat4.create(); 20 | this.projection = Mat4.perspective(Mat4.create(), 45, this.getAspectRatio(), 0.001, 10.0); 21 | this.view = Mat4.lookAt([], [0, 1, 5], [0, 0, 0], [0, 1, 0]); 22 | 23 | ctx.setProjectionMatrix(this.projection); 24 | ctx.setViewMatrix(this.view); 25 | ctx.setModelMatrix(this.model); 26 | 27 | var res = this.getResources(); 28 | 29 | this.program = ctx.createProgram(res.vert, res.frag); 30 | 31 | var g = createSphere(); 32 | 33 | var attributes = [ 34 | { data: g.positions, location: ctx.ATTRIB_POSITION }, 35 | { data: g.normals, location: ctx.ATTRIB_NORMAL } 36 | ]; 37 | var indices = { data: g.cells, usage: ctx.STATIC_DRAW }; 38 | this.mesh = ctx.createMesh(attributes, indices, ctx.TRIANGLES); 39 | }, 40 | draw: function() { 41 | var ctx = this.getContext(); 42 | ctx.setClearColor(0.2, 0.2, 0.2, 1); 43 | ctx.clear(ctx.COLOR_BIT | ctx.DEPTH_BIT); 44 | ctx.setDepthTest(true); 45 | 46 | ctx.bindProgram(this.program); 47 | this.program.setUniform('uLightPos', [10, 10, 10]) 48 | 49 | ctx.bindMesh(this.mesh); 50 | ctx.drawMesh(); 51 | } 52 | }) 53 | -------------------------------------------------------------------------------- /204-gamma-color/Material.frag: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | #pragma glslify: lambert = require(glsl-diffuse-lambert) 6 | #pragma glslify: toLinear = require(glsl-gamma/in) 7 | #pragma glslify: toGamma = require(glsl-gamma/out) 8 | 9 | //vec3 toLinear(vec3 v) { return v; } 10 | //vec4 toLinear(vec4 v) { return v; } 11 | //vec4 toGamma(vec4 v) { return v; } 12 | 13 | varying vec3 ecPosition; 14 | varying vec3 ecNormal; 15 | varying vec3 ecLightPos1; 16 | varying vec3 ecLightPos2; 17 | 18 | uniform vec4 uLightColor1; 19 | uniform vec4 uLightColor2; 20 | 21 | uniform bool uLinearSpace; 22 | uniform bool uCorrectGamma; 23 | 24 | float PI = 3.14159265; 25 | 26 | void main() { 27 | vec3 N = normalize(ecNormal); 28 | vec3 L1 = normalize(ecLightPos1 - ecPosition); 29 | vec3 L2 = normalize(ecLightPos2 - ecPosition); 30 | 31 | float diffuse1 = lambert(L1, N); 32 | float diffuse2 = lambert(L2, N); 33 | 34 | vec3 lightColor1 = uLinearSpace ? toLinear(uLightColor1.rgb) : uLightColor1.rgb; 35 | vec3 lightColor2 = uLinearSpace ? toLinear(uLightColor2.rgb) : uLightColor2.rgb; 36 | 37 | //albedo 38 | vec4 baseColor = uLinearSpace ? toLinear(vec4(1.0)) : vec4(1.0); 39 | 40 | vec4 finalColor = vec4(0.0, 0.0, 0.0, 1.0); 41 | finalColor.rgb = baseColor.rgb * diffuse1 * lightColor1 + baseColor.rgb * diffuse2 * lightColor2; 42 | gl_FragColor = uCorrectGamma ? toGamma(finalColor) : finalColor; 43 | } 44 | -------------------------------------------------------------------------------- /204-gamma-color/Material.vert: -------------------------------------------------------------------------------- 1 | attribute vec4 aPosition; 2 | attribute vec3 aNormal; 3 | 4 | uniform mat4 uProjectionMatrix; 5 | uniform mat4 uViewMatrix; 6 | uniform mat4 uModelMatrix; 7 | uniform mat3 uNormalMatrix; 8 | 9 | uniform vec3 uLightPos1; 10 | uniform vec3 uLightPos2; 11 | 12 | varying vec3 ecPosition; 13 | varying vec3 ecNormal; 14 | varying vec3 ecLightPos1; 15 | varying vec3 ecLightPos2; 16 | 17 | void main() { 18 | vec4 pos = uViewMatrix * uModelMatrix * aPosition; 19 | ecPosition = pos.xyz; 20 | ecNormal = uNormalMatrix * aNormal; 21 | 22 | ecLightPos1 = vec3(uViewMatrix * uModelMatrix * vec4(uLightPos1, 1.0)); 23 | ecLightPos2 = vec3(uViewMatrix * uModelMatrix * vec4(uLightPos2, 1.0)); 24 | 25 | gl_Position = uProjectionMatrix * pos; 26 | } 27 | -------------------------------------------------------------------------------- /204-gamma-color/main.js: -------------------------------------------------------------------------------- 1 | var Window = require('pex-sys/Window'); 2 | var Mat4 = require('pex-math/Mat4'); 3 | var Vec3 = require('pex-math/Vec3'); 4 | var glslify = require('glslify-promise'); 5 | var createSphere = require('primitive-sphere'); 6 | var GUI = require('pex-gui'); 7 | 8 | Window.create({ 9 | settings: { 10 | width: 1024, 11 | height: 576 12 | }, 13 | resources: { 14 | vert: { glsl: glslify(__dirname + '/Material.vert') }, 15 | frag: { glsl: glslify(__dirname + '/Material.frag') } 16 | }, 17 | init: function() { 18 | var ctx = this.getContext(); 19 | 20 | this.lightColor1 = [0.0, 0.9, 0.0, 1.0]; 21 | this.lightColor2 = [0.9, 0.0, 0.0, 1.0]; 22 | this.correctGamma = true; 23 | this.linearSpace = true; 24 | 25 | this.gui = new GUI(ctx, this.getWidth(), this.getHeight()); 26 | this.addEventListener(this.gui); 27 | this.gui.addHeader('Settings'); 28 | this.gui.addParam('Linear space', this, 'linearSpace'); 29 | this.gui.addParam('Correct gamma', this, 'correctGamma'); 30 | this.gui.addParam('Light 1', this, 'lightColor1', { type: 'color'}); 31 | this.gui.addParam('Light 2', this, 'lightColor2', { type: 'color'}); 32 | 33 | this.model = Mat4.create(); 34 | this.projection = Mat4.perspective(Mat4.create(), 45, this.getAspectRatio(), 0.001, 10.0); 35 | this.view = Mat4.lookAt([], [0, 1, 5], [0, 0, 0], [0, 1, 0]); 36 | 37 | ctx.setProjectionMatrix(this.projection); 38 | ctx.setViewMatrix(this.view); 39 | ctx.setModelMatrix(this.model); 40 | 41 | var res = this.getResources(); 42 | 43 | this.program = ctx.createProgram(res.vert, res.frag); 44 | 45 | var g = createSphere(1); 46 | 47 | var attributes = [ 48 | { data: g.positions, location: ctx.ATTRIB_POSITION }, 49 | { data: g.normals, location: ctx.ATTRIB_NORMAL } 50 | ]; 51 | var indices = { data: g.cells, usage: ctx.STATIC_DRAW }; 52 | this.mesh = ctx.createMesh(attributes, indices, ctx.TRIANGLES); 53 | }, 54 | draw: function() { 55 | var ctx = this.getContext(); 56 | ctx.setClearColor(0.2, 0.2, 0.2, 1); 57 | ctx.clear(ctx.COLOR_BIT | ctx.DEPTH_BIT); 58 | ctx.setDepthTest(true); 59 | 60 | ctx.bindProgram(this.program); 61 | this.program.setUniform('uLightPos1', [-10, 10, 5]); 62 | this.program.setUniform('uLightPos2', [10, 10, 5]); 63 | this.program.setUniform('uLightColor1', this.lightColor1); 64 | this.program.setUniform('uLightColor2', this.lightColor2); 65 | this.program.setUniform('uLinearSpace', this.linearSpace); 66 | this.program.setUniform('uCorrectGamma', this.correctGamma); 67 | 68 | ctx.bindMesh(this.mesh); 69 | ctx.drawMesh(); 70 | 71 | this.gui.draw(); 72 | } 73 | }) 74 | -------------------------------------------------------------------------------- /205-gamma-texture/Material.frag: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | #pragma glslify: lambert = require(glsl-diffuse-lambert) 6 | #pragma glslify: toLinear = require(glsl-gamma/in) 7 | #pragma glslify: toGamma = require(glsl-gamma/out) 8 | 9 | varying vec3 ecPosition; 10 | varying vec3 ecNormal; 11 | varying vec3 ecLightPos; 12 | varying vec2 vTexCoord0; 13 | 14 | uniform sampler2D uAlbedoTex; 15 | 16 | uniform bool uLinearSpace; 17 | uniform bool uCorrectGamma; 18 | 19 | float PI = 3.14159265; 20 | 21 | void main() { 22 | vec3 N = normalize(ecNormal); 23 | vec3 L = normalize(ecLightPos - ecPosition); 24 | 25 | float diffuse = lambert(L, N); 26 | 27 | vec4 baseColor = texture2D(uAlbedoTex, vTexCoord0 * vec2(3.0, 2.0)); 28 | baseColor.rgb = uLinearSpace ? toLinear(baseColor.rgb) : baseColor.rgb; 29 | 30 | //linear space lighting 31 | vec4 finalColor = vec4(baseColor.rgb * diffuse, 1.0); 32 | gl_FragColor = uCorrectGamma ? toGamma(finalColor) : finalColor; 33 | } 34 | -------------------------------------------------------------------------------- /205-gamma-texture/Material.vert: -------------------------------------------------------------------------------- 1 | attribute vec4 aPosition; 2 | attribute vec3 aNormal; 3 | attribute vec2 aTexCoord0; 4 | 5 | uniform mat4 uProjectionMatrix; 6 | uniform mat4 uViewMatrix; 7 | uniform mat4 uModelMatrix; 8 | uniform mat3 uNormalMatrix; 9 | 10 | uniform vec3 uLightPos; 11 | 12 | varying vec3 ecPosition; 13 | varying vec3 ecNormal; 14 | varying vec3 ecLightPos; 15 | varying vec2 vTexCoord0; 16 | 17 | void main() { 18 | vec4 pos = uViewMatrix * uModelMatrix * aPosition; 19 | ecPosition = pos.xyz; 20 | gl_Position = uProjectionMatrix * pos; 21 | ecLightPos = vec3(uViewMatrix * uModelMatrix * vec4(uLightPos, 1.0)); 22 | ecNormal = uNormalMatrix * aNormal; 23 | vTexCoord0 = aTexCoord0; 24 | } 25 | -------------------------------------------------------------------------------- /205-gamma-texture/main.js: -------------------------------------------------------------------------------- 1 | var Window = require('pex-sys/Window'); 2 | var Mat4 = require('pex-math/Mat4'); 3 | var Vec3 = require('pex-math/Vec3'); 4 | var glslify = require('glslify-promise'); 5 | var createTorus = require('primitive-torus'); 6 | var createSphere = require('primitive-sphere'); 7 | var isBrowser = require('is-browser'); 8 | var GUI = require('pex-gui'); 9 | 10 | //define path to the assets directory, here it's above (..) the example 11 | //folder so all examples can share the assets. `__dirname` is a nodejs 12 | //built-in variable pointing to the folder where the js script lives, 13 | //We need that to make it work in Plask. 14 | var ASSETS_DIR = isBrowser ? '../assets' : __dirname + '/../assets'; 15 | 16 | Window.create({ 17 | settings: { 18 | width: 1024, 19 | height: 576 20 | }, 21 | resources: { 22 | vert: { glsl: glslify(__dirname + '/Material.vert') }, 23 | frag: { glsl: glslify(__dirname + '/Material.frag') }, 24 | texture: { image: ASSETS_DIR + '/textures/Pink_tile_pxr128.jpg'} 25 | }, 26 | init: function() { 27 | var ctx = this.getContext(); 28 | 29 | this.model = Mat4.create(); 30 | this.projection = Mat4.perspective(Mat4.create(), 45, this.getAspectRatio(), 0.001, 10.0); 31 | this.view = Mat4.lookAt([], [0, 1, 5], [0, 0, 0], [0, 1, 0]); 32 | 33 | this.correctGamma = true; 34 | this.linearSpace = true; 35 | 36 | this.gui = new GUI(ctx, this.getWidth(), this.getHeight()); 37 | this.addEventListener(this.gui); 38 | this.gui.addHeader('Settings'); 39 | this.gui.addParam('Linear space', this, 'linearSpace'); 40 | this.gui.addParam('Correct gamma', this, 'correctGamma'); 41 | 42 | ctx.setProjectionMatrix(this.projection); 43 | ctx.setViewMatrix(this.view); 44 | ctx.setModelMatrix(this.model); 45 | 46 | var res = this.getResources(); 47 | 48 | this.program = ctx.createProgram(res.vert, res.frag); 49 | 50 | this.texture = ctx.createTexture2D(res.texture, res.texture.width, res.texture.height, { repeat: true }); 51 | 52 | var g = createSphere(); 53 | 54 | var attributes = [ 55 | { data: g.positions, location: ctx.ATTRIB_POSITION }, 56 | { data: g.normals, location: ctx.ATTRIB_NORMAL }, 57 | { data: g.uvs, location: ctx.ATTRIB_TEX_COORD_0 }, 58 | ]; 59 | var indices = { data: g.cells, usage: ctx.STATIC_DRAW }; 60 | this.mesh = ctx.createMesh(attributes, indices, ctx.TRIANGLES); 61 | }, 62 | draw: function() { 63 | var ctx = this.getContext(); 64 | ctx.setClearColor(0.2, 0.2, 0.2, 1); 65 | ctx.clear(ctx.COLOR_BIT | ctx.DEPTH_BIT); 66 | ctx.setDepthTest(true); 67 | 68 | ctx.bindProgram(this.program); 69 | this.program.setUniform('uLightPos', [10, 10, 10]); 70 | this.program.setUniform('uAlbedoTex', 0); 71 | this.program.setUniform('uLinearSpace', this.linearSpace); 72 | this.program.setUniform('uCorrectGamma', this.correctGamma); 73 | 74 | ctx.bindTexture(this.texture, 0); 75 | this.program.setUniform('uAlbedoTex', 0); 76 | 77 | 78 | ctx.bindMesh(this.mesh); 79 | ctx.drawMesh(); 80 | 81 | this.gui.draw(); 82 | } 83 | }) 84 | -------------------------------------------------------------------------------- /206-gamma-ext-srgb/Material.frag: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | #pragma glslify: lambert = require(glsl-diffuse-lambert) 6 | #pragma glslify: toGamma = require(glsl-gamma/out) 7 | 8 | varying vec3 ecNormal; 9 | varying vec3 ecLight; 10 | varying vec3 ecPosition; 11 | varying vec2 vTexCoord0; 12 | 13 | uniform sampler2D uAlbedoTex; 14 | 15 | float PI = 3.14159265; 16 | 17 | void main() { 18 | vec3 N = normalize(ecNormal); 19 | vec3 L = normalize(ecLight - ecPosition); 20 | vec3 V = normalize(-ecPosition); 21 | float diffuse = lambert(L, N); 22 | 23 | //sample color as usual, the RGB values will be converted to linear space for you 24 | vec4 baseColor = texture2D(uAlbedoTex, vTexCoord0 * vec2(3.0, 2.0)); 25 | vec4 finalColor = vec4(baseColor.rgb * diffuse, 1.0); 26 | 27 | //we still need to bring it back to the gamma color space as we don't have sRGB aware render buffer here 28 | gl_FragColor = toGamma(finalColor); 29 | } 30 | -------------------------------------------------------------------------------- /206-gamma-ext-srgb/Material.vert: -------------------------------------------------------------------------------- 1 | attribute vec4 aPosition; 2 | attribute vec3 aNormal; 3 | attribute vec2 aTexCoord0; 4 | 5 | uniform mat4 uProjectionMatrix; 6 | uniform mat4 uViewMatrix; 7 | uniform mat4 uModelMatrix; 8 | uniform mat3 uNormalMatrix; 9 | 10 | uniform vec3 uLightPos; 11 | 12 | varying vec3 ecNormal; 13 | varying vec3 ecLight; 14 | varying vec3 ecPosition; 15 | varying vec2 vTexCoord0; 16 | 17 | void main() { 18 | vec4 pos = uViewMatrix * uModelMatrix * aPosition; 19 | ecPosition = pos.xyz; 20 | gl_Position = uProjectionMatrix * pos; 21 | ecLight = vec3(uViewMatrix * uModelMatrix * vec4(uLightPos, 1.0)); 22 | ecNormal = uNormalMatrix * aNormal; 23 | vTexCoord0 = aTexCoord0; 24 | } 25 | -------------------------------------------------------------------------------- /206-gamma-ext-srgb/main.js: -------------------------------------------------------------------------------- 1 | var Window = require('pex-sys/Window'); 2 | var Mat4 = require('pex-math/Mat4'); 3 | var Vec3 = require('pex-math/Vec3'); 4 | var glslify = require('glslify-promise'); 5 | var createTorus = require('primitive-torus'); 6 | var createSphere = require('primitive-sphere'); 7 | var isBrowser = require('is-browser'); 8 | 9 | var ASSETS_DIR = isBrowser ? '../assets' : __dirname + '/../assets'; 10 | 11 | Window.create({ 12 | settings: { 13 | width: 1024, 14 | height: 576 15 | }, 16 | resources: { 17 | vert: { glsl: glslify(__dirname + '/Material.vert') }, 18 | frag: { glsl: glslify(__dirname + '/Material.frag') }, 19 | texture: { image: ASSETS_DIR + '/textures/Pink_tile_pxr128.jpg'} 20 | }, 21 | init: function() { 22 | var ctx = this.getContext(); 23 | 24 | this.model = Mat4.create(); 25 | this.projection = Mat4.perspective(Mat4.create(), 45, this.getAspectRatio(), 0.001, 10.0); 26 | this.view = Mat4.lookAt([], [0, 1, 5], [0, 0, 0], [0, 1, 0]); 27 | 28 | ctx.setProjectionMatrix(this.projection); 29 | ctx.setViewMatrix(this.view); 30 | ctx.setModelMatrix(this.model); 31 | 32 | var res = this.getResources(); 33 | 34 | this.program = ctx.createProgram(res.vert, res.frag); 35 | 36 | this.texture = ctx.createTexture2D(res.texture, res.texture.width, res.texture.height, { repeat: true, format: ctx.SRGB }); 37 | 38 | var g = createSphere(); 39 | 40 | var attributes = [ 41 | { data: g.positions, location: ctx.ATTRIB_POSITION }, 42 | { data: g.normals, location: ctx.ATTRIB_NORMAL }, 43 | { data: g.uvs, location: ctx.ATTRIB_TEX_COORD_0 }, 44 | ]; 45 | var indices = { data: g.cells, usage: ctx.STATIC_DRAW }; 46 | this.mesh = ctx.createMesh(attributes, indices, ctx.TRIANGLES); 47 | }, 48 | draw: function() { 49 | var ctx = this.getContext(); 50 | ctx.setClearColor(0.2, 0.2, 0.2, 1); 51 | ctx.clear(ctx.COLOR_BIT | ctx.DEPTH_BIT); 52 | ctx.setDepthTest(true); 53 | 54 | ctx.bindProgram(this.program); 55 | this.program.setUniform('uLightPos', [10, 10, 10]); 56 | this.program.setUniform('uAlbedoTex', 0); 57 | ctx.bindTexture(this.texture, 0); 58 | 59 | ctx.bindMesh(this.mesh); 60 | ctx.drawMesh(); 61 | } 62 | }) 63 | -------------------------------------------------------------------------------- /301-load-cubemap/Reflection.frag: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | //envMapCube samples a cubemap envmap by mirroring the sampling ray along X axis 6 | #pragma glslify: envMapCube = require(../local_modules/glsl-envmap-cube) 7 | 8 | uniform mat4 uInverseViewMatrix; 9 | uniform samplerCube uEnvMap; 10 | 11 | varying vec3 ecPosition; 12 | varying vec3 ecNormal; 13 | 14 | void main() { 15 | //direction towards they eye (camera) in the view (eye) space 16 | vec3 ecEyeDir = normalize(-ecPosition); 17 | //direction towards the camera in the world space 18 | vec3 wcEyeDir = vec3(uInverseViewMatrix * vec4(ecEyeDir, 0.0)); 19 | //surface normal in the world space 20 | vec3 wcNormal = vec3(uInverseViewMatrix * vec4(ecNormal, 0.0)); 21 | 22 | //reflection vector in the world space. We negate wcEyeDir as the reflect function expect incident vector pointing towards the surface 23 | vec3 reflectionWorld = reflect(-wcEyeDir, normalize(wcNormal)); 24 | 25 | gl_FragColor = textureCube(uEnvMap, envMapCube(reflectionWorld)); 26 | } 27 | -------------------------------------------------------------------------------- /301-load-cubemap/Reflection.vert: -------------------------------------------------------------------------------- 1 | attribute vec4 aPosition; 2 | attribute vec3 aNormal; 3 | 4 | uniform mat4 uProjectionMatrix; 5 | uniform mat4 uViewMatrix; 6 | uniform mat4 uModelMatrix; 7 | uniform mat3 uNormalMatrix; 8 | 9 | varying vec3 ecPosition; 10 | varying vec3 ecNormal; 11 | 12 | void main() { 13 | gl_Position = uProjectionMatrix * uViewMatrix * uModelMatrix * aPosition; 14 | ecPosition = vec3(uViewMatrix * uModelMatrix * aPosition); 15 | ecNormal = uNormalMatrix * aNormal; 16 | } 17 | -------------------------------------------------------------------------------- /301-load-cubemap/Skybox.frag: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | #pragma glslify: envMapCube = require(../local_modules/glsl-envmap-cube) 6 | 7 | varying vec3 wcNormal; 8 | 9 | uniform samplerCube uEnvMap; 10 | 11 | void main() { 12 | gl_FragColor = textureCube(uEnvMap, envMapCube(normalize(wcNormal))); 13 | } 14 | -------------------------------------------------------------------------------- /301-load-cubemap/Skybox.vert: -------------------------------------------------------------------------------- 1 | attribute vec4 aPosition; 2 | attribute vec3 aNormal; 3 | 4 | uniform mat4 uProjectionMatrix; 5 | uniform mat4 uViewMatrix; 6 | uniform mat4 uModelMatrix; 7 | 8 | varying vec3 wcNormal; 9 | 10 | void main() { 11 | wcNormal = aPosition.xyz; 12 | gl_Position = uProjectionMatrix * uViewMatrix * uModelMatrix * aPosition; 13 | } 14 | -------------------------------------------------------------------------------- /301-load-cubemap/mainNoDebug.js: -------------------------------------------------------------------------------- 1 | var Window = require('pex-sys/Window'); 2 | var Mat4 = require('pex-math/Mat4'); 3 | var Vec3 = require('pex-math/Vec3'); 4 | var glslify = require('glslify-promise'); 5 | var createSphere = require('primitive-sphere'); 6 | var createCube = require('primitive-cube'); 7 | var PerspCamera = require('pex-cam/PerspCamera'); 8 | var Arcball = require('pex-cam/Arcball'); 9 | var isBrowser = require('is-browser'); 10 | 11 | Window.create({ 12 | settings: { 13 | width: 1024, 14 | height: 576, 15 | fullscreen: isBrowser 16 | }, 17 | resources: { 18 | reflectionVert: { glsl: glslify(__dirname + '/Reflection.vert') }, 19 | reflectionFrag: { glsl: glslify(__dirname + '/Reflection.frag') }, 20 | skyboxVert: { glsl: glslify(__dirname + '/Skybox.vert') }, 21 | skyboxFrag: { glsl: glslify(__dirname + '/Skybox.frag') }, 22 | showColorsVert: { glsl: glslify(__dirname + '/../assets/glsl/ShowColors.vert') }, 23 | showColorsFrag: { glsl: glslify(__dirname + '/../assets/glsl/ShowColors.frag') }, 24 | lake_px: { image: __dirname + '/../assets/envmaps/lake_right.jpg' }, 25 | lake_nx: { image: __dirname + '/../assets/envmaps/lake_left.jpg' }, 26 | lake_py: { image: __dirname + '/../assets/envmaps/lake_top.jpg' }, 27 | lake_ny: { image: __dirname + '/../assets/envmaps/lake_bottom.jpg' }, 28 | lake_pz: { image: __dirname + '/../assets/envmaps/lake_back.jpg' }, //+x is 'back'! 29 | lake_nz: { image: __dirname + '/../assets/envmaps/lake_front.jpg' }//-z is 'front'! 30 | }, 31 | init: function() { 32 | var ctx = this.getContext(); 33 | 34 | this.camera = new PerspCamera(45, this.getAspectRatio(), 0.1, 20); 35 | this.camera.lookAt([0, 1, 4], [0, 0, 0], [0, 1, 0]); 36 | this.arcball = new Arcball(this.camera, this.getWidth(), this.getHeight()); 37 | this.addEventListener(this.arcball); 38 | 39 | ctx.setProjectionMatrix(this.camera.getProjectionMatrix()); 40 | ctx.setViewMatrix(this.camera.getViewMatrix()); 41 | 42 | this.modelMatrix = Mat4.create(); 43 | ctx.setModelMatrix(this.modelMatrix); 44 | 45 | var res = this.getResources(); 46 | 47 | this.reflectionProgram = ctx.createProgram(res.reflectionVert, res.reflectionFrag); 48 | this.skyboxProgram = ctx.createProgram(res.skyboxVert, res.skyboxFrag); 49 | 50 | var g = createSphere(); 51 | var attributes = [ 52 | { data: g.positions, location: ctx.ATTRIB_POSITION }, 53 | { data: g.normals, location: ctx.ATTRIB_NORMAL } 54 | ]; 55 | var indices = { data: g.cells }; 56 | this.mesh = ctx.createMesh(attributes, indices, ctx.TRIANGLES); 57 | 58 | var cube = createCube(20); 59 | this.skyboxMesh = ctx.createMesh( 60 | [ { data: cube.positions, location: ctx.ATTRIB_POSITION }], 61 | { data: cube.cells }, 62 | ctx.TRIANGLES 63 | ); 64 | 65 | this.reflectionMap = ctx.createTextureCube([ 66 | { face: 0, data: res.lake_px }, 67 | { face: 1, data: res.lake_nx }, 68 | { face: 2, data: res.lake_py }, 69 | { face: 3, data: res.lake_ny }, 70 | { face: 4, data: res.lake_pz }, 71 | { face: 5, data: res.lake_nz } 72 | ]) 73 | }, 74 | draw: function() { 75 | var ctx = this.getContext(); 76 | 77 | this.arcball.apply(); 78 | ctx.setViewMatrix(this.camera.getViewMatrix()); 79 | 80 | ctx.setClearColor(0.2, 0.2, 0.2, 1); 81 | ctx.clear(ctx.COLOR_BIT | ctx.DEPTH_BIT); 82 | 83 | ctx.bindTexture(this.reflectionMap, 0); 84 | 85 | ctx.setDepthTest(false); 86 | ctx.bindProgram(this.skyboxProgram); 87 | this.skyboxProgram.setUniform('uReflectionMap', 0); 88 | ctx.setCullFace(true); 89 | ctx.setCullFaceMode(ctx.FRONT); 90 | ctx.pushModelMatrix(); 91 | ctx.translate(this.camera.getPosition()); 92 | ctx.bindMesh(this.skyboxMesh); 93 | ctx.drawMesh(); 94 | ctx.popModelMatrix(); 95 | ctx.setCullFaceMode(ctx.BACK); 96 | 97 | ctx.setDepthTest(true); 98 | ctx.bindProgram(this.reflectionProgram); 99 | this.reflectionProgram.setUniform('uReflectionMap', 0); 100 | ctx.bindMesh(this.mesh); 101 | ctx.drawMesh(); 102 | } 103 | }) 104 | -------------------------------------------------------------------------------- /302-load-equirect/Reflection.frag: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | #pragma glslify: envMapEquirect = require(../local_modules/glsl-envmap-equirect) 6 | 7 | uniform mat4 uInverseViewMatrix; 8 | uniform sampler2D uEnvMap; 9 | 10 | varying vec3 ecPosition; 11 | varying vec3 ecNormal; 12 | 13 | void main() { 14 | vec3 ecEyeDir = normalize(-ecPosition); 15 | vec3 wcEyeDir = vec3(uInverseViewMatrix * vec4(ecEyeDir, 0.0)); 16 | vec3 wcNormal = vec3(uInverseViewMatrix * vec4(ecNormal, 0.0)); 17 | 18 | vec3 reflectionWorld = reflect(-wcEyeDir, normalize(wcNormal)); 19 | gl_FragColor = texture2D(uEnvMap, envMapEquirect(reflectionWorld)); 20 | } 21 | -------------------------------------------------------------------------------- /302-load-equirect/Reflection.vert: -------------------------------------------------------------------------------- 1 | attribute vec4 aPosition; 2 | attribute vec3 aNormal; 3 | 4 | uniform mat4 uProjectionMatrix; 5 | uniform mat4 uViewMatrix; 6 | uniform mat4 uModelMatrix; 7 | uniform mat3 uNormalMatrix; 8 | 9 | varying vec3 ecPosition; 10 | varying vec3 ecNormal; 11 | 12 | void main() { 13 | gl_Position = uProjectionMatrix * uViewMatrix * uModelMatrix * aPosition; 14 | ecPosition = vec3(uViewMatrix * uModelMatrix * aPosition); 15 | ecNormal = uNormalMatrix * aNormal; 16 | } 17 | -------------------------------------------------------------------------------- /302-load-equirect/Skybox.frag: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | #pragma glslify: envMapEquirect = require(../local_modules/glsl-envmap-equirect) 6 | 7 | varying vec3 wcNormal; 8 | 9 | uniform sampler2D uEnvMap; 10 | 11 | void main() { 12 | gl_FragColor = texture2D(uEnvMap, envMapEquirect(normalize(wcNormal))); 13 | } 14 | -------------------------------------------------------------------------------- /302-load-equirect/Skybox.vert: -------------------------------------------------------------------------------- 1 | attribute vec4 aPosition; 2 | attribute vec3 aNormal; 3 | 4 | uniform mat4 uProjectionMatrix; 5 | uniform mat4 uViewMatrix; 6 | uniform mat4 uModelMatrix; 7 | 8 | varying vec3 wcNormal; 9 | 10 | void main() { 11 | wcNormal = aPosition.xyz; 12 | gl_Position = uProjectionMatrix * uViewMatrix * uModelMatrix * aPosition; 13 | } 14 | -------------------------------------------------------------------------------- /303-fullscreenquad-skybox/Reflection.frag: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | #pragma glslify: envMapEquirect = require(../local_modules/glsl-envmap-equirect) 6 | 7 | uniform mat4 uInverseViewMatrix; 8 | uniform sampler2D uEnvMap; 9 | 10 | varying vec3 ecPosition; 11 | varying vec3 ecNormal; 12 | 13 | void main() { 14 | vec3 ecEyeDir = normalize(-ecPosition); 15 | vec3 wcEyeDir = vec3(uInverseViewMatrix * vec4(ecEyeDir, 0.0)); 16 | vec3 wcNormal = vec3(uInverseViewMatrix * vec4(ecNormal, 0.0)); 17 | 18 | vec3 reflectionWorld = reflect(-wcEyeDir, normalize(wcNormal)); 19 | 20 | gl_FragColor = texture2D(uEnvMap, envMapEquirect(reflectionWorld)); 21 | } 22 | -------------------------------------------------------------------------------- /303-fullscreenquad-skybox/Reflection.vert: -------------------------------------------------------------------------------- 1 | attribute vec4 aPosition; 2 | attribute vec3 aNormal; 3 | 4 | uniform mat4 uProjectionMatrix; 5 | uniform mat4 uViewMatrix; 6 | uniform mat4 uModelMatrix; 7 | uniform mat3 uNormalMatrix; 8 | 9 | varying vec3 ecPosition; 10 | varying vec3 ecNormal; 11 | 12 | void main() { 13 | gl_Position = uProjectionMatrix * uViewMatrix * uModelMatrix * aPosition; 14 | ecPosition = vec3(uViewMatrix * uModelMatrix * aPosition); 15 | ecNormal = uNormalMatrix * aNormal; 16 | } 17 | -------------------------------------------------------------------------------- /303-fullscreenquad-skybox/SkyboxQuad.frag: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | #pragma glslify: envMapEquirect = require(../local_modules/glsl-envmap-equirect) 6 | 7 | varying vec3 wcNormal; 8 | 9 | uniform sampler2D uEnvMap; 10 | 11 | void main() { 12 | vec3 N = normalize(wcNormal); 13 | gl_FragColor = texture2D(uEnvMap, envMapEquirect(N)); 14 | } 15 | -------------------------------------------------------------------------------- /303-fullscreenquad-skybox/SkyboxQuad.vert: -------------------------------------------------------------------------------- 1 | //Based on http://gamedev.stackexchange.com/questions/60313/implementing-a-skybox-with-glsl-version-330 2 | // 3 | attribute vec4 aPosition; 4 | 5 | #pragma glslify: inverse = require('glsl-inverse') 6 | #pragma glslify: transpose = require('glsl-transpose') 7 | 8 | uniform mat4 uProjectionMatrix; 9 | uniform mat4 uViewMatrix; 10 | 11 | varying vec3 wcNormal; 12 | 13 | void main() { 14 | mat4 inverseProjection = inverse(uProjectionMatrix); 15 | mat3 inverseModelview = transpose(mat3(uViewMatrix)); 16 | 17 | //transform from the normalized device coordinates back to the view space 18 | vec3 unprojected = (inverseProjection * aPosition).xyz; 19 | 20 | //transfrom from the view space back to the world space 21 | //and use it as a sampling vector 22 | wcNormal = inverseModelview * unprojected; 23 | 24 | gl_Position = aPosition; 25 | } 26 | -------------------------------------------------------------------------------- /303-fullscreenquad-skybox/SkyboxQuadDebug.vert: -------------------------------------------------------------------------------- 1 | //Based on http://gamedev.stackexchange.com/questions/60313/implementing-a-skybox-with-glsl-version-330 2 | attribute vec4 aPosition; 3 | 4 | #pragma glslify: inverse = require('glsl-inverse') 5 | #pragma glslify: transpose = require('glsl-transpose') 6 | 7 | uniform mat4 uProjectionMatrix; 8 | uniform mat4 uViewMatrix; 9 | 10 | uniform mat4 uOrigProjectionMatrix; 11 | uniform mat4 uOrigViewMatrix; 12 | 13 | uniform float uFarNearRatio; 14 | uniform vec3 uRightRight; 15 | uniform vec3 uUpTop; 16 | uniform vec3 uFrontNear; 17 | uniform vec3 uCamPosition; 18 | 19 | varying vec3 wcNormal; 20 | 21 | void main2() { 22 | mat4 inverseProjection = inverse(uOrigProjectionMatrix); 23 | mat3 transposedView = transpose(mat3(uOrigViewMatrix)); 24 | vec3 unprojected = (inverseProjection * aPosition).xyz; 25 | wcNormal = transposedView * unprojected; 26 | 27 | vec3 wcPos = uCamPosition + (uFrontNear + aPosition.x * uRightRight + aPosition.y * uUpTop) * uFarNearRatio; 28 | 29 | gl_Position = uProjectionMatrix * uViewMatrix * vec4(wcPos, 1.0); 30 | } 31 | 32 | void main() { 33 | main2(); 34 | return; 35 | mat4 inverseProjection = inverse(uProjectionMatrix); 36 | mat3 inverseModelview = transpose(mat3(uViewMatrix)); 37 | vec3 unprojected = (inverseProjection * aPosition).xyz; 38 | wcNormal = inverseModelview * unprojected; 39 | 40 | gl_Position = aPosition; 41 | } 42 | -------------------------------------------------------------------------------- /304-load-hdr/Reflection.frag: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | #pragma glslify: envMapEquirect = require(../local_modules/glsl-envmap-equirect) 6 | #pragma glslify: toGamma = require(glsl-gamma/out) 7 | 8 | uniform mat4 uInverseViewMatrix; 9 | uniform sampler2D uEnvMap; 10 | uniform bool uCorrectGamma; 11 | 12 | varying vec3 ecPosition; 13 | varying vec3 ecNormal; 14 | 15 | void main() { 16 | vec3 ecEyeDir = normalize(-ecPosition); 17 | vec3 wcEyeDir = vec3(uInverseViewMatrix * vec4(ecEyeDir, 0.0)); 18 | vec3 wcNormal = vec3(uInverseViewMatrix * vec4(ecNormal, 0.0)); 19 | 20 | vec3 reflectionWorld = reflect(-wcEyeDir, normalize(wcNormal)); 21 | 22 | gl_FragColor.rgb = texture2D(uEnvMap, envMapEquirect(reflectionWorld)).rgb; 23 | 24 | if (uCorrectGamma) { 25 | gl_FragColor.rgb = toGamma(gl_FragColor.rgb); 26 | } 27 | gl_FragColor.a = 1.0; 28 | } 29 | -------------------------------------------------------------------------------- /304-load-hdr/Reflection.vert: -------------------------------------------------------------------------------- 1 | attribute vec4 aPosition; 2 | attribute vec3 aNormal; 3 | 4 | uniform mat4 uProjectionMatrix; 5 | uniform mat4 uViewMatrix; 6 | uniform mat4 uModelMatrix; 7 | uniform mat3 uNormalMatrix; 8 | 9 | varying vec3 ecPosition; 10 | varying vec3 ecNormal; 11 | 12 | void main() { 13 | gl_Position = uProjectionMatrix * uViewMatrix * uModelMatrix * aPosition; 14 | ecPosition = vec3(uViewMatrix * uModelMatrix * aPosition); 15 | ecNormal = uNormalMatrix * aNormal; 16 | } 17 | -------------------------------------------------------------------------------- /304-load-hdr/SkyboxQuad.frag: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | #pragma glslify: envMapEquirect = require(../local_modules/glsl-envmap-equirect) 6 | #pragma glslify: toGamma = require(glsl-gamma/out) 7 | 8 | uniform sampler2D uEnvMap; 9 | uniform bool uCorrectGamma; 10 | 11 | varying vec3 wcNormal; 12 | 13 | void main() { 14 | vec3 N = normalize(wcNormal); 15 | gl_FragColor.rgb = texture2D(uEnvMap, envMapEquirect(N)).rgb; 16 | 17 | if (uCorrectGamma) { 18 | gl_FragColor.rgb = toGamma(gl_FragColor.rgb); 19 | } 20 | 21 | gl_FragColor.a = 1.0; 22 | } 23 | -------------------------------------------------------------------------------- /304-load-hdr/SkyboxQuad.vert: -------------------------------------------------------------------------------- 1 | //Based on http://gamedev.stackexchange.com/questions/60313/implementing-a-skybox-with-glsl-version-330 2 | // 3 | attribute vec4 aPosition; 4 | 5 | #pragma glslify: inverse = require('glsl-inverse') 6 | #pragma glslify: transpose = require('glsl-transpose') 7 | 8 | uniform mat4 uProjectionMatrix; 9 | uniform mat4 uViewMatrix; 10 | 11 | varying vec3 wcNormal; 12 | 13 | void main() { 14 | mat4 inverseProjection = inverse(uProjectionMatrix); 15 | mat3 inverseModelview = transpose(mat3(uViewMatrix)); 16 | vec3 unprojected = (inverseProjection * aPosition).xyz; 17 | wcNormal = inverseModelview * unprojected; 18 | 19 | gl_Position = aPosition; 20 | } 21 | -------------------------------------------------------------------------------- /304-load-hdr/main.js: -------------------------------------------------------------------------------- 1 | var Window = require('pex-sys/Window'); 2 | var Mat4 = require('pex-math/Mat4'); 3 | var Vec3 = require('pex-math/Vec3'); 4 | var glslify = require('glslify-promise'); 5 | var createSphere = require('primitive-sphere'); 6 | var parseHdr = require('../local_modules/parse-hdr'); 7 | var isBrowser = require('is-browser'); 8 | var GUI = require('pex-gui'); 9 | var PerspCamera = require('pex-cam/PerspCamera'); 10 | var Arcball = require('pex-cam/Arcball'); 11 | 12 | var ASSETS_DIR = isBrowser ? '../assets' : __dirname + '/../assets'; 13 | 14 | Window.create({ 15 | settings: { 16 | width: 1024, 17 | height: 576, 18 | fullscreen: isBrowser 19 | }, 20 | resources: { 21 | skyboxVert: { glsl: glslify(__dirname + '/SkyboxQuad.vert') }, 22 | skyboxFrag: { glsl: glslify(__dirname + '/SkyboxQuad.frag') }, 23 | reflectionVert: { glsl: glslify(__dirname + '/Reflection.vert') }, 24 | reflectionFrag: { glsl: glslify(__dirname + '/Reflection.frag') }, 25 | envMap: { binary: ASSETS_DIR + '/envmaps/pisa_latlong_256.hdr' } 26 | }, 27 | gamma: false, 28 | init: function() { 29 | var ctx = this.getContext(); 30 | 31 | this.gui = new GUI(ctx, this.getWidth(), this.getHeight()); 32 | this.gui.addParam('Gamma', this, 'gamma'); 33 | this.addEventListener(this.gui); 34 | 35 | this.camera = new PerspCamera(45, this.getAspectRatio(), 0.1, 50); 36 | this.camera.lookAt([0, 0, -5], [0, 0, 0], [0, 1, 0]); 37 | this.arcball = new Arcball(this.camera, this.getWidth(), this.getHeight()); 38 | this.addEventListener(this.arcball); 39 | 40 | ctx.setProjectionMatrix(this.camera.getProjectionMatrix()); 41 | ctx.setViewMatrix(this.camera.getViewMatrix()); 42 | 43 | var res = this.getResources(); 44 | 45 | this.skyboxProgram = ctx.createProgram(res.skyboxVert, res.skyboxFrag); 46 | ctx.bindProgram(this.skyboxProgram); 47 | this.skyboxProgram.setUniform('uEnvMap', 0); 48 | 49 | this.reflectionProgram = ctx.createProgram(res.reflectionVert, res.reflectionFrag); 50 | ctx.bindProgram(this.reflectionProgram); 51 | this.reflectionProgram.setUniform('uEnvMap', 0); 52 | 53 | var hdrInfo = parseHdr(res.envMap); 54 | this.envMap = ctx.createTexture2D(hdrInfo.data, hdrInfo.shape[0], hdrInfo.shape[1], { 55 | type: ctx.FLOAT 56 | }); 57 | 58 | var skyboxPositions = [[-1,-1],[1,-1], [1,1],[-1,1]]; 59 | var skyboxFaces = [ [0, 1, 2], [0, 2, 3]]; 60 | var skyboxAttributes = [ 61 | { data: skyboxPositions, location: ctx.ATTRIB_POSITION }, 62 | ]; 63 | var skyboxIndices = { data: skyboxFaces }; 64 | this.skyboxMesh = ctx.createMesh(skyboxAttributes, skyboxIndices); 65 | 66 | var sphere = createSphere(); 67 | var attributes = [ 68 | { data: sphere.positions, location: ctx.ATTRIB_POSITION }, 69 | { data: sphere.normals, location: ctx.ATTRIB_NORMAL }, 70 | { data: sphere.uvs, location: ctx.ATTRIB_TEX_COORD_0 }, 71 | ]; 72 | var sphereIndices = { data: sphere.cells, usage: ctx.STATIC_DRAW }; 73 | this.sphereMesh = ctx.createMesh(attributes, sphereIndices, ctx.TRIANGLES); 74 | }, 75 | draw: function() { 76 | var ctx = this.getContext(); 77 | ctx.setClearColor(0.2, 0.2, 0.2, 1); 78 | ctx.clear(ctx.COLOR_BIT | ctx.DEPTH_BIT); 79 | 80 | this.arcball.apply(); 81 | ctx.setViewMatrix(this.camera.getViewMatrix()); 82 | 83 | ctx.bindTexture(this.envMap, 0); 84 | ctx.bindProgram(this.skyboxProgram); 85 | this.skyboxProgram.setUniform('uCorrectGamma', this.gamma); 86 | 87 | ctx.setDepthTest(false); 88 | ctx.bindMesh(this.skyboxMesh); 89 | ctx.drawMesh(); 90 | 91 | ctx.bindProgram(this.reflectionProgram); 92 | this.reflectionProgram.setUniform('uCorrectGamma', this.gamma); 93 | ctx.setDepthTest(true); 94 | 95 | ctx.bindMesh(this.sphereMesh); 96 | ctx.drawMesh(); 97 | 98 | this.gui.draw(); 99 | } 100 | }) 101 | -------------------------------------------------------------------------------- /305-exposure-basic/Reflection.frag: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | #pragma glslify: envMapEquirect = require(../local_modules/glsl-envmap-equirect) 6 | #pragma glslify: toGamma = require(glsl-gamma/out) 7 | 8 | uniform mat4 uInverseViewMatrix; 9 | uniform sampler2D uEnvMap; 10 | uniform bool uCorrectGamma; 11 | uniform float uExposure; 12 | 13 | varying vec3 ecPosition; 14 | varying vec3 ecNormal; 15 | 16 | void main() { 17 | vec3 ecEyeDir = normalize(-ecPosition); 18 | vec3 wcEyeDir = vec3(uInverseViewMatrix * vec4(ecEyeDir, 0.0)); 19 | vec3 wcNormal = vec3(uInverseViewMatrix * vec4(ecNormal, 0.0)); 20 | 21 | vec3 reflectionWorld = reflect(-wcEyeDir, normalize(wcNormal)); 22 | 23 | gl_FragColor.rgb = texture2D(uEnvMap, envMapEquirect(reflectionWorld)).rgb; 24 | 25 | gl_FragColor.rgb *= uExposure; 26 | 27 | if (uCorrectGamma) { 28 | gl_FragColor.rgb = toGamma(gl_FragColor.rgb); 29 | } 30 | gl_FragColor.a = 1.0; 31 | } 32 | -------------------------------------------------------------------------------- /305-exposure-basic/Reflection.vert: -------------------------------------------------------------------------------- 1 | attribute vec4 aPosition; 2 | attribute vec3 aNormal; 3 | 4 | uniform mat4 uProjectionMatrix; 5 | uniform mat4 uViewMatrix; 6 | uniform mat4 uModelMatrix; 7 | uniform mat3 uNormalMatrix; 8 | 9 | varying vec3 ecPosition; 10 | varying vec3 ecNormal; 11 | 12 | void main() { 13 | gl_Position = uProjectionMatrix * uViewMatrix * uModelMatrix * aPosition; 14 | ecPosition = vec3(uViewMatrix * uModelMatrix * aPosition); 15 | ecNormal = uNormalMatrix * aNormal; 16 | } 17 | -------------------------------------------------------------------------------- /305-exposure-basic/SkyboxQuad.frag: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | #pragma glslify: envMapEquirect = require(../local_modules/glsl-envmap-equirect) 6 | #pragma glslify: toGamma = require(glsl-gamma/out) 7 | 8 | uniform sampler2D uEnvMap; 9 | uniform bool uCorrectGamma; 10 | uniform float uExposure; 11 | 12 | varying vec3 wcNormal; 13 | 14 | void main() { 15 | vec3 N = normalize(wcNormal); 16 | gl_FragColor.rgb = texture2D(uEnvMap, envMapEquirect(N)).rgb; 17 | 18 | gl_FragColor.rgb *= uExposure; 19 | 20 | if (uCorrectGamma) { 21 | gl_FragColor.rgb = toGamma(gl_FragColor.rgb); 22 | } 23 | 24 | gl_FragColor.a = 1.0; 25 | } 26 | -------------------------------------------------------------------------------- /305-exposure-basic/SkyboxQuad.vert: -------------------------------------------------------------------------------- 1 | //Based on http://gamedev.stackexchange.com/questions/60313/implementing-a-skybox-with-glsl-version-330 2 | // 3 | attribute vec4 aPosition; 4 | 5 | #pragma glslify: inverse = require('glsl-inverse') 6 | #pragma glslify: transpose = require('glsl-transpose') 7 | 8 | uniform mat4 uProjectionMatrix; 9 | uniform mat4 uViewMatrix; 10 | 11 | varying vec3 wcNormal; 12 | 13 | void main() { 14 | mat4 inverseProjection = inverse(uProjectionMatrix); 15 | mat3 inverseModelview = transpose(mat3(uViewMatrix)); 16 | vec3 unprojected = (inverseProjection * aPosition).xyz; 17 | wcNormal = inverseModelview * unprojected; 18 | 19 | gl_Position = aPosition; 20 | } 21 | -------------------------------------------------------------------------------- /305-exposure-basic/main.js: -------------------------------------------------------------------------------- 1 | var Window = require('pex-sys/Window'); 2 | var Mat4 = require('pex-math/Mat4'); 3 | var Vec3 = require('pex-math/Vec3'); 4 | var glslify = require('glslify-promise'); 5 | var createSphere = require('primitive-sphere'); 6 | var parseHdr = require('../local_modules/parse-hdr'); 7 | var isBrowser = require('is-browser'); 8 | var GUI = require('pex-gui'); 9 | var PerspCamera = require('pex-cam/PerspCamera'); 10 | var Arcball = require('pex-cam/Arcball'); 11 | 12 | var ASSETS_DIR = isBrowser ? '../assets' : __dirname + '/../assets'; 13 | 14 | Window.create({ 15 | settings: { 16 | width: 1024, 17 | height: 576, 18 | fullscreen: isBrowser 19 | }, 20 | resources: { 21 | skyboxVert: { glsl: glslify(__dirname + '/SkyboxQuad.vert') }, 22 | skyboxFrag: { glsl: glslify(__dirname + '/SkyboxQuad.frag') }, 23 | reflectionVert: { glsl: glslify(__dirname + '/Reflection.vert') }, 24 | reflectionFrag: { glsl: glslify(__dirname + '/Reflection.frag') }, 25 | envMap: { binary: ASSETS_DIR + '/envmaps/pisa_latlong_256.hdr' } 26 | }, 27 | gamma: true, 28 | exposure: 1, 29 | init: function() { 30 | var ctx = this.getContext(); 31 | 32 | this.gui = new GUI(ctx, this.getWidth(), this.getHeight()); 33 | this.gui.addParam('Gamma', this, 'gamma'); 34 | this.gui.addParam('Exposure', this, 'exposure', { min: 0, max: 3 }); 35 | this.addEventListener(this.gui); 36 | 37 | this.camera = new PerspCamera(45, this.getAspectRatio(), 0.1, 50); 38 | this.camera.lookAt([0, 0, -5], [0, 0, 0], [0, 1, 0]); 39 | this.arcball = new Arcball(this.camera, this.getWidth(), this.getHeight()); 40 | this.addEventListener(this.arcball); 41 | 42 | ctx.setProjectionMatrix(this.camera.getProjectionMatrix()); 43 | ctx.setViewMatrix(this.camera.getViewMatrix()); 44 | 45 | var res = this.getResources(); 46 | 47 | this.skyboxProgram = ctx.createProgram(res.skyboxVert, res.skyboxFrag); 48 | ctx.bindProgram(this.skyboxProgram); 49 | this.skyboxProgram.setUniform('uEnvMap', 0); 50 | 51 | this.reflectionProgram = ctx.createProgram(res.reflectionVert, res.reflectionFrag); 52 | ctx.bindProgram(this.reflectionProgram); 53 | this.reflectionProgram.setUniform('uEnvMap', 0); 54 | 55 | var hdrInfo = parseHdr(res.envMap); 56 | this.envMap = ctx.createTexture2D(hdrInfo.data, hdrInfo.shape[0], hdrInfo.shape[1], { 57 | type: ctx.FLOAT 58 | }); 59 | 60 | var skyboxPositions = [[-1,-1],[1,-1], [1,1],[-1,1]]; 61 | var skyboxFaces = [ [0, 1, 2], [0, 2, 3]]; 62 | var skyboxAttributes = [ 63 | { data: skyboxPositions, location: ctx.ATTRIB_POSITION }, 64 | ]; 65 | var skyboxIndices = { data: skyboxFaces }; 66 | this.skyboxMesh = ctx.createMesh(skyboxAttributes, skyboxIndices); 67 | 68 | var sphere = createSphere(); 69 | var attributes = [ 70 | { data: sphere.positions, location: ctx.ATTRIB_POSITION }, 71 | { data: sphere.normals, location: ctx.ATTRIB_NORMAL }, 72 | { data: sphere.uvs, location: ctx.ATTRIB_TEX_COORD_0 }, 73 | ]; 74 | var sphereIndices = { data: sphere.cells, usage: ctx.STATIC_DRAW }; 75 | this.sphereMesh = ctx.createMesh(attributes, sphereIndices, ctx.TRIANGLES); 76 | }, 77 | draw: function() { 78 | var ctx = this.getContext(); 79 | ctx.setClearColor(0.2, 0.2, 0.2, 1); 80 | ctx.clear(ctx.COLOR_BIT | ctx.DEPTH_BIT); 81 | 82 | this.arcball.apply(); 83 | ctx.setViewMatrix(this.camera.getViewMatrix()); 84 | 85 | ctx.bindTexture(this.envMap, 0); 86 | 87 | ctx.bindProgram(this.skyboxProgram); 88 | this.skyboxProgram.setUniform('uCorrectGamma', this.gamma); 89 | this.skyboxProgram.setUniform('uExposure', this.exposure); 90 | 91 | ctx.setDepthTest(false); 92 | ctx.bindMesh(this.skyboxMesh); 93 | ctx.drawMesh(); 94 | 95 | ctx.bindProgram(this.reflectionProgram); 96 | this.reflectionProgram.setUniform('uCorrectGamma', this.gamma); 97 | this.reflectionProgram.setUniform('uExposure', this.exposure); 98 | ctx.setDepthTest(true); 99 | 100 | ctx.bindMesh(this.sphereMesh); 101 | ctx.drawMesh(); 102 | 103 | this.gui.draw(); 104 | } 105 | }) 106 | -------------------------------------------------------------------------------- /306-tonemap-reinhard/Reflection.frag: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | #pragma glslify: envMapEquirect = require(../local_modules/glsl-envmap-equirect) 6 | #pragma glslify: tonemapReinhard = require(../local_modules/glsl-tonemap-reinhard) 7 | #pragma glslify: toGamma = require(glsl-gamma/out) 8 | 9 | uniform mat4 uInverseViewMatrix; 10 | uniform sampler2D uEnvMap; 11 | uniform bool uCorrectGamma; 12 | uniform bool uTonemap; 13 | uniform float uExposure; 14 | 15 | varying vec3 ecPosition; 16 | varying vec3 ecNormal; 17 | 18 | void main() { 19 | vec3 ecEyeDir = normalize(-ecPosition); 20 | vec3 wcEyeDir = vec3(uInverseViewMatrix * vec4(ecEyeDir, 0.0)); 21 | vec3 wcNormal = vec3(uInverseViewMatrix * vec4(ecNormal, 0.0)); 22 | 23 | vec3 reflectionWorld = reflect(-wcEyeDir, normalize(wcNormal)); 24 | 25 | gl_FragColor.rgb = texture2D(uEnvMap, envMapEquirect(reflectionWorld)).rgb; 26 | 27 | gl_FragColor.rgb *= uExposure; 28 | 29 | if (uTonemap) { 30 | gl_FragColor.rgb = tonemapReinhard(gl_FragColor.rgb); 31 | } 32 | 33 | if (uCorrectGamma) { 34 | gl_FragColor.rgb = toGamma(gl_FragColor.rgb); 35 | } 36 | gl_FragColor.a = 1.0; 37 | } 38 | -------------------------------------------------------------------------------- /306-tonemap-reinhard/Reflection.vert: -------------------------------------------------------------------------------- 1 | attribute vec4 aPosition; 2 | attribute vec3 aNormal; 3 | 4 | uniform mat4 uProjectionMatrix; 5 | uniform mat4 uViewMatrix; 6 | uniform mat4 uModelMatrix; 7 | uniform mat3 uNormalMatrix; 8 | 9 | varying vec3 ecPosition; 10 | varying vec3 ecNormal; 11 | 12 | void main() { 13 | gl_Position = uProjectionMatrix * uViewMatrix * uModelMatrix * aPosition; 14 | ecPosition = vec3(uViewMatrix * uModelMatrix * aPosition); 15 | ecNormal = uNormalMatrix * aNormal; 16 | } 17 | -------------------------------------------------------------------------------- /306-tonemap-reinhard/SkyboxQuad.frag: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | #pragma glslify: envMapEquirect = require(../local_modules/glsl-envmap-equirect) 6 | #pragma glslify: tonemapReinhard = require(../local_modules/glsl-tonemap-reinhard) 7 | #pragma glslify: toGamma = require(glsl-gamma/out) 8 | 9 | uniform sampler2D uEnvMap; 10 | uniform bool uCorrectGamma; 11 | uniform bool uTonemap; 12 | uniform float uExposure; 13 | 14 | varying vec3 wcNormal; 15 | 16 | void main() { 17 | vec3 N = normalize(wcNormal); 18 | gl_FragColor.rgb = texture2D(uEnvMap, envMapEquirect(N)).rgb; 19 | 20 | gl_FragColor.rgb *= uExposure; 21 | 22 | if (uTonemap) { 23 | gl_FragColor.rgb = tonemapReinhard(gl_FragColor.rgb); 24 | } 25 | 26 | if (uCorrectGamma) { 27 | gl_FragColor.rgb = toGamma(gl_FragColor.rgb); 28 | } 29 | 30 | gl_FragColor.a = 1.0; 31 | } 32 | -------------------------------------------------------------------------------- /306-tonemap-reinhard/SkyboxQuad.vert: -------------------------------------------------------------------------------- 1 | //Based on http://gamedev.stackexchange.com/questions/60313/implementing-a-skybox-with-glsl-version-330 2 | // 3 | attribute vec4 aPosition; 4 | 5 | #pragma glslify: inverse = require('glsl-inverse') 6 | #pragma glslify: transpose = require('glsl-transpose') 7 | 8 | uniform mat4 uProjectionMatrix; 9 | uniform mat4 uViewMatrix; 10 | 11 | varying vec3 wcNormal; 12 | 13 | void main() { 14 | mat4 inverseProjection = inverse(uProjectionMatrix); 15 | mat3 inverseModelview = transpose(mat3(uViewMatrix)); 16 | vec3 unprojected = (inverseProjection * aPosition).xyz; 17 | wcNormal = inverseModelview * unprojected; 18 | 19 | gl_Position = aPosition; 20 | } 21 | -------------------------------------------------------------------------------- /306-tonemap-reinhard/main.js: -------------------------------------------------------------------------------- 1 | var Window = require('pex-sys/Window'); 2 | var Mat4 = require('pex-math/Mat4'); 3 | var Vec3 = require('pex-math/Vec3'); 4 | var glslify = require('glslify-promise'); 5 | var createSphere = require('primitive-sphere'); 6 | var parseHdr = require('../local_modules/parse-hdr'); 7 | var isBrowser = require('is-browser'); 8 | var GUI = require('pex-gui'); 9 | var PerspCamera = require('pex-cam/PerspCamera'); 10 | var Arcball = require('pex-cam/Arcball'); 11 | 12 | var ASSETS_DIR = isBrowser ? '../assets' : __dirname + '/../assets'; 13 | 14 | Window.create({ 15 | settings: { 16 | width: 1024, 17 | height: 576, 18 | fullscreen: isBrowser 19 | }, 20 | resources: { 21 | skyboxVert: { glsl: glslify(__dirname + '/SkyboxQuad.vert') }, 22 | skyboxFrag: { glsl: glslify(__dirname + '/SkyboxQuad.frag') }, 23 | reflectionVert: { glsl: glslify(__dirname + '/Reflection.vert') }, 24 | reflectionFrag: { glsl: glslify(__dirname + '/Reflection.frag') }, 25 | envMap: { binary: ASSETS_DIR + '/envmaps/pisa_latlong_256.hdr' } 26 | }, 27 | gamma: true, 28 | tonemap: true, 29 | exposure: 1, 30 | init: function() { 31 | var ctx = this.getContext(); 32 | 33 | this.gui = new GUI(ctx, this.getWidth(), this.getHeight()); 34 | this.gui.addParam('Gamma', this, 'gamma'); 35 | this.gui.addParam('Tonemap', this, 'tonemap'); 36 | this.gui.addParam('Exposure', this, 'exposure', { min: 0, max: 3 }); 37 | this.addEventListener(this.gui); 38 | 39 | this.camera = new PerspCamera(45, this.getAspectRatio(), 0.1, 50); 40 | this.camera.lookAt([0, 0, -5], [0, 0, 0], [0, 1, 0]); 41 | this.arcball = new Arcball(this.camera, this.getWidth(), this.getHeight()); 42 | this.addEventListener(this.arcball); 43 | 44 | ctx.setProjectionMatrix(this.camera.getProjectionMatrix()); 45 | ctx.setViewMatrix(this.camera.getViewMatrix()); 46 | 47 | var res = this.getResources(); 48 | 49 | this.skyboxProgram = ctx.createProgram(res.skyboxVert, res.skyboxFrag); 50 | ctx.bindProgram(this.skyboxProgram); 51 | this.skyboxProgram.setUniform('uEnvMap', 0); 52 | 53 | this.reflectionProgram = ctx.createProgram(res.reflectionVert, res.reflectionFrag); 54 | ctx.bindProgram(this.reflectionProgram); 55 | this.reflectionProgram.setUniform('uEnvMap', 0); 56 | 57 | var hdrInfo = parseHdr(res.envMap); 58 | this.envMap = ctx.createTexture2D(hdrInfo.data, hdrInfo.shape[0], hdrInfo.shape[1], { 59 | type: ctx.FLOAT 60 | }); 61 | 62 | var skyboxPositions = [[-1,-1],[1,-1], [1,1],[-1,1]]; 63 | var skyboxFaces = [ [0, 1, 2], [0, 2, 3]]; 64 | var skyboxAttributes = [ 65 | { data: skyboxPositions, location: ctx.ATTRIB_POSITION }, 66 | ]; 67 | var skyboxIndices = { data: skyboxFaces }; 68 | this.skyboxMesh = ctx.createMesh(skyboxAttributes, skyboxIndices); 69 | 70 | var sphere = createSphere(); 71 | var attributes = [ 72 | { data: sphere.positions, location: ctx.ATTRIB_POSITION }, 73 | { data: sphere.normals, location: ctx.ATTRIB_NORMAL }, 74 | { data: sphere.uvs, location: ctx.ATTRIB_TEX_COORD_0 }, 75 | ]; 76 | var sphereIndices = { data: sphere.cells, usage: ctx.STATIC_DRAW }; 77 | this.sphereMesh = ctx.createMesh(attributes, sphereIndices, ctx.TRIANGLES); 78 | }, 79 | draw: function() { 80 | var ctx = this.getContext(); 81 | ctx.setClearColor(0.2, 0.2, 0.2, 1); 82 | ctx.clear(ctx.COLOR_BIT | ctx.DEPTH_BIT); 83 | 84 | this.arcball.apply(); 85 | ctx.setViewMatrix(this.camera.getViewMatrix()); 86 | 87 | ctx.bindTexture(this.envMap, 0); 88 | 89 | ctx.bindProgram(this.skyboxProgram); 90 | this.skyboxProgram.setUniform('uCorrectGamma', this.gamma); 91 | this.skyboxProgram.setUniform('uTonemap', this.tonemap); 92 | this.skyboxProgram.setUniform('uExposure', this.exposure); 93 | 94 | ctx.setDepthTest(false); 95 | ctx.bindMesh(this.skyboxMesh); 96 | ctx.drawMesh(); 97 | 98 | ctx.bindProgram(this.reflectionProgram); 99 | this.reflectionProgram.setUniform('uCorrectGamma', this.gamma); 100 | this.reflectionProgram.setUniform('uTonemap', this.tonemap); 101 | this.reflectionProgram.setUniform('uExposure', this.exposure); 102 | ctx.setDepthTest(true); 103 | 104 | ctx.bindMesh(this.sphereMesh); 105 | ctx.drawMesh(); 106 | 107 | this.gui.draw(); 108 | } 109 | }) 110 | -------------------------------------------------------------------------------- /307-tonemap-compare/Reflection.frag: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | #pragma glslify: envMapEquirect = require(../local_modules/glsl-envmap-equirect) 6 | #pragma glslify: toGamma = require(glsl-gamma/out) 7 | #pragma glslify: tonemapReinhard = require(../local_modules/glsl-tonemap-reinhard) 8 | #pragma glslify: tonemapFilmic = require(../local_modules/glsl-tonemap-filmic) 9 | #pragma glslify: tonemapUncharted2 = require(../local_modules/glsl-tonemap-uncharted2) 10 | 11 | uniform mat4 uInverseViewMatrix; 12 | uniform sampler2D uEnvMap; 13 | uniform float uExposure; 14 | uniform float uTonemappingMethod; 15 | 16 | varying vec3 ecPosition; 17 | varying vec3 ecNormal; 18 | 19 | void main() { 20 | vec3 ecEyeDir = normalize(-ecPosition); 21 | vec3 wcEyeDir = vec3(uInverseViewMatrix * vec4(ecEyeDir, 0.0)); 22 | vec3 wcNormal = vec3(uInverseViewMatrix * vec4(ecNormal, 0.0)); 23 | 24 | vec3 reflectionWorld = reflect(-wcEyeDir, normalize(wcNormal)); 25 | 26 | gl_FragColor.rgb = texture2D(uEnvMap, envMapEquirect(reflectionWorld)).rgb; 27 | gl_FragColor.rgb *= uExposure; 28 | 29 | if (uTonemappingMethod == 0.0) { 30 | //no tonemapping 31 | gl_FragColor.rgb = toGamma(gl_FragColor.rgb); 32 | } 33 | else if (uTonemappingMethod == 1.0) { 34 | gl_FragColor.rgb = tonemapReinhard(gl_FragColor.rgb); 35 | gl_FragColor.rgb = toGamma(gl_FragColor.rgb); 36 | } 37 | else if (uTonemappingMethod == 2.0) { 38 | gl_FragColor.rgb = tonemapFilmic(gl_FragColor.rgb); 39 | } 40 | else if (uTonemappingMethod == 3.0) { 41 | gl_FragColor.rgb = tonemapUncharted2(gl_FragColor.rgb); 42 | gl_FragColor.rgb = toGamma(gl_FragColor.rgb); 43 | } 44 | 45 | gl_FragColor.a = 1.0; 46 | } 47 | -------------------------------------------------------------------------------- /307-tonemap-compare/Reflection.vert: -------------------------------------------------------------------------------- 1 | attribute vec4 aPosition; 2 | attribute vec3 aNormal; 3 | 4 | uniform mat4 uProjectionMatrix; 5 | uniform mat4 uViewMatrix; 6 | uniform mat4 uModelMatrix; 7 | uniform mat3 uNormalMatrix; 8 | 9 | varying vec3 ecPosition; 10 | varying vec3 ecNormal; 11 | 12 | void main() { 13 | gl_Position = uProjectionMatrix * uViewMatrix * uModelMatrix * aPosition; 14 | ecPosition = vec3(uViewMatrix * uModelMatrix * aPosition); 15 | ecNormal = uNormalMatrix * aNormal; 16 | } 17 | -------------------------------------------------------------------------------- /307-tonemap-compare/SkyboxQuad.frag: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | #pragma glslify: envMapEquirect = require(../local_modules/glsl-envmap-equirect) 6 | #pragma glslify: toGamma = require(glsl-gamma/out) 7 | #pragma glslify: tonemapReinhard = require(../local_modules/glsl-tonemap-reinhard) 8 | #pragma glslify: tonemapFilmic = require(../local_modules/glsl-tonemap-filmic) 9 | #pragma glslify: tonemapUncharted2 = require(../local_modules/glsl-tonemap-uncharted2) 10 | 11 | varying vec3 wcNormal; 12 | 13 | uniform sampler2D uEnvMap; 14 | uniform float uExposure; 15 | uniform float uTonemappingMethod; 16 | 17 | void main() { 18 | vec3 N = normalize(wcNormal); 19 | gl_FragColor.rgb = texture2D(uEnvMap, envMapEquirect(N)).rgb; 20 | gl_FragColor.rgb *= uExposure; 21 | 22 | if (uTonemappingMethod == 0.0) { 23 | //no tonemapping 24 | gl_FragColor.rgb = toGamma(gl_FragColor.rgb); 25 | } 26 | else if (uTonemappingMethod == 1.0) { 27 | gl_FragColor.rgb = tonemapReinhard(gl_FragColor.rgb); 28 | gl_FragColor.rgb = toGamma(gl_FragColor.rgb); 29 | } 30 | else if (uTonemappingMethod == 2.0) { 31 | gl_FragColor.rgb = tonemapFilmic(gl_FragColor.rgb); 32 | } 33 | else if (uTonemappingMethod == 3.0) { 34 | gl_FragColor.rgb = tonemapUncharted2(gl_FragColor.rgb); 35 | gl_FragColor.rgb = toGamma(gl_FragColor.rgb); 36 | } 37 | 38 | gl_FragColor.a = 1.0; 39 | } 40 | -------------------------------------------------------------------------------- /307-tonemap-compare/SkyboxQuad.vert: -------------------------------------------------------------------------------- 1 | //Based on http://gamedev.stackexchange.com/questions/60313/implementing-a-skybox-with-glsl-version-330 2 | // 3 | attribute vec4 aPosition; 4 | 5 | #pragma glslify: inverse = require('glsl-inverse') 6 | #pragma glslify: transpose = require('glsl-transpose') 7 | 8 | uniform mat4 uProjectionMatrix; 9 | uniform mat4 uViewMatrix; 10 | 11 | varying vec3 wcNormal; 12 | 13 | void main() { 14 | mat4 inverseProjection = inverse(uProjectionMatrix); 15 | mat3 inverseModelview = transpose(mat3(uViewMatrix)); 16 | vec3 unprojected = (inverseProjection * aPosition).xyz; 17 | wcNormal = inverseModelview * unprojected; 18 | 19 | gl_Position = aPosition; 20 | } 21 | -------------------------------------------------------------------------------- /308-exposure-camera/Reflection.frag: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | #pragma glslify: envMapEquirect = require(../local_modules/glsl-envmap-equirect) 6 | #pragma glslify: toGamma = require(glsl-gamma/out) 7 | #pragma glslify: tonemapReinhard = require(../local_modules/glsl-tonemap-reinhard) 8 | 9 | uniform mat4 uInverseViewMatrix; 10 | uniform sampler2D uEnvMap; 11 | uniform float uAperture; 12 | uniform float uShutterSpeed; 13 | uniform float uIso; 14 | uniform float uMiddleGrey; 15 | 16 | varying vec3 ecPosition; 17 | varying vec3 ecNormal; 18 | 19 | //White balance middle grey we are targetting for a good scene exposure 20 | //https://en.wikipedia.org/wiki/Middle_gray 21 | const float MIDDLE_GREY = 0.18; 22 | 23 | /* 24 | * Get an exposure using the Standard Output Sensitivity method. 25 | * Accepts an additional parameter of the target middle grey. 26 | */ 27 | float getStandardOutputBasedExposure(float aperture, 28 | float shutterSpeed, 29 | float iso) 30 | { 31 | float q = 0.65; 32 | //float l_avg = (1000.0f / 65.0f) * sqrt(aperture) / (iso * shutterSpeed); 33 | float l_avg = (1.0 / q) * sqrt(aperture) / (iso * shutterSpeed); 34 | //float l_avg = sqrt(aperture) / (iso * shutterSpeed); 35 | return MIDDLE_GREY / l_avg; 36 | } 37 | 38 | void main() { 39 | vec3 ecEyeDir = normalize(-ecPosition); 40 | vec3 wcEyeDir = vec3(uInverseViewMatrix * vec4(ecEyeDir, 0.0)); 41 | vec3 wcNormal = vec3(uInverseViewMatrix * vec4(ecNormal, 0.0)); 42 | 43 | vec3 reflectionWorld = reflect(-wcEyeDir, normalize(wcNormal)); 44 | 45 | //gl_FragColor.rgb = rgbe2rgb(texture2DEnvLatLong(uEnvMap, reflectionWorld)); 46 | //gl_FragColor.rgb *= log(uExposure); 47 | gl_FragColor.rgb = texture2D(uEnvMap, envMapEquirect(reflectionWorld)).rgb; 48 | gl_FragColor.rgb *= getStandardOutputBasedExposure(uAperture, uShutterSpeed, uIso); 49 | //gl_FragColor.rgb *= getStandardOutputBasedExposure(16, uExposure, 100.0, 0.18); 50 | gl_FragColor.rgb = tonemapReinhard(gl_FragColor.rgb); 51 | gl_FragColor.rgb = toGamma(gl_FragColor.rgb); 52 | 53 | gl_FragColor.a = 1.0; 54 | } 55 | -------------------------------------------------------------------------------- /308-exposure-camera/Reflection.vert: -------------------------------------------------------------------------------- 1 | attribute vec4 aPosition; 2 | attribute vec3 aNormal; 3 | 4 | uniform mat4 uProjectionMatrix; 5 | uniform mat4 uViewMatrix; 6 | uniform mat4 uModelMatrix; 7 | uniform mat3 uNormalMatrix; 8 | 9 | varying vec3 ecPosition; 10 | varying vec3 ecNormal; 11 | 12 | void main() { 13 | gl_Position = uProjectionMatrix * uViewMatrix * uModelMatrix * aPosition; 14 | ecPosition = vec3(uViewMatrix * uModelMatrix * aPosition); 15 | ecNormal = uNormalMatrix * aNormal; 16 | } 17 | -------------------------------------------------------------------------------- /308-exposure-camera/SkyboxQuad.frag: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | #pragma glslify: envMapEquirect = require(../local_modules/glsl-envmap-equirect) 6 | #pragma glslify: toGamma = require(glsl-gamma/out) 7 | #pragma glslify: tonemapReinhard = require(../local_modules/glsl-tonemap-reinhard) 8 | 9 | /* 10 | * Get an exposure using the Saturation-based Speed method. 11 | */ 12 | float getSaturationBasedExposure(float aperture, 13 | float shutterSpeed, 14 | float iso) 15 | { 16 | float l_max = (7800.0 / 65.0) * sqrt(aperture) / (iso * shutterSpeed); 17 | return 1.0 / l_max; 18 | } 19 | 20 | //White balance middle grey we are targetting for a good scene exposure 21 | //https://en.wikipedia.org/wiki/Middle_gray 22 | const float MIDDLE_GREY = 0.18; 23 | 24 | /* 25 | * Get an exposure using the Standard Output Sensitivity method. 26 | * Accepts an additional parameter of the target middle grey. 27 | */ 28 | float getStandardOutputBasedExposure(float aperture, 29 | float shutterSpeed, 30 | float iso) 31 | { 32 | //https://placeholderart.wordpress.com/2014/11/21/implementing-a-physically-based-camera-manual-exposure/ 33 | //https://en.wikipedia.org/wiki/Film_speed#Standard_output_sensitivity_.28SOS.29 34 | //photometric exposure magic 35 | //represents the properties of lens 36 | float q = 0.65; 37 | 38 | //float l_avg = (1000.0f / 65.0f) * sqrt(aperture) / (iso * shutterSpeed); 39 | float l_avg = (1.0 / q) * sqrt(aperture) / (iso * shutterSpeed); 40 | //float l_avg = sqrt(aperture) / (iso * shutterSpeed); 41 | return MIDDLE_GREY / l_avg; 42 | } 43 | 44 | varying vec3 vNormal; 45 | 46 | uniform sampler2D uEnvMap; 47 | uniform float uAperture; 48 | uniform float uShutterSpeed; 49 | uniform float uIso; 50 | 51 | void main() { 52 | vec3 N = normalize(vNormal); 53 | //gl_FragColor.rgb = rgbe2rgb(texture2DEnvLatLong(uEnvMap, N)); 54 | //gl_FragColor.rgb *= log(uExposure); 55 | gl_FragColor.rgb = texture2D(uEnvMap, envMapEquirect(N)).rgb; 56 | gl_FragColor.rgb *= getStandardOutputBasedExposure(uAperture, uShutterSpeed, uIso); 57 | //gl_FragColor.rgb *= getStandardOutputBasedExposure(16, uExposure, 100.0, 0.18); 58 | gl_FragColor.rgb = tonemapReinhard(gl_FragColor.rgb); 59 | gl_FragColor.rgb = toGamma(gl_FragColor.rgb); 60 | gl_FragColor.a = 1.0; 61 | } 62 | -------------------------------------------------------------------------------- /308-exposure-camera/SkyboxQuad.vert: -------------------------------------------------------------------------------- 1 | //Based on http://gamedev.stackexchange.com/questions/60313/implementing-a-skybox-with-glsl-version-330 2 | // 3 | attribute vec4 aPosition; 4 | 5 | #pragma glslify: inverse = require('glsl-inverse') 6 | #pragma glslify: transpose = require('glsl-transpose') 7 | 8 | uniform mat4 uProjectionMatrix; 9 | uniform mat4 uViewMatrix; 10 | 11 | varying vec3 vNormal; 12 | 13 | void main() { 14 | mat4 inverseProjection = inverse(uProjectionMatrix); 15 | mat3 inverseModelview = transpose(mat3(uViewMatrix)); 16 | vec3 unprojected = (inverseProjection * aPosition).xyz; 17 | vNormal = inverseModelview * unprojected; 18 | 19 | gl_Position = aPosition; 20 | } 21 | -------------------------------------------------------------------------------- /308-exposure-camera/main.js: -------------------------------------------------------------------------------- 1 | var Window = require('pex-sys/Window'); 2 | var Mat4 = require('pex-math/Mat4'); 3 | var Vec3 = require('pex-math/Vec3'); 4 | var MathUtils = require('pex-math/Utils'); 5 | var glslify = require('glslify-promise'); 6 | var createSphere = require('primitive-sphere'); 7 | var createCube = require('primitive-cube'); 8 | var parseHdr = require('../local_modules/parse-hdr'); 9 | var isBrowser = require('is-browser'); 10 | var GUI = require('pex-gui'); 11 | var PerspCamera = require('pex-cam/PerspCamera'); 12 | var Arcball = require('pex-cam/Arcball'); 13 | 14 | var ASSETS_DIR = isBrowser ? '../assets' : __dirname + '/../assets'; 15 | 16 | Window.create({ 17 | settings: { 18 | width: 1024, 19 | height: 576, 20 | fullscreen: isBrowser 21 | }, 22 | resources: { 23 | skyboxVert: { glsl: glslify(__dirname + '/SkyboxQuad.vert') }, 24 | skyboxFrag: { glsl: glslify(__dirname + '/SkyboxQuad.frag') }, 25 | reflectionVert: { glsl: glslify(__dirname + '/Reflection.vert') }, 26 | reflectionFrag: { glsl: glslify(__dirname + '/Reflection.frag') }, 27 | envMap: { binary: ASSETS_DIR + '/envmaps/pisa_latlong_256.hdr' } 28 | }, 29 | aperture: 16, 30 | shutterSpeed: 0.5, 31 | iso: 100, 32 | onMouseMove: function(e) { 33 | var w = this.getWidth(); 34 | //this.exposure = MathUtils.clamp(MathUtils.map(e.x, 0, w, 1/60, 1), 0, 1); 35 | }, 36 | init: function() { 37 | var ctx = this.getContext(); 38 | 39 | this.gui = new GUI(ctx, this.getWidth(), this.getHeight()); 40 | this.addEventListener(this.gui); 41 | this.gui.addParam('Aperture - f', this, 'aperture', { min: 1.4, max: 32 }); 42 | this.gui.addParam('Sutter Speed (sec)', this, 'shutterSpeed', {min: 1/1000, max: 1/2}); 43 | this.gui.addParam('ISO', this, 'iso', { min: 100, max: 1600 }); 44 | this.gui.addParam('Middle grey', this, 'middleGrey', { min: 0, max: 1 }); 45 | 46 | this.camera = new PerspCamera(45, this.getAspectRatio(), 0.1, 100); 47 | this.camera.lookAt([0, 0, -5], [0, 0, 0], [0, 1, 0]); 48 | this.arcball = new Arcball(this.camera, this.getWidth(), this.getHeight()); 49 | this.addEventListener(this.arcball); 50 | 51 | ctx.setProjectionMatrix(this.camera.getProjectionMatrix()); 52 | ctx.setViewMatrix(this.camera.getViewMatrix()); 53 | 54 | this.modelMatrix = Mat4.create(); 55 | ctx.setModelMatrix(this.modelMatrix); 56 | 57 | var res = this.getResources(); 58 | 59 | this.skyboxProgram = ctx.createProgram(res.skyboxVert, res.skyboxFrag); 60 | ctx.bindProgram(this.skyboxProgram); 61 | this.skyboxProgram.setUniform('uEnvMap', 0); 62 | this.skyboxProgram.setUniform('uAperture', this.aperture); 63 | this.skyboxProgram.setUniform('uShutterSpeed', this.shutterSpeed); 64 | this.skyboxProgram.setUniform('uIso', this.iso); 65 | 66 | 67 | this.reflectionProgram = ctx.createProgram(res.reflectionVert, res.reflectionFrag); 68 | ctx.bindProgram(this.reflectionProgram); 69 | this.reflectionProgram.setUniform('uEnvMap', 0); 70 | this.reflectionProgram.setUniform('uAperture', this.aperture); 71 | this.reflectionProgram.setUniform('uShutterSpeed', this.shutterSpeed); 72 | this.reflectionProgram.setUniform('uIso', this.iso); 73 | 74 | var hdrInfo = parseHdr(res.envMap); 75 | this.envMap = ctx.createTexture2D(hdrInfo.data, hdrInfo.shape[0], hdrInfo.shape[1], { 76 | type: ctx.FLOAT 77 | }); 78 | 79 | var skyboxPositions = [[-1,-1],[1,-1], [1,1],[-1,1]]; 80 | var skyboxFaces = [ [0, 1, 2], [0, 2, 3]]; 81 | var skyboxAttributes = [ 82 | { data: skyboxPositions, location: ctx.ATTRIB_POSITION }, 83 | ]; 84 | var skyboxIndices = { data: skyboxFaces }; 85 | this.skyboxMesh = ctx.createMesh(skyboxAttributes, skyboxIndices); 86 | 87 | var sphere = createSphere(); 88 | var attributes = [ 89 | { data: sphere.positions, location: ctx.ATTRIB_POSITION }, 90 | { data: sphere.normals, location: ctx.ATTRIB_NORMAL }, 91 | { data: sphere.uvs, location: ctx.ATTRIB_TEX_COORD_0 }, 92 | ]; 93 | var sphereIndices = { data: sphere.cells, usage: ctx.STATIC_DRAW }; 94 | this.sphereMesh = ctx.createMesh(attributes, sphereIndices, ctx.TRIANGLES); 95 | }, 96 | draw: function() { 97 | var ctx = this.getContext(); 98 | ctx.setClearColor(0.2, 0.2, 0.2, 1); 99 | ctx.clear(ctx.COLOR_BIT | ctx.DEPTH_BIT); 100 | ctx.setDepthTest(true); 101 | 102 | this.arcball.apply(); 103 | ctx.setViewMatrix(this.camera.getViewMatrix()); 104 | 105 | ctx.bindTexture(this.envMap, 0); 106 | 107 | //move skybox to the camera position 108 | ctx.setDepthTest(false); 109 | ctx.bindProgram(this.skyboxProgram); 110 | this.skyboxProgram.setUniform('uAperture', this.aperture); 111 | this.skyboxProgram.setUniform('uShutterSpeed', this.shutterSpeed); 112 | this.skyboxProgram.setUniform('uIso', this.iso); 113 | ctx.bindMesh(this.skyboxMesh); 114 | ctx.drawMesh(); 115 | 116 | ctx.setDepthTest(true); 117 | ctx.bindProgram(this.reflectionProgram); 118 | this.reflectionProgram.setUniform('uAperture', this.aperture); 119 | this.reflectionProgram.setUniform('uShutterSpeed', this.shutterSpeed); 120 | this.reflectionProgram.setUniform('uIso', this.iso); 121 | ctx.bindMesh(this.sphereMesh); 122 | ctx.drawMesh(); 123 | 124 | this.gui.draw(); 125 | } 126 | }) 127 | -------------------------------------------------------------------------------- /400-hammersley-point-set/main.js: -------------------------------------------------------------------------------- 1 | var Window = require('pex-sys/Window'); 2 | var glslify = require('glslify-promise'); 3 | var PerspCamera = require('pex-cam/PerspCamera'); 4 | var Arcball = require('pex-cam/Arcball'); 5 | var hammersley = require('hammersley'); 6 | var GUI = require('pex-gui'); 7 | var Draw = require('pex-draw'); 8 | var isBrowser = require('is-browser'); 9 | var createSphere = require('primitive-sphere'); 10 | var random = require('pex-random'); 11 | var Vec3 = require('pex-math/Vec3'); 12 | 13 | Window.create({ 14 | settings: { 15 | width: 1024, 16 | height: 576, 17 | fullscreen: isBrowser 18 | }, 19 | resources: { 20 | showColorsVert: { glsl: glslify(__dirname + '/../assets/glsl/ShowColors.vert') }, 21 | showColorsFrag: { glsl: glslify(__dirname + '/../assets/glsl/ShowColors.frag') } 22 | }, 23 | init: function() { 24 | var ctx = this.getContext(); 25 | var res = this.getResources(); 26 | 27 | this.camera = new PerspCamera(60, this.getAspectRatio(), 0.1, 100); 28 | this.camera.lookAt([0, 1, 3], [0, 0, 0], [0, 1, 0]); 29 | this.arcball = new Arcball(this.camera, this.getWidth(), this.getHeight()); 30 | this.addEventListener(this.arcball); 31 | 32 | ctx.setProjectionMatrix(this.camera.getProjectionMatrix()); 33 | ctx.setViewMatrix(this.camera.getViewMatrix()); 34 | 35 | var sphere = createSphere(1, { segments: 16}); 36 | var colors = sphere.positions.map(function() { return [1, 1, 1, 0.25]; }) 37 | var attributes = [ 38 | { data: sphere.positions, location: ctx.ATTRIB_POSITION }, 39 | { data: colors, location: ctx.ATTRIB_COLOR }, 40 | ]; 41 | var sphereIndices = { data: sphere.cells, usage: ctx.STATIC_DRAW }; 42 | this.sphereMesh = ctx.createMesh(attributes, sphereIndices, ctx.LINES); 43 | 44 | this.debugDraw = new Draw(ctx); 45 | this.showColorsProgram = ctx.createProgram(res.showColorsVert, res.showColorsFrag); 46 | 47 | this.center = [0, 0, 0]; 48 | this.samplingDir = Vec3.normalize([1, 1, 1]); 49 | this.samples = this.resamplePoints(this.samplingDir); 50 | }, 51 | resamplePoints: function(N) { 52 | var numSamples = 1024; 53 | var points = []; 54 | for(var i=0; i