Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.x] Add support for 16-bit directional and point light shadow atlases #57430

Open
wants to merge 1 commit into
base: 3.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1682,6 +1682,9 @@
<member name="rendering/quality/depth_prepass/enable" type="bool" setter="" getter="" default="true">
If [code]true[/code], performs a previous depth pass before rendering materials. This increases performance in scenes with high overdraw, when complex materials and lighting are used.
</member>
<member name="rendering/quality/directional_shadow/16_bits" type="bool" setter="" getter="" default="true">
If [code]true[/code], renders directional shadows on a buffer with 16-bit precision. This results in slightly better performance with usually no noticeable visual difference. If [code]false[/code], renders directional shadows on a buffer with 24-bit precision.
</member>
<member name="rendering/quality/directional_shadow/size" type="int" setter="" getter="" default="4096">
The directional shadow's size in pixels. Higher values will result in sharper shadows, at the cost of performance. The value will be rounded up to the nearest power of 2. This setting can be changed at run-time; the change will be applied immediately.
</member>
Expand Down Expand Up @@ -1779,6 +1782,9 @@
If [code]true[/code], enables new physical light attenuation for [OmniLight]s and [SpotLight]s. This results in more realistic lighting appearance with a very small performance cost. When physical light attenuation is enabled, lights will appear to be darker as a result of the new attenuation formula. This can be compensated by adjusting the lights' energy or attenuation values.
Changes to this setting will only be applied upon restarting the application.
</member>
<member name="rendering/quality/shadow_atlas/16_bits" type="bool" setter="" getter="" default="true">
If [code]true[/code], renders point light shadows on a buffer with 16-bit precision. This results in slightly better performance with usually no noticeable visual difference. If [code]false[/code], renders point light shadows on a buffer with 24-bit precision.
</member>
<member name="rendering/quality/shadow_atlas/cubemap_size" type="int" setter="" getter="" default="512">
Size for cubemap into which the shadow is rendered before being copied into the shadow atlas. A higher number can result in higher resolution shadows when used with a higher [member rendering/quality/shadow_atlas/size]. Setting higher than a quarter of the [member rendering/quality/shadow_atlas/size] will not result in a perceptible increase in visual quality.
</member>
Expand Down
3 changes: 3 additions & 0 deletions doc/classes/Viewport.xml
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,9 @@
<member name="render_target_v_flip" type="bool" setter="set_vflip" getter="get_vflip" default="false">
If [code]true[/code], the result of rendering will be flipped vertically. Since Viewports in Godot 3.x render upside-down, it's recommended to set this to [code]true[/code] in most situations.
</member>
<member name="shadow_atlas_16_bits" type="bool" setter="set_shadow_atlas_16_bits" getter="is_shadow_atlas_16_bits" default="true">
If [code]true[/code], renders point light shadows on a buffer with 16-bit precision. This results in slightly better performance with usually no noticeable visual difference. If [code]false[/code], renders point light shadows on a buffer with 24-bit precision.
</member>
<member name="shadow_atlas_quad_0" type="int" setter="set_shadow_atlas_quadrant_subdiv" getter="get_shadow_atlas_quadrant_subdiv" enum="Viewport.ShadowAtlasQuadrantSubdiv" default="2">
The subdivision amount of the first quadrant on the shadow atlas.
</member>
Expand Down
3 changes: 2 additions & 1 deletion doc/classes/VisualServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3182,8 +3182,9 @@
<return type="void" />
<argument index="0" name="viewport" type="RID" />
<argument index="1" name="size" type="int" />
<argument index="2" name="use_16_bits" type="bool" default="true" />
<description>
Sets the size of the shadow atlas's images (used for omni and spot lights). The value will be rounded up to the nearest power of 2.
Sets the size of the shadow atlas's images (used for omni and spot lights). The value will be rounded up to the nearest power of 2. If [code]use_16_bits[/code] is [code]true[/code], renders point light shadows on a buffer with 16-bit precision. This results in slightly better performance with usually no noticeable visual difference. If [code]use_16_bits[/code] is [code]false[/code], renders point light shadows on a buffer with 24-bit precision.
</description>
</method>
<method name="viewport_set_sharpen_intensity">
Expand Down
2 changes: 1 addition & 1 deletion drivers/dummy/rasterizer_dummy.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class RasterizerSceneDummy : public RasterizerScene {
/* SHADOW ATLAS API */

RID shadow_atlas_create() { return RID(); }
void shadow_atlas_set_size(RID p_atlas, int p_size) {}
void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) {}
void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) {}
bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) { return false; }

