Working sky shader implementation

This commit is contained in:
clayjohn 2020-03-19 17:32:19 -07:00
parent c3fee7ba6c
commit 61a74739ca
40 changed files with 2354 additions and 1744 deletions

View file

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="PanoramaSky" inherits="Sky" version="4.0">
<class name="PanoramaSkyMaterial" inherits="Material" version="4.0">
<brief_description>
A type of [Sky] used to draw a background texture.
A [Material] used with [Sky] to draw a background texture.
</brief_description>
<description>
A resource referenced in an [Environment] that is used to draw a background. The Panorama sky functions similar to skyboxes in other engines, except it uses an equirectangular sky map instead of a cube map.
A resource referenced in a [Sky] that is used to draw a background. The Panorama sky material functions similar to skyboxes in other engines, except it uses an equirectangular sky map instead of a cube map.
Using an HDR panorama is strongly recommended for accurate, high-quality reflections. Godot supports the Radiance HDR ([code].hdr[/code]) and OpenEXR ([code].exr[/code]) image formats for this purpose.
You can use [url=https://danilw.github.io/GLSL-howto/cubemap_to_panorama_js/cubemap_to_panorama.html]this tool[/url] to convert a cube map to an equirectangular sky map.
</description>
@ -14,7 +14,7 @@
</methods>
<members>
<member name="panorama" type="Texture2D" setter="set_panorama" getter="get_panorama">
[Texture2D] to be applied to the PanoramaSky.
[Texture2D] to be applied to the [PanoramaSkyMaterial].
</member>
</members>
<constants>

View file

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="PhysicalSkyMaterial" inherits="Material" version="4.0">
<brief_description>
[Sky] [Material] used for a physically based sky.
</brief_description>
<description>
The [PhysicalSkyMaterial] uses the Preetham analytic daylight model to draw a sky based on physical properties. This results in a substantially more realistic sky than the [ProceduralSkyMaterial], but it is slightly slower and less flexible.
The [PhysicalSkyMaterial] only supports one sun. The color, energy, and direction of the sun are taken from the first [DirectionalLight] in the scene tree.
As it is based on a daylight model, the sky fades to black as the sunset ends. If you want a full day/night cycle, you will have to add a night sky by converting this to a [ShaderMaterial] and adding a night sky directly into the resulting shader.
</description>
<tutorials>
</tutorials>
<methods>
</methods>
<members>
<member name="dither_strength" type="float" setter="set_dither_strength" getter="get_dither_strength" default="1.0">
Sets the amount of dithering to use. Dithering helps reduce banding that appears from the smooth changes in color in the sky. Use the lowest value possible, higher amounts may add fuzziness to the sky.
</member>
<member name="exposure" type="float" setter="set_exposure" getter="get_exposure" default="0.1">
Sets the exposure of the sky. Higher exposure values make the entire sky brighter.
</member>
<member name="ground_color" type="Color" setter="set_ground_color" getter="get_ground_color" default="Color( 1, 1, 1, 1 )">
Modulates the [Color] on the bottom half of the sky to represent the ground.
</member>
<member name="mie_coefficient" type="float" setter="set_mie_coefficient" getter="get_mie_coefficient" default="0.005">
Controls the strength of mie scattering for the sky. Mie scattering results from light colliding with larger particles (like water). On earth, mie scattering results in a whiteish color around the sun and horizon.
</member>
<member name="mie_color" type="Color" setter="set_mie_color" getter="get_mie_color" default="Color( 0.36, 0.56, 0.82, 1 )">
Controls the [Color] of the mie scattering effect. While not physically accurate, this allows for the creation of alien looking planets.
</member>
<member name="mie_eccentricity" type="float" setter="set_mie_eccentricity" getter="get_mie_eccentricity" default="0.8">
Controls the direction of the mie scattering. A value of [code]1[/code] means that when light hits a particle it passing through straight forward. A value of [code]-1[/code] means that all light is scatter backwards.
</member>
<member name="rayleigh_coefficient" type="float" setter="set_rayleigh_coefficient" getter="get_rayleigh_coefficient" default="2.0">
Controls the strength of the rayleigh scattering. Rayleigh scattering results from light colliding with small particles. It is responsible for the blue color of the sky.
</member>
<member name="rayleigh_color" type="Color" setter="set_rayleigh_color" getter="get_rayleigh_color" default="Color( 0.056, 0.14, 0.3, 1 )">
Controls the [Color] of the rayleigh scattering. While not physically accurate, this allows for the creation of alien looking planets. For example, setting this to a red [Color] results in a mars looking atmosphere with a corresponding blue sunset.
</member>
<member name="sun_disk_scale" type="float" setter="set_sun_disk_scale" getter="get_sun_disk_scale" default="1.0">
Sets the size of the sun disk. Default value is based on Sol's perceived size from Earth.
</member>
<member name="turbidity" type="float" setter="set_turbidity" getter="get_turbidity" default="10.0">
Sets the thickness of the atmosphere. High turbidity creates a foggy looking atmosphere, while a low turbidity results in a clearer atmosphere.
</member>
</members>
<constants>
</constants>
</class>

View file

@ -1,84 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="ProceduralSky" inherits="Sky" version="4.0">
<brief_description>
Type of [Sky] that is generated procedurally based on user input parameters.
</brief_description>
<description>
ProceduralSky provides a way to create an effective background quickly by defining procedural parameters for the sun, the sky and the ground. The sky and ground are very similar, they are defined by a color at the horizon, another color, and finally an easing curve to interpolate between these two colors. Similarly, the sun is described by a position in the sky, a color, and an easing curve. However, the sun also defines a minimum and maximum angle, these two values define at what distance the easing curve begins and ends from the sun, and thus end up defining the size of the sun in the sky.
The ProceduralSky is updated on the CPU after the parameters change. It is stored in a texture and then displayed as a background in the scene. This makes it relatively unsuitable for real-time updates during gameplay. However, with a small enough texture size, it can still be updated relatively frequently, as it is updated on a background thread when multi-threading is available.
</description>
<tutorials>
</tutorials>
<methods>
</methods>
<members>
<member name="ground_bottom_color" type="Color" setter="set_ground_bottom_color" getter="get_ground_bottom_color" default="Color( 0.156863, 0.184314, 0.211765, 1 )">
Color of the ground at the bottom.
</member>
<member name="ground_curve" type="float" setter="set_ground_curve" getter="get_ground_curve" default="0.02">
How quickly the [member ground_horizon_color] fades into the [member ground_bottom_color].
</member>
<member name="ground_energy" type="float" setter="set_ground_energy" getter="get_ground_energy" default="1.0">
Amount of energy contribution from the ground.
</member>
<member name="ground_horizon_color" type="Color" setter="set_ground_horizon_color" getter="get_ground_horizon_color" default="Color( 0.423529, 0.396078, 0.372549, 1 )">
Color of the ground at the horizon.
</member>
<member name="sky_curve" type="float" setter="set_sky_curve" getter="get_sky_curve" default="0.09">
How quickly the [member sky_horizon_color] fades into the [member sky_top_color].
</member>
<member name="sky_energy" type="float" setter="set_sky_energy" getter="get_sky_energy" default="1.0">
Amount of energy contribution from the sky.
</member>
<member name="sky_horizon_color" type="Color" setter="set_sky_horizon_color" getter="get_sky_horizon_color" default="Color( 0.839216, 0.917647, 0.980392, 1 )">
Color of the sky at the horizon.
</member>
<member name="sky_top_color" type="Color" setter="set_sky_top_color" getter="get_sky_top_color" default="Color( 0.647059, 0.839216, 0.945098, 1 )">
Color of the sky at the top.
</member>
<member name="sun_angle_max" type="float" setter="set_sun_angle_max" getter="get_sun_angle_max" default="100.0">
Distance from center of sun where it fades out completely.
</member>
<member name="sun_angle_min" type="float" setter="set_sun_angle_min" getter="get_sun_angle_min" default="1.0">
Distance from sun where it goes from solid to starting to fade.
</member>
<member name="sun_color" type="Color" setter="set_sun_color" getter="get_sun_color" default="Color( 1, 1, 1, 1 )">
The sun's color.
</member>
<member name="sun_curve" type="float" setter="set_sun_curve" getter="get_sun_curve" default="0.05">
How quickly the sun fades away between [member sun_angle_min] and [member sun_angle_max].
</member>
<member name="sun_energy" type="float" setter="set_sun_energy" getter="get_sun_energy" default="1.0">
Amount of energy contribution from the sun.
</member>
<member name="sun_latitude" type="float" setter="set_sun_latitude" getter="get_sun_latitude" default="35.0">
The sun's height using polar coordinates.
</member>
<member name="sun_longitude" type="float" setter="set_sun_longitude" getter="get_sun_longitude" default="0.0">
The direction of the sun using polar coordinates.
</member>
<member name="texture_size" type="int" setter="set_texture_size" getter="get_texture_size" enum="ProceduralSky.TextureSize" default="2">
Size of [Texture2D] that the ProceduralSky will generate. The size is set using [enum TextureSize].
</member>
</members>
<constants>
<constant name="TEXTURE_SIZE_256" value="0" enum="TextureSize">
Sky texture will be 256x128.
</constant>
<constant name="TEXTURE_SIZE_512" value="1" enum="TextureSize">
Sky texture will be 512x256.
</constant>
<constant name="TEXTURE_SIZE_1024" value="2" enum="TextureSize">
Sky texture will be 1024x512. This is the default size.
</constant>
<constant name="TEXTURE_SIZE_2048" value="3" enum="TextureSize">
Sky texture will be 2048x1024.
</constant>
<constant name="TEXTURE_SIZE_4096" value="4" enum="TextureSize">
Sky texture will be 4096x2048.
</constant>
<constant name="TEXTURE_SIZE_MAX" value="5" enum="TextureSize">
Represents the size of the [enum TextureSize] enum.
</constant>
</constants>
</class>

View file

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="ProceduralSkyMaterial" inherits="Material" version="4.0">
<brief_description>
A [Material] used with [Sky] to generate a background based on user input parameters.
</brief_description>
<description>
ProceduralSkyMaterial provides a way to create an effective background quickly by defining procedural parameters for the sun, the sky and the ground. The sky and ground are very similar, they are defined by a color at the horizon, another color, and finally an easing curve to interpolate between these two colors. Similarly, the sun is described by a position in the sky, a color, and an easing curve. However, the sun also defines a minimum and maximum angle, these two values define at what distance the easing curve begins and ends from the sun, and thus end up defining the size of the sun in the sky.
The [ProceduralSkyMaterial] uses a lightweight shader to draw the sky and is thus suited for real time updates. When you do not need a quick sky that is not realistic, this is a good option.
The [ProceduralSkyMaterial] supports up to 4 suns. Each sun takes its color, energy, and direction from the corresponding [DirectionalLight] in the scene.
</description>
<tutorials>
</tutorials>
<methods>
</methods>
<members>
<member name="ground_bottom_color" type="Color" setter="set_ground_bottom_color" getter="get_ground_bottom_color" default="Color( 0.12, 0.12, 0.13, 1 )">
Color of the ground at the bottom. Blends with [member ground_horizon_color].
</member>
<member name="ground_curve" type="float" setter="set_ground_curve" getter="get_ground_curve" default="0.02">
How quickly the [member ground_horizon_color] fades into the [member ground_bottom_color].
</member>
<member name="ground_energy" type="float" setter="set_ground_energy" getter="get_ground_energy" default="1.0">
Amount of energy contribution from the ground.
</member>
<member name="ground_horizon_color" type="Color" setter="set_ground_horizon_color" getter="get_ground_horizon_color" default="Color( 0.37, 0.33, 0.31, 1 )">
Color of the ground at the horizon. Blends with [member ground_bottom_color].
</member>
<member name="sky_curve" type="float" setter="set_sky_curve" getter="get_sky_curve" default="0.09">
How quickly the [member sky_horizon_color] fades into the [member sky_top_color].
</member>
<member name="sky_energy" type="float" setter="set_sky_energy" getter="get_sky_energy" default="1.0">
Amount of energy contribution from the sky.
</member>
<member name="sky_horizon_color" type="Color" setter="set_sky_horizon_color" getter="get_sky_horizon_color" default="Color( 0.55, 0.69, 0.81, 1 )">
Color of the sky at the horizon. Blends with [member sky_top_color].
</member>
<member name="sky_top_color" type="Color" setter="set_sky_top_color" getter="get_sky_top_color" default="Color( 0.35, 0.46, 0.71, 1 )">
Color of the sky at the top. Blends with [member sky_horizon_color].
</member>
<member name="sun_angle_max" type="float" setter="set_sun_angle_max" getter="get_sun_angle_max" default="100.0">
Distance from center of sun where it fades out completely.
</member>
<member name="sun_angle_min" type="float" setter="set_sun_angle_min" getter="get_sun_angle_min" default="1.0">
Distance from sun where it goes from solid to starting to fade.
</member>
<member name="sun_curve" type="float" setter="set_sun_curve" getter="get_sun_curve" default="0.05">
How quickly the sun fades away between [member sun_angle_min] and [member sun_angle_max].
</member>
</members>
<constants>
</constants>
</class>

View file

@ -1036,7 +1036,7 @@
<member name="rendering/quality/reflection_atlas/reflection_count" type="int" setter="" getter="" default="64">
Number of cubemaps to store in the reflection atlas. The number of [ReflectionProbe]s in a scene will be limited by this amount. A higher number requires more VRAM.
</member>
<member name="rendering/quality/reflection_atlas/reflection_size" type="int" setter="" getter="" default="128">
<member name="rendering/quality/reflection_atlas/reflection_size" type="int" setter="" getter="" default="256">
Size of cubemap faces for [ReflectionProbe]s. A higher number requires more VRAM and may make reflection probe updating slower.
</member>
<member name="rendering/quality/reflection_atlas/reflection_size.mobile" type="int" setter="" getter="" default="128">
@ -1051,7 +1051,7 @@
<member name="rendering/quality/reflections/ggx_samples.mobile" type="int" setter="" getter="" default="128">
Lower-end override for [member rendering/quality/reflections/ggx_samples] on mobile devices, due to performance concerns or driver support.
</member>
<member name="rendering/quality/reflections/roughness_layers" type="int" setter="" getter="" default="6">
<member name="rendering/quality/reflections/roughness_layers" type="int" setter="" getter="" default="8">
Limits the number of layers to use in radiance maps when using importance sampling. A lower number will be slightly faster and take up less VRAM.
</member>
<member name="rendering/quality/reflections/texture_array_reflections" type="bool" setter="" getter="" default="true">

View file

@ -66,5 +66,8 @@
<constant name="MODE_PARTICLES" value="2" enum="Mode">
Mode used to calculate particle information on a per-particle basis. Not used for drawing.
</constant>
<constant name="MODE_SKY" value="3" enum="Mode">
Mode used for drawing skies. Only works with shaders attached to [Sky] objects.
</constant>
</constants>
</class>

View file

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Sky" inherits="Resource" version="4.0">
<brief_description>
The base class for [PanoramaSky] and [ProceduralSky].
Background that uses a [Material] to draw a sky.
</brief_description>
<description>
The base class for [PanoramaSky] and [ProceduralSky].
The [Sky] class uses a [Material] to draw the background and update the reflection/radiance cubemaps.
</description>
<tutorials>
</tutorials>
@ -14,11 +14,14 @@
<member name="process_mode" type="int" setter="set_process_mode" getter="get_process_mode" enum="Sky.ProcessMode" default="0">
Sets the method for generating the radiance map from the sky. The radiance map is a cubemap with increasingly blurry versions of the sky corresponding to different levels of roughness. Radiance maps can be expensive to calculate. See [enum ProcessMode] for options.
</member>
<member name="radiance_size" type="int" setter="set_radiance_size" getter="get_radiance_size" enum="Sky.RadianceSize" default="2">
<member name="radiance_size" type="int" setter="set_radiance_size" getter="get_radiance_size" enum="Sky.RadianceSize" default="3">
The [Sky]'s radiance map size. The higher the radiance map size, the more detailed the lighting from the [Sky] will be.
See [enum RadianceSize] constants for values.
[b]Note:[/b] Some hardware will have trouble with higher radiance sizes, especially [constant RADIANCE_SIZE_512] and above. Only use such high values on high-end hardware.
</member>
<member name="sky_material" type="Material" setter="set_material" getter="get_material">
[Material] used to draw the background. Can be [PanoramaSkyMaterial], [ProceduralSkyMaterial], [PhysicalSkyMaterial], or even a [ShaderMaterial] if you want to use your own custom shader.
</member>
</members>
<constants>
<constant name="RADIANCE_SIZE_32" value="0" enum="RadianceSize">
@ -50,7 +53,7 @@
</constant>
<constant name="PROCESS_MODE_REALTIME" value="1" enum="ProcessMode">
Uses the fast filtering algorithm to process the radiance map. In general this results in lower quality, but substantially faster run times.
[b]Note:[/b] The fast filtering algorithm is limited to 128x128 cubemaps, so [member radiance_size] must be set to [constant RADIANCE_SIZE_128].
[b]Note:[/b] The fast filtering algorithm is limited to 256x256 cubemaps, so [member radiance_size] must be set to [constant RADIANCE_SIZE_256].
</constant>
</constants>
</class>

View file

@ -2744,14 +2744,15 @@
Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
</description>
</method>
<method name="sky_set_texture">
<method name="sky_set_material">
<return type="void">
</return>
<argument index="0" name="sky" type="RID">
</argument>
<argument index="1" name="panorama" type="RID">
<argument index="1" name="material" type="RID">
</argument>
<description>
Sets the material that the sky uses to render the background and reflection maps.
</description>
</method>
<method name="spot_light_create">
@ -3155,7 +3156,10 @@
<constant name="SHADER_PARTICLES" value="2" enum="ShaderMode">
Shader is a particle shader.
</constant>
<constant name="SHADER_MAX" value="3" enum="ShaderMode">
<constant name="SHADER_SKY" value="3" enum="ShaderMode">
Shader is a sky shader.
</constant>
<constant name="SHADER_MAX" value="4" enum="ShaderMode">
Represents the size of the [enum ShaderMode] enum.
</constant>
<constant name="ARRAY_VERTEX" value="0" enum="ArrayType">

View file

@ -58,6 +58,7 @@ public:
void sky_set_mode(RID p_sky, VS::SkyMode p_samples) {}
void sky_set_texture(RID p_sky, RID p_panorama) {}
void sky_set_texture(RID p_sky, RID p_cube_map, int p_radiance_size) {}
void sky_set_material(RID p_sky, RID p_material) {}
/* ENVIRONMENT API */
@ -67,7 +68,6 @@ public:
void environment_set_sky(RID p_env, RID p_sky) {}
void environment_set_sky_custom_fov(RID p_env, float p_scale) {}
void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) {}
void environment_set_bg_material(RID p_env, RID p_material) {}
void environment_set_bg_color(RID p_env, const Color &p_color) {}
void environment_set_bg_energy(RID p_env, float p_energy) {}
void environment_set_canvas_max_layer(RID p_env, int p_max_layer) {}
@ -314,6 +314,11 @@ public:
void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) {}
#endif
/* SKY API */
RID sky_create() { return RID(); }
void sky_set_texture(RID p_sky, RID p_cube_map, int p_radiance_size) {}
/* SHADER API */
RID shader_create() { return RID(); }

