diff options
Diffstat (limited to 'scene/resources/sky_material.cpp')
-rw-r--r-- | scene/resources/sky_material.cpp | 191 |
1 files changed, 90 insertions, 101 deletions
diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp index a0b6ab1e30..b2efecb1cb 100644 --- a/scene/resources/sky_material.cpp +++ b/scene/resources/sky_material.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,103 +31,92 @@ #include "sky_material.h" void ProceduralSkyMaterial::set_sky_top_color(const Color &p_sky_top) { - sky_top_color = p_sky_top; RS::get_singleton()->material_set_param(_get_material(), "sky_top_color", sky_top_color.to_linear()); } Color ProceduralSkyMaterial::get_sky_top_color() const { - return sky_top_color; } void ProceduralSkyMaterial::set_sky_horizon_color(const Color &p_sky_horizon) { - sky_horizon_color = p_sky_horizon; RS::get_singleton()->material_set_param(_get_material(), "sky_horizon_color", sky_horizon_color.to_linear()); } -Color ProceduralSkyMaterial::get_sky_horizon_color() const { +Color ProceduralSkyMaterial::get_sky_horizon_color() const { return sky_horizon_color; } void ProceduralSkyMaterial::set_sky_curve(float p_curve) { - sky_curve = p_curve; RS::get_singleton()->material_set_param(_get_material(), "sky_curve", sky_curve); } -float ProceduralSkyMaterial::get_sky_curve() const { +float ProceduralSkyMaterial::get_sky_curve() const { return sky_curve; } void ProceduralSkyMaterial::set_sky_energy(float p_energy) { - sky_energy = p_energy; RS::get_singleton()->material_set_param(_get_material(), "sky_energy", sky_energy); } -float ProceduralSkyMaterial::get_sky_energy() const { +float ProceduralSkyMaterial::get_sky_energy() const { return sky_energy; } void ProceduralSkyMaterial::set_ground_bottom_color(const Color &p_ground_bottom) { - ground_bottom_color = p_ground_bottom; RS::get_singleton()->material_set_param(_get_material(), "ground_bottom_color", ground_bottom_color.to_linear()); } -Color ProceduralSkyMaterial::get_ground_bottom_color() const { +Color ProceduralSkyMaterial::get_ground_bottom_color() const { return ground_bottom_color; } void ProceduralSkyMaterial::set_ground_horizon_color(const Color &p_ground_horizon) { - ground_horizon_color = p_ground_horizon; RS::get_singleton()->material_set_param(_get_material(), "ground_horizon_color", ground_horizon_color.to_linear()); } -Color ProceduralSkyMaterial::get_ground_horizon_color() const { +Color ProceduralSkyMaterial::get_ground_horizon_color() const { return ground_horizon_color; } void ProceduralSkyMaterial::set_ground_curve(float p_curve) { - ground_curve = p_curve; RS::get_singleton()->material_set_param(_get_material(), "ground_curve", ground_curve); } -float ProceduralSkyMaterial::get_ground_curve() const { +float ProceduralSkyMaterial::get_ground_curve() const { return ground_curve; } void ProceduralSkyMaterial::set_ground_energy(float p_energy) { - ground_energy = p_energy; RS::get_singleton()->material_set_param(_get_material(), "ground_energy", ground_energy); } -float ProceduralSkyMaterial::get_ground_energy() const { +float ProceduralSkyMaterial::get_ground_energy() const { return ground_energy; } void ProceduralSkyMaterial::set_sun_angle_max(float p_angle) { - sun_angle_max = p_angle; RS::get_singleton()->material_set_param(_get_material(), "sun_angle_max", Math::deg2rad(sun_angle_max)); } -float ProceduralSkyMaterial::get_sun_angle_max() const { +float ProceduralSkyMaterial::get_sun_angle_max() const { return sun_angle_max; } void ProceduralSkyMaterial::set_sun_curve(float p_curve) { - sun_curve = p_curve; RS::get_singleton()->material_set_param(_get_material(), "sun_curve", sun_curve); } -float ProceduralSkyMaterial::get_sun_curve() const { +float ProceduralSkyMaterial::get_sun_curve() const { return sun_curve; } @@ -136,17 +125,14 @@ bool ProceduralSkyMaterial::_can_do_next_pass() const { } Shader::Mode ProceduralSkyMaterial::get_shader_mode() const { - return Shader::MODE_SKY; } RID ProceduralSkyMaterial::get_shader_rid() const { - return shader; } void ProceduralSkyMaterial::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_sky_top_color", "color"), &ProceduralSkyMaterial::set_sky_top_color); ClassDB::bind_method(D_METHOD("get_sky_top_color"), &ProceduralSkyMaterial::get_sky_top_color); @@ -195,7 +181,6 @@ void ProceduralSkyMaterial::_bind_methods() { } ProceduralSkyMaterial::ProceduralSkyMaterial() { - String code = "shader_type sky;\n\n"; code += "uniform vec4 sky_top_color : hint_color = vec4(0.35, 0.46, 0.71, 1.0);\n"; @@ -285,13 +270,11 @@ ProceduralSkyMaterial::~ProceduralSkyMaterial() { /* PanoramaSkyMaterial */ void PanoramaSkyMaterial::set_panorama(const Ref<Texture2D> &p_panorama) { - panorama = p_panorama; RS::get_singleton()->material_set_param(_get_material(), "source_panorama", panorama); } Ref<Texture2D> PanoramaSkyMaterial::get_panorama() const { - return panorama; } @@ -300,17 +283,14 @@ bool PanoramaSkyMaterial::_can_do_next_pass() const { } Shader::Mode PanoramaSkyMaterial::get_shader_mode() const { - return Shader::MODE_SKY; } RID PanoramaSkyMaterial::get_shader_rid() const { - return shader; } void PanoramaSkyMaterial::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_panorama", "texture"), &PanoramaSkyMaterial::set_panorama); ClassDB::bind_method(D_METHOD("get_panorama"), &PanoramaSkyMaterial::get_panorama); @@ -336,124 +316,122 @@ PanoramaSkyMaterial::~PanoramaSkyMaterial() { RS::get_singleton()->free(shader); RS::get_singleton()->material_set_shader(_get_material(), RID()); } + ////////////////////////////////// /* PhysicalSkyMaterial */ void PhysicalSkyMaterial::set_rayleigh_coefficient(float p_rayleigh) { - rayleigh = p_rayleigh; RS::get_singleton()->material_set_param(_get_material(), "rayleigh", rayleigh); } -float PhysicalSkyMaterial::get_rayleigh_coefficient() const { +float PhysicalSkyMaterial::get_rayleigh_coefficient() const { return rayleigh; } void PhysicalSkyMaterial::set_rayleigh_color(Color p_rayleigh_color) { - rayleigh_color = p_rayleigh_color; RS::get_singleton()->material_set_param(_get_material(), "rayleigh_color", rayleigh_color); } -Color PhysicalSkyMaterial::get_rayleigh_color() const { +Color PhysicalSkyMaterial::get_rayleigh_color() const { return rayleigh_color; } void PhysicalSkyMaterial::set_mie_coefficient(float p_mie) { - mie = p_mie; RS::get_singleton()->material_set_param(_get_material(), "mie", mie); } -float PhysicalSkyMaterial::get_mie_coefficient() const { +float PhysicalSkyMaterial::get_mie_coefficient() const { return mie; } void PhysicalSkyMaterial::set_mie_eccentricity(float p_eccentricity) { - mie_eccentricity = p_eccentricity; RS::get_singleton()->material_set_param(_get_material(), "mie_eccentricity", mie_eccentricity); } -float PhysicalSkyMaterial::get_mie_eccentricity() const { +float PhysicalSkyMaterial::get_mie_eccentricity() const { return mie_eccentricity; } void PhysicalSkyMaterial::set_mie_color(Color p_mie_color) { - mie_color = p_mie_color; RS::get_singleton()->material_set_param(_get_material(), "mie_color", mie_color); } + Color PhysicalSkyMaterial::get_mie_color() const { return mie_color; } void PhysicalSkyMaterial::set_turbidity(float p_turbidity) { - turbidity = p_turbidity; RS::get_singleton()->material_set_param(_get_material(), "turbidity", turbidity); } -float PhysicalSkyMaterial::get_turbidity() const { +float PhysicalSkyMaterial::get_turbidity() const { return turbidity; } void PhysicalSkyMaterial::set_sun_disk_scale(float p_sun_disk_scale) { - sun_disk_scale = p_sun_disk_scale; RS::get_singleton()->material_set_param(_get_material(), "sun_disk_scale", sun_disk_scale); } -float PhysicalSkyMaterial::get_sun_disk_scale() const { +float PhysicalSkyMaterial::get_sun_disk_scale() const { return sun_disk_scale; } void PhysicalSkyMaterial::set_ground_color(Color p_ground_color) { - ground_color = p_ground_color; RS::get_singleton()->material_set_param(_get_material(), "ground_color", ground_color); } -Color PhysicalSkyMaterial::get_ground_color() const { +Color PhysicalSkyMaterial::get_ground_color() const { return ground_color; } void PhysicalSkyMaterial::set_exposure(float p_exposure) { - exposure = p_exposure; RS::get_singleton()->material_set_param(_get_material(), "exposure", exposure); } -float PhysicalSkyMaterial::get_exposure() const { +float PhysicalSkyMaterial::get_exposure() const { return exposure; } void PhysicalSkyMaterial::set_dither_strength(float p_dither_strength) { - dither_strength = p_dither_strength; RS::get_singleton()->material_set_param(_get_material(), "dither_strength", dither_strength); } -float PhysicalSkyMaterial::get_dither_strength() const { +float PhysicalSkyMaterial::get_dither_strength() const { return dither_strength; } +void PhysicalSkyMaterial::set_night_sky(const Ref<Texture2D> &p_night_sky) { + night_sky = p_night_sky; + RS::get_singleton()->material_set_param(_get_material(), "night_sky", night_sky); +} + +Ref<Texture2D> PhysicalSkyMaterial::get_night_sky() const { + return night_sky; +} + bool PhysicalSkyMaterial::_can_do_next_pass() const { return false; } Shader::Mode PhysicalSkyMaterial::get_shader_mode() const { - return Shader::MODE_SKY; } RID PhysicalSkyMaterial::get_shader_rid() const { - return shader; } void PhysicalSkyMaterial::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_rayleigh_coefficient", "rayleigh"), &PhysicalSkyMaterial::set_rayleigh_coefficient); ClassDB::bind_method(D_METHOD("get_rayleigh_coefficient"), &PhysicalSkyMaterial::get_rayleigh_coefficient); @@ -484,6 +462,9 @@ void PhysicalSkyMaterial::_bind_methods() { ClassDB::bind_method(D_METHOD("set_dither_strength", "strength"), &PhysicalSkyMaterial::set_dither_strength); ClassDB::bind_method(D_METHOD("get_dither_strength"), &PhysicalSkyMaterial::get_dither_strength); + ClassDB::bind_method(D_METHOD("set_night_sky", "night_sky"), &PhysicalSkyMaterial::set_night_sky); + ClassDB::bind_method(D_METHOD("get_night_sky"), &PhysicalSkyMaterial::get_night_sky); + ADD_GROUP("Rayleigh", "rayleigh_"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rayleigh_coefficient", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_rayleigh_coefficient", "get_rayleigh_coefficient"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "rayleigh_color"), "set_rayleigh_color", "get_rayleigh_color"); @@ -498,6 +479,7 @@ void PhysicalSkyMaterial::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_color"), "set_ground_color", "get_ground_color"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure", PROPERTY_HINT_RANGE, "0,128,0.01"), "set_exposure", "get_exposure"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dither_strength", PROPERTY_HINT_RANGE, "0,10,0.01"), "set_dither_strength", "get_dither_strength"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "night_sky", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_night_sky", "get_night_sky"); } PhysicalSkyMaterial::PhysicalSkyMaterial() { @@ -515,6 +497,8 @@ PhysicalSkyMaterial::PhysicalSkyMaterial() { code += "uniform float exposure : hint_range(0, 128) = 0.1;\n"; code += "uniform float dither_strength : hint_range(0, 10) = 1.0;\n\n"; + code += "uniform sampler2D night_sky : hint_black;"; + code += "const float PI = 3.141592653589793238462643383279502884197169;\n"; code += "const vec3 UP = vec3( 0.0, 1.0, 0.0 );\n\n"; @@ -538,53 +522,59 @@ PhysicalSkyMaterial::PhysicalSkyMaterial() { code += "}\n\n"; code += "void fragment() {\n"; - code += "\tfloat zenith_angle = clamp( dot(UP, normalize(LIGHT0_DIRECTION)), -1.0, 1.0 );\n"; - code += "\tfloat sun_energy = max(0.0, 1.0 - exp(-((PI * 0.5) - acos(zenith_angle)))) * SUN_ENERGY * LIGHT0_ENERGY;\n"; - code += "\tfloat sun_fade = 1.0 - clamp(1.0 - exp(LIGHT0_DIRECTION.y), 0.0, 1.0);\n\n"; - - code += "\t// rayleigh coefficients\n"; - code += "\tfloat rayleigh_coefficient = rayleigh - ( 1.0 * ( 1.0 - sun_fade ) );\n"; - code += "\tvec3 rayleigh_beta = rayleigh_coefficient * rayleigh_color.rgb * 0.0001;\n"; - code += "\t// mie coefficients from Preetham\n"; - code += "\tvec3 mie_beta = turbidity * mie * mie_color.rgb * 0.000434;\n\n"; - - code += "\t// optical length\n"; - code += "\tfloat zenith = acos(max(0.0, dot(UP, EYEDIR)));\n"; - code += "\tfloat optical_mass = 1.0 / (cos(zenith) + 0.15 * pow(93.885 - degrees(zenith), -1.253));\n"; - code += "\tfloat rayleigh_scatter = rayleigh_zenith_size * optical_mass;\n"; - code += "\tfloat mie_scatter = mie_zenith_size * optical_mass;\n\n"; - - code += "\t// light extinction based on thickness of atmosphere\n"; - code += "\tvec3 extinction = exp(-(rayleigh_beta * rayleigh_scatter + mie_beta * mie_scatter));\n\n"; - - code += "\t// in scattering\n"; - code += "\tfloat cos_theta = dot(EYEDIR, normalize(LIGHT0_DIRECTION));\n\n"; - - code += "\tfloat rayleigh_phase = (3.0 / (16.0 * PI)) * (1.0 + pow(cos_theta * 0.5 + 0.5, 2.0));\n"; - code += "\tvec3 betaRTheta = rayleigh_beta * rayleigh_phase;\n\n"; - - code += "\tfloat mie_phase = henyey_greenstein(cos_theta, mie_eccentricity);\n"; - code += "\tvec3 betaMTheta = mie_beta * mie_phase;\n\n"; - - code += "\tvec3 Lin = pow(sun_energy * ((betaRTheta + betaMTheta) / (rayleigh_beta + mie_beta)) * (1.0 - extinction), vec3(1.5));\n"; - code += "\t// Hack from https://github.com/mrdoob/three.js/blob/master/examples/jsm/objects/Sky.js\n"; - code += "\tLin *= mix(vec3(1.0), pow(sun_energy * ((betaRTheta + betaMTheta) / (rayleigh_beta + mie_beta)) * extinction, vec3(0.5)), clamp(pow(1.0 - zenith_angle, 5.0), 0.0, 1.0));\n\n"; - - code += "\t// Hack in the ground color\n"; - code += "\tLin *= mix(ground_color.rgb, vec3(1.0), smoothstep(-0.1, 0.1, dot(UP, EYEDIR)));\n\n"; - - code += "\t// Solar disk and out-scattering\n"; - code += "\tfloat sunAngularDiameterCos = cos(LIGHT0_SIZE * sun_disk_scale);\n"; - code += "\tfloat sunAngularDiameterCos2 = cos(LIGHT0_SIZE * sun_disk_scale*0.5);\n"; - code += "\tfloat sundisk = smoothstep(sunAngularDiameterCos, sunAngularDiameterCos2, cos_theta);\n"; - code += "\tvec3 L0 = (sun_energy * 1900.0 * extinction) * sundisk * LIGHT0_COLOR;\n"; - code += "\t// Note: Add nightime here: L0 += night_sky * extinction\n\n"; - - code += "\tvec3 color = (Lin + L0) * 0.04;\n"; - code += "\tCOLOR = pow(color, vec3(1.0 / (1.2 + (1.2 * sun_fade))));\n"; - code += "\tCOLOR *= exposure;\n"; - code += "\t// Make optional, eliminates banding\n"; - code += "\tCOLOR += (hash(EYEDIR * 1741.9782) * 0.08 - 0.04) * 0.008 * dither_strength;\n"; + code += "\tif (LIGHT0_ENABLED) {\n"; + code += "\t\tfloat zenith_angle = clamp( dot(UP, normalize(LIGHT0_DIRECTION)), -1.0, 1.0 );\n"; + code += "\t\tfloat sun_energy = max(0.0, 1.0 - exp(-((PI * 0.5) - acos(zenith_angle)))) * SUN_ENERGY * LIGHT0_ENERGY;\n"; + code += "\t\tfloat sun_fade = 1.0 - clamp(1.0 - exp(LIGHT0_DIRECTION.y), 0.0, 1.0);\n\n"; + + code += "\t\t// rayleigh coefficients\n"; + code += "\t\tfloat rayleigh_coefficient = rayleigh - ( 1.0 * ( 1.0 - sun_fade ) );\n"; + code += "\t\tvec3 rayleigh_beta = rayleigh_coefficient * rayleigh_color.rgb * 0.0001;\n"; + code += "\t\t// mie coefficients from Preetham\n"; + code += "\t\tvec3 mie_beta = turbidity * mie * mie_color.rgb * 0.000434;\n\n"; + + code += "\t\t// optical length\n"; + code += "\t\tfloat zenith = acos(max(0.0, dot(UP, EYEDIR)));\n"; + code += "\t\tfloat optical_mass = 1.0 / (cos(zenith) + 0.15 * pow(93.885 - degrees(zenith), -1.253));\n"; + code += "\t\tfloat rayleigh_scatter = rayleigh_zenith_size * optical_mass;\n"; + code += "\t\tfloat mie_scatter = mie_zenith_size * optical_mass;\n\n"; + + code += "\t\t// light extinction based on thickness of atmosphere\n"; + code += "\t\tvec3 extinction = exp(-(rayleigh_beta * rayleigh_scatter + mie_beta * mie_scatter));\n\n"; + + code += "\t\t// in scattering\n"; + code += "\t\tfloat cos_theta = dot(EYEDIR, normalize(LIGHT0_DIRECTION));\n\n"; + + code += "\t\tfloat rayleigh_phase = (3.0 / (16.0 * PI)) * (1.0 + pow(cos_theta * 0.5 + 0.5, 2.0));\n"; + code += "\t\tvec3 betaRTheta = rayleigh_beta * rayleigh_phase;\n\n"; + + code += "\t\tfloat mie_phase = henyey_greenstein(cos_theta, mie_eccentricity);\n"; + code += "\t\tvec3 betaMTheta = mie_beta * mie_phase;\n\n"; + + code += "\t\tvec3 Lin = pow(sun_energy * ((betaRTheta + betaMTheta) / (rayleigh_beta + mie_beta)) * (1.0 - extinction), vec3(1.5));\n"; + code += "\t\t// Hack from https://github.com/mrdoob/three.js/blob/master/examples/jsm/objects/Sky.js\n"; + code += "\t\tLin *= mix(vec3(1.0), pow(sun_energy * ((betaRTheta + betaMTheta) / (rayleigh_beta + mie_beta)) * extinction, vec3(0.5)), clamp(pow(1.0 - zenith_angle, 5.0), 0.0, 1.0));\n\n"; + + code += "\t\t// Hack in the ground color\n"; + code += "\t\tLin *= mix(ground_color.rgb, vec3(1.0), smoothstep(-0.1, 0.1, dot(UP, EYEDIR)));\n\n"; + + code += "\t\t// Solar disk and out-scattering\n"; + code += "\t\tfloat sunAngularDiameterCos = cos(LIGHT0_SIZE * sun_disk_scale);\n"; + code += "\t\tfloat sunAngularDiameterCos2 = cos(LIGHT0_SIZE * sun_disk_scale*0.5);\n"; + code += "\t\tfloat sundisk = smoothstep(sunAngularDiameterCos, sunAngularDiameterCos2, cos_theta);\n"; + code += "\t\tvec3 L0 = (sun_energy * 1900.0 * extinction) * sundisk * LIGHT0_COLOR;\n"; + code += "\t\tL0 += texture(night_sky, SKY_COORDS).xyz * extinction;\n\n"; + + code += "\t\tvec3 color = (Lin + L0) * 0.04;\n"; + code += "\t\tCOLOR = pow(color, vec3(1.0 / (1.2 + (1.2 * sun_fade))));\n"; + code += "\t\tCOLOR *= exposure;\n"; + code += "\t\t// Make optional, eliminates banding\n"; + code += "\t\tCOLOR += (hash(EYEDIR * 1741.9782) * 0.08 - 0.04) * 0.016 * dither_strength;\n"; + code += "\t} else {\n"; + code += "\t\t// There is no sun, so display night_sky and nothing else\n"; + code += "\t\tCOLOR = texture(night_sky, SKY_COORDS).xyz * 0.04;\n"; + code += "\t\tCOLOR *= exposure;\n"; + code += "\t}\n"; code += "}\n"; shader = RS::get_singleton()->shader_create(); @@ -607,5 +597,4 @@ PhysicalSkyMaterial::PhysicalSkyMaterial() { PhysicalSkyMaterial::~PhysicalSkyMaterial() { RS::get_singleton()->free(shader); - RS::get_singleton()->material_set_shader(_get_material(), RID()); } |