mirror of
https://github.com/Ttanasart-pt/Pixel-Composer.git
synced 2024-12-27 07:26:33 +01:00
401 lines
13 KiB
GLSL
401 lines
13 KiB
GLSL
// Hosek-Wilkie Skylight Model
|
|
// By pajunen
|
|
// https://www.shadertoy.com/view/wslfD7
|
|
|
|
/*
|
|
This source is published under the following 3-clause BSD license.
|
|
|
|
Copyright (c) 2012 - 2013, Lukas Hosek and Alexander Wilkie
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
* Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
* None of the names of the contributors may be used to endorse or promote
|
|
products derived from this software without specific prior written
|
|
permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
varying vec2 v_vTexcoord;
|
|
varying vec4 v_vColour;
|
|
|
|
// Implementation of 2012 Hosek-Wilkie skylight model
|
|
// Ground albedo and turbidity are baked into the lookup tables
|
|
#define ALBEDO 1
|
|
#define TURBIDITY 3
|
|
|
|
#define PI 3.1415926535897932384626433832795
|
|
#define CIE_X 0
|
|
#define CIE_Y 1
|
|
#define CIE_Z 2
|
|
|
|
uniform vec2 dimension;
|
|
uniform int mapping;
|
|
|
|
uniform float albedo;
|
|
uniform float turbidity;
|
|
uniform vec2 sunPosition;
|
|
|
|
float kHosekCoeffsX[54];
|
|
float kHosekCoeffsY[54];
|
|
float kHosekCoeffsZ[54];
|
|
|
|
float kHosekRadX[6];
|
|
float kHosekRadY[6];
|
|
float kHosekRadZ[6];
|
|
|
|
void init() {
|
|
kHosekCoeffsX[ 0] = -1.171419;
|
|
kHosekCoeffsX[ 1] = -0.242975;
|
|
kHosekCoeffsX[ 2] = -8.991334;
|
|
kHosekCoeffsX[ 3] = 9.571216;
|
|
kHosekCoeffsX[ 4] = -0.027729;
|
|
kHosekCoeffsX[ 5] = 0.668826;
|
|
kHosekCoeffsX[ 6] = 0.076835;
|
|
kHosekCoeffsX[ 7] = 3.785611;
|
|
kHosekCoeffsX[ 8] = 0.634764;
|
|
kHosekCoeffsX[ 9] = -1.228554;
|
|
kHosekCoeffsX[10] = -0.291756;
|
|
kHosekCoeffsX[11] = 2.753986;
|
|
kHosekCoeffsX[12] = -2.491780;
|
|
kHosekCoeffsX[13] = -0.046634;
|
|
kHosekCoeffsX[14] = 0.311830;
|
|
kHosekCoeffsX[15] = 0.075465;
|
|
kHosekCoeffsX[16] = 4.463096;
|
|
kHosekCoeffsX[17] = 0.595507;
|
|
kHosekCoeffsX[18] = -1.093124;
|
|
kHosekCoeffsX[19] = -0.244777;
|
|
kHosekCoeffsX[20] = 0.909741;
|
|
kHosekCoeffsX[21] = 0.544830;
|
|
kHosekCoeffsX[22] = -0.295782;
|
|
kHosekCoeffsX[23] = 2.024167;
|
|
kHosekCoeffsX[24] = -0.000515;
|
|
kHosekCoeffsX[25] = -1.069081;
|
|
kHosekCoeffsX[26] = 0.936956;
|
|
kHosekCoeffsX[27] = -1.056994;
|
|
kHosekCoeffsX[28] = 0.015695;
|
|
kHosekCoeffsX[29] = -0.821749;
|
|
kHosekCoeffsX[30] = 1.870818;
|
|
kHosekCoeffsX[31] = 0.706193;
|
|
kHosekCoeffsX[32] = -1.483928;
|
|
kHosekCoeffsX[33] = 0.597821;
|
|
kHosekCoeffsX[34] = 6.864902;
|
|
kHosekCoeffsX[35] = 0.367333;
|
|
kHosekCoeffsX[36] = -1.054871;
|
|
kHosekCoeffsX[37] = -0.275813;
|
|
kHosekCoeffsX[38] = 2.712807;
|
|
kHosekCoeffsX[39] = -5.950110;
|
|
kHosekCoeffsX[40] = -6.554039;
|
|
kHosekCoeffsX[41] = 2.447523;
|
|
kHosekCoeffsX[42] = -0.189517;
|
|
kHosekCoeffsX[43] = -1.454292;
|
|
kHosekCoeffsX[44] = 0.913174;
|
|
kHosekCoeffsX[45] = -1.100218;
|
|
kHosekCoeffsX[46] = -0.174624;
|
|
kHosekCoeffsX[47] = 1.438505;
|
|
kHosekCoeffsX[48] = 11.154810;
|
|
kHosekCoeffsX[49] = -3.266076;
|
|
kHosekCoeffsX[50] = -0.883736;
|
|
kHosekCoeffsX[51] = 0.197010;
|
|
kHosekCoeffsX[52] = 1.991595;
|
|
kHosekCoeffsX[53] = 0.590782;
|
|
|
|
kHosekCoeffsY[ 0] = -1.185983;
|
|
kHosekCoeffsY[ 1] = -0.258118;
|
|
kHosekCoeffsY[ 2] = -7.761056;
|
|
kHosekCoeffsY[ 3] = 8.317053;
|
|
kHosekCoeffsY[ 4] = -0.033518;
|
|
kHosekCoeffsY[ 5] = 0.667667;
|
|
kHosekCoeffsY[ 6] = 0.059417;
|
|
kHosekCoeffsY[ 7] = 3.820727;
|
|
kHosekCoeffsY[ 8] = 0.632403;
|
|
kHosekCoeffsY[ 9] = -1.268591;
|
|
kHosekCoeffsY[10] = -0.339807;
|
|
kHosekCoeffsY[11] = 2.348503;
|
|
kHosekCoeffsY[12] = -2.023779;
|
|
kHosekCoeffsY[13] = -0.053685;
|
|
kHosekCoeffsY[14] = 0.108328;
|
|
kHosekCoeffsY[15] = 0.084029;
|
|
kHosekCoeffsY[16] = 3.910254;
|
|
kHosekCoeffsY[17] = 0.557748;
|
|
kHosekCoeffsY[18] = -1.071353;
|
|
kHosekCoeffsY[19] = -0.199246;
|
|
kHosekCoeffsY[20] = 0.787839;
|
|
kHosekCoeffsY[21] = 0.197470;
|
|
kHosekCoeffsY[22] = -0.303306;
|
|
kHosekCoeffsY[23] = 2.335298;
|
|
kHosekCoeffsY[24] = -0.082053;
|
|
kHosekCoeffsY[25] = 0.795445;
|
|
kHosekCoeffsY[26] = 0.997231;
|
|
kHosekCoeffsY[27] = -1.089513;
|
|
kHosekCoeffsY[28] = -0.031044;
|
|
kHosekCoeffsY[29] = -0.599575;
|
|
kHosekCoeffsY[30] = 2.330281;
|
|
kHosekCoeffsY[31] = 0.658194;
|
|
kHosekCoeffsY[32] = -1.821467;
|
|
kHosekCoeffsY[33] = 0.667997;
|
|
kHosekCoeffsY[34] = 5.090195;
|
|
kHosekCoeffsY[35] = 0.312516;
|
|
kHosekCoeffsY[36] = -1.040214;
|
|
kHosekCoeffsY[37] = -0.257093;
|
|
kHosekCoeffsY[38] = 2.660489;
|
|
kHosekCoeffsY[39] = -6.506045;
|
|
kHosekCoeffsY[40] = -7.053586;
|
|
kHosekCoeffsY[41] = 2.763153;
|
|
kHosekCoeffsY[42] = -0.243363;
|
|
kHosekCoeffsY[43] = -0.764818;
|
|
kHosekCoeffsY[44] = 0.945294;
|
|
kHosekCoeffsY[45] = -1.116052;
|
|
kHosekCoeffsY[46] = -0.183199;
|
|
kHosekCoeffsY[47] = 1.457694;
|
|
kHosekCoeffsY[48] = 11.636080;
|
|
kHosekCoeffsY[49] = -3.216426;
|
|
kHosekCoeffsY[50] = -1.045594;
|
|
kHosekCoeffsY[51] = 0.228500;
|
|
kHosekCoeffsY[52] = 1.817407;
|
|
kHosekCoeffsY[53] = 0.581040;
|
|
|
|
kHosekCoeffsZ[ 0] = -1.354183;
|
|
kHosekCoeffsZ[ 1] = -0.513062;
|
|
kHosekCoeffsZ[ 2] = -42.192680;
|
|
kHosekCoeffsZ[ 3] = 42.717720;
|
|
kHosekCoeffsZ[ 4] = -0.005365;
|
|
kHosekCoeffsZ[ 5] = 0.413674;
|
|
kHosekCoeffsZ[ 6] = 0.012352;
|
|
kHosekCoeffsZ[ 7] = 2.520122;
|
|
kHosekCoeffsZ[ 8] = 0.518727;
|
|
kHosekCoeffsZ[ 9] = -1.741434;
|
|
kHosekCoeffsZ[10] = -0.958976;
|
|
kHosekCoeffsZ[11] = -8.230339;
|
|
kHosekCoeffsZ[12] = 9.296799;
|
|
kHosekCoeffsZ[13] = -0.009600;
|
|
kHosekCoeffsZ[14] = 0.499497;
|
|
kHosekCoeffsZ[15] = 0.029555;
|
|
kHosekCoeffsZ[16] = 0.366710;
|
|
kHosekCoeffsZ[17] = 0.352700;
|
|
kHosekCoeffsZ[18] = -0.691735;
|
|
kHosekCoeffsZ[19] = 0.215489;
|
|
kHosekCoeffsZ[20] = -0.876026;
|
|
kHosekCoeffsZ[21] = 0.233412;
|
|
kHosekCoeffsZ[22] = -0.019096;
|
|
kHosekCoeffsZ[23] = 0.474803;
|
|
kHosekCoeffsZ[24] = -0.113851;
|
|
kHosekCoeffsZ[25] = 6.515360;
|
|
kHosekCoeffsZ[26] = 1.225097;
|
|
kHosekCoeffsZ[27] = -1.293189;
|
|
kHosekCoeffsZ[28] = -0.421870;
|
|
kHosekCoeffsZ[29] = 1.620952;
|
|
kHosekCoeffsZ[30] = -0.785860;
|
|
kHosekCoeffsZ[31] = -0.037694;
|
|
kHosekCoeffsZ[32] = 0.663679;
|
|
kHosekCoeffsZ[33] = 0.336494;
|
|
kHosekCoeffsZ[34] = -0.534102;
|
|
kHosekCoeffsZ[35] = 0.212835;
|
|
kHosekCoeffsZ[36] = -0.973552;
|
|
kHosekCoeffsZ[37] = -0.132549;
|
|
kHosekCoeffsZ[38] = 1.007517;
|
|
kHosekCoeffsZ[39] = 0.259826;
|
|
kHosekCoeffsZ[40] = 0.067622;
|
|
kHosekCoeffsZ[41] = 0.001421;
|
|
kHosekCoeffsZ[42] = -0.069160;
|
|
kHosekCoeffsZ[43] = 3.185897;
|
|
kHosekCoeffsZ[44] = 0.864196;
|
|
kHosekCoeffsZ[45] = -1.094800;
|
|
kHosekCoeffsZ[46] = -0.196206;
|
|
kHosekCoeffsZ[47] = 0.575559;
|
|
kHosekCoeffsZ[48] = 0.290626;
|
|
kHosekCoeffsZ[49] = 0.262575;
|
|
kHosekCoeffsZ[50] = 0.764405;
|
|
kHosekCoeffsZ[51] = 0.134749;
|
|
kHosekCoeffsZ[52] = 2.677126;
|
|
kHosekCoeffsZ[53] = 0.646546;
|
|
|
|
kHosekRadX[0] = 1.468395;
|
|
kHosekRadX[1] = 2.211970;
|
|
kHosekRadX[2] = -2.845869;
|
|
kHosekRadX[3] = 20.750270;
|
|
kHosekRadX[4] = 15.248220;
|
|
kHosekRadX[5] = 19.376220;
|
|
|
|
kHosekRadY[0] = 1.516536;
|
|
kHosekRadY[1] = 2.438729;
|
|
kHosekRadY[2] = -3.624121;
|
|
kHosekRadY[3] = 22.986210;
|
|
kHosekRadY[4] = 15.997820;
|
|
kHosekRadY[5] = 20.700270;
|
|
|
|
kHosekRadZ[0] = 1.234428;
|
|
kHosekRadZ[1] = 2.289628;
|
|
kHosekRadZ[2] = -3.404699;
|
|
kHosekRadZ[3] = 14.994360;
|
|
kHosekRadZ[4] = 34.683900;
|
|
kHosekRadZ[5] = 30.848420;
|
|
}
|
|
|
|
float sample_coeff(int channel, int albedo, int turbidity, int quintic_coeff, int coeff) {
|
|
// int index = 540 * albedo + 54 * turbidity + 9 * quintic_coeff + coeff;
|
|
int index = 9 * quintic_coeff + coeff;
|
|
if (channel == CIE_X) return kHosekCoeffsX[index];
|
|
if (channel == CIE_Y) return kHosekCoeffsY[index];
|
|
if (channel == CIE_Z) return kHosekCoeffsZ[index];
|
|
return 0.;
|
|
}
|
|
|
|
float sample_radiance(int channel, int albedo, int turbidity, int quintic_coeff) {
|
|
//int index = 60 * albedo + 6 * turbidity + quintic_coeff;
|
|
int index = quintic_coeff;
|
|
if (channel == CIE_X) return kHosekRadX[index];
|
|
if (channel == CIE_Y) return kHosekRadY[index];
|
|
if (channel == CIE_Z) return kHosekRadZ[index];
|
|
return 0.;
|
|
}
|
|
|
|
float eval_quintic_bezier(in float[6] control_points, float t) {
|
|
float t2 = t * t;
|
|
float t3 = t2 * t;
|
|
float t4 = t3 * t;
|
|
float t5 = t4 * t;
|
|
|
|
float t_inv = 1.0 - t;
|
|
float t_inv2 = t_inv * t_inv;
|
|
float t_inv3 = t_inv2 * t_inv;
|
|
float t_inv4 = t_inv3 * t_inv;
|
|
float t_inv5 = t_inv4 * t_inv;
|
|
|
|
return (
|
|
control_points[0] * t_inv5 +
|
|
control_points[1] * 5.0 * t * t_inv4 +
|
|
control_points[2] * 10.0 * t2 * t_inv3 +
|
|
control_points[3] * 10.0 * t3 * t_inv2 +
|
|
control_points[4] * 5.0 * t4 * t_inv +
|
|
control_points[5] * t5
|
|
);
|
|
}
|
|
|
|
float transform_sun_zenith(float sun_zenith) {
|
|
float elevation = PI / 2.0 - sun_zenith;
|
|
return pow(elevation / (PI / 2.0), 0.333333);
|
|
}
|
|
|
|
void get_control_points(int channel, int albedo, int turbidity, int coeff, out float[6] control_points) {
|
|
for (int i = 0; i < 6; ++i) control_points[i] = sample_coeff(channel, albedo, turbidity, i, coeff);
|
|
}
|
|
|
|
void get_control_points_radiance(int channel, int albedo, int turbidity, out float[6] control_points) {
|
|
for (int i = 0; i < 6; ++i) control_points[i] = sample_radiance(channel, albedo, turbidity, i);
|
|
}
|
|
|
|
void get_coeffs(int channel, int albedo, int turbidity, float sun_zenith, out float[9] coeffs) {
|
|
float t = transform_sun_zenith(sun_zenith);
|
|
for (int i = 0; i < 9; ++i) {
|
|
float control_points[6];
|
|
get_control_points(channel, albedo, turbidity, i, control_points);
|
|
coeffs[i] = eval_quintic_bezier(control_points, t);
|
|
}
|
|
}
|
|
|
|
vec3 mean_spectral_radiance(int albedo, int turbidity, float sun_zenith) {
|
|
vec3 spectral_radiance;
|
|
for (int i = 0; i < 3; ++i) {
|
|
float control_points[6];
|
|
get_control_points_radiance(i, albedo, turbidity, control_points);
|
|
float t = transform_sun_zenith(sun_zenith);
|
|
spectral_radiance[i] = eval_quintic_bezier(control_points, t);
|
|
}
|
|
return spectral_radiance;
|
|
}
|
|
|
|
float F(float theta, float gamma, in float[9] coeffs) {
|
|
float A = coeffs[0];
|
|
float B = coeffs[1];
|
|
float C = coeffs[2];
|
|
float D = coeffs[3];
|
|
float E = coeffs[4];
|
|
float F = coeffs[5];
|
|
float G = coeffs[6];
|
|
float H = coeffs[8];
|
|
float I = coeffs[7];
|
|
float chi = (1.0 + pow(cos(gamma), 2.0)) / pow(1.0 + H*H - 2.0 * H * cos(gamma), 1.5);
|
|
|
|
return (
|
|
(1.0 + A * exp(B / (cos(theta) + 0.01))) *
|
|
(C + D * exp(E * gamma) + F * pow(cos(gamma), 2.0) + G * chi + I * sqrt(cos(theta)))
|
|
);
|
|
}
|
|
|
|
vec3 spectral_radiance(float theta, float gamma, int albedo, int turbidity, float sun_zenith) {
|
|
vec3 XYZ;
|
|
for (int i = 0; i < 3; ++i) {
|
|
float coeffs[9];
|
|
get_coeffs(i, albedo, turbidity, sun_zenith, coeffs);
|
|
XYZ[i] = F(theta, gamma, coeffs);
|
|
}
|
|
return XYZ;
|
|
}
|
|
|
|
// Returns angle between two directions defined by zentih and azimuth angles
|
|
float angle(float z1, float a1, float z2, float a2) {
|
|
return acos(
|
|
sin(z1) * cos(a1) * sin(z2) * cos(a2) +
|
|
sin(z1) * sin(a1) * sin(z2) * sin(a2) +
|
|
cos(z1) * cos(z2));
|
|
}
|
|
|
|
vec3 sample_sky(float view_zenith, float view_azimuth, float sun_zenith, float sun_azimuth) {
|
|
float gamma = angle(view_zenith, view_azimuth, sun_zenith, sun_azimuth);
|
|
float theta = view_zenith;
|
|
return spectral_radiance(theta, gamma, int(albedo), int(turbidity), sun_zenith) * mean_spectral_radiance(int(albedo), int(turbidity), sun_zenith);
|
|
}
|
|
|
|
// CIE-XYZ to linear RGB
|
|
vec3 XYZ_to_RGB(vec3 XYZ) {
|
|
mat3 XYZ_to_linear = mat3(
|
|
3.24096994, -0.96924364, 0.55630080,
|
|
-1.53738318, 1.8759675, -0.20397696,
|
|
-0.49861076, 0.04155506, 1.05697151
|
|
);
|
|
return XYZ_to_linear * XYZ;
|
|
}
|
|
|
|
// Ad-hoc tonemapping, better approach should be used
|
|
vec3 tonemap(vec3 color, float exposure) {
|
|
return vec3(2.0) / (vec3(1.0) + exp(-exposure * color)) - vec3(1.0);
|
|
}
|
|
|
|
void main() {
|
|
init();
|
|
|
|
vec2 uv = v_vTexcoord;
|
|
vec2 sun = sunPosition / dimension;
|
|
|
|
uv.y = 1. - uv.y;
|
|
sun.y = 1. - sun.y;
|
|
|
|
float sun_zenith = PI - sun.y * PI;
|
|
float sun_azimuth = PI + 2. * PI * sun.x;
|
|
|
|
float view_zenith = PI - uv.y * PI;
|
|
float view_azimuth = PI + 2. * PI * uv.x;
|
|
|
|
vec3 XYZ = sample_sky(view_zenith, view_azimuth, sun_zenith, sun_azimuth);
|
|
vec3 RGB = XYZ_to_RGB(XYZ);
|
|
vec3 col = tonemap(RGB, 0.1);
|
|
|
|
gl_FragColor = vec4(col, 1.0);
|
|
}
|