View file

@ -718,13 +718,6 @@ void RasterizerSceneGLES2::environment_set_sky_orientation(RID p_env, const Basi
env->sky_orientation = p_orientation;
}
void RasterizerSceneGLES2::environment_set_bg_material(RID p_env, RID p_material) {
Environment *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
env->bg_material = p_material;
}
void RasterizerSceneGLES2::environment_set_bg_color(RID p_env, const Color &p_color) {
Environment *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);

View file

@ -242,8 +242,6 @@ public:
float sky_custom_fov;
Basis sky_orientation;
RID bg_material;
Color bg_color;
float bg_energy;
float sky_ambient;
@ -359,7 +357,6 @@ public:
virtual void environment_set_sky(RID p_env, RID p_sky);
virtual void environment_set_sky_custom_fov(RID p_env, float p_scale);
virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation);
virtual void environment_set_bg_material(RID p_env, RID p_material);
virtual void environment_set_bg_color(RID p_env, const Color &p_color);
virtual void environment_set_bg_energy(RID p_env, float p_energy);
virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer);

View file

@ -6584,6 +6584,18 @@ EditorNode::EditorNode() {
particles_mat_convert.instance();
resource_conversion_plugins.push_back(particles_mat_convert);
Ref<ProceduralSkyMaterialConversionPlugin> procedural_sky_mat_convert;
procedural_sky_mat_convert.instance();
resource_conversion_plugins.push_back(procedural_sky_mat_convert);
Ref<PanoramaSkyMaterialConversionPlugin> panorama_sky_mat_convert;
panorama_sky_mat_convert.instance();
resource_conversion_plugins.push_back(panorama_sky_mat_convert);
Ref<PhysicalSkyMaterialConversionPlugin> physical_sky_mat_convert;
physical_sky_mat_convert.instance();
resource_conversion_plugins.push_back(physical_sky_mat_convert);
Ref<VisualShaderConversionPlugin> vshader_convert;
vshader_convert.instance();
resource_conversion_plugins.push_back(vshader_convert);

View file

@ -187,8 +187,7 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme =
exceptions.insert("EditorHandle");
exceptions.insert("Editor3DHandle");
exceptions.insert("Godot");
exceptions.insert("PanoramaSky");
exceptions.insert("ProceduralSky");
exceptions.insert("Sky");
exceptions.insert("EditorControlAnchor");
exceptions.insert("DefaultProjectIcon");
exceptions.insert("GuiCloseCustomizable");

1
editor/icons/Sky.svg Normal file
View file

@ -0,0 +1 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1040.4" y2="1050.4"><stop offset="0" stop-color="#1ec3ff"/><stop offset="1" stop-color="#b2e1ff"/></linearGradient><g transform="translate(0 -1037.4)"><path d="m8 1040.4a7 7 0 0 0 -7 7 7 7 0 0 0 .68555 3h12.631a7 7 0 0 0 .68359-3 7 7 0 0 0 -7-7z" fill="url(#a)"/><path d="m10 7c-.554 0-1 .446-1 1h-1c-.554 0-1 .446-1 1s.446 1 1 1h2c.554 0 1-.446 1-1h1c.554 0 1-.446 1-1s-.446-1-1-1zm-7 3c-.554 0-1 .446-1 1s.446 1 1 1h1c.554 0 1-.446 1-1s-.446-1-1-1z" fill="#fff" transform="translate(0 1037.4)"/></g></svg>

After

Width:  |  Height:  |  Size: 705 B

View file

@ -33,6 +33,7 @@
#include "editor/editor_scale.h"
#include "scene/gui/viewport_container.h"
#include "scene/resources/particles_material.h"
#include "scene/resources/sky_material.h"
void MaterialEditor::_notification(int p_what) {
@ -221,8 +222,8 @@ void EditorInspectorPluginMaterial::parse_begin(Object *p_object) {
EditorInspectorPluginMaterial::EditorInspectorPluginMaterial() {
env.instance();
Ref<ProceduralSky> proc_sky = memnew(ProceduralSky(true));
env->set_sky(proc_sky);
Ref<Sky> sky = memnew(Sky());
env->set_sky(sky);
env->set_background(Environment::BG_COLOR);
env->set_ambient_source(Environment::AMBIENT_SOURCE_SKY);
env->set_reflection_source(Environment::REFLECTION_SOURCE_SKY);
@ -356,3 +357,117 @@ Ref<Resource> CanvasItemMaterialConversionPlugin::convert(const Ref<Resource> &p
smat->set_render_priority(mat->get_render_priority());
return smat;
}
String ProceduralSkyMaterialConversionPlugin::converts_to() const {
return "ShaderMaterial";
}
bool ProceduralSkyMaterialConversionPlugin::handles(const Ref<Resource> &p_resource) const {
Ref<ProceduralSkyMaterial> mat = p_resource;
return mat.is_valid();
}
Ref<Resource> ProceduralSkyMaterialConversionPlugin::convert(const Ref<Resource> &p_resource) const {
Ref<ProceduralSkyMaterial> mat = p_resource;
ERR_FAIL_COND_V(!mat.is_valid(), Ref<Resource>());
Ref<ShaderMaterial> smat;
smat.instance();
Ref<Shader> shader;
shader.instance();
String code = VS::get_singleton()->shader_get_code(mat->get_shader_rid());
shader->set_code(code);
smat->set_shader(shader);
List<PropertyInfo> params;
VS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), &params);
for (List<PropertyInfo>::Element *E = params.front(); E; E = E->next()) {
Variant value = VS::get_singleton()->material_get_param(mat->get_rid(), E->get().name);
smat->set_shader_param(E->get().name, value);
}
smat->set_render_priority(mat->get_render_priority());
return smat;
}
String PanoramaSkyMaterialConversionPlugin::converts_to() const {
return "ShaderMaterial";
}
bool PanoramaSkyMaterialConversionPlugin::handles(const Ref<Resource> &p_resource) const {
Ref<PanoramaSkyMaterial> mat = p_resource;
return mat.is_valid();
}
Ref<Resource> PanoramaSkyMaterialConversionPlugin::convert(const Ref<Resource> &p_resource) const {
Ref<PanoramaSkyMaterial> mat = p_resource;
ERR_FAIL_COND_V(!mat.is_valid(), Ref<Resource>());
Ref<ShaderMaterial> smat;
smat.instance();
Ref<Shader> shader;
shader.instance();
String code = VS::get_singleton()->shader_get_code(mat->get_shader_rid());
shader->set_code(code);
smat->set_shader(shader);
List<PropertyInfo> params;
VS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), &params);
for (List<PropertyInfo>::Element *E = params.front(); E; E = E->next()) {
Variant value = VS::get_singleton()->material_get_param(mat->get_rid(), E->get().name);
smat->set_shader_param(E->get().name, value);
}
smat->set_render_priority(mat->get_render_priority());
return smat;
}
String PhysicalSkyMaterialConversionPlugin::converts_to() const {
return "ShaderMaterial";
}
bool PhysicalSkyMaterialConversionPlugin::handles(const Ref<Resource> &p_resource) const {
Ref<PhysicalSkyMaterial> mat = p_resource;
return mat.is_valid();
}
Ref<Resource> PhysicalSkyMaterialConversionPlugin::convert(const Ref<Resource> &p_resource) const {
Ref<PhysicalSkyMaterial> mat = p_resource;
ERR_FAIL_COND_V(!mat.is_valid(), Ref<Resource>());
Ref<ShaderMaterial> smat;
smat.instance();
Ref<Shader> shader;
shader.instance();
String code = VS::get_singleton()->shader_get_code(mat->get_shader_rid());
shader->set_code(code);
smat->set_shader(shader);
List<PropertyInfo> params;
VS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), &params);
for (List<PropertyInfo>::Element *E = params.front(); E; E = E->next()) {
Variant value = VS::get_singleton()->material_get_param(mat->get_rid(), E->get().name);
smat->set_shader_param(E->get().name, value);
}
smat->set_render_priority(mat->get_render_priority());
return smat;
}

View file

@ -127,4 +127,31 @@ public:
virtual Ref<Resource> convert(const Ref<Resource> &p_resource) const;
};
class ProceduralSkyMaterialConversionPlugin : public EditorResourceConversionPlugin {
GDCLASS(ProceduralSkyMaterialConversionPlugin, EditorResourceConversionPlugin);
public:
virtual String converts_to() const;
virtual bool handles(const Ref<Resource> &p_resource) const;
virtual Ref<Resource> convert(const Ref<Resource> &p_resource) const;
};
class PanoramaSkyMaterialConversionPlugin : public EditorResourceConversionPlugin {
GDCLASS(PanoramaSkyMaterialConversionPlugin, EditorResourceConversionPlugin);
public:
virtual String converts_to() const;
virtual bool handles(const Ref<Resource> &p_resource) const;
virtual Ref<Resource> convert(const Ref<Resource> &p_resource) const;
};
class PhysicalSkyMaterialConversionPlugin : public EditorResourceConversionPlugin {
GDCLASS(PhysicalSkyMaterialConversionPlugin, EditorResourceConversionPlugin);
public:
virtual String converts_to() const;
virtual bool handles(const Ref<Resource> &p_resource) const;
virtual Ref<Resource> convert(const Ref<Resource> &p_resource) const;
};
#endif // MATERIAL_EDITOR_PLUGIN_H

View file

