New Sky generator node.

This commit is contained in:
Tanasart 2024-10-20 16:47:29 +07:00
parent 68035d8ec7
commit 1790d564ca
14 changed files with 907 additions and 30 deletions

View File

@ -1744,6 +1744,8 @@
{"name":"sh_shape_map_polygon","order":15,"path":"shaders/sh_shape_map_polygon/sh_shape_map_polygon.yy",},
{"name":"sh_simplex","order":16,"path":"shaders/sh_simplex/sh_simplex.yy",},
{"name":"sh_skew","order":6,"path":"shaders/sh_skew/sh_skew.yy",},
{"name":"sh_sky_hosek","order":2,"path":"shaders/sh_sky_hosek/sh_sky_hosek.yy",},
{"name":"sh_sky_scattering","order":1,"path":"shaders/sh_sky_scattering/sh_sky_scattering.yy",},
{"name":"sh_slice_spritesheet_empty_scan","order":6,"path":"shaders/sh_slice_spritesheet_empty_scan/sh_slice_spritesheet_empty_scan.yy",},
{"name":"sh_smear","order":13,"path":"shaders/sh_smear/sh_smear.yy",},
{"name":"sh_solid","order":5,"path":"shaders/sh_solid/sh_solid.yy",},
@ -2504,6 +2506,7 @@
{"name":"s_node_shard","order":33,"path":"sprites/s_node_shard/s_node_shard.yy",},
{"name":"s_node_shell_excecute","order":33,"path":"sprites/s_node_shell_excecute/s_node_shell_excecute.yy",},
{"name":"s_node_skew","order":11,"path":"sprites/s_node_skew/s_node_skew.yy",},
{"name":"s_node_sky","order":57,"path":"sprites/s_node_sky/s_node_sky.yy",},
{"name":"s_node_slider","order":4,"path":"sprites/s_node_slider/s_node_slider.yy",},
{"name":"s_node_smear","order":8,"path":"sprites/s_node_smear/s_node_smear.yy",},
{"name":"s_node_smokeSim_add_collider","order":6,"path":"sprites/s_node_smokeSim_add_collider/s_node_smokeSim_add_collider.yy",},

View File

@ -2440,7 +2440,9 @@
{"id":{"name":"sh_shape","path":"shaders/sh_shape/sh_shape.yy",},},
{"id":{"name":"sh_simplex","path":"shaders/sh_simplex/sh_simplex.yy",},},
{"id":{"name":"sh_skew","path":"shaders/sh_skew/sh_skew.yy",},},
{"id":{"name":"sh_sky_hosek","path":"shaders/sh_sky_hosek/sh_sky_hosek.yy",},},
{"id":{"name":"sh_sky_preetham","path":"shaders/sh_sky_preetham/sh_sky_preetham.yy",},},
{"id":{"name":"sh_sky_scattering","path":"shaders/sh_sky_scattering/sh_sky_scattering.yy",},},
{"id":{"name":"sh_slice_spritesheet_empty_scan","path":"shaders/sh_slice_spritesheet_empty_scan/sh_slice_spritesheet_empty_scan.yy",},},
{"id":{"name":"sh_smear","path":"shaders/sh_smear/sh_smear.yy",},},
{"id":{"name":"sh_solid","path":"shaders/sh_solid/sh_solid.yy",},},
@ -3247,6 +3249,7 @@
{"id":{"name":"s_node_shard","path":"sprites/s_node_shard/s_node_shard.yy",},},
{"id":{"name":"s_node_shell_excecute","path":"sprites/s_node_shell_excecute/s_node_shell_excecute.yy",},},
{"id":{"name":"s_node_skew","path":"sprites/s_node_skew/s_node_skew.yy",},},
{"id":{"name":"s_node_sky","path":"sprites/s_node_sky/s_node_sky.yy",},},
{"id":{"name":"s_node_slider","path":"sprites/s_node_slider/s_node_slider.yy",},},
{"id":{"name":"s_node_smear","path":"sprites/s_node_smear/s_node_smear.yy",},},
{"id":{"name":"s_node_smokeSim_add_collider","path":"sprites/s_node_smokeSim_add_collider/s_node_smokeSim_add_collider.yy",},},

