├── fit ├── plots │ └── .dummy ├── results │ ├── ltc_1.dds │ ├── ltc_2.dds │ └── ltc.h ├── dds.h ├── brdf.h ├── genie.lua ├── brdf_disneyDiffuse.h ├── LTC.h ├── brdf_beckmann.h ├── brdf_ggx.h ├── float_to_half.h ├── dds.cpp ├── nelder_mead.h ├── export.h ├── plot.h └── fitLTC.cpp ├── webgl ├── images │ └── error_icon.png ├── shaders │ └── ltc │ │ ├── ltc.vs │ │ ├── ltc_blit.vs │ │ ├── ltc_blit.fs │ │ ├── ltc_quad.fs │ │ ├── ltc_line.fs │ │ └── ltc_disk.fs ├── css │ ├── normal_map_blending.css │ ├── plugin.css │ ├── ace_theme_tweaks.css │ ├── super_picker.css │ ├── sandbox.css │ ├── jquery.ui.resizable.css │ └── super_slider.css ├── js │ ├── jquery.mousewheel.min.js │ ├── ace │ │ ├── theme-clouds_midnight.js │ │ └── mode-glsl.js │ ├── macton │ │ ├── macton-utils.js │ │ ├── webgl-utils.js │ │ ├── cameracontroller.js │ │ ├── matrix4x4.js │ │ └── macton-gl-utils.js │ ├── super_picker.js │ ├── super_slider.js │ └── color_picker.js └── ltc_quad.html ├── .gitmodules ├── .gitignore ├── README.md └── LICENSE /fit/plots/.dummy: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fit/results/ltc_1.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selfshadow/ltc_code/HEAD/fit/results/ltc_1.dds -------------------------------------------------------------------------------- /fit/results/ltc_2.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selfshadow/ltc_code/HEAD/fit/results/ltc_2.dds -------------------------------------------------------------------------------- /webgl/images/error_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selfshadow/ltc_code/HEAD/webgl/images/error_icon.png -------------------------------------------------------------------------------- /webgl/shaders/ltc/ltc.vs: -------------------------------------------------------------------------------- 1 | in vec3 position; 2 | 3 | void main() 4 | { 5 | gl_Position = vec4(position, 1.0); 6 | } -------------------------------------------------------------------------------- /webgl/shaders/ltc/ltc_blit.vs: -------------------------------------------------------------------------------- 1 | in vec3 position; 2 | 3 | void main() 4 | { 5 | gl_Position = vec4(position, 1.0); 6 | } -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "external/CImg"] 2 | path = external/CImg 3 | url = https://github.com/dtschump/CImg 4 | [submodule "external/glm"] 5 | path = external/glm 6 | url = https://github.com/g-truc/glm 7 | -------------------------------------------------------------------------------- /fit/dds.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum PixelFormat 4 | { 5 | DDS_FORMAT_R16G16B16A16_FLOAT = 0, 6 | DDS_FORMAT_R32G32B32A32_FLOAT = 1 7 | }; 8 | 9 | bool SaveDDS(char const* path, PixelFormat format, unsigned texelSizeInBytes, unsigned width, unsigned height, void const* data); 10 | -------------------------------------------------------------------------------- /webgl/css/normal_map_blending.css: -------------------------------------------------------------------------------- 1 | #method { 2 | width: 484px; 3 | float: left; 4 | position: relative; 5 | padding: 8px; 6 | margin: 16px 0px 0px 0px; 7 | background: #191919; 8 | } 9 | 10 | #method_text { 11 | font-family: helvetica, arial, sans-serif; 12 | color: #999; 13 | font-size: 12px 14 | } 15 | 16 | -------------------------------------------------------------------------------- /webgl/css/plugin.css: -------------------------------------------------------------------------------- 1 | #colorjack_square { 2 | border: 1px solid #404040; 3 | border-radius: 6px; 4 | background: #191919; 5 | box-shadow: 3px 3px 3px rgba(0,0,0,0.35); 6 | -webkit-box-shadow: 3px 3px 3px rgba(0,0,0,0.35); 7 | -moz-box-shadow: 3px 3px 3px rgba(0,0,0,0.35); 8 | cursor: default; 9 | display: block; 10 | font-family: arial, helvetica, sans-serif; 11 | font-size: 11px; 12 | position: relative; 13 | width: 215px; 14 | height: 10px; 15 | z-index:1; 16 | } 17 | -------------------------------------------------------------------------------- /fit/brdf.h: -------------------------------------------------------------------------------- 1 | #ifndef _BRDF_ 2 | #define _BRDF_ 3 | 4 | #include 5 | using namespace glm; 6 | 7 | class Brdf 8 | { 9 | public: 10 | // evaluation of the cosine-weighted BRDF 11 | // pdf is set to the PDF of sampling L 12 | virtual float eval(const vec3& V, const vec3& L, const float alpha, float& pdf) const = 0; 13 | 14 | // sampling 15 | virtual vec3 sample(const vec3& V, const float alpha, const float U1, const float U2) const = 0; 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # Makefiles 35 | Makefile 36 | *.make 37 | 38 | # Visual Studio 39 | *.sln 40 | *.vcxproj* 41 | *.VC.db 42 | .vs 43 | 44 | # Build 45 | bin 46 | obj 47 | out 48 | -------------------------------------------------------------------------------- /fit/genie.lua: -------------------------------------------------------------------------------- 1 | solution "fitLTC" 2 | configurations { "Debug", "Release" } 3 | 4 | project "fitLTC" 5 | kind "ConsoleApp" 6 | language "C++" 7 | files { "**.h", "**.cpp", "**.c" } 8 | 9 | includedirs { 10 | "../external/CImg", 11 | "../external/glm" 12 | } 13 | 14 | defines { 15 | "cimg_display=0" 16 | } 17 | 18 | configuration "Debug" 19 | targetdir "bin" 20 | defines { "DEBUG" } 21 | flags { "Symbols" } 22 | 23 | configuration "Release" 24 | targetdir "bin" 25 | defines { "NDEBUG" } 26 | flags { "Optimize" } 27 | -------------------------------------------------------------------------------- /webgl/css/ace_theme_tweaks.css: -------------------------------------------------------------------------------- 1 | .ace-clouds-midnight .ace_gutter { 2 | width: 50px; 3 | background: #191919; 4 | color: #333; 5 | overflow : hidden; 6 | } 7 | 8 | .ace-clouds-midnight .ace_support.ace_function { 9 | color:#B58900; 10 | } 11 | 12 | .ace-clouds-midnight .ace_constant.ace_language { 13 | color:#B58900; 14 | } 15 | 16 | .ace-clouds-midnight .ace_variable.ace_language { 17 | color:#1F74CF; 18 | } 19 | 20 | .ace_gutter-cell.ace_error { 21 | background-image: url("../images/error_icon.png"); 22 | } 23 | 24 | .ace_marker-layer .ace_error { 25 | position: absolute; 26 | z-index: 5; 27 | background: rgba(255, 0, 0, 0.5); 28 | } 29 | -------------------------------------------------------------------------------- /webgl/css/super_picker.css: -------------------------------------------------------------------------------- 1 | /* Default styling for SuperPicker controls */ 2 | 3 | .sp_picker { 4 | border: 0px solid #333; 5 | border-radius: 6px; 6 | min-height: 14px; 7 | clear: both; 8 | float: left; 9 | -webkit-user-select: none; 10 | -moz-user-select: none; 11 | } 12 | .sp_label { 13 | font-family: helvetica, arial, sans-serif; 14 | clear: both; 15 | color: #999; 16 | display: block; 17 | float: left; 18 | font-size: 12px; 19 | margin: 0 0 1px 0; 20 | -webkit-user-select: none; 21 | -moz-user-select: none; 22 | } 23 | .sp_label:hover { 24 | color: #FFF; 25 | } 26 | 27 | .sp_swatch { 28 | background: #ff0000; 29 | border-radius: 6px; 30 | width: 32px; 31 | height: 32px; 32 | float: left; 33 | position: relative; 34 | clear: left; 35 | } -------------------------------------------------------------------------------- /fit/results/ltc.h: -------------------------------------------------------------------------------- 1 | struct mat33 2 | { 3 | operator glm::mat3() const 4 | { 5 | return glm::mat3(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]); 6 | } 7 | 8 | double m[9]; 9 | }; 10 | 11 | 12 | #include "ltc.inc" 13 | 14 | #if 1 15 | mat3 M_GGX(const float cosTheta, const float alpha) 16 | { 17 | int t = std::max(0, std::min(size - 1, (int)floorf(sqrtf(1.0f - cosTheta) * size))); 18 | int a = std::max(0, std::min(size - 1, (int)floorf(sqrtf(alpha) * size))); 19 | 20 | return tabM[a + t*size]; 21 | } 22 | 23 | float magnitude_GGX(const float cosTheta, const float alpha) 24 | { 25 | int t = std::max(0, std::min(size - 1, (int)floorf(sqrtf(1.0f - cosTheta) * size))); 26 | int a = std::max(0, std::min(size - 1, (int)floorf(sqrtf(alpha) * size))); 27 | 28 | return tabMagnitude[a + t*size]; 29 | } 30 | #endif 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Overview 2 | This repository contains an (evolving) reference implementation for the following publications: 3 | * [Real-Time Polygonal-Light Shading with Linearly Transformed Cosines](https://eheitzresearch.wordpress.com/415-2/) (2016) 4 | * [Real-Time Area Lighting: a Journey From Research to Production](https://blog.selfshadow.com/publications/s2016-advances/) (2016) 5 | * [Linear-Light Shading with Linearly Transformed Cosines](https://blogs.unity3d.com/2017/04/17/linear-light-shading-with-linearly-transformed-cosines/) (2017) 6 | * [Real-Time Line- and Disk-Light Shading](https://blog.selfshadow.com/publications/s2017-shading-course/) (2017) 7 | 8 | ## Notes: 9 | * The Linearly Transformed Cosine (LTC) tables in this implementation differ in their parameterisation and storage compared to [the original paper](https://eheitzresearch.wordpress.com/415-2/). See fitting code and WebGL demos for details. 10 | 11 | ## WebGL Demos 12 | [Quad lights](http://blog.selfshadow.com/ltc/webgl/ltc_quad.html) 13 | [Line lights](http://blog.selfshadow.com/ltc/webgl/ltc_line.html) 14 | [Disk lights](http://blog.selfshadow.com/ltc/webgl/ltc_disk.html) 15 | -------------------------------------------------------------------------------- /webgl/js/jquery.mousewheel.min.js: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009 Brandon Aaron (http://brandonaaron.net) 2 | * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 3 | * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. 4 | * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. 5 | * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. 6 | * 7 | * Version: 3.0.2 8 | * 9 | * Requires: 1.2.2+ 10 | */ 11 | (function(c){var a=["DOMMouseScroll","mousewheel"];c.event.special.mousewheel={setup:function(){if(this.addEventListener){for(var d=a.length;d;){this.addEventListener(a[--d],b,false)}}else{this.onmousewheel=b}},teardown:function(){if(this.removeEventListener){for(var d=a.length;d;){this.removeEventListener(a[--d],b,false)}}else{this.onmousewheel=null}}};c.fn.extend({mousewheel:function(d){return d?this.bind("mousewheel",d):this.trigger("mousewheel")},unmousewheel:function(d){return this.unbind("mousewheel",d)}});function b(f){var d=[].slice.call(arguments,1),g=0,e=true;f=c.event.fix(f||window.event);f.type="mousewheel";if(f.wheelDelta){g=f.wheelDelta/120}if(f.detail){g=-f.detail/3}d.unshift(f,g);return c.event.handle.apply(this,d)}})(jQuery); -------------------------------------------------------------------------------- /webgl/css/sandbox.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #000000; 3 | margin: 0px; 4 | overflow: hidden; 5 | } 6 | 7 | 8 | #editor { 9 | width: 100%; 10 | height: 100%; 11 | margin: 0px; 12 | border: 2px solid #404040; 13 | border-radius: 6px 14 | } 15 | 16 | 17 | .canvas { 18 | border: 2px solid #404040; 19 | border-radius: 6px 20 | } 21 | 22 | 23 | #params { 24 | display: table; 25 | float: left; 26 | position: relative; 27 | padding: 8px 8px 0px; 28 | margin: 8px; 29 | background: #191919; 30 | border: 2px solid #404040; 31 | border-radius: 6px 32 | } 33 | 34 | 35 | #status { 36 | width: 484px; 37 | float: left; 38 | position: relative; 39 | padding: 8px; 40 | margin: 16px 0px 0px 0px; 41 | background: #191919; 42 | border: 2px solid #404040; 43 | border-radius: 6px 44 | } 45 | 46 | #status_text { 47 | font-family: helvetica, arial, sans-serif; 48 | color: #999; 49 | font-size: 12px 50 | } 51 | 52 | 53 | .checkbox_label { 54 | font-family: helvetica, arial, sans-serif; 55 | clear: both; 56 | color: #999; 57 | display: block; 58 | float: left; 59 | font-size: 12px; 60 | -webkit-user-select: none; 61 | -moz-user-select: none; 62 | } 63 | 64 | .checkbox_label:hover { 65 | color: #FFF; 66 | } -------------------------------------------------------------------------------- /fit/brdf_disneyDiffuse.h: -------------------------------------------------------------------------------- 1 | #ifndef _BRDF_DISNEY_DIFFUSE_ 2 | #define _BRDF_DISNEY_DIFFUSE_ 3 | 4 | #include "brdf.h" 5 | 6 | class BrdfDisneyDiffuse : public Brdf 7 | { 8 | public: 9 | 10 | virtual float eval(const vec3& V, const vec3& L, const float alpha, float& pdf) const 11 | { 12 | if (V.z <= 0 || L.z <= 0) 13 | { 14 | pdf = 0; 15 | return 0; 16 | } 17 | 18 | pdf = L.z / 3.14159f; 19 | 20 | float NdotV = V.z; 21 | float NdotL = L.z; 22 | float LdotH = dot(L, normalize(V + L)); 23 | float perceptualRoughness = sqrtf(alpha); 24 | float fd90 = 0.5f + 2 * LdotH*LdotH * perceptualRoughness; 25 | float lightScatter = (1 + (fd90 - 1) * powf(1 - NdotL, 5.0f)); 26 | float viewScatter = (1 + (fd90 - 1) * powf(1 - NdotV, 5.0f)); 27 | return lightScatter * viewScatter * L.z / 3.14159f; 28 | } 29 | 30 | virtual vec3 sample(const vec3& V, const float alpha, const float U1, const float U2) const 31 | { 32 | const float r = sqrtf(U1); 33 | const float phi = 2.0f*3.14159f * U2; 34 | const vec3 L = vec3(r*cosf(phi), r*sinf(phi), sqrtf(1.0f - r*r)); 35 | return L; 36 | } 37 | }; 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /webgl/css/jquery.ui.resizable.css: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery UI Resizable 1.8.13 3 | * 4 | * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 5 | * Dual licensed under the MIT or GPL Version 2 licenses. 6 | * http://jquery.org/license 7 | * 8 | * http://docs.jquery.com/UI/Resizable#theming 9 | */ 10 | .ui-resizable { position: relative;} 11 | .ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block; 12 | /* http://bugs.jqueryui.com/ticket/7233 13 | - Resizable: resizable handles fail to work in IE if transparent and content overlaps 14 | */ 15 | background-image:url(data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=); 16 | } 17 | .ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } 18 | .ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } 19 | .ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } 20 | .ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } 21 | .ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } 22 | .ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } 23 | .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } 24 | .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } 25 | .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;} -------------------------------------------------------------------------------- /fit/LTC.h: -------------------------------------------------------------------------------- 1 | #ifndef _LTC_ 2 | #define _LTC_ 3 | 4 | 5 | #include 6 | using namespace glm; 7 | 8 | #include 9 | using namespace std; 10 | 11 | struct LTC { 12 | 13 | // lobe magnitude 14 | float magnitude; 15 | 16 | // Average Schlick Fresnel term 17 | float fresnel; 18 | 19 | // parametric representation 20 | float m11, m22, m13; 21 | vec3 X, Y, Z; 22 | 23 | // matrix representation 24 | mat3 M; 25 | mat3 invM; 26 | float detM; 27 | 28 | LTC() 29 | { 30 | magnitude = 1; 31 | fresnel = 1; 32 | m11 = 1; 33 | m22 = 1; 34 | m13 = 0; 35 | X = vec3(1, 0, 0); 36 | Y = vec3(0, 1, 0); 37 | Z = vec3(0, 0, 1); 38 | update(); 39 | } 40 | 41 | void update() // compute matrix from parameters 42 | { 43 | M = mat3(X, Y, Z) * 44 | mat3(m11, 0, 0, 45 | 0, m22, 0, 46 | m13, 0, 1); 47 | invM = inverse(M); 48 | detM = abs(glm::determinant(M)); 49 | } 50 | 51 | float eval(const vec3& L) const 52 | { 53 | vec3 Loriginal = normalize(invM * L); 54 | vec3 L_ = M * Loriginal; 55 | 56 | float l = length(L_); 57 | float Jacobian = detM / (l*l*l); 58 | 59 | float D = 1.0f / 3.14159f * glm::max(0.0f, Loriginal.z); 60 | 61 | float res = magnitude * D / Jacobian; 62 | return res; 63 | } 64 | 65 | vec3 sample(const float U1, const float U2) const 66 | { 67 | const float theta = acosf(sqrtf(U1)); 68 | const float phi = 2.0f*3.14159f * U2; 69 | const vec3 L = normalize(M * vec3(sinf(theta)*cosf(phi), sinf(theta)*sinf(phi), cosf(theta))); 70 | return L; 71 | } 72 | }; 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017, Eric Heitz, Jonathan Dupuy, Stephen Hill and David Neubelt. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * If you use (or adapt) the source code in your own work, please include a 8 | reference to the paper: 9 | 10 | Real-Time Polygonal-Light Shading with Linearly Transformed Cosines. 11 | Eric Heitz, Jonathan Dupuy, Stephen Hill and David Neubelt. 12 | ACM Transactions on Graphics (Proceedings of ACM SIGGRAPH 2016) 35(4), 2016. 13 | Project page: https://eheitzresearch.wordpress.com/415-2/ 14 | 15 | * Redistributions of source code must retain the above copyright notice, this 16 | list of conditions and the following disclaimer. 17 | 18 | * Redistributions in binary form must reproduce the above copyright notice, 19 | this list of conditions and the following disclaimer in the documentation 20 | and/or other materials provided with the distribution. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | -------------------------------------------------------------------------------- /fit/brdf_beckmann.h: -------------------------------------------------------------------------------- 1 | #ifndef _BRDF_BECKMANN_ 2 | #define _BRDF_BECKMANN_ 3 | 4 | #include "brdf.h" 5 | 6 | class BrdfBeckmann : public Brdf 7 | { 8 | public: 9 | virtual float eval(const vec3& V, const vec3& L, const float alpha, float& pdf) const 10 | { 11 | if (V.z <= 0) 12 | { 13 | pdf = 0; 14 | return 0; 15 | } 16 | 17 | // masking 18 | const float LambdaV = lambda(alpha, V.z); 19 | 20 | // shadowing 21 | float G2; 22 | if (L.z <= 0.0f) 23 | G2 = 0; 24 | else 25 | { 26 | const float LambdaL = lambda(alpha, L.z); 27 | G2 = 1.0f/(1.0f + LambdaV + LambdaL); 28 | } 29 | 30 | // D 31 | const vec3 H = normalize(V + L); 32 | const float slopex = H.x/H.z; 33 | const float slopey = H.y/H.z; 34 | float D = expf(-(slopex*slopex + slopey*slopey)/(alpha*alpha)) / (3.14159f * alpha*alpha * H.z*H.z*H.z*H.z); 35 | 36 | pdf = fabsf(D * H.z / 4.0f / dot(V, H)); 37 | float res = D * G2 / 4.0f / V.z; 38 | 39 | return res; 40 | } 41 | 42 | virtual vec3 sample(const vec3& V, const float alpha, const float U1, const float U2) const 43 | { 44 | const float phi = 2.0f*3.14159f * U1; 45 | const float r = alpha*sqrtf(-logf(U2)); 46 | const vec3 N = normalize(vec3(r*cosf(phi), r*sinf(phi), 1.0f)); 47 | const vec3 L = -V + 2.0f * N * dot(N, V); 48 | return L; 49 | } 50 | 51 | private: 52 | float lambda(const float alpha, const float cosTheta) const 53 | { 54 | const float a = 1.0f / alpha / tanf(acosf(cosTheta)); 55 | return (cosTheta < 1.0f) ? (1.0f - 1.259f*a + 0.396f*a*a) / (3.535f*a + 2.181f*a*a) : 0.0f; 56 | } 57 | }; 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /fit/brdf_ggx.h: -------------------------------------------------------------------------------- 1 | #ifndef _BRDF_GGX_ 2 | #define _BRDF_GGX_ 3 | 4 | #include "brdf.h" 5 | 6 | class BrdfGGX : public Brdf 7 | { 8 | public: 9 | virtual float eval(const vec3& V, const vec3& L, const float alpha, float& pdf) const 10 | { 11 | if (V.z <= 0) 12 | { 13 | pdf = 0; 14 | return 0; 15 | } 16 | 17 | // masking 18 | const float LambdaV = lambda(alpha, V.z); 19 | 20 | // shadowing 21 | float G2; 22 | if (L.z <= 0.0f) 23 | G2 = 0; 24 | else 25 | { 26 | const float LambdaL = lambda(alpha, L.z); 27 | G2 = 1.0f/(1.0f + LambdaV + LambdaL); 28 | } 29 | 30 | // D 31 | const vec3 H = normalize(V + L); 32 | const float slopex = H.x/H.z; 33 | const float slopey = H.y/H.z; 34 | float D = 1.0f / (1.0f + (slopex*slopex + slopey*slopey)/alpha/alpha); 35 | D = D*D; 36 | D = D/(3.14159f * alpha*alpha * H.z*H.z*H.z*H.z); 37 | 38 | pdf = fabsf(D * H.z / 4.0f / dot(V, H)); 39 | float res = D * G2 / 4.0f / V.z; 40 | 41 | return res; 42 | } 43 | 44 | virtual vec3 sample(const vec3& V, const float alpha, const float U1, const float U2) const 45 | { 46 | const float phi = 2.0f*3.14159f * U1; 47 | const float r = alpha*sqrtf(U2/(1.0f - U2)); 48 | const vec3 N = normalize(vec3(r*cosf(phi), r*sinf(phi), 1.0f)); 49 | const vec3 L = -V + 2.0f * N * dot(N, V); 50 | return L; 51 | } 52 | 53 | private: 54 | float lambda(const float alpha, const float cosTheta) const 55 | { 56 | const float a = 1.0f / alpha / tanf(acosf(cosTheta)); 57 | return (cosTheta < 1.0f) ? 0.5f * (-1.0f + sqrtf(1.0f + 1.0f/a/a)) : 0.0f; 58 | } 59 | }; 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /fit/float_to_half.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Adapted from: 4 | // https://gist.github.com/rygorous/2156668 5 | 6 | union FP32 7 | { 8 | uint32_t u; 9 | float f; 10 | struct 11 | { 12 | uint32_t Mantissa : 23; 13 | uint32_t Exponent : 8; 14 | uint32_t Sign : 1; 15 | }; 16 | }; 17 | 18 | union FP16 19 | { 20 | uint16_t u; 21 | struct 22 | { 23 | uint32_t Mantissa : 10; 24 | uint32_t Exponent : 5; 25 | uint32_t Sign : 1; 26 | }; 27 | }; 28 | 29 | static uint16_t float_to_half_fast(float x) 30 | { 31 | FP32 f; 32 | f.f = x; 33 | 34 | FP16 o = { 0 }; 35 | 36 | // Based on ISPC reference code (with minor modifications) 37 | if (f.Exponent == 255) // Inf or NaN (all exponent bits set) 38 | { 39 | o.Exponent = 31; 40 | o.Mantissa = f.Mantissa ? 0x200 : 0; // NaN->qNaN and Inf->Inf 41 | } 42 | else // Normalized number 43 | { 44 | // Exponent unbias the single, then bias the halfp 45 | int newexp = f.Exponent - 127 + 15; 46 | if (newexp >= 31) // Overflow, return signed infinity 47 | o.Exponent = 31; 48 | else if (newexp <= 0) // Underflow 49 | { 50 | if ((14 - newexp) <= 24) // Mantissa might be non-zero 51 | { 52 | uint32_t mant = f.Mantissa | 0x800000; // Hidden 1 bit 53 | o.Mantissa = mant >> (14 - newexp); 54 | if ((mant >> (13 - newexp)) & 1) // Check for rounding 55 | o.u++; // Round, might overflow into exp bit, but this is OK 56 | } 57 | } 58 | else 59 | { 60 | o.Exponent = newexp; 61 | o.Mantissa = f.Mantissa >> 13; 62 | if (f.Mantissa & 0x1000) // Check for rounding 63 | o.u++; // Round, might overflow to inf, this is OK 64 | } 65 | } 66 | 67 | o.Sign = f.Sign; 68 | return o.u; 69 | } -------------------------------------------------------------------------------- /webgl/shaders/ltc/ltc_blit.fs: -------------------------------------------------------------------------------- 1 | 2 | uniform vec2 resolution; 3 | 4 | uniform sampler2D tex; 5 | 6 | vec3 rrt_odt_fit(vec3 v) 7 | { 8 | vec3 a = v*( v + 0.0245786) - 0.000090537; 9 | vec3 b = v*(0.983729*v + 0.4329510) + 0.238081; 10 | return a/b; 11 | } 12 | 13 | mat3 mat3_from_rows(vec3 c0, vec3 c1, vec3 c2) 14 | { 15 | mat3 m = mat3(c0, c1, c2); 16 | m = transpose(m); 17 | 18 | return m; 19 | } 20 | 21 | vec3 mul(mat3 m, vec3 v) 22 | { 23 | return m * v; 24 | } 25 | 26 | mat3 mul(mat3 m1, mat3 m2) 27 | { 28 | return m1 * m2; 29 | } 30 | 31 | float saturate(float v) 32 | { 33 | return clamp(v, 0.0, 1.0); 34 | } 35 | 36 | vec3 saturate(vec3 v) 37 | { 38 | return vec3(saturate(v.x), saturate(v.y), saturate(v.z)); 39 | } 40 | 41 | vec3 aces_fitted(vec3 color) 42 | { 43 | mat3 ACES_INPUT_MAT = mat3_from_rows( 44 | vec3( 0.59719, 0.35458, 0.04823), 45 | vec3( 0.07600, 0.90834, 0.01566), 46 | vec3( 0.02840, 0.13383, 0.83777)); 47 | 48 | mat3 ACES_OUTPUT_MAT = mat3_from_rows( 49 | vec3( 1.60475,-0.53108,-0.07367), 50 | vec3(-0.10208, 1.10813,-0.00605), 51 | vec3(-0.00327,-0.07276, 1.07602)); 52 | 53 | color = mul(ACES_INPUT_MAT, color); 54 | 55 | // Apply RRT and ODT 56 | color = rrt_odt_fit(color); 57 | 58 | color = mul(ACES_OUTPUT_MAT, color); 59 | 60 | // Clamp to [0, 1] 61 | color = saturate(color); 62 | 63 | return color; 64 | } 65 | 66 | vec3 PowVec3(vec3 v, float p) 67 | { 68 | return vec3(pow(v.x, p), pow(v.y, p), pow(v.z, p)); 69 | } 70 | 71 | const float gamma = 2.2; 72 | vec3 ToSRGB(vec3 v) { return PowVec3(v, 1.0/gamma); } 73 | 74 | out vec4 FragColor; 75 | 76 | void main() 77 | { 78 | vec2 pos = gl_FragCoord.xy/resolution; 79 | 80 | vec4 col = texture(tex, pos); 81 | 82 | // Rescale by number of samples 83 | col /= col.w; 84 | 85 | col.rgb = aces_fitted(col.rgb); 86 | col.rgb = ToSRGB(col.rgb); 87 | 88 | FragColor = vec4(col); 89 | } 90 | -------------------------------------------------------------------------------- /webgl/js/ace/theme-clouds_midnight.js: -------------------------------------------------------------------------------- 1 | define("ace/theme/clouds_midnight",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-clouds-midnight",t.cssText=".ace-clouds-midnight .ace_gutter {background: #232323;color: #929292}.ace-clouds-midnight .ace_print-margin {width: 1px;background: #232323}.ace-clouds-midnight{background-color: #191919;color: #929292}.ace-clouds-midnight .ace_cursor {color: #7DA5DC}.ace-clouds-midnight .ace_marker-layer .ace_selection {background: #000000}.ace-clouds-midnight.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #191919;border-radius: 2px}.ace-clouds-midnight .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-clouds-midnight .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #BFBFBF}.ace-clouds-midnight .ace_marker-layer .ace_active-line {background: rgba(215, 215, 215, 0.031)}.ace-clouds-midnight .ace_gutter-active-line {background-color: rgba(215, 215, 215, 0.031)}.ace-clouds-midnight .ace_marker-layer .ace_selected-word {border: 1px solid #000000}.ace-clouds-midnight .ace_invisible {color: #BFBFBF}.ace-clouds-midnight .ace_keyword,.ace-clouds-midnight .ace_meta,.ace-clouds-midnight .ace_support.ace_constant.ace_property-value {color: #927C5D}.ace-clouds-midnight .ace_keyword.ace_operator {color: #4B4B4B}.ace-clouds-midnight .ace_keyword.ace_other.ace_unit {color: #366F1A}.ace-clouds-midnight .ace_constant.ace_language {color: #39946A}.ace-clouds-midnight .ace_constant.ace_numeric {color: #46A609}.ace-clouds-midnight .ace_constant.ace_character.ace_entity {color: #A165AC}.ace-clouds-midnight .ace_invalid {color: #FFFFFF;background-color: #E92E2E}.ace-clouds-midnight .ace_fold {background-color: #927C5D;border-color: #929292}.ace-clouds-midnight .ace_storage,.ace-clouds-midnight .ace_support.ace_class,.ace-clouds-midnight .ace_support.ace_function,.ace-clouds-midnight .ace_support.ace_other,.ace-clouds-midnight .ace_support.ace_type {color: #E92E2E}.ace-clouds-midnight .ace_string {color: #5D90CD}.ace-clouds-midnight .ace_comment {color: #3C403B}.ace-clouds-midnight .ace_entity.ace_name.ace_tag,.ace-clouds-midnight .ace_entity.ace_other.ace_attribute-name {color: #606060}.ace-clouds-midnight .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYHB3d/8PAAOIAdULw8qMAAAAAElFTkSuQmCC) right repeat-y;}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) -------------------------------------------------------------------------------- /fit/dds.cpp: -------------------------------------------------------------------------------- 1 | #include "dds.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #pragma pack(push, 1) 8 | struct DDS_PIXELFORMAT 9 | { 10 | uint32_t dwSize; 11 | uint32_t dwFlags; 12 | uint32_t dwFourCC; 13 | uint32_t dwRGBBitCount; 14 | uint32_t dwRBitMask; 15 | uint32_t dwGBitMask; 16 | uint32_t dwBBitMask; 17 | uint32_t dwABitMask; 18 | }; 19 | 20 | struct DDS_HEADER 21 | { 22 | uint32_t dwSize; 23 | uint32_t dwFlags; 24 | uint32_t dwHeight; 25 | uint32_t dwWidth; 26 | uint32_t dwPitchOrLinearSize; 27 | uint32_t dwDepth; 28 | uint32_t dwMipMapCount; 29 | uint32_t dwReserved1[11]; 30 | DDS_PIXELFORMAT ddspf; 31 | uint32_t dwCaps; 32 | uint32_t dwCaps2; 33 | uint32_t dwCaps3; 34 | uint32_t dwCaps4; 35 | uint32_t dwReserved2; 36 | }; 37 | #pragma pack(pop) 38 | 39 | uint32_t const DDS_MAGIC = 0x20534444; // "DDS " 40 | uint32_t const DDS_HEADER_FLAGS_TEXTURE = 0x00001007; // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT 41 | uint32_t const DDS_HEADER_FLAGS_PITCH = 0x00000008; 42 | uint32_t const DDS_SURFACE_FLAGS_TEXTURE = 0x00001000; // DDSCAPS_TEXTURE 43 | uint32_t const DDS_PF_FLAGS_FOURCC = 0x00000004; 44 | uint32_t const DDS_RESOURCE_DIMENSION_TEXTURE2D = 3; 45 | 46 | DDS_PIXELFORMAT const DDSPF_RGBA16F = { sizeof(DDS_PIXELFORMAT), DDS_PF_FLAGS_FOURCC, 113, 0, 0, 0, 0, 0 }; 47 | DDS_PIXELFORMAT const DDSPF_RGBA32F = { sizeof(DDS_PIXELFORMAT), DDS_PF_FLAGS_FOURCC, 116, 0, 0, 0, 0, 0 }; 48 | 49 | DDS_PIXELFORMAT const* GetDDSPixelFormat(PixelFormat format) 50 | { 51 | switch (format) 52 | { 53 | case DDS_FORMAT_R16G16B16A16_FLOAT: return &DDSPF_RGBA16F; 54 | case DDS_FORMAT_R32G32B32A32_FLOAT: return &DDSPF_RGBA32F; 55 | } 56 | 57 | return nullptr; 58 | } 59 | 60 | bool SaveDDS(char const* path, PixelFormat format, unsigned texelSizeInBytes, unsigned width, unsigned height, void const* data) 61 | { 62 | FILE* f = fopen(path, "wb"); 63 | if (!f) 64 | return false; 65 | 66 | fwrite(&DDS_MAGIC, sizeof(DDS_MAGIC), 1, f); 67 | 68 | DDS_PIXELFORMAT const* ddspf = GetDDSPixelFormat(format); 69 | if (ddspf == nullptr) 70 | return false; 71 | 72 | DDS_HEADER hdr; 73 | memset(&hdr, 0, sizeof(hdr)); 74 | hdr.dwSize = sizeof(hdr); 75 | hdr.dwFlags = DDS_HEADER_FLAGS_TEXTURE | DDS_HEADER_FLAGS_PITCH; 76 | hdr.dwHeight = height; 77 | hdr.dwWidth = width; 78 | hdr.dwDepth = 1; 79 | hdr.dwMipMapCount = 1; 80 | hdr.dwPitchOrLinearSize = width*texelSizeInBytes; 81 | hdr.ddspf = *ddspf; 82 | hdr.dwCaps = DDS_SURFACE_FLAGS_TEXTURE; 83 | fwrite(&hdr, sizeof(hdr), 1, f); 84 | 85 | fwrite(data, width * height * texelSizeInBytes, 1, f); 86 | 87 | fclose(f); 88 | 89 | return true; 90 | } -------------------------------------------------------------------------------- /webgl/js/macton/macton-utils.js: -------------------------------------------------------------------------------- 1 | jQuery.getFiles = function( file_list, success ) 2 | { 3 | var results = []; 4 | var file_count = file_list.length; 5 | 6 | var hold_file = function( ndx, data ) 7 | { 8 | results[ndx] = data; 9 | file_count--; 10 | if ( file_count == 0 ) success( results ); 11 | } 12 | 13 | var get_file = function( ndx, url ) 14 | { 15 | $.get( url, function( data ) { hold_file( ndx, data ); } ); 16 | } 17 | 18 | for (var i=0;i") 36 | .addClass(this.options.picker_class) 37 | .css("webkitUserSelect", 'none'); 38 | 39 | if (this.options.label) { 40 | this.label = $("