@ -505,7 +505,7 @@ private:
set_message(TTR("Couldn't create project.godot in project path."), MESSAGE_ERROR);
} else {
f->store_line("[gd_resource type=\"Environment\" load_steps=2 format=2]");
f->store_line("[sub_resource type=\"ProceduralSky\" id=1]");
f->store_line("[sub_resource type=\"Sky\" id=1]");
f->store_line("[resource]");
f->store_line("background_mode = 2");
f->store_line("background_sky = SubResource( 1 )");

View file

@ -610,8 +610,9 @@ void register_scene_types() {
SceneTree::add_idle_callback(ParticlesMaterial::flush_changes);
ParticlesMaterial::init_shaders();
ClassDB::register_class<SkyMaterial>();
SkyMaterial::init_shaders();
ClassDB::register_class<ProceduralSkyMaterial>();
ClassDB::register_class<PanoramaSkyMaterial>();
ClassDB::register_class<PhysicalSkyMaterial>();
ClassDB::register_virtual_class<Mesh>();
ClassDB::register_class<ArrayMesh>();
@ -663,9 +664,7 @@ void register_scene_types() {
ClassDB::register_class<World2D>();
ClassDB::register_virtual_class<Texture>();
ClassDB::register_virtual_class<Texture2D>();
ClassDB::register_virtual_class<Sky>();
ClassDB::register_class<PanoramaSky>();
ClassDB::register_class<ProceduralSky>();
ClassDB::register_class<Sky>();
ClassDB::register_class<StreamTexture>();
ClassDB::register_class<ImageTexture>();
ClassDB::register_class<AtlasTexture>();

View file

@ -56,17 +56,6 @@ void Environment::set_sky(const Ref<Sky> &p_sky) {
VS::get_singleton()->environment_set_sky(environment, sb_rid);
}
void Environment::set_bg_material(const Ref<Material> &p_material) {
bg_material = p_material;
RID mb_rid;
if (bg_material.is_valid())
mb_rid = bg_material->get_rid();
VS::get_singleton()->environment_set_bg_material(environment, mb_rid);
}
void Environment::set_sky_custom_fov(float p_scale) {
bg_sky_custom_fov = p_scale;
@ -151,11 +140,6 @@ Vector3 Environment::get_sky_rotation() const {
return sky_rotation;
}
Ref<Material> Environment::get_bg_material() const {
return bg_material;
}
Color Environment::get_bg_color() const {
return bg_color;
@ -322,13 +306,6 @@ Ref<Texture2D> Environment::get_adjustment_color_correction() const {
void Environment::_validate_property(PropertyInfo &property) const {
if (property.name == "background_material") {
if (bg_mode != BG_SKY) {
property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
}
}
// TODO: We are retiring sky in favour of a background material that implements the sky. These properties will become part of the sky material
if (property.name == "sky" || property.name == "sky_custom_fov" || property.name == "sky_rotation" || property.name == "ambient_light/sky_contribution") {
if (bg_mode != BG_SKY && ambient_source != AMBIENT_SOURCE_SKY && reflection_source != REFLECTION_SOURCE_SKY) {
property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
@ -357,7 +334,7 @@ void Environment::_validate_property(PropertyInfo &property) const {
if (property.name == "background_camera_feed_id") {
if (bg_mode != BG_CAMERA_FEED) {
property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
property.usage = PROPERTY_USAGE_NOEDITOR;
}
}
@ -862,7 +839,6 @@ void Environment::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_sky", "sky"), &Environment::set_sky);
ClassDB::bind_method(D_METHOD("set_sky_custom_fov", "scale"), &Environment::set_sky_custom_fov);
ClassDB::bind_method(D_METHOD("set_sky_rotation", "euler_radians"), &Environment::set_sky_rotation);
ClassDB::bind_method(D_METHOD("set_bg_material", "material"), &Environment::set_bg_material);
ClassDB::bind_method(D_METHOD("set_bg_color", "color"), &Environment::set_bg_color);
ClassDB::bind_method(D_METHOD("set_bg_energy", "energy"), &Environment::set_bg_energy);
ClassDB::bind_method(D_METHOD("set_canvas_max_layer", "layer"), &Environment::set_canvas_max_layer);
@ -877,7 +853,6 @@ void Environment::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_sky"), &Environment::get_sky);
ClassDB::bind_method(D_METHOD("get_sky_custom_fov"), &Environment::get_sky_custom_fov);
ClassDB::bind_method(D_METHOD("get_sky_rotation"), &Environment::get_sky_rotation);
ClassDB::bind_method(D_METHOD("get_bg_material"), &Environment::get_bg_material);
ClassDB::bind_method(D_METHOD("get_bg_color"), &Environment::get_bg_color);
ClassDB::bind_method(D_METHOD("get_bg_energy"), &Environment::get_bg_energy);
ClassDB::bind_method(D_METHOD("get_canvas_max_layer"), &Environment::get_canvas_max_layer);
@ -896,14 +871,10 @@ void Environment::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "background_camera_feed_id", PROPERTY_HINT_RANGE, "1,10,1"), "set_camera_feed_id", "get_camera_feed_id");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "background_color"), "set_bg_color", "get_bg_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "background_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_bg_energy", "get_bg_energy");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "background_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,SkyMaterial"), "set_bg_material", "get_bg_material");
// TODO: We are retiring sky in favour of a background material that implements the sky. These properties will become part of the sky material
ADD_GROUP("Sky", "sky_");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "sky", PROPERTY_HINT_RESOURCE_TYPE, "Sky"), "set_sky", "get_sky");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_custom_fov", PROPERTY_HINT_RANGE, "0,180,0.1"), "set_sky_custom_fov", "get_sky_custom_fov");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "sky_rotation"), "set_sky_rotation", "get_sky_rotation");
ADD_GROUP("Ambient Light", "ambient_light_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "ambient_light_source", PROPERTY_HINT_ENUM, "Background,Disabled,Color,Sky"), "set_ambient_source", "get_ambient_source");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ambient_light_color"), "set_ambient_light_color", "get_ambient_light_color");

View file

@ -34,7 +34,6 @@
#include "core/resource.h"
#include "scene/resources/sky.h"
#include "scene/resources/texture.h"
#include "scene/resources/material.h"
#include "servers/visual_server.h"
class Environment : public Resource {
@ -93,8 +92,6 @@ private:
BGMode bg_mode;
Ref<Sky> bg_sky;
//@TODO for now introducing material but once it works we'll be replacing the current sky classes with material classes
Ref<Material> bg_material;
float bg_sky_custom_fov;
Vector3 sky_rotation;
Color bg_color;
@ -183,7 +180,6 @@ public:
void set_sky(const Ref<Sky> &p_sky);
void set_sky_custom_fov(float p_scale);
void set_sky_rotation(const Vector3 &p_rotation);
void set_bg_material(const Ref<Material> &p_material);
void set_bg_color(const Color &p_color);
void set_bg_energy(float p_energy);
void set_canvas_max_layer(int p_max_layer);
@ -200,7 +196,6 @@ public:
Ref<Sky> get_sky() const;
float get_sky_custom_fov() const;
Vector3 get_sky_rotation() const;
Ref<Material> get_bg_material() const;
Color get_bg_color() const;
float get_bg_energy() const;
int get_canvas_max_layer() const;

View file

@ -56,6 +56,18 @@ Sky::ProcessMode Sky::get_process_mode() const {
return mode;
}
void Sky::set_material(const Ref<Material> &p_material) {
sky_material = p_material;
RID material_rid;
if (sky_material.is_valid())
material_rid = sky_material->get_rid();
VS::get_singleton()->sky_set_material(sky, material_rid);
}
Ref<Material> Sky::get_material() const {
return sky_material;
}
RID Sky::get_rid() const {
return sky;
@ -69,6 +81,10 @@ void Sky::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_process_mode", "mode"), &Sky::set_process_mode);
ClassDB::bind_method(D_METHOD("get_process_mode"), &Sky::get_process_mode);
ClassDB::bind_method(D_METHOD("set_material", "material"), &Sky::set_material);
ClassDB::bind_method(D_METHOD("get_material"), &Sky::get_material);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "sky_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,PanoramaSkyMaterial,ProceduralSkyMaterial,PhysicalSkyMaterial"), "set_material", "get_material");
ADD_PROPERTY(PropertyInfo(Variant::INT, "radiance_size", PROPERTY_HINT_ENUM, "32,64,128,256,512,1024,2048"), "set_radiance_size", "get_radiance_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "HighQuality,RealTime"), "set_process_mode", "get_process_mode");
@ -87,500 +103,11 @@ void Sky::_bind_methods() {
Sky::Sky() {
mode = PROCESS_MODE_QUALITY;
radiance_size = RADIANCE_SIZE_128;
radiance_size = RADIANCE_SIZE_256;
sky = VS::get_singleton()->sky_create();
}
Sky::~Sky() {
VS::get_singleton()->free(sky);
}
/////////////////////////////////////////
void PanoramaSky::set_panorama(const Ref<Texture2D> &p_panorama) {
panorama = p_panorama;
RID rid = p_panorama.is_valid() ? p_panorama->get_rid() : RID();
VS::get_singleton()->sky_set_texture(get_rid(), rid);
}
Ref<Texture2D> PanoramaSky::get_panorama() const {
return panorama;
}
void PanoramaSky::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_panorama", "texture"), &PanoramaSky::set_panorama);
ClassDB::bind_method(D_METHOD("get_panorama"), &PanoramaSky::get_panorama);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "panorama", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_panorama", "get_panorama");
}
PanoramaSky::PanoramaSky() {
}
PanoramaSky::~PanoramaSky() {
}
//////////////////////////////////
Ref<Image> ProceduralSky::_generate_sky() {
update_queued = false;
Vector<uint8_t> imgdata;
static const int size[TEXTURE_SIZE_MAX] = {
256, 512, 1024, 2048, 4096
};
int w = size[texture_size];
int h = w / 2;
imgdata.resize(w * h * 4); //RGBE
{
uint8_t *dataw = imgdata.ptrw();
uint32_t *ptr = (uint32_t *)dataw;
Color sky_top_linear = sky_top_color.to_linear();
Color sky_horizon_linear = sky_horizon_color.to_linear();
Color ground_bottom_linear = ground_bottom_color.to_linear();
Color ground_horizon_linear = ground_horizon_color.to_linear();
Color sun_linear;
sun_linear.r = sun_color.r * sun_energy;
sun_linear.g = sun_color.g * sun_energy;
sun_linear.b = sun_color.b * sun_energy;
Vector3 sun(0, 0, -1);
sun = Basis(Vector3(1, 0, 0), Math::deg2rad(sun_latitude)).xform(sun);
sun = Basis(Vector3(0, 1, 0), Math::deg2rad(sun_longitude)).xform(sun);
sun.normalize();
for (int i = 0; i < w; i++) {
float u = float(i) / (w - 1);
float phi = u * 2.0 * Math_PI;
for (int j = 0; j < h; j++) {
float v = float(j) / (h - 1);
float theta = v * Math_PI;
Vector3 normal(
Math::sin(phi) * Math::sin(theta) * -1.0,
Math::cos(theta),
Math::cos(phi) * Math::sin(theta) * -1.0);
normal.normalize();
float v_angle = Math::acos(CLAMP(normal.y, -1.0, 1.0));
Color color;
if (normal.y < 0) {
//ground
float c = (v_angle - (Math_PI * 0.5)) / (Math_PI * 0.5);
color = ground_horizon_linear.linear_interpolate(ground_bottom_linear, Math::ease(c, ground_curve));
color.r *= ground_energy;
color.g *= ground_energy;
color.b *= ground_energy;
} else {
float c = v_angle / (Math_PI * 0.5);
color = sky_horizon_linear.linear_interpolate(sky_top_linear, Math::ease(1.0 - c, sky_curve));
color.r *= sky_energy;
color.g *= sky_energy;
color.b *= sky_energy;
float sun_angle = Math::rad2deg(Math::acos(CLAMP(sun.dot(normal), -1.0, 1.0)));
if (sun_angle < sun_angle_min) {
color = color.blend(sun_linear);
} else if (sun_angle < sun_angle_max) {
float c2 = (sun_angle - sun_angle_min) / (sun_angle_max - sun_angle_min);
c2 = Math::ease(c2, sun_curve);
color = color.blend(sun_linear).linear_interpolate(color, c2);
}
}
ptr[j * w + i] = color.to_rgbe9995();
}
}
}
Ref<Image> image;
image.instance();
image->create(w, h, false, Image::FORMAT_RGBE9995, imgdata);
return image;
}
void ProceduralSky::set_sky_top_color(const Color &p_sky_top) {
sky_top_color = p_sky_top;
_queue_update();
}
Color ProceduralSky::get_sky_top_color() const {
return sky_top_color;
}
void ProceduralSky::set_sky_horizon_color(const Color &p_sky_horizon) {
sky_horizon_color = p_sky_horizon;
_queue_update();
}
Color ProceduralSky::get_sky_horizon_color() const {
return sky_horizon_color;
}
void ProceduralSky::set_sky_curve(float p_curve) {
sky_curve = p_curve;
_queue_update();
}
float ProceduralSky::get_sky_curve() const {
return sky_curve;
}
void ProceduralSky::set_sky_energy(float p_energy) {
sky_energy = p_energy;
_queue_update();
}
float ProceduralSky::get_sky_energy() const {
return sky_energy;
}
void ProceduralSky::set_ground_bottom_color(const Color &p_ground_bottom) {
ground_bottom_color = p_ground_bottom;
_queue_update();
}
Color ProceduralSky::get_ground_bottom_color() const {
return ground_bottom_color;
}
void ProceduralSky::set_ground_horizon_color(const Color &p_ground_horizon) {
ground_horizon_color = p_ground_horizon;
_queue_update();
}
Color ProceduralSky::get_ground_horizon_color() const {
return ground_horizon_color;
}
void ProceduralSky::set_ground_curve(float p_curve) {
ground_curve = p_curve;
_queue_update();
}
float ProceduralSky::get_ground_curve() const {
return ground_curve;
}
void ProceduralSky::set_ground_energy(float p_energy) {
ground_energy = p_energy;
_queue_update();
}
float ProceduralSky::get_ground_energy() const {
return ground_energy;
}
void ProceduralSky::set_sun_color(const Color &p_sun) {
sun_color = p_sun;
_queue_update();
}
Color ProceduralSky::get_sun_color() const {
return sun_color;
}
void ProceduralSky::set_sun_latitude(float p_angle) {
sun_latitude = p_angle;
_queue_update();
}
float ProceduralSky::get_sun_latitude() const {
return sun_latitude;
}
void ProceduralSky::set_sun_longitude(float p_angle) {
sun_longitude = p_angle;
_queue_update();
}
float ProceduralSky::get_sun_longitude() const {
return sun_longitude;
}
void ProceduralSky::set_sun_angle_min(float p_angle) {
sun_angle_min = p_angle;
_queue_update();
}
float ProceduralSky::get_sun_angle_min() const {
return sun_angle_min;
}
void ProceduralSky::set_sun_angle_max(float p_angle) {
sun_angle_max = p_angle;
_queue_update();
}
float ProceduralSky::get_sun_angle_max() const {
return sun_angle_max;
}
void ProceduralSky::set_sun_curve(float p_curve) {
sun_curve = p_curve;
_queue_update();
}
float ProceduralSky::get_sun_curve() const {
return sun_curve;
}
void ProceduralSky::set_sun_energy(float p_energy) {
sun_energy = p_energy;
_queue_update();
}
float ProceduralSky::get_sun_energy() const {
return sun_energy;
}
void ProceduralSky::set_texture_size(TextureSize p_size) {
ERR_FAIL_INDEX(p_size, TEXTURE_SIZE_MAX);
texture_size = p_size;
_queue_update();
}
ProceduralSky::TextureSize ProceduralSky::get_texture_size() const {
return texture_size;
}
void ProceduralSky::_update_sky() {
bool use_thread = true;
if (first_time) {
use_thread = false;
first_time = false;
}
#ifdef NO_THREADS
use_thread = false;
#endif
if (use_thread) {
if (!sky_thread) {
sky_thread = Thread::create(_thread_function, this);
regen_queued = false;
} else {
regen_queued = true;
}
} else {
Ref<Image> image = _generate_sky();
if (texture.is_valid()) {
RID new_texture = VS::get_singleton()->texture_2d_create(image);
VS::get_singleton()->texture_replace(texture, new_texture);
} else {
texture = VS::get_singleton()->texture_2d_create(image);
}
VS::get_singleton()->sky_set_texture(get_rid(), texture);
}
}
void ProceduralSky::_queue_update() {
if (update_queued)
return;
update_queued = true;
call_deferred("_update_sky");
}
void ProceduralSky::_thread_done(const Ref<Image> &p_image) {
if (texture.is_valid()) {
RID new_texture = VS::get_singleton()->texture_2d_create(p_image);
VS::get_singleton()->texture_replace(texture, new_texture);
} else {
texture = VS::get_singleton()->texture_2d_create(p_image);
}
VS::get_singleton()->sky_set_texture(get_rid(), texture);
Thread::wait_to_finish(sky_thread);
memdelete(sky_thread);
sky_thread = NULL;
if (regen_queued) {
sky_thread = Thread::create(_thread_function, this);
regen_queued = false;
}
}
void ProceduralSky::_thread_function(void *p_ud) {
ProceduralSky *psky = (ProceduralSky *)p_ud;
psky->call_deferred("_thread_done", psky->_generate_sky());
}
void ProceduralSky::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update_sky"), &ProceduralSky::_update_sky);
ClassDB::bind_method(D_METHOD("set_sky_top_color", "color"), &ProceduralSky::set_sky_top_color);
ClassDB::bind_method(D_METHOD("get_sky_top_color"), &ProceduralSky::get_sky_top_color);
ClassDB::bind_method(D_METHOD("set_sky_horizon_color", "color"), &ProceduralSky::set_sky_horizon_color);
ClassDB::bind_method(D_METHOD("get_sky_horizon_color"), &ProceduralSky::get_sky_horizon_color);
ClassDB::bind_method(D_METHOD("set_sky_curve", "curve"), &ProceduralSky::set_sky_curve);
ClassDB::bind_method(D_METHOD("get_sky_curve"), &ProceduralSky::get_sky_curve);
ClassDB::bind_method(D_METHOD("set_sky_energy", "energy"), &ProceduralSky::set_sky_energy);
ClassDB::bind_method(D_METHOD("get_sky_energy"), &ProceduralSky::get_sky_energy);
ClassDB::bind_method(D_METHOD("set_ground_bottom_color", "color"), &ProceduralSky::set_ground_bottom_color);
ClassDB::bind_method(D_METHOD("get_ground_bottom_color"), &ProceduralSky::get_ground_bottom_color);
ClassDB::bind_method(D_METHOD("set_ground_horizon_color", "color"), &ProceduralSky::set_ground_horizon_color);
ClassDB::bind_method(D_METHOD("get_ground_horizon_color"), &ProceduralSky::get_ground_horizon_color);
ClassDB::bind_method(D_METHOD("set_ground_curve", "curve"), &ProceduralSky::set_ground_curve);
ClassDB::bind_method(D_METHOD("get_ground_curve"), &ProceduralSky::get_ground_curve);
ClassDB::bind_method(D_METHOD("set_ground_energy", "energy"), &ProceduralSky::set_ground_energy);
ClassDB::bind_method(D_METHOD("get_ground_energy"), &ProceduralSky::get_ground_energy);
ClassDB::bind_method(D_METHOD("set_sun_color", "color"), &ProceduralSky::set_sun_color);
ClassDB::bind_method(D_METHOD("get_sun_color"), &ProceduralSky::get_sun_color);
ClassDB::bind_method(D_METHOD("set_sun_latitude", "degrees"), &ProceduralSky::set_sun_latitude);
ClassDB::bind_method(D_METHOD("get_sun_latitude"), &ProceduralSky::get_sun_latitude);
ClassDB::bind_method(D_METHOD("set_sun_longitude", "degrees"), &ProceduralSky::set_sun_longitude);
ClassDB::bind_method(D_METHOD("get_sun_longitude"), &ProceduralSky::get_sun_longitude);
ClassDB::bind_method(D_METHOD("set_sun_angle_min", "degrees"), &ProceduralSky::set_sun_angle_min);
ClassDB::bind_method(D_METHOD("get_sun_angle_min"), &ProceduralSky::get_sun_angle_min);
ClassDB::bind_method(D_METHOD("set_sun_angle_max", "degrees"), &ProceduralSky::set_sun_angle_max);
ClassDB::bind_method(D_METHOD("get_sun_angle_max"), &ProceduralSky::get_sun_angle_max);
ClassDB::bind_method(D_METHOD("set_sun_curve", "curve"), &ProceduralSky::set_sun_curve);
ClassDB::bind_method(D_METHOD("get_sun_curve"), &ProceduralSky::get_sun_curve);
ClassDB::bind_method(D_METHOD("set_sun_energy", "energy"), &ProceduralSky::set_sun_energy);
ClassDB::bind_method(D_METHOD("get_sun_energy"), &ProceduralSky::get_sun_energy);
ClassDB::bind_method(D_METHOD("set_texture_size", "size"), &ProceduralSky::set_texture_size);
ClassDB::bind_method(D_METHOD("get_texture_size"), &ProceduralSky::get_texture_size);
ClassDB::bind_method(D_METHOD("_thread_done", "image"), &ProceduralSky::_thread_done);
ADD_GROUP("Sky", "sky_");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_top_color"), "set_sky_top_color", "get_sky_top_color");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_horizon_color"), "set_sky_horizon_color", "get_sky_horizon_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_curve", PROPERTY_HINT_EXP_EASING), "set_sky_curve", "get_sky_curve");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_sky_energy", "get_sky_energy");
ADD_GROUP("Ground", "ground_");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_bottom_color"), "set_ground_bottom_color", "get_ground_bottom_color");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_horizon_color"), "set_ground_horizon_color", "get_ground_horizon_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ground_curve", PROPERTY_HINT_EXP_EASING), "set_ground_curve", "get_ground_curve");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ground_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_ground_energy", "get_ground_energy");
ADD_GROUP("Sun", "sun_");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sun_color"), "set_sun_color", "get_sun_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_latitude", PROPERTY_HINT_RANGE, "-180,180,0.01"), "set_sun_latitude", "get_sun_latitude");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_longitude", PROPERTY_HINT_RANGE, "-180,180,0.01"), "set_sun_longitude", "get_sun_longitude");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_angle_min", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_angle_min", "get_sun_angle_min");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_angle_max", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_angle_max", "get_sun_angle_max");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_curve", PROPERTY_HINT_EXP_EASING), "set_sun_curve", "get_sun_curve");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_sun_energy", "get_sun_energy");
ADD_GROUP("Texture2D", "texture_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_size", PROPERTY_HINT_ENUM, "256,512,1024,2048,4096"), "set_texture_size", "get_texture_size");
BIND_ENUM_CONSTANT(TEXTURE_SIZE_256);
BIND_ENUM_CONSTANT(TEXTURE_SIZE_512);
BIND_ENUM_CONSTANT(TEXTURE_SIZE_1024);
BIND_ENUM_CONSTANT(TEXTURE_SIZE_2048);
BIND_ENUM_CONSTANT(TEXTURE_SIZE_4096);
BIND_ENUM_CONSTANT(TEXTURE_SIZE_MAX);
}
ProceduralSky::ProceduralSky(bool p_desaturate) {
update_queued = false;
sky_top_color = Color::hex(0xa5d6f1ff);
sky_horizon_color = Color::hex(0xd6eafaff);
sky_curve = 0.09;
sky_energy = 1;
ground_bottom_color = Color::hex(0x282f36ff);
ground_horizon_color = Color::hex(0x6c655fff);
ground_curve = 0.02;
ground_energy = 1;
if (p_desaturate) {
sky_top_color.set_hsv(sky_top_color.get_h(), 0, sky_top_color.get_v());
sky_horizon_color.set_hsv(sky_horizon_color.get_h(), 0, sky_horizon_color.get_v());
ground_bottom_color.set_hsv(ground_bottom_color.get_h(), 0, ground_bottom_color.get_v());
ground_horizon_color.set_hsv(ground_horizon_color.get_h(), 0, ground_horizon_color.get_v());
}
sun_color = Color(1, 1, 1);
sun_latitude = 35;
sun_longitude = 0;
sun_angle_min = 1;
sun_angle_max = 100;
sun_curve = 0.05;
sun_energy = 1;
texture_size = TEXTURE_SIZE_1024;
sky_thread = NULL;
regen_queued = false;
first_time = true;
_queue_update();
}
ProceduralSky::~ProceduralSky() {
if (sky_thread) {
Thread::wait_to_finish(sky_thread);
memdelete(sky_thread);
sky_thread = NULL;
}
if (texture.is_valid()) {
VS::get_singleton()->free(texture);
}
}
}

View file