View File

@ -752,7 +752,7 @@ function __initNodes() {
addNodeObject(generator, "Solid", s_node_solid, "Node_Solid", [1, Node_Solid],, "Create image of a single color.");
addNodeObject(generator, "Draw Gradient", s_node_gradient, "Node_Gradient", [1, Node_Gradient],, "Create image from gradient.");
addNodeObject(generator, "Draw 4 Points Gradient", s_node_gradient_4points, "Node_Gradient_Points", [1, Node_Gradient_Points],, "Create image from 4 color points.");
/**/ addNodeObject(generator, "Sky", s_node_gradient_4points, "Node_Sky", [1, Node_Sky],, "Generate sky texture using different model.");
addNodeObject(generator, "Sky", s_node_sky, "Node_Sky", [1, Node_Sky],, "Generate sky texture using different model.");
ds_list_add(generator, "Drawer");
addNodeObject(generator, "Draw Line", s_node_line, "Node_Line", [1, Node_Line],, "Draw line on an image. Connect path data to it to draw line from path.");

View File

@ -3,25 +3,32 @@ function Node_Sky(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) const
newInput(0, nodeValue_Dimension(self));
newInput(1, nodeValue_Enum_Scroll("Model", self, 0, [ "Preetham" ]));
newInput(1, nodeValue_Vec2("Offset", self, [ 0, 0 ]));
newInput(2, nodeValue_Float("Turbidity", self, 2));
newInput(2, nodeValue_Vec2("Scale", self, [ 1, 1 ]));
newInput(3, nodeValue_Float("Azimuth", self, 0))
.setDisplay(VALUE_DISPLAY.slider, { range: [ -180, 180, 1 ] });
newInput(3, nodeValue_Enum_Scroll("Model", self, 0, [ "Preetham", "Basic scattering", "Hosek" ]));
newInput(4, nodeValue_Float("Inclination", self, 0))
.setDisplay(VALUE_DISPLAY.slider, { range: [ -180, 180, 1 ] });
newInput(4, nodeValue_Float("Turbidity", self, 2));
newInput(5, nodeValue_Vec2("Scale", self, [ 1, 1 ]));
newInput(5, nodeValue_Vec2("Sun", self, [ .5, .5 ]))
.setUnitRef(function(index) /*=>*/ {return getDimension(index)}, VALUE_UNIT.reference);
newInput(6, nodeValue_Vec2("Offset", self, [ 0, 0 ]));
newInput(6, nodeValue_Float("Sun radius", self, 500));
newInput(7, nodeValue_Float("Sun radiance", self, 20));
newInput(8, nodeValue_Float("Albedo", self, 1));
newInput(9, nodeValue_Enum_Scroll("Coordinate", self, 0, [ "Rectangular", "Polar" ]));
newOutput(0, nodeValue_Output("Surface out", self, VALUE_TYPE.surface, noone));
input_display_list = [ 0,
["Transform", false], 6, 5,
["Sky", false], 1, 2, 3, 4,
// ["Transform", false], 1, 2,
["Sky", false], 3, 4, 8,
["Sun", false], 5, 6, 7,
//["Render", false], 9,
];
attribute_surface_depth();
@ -29,30 +36,73 @@ function Node_Sky(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) const
static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
var _hov = false;
var hv = inputs[6].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); _hov |= hv;
var hv = inputs[5].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); _hov |= hv;
return _hov;
}
static processData = function(_outSurf, _data, _output_index, _array_index) {
var _dim = _data[0];
var _mod = _data[1];
var _tur = _data[2];
var _azi = _data[3];
var _inc = _data[4];
var _sca = _data[5];
var _pos = _data[6];
var _pos = _data[1];
var _sca = _data[2];
var _mod = _data[3];
var _tur = _data[4];
var _sun = _data[5];
var _sunRad = _data[6];
var _sunRdd = _data[7];
var _alb = _data[8];
var _map = _data[9];
if(_mod == 0) {
inputs[4].setVisible( true);
inputs[6].setVisible(false);
inputs[7].setVisible(false);
inputs[8].setVisible(false);
surface_set_shader(_outSurf, sh_sky_preetham);
DRAW_CLEAR
shader_set_2("dimension", _dim);
shader_set_2("position", _pos);
shader_set_2("scale", _sca);
shader_set_2("sunPosition", _sun);
shader_set_f("turbidity", _tur);
shader_set_f("azimuth", degtorad(_azi));
shader_set_f("inclination", degtorad(_inc));
shader_set_i("mapping", _map);
draw_empty();
surface_reset_shader();
} else if(_mod == 1) {
inputs[4].setVisible(false);
inputs[6].setVisible( true);
inputs[7].setVisible( true);
inputs[8].setVisible(false);
surface_set_shader(_outSurf, sh_sky_scattering);
DRAW_CLEAR
shader_set_2("dimension", _dim);
shader_set_2("sunPosition", _sun);
shader_set_f("sunRadius", _sunRad);
shader_set_f("sunRadiance", _sunRdd);
shader_set_i("mapping", _map);
draw_empty();
surface_reset_shader();
} else if(_mod == 2) {
inputs[4].setVisible(false);
inputs[6].setVisible(false);
inputs[7].setVisible(false);
inputs[8].setVisible(false);
surface_set_shader(_outSurf, sh_sky_hosek);
DRAW_CLEAR
shader_set_2("dimension", _dim);
shader_set_2("sunPosition", _sun);
shader_set_f("turbidity", 3);
shader_set_f("albedo", 1);
shader_set_i("mapping", _map);
draw_empty();
surface_reset_shader();

View File

@ -0,0 +1,401 @@
// 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);
}

View File

@ -0,0 +1,19 @@
//
// Simple passthrough vertex shader
//
attribute vec3 in_Position; // (x,y,z)
//attribute vec3 in_Normal; // (x,y,z) unused in this shader.
attribute vec4 in_Colour; // (r,g,b,a)
attribute vec2 in_TextureCoord; // (u,v)
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
void main()
{
vec4 object_space_pos = vec4( in_Position.x, in_Position.y, in_Position.z, 1.0);
gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * object_space_pos;
v_vColour = in_Colour;
v_vTexcoord = in_TextureCoord;
}

View File

@ -0,0 +1,12 @@
{
"$GMShader":"",
"%Name":"sh_sky_hosek",
"name":"sh_sky_hosek",
"parent":{
"name":"sky model",
"path":"folders/shader/generator/sky model.yy",
},
"resourceType":"GMShader",
"resourceVersion":"2.0",
"type":1,
}

View File

@ -1,15 +1,17 @@
// Preetham Sky
// By Althar
// https://www.shadertoy.com/view/llSSDR
#define PI 3.14159265359
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
uniform vec2 dimension;
uniform vec2 position;
uniform vec2 scale;
uniform int mapping;
uniform float turbidity;
uniform float azimuth;
uniform float inclination;
uniform vec2 sunPosition;
float saturatedDot( in vec3 a, in vec3 b ) {
return max( dot( a, b ), 0.0 );
@ -44,7 +46,6 @@ vec3 XYZToRGB( in vec3 XYZ ) {
return XYZ * M;
}
vec3 YxyToRGB( in vec3 Yxy ) {
vec3 XYZ = YxyToXYZ( Yxy );
vec3 RGB = XYZToRGB( XYZ );
@ -105,9 +106,30 @@ vec3 calculateSkyLuminanceRGB( in vec3 s, in vec3 e, in float t ) {
void main() {
vec2 uv = v_vTexcoord;
uv = (uv - position / dimension);
uv.y = 1. - uv.y;
uv /= scale;
vec2 sun = sunPosition / dimension;
// if(mapping == 0) {
uv.y = 1. - uv.y;
sun.y = 1. - sun.y;
// } else if(mapping == 1) {
// float sun_angle = atan(sun.x, sun.y);
// float sun_distance = clamp(length(sun) * PI, 0.0, PI / 2.0 - 0.1);
// float uv_angle = atan(uv.x,uv.y);
// float uv_distance = length(uv) * PI;
// if (uv_distance > PI / 2.0) {
// gl_FragColor = vec4(vec3(0.0), 1.0);
// return;
// }
// uv = vec2(uv_angle, uv_distance);
// sun = vec2(sun_angle, sun_distance);
// }
float azimuth = PI + 2. * PI * sun.x;
float inclination = PI - sun.y * PI;
vec3 sunDir = normalize( vec3( sin( inclination ) * cos( azimuth ), cos( inclination ), sin( inclination ) * sin(azimuth) ) );
vec3 viewDir = -computeSphericalCoordinates( uv ).xzy;

View File

@ -0,0 +1,246 @@
// Atmospheric Scattering
// Author: cubi
// https://www.shadertoy.com/view/XlBfRD
// License (MIT) Copyright (C) 2017-2018 Rui. All rights reserved.
#define PI 3.1415926535
#define PI_2 (3.1415926535 * 2.0)
#define EPSILON 1e-5
#define SAMPLES_NUMS 16
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
uniform vec2 dimension;
uniform int mapping;
uniform vec2 sunPosition;
uniform float sunRadius;
uniform float sunRadiance;
/*uniform*/ float mieG;
/*uniform*/ float mieHeight;
/*uniform*/ float rayleighHeight;
vec3 waveLambdaMie;
vec3 waveLambdaOzone;
vec3 waveLambdaRayleigh;
float earthRadius;
float earthAtmTopRadius;
vec3 earthCenter;
float saturate(float x) { return clamp(x, 0.0, 1.0); }
vec3 ComputeSphereNormal(vec2 coord, float phiStart, float phiLength, float thetaStart, float thetaLength) {
vec3 normal;
normal.x = -sin(thetaStart + coord.y * thetaLength) * sin(phiStart + coord.x * phiLength);
normal.y = -cos(thetaStart + coord.y * thetaLength);
normal.z = -sin(thetaStart + coord.y * thetaLength) * cos(phiStart + coord.x * phiLength);
return normalize(normal);
}
vec2 ComputeRaySphereIntersection(vec3 position, vec3 dir, vec3 center, float radius) {
vec3 origin = position - center;
float B = dot(origin, dir);
float C = dot(origin, origin) - radius * radius;
float D = B * B - C;
vec2 minimaxIntersections;
if (D < 0.0) {
minimaxIntersections = vec2(-1.0, -1.0);
} else {
D = sqrt(D);
minimaxIntersections = vec2(-B - D, -B + D);
}
return minimaxIntersections;
}
vec3 ComputeWaveLambdaRayleigh(vec3 lambda) {
float n = 1.0003;
float N = 2.545E25;
float pn = 0.035;
float n2 = n * n;
float pi3 = PI * PI * PI;
float rayleighConst = (8.0 * pi3 * pow(n2 - 1.0, 2.0)) / (3.0 * N) * ((6.0 + 3.0 * pn) / (6.0 - 7.0 * pn));
return rayleighConst / (lambda * lambda * lambda * lambda);
}
float ComputePhaseMie(float theta, float g) {
float g2 = g * g;
return (1.0 - g2) / pow(1.0 + g2 - 2.0 * g * saturate(theta), 1.5) / (4.0 * PI);
}
float ComputePhaseRayleigh(float theta) {
float theta2 = theta * theta;
return (theta2 * 0.75 + 0.75) / (4.0 * PI);
}
float ChapmanApproximation(float X, float h, float cosZenith) {
float c = sqrt(X + h);
float c_exp_h = c * exp(-h);
if (cosZenith >= 0.0) {
return c_exp_h / (c * cosZenith + 1.0);
} else {
float x0 = sqrt(1.0 - cosZenith * cosZenith) * (X + h);
float c0 = sqrt(x0);
return 2.0 * c0 * exp(X - x0) - c_exp_h / (1.0 - c * cosZenith);
}
}
float GetOpticalDepthSchueler(float h, float H, float earthRadius, float cosZenith) {
return H * ChapmanApproximation(earthRadius / H, h / H, cosZenith);
}
vec3 GetTransmittance(vec3 L, vec3 V) {
float ch = GetOpticalDepthSchueler(L.y, rayleighHeight, earthRadius, V.y);
return exp(-(waveLambdaMie + waveLambdaRayleigh) * ch);
}
vec2 ComputeOpticalDepth(vec3 samplePoint, vec3 V, vec3 L, float neg) {
float rl = length(samplePoint);
float h = rl - earthRadius;
vec3 r = samplePoint / rl;
float cos_chi_sun = dot(r, L);
float cos_chi_ray = dot(r, V * neg);
float opticalDepthSun = GetOpticalDepthSchueler(h, rayleighHeight, earthRadius, cos_chi_sun);
float opticalDepthCamera = GetOpticalDepthSchueler(h, rayleighHeight, earthRadius, cos_chi_ray) * neg;
return vec2(opticalDepthSun, opticalDepthCamera);
}
void AerialPerspective(vec3 start, vec3 end, vec3 V, vec3 L, bool infinite, out vec3 transmittance, out vec3 insctrMie, out vec3 insctrRayleigh) {
float inf_neg = infinite ? 1.0 : -1.0;
vec3 sampleStep = (end - start) / float(SAMPLES_NUMS);
vec3 samplePoint = end - sampleStep;
vec3 sampleLambda = waveLambdaMie + waveLambdaRayleigh + waveLambdaOzone;
float sampleLength = length(sampleStep);
vec3 scattering = vec3(0.0);
vec2 lastOpticalDepth = ComputeOpticalDepth(end, V, L, inf_neg);
for (int i = 1; i < SAMPLES_NUMS; i++, samplePoint -= sampleStep) {
vec2 opticalDepth = ComputeOpticalDepth(samplePoint, V, L, inf_neg);
vec3 segment_s = exp(-sampleLambda * (opticalDepth.x + lastOpticalDepth.x));
vec3 segment_t = exp(-sampleLambda * (opticalDepth.y - lastOpticalDepth.y));
transmittance *= segment_t;
scattering = scattering * segment_t;
scattering += exp(-(length(samplePoint) - earthRadius) / rayleighHeight) * segment_s;
lastOpticalDepth = opticalDepth;
}
insctrMie = scattering * waveLambdaMie * sampleLength;
insctrRayleigh = scattering * waveLambdaRayleigh * sampleLength;
}
float ComputeSkyboxChapman(vec3 eye, vec3 V, vec3 L, out vec3 transmittance, out vec3 insctrMie, out vec3 insctrRayleigh) {
bool neg = true;
vec2 outerIntersections = ComputeRaySphereIntersection(eye, V, earthCenter, earthAtmTopRadius);
if (outerIntersections.y < 0.0) return 0.0;
vec2 innerIntersections = ComputeRaySphereIntersection(eye, V, earthCenter, earthRadius);
if (innerIntersections.x > 0.0) {
neg = false;
outerIntersections.y = innerIntersections.x;
}
eye -= earthCenter;
vec3 start = eye + V * max(0.0, outerIntersections.x);
vec3 end = eye + V * outerIntersections.y;
AerialPerspective(start, end, V, L, neg, transmittance, insctrMie, insctrRayleigh);
bool intersectionTest = innerIntersections.x < 0.0 && innerIntersections.y < 0.0;
return intersectionTest ? 1.0 : 0.0;
}
vec4 ComputeSkyInscattering(vec3 eye, vec3 V, vec3 L) {
vec3 insctrMie = vec3(0.0);
vec3 insctrRayleigh = vec3(0.0);
vec3 insctrOpticalLength = vec3(1.0);
float intersectionTest = ComputeSkyboxChapman(eye, V, L, insctrOpticalLength, insctrMie, insctrRayleigh);
float phaseTheta = dot(V, L);
float phaseMie = ComputePhaseMie(phaseTheta, mieG);
float phaseRayleigh = ComputePhaseRayleigh(phaseTheta);
float phaseNight = 1.0 - saturate(insctrOpticalLength.x * EPSILON);
vec3 insctrTotalMie = insctrMie * phaseMie;
vec3 insctrTotalRayleigh = insctrRayleigh * phaseRayleigh;
vec3 sky = (insctrTotalMie + insctrTotalRayleigh) * sunRadiance;
float angle = saturate((1.0 - phaseTheta) * sunRadius);
float cosAngle = cos(angle * PI * 0.5);
float edge = ((angle >= 0.9) ? smoothstep(0.9, 1.0, angle) : 0.0);
vec3 limbDarkening = GetTransmittance(-L, V);
limbDarkening *= pow(vec3(cosAngle), vec3(0.420, 0.503, 0.652)) * mix(vec3(1.0), vec3(1.2,0.9,0.5), edge) * intersectionTest;
sky += limbDarkening;
return vec4(sky, phaseNight * intersectionTest);
}
vec3 TonemapACES(vec3 x) {
float A = 2.51;
float B = 0.03;
float C = 2.43;
float D = 0.59;
float E = 0.14;
return (x * (A * x + B)) / (x * (C * x + D) + E);
}
float noise(vec2 uv) {
return fract(dot(sin(uv.xyx * uv.xyy * 1024.0), vec3(341896.483, 891618.637, 602649.7031)));
}
void main() {
vec2 uv = v_vTexcoord;
vec2 sun = sunPosition / dimension;
uv.y = 1. - uv.y;
sun.y = 1. - sun.y;
vec3 V = ComputeSphereNormal(uv, 0.0, PI_2, 0.0, PI);
vec3 L = ComputeSphereNormal(vec2(sun.x, sun.y), 0.0, PI_2, 0.0, PI);
mieG = 0.76;
mieHeight = 1200.0;
rayleighHeight = 8000.0;
earthRadius = 6360000.0;
earthAtmTopRadius = 6420000.0;
earthCenter = vec3(0, -earthRadius, 0);
waveLambdaMie = vec3(2e-7);
// wavelength with 680nm, 550nm, 450nm
waveLambdaRayleigh = ComputeWaveLambdaRayleigh(vec3(680e-9, 550e-9, 450e-9));
// see https://www.shadertoy.com/view/MllBR2
waveLambdaOzone = vec3(1.36820899679147, 3.31405330400124, 0.13601728252538) * 0.6e-6 * 2.504;
vec3 eye = vec3(0., 1000.0, 0.);
vec4 sky = ComputeSkyInscattering(eye, V, L);
sky.rgb = TonemapACES(sky.rgb * 2.0);
sky.rgb = pow(sky.rgb, vec3(1.0 / 2.2)); // gamma
gl_FragColor = vec4(sky.rgb, 1.0);
}

View File

@ -0,0 +1,19 @@
//
// Simple passthrough vertex shader
//
attribute vec3 in_Position; // (x,y,z)
//attribute vec3 in_Normal; // (x,y,z) unused in this shader.
attribute vec4 in_Colour; // (r,g,b,a)
attribute vec2 in_TextureCoord; // (u,v)
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
void main()
{
vec4 object_space_pos = vec4( in_Position.x, in_Position.y, in_Position.z, 1.0);
gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * object_space_pos;
v_vColour = in_Colour;
v_vTexcoord = in_TextureCoord;
}

View File

@ -0,0 +1,12 @@
{
"$GMShader":"",
"%Name":"sh_sky_scattering",
"name":"sh_sky_scattering",
"parent":{
"name":"sky model",
"path":"folders/shader/generator/sky model.yy",
},
"resourceType":"GMShader",
"resourceVersion":"2.0",
"type":1,
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -0,0 +1,90 @@
{
"$GMSprite":"",
"%Name":"s_node_sky",
"bboxMode":0,
"bbox_bottom":61,
"bbox_left":2,
"bbox_right":61,
"bbox_top":2,
"collisionKind":1,
"collisionTolerance":0,
"DynamicTexturePage":false,
"edgeFiltering":false,
"For3D":false,
"frames":[
{"$GMSpriteFrame":"","%Name":"68373dee-c8d3-42f8-a753-ddf0f15676ed","name":"68373dee-c8d3-42f8-a753-ddf0f15676ed","resourceType":"GMSpriteFrame","resourceVersion":"2.0",},
],
"gridX":0,
"gridY":0,
"height":64,
"HTile":false,
"layers":[
{"$GMImageLayer":"","%Name":"f370aa54-fd4b-4081-bb69-366f6a87e8e6","blendMode":0,"displayName":"default","isLocked":false,"name":"f370aa54-fd4b-4081-bb69-366f6a87e8e6","opacity":100.0,"resourceType":"GMImageLayer","resourceVersion":"2.0","visible":true,},
],
"name":"s_node_sky",
"nineSlice":null,
"origin":4,
"parent":{
"name":"generator",
"path":"folders/nodes/icons/generator.yy",
},
"preMultiplyAlpha":false,
"resourceType":"GMSprite",
"resourceVersion":"2.0",
"sequence":{
"$GMSequence":"",
"%Name":"s_node_sky",
"autoRecord":true,
"backdropHeight":768,
"backdropImageOpacity":0.5,
"backdropImagePath":"",
"backdropWidth":1366,
"backdropXOffset":0.0,
"backdropYOffset":0.0,
"events":{
"$KeyframeStore<MessageEventKeyframe>":"",
"Keyframes":[],
"resourceType":"KeyframeStore<MessageEventKeyframe>",
"resourceVersion":"2.0",
},
"eventStubScript":null,
"eventToFunction":{},
"length":1.0,
"lockOrigin":false,
"moments":{
"$KeyframeStore<MomentsEventKeyframe>":"",
"Keyframes":[],
"resourceType":"KeyframeStore<MomentsEventKeyframe>",
"resourceVersion":"2.0",
},
"name":"s_node_sky",
"playback":1,
"playbackSpeed":30.0,
"playbackSpeedType":0,
"resourceType":"GMSequence",
"resourceVersion":"2.0",
"showBackdrop":true,
"showBackdropImage":false,
"timeUnits":1,
"tracks":[
{"$GMSpriteFramesTrack":"","builtinName":0,"events":[],"inheritsTrackColour":true,"interpolation":1,"isCreationTrack":false,"keyframes":{"$KeyframeStore<SpriteFrameKeyframe>":"","Keyframes":[
{"$Keyframe<SpriteFrameKeyframe>":"","Channels":{
"0":{"$SpriteFrameKeyframe":"","Id":{"name":"68373dee-c8d3-42f8-a753-ddf0f15676ed","path":"sprites/s_node_sky/s_node_sky.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",},
},"Disabled":false,"id":"8145cea0-1720-4def-8afe-111dbdb8ee79","IsCreationKey":false,"Key":0.0,"Length":1.0,"resourceType":"Keyframe<SpriteFrameKeyframe>","resourceVersion":"2.0","Stretch":false,},
],"resourceType":"KeyframeStore<SpriteFrameKeyframe>","resourceVersion":"2.0",},"modifiers":[],"name":"frames","resourceType":"GMSpriteFramesTrack","resourceVersion":"2.0","spriteId":null,"trackColour":0,"tracks":[],"traits":0,},
],
"visibleRange":null,
"volume":1.0,
"xorigin":32,
"yorigin":32,
},
"swatchColours":null,
"swfPrecision":0.5,
"textureGroupId":{
"name":"Default",
"path":"texturegroups/Default",
},
"type":0,
"VTile":false,
"width":64,
}