diff --git a/PixelComposer.resource_order b/PixelComposer.resource_order index 287c59d6e..c3480ea5f 100644 --- a/PixelComposer.resource_order +++ b/PixelComposer.resource_order @@ -188,6 +188,7 @@ {"name":"blinker","order":19,"path":"folders/shader/generator/blinker.yy",}, {"name":"cell","order":20,"path":"folders/shader/generator/cell.yy",}, {"name":"grid","order":18,"path":"folders/shader/generator/grid.yy",}, + {"name":"sky model","order":31,"path":"folders/shader/generator/sky model.yy",}, {"name":"interpret","order":17,"path":"folders/shader/generator/interpret.yy",}, {"name":"random_shape","order":21,"path":"folders/shader/generator/random_shape.yy",}, {"name":"reaction_diffusion","order":22,"path":"folders/shader/generator/reaction_diffusion.yy",}, @@ -1112,6 +1113,7 @@ {"name":"node_shard_noise","order":12,"path":"scripts/node_shard_noise/node_shard_noise.yy",}, {"name":"node_shell","order":13,"path":"scripts/node_shell/node_shell.yy",}, {"name":"node_skew","order":11,"path":"scripts/node_skew/node_skew.yy",}, + {"name":"node_sky","order":24,"path":"scripts/node_sky/node_sky.yy",}, {"name":"node_slideshow","order":28,"path":"scripts/node_slideshow/node_slideshow.yy",}, {"name":"node_smear","order":12,"path":"scripts/node_smear/node_smear.yy",}, {"name":"node_smoke_add_collider","order":6,"path":"scripts/node_smoke_add_collider/node_smoke_add_collider.yy",}, diff --git a/PixelComposer.yyp b/PixelComposer.yyp index 2d89f4e51..abfc1014a 100644 --- a/PixelComposer.yyp +++ b/PixelComposer.yyp @@ -299,6 +299,7 @@ {"$GMFolder":"","%Name":"blinker","folderPath":"folders/shader/generator/blinker.yy","name":"blinker","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"cell","folderPath":"folders/shader/generator/cell.yy","name":"cell","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"grid","folderPath":"folders/shader/generator/grid.yy","name":"grid","resourceType":"GMFolder","resourceVersion":"2.0",}, + {"$GMFolder":"","%Name":"sky model","folderPath":"folders/shader/generator/sky model.yy","name":"sky model","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"interpret","folderPath":"folders/shader/generator/interpret.yy","name":"interpret","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"random_shape","folderPath":"folders/shader/generator/random_shape.yy","name":"random_shape","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"reaction_diffusion","folderPath":"folders/shader/generator/reaction_diffusion.yy","name":"reaction_diffusion","resourceType":"GMFolder","resourceVersion":"2.0",}, @@ -1704,6 +1705,7 @@ {"id":{"name":"node_shard_noise","path":"scripts/node_shard_noise/node_shard_noise.yy",},}, {"id":{"name":"node_shell","path":"scripts/node_shell/node_shell.yy",},}, {"id":{"name":"node_skew","path":"scripts/node_skew/node_skew.yy",},}, + {"id":{"name":"node_sky","path":"scripts/node_sky/node_sky.yy",},}, {"id":{"name":"node_slideshow","path":"scripts/node_slideshow/node_slideshow.yy",},}, {"id":{"name":"node_smear","path":"scripts/node_smear/node_smear.yy",},}, {"id":{"name":"node_smoke_add_collider","path":"scripts/node_smoke_add_collider/node_smoke_add_collider.yy",},}, @@ -2438,6 +2440,7 @@ {"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_preetham","path":"shaders/sh_sky_preetham/sh_sky_preetham.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",},}, diff --git a/scripts/node_registry/node_registry.gml b/scripts/node_registry/node_registry.gml index fecc533a7..3a1d4b2be 100644 --- a/scripts/node_registry/node_registry.gml +++ b/scripts/node_registry/node_registry.gml @@ -752,6 +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."); 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."); diff --git a/scripts/node_sky/node_sky.gml b/scripts/node_sky/node_sky.gml new file mode 100644 index 000000000..959a0b259 --- /dev/null +++ b/scripts/node_sky/node_sky.gml @@ -0,0 +1,63 @@ +function Node_Sky(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor { + name = "Sky"; + + newInput(0, nodeValue_Dimension(self)); + + newInput(1, nodeValue_Enum_Scroll("Model", self, 0, [ "Preetham" ])); + + newInput(2, nodeValue_Float("Turbidity", self, 2)); + + newInput(3, nodeValue_Float("Azimuth", self, 0)) + .setDisplay(VALUE_DISPLAY.slider, { range: [ -180, 180, 1 ] }); + + newInput(4, nodeValue_Float("Inclination", self, 0)) + .setDisplay(VALUE_DISPLAY.slider, { range: [ -180, 180, 1 ] }); + + newInput(5, nodeValue_Vec2("Scale", self, [ 1, 1 ])); + + newInput(6, nodeValue_Vec2("Offset", self, [ 0, 0 ])); + + 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, + ]; + + attribute_surface_depth(); + + 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; + + 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]; + + if(_mod == 0) { + 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_f("turbidity", _tur); + shader_set_f("azimuth", degtorad(_azi)); + shader_set_f("inclination", degtorad(_inc)); + + draw_empty(); + surface_reset_shader(); + } + + return _outSurf; + } +} \ No newline at end of file diff --git a/scripts/node_sky/node_sky.yy b/scripts/node_sky/node_sky.yy new file mode 100644 index 000000000..e4bf00188 --- /dev/null +++ b/scripts/node_sky/node_sky.yy @@ -0,0 +1,13 @@ +{ + "$GMScript":"v1", + "%Name":"node_sky", + "isCompatibility":false, + "isDnD":false, + "name":"node_sky", + "parent":{ + "name":"generator", + "path":"folders/nodes/data/generator.yy", + }, + "resourceType":"GMScript", + "resourceVersion":"2.0", +} \ No newline at end of file diff --git a/shaders/sh_sky_preetham/sh_sky_preetham.fsh b/shaders/sh_sky_preetham/sh_sky_preetham.fsh new file mode 100644 index 000000000..8a02377fb --- /dev/null +++ b/shaders/sh_sky_preetham/sh_sky_preetham.fsh @@ -0,0 +1,117 @@ +#define PI 3.14159265359 + +varying vec2 v_vTexcoord; +varying vec4 v_vColour; + +uniform vec2 dimension; +uniform vec2 position; +uniform vec2 scale; + +uniform float turbidity; +uniform float azimuth; +uniform float inclination; + +float saturatedDot( in vec3 a, in vec3 b ) { + return max( dot( a, b ), 0.0 ); +} + +vec3 computeSphericalCoordinates( in vec2 uv ) { + float theta = uv.x * 2.0 * PI; + float phi = uv.y * PI; + return vec3(cos(theta) * sin(phi), sin(theta) * sin(phi), cos(phi)); +} + +vec3 YxyToXYZ( in vec3 Yxy ) { + float Y = Yxy.r; + float x = Yxy.g; + float y = Yxy.b; + + float X = x * ( Y / y ); + float Z = ( 1.0 - x - y ) * ( Y / y ); + + return vec3(X,Y,Z); +} + +vec3 XYZToRGB( in vec3 XYZ ) { + // CIE/E + mat3 M = mat3 + ( + 2.3706743, -0.9000405, -0.4706338, + -0.5138850, 1.4253036, 0.0885814, + 0.0052982, -0.0146949, 1.0093968 + ); + + return XYZ * M; +} + + +vec3 YxyToRGB( in vec3 Yxy ) { + vec3 XYZ = YxyToXYZ( Yxy ); + vec3 RGB = XYZToRGB( XYZ ); + return RGB; +} + +void calculatePerezDistribution( in float t, out vec3 A, out vec3 B, out vec3 C, out vec3 D, out vec3 E ) { + A = vec3( 0.1787 * t - 1.4630, -0.0193 * t - 0.2592, -0.0167 * t - 0.2608 ); + B = vec3( -0.3554 * t + 0.4275, -0.0665 * t + 0.0008, -0.0950 * t + 0.0092 ); + C = vec3( -0.0227 * t + 5.3251, -0.0004 * t + 0.2125, -0.0079 * t + 0.2102 ); + D = vec3( 0.1206 * t - 2.5771, -0.0641 * t - 0.8989, -0.0441 * t - 1.6537 ); + E = vec3( -0.0670 * t + 0.3703, -0.0033 * t + 0.0452, -0.0109 * t + 0.0529 ); +} + +vec3 calculateZenithLuminanceYxy( in float t, in float thetaS ) { + float chi = ( 4.0 / 9.0 - t / 120.0 ) * ( PI - 2.0 * thetaS ); + float Yz = ( 4.0453 * t - 4.9710 ) * tan( chi ) - 0.2155 * t + 2.4192; + + float theta2 = thetaS * thetaS; + float theta3 = theta2 * thetaS; + float T = t; + float T2 = t * t; + + float xz = + ( 0.00165 * theta3 - 0.00375 * theta2 + 0.00209 * thetaS + 0.0) * T2 + + (-0.02903 * theta3 + 0.06377 * theta2 - 0.03202 * thetaS + 0.00394) * T + + ( 0.11693 * theta3 - 0.21196 * theta2 + 0.06052 * thetaS + 0.25886); + + float yz = + ( 0.00275 * theta3 - 0.00610 * theta2 + 0.00317 * thetaS + 0.0) * T2 + + (-0.04214 * theta3 + 0.08970 * theta2 - 0.04153 * thetaS + 0.00516) * T + + ( 0.15346 * theta3 - 0.26756 * theta2 + 0.06670 * thetaS + 0.26688); + + return vec3( Yz, xz, yz ); +} + +vec3 calculatePerezLuminanceYxy( in float theta, in float gamma, in vec3 A, in vec3 B, in vec3 C, in vec3 D, in vec3 E ) { + return ( 1.0 + A * exp( B / cos( theta ) ) ) * ( 1.0 + C * exp( D * gamma ) + E * cos( gamma ) * cos( gamma ) ); +} + +vec3 calculateSkyLuminanceRGB( in vec3 s, in vec3 e, in float t ) { + vec3 A, B, C, D, E; + calculatePerezDistribution( t, A, B, C, D, E ); + + float thetaS = acos( saturatedDot( s, vec3(0,1,0) ) ); + float thetaE = acos( saturatedDot( e, vec3(0,1,0) ) ); + float gammaE = acos( saturatedDot( s, e ) ); + + vec3 Yz = calculateZenithLuminanceYxy( t, thetaS ); + + vec3 fThetaGamma = calculatePerezLuminanceYxy( thetaE, gammaE, A, B, C, D, E ); + vec3 fZeroThetaS = calculatePerezLuminanceYxy( 0.0, thetaS, A, B, C, D, E ); + + vec3 Yp = Yz * ( fThetaGamma / fZeroThetaS ); + + return YxyToRGB( Yp ); +} + +void main() { + vec2 uv = v_vTexcoord; + uv = (uv - position / dimension); + uv.y = 1. - uv.y; + uv /= scale; + + vec3 sunDir = normalize( vec3( sin( inclination ) * cos( azimuth ), cos( inclination ), sin( inclination ) * sin(azimuth) ) ); + vec3 viewDir = -computeSphericalCoordinates( uv ).xzy; + vec3 skyLuminance = calculateSkyLuminanceRGB( sunDir, viewDir, turbidity ); + + gl_FragColor = vec4( skyLuminance * 0.05, 1.0 ); +} \ No newline at end of file diff --git a/shaders/sh_sky_preetham/sh_sky_preetham.vsh b/shaders/sh_sky_preetham/sh_sky_preetham.vsh new file mode 100644 index 000000000..3900c20f4 --- /dev/null +++ b/shaders/sh_sky_preetham/sh_sky_preetham.vsh @@ -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; +} diff --git a/shaders/sh_sky_preetham/sh_sky_preetham.yy b/shaders/sh_sky_preetham/sh_sky_preetham.yy new file mode 100644 index 000000000..35b6c1dba --- /dev/null +++ b/shaders/sh_sky_preetham/sh_sky_preetham.yy @@ -0,0 +1,12 @@ +{ + "$GMShader":"", + "%Name":"sh_sky_preetham", + "name":"sh_sky_preetham", + "parent":{ + "name":"sky model", + "path":"folders/shader/generator/sky model.yy", + }, + "resourceType":"GMShader", + "resourceVersion":"2.0", + "type":1, +} \ No newline at end of file