@ -32,6 +32,7 @@
#define SKY_H
#include "core/os/thread.h"
#include "scene/resources/material.h"
#include "scene/resources/texture.h"
class Sky : public Resource {
@ -58,6 +59,7 @@ private:
RID sky;
ProcessMode mode;
RadianceSize radiance_size;
Ref<Material> sky_material;
protected:
static void _bind_methods();
@ -69,6 +71,9 @@ public:
void set_process_mode(ProcessMode p_mode);
ProcessMode get_process_mode() const;
void set_material(const Ref<Material> &p_material);
Ref<Material> get_material() const;
virtual RID get_rid() const;
Sky();
@ -78,129 +83,4 @@ public:
VARIANT_ENUM_CAST(Sky::RadianceSize)
VARIANT_ENUM_CAST(Sky::ProcessMode)
class PanoramaSky : public Sky {
GDCLASS(PanoramaSky, Sky);
private:
Ref<Texture2D> panorama;
protected:
static void _bind_methods();
public:
void set_panorama(const Ref<Texture2D> &p_panorama);
Ref<Texture2D> get_panorama() const;
PanoramaSky();
~PanoramaSky();
};
class ProceduralSky : public Sky {
GDCLASS(ProceduralSky, Sky);
public:
enum TextureSize {
TEXTURE_SIZE_256,
TEXTURE_SIZE_512,
TEXTURE_SIZE_1024,
TEXTURE_SIZE_2048,
TEXTURE_SIZE_4096,
TEXTURE_SIZE_MAX
};
private:
Thread *sky_thread;
Color sky_top_color;
Color sky_horizon_color;
float sky_curve;
float sky_energy;
Color ground_bottom_color;
Color ground_horizon_color;
float ground_curve;
float ground_energy;
Color sun_color;
float sun_latitude;
float sun_longitude;
float sun_angle_min;
float sun_angle_max;
float sun_curve;
float sun_energy;
TextureSize texture_size;
RID texture;
bool update_queued;
bool regen_queued;
bool first_time;
void _thread_done(const Ref<Image> &p_image);
static void _thread_function(void *p_ud);
protected:
static void _bind_methods();
Ref<Image> _generate_sky();
void _update_sky();
void _queue_update();
public:
void set_sky_top_color(const Color &p_sky_top);
Color get_sky_top_color() const;
void set_sky_horizon_color(const Color &p_sky_horizon);
Color get_sky_horizon_color() const;
void set_sky_curve(float p_curve);
float get_sky_curve() const;
void set_sky_energy(float p_energy);
float get_sky_energy() const;
void set_ground_bottom_color(const Color &p_ground_bottom);
Color get_ground_bottom_color() const;
void set_ground_horizon_color(const Color &p_ground_horizon);
Color get_ground_horizon_color() const;
void set_ground_curve(float p_curve);
float get_ground_curve() const;
void set_ground_energy(float p_energy);
float get_ground_energy() const;
void set_sun_color(const Color &p_sun);
Color get_sun_color() const;
void set_sun_latitude(float p_angle);
float get_sun_latitude() const;
void set_sun_longitude(float p_angle);
float get_sun_longitude() const;
void set_sun_angle_min(float p_angle);
float get_sun_angle_min() const;
void set_sun_angle_max(float p_angle);
float get_sun_angle_max() const;
void set_sun_curve(float p_curve);
float get_sun_curve() const;
void set_sun_energy(float p_energy);
float get_sun_energy() const;
void set_texture_size(TextureSize p_size);
TextureSize get_texture_size() const;
ProceduralSky(bool p_desaturate = false);
~ProceduralSky();
};
VARIANT_ENUM_CAST(ProceduralSky::TextureSize)
#endif // SKY_H

View file

@ -30,162 +30,597 @@
#include "sky_material.h"
Mutex *SkyMaterial::material_mutex = NULL;
SelfList<SkyMaterial>::List *SkyMaterial::dirty_materials = NULL;
Map<SkyMaterial::MaterialKey, SkyMaterial::ShaderData> SkyMaterial::shader_map;
SkyMaterial::ShaderNames *SkyMaterial::shader_names = NULL;
void ProceduralSkyMaterial::set_sky_top_color(const Color &p_sky_top) {
void SkyMaterial::init_shaders() {
#ifndef NO_THREADS
material_mutex = Mutex::create();
#endif
dirty_materials = memnew(SelfList<SkyMaterial>::List);
shader_names = memnew(ShaderNames);
shader_names->placeholder = "placeholder";
sky_top_color = p_sky_top;
VS::get_singleton()->material_set_param(_get_material(), "sky_top_color", sky_top_color.to_linear());
}
void SkyMaterial::finish_shaders() {
Color ProceduralSkyMaterial::get_sky_top_color() const {
#ifndef NO_THREADS
memdelete(material_mutex);
#endif
memdelete(dirty_materials);
dirty_materials = NULL;
memdelete(shader_names);
return sky_top_color;
}
void SkyMaterial::_update_shader() {
void ProceduralSkyMaterial::set_sky_horizon_color(const Color &p_sky_horizon) {
dirty_materials->remove(&element);
sky_horizon_color = p_sky_horizon;
VS::get_singleton()->material_set_param(_get_material(), "sky_horizon_color", sky_horizon_color.to_linear());
}
Color ProceduralSkyMaterial::get_sky_horizon_color() const {
MaterialKey mk = _compute_key();
if (mk.key == current_key.key)
return; //no update required in the end
if (shader_map.has(current_key)) {
shader_map[current_key].users--;
if (shader_map[current_key].users == 0) {
//deallocate shader, as it's no longer in use
VS::get_singleton()->free(shader_map[current_key].shader);
shader_map.erase(current_key);
}
}
current_key = mk;
if (shader_map.has(mk)) {
VS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader);
shader_map[mk].users++;
return;
}
//must create a shader!
String code = "shader_type sky;\n";
ShaderData shader_data;
shader_data.shader = VS::get_singleton()->shader_create();
shader_data.users = 1;
VS::get_singleton()->shader_set_code(shader_data.shader, code);
shader_map[mk] = shader_data;
VS::get_singleton()->material_set_shader(_get_material(), shader_data.shader);
return sky_horizon_color;
}
void SkyMaterial::flush_changes() {
void ProceduralSkyMaterial::set_sky_curve(float p_curve) {
if (material_mutex)
material_mutex->lock();
sky_curve = p_curve;
VS::get_singleton()->material_set_param(_get_material(), "sky_curve", sky_curve);
}
float ProceduralSkyMaterial::get_sky_curve() const {
while (dirty_materials->first()) {
dirty_materials->first()->self()->_update_shader();
}
if (material_mutex)
material_mutex->unlock();
return sky_curve;
}
void SkyMaterial::_queue_shader_change() {
void ProceduralSkyMaterial::set_sky_energy(float p_energy) {
if (material_mutex)
material_mutex->lock();
sky_energy = p_energy;
VS::get_singleton()->material_set_param(_get_material(), "sky_energy", sky_energy);
}
float ProceduralSkyMaterial::get_sky_energy() const {
if (!element.in_list()) {
dirty_materials->add(&element);
}
if (material_mutex)
material_mutex->unlock();
return sky_energy;
}
bool SkyMaterial::_is_shader_dirty() const {
void ProceduralSkyMaterial::set_ground_bottom_color(const Color &p_ground_bottom) {
bool dirty = false;
ground_bottom_color = p_ground_bottom;
VS::get_singleton()->material_set_param(_get_material(), "ground_bottom_color", ground_bottom_color.to_linear());
}
Color ProceduralSkyMaterial::get_ground_bottom_color() const {
if (material_mutex)
material_mutex->lock();
dirty = element.in_list();
if (material_mutex)
material_mutex->unlock();
return dirty;
return ground_bottom_color;
}
void ProceduralSkyMaterial::set_ground_horizon_color(const Color &p_ground_horizon) {
RID SkyMaterial::get_shader_rid() const {
ground_horizon_color = p_ground_horizon;
VS::get_singleton()->material_set_param(_get_material(), "ground_horizon_color", ground_horizon_color.to_linear());
}
Color ProceduralSkyMaterial::get_ground_horizon_color() const {
ERR_FAIL_COND_V(!shader_map.has(current_key), RID());
return shader_map[current_key].shader;
return ground_horizon_color;
}
void SkyMaterial::_validate_property(PropertyInfo &property) const {
void ProceduralSkyMaterial::set_ground_curve(float p_curve) {
ground_curve = p_curve;
VS::get_singleton()->material_set_param(_get_material(), "ground_curve", ground_curve);
}
float ProceduralSkyMaterial::get_ground_curve() const {
return ground_curve;
}
Shader::Mode SkyMaterial::get_shader_mode() const {
void ProceduralSkyMaterial::set_ground_energy(float p_energy) {
ground_energy = p_energy;
VS::get_singleton()->material_set_param(_get_material(), "ground_energy", ground_energy);
}
float ProceduralSkyMaterial::get_ground_energy() const {
return ground_energy;
}
void ProceduralSkyMaterial::set_sun_angle_min(float p_angle) {
sun_angle_min = p_angle;
VS::get_singleton()->material_set_param(_get_material(), "sun_angle_min", Math::deg2rad(sun_angle_min));
}
float ProceduralSkyMaterial::get_sun_angle_min() const {
return sun_angle_min;
}
void ProceduralSkyMaterial::set_sun_angle_max(float p_angle) {
sun_angle_max = p_angle;
VS::get_singleton()->material_set_param(_get_material(), "sun_angle_max", Math::deg2rad(sun_angle_max));
}
float ProceduralSkyMaterial::get_sun_angle_max() const {
return sun_angle_max;
}
void ProceduralSkyMaterial::set_sun_curve(float p_curve) {
sun_curve = p_curve;
VS::get_singleton()->material_set_param(_get_material(), "sun_curve", sun_curve);
}
float ProceduralSkyMaterial::get_sun_curve() const {
return sun_curve;
}
bool ProceduralSkyMaterial::_can_do_next_pass() const {
return false;
}
Shader::Mode ProceduralSkyMaterial::get_shader_mode() const {
return Shader::MODE_SKY;
}
void SkyMaterial::_bind_methods() {
RID ProceduralSkyMaterial::get_shader_rid() const {
return shader;
}
SkyMaterial::SkyMaterial() :
element(this) {
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);
_queue_shader_change();
ClassDB::bind_method(D_METHOD("set_sky_horizon_color", "color"), &ProceduralSkyMaterial::set_sky_horizon_color);
ClassDB::bind_method(D_METHOD("get_sky_horizon_color"), &ProceduralSkyMaterial::get_sky_horizon_color);
ClassDB::bind_method(D_METHOD("set_sky_curve", "curve"), &ProceduralSkyMaterial::set_sky_curve);
ClassDB::bind_method(D_METHOD("get_sky_curve"), &ProceduralSkyMaterial::get_sky_curve);
ClassDB::bind_method(D_METHOD("set_sky_energy", "energy"), &ProceduralSkyMaterial::set_sky_energy);
ClassDB::bind_method(D_METHOD("get_sky_energy"), &ProceduralSkyMaterial::get_sky_energy);
ClassDB::bind_method(D_METHOD("set_ground_bottom_color", "color"), &ProceduralSkyMaterial::set_ground_bottom_color);
ClassDB::bind_method(D_METHOD("get_ground_bottom_color"), &ProceduralSkyMaterial::get_ground_bottom_color);
ClassDB::bind_method(D_METHOD("set_ground_horizon_color", "color"), &ProceduralSkyMaterial::set_ground_horizon_color);
ClassDB::bind_method(D_METHOD("get_ground_horizon_color"), &ProceduralSkyMaterial::get_ground_horizon_color);
ClassDB::bind_method(D_METHOD("set_ground_curve", "curve"), &ProceduralSkyMaterial::set_ground_curve);
ClassDB::bind_method(D_METHOD("get_ground_curve"), &ProceduralSkyMaterial::get_ground_curve);
ClassDB::bind_method(D_METHOD("set_ground_energy", "energy"), &ProceduralSkyMaterial::set_ground_energy);
ClassDB::bind_method(D_METHOD("get_ground_energy"), &ProceduralSkyMaterial::get_ground_energy);
ClassDB::bind_method(D_METHOD("set_sun_angle_min", "degrees"), &ProceduralSkyMaterial::set_sun_angle_min);
ClassDB::bind_method(D_METHOD("get_sun_angle_min"), &ProceduralSkyMaterial::get_sun_angle_min);
ClassDB::bind_method(D_METHOD("set_sun_angle_max", "degrees"), &ProceduralSkyMaterial::set_sun_angle_max);
ClassDB::bind_method(D_METHOD("get_sun_angle_max"), &ProceduralSkyMaterial::get_sun_angle_max);
ClassDB::bind_method(D_METHOD("set_sun_curve", "curve"), &ProceduralSkyMaterial::set_sun_curve);
ClassDB::bind_method(D_METHOD("get_sun_curve"), &ProceduralSkyMaterial::get_sun_curve);
ADD_GROUP("Sky", "sky_");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_top_color"), "set_sky_top_color", "get_sky_top_color");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_horizon_color"), "set_sky_horizon_color", "get_sky_horizon_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_curve", PROPERTY_HINT_EXP_EASING), "set_sky_curve", "get_sky_curve");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_sky_energy", "get_sky_energy");
ADD_GROUP("Ground", "ground_");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_bottom_color"), "set_ground_bottom_color", "get_ground_bottom_color");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_horizon_color"), "set_ground_horizon_color", "get_ground_horizon_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ground_curve", PROPERTY_HINT_EXP_EASING), "set_ground_curve", "get_ground_curve");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ground_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_ground_energy", "get_ground_energy");
ADD_GROUP("Sun", "sun_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_angle_min", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_angle_min", "get_sun_angle_min");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_angle_max", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_angle_max", "get_sun_angle_max");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_curve", PROPERTY_HINT_EXP_EASING), "set_sun_curve", "get_sun_curve");
}
SkyMaterial::~SkyMaterial() {
ProceduralSkyMaterial::ProceduralSkyMaterial() {
if (material_mutex)
material_mutex->lock();
String code = "shader_type sky;\n\n";
if (shader_map.has(current_key)) {
shader_map[current_key].users--;
if (shader_map[current_key].users == 0) {
//deallocate shader, as it's no longer in use
VS::get_singleton()->free(shader_map[current_key].shader);
shader_map.erase(current_key);
}
code += "uniform vec4 sky_top_color : hint_color = vec4(0.35, 0.46, 0.71, 1.0);\n";
code += "uniform vec4 sky_horizon_color : hint_color = vec4(0.55, 0.69, 0.81, 1.0);\n";
code += "uniform float sky_curve : hint_range(0, 1) = 0.09;\n";
code += "uniform float sky_energy = 1.0;\n\n";
code += "uniform vec4 ground_bottom_color : hint_color = vec4(0.12, 0.12, 0.13, 1.0);\n";
code += "uniform vec4 ground_horizon_color : hint_color = vec4(0.37, 0.33, 0.31, 1.0);\n";
code += "uniform float ground_curve : hint_range(0, 1) = 0.02;\n";
code += "uniform float ground_energy = 1.0;\n\n";
code += "uniform float sun_angle_min = 0.01;\n";
code += "uniform float sun_angle_max = 1.0;\n";
code += "uniform float sun_curve : hint_range(0, 1) = 0.05;\n\n";
code += "const float PI = 3.1415926535897932384626433833;\n\n";
code += "void fragment() {\n";
code += "\tfloat v_angle = acos(clamp(EYEDIR.y, -1.0, 1.0));\n";
code += "\tfloat c = (1.0 - v_angle / (PI * 0.5));\n";
code += "\tvec3 sky = mix(sky_horizon_color.rgb, sky_top_color.rgb, clamp(1.0 - pow(1.0 - c, 1.0 / sky_curve), 0.0, 1.0));\n";
code += "\tsky *= sky_energy;\n";
code += "\tif (LIGHT0_ENABLED) {\n";
code += "\t\tfloat sun_angle = acos(dot(LIGHT0_DIRECTION, EYEDIR));\n";
code += "\t\tif (sun_angle < sun_angle_min) {\n";
code += "\t\t\tsky = LIGHT0_COLOR * LIGHT0_ENERGY;\n";
code += "\t\t} else if (sun_angle < sun_angle_max) {\n";
code += "\t\t\tfloat c2 = (sun_angle - sun_angle_min) / (sun_angle_max - sun_angle_min);\n";
code += "\t\t\tsky = mix(LIGHT0_COLOR * LIGHT0_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));\n";
code += "\t\t}\n";
code += "\t}\n";
code += "\tif (LIGHT1_ENABLED) {\n";
code += "\t\tfloat sun_angle = acos(dot(LIGHT1_DIRECTION, EYEDIR));\n";
code += "\t\tif (sun_angle < sun_angle_min) {\n";
code += "\t\t\tsky = LIGHT1_COLOR * LIGHT1_ENERGY;\n";
code += "\t\t} else if (sun_angle < sun_angle_max) {\n";
code += "\t\t\tfloat c2 = (sun_angle - sun_angle_min) / (sun_angle_max - sun_angle_min);\n";
code += "\t\t\tsky = mix(LIGHT1_COLOR * LIGHT1_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));\n";
code += "\t\t}\n";
code += "\t}\n";
code += "\tif (LIGHT2_ENABLED) {\n";
code += "\t\tfloat sun_angle = acos(dot(LIGHT2_DIRECTION, EYEDIR));\n";
code += "\t\tif (sun_angle < sun_angle_min) {\n";
code += "\t\t\tsky = LIGHT2_COLOR * LIGHT2_ENERGY;\n";
code += "\t\t} else if (sun_angle < sun_angle_max) {\n";
code += "\t\t\tfloat c2 = (sun_angle - sun_angle_min) / (sun_angle_max - sun_angle_min);\n";
code += "\t\t\tsky = mix(LIGHT2_COLOR * LIGHT2_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));\n";
code += "\t\t}\n";
code += "\t}\n";
code += "\tif (LIGHT3_ENABLED) {\n";
code += "\t\tfloat sun_angle = acos(dot(LIGHT3_DIRECTION, EYEDIR));\n";
code += "\t\tif (sun_angle < sun_angle_min) {\n";
code += "\t\t\tsky = LIGHT3_COLOR * LIGHT3_ENERGY;\n";
code += "\t\t} else if (sun_angle < sun_angle_max) {\n";
code += "\t\t\tfloat c2 = (sun_angle - sun_angle_min) / (sun_angle_max - sun_angle_min);\n";
code += "\t\t\tsky = mix(LIGHT3_COLOR * LIGHT3_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));\n";
code += "\t\t}\n";
code += "\t}\n";
code += "\tc = (v_angle - (PI * 0.5)) / (PI * 0.5);\n";
code += "\tvec3 ground = mix(ground_horizon_color.rgb, ground_bottom_color.rgb, clamp(1.0 - pow(1.0 - c, 1.0 / ground_curve), 0.0, 1.0));\n";
code += "\tground *= ground_energy;\n";
code += "\tCOLOR = mix(ground, sky, step(0.0, EYEDIR.y));\n";
code += "}\n";
VS::get_singleton()->material_set_shader(_get_material(), RID());
}
shader = VS::get_singleton()->shader_create();
if (material_mutex)
material_mutex->unlock();
VS::get_singleton()->shader_set_code(shader, code);
VS::get_singleton()->material_set_shader(_get_material(), shader);
set_sky_top_color(Color(0.35, 0.46, 0.71));
set_sky_horizon_color(Color(0.55, 0.69, 0.81));
set_sky_curve(0.09);
set_sky_energy(1.0);
set_ground_bottom_color(Color(0.12, 0.12, 0.13));
set_ground_horizon_color(Color(0.37, 0.33, 0.31));
set_ground_curve(0.02);
set_ground_energy(1.0);
set_sun_angle_min(1.0);
set_sun_angle_max(100.0);
set_sun_curve(0.05);
}
ProceduralSkyMaterial::~ProceduralSkyMaterial() {
}
/////////////////////////////////////////
/* PanoramaSkyMaterial */
void PanoramaSkyMaterial::set_panorama(const Ref<Texture2D> &p_panorama) {
panorama = p_panorama;
VS::get_singleton()->material_set_param(_get_material(), "source_panorama", panorama);
}
Ref<Texture2D> PanoramaSkyMaterial::get_panorama() const {
return panorama;
}
bool PanoramaSkyMaterial::_can_do_next_pass() const {
return false;
}
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);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "panorama", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_panorama", "get_panorama");
}
PanoramaSkyMaterial::PanoramaSkyMaterial() {
String code = "shader_type sky;\n\n";
code += "uniform sampler2D source_panorama : filter_linear;\n";
code += "void fragment() {\n";
code += "\tCOLOR = texture(source_panorama, SKY_COORDS).rgb;\n";
code += "}";
shader = VS::get_singleton()->shader_create();
VS::get_singleton()->shader_set_code(shader, code);
VS::get_singleton()->material_set_shader(_get_material(), shader);
}
PanoramaSkyMaterial::~PanoramaSkyMaterial() {
VS::get_singleton()->free(shader);
VS::get_singleton()->material_set_shader(_get_material(), RID());
}
//////////////////////////////////
/* PhysicalSkyMaterial */
void PhysicalSkyMaterial::set_rayleigh_coefficient(float p_rayleigh) {
rayleigh = p_rayleigh;
VS::get_singleton()->material_set_param(_get_material(), "rayleigh", rayleigh);
}
float PhysicalSkyMaterial::get_rayleigh_coefficient() const {
return rayleigh;
}
void PhysicalSkyMaterial::set_rayleigh_color(Color p_rayleigh_color) {
rayleigh_color = p_rayleigh_color;
VS::get_singleton()->material_set_param(_get_material(), "rayleigh_color", rayleigh_color);
}
Color PhysicalSkyMaterial::get_rayleigh_color() const {
return rayleigh_color;
}
void PhysicalSkyMaterial::set_mie_coefficient(float p_mie) {
mie = p_mie;
VS::get_singleton()->material_set_param(_get_material(), "mie", mie);
}
float PhysicalSkyMaterial::get_mie_coefficient() const {
return mie;
}
void PhysicalSkyMaterial::set_mie_eccentricity(float p_eccentricity) {
mie_eccentricity = p_eccentricity;
VS::get_singleton()->material_set_param(_get_material(), "mie_eccentricity", mie_eccentricity);
}
float PhysicalSkyMaterial::get_mie_eccentricity() const {
return mie_eccentricity;
}
void PhysicalSkyMaterial::set_mie_color(Color p_mie_color) {
mie_color = p_mie_color;
VS::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;
VS::get_singleton()->material_set_param(_get_material(), "turbidity", turbidity);
}
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;
VS::get_singleton()->material_set_param(_get_material(), "sun_disk_scale", sun_disk_scale);
}
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;
VS::get_singleton()->material_set_param(_get_material(), "ground_color", ground_color);
}
Color PhysicalSkyMaterial::get_ground_color() const {
return ground_color;
}
void PhysicalSkyMaterial::set_exposure(float p_exposure) {
exposure = p_exposure;
VS::get_singleton()->material_set_param(_get_material(), "exposure", exposure);
}
float PhysicalSkyMaterial::get_exposure() const {
return exposure;
}
void PhysicalSkyMaterial::set_dither_strength(float p_dither_strength) {
dither_strength = p_dither_strength;
VS::get_singleton()->material_set_param(_get_material(), "dither_strength", dither_strength);
}
float PhysicalSkyMaterial::get_dither_strength() const {
return dither_strength;
}
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);
ClassDB::bind_method(D_METHOD("set_rayleigh_color", "color"), &PhysicalSkyMaterial::set_rayleigh_color);
ClassDB::bind_method(D_METHOD("get_rayleigh_color"), &PhysicalSkyMaterial::get_rayleigh_color);
ClassDB::bind_method(D_METHOD("set_mie_coefficient", "mie"), &PhysicalSkyMaterial::set_mie_coefficient);
ClassDB::bind_method(D_METHOD("get_mie_coefficient"), &PhysicalSkyMaterial::get_mie_coefficient);
ClassDB::bind_method(D_METHOD("set_mie_eccentricity", "eccentricity"), &PhysicalSkyMaterial::set_mie_eccentricity);
ClassDB::bind_method(D_METHOD("get_mie_eccentricity"), &PhysicalSkyMaterial::get_mie_eccentricity);
ClassDB::bind_method(D_METHOD("set_mie_color", "color"), &PhysicalSkyMaterial::set_mie_color);
ClassDB::bind_method(D_METHOD("get_mie_color"), &PhysicalSkyMaterial::get_mie_color);
ClassDB::bind_method(D_METHOD("set_turbidity", "turbidity"), &PhysicalSkyMaterial::set_turbidity);
ClassDB::bind_method(D_METHOD("get_turbidity"), &PhysicalSkyMaterial::get_turbidity);
ClassDB::bind_method(D_METHOD("set_sun_disk_scale", "scale"), &PhysicalSkyMaterial::set_sun_disk_scale);
ClassDB::bind_method(D_METHOD("get_sun_disk_scale"), &PhysicalSkyMaterial::get_sun_disk_scale);
ClassDB::bind_method(D_METHOD("set_ground_color", "color"), &PhysicalSkyMaterial::set_ground_color);
ClassDB::bind_method(D_METHOD("get_ground_color"), &PhysicalSkyMaterial::get_ground_color);
ClassDB::bind_method(D_METHOD("set_exposure", "exposure"), &PhysicalSkyMaterial::set_exposure);
ClassDB::bind_method(D_METHOD("get_exposure"), &PhysicalSkyMaterial::get_exposure);
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);
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");
ADD_GROUP("Mie", "mie_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mie_coefficient", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_mie_coefficient", "get_mie_coefficient");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mie_eccentricity", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_mie_eccentricity", "get_mie_eccentricity");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "mie_color"), "set_mie_color", "get_mie_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "turbidity", PROPERTY_HINT_RANGE, "0,1000,0.01"), "set_turbidity", "get_turbidity");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_disk_scale", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_disk_scale", "get_sun_disk_scale");
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");
}
PhysicalSkyMaterial::PhysicalSkyMaterial() {
String code = "shader_type sky;\n\n";
code += "uniform float rayleigh : hint_range(0, 64) = 2.0;\n";
code += "uniform vec4 rayleigh_color : hint_color = vec4(0.056, 0.14, 0.3, 1.0);\n";
code += "uniform float mie : hint_range(0, 1) = 0.005;\n";
code += "uniform float mie_eccentricity : hint_range(-1, 1) = 0.8;\n";
code += "uniform vec4 mie_color : hint_color = vec4(0.36, 0.56, 0.82, 1.0);\n\n";
code += "uniform float turbidity : hint_range(0, 1000) = 10.0;\n";
code += "uniform float sun_disk_scale : hint_range(0, 360) = 1.0;\n";
code += "uniform vec4 ground_color : hint_color = vec4(1.0);\n";
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 += "const float PI = 3.141592653589793238462643383279502884197169;\n";
code += "const vec3 UP = vec3( 0.0, 1.0, 0.0 );\n\n";
code += "// Sun constants\n";
code += "const float SOL_SIZE = 0.00872663806;\n";
code += "const float SUN_ENERGY = 1000.0;\n\n";
code += "// optical length at zenith for molecules\n";
code += "const float rayleigh_zenith_size = 8.4e3;\n";
code += "const float mie_zenith_size = 1.25e3;\n\n";
code += "float henyey_greenstein(float cos_theta, float g) {\n";
code += "\tconst float k = 0.0795774715459;\n";
code += "\treturn k * (1.0 - g * g) / (pow(1.0 + g * g - 2.0 * g * cos_theta, 1.5));\n";
code += "}\n\n";
code += "// From: https://www.shadertoy.com/view/4sfGzS credit to iq\n";
code += "float hash(vec3 p) {\n";
code += "\tp = fract( p * 0.3183099 + 0.1 );\n";
code += "\tp *= 17.0;\n";
code += "\treturn fract(p.x * p.y * p.z * (p.x + p.y + p.z));\n";
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(SOL_SIZE * sun_disk_scale);\n";
code += "\tfloat sunAngularDiameterCos2 = cos(SOL_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 += "}\n";
shader = VS::get_singleton()->shader_create();
VS::get_singleton()->shader_set_code(shader, code);
VS::get_singleton()->material_set_shader(_get_material(), shader);
set_rayleigh_coefficient(2.0);
set_rayleigh_color(Color(0.056, 0.14, 0.3));
set_mie_coefficient(0.005);
set_mie_eccentricity(0.8);
set_mie_color(Color(0.36, 0.56, 0.82));
set_turbidity(10.0);
set_sun_disk_scale(1.0);
set_ground_color(Color(1.0, 1.0, 1.0));
set_exposure(0.1);
set_dither_strength(1.0);
}
PhysicalSkyMaterial::~PhysicalSkyMaterial() {
VS::get_singleton()->free(shader);
VS::get_singleton()->material_set_shader(_get_material(), RID());
}