Expand Down
20 changes: 13 additions & 7 deletions drivers/gles2/rasterizer_scene_gles2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ void RasterizerSceneGLES2::directional_shadow_create() {

directional_shadow.light_count = 0;
directional_shadow.size = next_power_of_2(directional_shadow_size);
directional_shadow.use_16_bits = directional_shadow_16_bits;

if (directional_shadow.size > storage->config.max_viewport_dimensions[0] || directional_shadow.size > storage->config.max_viewport_dimensions[1]) {
WARN_PRINT("Cannot set directional shadow size larger than maximum hardware supported size of (" + itos(storage->config.max_viewport_dimensions[0]) + ", " + itos(storage->config.max_viewport_dimensions[1]) + "). Setting size to maximum.");
Expand All @@ -90,7 +91,7 @@ void RasterizerSceneGLES2::directional_shadow_create() {
//maximum compatibility, renderbuffer and RGBA shadow
glGenRenderbuffers(1, &directional_shadow.depth);
glBindRenderbuffer(GL_RENDERBUFFER, directional_shadow.depth);
glRenderbufferStorage(GL_RENDERBUFFER, storage->config.depth_buffer_internalformat, directional_shadow.size, directional_shadow.size);
glRenderbufferStorage(GL_RENDERBUFFER, directional_shadow.use_16_bits ? GL_DEPTH_COMPONENT16 : storage->config.depth_buffer_internalformat, directional_shadow.size, directional_shadow.size);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, directional_shadow.depth);

glGenTextures(1, &directional_shadow.color);
Expand All @@ -106,7 +107,7 @@ void RasterizerSceneGLES2::directional_shadow_create() {
glGenTextures(1, &directional_shadow.depth);
glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);

glTexImage2D(GL_TEXTURE_2D, 0, storage->config.depth_internalformat, directional_shadow.size, directional_shadow.size, 0, GL_DEPTH_COMPONENT, storage->config.depth_type, nullptr);
glTexImage2D(GL_TEXTURE_2D, 0, directional_shadow.use_16_bits ? GL_DEPTH_COMPONENT16 : storage->config.depth_internalformat, directional_shadow.size, directional_shadow.size, 0, GL_DEPTH_COMPONENT, storage->config.depth_type, nullptr);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
Expand All @@ -130,6 +131,7 @@ RID RasterizerSceneGLES2::shadow_atlas_create() {
shadow_atlas->depth = 0;
shadow_atlas->color = 0;
shadow_atlas->size = 0;
shadow_atlas->use_16_bits = true;
shadow_atlas->smallest_subdiv = 0;

for (int i = 0; i < 4; i++) {
Expand All @@ -139,14 +141,14 @@ RID RasterizerSceneGLES2::shadow_atlas_create() {
return shadow_atlas_owner.make_rid(shadow_atlas);
}

void RasterizerSceneGLES2::shadow_atlas_set_size(RID p_atlas, int p_size) {
void RasterizerSceneGLES2::shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits) {
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas);
ERR_FAIL_COND(!shadow_atlas);
ERR_FAIL_COND(p_size < 0);

p_size = next_power_of_2(p_size);

if (p_size == shadow_atlas->size) {
if (p_size == shadow_atlas->size && p_16_bits == shadow_atlas->use_16_bits) {
return;
}

Expand Down Expand Up @@ -177,6 +179,7 @@ void RasterizerSceneGLES2::shadow_atlas_set_size(RID p_atlas, int p_size) {
shadow_atlas->shadow_owners.clear();

shadow_atlas->size = p_size;
shadow_atlas->use_16_bits = p_16_bits;

if (shadow_atlas->size) {
glGenFramebuffers(1, &shadow_atlas->fbo);
Expand All @@ -195,7 +198,7 @@ void RasterizerSceneGLES2::shadow_atlas_set_size(RID p_atlas, int p_size) {
//maximum compatibility, renderbuffer and RGBA shadow
glGenRenderbuffers(1, &shadow_atlas->depth);
glBindRenderbuffer(GL_RENDERBUFFER, shadow_atlas->depth);
glRenderbufferStorage(GL_RENDERBUFFER, storage->config.depth_buffer_internalformat, shadow_atlas->size, shadow_atlas->size);
glRenderbufferStorage(GL_RENDERBUFFER, shadow_atlas->use_16_bits ? GL_DEPTH_COMPONENT16 : storage->config.depth_buffer_internalformat, shadow_atlas->size, shadow_atlas->size);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, shadow_atlas->depth);

glGenTextures(1, &shadow_atlas->color);
Expand All @@ -210,7 +213,7 @@ void RasterizerSceneGLES2::shadow_atlas_set_size(RID p_atlas, int p_size) {
//just depth texture
glGenTextures(1, &shadow_atlas->depth);
glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
glTexImage2D(GL_TEXTURE_2D, 0, storage->config.depth_internalformat, shadow_atlas->size, shadow_atlas->size, 0, GL_DEPTH_COMPONENT, storage->config.depth_type, nullptr);
glTexImage2D(GL_TEXTURE_2D, 0, shadow_atlas->use_16_bits ? GL_DEPTH_COMPONENT16 : storage->config.depth_internalformat, shadow_atlas->size, shadow_atlas->size, 0, GL_DEPTH_COMPONENT, storage->config.depth_type, nullptr);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
Expand Down Expand Up @@ -4111,8 +4114,10 @@ void RasterizerSceneGLES2::iteration() {
shadow_filter_mode = ShadowFilterMode(int(GLOBAL_GET("rendering/quality/shadows/filter_mode")));

const int directional_shadow_size_new = next_power_of_2(int(GLOBAL_GET("rendering/quality/directional_shadow/size")));
if (directional_shadow_size != directional_shadow_size_new) {
const bool directional_shadow_16_bits_new = bool(GLOBAL_GET("rendering/quality/directional_shadow/16_bits"));
if (directional_shadow_size != directional_shadow_size_new || directional_shadow_16_bits_new != directional_shadow_16_bits) {
directional_shadow_size = directional_shadow_size_new;
directional_shadow_16_bits = directional_shadow_16_bits_new;
directional_shadow_create();
}
}
Expand All @@ -4123,6 +4128,7 @@ void RasterizerSceneGLES2::finalize() {
RasterizerSceneGLES2::RasterizerSceneGLES2() {
_light_counter = 0;
directional_shadow_size = next_power_of_2(int(GLOBAL_GET("rendering/quality/directional_shadow/size")));
directional_shadow_16_bits = bool(GLOBAL_GET("rendering/quality/directional_shadow/16_bits"));
}

RasterizerSceneGLES2::~RasterizerSceneGLES2() {
Expand Down
5 changes: 4 additions & 1 deletion drivers/gles2/rasterizer_scene_gles2.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ class RasterizerSceneGLES2 : public RasterizerScene {
uint32_t smallest_subdiv;

int size;
bool use_16_bits;

GLuint fbo;
GLuint depth;
Expand All @@ -278,11 +279,12 @@ class RasterizerSceneGLES2 : public RasterizerScene {
RID_Owner<ShadowAtlas> shadow_atlas_owner;

int directional_shadow_size;
bool directional_shadow_16_bits;

void directional_shadow_create();

RID shadow_atlas_create();
void shadow_atlas_set_size(RID p_atlas, int p_size);
void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true);
void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision);
bool _shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow);
bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version);
Expand All @@ -294,6 +296,7 @@ class RasterizerSceneGLES2 : public RasterizerScene {

int light_count = 0;
int size = 0;
bool use_16_bits = true;
int current_light = 0;
} directional_shadow;

Expand Down
16 changes: 11 additions & 5 deletions drivers/gles3/rasterizer_scene_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,12 @@ void RasterizerSceneGLES3::directional_shadow_create() {

directional_shadow.light_count = 0;
directional_shadow.size = next_power_of_2(directional_shadow_size);
directional_shadow.use_16_bits = directional_shadow_16_bits;
glGenFramebuffers(1, &directional_shadow.fbo);
glBindFramebuffer(GL_FRAMEBUFFER, directional_shadow.fbo);
glGenTextures(1, &directional_shadow.depth);
glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, directional_shadow.size, directional_shadow.size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
glTexImage2D(GL_TEXTURE_2D, 0, directional_shadow.use_16_bits ? GL_DEPTH_COMPONENT16 : GL_DEPTH_COMPONENT24, directional_shadow.size, directional_shadow.size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
Expand All @@ -115,6 +116,7 @@ RID RasterizerSceneGLES3::shadow_atlas_create() {
shadow_atlas->fbo = 0;
shadow_atlas->depth = 0;
shadow_atlas->size = 0;
shadow_atlas->use_16_bits = true;
shadow_atlas->smallest_subdiv = 0;

for (int i = 0; i < 4; i++) {
Expand All @@ -124,14 +126,14 @@ RID RasterizerSceneGLES3::shadow_atlas_create() {
return shadow_atlas_owner.make_rid(shadow_atlas);
}

void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas, int p_size) {
void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits) {
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas);
ERR_FAIL_COND(!shadow_atlas);
ERR_FAIL_COND(p_size < 0);

p_size = next_power_of_2(p_size);

if (p_size == shadow_atlas->size) {
if (p_size == shadow_atlas->size && p_16_bits == shadow_atlas->use_16_bits) {
return;
}

Expand Down Expand Up @@ -160,6 +162,7 @@ void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas, int p_size) {
shadow_atlas->shadow_owners.clear();

shadow_atlas->size = p_size;
shadow_atlas->use_16_bits = p_16_bits;

if (shadow_atlas->size) {
glGenFramebuffers(1, &shadow_atlas->fbo);
Expand All @@ -169,7 +172,7 @@ void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas, int p_size) {
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &shadow_atlas->depth);
glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, shadow_atlas->size, shadow_atlas->size, 0,
glTexImage2D(GL_TEXTURE_2D, 0, shadow_atlas->use_16_bits ? GL_DEPTH_COMPONENT16 : GL_DEPTH_COMPONENT24, shadow_atlas->size, shadow_atlas->size, 0,
GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
Expand Down Expand Up @@ -5329,8 +5332,10 @@ void RasterizerSceneGLES3::iteration() {
shadow_filter_mode = ShadowFilterMode(int(GLOBAL_GET("rendering/quality/shadows/filter_mode")));

const int directional_shadow_size_new = next_power_of_2(int(GLOBAL_GET("rendering/quality/directional_shadow/size")));
if (directional_shadow_size != directional_shadow_size_new) {
const bool directional_shadow_16_bits_new = bool(GLOBAL_GET("rendering/quality/directional_shadow/16_bits"));
if (directional_shadow_size != directional_shadow_size_new || directional_shadow_16_bits_new != directional_shadow_16_bits) {
directional_shadow_size = directional_shadow_size_new;
directional_shadow_16_bits = directional_shadow_16_bits_new;
directional_shadow_create();
}

Expand All @@ -5349,6 +5354,7 @@ void RasterizerSceneGLES3::finalize() {

RasterizerSceneGLES3::RasterizerSceneGLES3() {
directional_shadow_size = next_power_of_2(int(GLOBAL_GET("rendering/quality/directional_shadow/size")));
directional_shadow_16_bits = bool(GLOBAL_GET("rendering/quality/directional_shadow/16_bits"));
}

RasterizerSceneGLES3::~RasterizerSceneGLES3() {
Expand Down
5 changes: 4 additions & 1 deletion drivers/gles3/rasterizer_scene_gles3.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ class RasterizerSceneGLES3 : public RasterizerScene {
uint32_t smallest_subdiv;

int size;
bool use_16_bits;

GLuint fbo;
GLuint depth;
Expand All @@ -269,10 +270,11 @@ class RasterizerSceneGLES3 : public RasterizerScene {
RID_Owner<ShadowAtlas> shadow_atlas_owner;

int directional_shadow_size;
bool directional_shadow_16_bits;

void directional_shadow_create();
RID shadow_atlas_create();
void shadow_atlas_set_size(RID p_atlas, int p_size);
void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true);
void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision);
bool _shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow);
bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version);
Expand All @@ -282,6 +284,7 @@ class RasterizerSceneGLES3 : public RasterizerScene {
GLuint depth = 0;
int light_count = 0;
int size = 0;
bool use_16_bits = true;
int current_light = 0;
} directional_shadow;

Expand Down
20 changes: 19 additions & 1 deletion scene/main/viewport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1354,13 +1354,26 @@ void Viewport::set_shadow_atlas_size(int p_size) {
}

shadow_atlas_size = p_size;
VS::get_singleton()->viewport_set_shadow_atlas_size(viewport, p_size);
VS::get_singleton()->viewport_set_shadow_atlas_size(viewport, p_size, shadow_atlas_16_bits);
}

int Viewport::get_shadow_atlas_size() const {
return shadow_atlas_size;
}

void Viewport::set_shadow_atlas_16_bits(bool p_16_bits) {
if (shadow_atlas_16_bits == p_16_bits) {
return;
}

shadow_atlas_16_bits = p_16_bits;
VS::get_singleton()->viewport_set_shadow_atlas_size(viewport, shadow_atlas_size, p_16_bits);
}

bool Viewport::is_shadow_atlas_16_bits() const {
return shadow_atlas_16_bits;
}

void Viewport::set_shadow_atlas_quadrant_subdiv(int p_quadrant, ShadowAtlasQuadrantSubdiv p_subdiv) {
ERR_FAIL_INDEX(p_quadrant, 4);
ERR_FAIL_INDEX(p_subdiv, SHADOW_ATLAS_QUADRANT_SUBDIV_MAX);
Expand Down Expand Up @@ -3346,6 +3359,9 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_shadow_atlas_size", "size"), &Viewport::set_shadow_atlas_size);
ClassDB::bind_method(D_METHOD("get_shadow_atlas_size"), &Viewport::get_shadow_atlas_size);

ClassDB::bind_method(D_METHOD("set_shadow_atlas_16_bits", "16_bits"), &Viewport::set_shadow_atlas_16_bits);
ClassDB::bind_method(D_METHOD("is_shadow_atlas_16_bits"), &Viewport::is_shadow_atlas_16_bits);

ClassDB::bind_method(D_METHOD("set_snap_controls_to_pixels", "enabled"), &Viewport::set_snap_controls_to_pixels);
ClassDB::bind_method(D_METHOD("is_snap_controls_to_pixels_enabled"), &Viewport::is_snap_controls_to_pixels_enabled);

Expand Down Expand Up @@ -3399,6 +3415,7 @@ void Viewport::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_snap_controls_to_pixels"), "set_snap_controls_to_pixels", "is_snap_controls_to_pixels_enabled");
ADD_GROUP("Shadow Atlas", "shadow_atlas_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_atlas_size", PROPERTY_HINT_RANGE, "0,16384,256"), "set_shadow_atlas_size", "get_shadow_atlas_size");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_atlas_16_bits"), "set_shadow_atlas_16_bits", "is_shadow_atlas_16_bits");
ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_0", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 0);
ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_1", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 1);
ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_2", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 2);
Expand Down Expand Up @@ -3502,6 +3519,7 @@ Viewport::Viewport() {
physics_last_mousepos = Vector2(Math_INF, Math_INF);

shadow_atlas_size = 0;
shadow_atlas_16_bits = true;
for (int i = 0; i < 4; i++) {
shadow_atlas_quadrant_subdiv[i] = SHADOW_ATLAS_QUADRANT_SUBDIV_MAX;
}
Expand Down
Loading