View file

@ -34,98 +34,157 @@
#ifndef SKY_MATERIAL_H
#define SKY_MATERIAL_H
class SkyMaterial : public Material {
class ProceduralSkyMaterial : public Material {
GDCLASS(SkyMaterial, Material);
public:
GDCLASS(ProceduralSkyMaterial, Material);
private:
union MaterialKey {
Color sky_top_color;
Color sky_horizon_color;
float sky_curve;
float sky_energy;
struct {
uint32_t texture_mask : 16;
uint32_t texture_color : 1;
uint32_t flags : 4;
uint32_t emission_shape : 2;
uint32_t trail_size_texture : 1;
uint32_t trail_color_texture : 1;
uint32_t invalid_key : 1;
uint32_t has_emission_color : 1;
};
Color ground_bottom_color;
Color ground_horizon_color;
float ground_curve;
float ground_energy;
uint32_t key;
float sun_angle_min;
float sun_angle_max;
float sun_curve;
bool operator<(const MaterialKey &p_key) const {
return key < p_key.key;
}
};
struct ShaderData {
RID shader;
int users;
};
static Map<MaterialKey, ShaderData> shader_map;
MaterialKey current_key;
_FORCE_INLINE_ MaterialKey _compute_key() const {
MaterialKey mk;
mk.key = 0;
/*
for (int i = 0; i < PARAM_MAX; i++) {
if (tex_parameters[i].is_valid()) {
mk.texture_mask |= (1 << i);
}
}
for (int i = 0; i < FLAG_MAX; i++) {
if (flags[i]) {
mk.flags |= (1 << i);
}
}
mk.texture_color = color_ramp.is_valid() ? 1 : 0;
mk.emission_shape = emission_shape;
mk.trail_color_texture = trail_color_modifier.is_valid() ? 1 : 0;
mk.trail_size_texture = trail_size_modifier.is_valid() ? 1 : 0;
mk.has_emission_color = emission_shape >= EMISSION_SHAPE_POINTS && emission_color_texture.is_valid();
*/
return mk;
}
static Mutex *material_mutex;
static SelfList<SkyMaterial>::List *dirty_materials;
struct ShaderNames {
StringName placeholder;
};
static ShaderNames *shader_names;
SelfList<SkyMaterial> element;
void _update_shader();
_FORCE_INLINE_ void _queue_shader_change();
_FORCE_INLINE_ bool _is_shader_dirty() const;
RID shader;
protected:
static void _bind_methods();
virtual void _validate_property(PropertyInfo &property) const;
virtual bool _can_do_next_pass() const;
public:
static void init_shaders();
static void finish_shaders();
static void flush_changes();
void set_sky_top_color(const Color &p_sky_top);
Color get_sky_top_color() const;
RID get_shader_rid() const;
void set_sky_horizon_color(const Color &p_sky_horizon);
Color get_sky_horizon_color() const;
void set_sky_curve(float p_curve);
float get_sky_curve() const;
void set_sky_energy(float p_energy);
float get_sky_energy() const;
void set_ground_bottom_color(const Color &p_ground_bottom);
Color get_ground_bottom_color() const;
void set_ground_horizon_color(const Color &p_ground_horizon);
Color get_ground_horizon_color() const;
void set_ground_curve(float p_curve);
float get_ground_curve() const;
void set_ground_energy(float p_energy);
float get_ground_energy() const;
void set_sun_angle_min(float p_angle);
float get_sun_angle_min() const;
void set_sun_angle_max(float p_angle);
float get_sun_angle_max() const;
void set_sun_curve(float p_curve);
float get_sun_curve() const;
virtual Shader::Mode get_shader_mode() const;
RID get_shader_rid() const;
SkyMaterial();
~SkyMaterial();
ProceduralSkyMaterial();
~ProceduralSkyMaterial();
};
//////////////////////////////////////////////////////
/* PanoramaSkyMaterial */
class PanoramaSkyMaterial : public Material {
GDCLASS(PanoramaSkyMaterial, Material);
private:
Ref<Texture2D> panorama;
RID shader;
protected:
static void _bind_methods();
virtual bool _can_do_next_pass() const;
public:
void set_panorama(const Ref<Texture2D> &p_panorama);
Ref<Texture2D> get_panorama() const;
virtual Shader::Mode get_shader_mode() const;
RID get_shader_rid() const;
PanoramaSkyMaterial();
~PanoramaSkyMaterial();
};
//////////////////////////////////////////////////////
/* PanoramaSkyMaterial */
class PhysicalSkyMaterial : public Material {
GDCLASS(PhysicalSkyMaterial, Material);
private:
RID shader;
float rayleigh;
Color rayleigh_color;
float mie;
float mie_eccentricity;
Color mie_color;
float turbidity;
float sun_disk_scale;
Color ground_color;
float exposure;
float dither_strength;
protected:
static void _bind_methods();
virtual bool _can_do_next_pass() const;
public:
void set_rayleigh_coefficient(float p_rayleigh);
float get_rayleigh_coefficient() const;
void set_rayleigh_color(Color p_rayleigh_color);
Color get_rayleigh_color() const;
void set_turbidity(float p_turbidity);
float get_turbidity() const;
void set_mie_coefficient(float p_mie);
float get_mie_coefficient() const;
void set_mie_eccentricity(float p_eccentricity);
float get_mie_eccentricity() const;
void set_mie_color(Color p_mie_color);
Color get_mie_color() const;
void set_sun_disk_scale(float p_sun_disk_scale);
float get_sun_disk_scale() const;
void set_ground_color(Color p_ground_color);
Color get_ground_color() const;
void set_exposure(float p_exposure);
float get_exposure() const;
void set_dither_strength(float p_dither_strength);
float get_dither_strength() const;
virtual Shader::Mode get_shader_mode() const;
RID get_shader_rid() const;
PhysicalSkyMaterial();
~PhysicalSkyMaterial();
};
#endif /* !SKY_MATERIAL_H */

View file

@ -56,7 +56,7 @@ public:
virtual RID sky_create() = 0;
virtual void sky_set_radiance_size(RID p_sky, int p_radiance_size) = 0;
virtual void sky_set_mode(RID p_sky, VS::SkyMode p_samples) = 0;
virtual void sky_set_texture(RID p_sky, RID p_panorama) = 0;
virtual void sky_set_material(RID p_sky, RID p_material) = 0;
/* ENVIRONMENT API */
@ -66,7 +66,6 @@ public:
virtual void environment_set_sky(RID p_env, RID p_sky) = 0;
virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0;
virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) = 0;
virtual void environment_set_bg_material(RID p_env, RID p_material) = 0;
virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0;
virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0;
virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0;

View file

@ -248,32 +248,6 @@ void RasterizerEffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_framebuff
RD::get_singleton()->draw_list_end();
}
void RasterizerEffectsRD::cubemap_roughness(RID p_source_rd_texture, bool p_source_is_panorama, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size) {
zeromem(&roughness.push_constant, sizeof(CubemapRoughnessPushConstant));
roughness.push_constant.face_id = p_face_id > 9 ? 0 : p_face_id;
roughness.push_constant.roughness = p_roughness;
roughness.push_constant.sample_count = p_sample_count;
roughness.push_constant.use_direct_write = p_roughness == 0.0;
roughness.push_constant.face_size = p_size;
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, roughness.pipelines[p_source_is_panorama ? CUBEMAP_ROUGHNESS_SOURCE_PANORAMA : CUBEMAP_ROUGHNESS_SOURCE_CUBEMAP]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_framebuffer), 1);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &roughness.push_constant, sizeof(CubemapRoughnessPushConstant));
int x_groups = (p_size - 1) / 8 + 1;
int y_groups = (p_size - 1) / 8 + 1;
RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, p_face_id > 9 ? 6 : 1);
RD::get_singleton()->compute_list_end();
}
void RasterizerEffectsRD::make_mipmap(RID p_source_rd_texture, RID p_dest_framebuffer, const Vector2 &p_pixel_size) {
zeromem(&blur.push_constant, sizeof(BlurPushConstant));
@ -731,12 +705,38 @@ void RasterizerEffectsRD::roughness_limit(RID p_source_normal, RID p_roughness,
RD::get_singleton()->compute_list_end();
}
void RasterizerEffectsRD::cubemap_downsample(RID p_source_cubemap, bool p_source_is_panorama, RID p_dest_cubemap, const Size2i &p_size) {
void RasterizerEffectsRD::cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size) {
zeromem(&roughness.push_constant, sizeof(CubemapRoughnessPushConstant));
roughness.push_constant.face_id = p_face_id > 9 ? 0 : p_face_id;
roughness.push_constant.roughness = p_roughness;
roughness.push_constant.sample_count = p_sample_count;
roughness.push_constant.use_direct_write = p_roughness == 0.0;
roughness.push_constant.face_size = p_size;
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, roughness.pipeline);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_framebuffer), 1);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &roughness.push_constant, sizeof(CubemapRoughnessPushConstant));
int x_groups = (p_size - 1) / 8 + 1;
int y_groups = (p_size - 1) / 8 + 1;
RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, p_face_id > 9 ? 6 : 1);
RD::get_singleton()->compute_list_end();
}
void RasterizerEffectsRD::cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size) {
cubemap_downsampler.push_constant.face_size = p_size.x;
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, cubemap_downsampler.pipelines[p_source_is_panorama ? CUBEMAP_DOWNSAMPLER_SOURCE_PANORAMA : CUBEMAP_DOWNSAMPLER_SOURCE_CUBEMAP]);
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, cubemap_downsampler.pipeline);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_cubemap), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_cubemap), 1);
@ -780,6 +780,41 @@ void RasterizerEffectsRD::cubemap_filter(RID p_source_cubemap, Vector<RID> p_des
RD::get_singleton()->compute_list_end();
}
void RasterizerEffectsRD::render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_lights, RenderPipelineVertexFormatCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const CameraMatrix &p_camera, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position) {
SkyPushConstant sky_push_constant;
zeromem(&sky_push_constant, sizeof(SkyPushConstant));
sky_push_constant.proj[0] = p_camera.matrix[2][0];
sky_push_constant.proj[1] = p_camera.matrix[0][0];
sky_push_constant.proj[2] = p_camera.matrix[2][1];
sky_push_constant.proj[3] = p_camera.matrix[1][1];
sky_push_constant.position[0] = p_position.x;
sky_push_constant.position[1] = p_position.y;
sky_push_constant.position[2] = p_position.z;
sky_push_constant.multiplier = p_multiplier;
sky_push_constant.time = p_time;
store_transform_3x3(p_orientation, sky_push_constant.orientation);
RenderingDevice::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(p_fb);
RD::DrawListID draw_list = p_list;
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, p_pipeline->get_render_pipeline(RD::INVALID_ID, fb_format));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_samplers, 0);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_uniform_set, 1);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_texture_set, 2);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_lights, 3);
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
RD::get_singleton()->draw_list_set_push_constant(draw_list, &sky_push_constant, sizeof(SkyPushConstant));
RD::get_singleton()->draw_list_draw(draw_list, true);
}
RasterizerEffectsRD::RasterizerEffectsRD() {
{
@ -813,15 +848,12 @@ RasterizerEffectsRD::RasterizerEffectsRD() {
{
// Initialize roughness
Vector<String> cubemap_roughness_modes;
cubemap_roughness_modes.push_back("\n#define MODE_SOURCE_PANORAMA\n");
cubemap_roughness_modes.push_back("\n#define MODE_SOURCE_CUBEMAP\n");
cubemap_roughness_modes.push_back("");
roughness.shader.initialize(cubemap_roughness_modes);
roughness.shader_version = roughness.shader.version_create();
for (int i = 0; i < CUBEMAP_ROUGHNESS_SOURCE_MAX; i++) {
roughness.pipelines[i] = RD::get_singleton()->compute_pipeline_create(roughness.shader.version_get_shader(roughness.shader_version, i));
}
roughness.pipeline = RD::get_singleton()->compute_pipeline_create(roughness.shader.version_get_shader(roughness.shader_version, 0));
}
{
@ -958,15 +990,12 @@ RasterizerEffectsRD::RasterizerEffectsRD() {
{
//Initialize cubemap downsampler
Vector<String> cubemap_downsampler_modes;
cubemap_downsampler_modes.push_back("\n#define MODE_SOURCE_PANORAMA\n");
cubemap_downsampler_modes.push_back("\n#define MODE_SOURCE_CUBEMAP\n");
cubemap_downsampler_modes.push_back("");
cubemap_downsampler.shader.initialize(cubemap_downsampler_modes);
cubemap_downsampler.shader_version = cubemap_downsampler.shader.version_create();
for (int i = 0; i < CUBEMAP_DOWNSAMPLER_SOURCE_MAX; i++) {
cubemap_downsampler.pipelines[i] = RD::get_singleton()->compute_pipeline_create(cubemap_downsampler.shader.version_get_shader(cubemap_downsampler.shader_version, i));
}
cubemap_downsampler.pipeline = RD::get_singleton()->compute_pipeline_create(cubemap_downsampler.shader.version_get_shader(cubemap_downsampler.shader_version, 0));
}
{
@ -1050,7 +1079,6 @@ RasterizerEffectsRD::~RasterizerEffectsRD() {
RD::get_singleton()->free(filter.coefficient_buffer);
blur.shader.version_free(blur.shader_version);
roughness.shader.version_free(roughness.shader_version);
sky.shader.version_free(sky.shader_version);
tonemap.shader.version_free(tonemap.shader_version);
luminance_reduce.shader.version_free(luminance_reduce.shader_version);
copy.shader.version_free(copy.shader_version);

View file

@ -115,12 +115,6 @@ class RasterizerEffectsRD {
} blur;
enum CubemapRoughnessSource {
CUBEMAP_ROUGHNESS_SOURCE_PANORAMA,
CUBEMAP_ROUGHNESS_SOURCE_CUBEMAP,
CUBEMAP_ROUGHNESS_SOURCE_MAX
};
struct CubemapRoughnessPushConstant {
uint32_t face_id;
uint32_t sample_count;
@ -135,7 +129,7 @@ class RasterizerEffectsRD {
CubemapRoughnessPushConstant push_constant;
CubemapRoughnessShaderRD shader;
RID shader_version;
RID pipelines[CUBEMAP_ROUGHNESS_SOURCE_MAX];
RID pipeline;
} roughness;
enum TonemapMode {
@ -341,12 +335,6 @@ class RasterizerEffectsRD {
} roughness_limiter;
enum CubemapDownsamplerSource {
CUBEMAP_DOWNSAMPLER_SOURCE_PANORAMA,
CUBEMAP_DOWNSAMPLER_SOURCE_CUBEMAP,
CUBEMAP_DOWNSAMPLER_SOURCE_MAX
};
struct CubemapDownsamplerPushConstant {
uint32_t face_size;
float pad[3];
@ -357,7 +345,7 @@ class RasterizerEffectsRD {
CubemapDownsamplerPushConstant push_constant;
CubemapDownsamplerShaderRD shader;
RID shader_version;
RID pipelines[CUBEMAP_DOWNSAMPLER_SOURCE_MAX];
RID pipeline;
} cubemap_downsampler;
@ -381,6 +369,15 @@ class RasterizerEffectsRD {
} filter;
struct SkyPushConstant {
float orientation[12];
float proj[4];
float position[3];
float multiplier;
float time;
float pad[3];
};
RID default_sampler;
RID default_mipmap_sampler;
RID index_buffer;
@ -403,7 +400,7 @@ public:
void gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region);
void gaussian_glow(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
void cubemap_roughness(RID p_source_rd_texture, bool p_source_is_panorama, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
void cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
void make_mipmap(RID p_source_rd_texture, RID p_framebuffer_half, const Vector2 &p_pixel_size);
void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip);
void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
@ -449,8 +446,9 @@ public:
void generate_ssao(RID p_depth_buffer, RID p_normal_buffer, const Size2i &p_depth_buffer_size, RID p_depth_mipmaps_texture, const Vector<RID> &depth_mipmaps, RID p_ao1, bool p_half_size, RID p_ao2, RID p_upscale_buffer, float p_intensity, float p_radius, float p_bias, const CameraMatrix &p_projection, VS::EnvironmentSSAOQuality p_quality, VS::EnvironmentSSAOBlur p_blur, float p_edge_sharpness);
void roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve);
void cubemap_downsample(RID p_source_cubemap, bool p_source_is_panorama, RID p_dest_cubemap, const Size2i &p_size);
void cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size);
void cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array);
void render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_lights, RenderPipelineVertexFormatCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const CameraMatrix &p_camera, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position);
RasterizerEffectsRD();
~RasterizerEffectsRD();

View file

@ -522,255 +522,6 @@ RasterizerStorageRD::MaterialData *RasterizerSceneHighEndRD::_create_material_fu
return material_data;
}
/* SKY SHADER */
void RasterizerSceneHighEndRD::SkyShaderData::set_code(const String &p_code) {
//compile
code = p_code;
valid = false;
ubo_size = 0;
uniforms.clear();
if (code == String()) {
return; //just invalid, but no error
}
ShaderCompilerRD::GeneratedCode gen_code;
ShaderCompilerRD::IdentifierActions actions;
// actions.render_mode_values["blend_add"] = Pair<int *, int>(&blend_mode, BLEND_MODE_ADD);
// actions.usage_flag_pointers["ALPHA"] = &uses_alpha;
actions.uniforms = &uniforms;
RasterizerSceneHighEndRD *scene_singleton = (RasterizerSceneHighEndRD *)RasterizerSceneHighEndRD::singleton;
Error err = scene_singleton->sky_shader.compiler.compile(VS::SHADER_SKY, code, &actions, path, gen_code);
ERR_FAIL_COND(err != OK);
if (version.is_null()) {
version = scene_singleton->sky_shader.shader.version_create();
}
#if 0
print_line("**compiling shader:");
print_line("**defines:\n");
for (int i = 0; i < gen_code.defines.size(); i++) {
print_line(gen_code.defines[i]);
}
print_line("\n**uniforms:\n" + gen_code.uniforms);
// print_line("\n**vertex_globals:\n" + gen_code.vertex_global);
// print_line("\n**vertex_code:\n" + gen_code.vertex);
print_line("\n**fragment_globals:\n" + gen_code.fragment_global);
print_line("\n**fragment_code:\n" + gen_code.fragment);
print_line("\n**light_code:\n" + gen_code.light);
#endif
scene_singleton->sky_shader.shader.version_set_code(version, gen_code.uniforms, gen_code.vertex_global, gen_code.vertex, gen_code.fragment_global, gen_code.light, gen_code.fragment, gen_code.defines);
ERR_FAIL_COND(!scene_singleton->sky_shader.shader.version_is_valid(version));
ubo_size = gen_code.uniform_total_size;
ubo_offsets = gen_code.uniform_offsets;
texture_uniforms = gen_code.texture_uniforms;
//update pipelines
for (int i = 0; i < SKY_VERSION_MAX; i++) {
RD::PipelineDepthStencilState depth_stencil_state;
depth_stencil_state.enable_depth_test = false;
RID shader_variant = scene_singleton->sky_shader.shader.version_get_shader(version, i);
pipelines[i].setup(shader_variant, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), depth_stencil_state, RD::PipelineColorBlendState::create_disabled(), 0);
}
valid = true;
}
void RasterizerSceneHighEndRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
if (!p_texture.is_valid()) {
default_texture_params.erase(p_name);
} else {
default_texture_params[p_name] = p_texture;
}
}
void RasterizerSceneHighEndRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
Map<int, StringName> order;
for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
if (E->get().texture_order >= 0) {
order[E->get().texture_order + 100000] = E->key();
} else {
order[E->get().order] = E->key();
}
}
for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) {
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]);
pi.name = E->get();
p_param_list->push_back(pi);
}
}
bool RasterizerSceneHighEndRD::SkyShaderData::is_param_texture(const StringName &p_param) const {
if (!uniforms.has(p_param)) {
return false;
}
return uniforms[p_param].texture_order >= 0;
}
bool RasterizerSceneHighEndRD::SkyShaderData::is_animated() const {
return false;
}
bool RasterizerSceneHighEndRD::SkyShaderData::casts_shadows() const {
return false;
}
Variant RasterizerSceneHighEndRD::SkyShaderData::get_default_parameter(const StringName &p_parameter) const {
if (uniforms.has(p_parameter)) {
ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint);
}
return Variant();
}
RasterizerSceneHighEndRD::SkyShaderData::SkyShaderData() {
valid = false;
}
RasterizerSceneHighEndRD::SkyShaderData::~SkyShaderData() {
RasterizerSceneHighEndRD *scene_singleton = (RasterizerSceneHighEndRD *)RasterizerSceneHighEndRD::singleton;
ERR_FAIL_COND(!scene_singleton);
//pipeline variants will clear themselves if shader is gone
if (version.is_valid()) {
scene_singleton->sky_shader.shader.version_free(version);
}
}
RasterizerStorageRD::ShaderData *RasterizerSceneHighEndRD::_create_sky_shader_func() {
SkyShaderData *shader_data = memnew(SkyShaderData);
return shader_data;
}
void RasterizerSceneHighEndRD::SkyMaterialData::set_render_priority(int p_priority) {
priority = p_priority - VS::MATERIAL_RENDER_PRIORITY_MIN; //8 bits
}
void RasterizerSceneHighEndRD::SkyMaterialData::set_next_pass(RID p_pass) {
next_pass = p_pass;
}
void RasterizerSceneHighEndRD::SkyMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
RasterizerSceneHighEndRD *scene_singleton = (RasterizerSceneHighEndRD *)RasterizerSceneHighEndRD::singleton;
if ((uint32_t)ubo_data.size() != shader_data->ubo_size) {
p_uniform_dirty = true;
if (uniform_buffer.is_valid()) {
RD::get_singleton()->free(uniform_buffer);
uniform_buffer = RID();
}
ubo_data.resize(shader_data->ubo_size);
if (ubo_data.size()) {
uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size());
memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear
}
//clear previous uniform set
if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
RD::get_singleton()->free(uniform_set);
uniform_set = RID();
}
}
//check whether buffer changed
if (p_uniform_dirty && ubo_data.size()) {
update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false);
RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw());
}
uint32_t tex_uniform_count = shader_data->texture_uniforms.size();
if ((uint32_t)texture_cache.size() != tex_uniform_count) {
texture_cache.resize(tex_uniform_count);
p_textures_dirty = true;
//clear previous uniform set
if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
RD::get_singleton()->free(uniform_set);
uniform_set = RID();
}
}
if (p_textures_dirty && tex_uniform_count) {
update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), true);
}
if (shader_data->ubo_size == 0 && shader_data->texture_uniforms.size() == 0) {
// This material does not require an uniform set, so don't create it.
return;
}
if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
//no reason to update uniform set, only UBO (or nothing) was needed to update
return;
}
Vector<RD::Uniform> uniforms;
{
if (shader_data->ubo_size) {
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 0;
u.ids.push_back(uniform_buffer);
uniforms.push_back(u);
}
const RID *textures = texture_cache.ptrw();
for (uint32_t i = 0; i < tex_uniform_count; i++) {
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 1 + i;
u.ids.push_back(textures[i]);
uniforms.push_back(u);
}
}
uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_singleton->sky_shader.shader.version_get_shader(shader_data->version, 0), 2);
}
RasterizerSceneHighEndRD::SkyMaterialData::~SkyMaterialData() {
if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
RD::get_singleton()->free(uniform_set);
}
if (uniform_buffer.is_valid()) {
RD::get_singleton()->free(uniform_buffer);
}
}
RasterizerStorageRD::MaterialData *RasterizerSceneHighEndRD::_create_sky_material_func(SkyShaderData *p_shader) {
SkyMaterialData *material_data = memnew(SkyMaterialData);
material_data->shader_data = p_shader;
material_data->last_frame = false;
//update will happen later anyway so do nothing.
return material_data;
}
RasterizerSceneHighEndRD::RenderBufferDataHighEnd::~RenderBufferDataHighEnd() {
clear();
}
@ -1544,72 +1295,6 @@ void RasterizerSceneHighEndRD::_fill_render_list(InstanceBase **p_cull_result, i
}
}
void RasterizerSceneHighEndRD::_draw_sky(RD::DrawListID p_draw_list, RD::FramebufferFormatID p_fb_format, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, float p_alpha) {
ERR_FAIL_COND(!is_environment(p_environment));
RID env_material = environment_get_bg_material(p_environment);
ERR_FAIL_COND(!env_material.is_valid());
SkyMaterialData *material = NULL;
if (env_material.is_valid()) {
material = (SkyMaterialData *)storage->material_get_data(env_material, RasterizerStorageRD::SHADER_TYPE_SKY);
if (!material || !material->shader_data->valid) {
material = NULL;
}
}
if (!material) {
env_material = sky_shader.default_material;
material = (SkyMaterialData *)storage->material_get_data(env_material, RasterizerStorageRD::SHADER_TYPE_SKY);
}
ERR_FAIL_COND(!material);
SkyShaderData *shader_data = material->shader_data;
ERR_FAIL_COND(!shader_data);
RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_BACKGROUND];
//@TODO need to gather parameters we source from our environment settings and feed into our material/shader
// such as bg energy, sky transform, etc.
// some we should remove and make part of our material settings instead of environment settings
/*
TODO need to change this to use our sky shader instead
RID sky = environment_get_sky(p_environment);
ERR_FAIL_COND(!sky.is_valid());
RID panorama = sky_get_panorama_texture_rd(sky);
ERR_FAIL_COND(!panorama.is_valid());
Basis sky_transform = environment_get_sky_orientation(p_environment);
sky_transform.invert();
float multiplier = environment_get_bg_energy(p_environment);
float custom_fov = environment_get_sky_custom_fov(p_environment);
// Camera
CameraMatrix camera;
if (custom_fov) {
float near_plane = p_projection.get_z_near();
float far_plane = p_projection.get_z_far();
float aspect = p_projection.get_aspect();
camera.set_perspective(custom_fov, aspect, near_plane, far_plane);
} else {
camera = p_projection;
}
sky_transform = p_transform.basis * sky_transform;
storage->get_effects()->render_panorama(p_draw_list, p_fb_format, panorama, camera, sky_transform, 1.0, multiplier);
*/
}
void RasterizerSceneHighEndRD::_setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment) {
for (int i = 0; i < p_reflection_probe_cull_count; i++) {
@ -1748,6 +1433,7 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
uint32_t light_count = 0;
scene_state.ubo.directional_light_count = 0;
sky_scene_state.directional_light_count = 0;
for (int i = 0; i < p_light_cull_count; i++) {
@ -1823,6 +1509,27 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
light_data.fade_to = -light_data.shadow_split_offsets[3];
}
// Copy to SkyDirectionalLightData
if (sky_scene_state.directional_light_count < sky_scene_state.max_directional_lights) {
SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[sky_scene_state.directional_light_count];
Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized();
sky_light_data.direction[0] = world_direction.x;
sky_light_data.direction[1] = world_direction.y;
sky_light_data.direction[2] = -world_direction.z;
sky_light_data.energy = light_data.energy / Math_PI;
sky_light_data.color[0] = light_data.color[0];
sky_light_data.color[1] = light_data.color[1];
sky_light_data.color[2] = light_data.color[2];
sky_light_data.enabled = true;
sky_scene_state.directional_light_count++;
}
scene_state.ubo.directional_light_count++;
} break;
case VS::LIGHT_SPOT:
@ -1993,6 +1700,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
scene_state.ubo.viewport_size[1] = vp_he.y;
Size2 screen_pixel_size;
Size2i screen_size;
RID opaque_framebuffer;
RID depth_framebuffer;
RID alpha_framebuffer;
@ -2003,6 +1711,8 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
if (render_buffer) {
screen_pixel_size.width = 1.0 / render_buffer->width;
screen_pixel_size.height = 1.0 / render_buffer->height;
screen_size.x = render_buffer->width;
screen_size.y = render_buffer->height;
opaque_framebuffer = render_buffer->color_fb;
@ -2043,6 +1753,8 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
uint32_t resolution = reflection_probe_instance_get_resolution(p_reflection_probe);
screen_pixel_size.width = 1.0 / resolution;
screen_pixel_size.height = 1.0 / resolution;
screen_size.x = resolution;
screen_size.y = resolution;
opaque_framebuffer = reflection_probe_instance_get_framebuffer(p_reflection_probe, p_reflection_probe_pass);
depth_framebuffer = reflection_probe_instance_get_depth_framebuffer(p_reflection_probe, p_reflection_probe_pass);
@ -2097,7 +1809,17 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
case VS::ENV_BG_SKY: {
RID sky = environment_get_sky(p_environment);
if (sky.is_valid()) {
// TODO: change this, we need to check if our radiance texture is dirty and needs updating...
RENDER_TIMESTAMP("Setup Sky");
CameraMatrix projection = p_cam_projection;
if (p_reflection_probe.is_valid()) {
CameraMatrix correction;
correction.set_depth_correction(true);
projection = correction * p_cam_projection;
}
_setup_sky(p_environment, p_cam_transform.origin, screen_size);
_update_sky(p_environment, projection, p_cam_transform);
radiance_uniform_set = sky_get_radiance_uniform_set_rd(sky, default_shader_rd, RADIANCE_UNIFORM_SET);
draw_sky = true;
@ -2192,9 +1914,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
projection = correction * p_cam_projection;
}
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, can_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, can_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
_draw_sky(draw_list, RD::get_singleton()->framebuffer_get_format(opaque_framebuffer), p_environment, projection, p_cam_transform, 1.0);
RD::get_singleton()->draw_list_end();
_draw_sky(can_continue, opaque_framebuffer, p_environment, projection, p_cam_transform);
if (using_separate_specular && !can_continue) {
//can't continue, so close the buffers
@ -2886,41 +2606,6 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
shader.compiler.initialize(actions);
}
/* SKY SHADER */
{
// Initialize sky, we may need two modes here
Vector<String> sky_modes;
sky_modes.push_back(""); // background
sky_shader.shader.initialize(sky_modes);
}
// register our shader funds
storage->shader_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_SKY, _create_sky_shader_funcs);
storage->material_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_SKY, _create_sky_material_funcs);
{
ShaderCompilerRD::DefaultIdentifierActions actions;
actions.renames["COLOR"] = "color";
actions.renames["EYEDIR"] = "cube_normal";
// actions.usage_defines["TANGENT"] = "#define TANGENT_USED\n";
// actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
// are these correct?
actions.sampler_array_name = "material_samplers";
actions.base_texture_binding_index = 1;
actions.texture_layout_set = 2;
actions.base_uniform_string = "material.";
actions.base_varying_index = 10;
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
sky_shader.compiler.initialize(actions);
}
//render list
render_list.max_elements = GLOBAL_DEF_RST("rendering/limits/rendering/max_renderable_elements", (int)128000);
render_list.init();
@ -2946,17 +2631,6 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
default_shader_rd = shader.scene_shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS);
}
{
// default material and shader for sky shader
sky_shader.default_shader = storage->shader_create();
storage->shader_set_code(sky_shader.default_shader, "shader_type sky; void fragment() { COLOR = vec3(0.0, 0.0, 0.0); } \n");
sky_shader.default_material = storage->material_create();
storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader);
MaterialData *md = (MaterialData *)storage->material_get_data(sky_shader.default_material, RasterizerStorageRD::SHADER_TYPE_SKY);
sky_shader.default_shader_rd = sky_shader.shader.version_get_shader(md->shader_data->version, SKY_VERSION_BACKGROUND);
}
{
overdraw_material_shader = storage->shader_create();

View file

@ -36,7 +36,6 @@
#include "servers/visual/rasterizer_rd/rasterizer_storage_rd.h"
#include "servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h"
#include "servers/visual/rasterizer_rd/shaders/scene_high_end.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/sky.glsl.gen.h"
class RasterizerSceneHighEndRD : public RasterizerSceneRD {
@ -51,8 +50,6 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
/* Scene Shader */
// TODO possibly rename this to make it clear we have a SceneShader and SkyShader??
enum ShaderVersion {
SHADER_VERSION_DEPTH_PASS,
SHADER_VERSION_DEPTH_PASS_DP,
@ -196,87 +193,6 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
uint32_t pad[3];
};
/* Sky shader */
enum SkyVersion {
SKY_VERSION_BACKGROUND,
SKY_VERSION_MAX
};
struct SkyShader {
SkyShaderRD shader;
ShaderCompilerRD compiler;
RID default_shader;
RID default_material;
RID default_shader_rd;
} sky_shader;
struct SkyShaderData : public RasterizerStorageRD::ShaderData {
bool valid;
RID version;
RenderPipelineVertexFormatCacheRD pipelines[SKY_VERSION_MAX];
Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
uint32_t ubo_size;
String path;
String code;
Map<StringName, RID> default_texture_params;
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
virtual bool casts_shadows() const;
virtual Variant get_default_parameter(const StringName &p_parameter) const;
SkyShaderData();
virtual ~SkyShaderData();
};
RasterizerStorageRD::ShaderData *_create_sky_shader_func();
static RasterizerStorageRD::ShaderData *_create_sky_shader_funcs() {
return static_cast<RasterizerSceneHighEndRD *>(singleton)->_create_sky_shader_func();
};
// !BAS! Can we re-use MaterialData for our sky shader? does it need its own material subclass?
struct SkyMaterialData : public RasterizerStorageRD::MaterialData {
// !BAS! do we need all of these?
uint64_t last_frame;
SkyShaderData *shader_data;
RID uniform_buffer;
RID uniform_set;
Vector<RID> texture_cache;
Vector<uint8_t> ubo_data;
uint64_t last_pass = 0;
uint32_t index = 0;
RID next_pass;
uint8_t priority;
virtual void set_render_priority(int p_priority);
virtual void set_next_pass(RID p_pass);
virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
virtual ~SkyMaterialData();
};
RasterizerStorageRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader);
static RasterizerStorageRD::MaterialData *_create_sky_material_funcs(RasterizerStorageRD::ShaderData *p_shader) {
return static_cast<RasterizerSceneHighEndRD *>(singleton)->_create_sky_material_func(static_cast<SkyShaderData *>(p_shader));
};
struct SkyPushConstant {
float orientation[12];
float proj[4];
float multiplier;
float alpha;
float depth;
float pad;
};
/* Framebuffer */
struct RenderBufferDataHighEnd : public RenderBufferData {
@ -653,8 +569,6 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_no_gi);
void _draw_sky(RD::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_fb_format, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, float p_alpha);
protected:
virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color);
virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip);

File diff suppressed because it is too large Load diff

View file

@ -36,6 +36,7 @@
#include "servers/visual/rasterizer_rd/rasterizer_storage_rd.h"
#include "servers/visual/rasterizer_rd/shaders/giprobe.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/giprobe_debug.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/sky.glsl.gen.h"
#include "servers/visual/rendering_device.h"
class RasterizerSceneRD : public RasterizerScene {
@ -47,6 +48,29 @@ public:
};
protected:
double time;
// Skys need less info from Directional Lights than the normal shaders
struct SkyDirectionalLightData {
float direction[3];
float energy;
float color[3];
uint32_t enabled;
};
struct SkySceneState {
SkyDirectionalLightData *directional_lights;
SkyDirectionalLightData *last_frame_directional_lights;
uint32_t max_directional_lights;
uint32_t directional_light_count;
uint32_t last_frame_directional_light_count;
RID directional_light_buffer;
RID sampler_uniform_set;
RID light_uniform_set;
} sky_scene_state;
struct RenderBufferData {
virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, VS::ViewportMSAA p_msaa) = 0;
@ -69,9 +93,14 @@ protected:
void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection);
void _setup_sky(RID p_environment, const Vector3 &p_position, const Size2i p_screen_size);
void _update_sky(RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform);
void _draw_sky(bool p_can_continue, RID p_fb, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform);
private:
VS::ViewportDebugDraw debug_draw = VS::VIEWPORT_DEBUG_DRAW_DISABLED;
double time_step = 0;
static RasterizerSceneRD *singleton;
int roughness_layers;
@ -102,31 +131,160 @@ private:
DownsampleLayer downsampled_layer;
RID coefficient_buffer;
bool dirty = true;
Vector<Layer> layers;
};
void _clear_reflection_data(ReflectionData &rd);
void _update_reflection_data(ReflectionData &rd, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality);
void _create_reflection_from_panorama(ReflectionData &rd, RID p_panorama, bool p_quality);
void _create_reflection_from_base_mipmap(ReflectionData &rd, bool p_use_arrays, bool p_quality, int p_cube_side, int p_base_layer);
void _update_reflection_mipmaps(ReflectionData &rd, bool p_quality);
void _create_reflection_fast_filter(ReflectionData &rd, bool p_use_arrays);
void _create_reflection_importance_sample(ReflectionData &rd, bool p_use_arrays, int p_cube_side, int p_base_layer);
void _update_reflection_mipmaps(ReflectionData &rd);
/* Sky shader */
enum SkyVersion {
SKY_VERSION_BACKGROUND,
SKY_VERSION_HALF_RES,
SKY_VERSION_QUARTER_RES,
SKY_VERSION_CUBEMAP,
SKY_VERSION_MAX
};
struct SkyShader {
SkyShaderRD shader;
ShaderCompilerRD compiler;
RID default_shader;
RID default_material;
RID default_shader_rd;
} sky_shader;
struct SkyShaderData : public RasterizerStorageRD::ShaderData {
bool valid;
RID version;
RenderPipelineVertexFormatCacheRD pipelines[SKY_VERSION_MAX];
Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
uint32_t ubo_size;
String path;
String code;
Map<StringName, RID> default_texture_params;
bool uses_time;
bool uses_position;
bool uses_half_res;
bool uses_quarter_res;
bool uses_light;
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
virtual bool casts_shadows() const;
virtual Variant get_default_parameter(const StringName &p_parameter) const;
SkyShaderData();
virtual ~SkyShaderData();
};
RasterizerStorageRD::ShaderData *_create_sky_shader_func();
static RasterizerStorageRD::ShaderData *_create_sky_shader_funcs() {
return static_cast<RasterizerSceneRD *>(singleton)->_create_sky_shader_func();
};
struct SkyMaterialData : public RasterizerStorageRD::MaterialData {
uint64_t last_frame;
SkyShaderData *shader_data;
RID uniform_buffer;
RID uniform_set;
Vector<RID> texture_cache;
Vector<uint8_t> ubo_data;
bool uniform_set_updated;
virtual void set_render_priority(int p_priority) {}
virtual void set_next_pass(RID p_pass) {}
virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
virtual ~SkyMaterialData();
};
RasterizerStorageRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader);
static RasterizerStorageRD::MaterialData *_create_sky_material_funcs(RasterizerStorageRD::ShaderData *p_shader) {
return static_cast<RasterizerSceneRD *>(singleton)->_create_sky_material_func(static_cast<SkyShaderData *>(p_shader));
};
enum SkyTextureSetVersion {
SKY_TEXTURE_SET_BACKGROUND,
SKY_TEXTURE_SET_HALF_RES,
SKY_TEXTURE_SET_QUARTER_RES,
SKY_TEXTURE_SET_CUBEMAP0,
SKY_TEXTURE_SET_CUBEMAP1,
SKY_TEXTURE_SET_CUBEMAP2,
SKY_TEXTURE_SET_CUBEMAP3,
SKY_TEXTURE_SET_CUBEMAP4,
SKY_TEXTURE_SET_CUBEMAP5,
SKY_TEXTURE_SET_CUBEMAP_HALF_RES0,
SKY_TEXTURE_SET_CUBEMAP_HALF_RES1,
SKY_TEXTURE_SET_CUBEMAP_HALF_RES2,
SKY_TEXTURE_SET_CUBEMAP_HALF_RES3,
SKY_TEXTURE_SET_CUBEMAP_HALF_RES4,
SKY_TEXTURE_SET_CUBEMAP_HALF_RES5,
SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES0,
SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES1,
SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES2,
SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES3,
SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES4,
SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES5,
SKY_TEXTURE_SET_MAX
};
enum SkySet {
SKY_SET_SAMPLERS,
SKY_SET_MATERIAL,
SKY_SET_TEXTURES,
SKY_SET_LIGHTS,
SKY_SET_MAX
};
/* SKY */
struct Sky {
RID radiance;
RID half_res_pass;
RID half_res_framebuffer;
RID quarter_res_pass;
RID quarter_res_framebuffer;
Size2i screen_size;
RID texture_uniform_sets[SKY_TEXTURE_SET_MAX];
RID uniform_set;
int radiance_size = 128;
RID material;
RID uniform_buffer;
int radiance_size = 256;
VS::SkyMode mode = VS::SKY_MODE_QUALITY;
RID panorama;
ReflectionData reflection;
bool dirty = false;
Sky *dirty_list = nullptr;
//State to track when radiance cubemap needs updating
SkyMaterialData *prev_material;
Vector3 prev_position;
float prev_time;
};
Sky *dirty_sky_list = nullptr;
void _sky_invalidate(Sky *p_sky);
void _update_dirty_skys();
RID _get_sky_textures(Sky *p_sky, SkyTextureSetVersion p_version);
uint32_t sky_ggx_samples_quality;
bool sky_use_cubemap_array;
@ -465,7 +623,6 @@ private:
// BG
VS::EnvironmentBG background = VS::ENV_BG_CLEAR_COLOR;
RID sky;
RID bg_material;
float sky_custom_fov = 0.0;
Basis sky_orientation;
Color bg_color;
@ -648,11 +805,11 @@ public:
RID sky_create();
void sky_set_radiance_size(RID p_sky, int p_radiance_size);
void sky_set_mode(RID p_sky, VS::SkyMode p_mode);
void sky_set_texture(RID p_sky, RID p_panorama);
void sky_set_material(RID p_sky, RID p_material);
RID sky_get_panorama_texture_rd(RID p_sky) const;
RID sky_get_radiance_texture_rd(RID p_sky) const;
RID sky_get_radiance_uniform_set_rd(RID p_sky, RID p_shader, int p_set) const;
RID sky_get_material(RID p_sky) const;
/* ENVIRONMENT API */
@ -662,7 +819,6 @@ public:
void environment_set_sky(RID p_env, RID p_sky);
void environment_set_sky_custom_fov(RID p_env, float p_scale);
void environment_set_sky_orientation(RID p_env, const Basis &p_orientation);
void environment_set_bg_material(RID p_env, RID p_material);
void environment_set_bg_color(RID p_env, const Color &p_color);
void environment_set_bg_energy(RID p_env, float p_energy);
void environment_set_canvas_max_layer(RID p_env, int p_max_layer);
@ -672,7 +828,6 @@ public:
RID environment_get_sky(RID p_env) const;
float environment_get_sky_custom_fov(RID p_env) const;
Basis environment_get_sky_orientation(RID p_env) const;
RID environment_get_bg_material(RID p_env) const;
Color environment_get_bg_color(RID p_env) const;
float environment_get_bg_energy(RID p_env) const;
int environment_get_canvas_max_layer(RID p_env) const;

View file

@ -30,13 +30,7 @@ VERSION_DEFINES
layout(local_size_x = BLOCK_SIZE, local_size_y = BLOCK_SIZE, local_size_z = 1) in;
/* clang-format on */
#ifdef MODE_SOURCE_PANORAMA
layout(set = 0, binding = 0) uniform sampler2D source_panorama;
#endif
#ifdef MODE_SOURCE_CUBEMAP
layout(set = 0, binding = 0) uniform samplerCube source_cubemap;
#endif
layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly imageCube dest_cubemap;
@ -83,32 +77,6 @@ float calcWeight(float u, float v) {
return val * sqrt(val);
}
#ifdef MODE_SOURCE_PANORAMA
vec4 texturePanorama(vec3 normal, sampler2D pano) {
vec2 st = vec2(
atan(normal.x, -normal.z),
acos(normal.y));
if (st.x < 0.0)
st.x += M_PI * 2.0;
st /= vec2(M_PI * 2.0, M_PI);
return textureLod(pano, st, 0.0);
}
#endif
vec4 get_texture(vec3 p_dir) {
#ifdef MODE_SOURCE_PANORAMA
return texturePanorama(normalize(p_dir), source_panorama);
#else
return textureLod(source_cubemap, normalize(p_dir), 0.0);
#endif
}
void main() {
uvec3 id = gl_GlobalInvocationID;
uint face_size = params.face_size;
@ -138,81 +106,81 @@ void main() {
switch (id.z) {
case 0:
get_dir_0(dir, u0, v0);
color = get_texture(dir) * weights[0];
color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
get_dir_0(dir, u1, v0);
color += get_texture(dir) * weights[1];
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
get_dir_0(dir, u0, v1);
color += get_texture(dir) * weights[2];
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
get_dir_0(dir, u1, v1);
color += get_texture(dir) * weights[3];
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
break;
case 1:
get_dir_1(dir, u0, v0);
color = get_texture(dir) * weights[0];
color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
get_dir_1(dir, u1, v0);
color += get_texture(dir) * weights[1];
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
get_dir_1(dir, u0, v1);
color += get_texture(dir) * weights[2];
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
get_dir_1(dir, u1, v1);
color += get_texture(dir) * weights[3];
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
break;
case 2:
get_dir_2(dir, u0, v0);
color = get_texture(dir) * weights[0];
color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
get_dir_2(dir, u1, v0);
color += get_texture(dir) * weights[1];
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
get_dir_2(dir, u0, v1);
color += get_texture(dir) * weights[2];
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
get_dir_2(dir, u1, v1);
color += get_texture(dir) * weights[3];
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
break;
case 3:
get_dir_3(dir, u0, v0);
color = get_texture(dir) * weights[0];
color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
get_dir_3(dir, u1, v0);
color += get_texture(dir) * weights[1];
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
get_dir_3(dir, u0, v1);
color += get_texture(dir) * weights[2];
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
get_dir_3(dir, u1, v1);
color += get_texture(dir) * weights[3];
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
break;
case 4:
get_dir_4(dir, u0, v0);
color = get_texture(dir) * weights[0];
color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
get_dir_4(dir, u1, v0);
color += get_texture(dir) * weights[1];
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
get_dir_4(dir, u0, v1);
color += get_texture(dir) * weights[2];
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
get_dir_4(dir, u1, v1);
color += get_texture(dir) * weights[3];
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
break;
default:
get_dir_5(dir, u0, v0);
color = get_texture(dir) * weights[0];
color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
get_dir_5(dir, u1, v0);
color += get_texture(dir) * weights[1];
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
get_dir_5(dir, u0, v1);
color += get_texture(dir) * weights[2];
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
get_dir_5(dir, u1, v1);
color += get_texture(dir) * weights[3];
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
break;
}
imageStore(dest_cubemap, ivec3(id), color);

View file

@ -262,28 +262,66 @@ void main() {
// write color
color.xyz = max(vec3(0.0), color.xyz);
color.w = 1.0;
#ifdef USE_TEXTURE_ARRAY
id.xy *= uvec2(2, 2);
#endif
switch (level) {
case 0:
imageStore(dest_cubemap0, ivec3(id), color);
#ifdef USE_TEXTURE_ARRAY
imageStore(dest_cubemap0, ivec3(id) + ivec3(1.0, 0.0, 0.0), color);
imageStore(dest_cubemap0, ivec3(id) + ivec3(0.0, 1.0, 0.0), color);
imageStore(dest_cubemap0, ivec3(id) + ivec3(1.0, 1.0, 0.0), color);
#endif
break;
case 1:
imageStore(dest_cubemap1, ivec3(id), color);
#ifdef USE_TEXTURE_ARRAY
imageStore(dest_cubemap1, ivec3(id) + ivec3(1.0, 0.0, 0.0), color);
imageStore(dest_cubemap1, ivec3(id) + ivec3(0.0, 1.0, 0.0), color);
imageStore(dest_cubemap1, ivec3(id) + ivec3(1.0, 1.0, 0.0), color);
#endif
break;
case 2:
imageStore(dest_cubemap2, ivec3(id), color);
#ifdef USE_TEXTURE_ARRAY
imageStore(dest_cubemap2, ivec3(id) + ivec3(1.0, 0.0, 0.0), color);
imageStore(dest_cubemap2, ivec3(id) + ivec3(0.0, 1.0, 0.0), color);
imageStore(dest_cubemap2, ivec3(id) + ivec3(1.0, 1.0, 0.0), color);
#endif
break;
case 3:
imageStore(dest_cubemap3, ivec3(id), color);
#ifdef USE_TEXTURE_ARRAY
imageStore(dest_cubemap3, ivec3(id) + ivec3(1.0, 0.0, 0.0), color);
imageStore(dest_cubemap3, ivec3(id) + ivec3(0.0, 1.0, 0.0), color);
imageStore(dest_cubemap3, ivec3(id) + ivec3(1.0, 1.0, 0.0), color);
#endif
break;
case 4:
imageStore(dest_cubemap4, ivec3(id), color);
#ifdef USE_TEXTURE_ARRAY
imageStore(dest_cubemap4, ivec3(id) + ivec3(1.0, 0.0, 0.0), color);
imageStore(dest_cubemap4, ivec3(id) + ivec3(0.0, 1.0, 0.0), color);
imageStore(dest_cubemap4, ivec3(id) + ivec3(1.0, 1.0, 0.0), color);
#endif
break;
case 5:
imageStore(dest_cubemap5, ivec3(id), color);
#ifdef USE_TEXTURE_ARRAY
imageStore(dest_cubemap5, ivec3(id) + ivec3(1.0, 0.0, 0.0), color);
imageStore(dest_cubemap5, ivec3(id) + ivec3(0.0, 1.0, 0.0), color);
imageStore(dest_cubemap5, ivec3(id) + ivec3(1.0, 1.0, 0.0), color);
#endif
break;
default:
imageStore(dest_cubemap6, ivec3(id), color);
#ifdef USE_TEXTURE_ARRAY
imageStore(dest_cubemap6, ivec3(id) + ivec3(1.0, 0.0, 0.0), color);
imageStore(dest_cubemap6, ivec3(id) + ivec3(0.0, 1.0, 0.0), color);
imageStore(dest_cubemap6, ivec3(id) + ivec3(1.0, 1.0, 0.0), color);
#endif
break;
}
}

View file

@ -10,13 +10,7 @@ VERSION_DEFINES
layout(local_size_x = GROUP_SIZE, local_size_y = GROUP_SIZE, local_size_z = 1) in;
/* clang-format on */
#ifdef MODE_SOURCE_PANORAMA
layout(set = 0, binding = 0) uniform sampler2D source_panorama;
#endif
#ifdef MODE_SOURCE_CUBEMAP
layout(set = 0, binding = 0) uniform samplerCube source_cube;
#endif
layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly imageCube dest_cubemap;
@ -115,24 +109,6 @@ vec2 Hammersley(uint i, uint N) {
return vec2(float(i) / float(N), radicalInverse_VdC(i));
}
#ifdef MODE_SOURCE_PANORAMA
vec4 texturePanorama(vec3 normal, sampler2D pano) {
vec2 st = vec2(
atan(normal.x, -normal.z),
acos(normal.y));
if (st.x < 0.0)
st.x += M_PI * 2.0;
st /= vec2(M_PI * 2.0, M_PI);
return textureLod(pano, st, 0.0);
}
#endif
void main() {
uvec3 id = gl_GlobalInvocationID;
id.z += params.face_id;
@ -144,15 +120,7 @@ void main() {
if (params.use_direct_write) {
#ifdef MODE_SOURCE_PANORAMA
imageStore(dest_cubemap, ivec3(id), vec4(texturePanorama(N, source_panorama).rgb, 1.0));
#endif
#ifdef MODE_SOURCE_CUBEMAP
imageStore(dest_cubemap, ivec3(id), vec4(texture(source_cube, N).rgb, 1.0));
#endif
} else {
vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);
@ -167,13 +135,8 @@ void main() {
float ndotl = clamp(dot(N, L), 0.0, 1.0);
if (ndotl > 0.0) {
#ifdef MODE_SOURCE_PANORAMA
sum.rgb += texturePanorama(L, source_panorama).rgb * ndotl;
#endif
#ifdef MODE_SOURCE_CUBEMAP
sum.rgb += textureLod(source_cube, L, 0.0).rgb * ndotl;
#endif
sum.a += ndotl;
}
}

View file

@ -11,10 +11,8 @@ layout(location = 0) out vec2 uv_interp;
layout(push_constant, binding = 1, std430) uniform Params {
mat3 orientation;
vec4 proj;
float multiplier;
float alpha;
float depth;
float pad;
vec4 position_multiplier;
float time;
}
params;
@ -22,7 +20,7 @@ void main() {
vec2 base_arr[4] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 1.0), vec2(1.0, 1.0), vec2(1.0, -1.0));
uv_interp = base_arr[gl_VertexIndex];
gl_Position = vec4(uv_interp, params.depth, 1.0);
gl_Position = vec4(uv_interp, 1.0, 1.0);
}
/* clang-format off */
@ -37,20 +35,18 @@ VERSION_DEFINES
layout(location = 0) in vec2 uv_interp;
/* clang-format on */
layout(set = 0, binding = 0) uniform sampler2D source_panorama;
layout(push_constant, binding = 1, std430) uniform Params {
mat3 orientation;
vec4 proj;
float multiplier;
float alpha;
float depth;
float pad;
vec4 position_multiplier;
float time; //TODO consider adding vec2 screen res, and float radiance size
}
params;
layout(set = 0, binding = 0) uniform sampler material_samplers[12];
#ifdef USE_MATERIAL_UNIFORMS
layout(set = 3, binding = 0, std140) uniform MaterialUniforms{
layout(set = 1, binding = 0, std140) uniform MaterialUniforms{
/* clang-format off */
MATERIAL_UNIFORMS
@ -59,26 +55,28 @@ MATERIAL_UNIFORMS
} material;
#endif
layout(set = 2, binding = 0) uniform textureCube radiance;
layout(set = 2, binding = 1) uniform texture2D half_res;
layout(set = 2, binding = 2) uniform texture2D quarter_res;
struct DirectionalLightData {
vec3 direction;
float energy;
vec3 color;
bool enabled;
};
layout(set = 3, binding = 0, std140) uniform DirectionalLights {
DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
}
directional_lights;
/* clang-format off */
FRAGMENT_SHADER_GLOBALS
/* clang-format on */
vec4 texturePanorama(sampler2D pano, vec3 normal) {
vec2 st = vec2(
atan(normal.x, normal.z),
acos(normal.y));
if (st.x < 0.0)
st.x += M_PI * 2.0;
st /= vec2(M_PI * 2.0, M_PI);
return texture(pano, st);
}
layout(location = 0) out vec4 frag_color;
void main() {
@ -89,10 +87,22 @@ void main() {
cube_normal.y = -(cube_normal.z * (-uv_interp.y - params.proj.z)) / params.proj.w;
cube_normal = mat3(params.orientation) * cube_normal;
cube_normal.z = -cube_normal.z;
cube_normal = normalize(cube_normal);
vec2 uv = uv_interp * 0.5 + 0.5;
vec2 panorama_coords = vec2(atan(cube_normal.x, cube_normal.z), acos(cube_normal.y));
if (panorama_coords.x < 0.0) {
panorama_coords.x += M_PI * 2.0;
}
panorama_coords /= vec2(M_PI * 2.0, M_PI);
vec3 color = vec3(0.0, 0.0, 0.0);
float alpha = 1.0; // Only available to subpasses
// unused, just here to make our compiler happy, make sure we don't execute any light code the user adds in..
// unused, just here to make our compiler happy, make sure we don't execute any light code the user adds in..
#ifndef REALLYINCLUDETHIS
{
/* clang-format off */
@ -102,8 +112,6 @@ LIGHT_SHADER_CODE
/* clang-format on */
}
#endif
// color = texturePanorama(source_panorama, normalize(cube_normal.xyz)).rgb;
{
/* clang-format off */
@ -112,6 +120,6 @@ FRAGMENT_SHADER_CODE
/* clang-format on */
}
frag_color.rgb = color;
frag_color.a = params.alpha;
frag_color.rgb = color * params.position_multiplier.w;
frag_color.a = alpha;
}

View file

@ -287,8 +287,38 @@ ShaderTypes::ShaderTypes() {
/************ SKY **************************/
shader_modes[VS::SHADER_SKY].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["EYEDIR"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["EYEDIR"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["SKY_COORDS"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["POSITION"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["HALF_RES_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["QUARTER_RES_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["RADIANCE"] = constt(ShaderLanguage::TYPE_SAMPLERCUBE);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["AT_HALF_RES_PASS"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["AT_QUARTER_RES_PASS"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["AT_CUBEMAP_PASS"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT0_ENABLED"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT0_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT0_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT0_COLOR"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT1_ENABLED"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT1_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT1_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT1_COLOR"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT2_ENABLED"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT2_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT2_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT2_COLOR"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT3_ENABLED"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT3_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT3_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["LIGHT3_COLOR"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[VS::SHADER_SKY].modes.push_back("use_half_res_pass");
shader_modes[VS::SHADER_SKY].modes.push_back("use_quarter_res_pass");
shader_types.insert("spatial");
shader_types.insert("canvas_item");

View file

@ -507,7 +507,7 @@ public:
BIND0R(RID, sky_create)
BIND2(sky_set_radiance_size, RID, int)
BIND2(sky_set_mode, RID, SkyMode)
BIND2(sky_set_texture, RID, RID)
BIND2(sky_set_material, RID, RID)
BIND0R(RID, environment_create)
@ -515,7 +515,6 @@ public:
BIND2(environment_set_sky, RID, RID)
BIND2(environment_set_sky_custom_fov, RID, float)
BIND2(environment_set_sky_orientation, RID, const Basis &)
BIND2(environment_set_bg_material, RID, RID)
BIND2(environment_set_bg_color, RID, const Color &)
BIND2(environment_set_bg_energy, RID, float)
BIND2(environment_set_canvas_max_layer, RID, int)

View file

@ -419,7 +419,7 @@ public:
FUNCRID(sky)
FUNC2(sky_set_radiance_size, RID, int)
FUNC2(sky_set_mode, RID, SkyMode)
FUNC2(sky_set_texture, RID, RID)
FUNC2(sky_set_material, RID, RID)
/* ENVIRONMENT API */
@ -429,7 +429,6 @@ public:
FUNC2(environment_set_sky, RID, RID)
FUNC2(environment_set_sky_custom_fov, RID, float)
FUNC2(environment_set_sky_orientation, RID, const Basis &)
FUNC2(environment_set_bg_material, RID, RID)
FUNC2(environment_set_bg_color, RID, const Color &)
FUNC2(environment_set_bg_energy, RID, float)
FUNC2(environment_set_canvas_max_layer, RID, int)

View file

@ -1578,7 +1578,7 @@ void VisualServer::_bind_methods() {
#ifndef _3D_DISABLED
ClassDB::bind_method(D_METHOD("sky_create"), &VisualServer::sky_create);
ClassDB::bind_method(D_METHOD("sky_set_texture", "sky", "panorama"), &VisualServer::sky_set_texture);
ClassDB::bind_method(D_METHOD("sky_set_material", "sky", "material"), &VisualServer::sky_set_material);
#endif
ClassDB::bind_method(D_METHOD("shader_create"), &VisualServer::shader_create);
ClassDB::bind_method(D_METHOD("shader_set_code", "shader", "code"), &VisualServer::shader_set_code);
@ -1797,7 +1797,6 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("environment_set_sky", "env", "sky"), &VisualServer::environment_set_sky);
ClassDB::bind_method(D_METHOD("environment_set_sky_custom_fov", "env", "scale"), &VisualServer::environment_set_sky_custom_fov);
ClassDB::bind_method(D_METHOD("environment_set_sky_orientation", "env", "orientation"), &VisualServer::environment_set_sky_orientation);
ClassDB::bind_method(D_METHOD("environment_set_bg_material", "env", "material"), &VisualServer::environment_set_bg_material);
ClassDB::bind_method(D_METHOD("environment_set_bg_color", "env", "color"), &VisualServer::environment_set_bg_color);
ClassDB::bind_method(D_METHOD("environment_set_bg_energy", "env", "energy"), &VisualServer::environment_set_bg_energy);
ClassDB::bind_method(D_METHOD("environment_set_canvas_max_layer", "env", "max_layer"), &VisualServer::environment_set_canvas_max_layer);
@ -2313,13 +2312,13 @@ VisualServer::VisualServer() {
GLOBAL_DEF("rendering/quality/shadows/filter_mode.mobile", 0);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadows/filter_mode", PropertyInfo(Variant::INT, "rendering/quality/shadows/filter_mode", PROPERTY_HINT_ENUM, "Disabled (Fastest),PCF5,PCF13 (Slowest)"));
GLOBAL_DEF("rendering/quality/reflections/roughness_layers", 6);
GLOBAL_DEF("rendering/quality/reflections/roughness_layers", 8);
GLOBAL_DEF("rendering/quality/reflections/texture_array_reflections", true);
GLOBAL_DEF("rendering/quality/reflections/texture_array_reflections.mobile", false);
GLOBAL_DEF("rendering/quality/reflections/ggx_samples", 1024);
GLOBAL_DEF("rendering/quality/reflections/ggx_samples.mobile", 128);
GLOBAL_DEF("rendering/quality/reflections/fast_filter_high_quality", false);
GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_size", 128);
GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_size", 256);
GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_size.mobile", 128);
GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_count", 64);

View file

@ -682,7 +682,7 @@ public:
virtual RID sky_create() = 0;
virtual void sky_set_radiance_size(RID p_sky, int p_radiance_size) = 0;
virtual void sky_set_mode(RID p_sky, SkyMode p_mode) = 0;
virtual void sky_set_texture(RID p_sky, RID p_panorama) = 0;
virtual void sky_set_material(RID p_sky, RID p_material) = 0;
/* ENVIRONMENT API */
@ -716,7 +716,6 @@ public:
virtual void environment_set_sky(RID p_env, RID p_sky) = 0;
virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0;
virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) = 0;
virtual void environment_set_bg_material(RID p_env, RID p_material) = 0;
virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0;
virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0;
virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0;