mirror of
https://github.com/Relintai/pandemonium_engine_minimal.git
synced 2024-11-17 22:17:19 +01:00
More shadow related code cleanups.
This commit is contained in:
parent
d821a15748
commit
d3ca4c124d
@ -38,18 +38,7 @@
|
|||||||
|
|
||||||
class RasterizerSceneDummy : public RasterizerScene {
|
class RasterizerSceneDummy : public RasterizerScene {
|
||||||
public:
|
public:
|
||||||
/* SHADOW ATLAS API */
|
void render_scene(const Transform &p_cam_transform, const Projection &p_cam_projection, const int p_eye, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count) {}
|
||||||
|
|
||||||
RID shadow_atlas_create() { return RID(); }
|
|
||||||
void shadow_atlas_set_size(RID p_atlas, int p_size) {}
|
|
||||||
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; }
|
|
||||||
|
|
||||||
int get_directional_light_shadow_size(RID p_light_intance) { return 0; }
|
|
||||||
void set_directional_shadow_count(int p_count) {}
|
|
||||||
|
|
||||||
void render_scene(const Transform &p_cam_transform, const Projection &p_cam_projection, const int p_eye, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID p_environment, RID p_shadow_atlas) {}
|
|
||||||
void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {}
|
|
||||||
|
|
||||||
void set_scene_pass(uint64_t p_pass) {}
|
void set_scene_pass(uint64_t p_pass) {}
|
||||||
void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) {}
|
void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) {}
|
||||||
|
@ -52,416 +52,9 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const GLenum RasterizerSceneGLES2::_cube_side_enum[6] = {
|
|
||||||
|
|
||||||
GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
|
|
||||||
GL_TEXTURE_CUBE_MAP_POSITIVE_X,
|
|
||||||
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
|
||||||
GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
|
|
||||||
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
|
|
||||||
GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
void RasterizerSceneGLES2::directional_shadow_create() {
|
|
||||||
if (directional_shadow.fbo) {
|
|
||||||
// Erase existing directional shadow texture to recreate it.
|
|
||||||
glDeleteTextures(1, &directional_shadow.depth);
|
|
||||||
glDeleteFramebuffers(1, &directional_shadow.fbo);
|
|
||||||
|
|
||||||
directional_shadow.depth = 0;
|
|
||||||
directional_shadow.fbo = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
directional_shadow.light_count = 0;
|
|
||||||
directional_shadow.size = next_power_of_2(directional_shadow_size);
|
|
||||||
|
|
||||||
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.");
|
|
||||||
directional_shadow.size = MIN(directional_shadow.size, storage->config.max_viewport_dimensions[0]);
|
|
||||||
directional_shadow.size = MIN(directional_shadow.size, storage->config.max_viewport_dimensions[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
glGenFramebuffers(1, &directional_shadow.fbo);
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, directional_shadow.fbo);
|
|
||||||
|
|
||||||
if (storage->config.use_rgba_3d_shadows) {
|
|
||||||
//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);
|
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, directional_shadow.depth);
|
|
||||||
|
|
||||||
glGenTextures(1, &directional_shadow.color);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, directional_shadow.color);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, directional_shadow.size, directional_shadow.size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, directional_shadow.color, 0);
|
|
||||||
} else {
|
|
||||||
//just a depth buffer
|
|
||||||
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);
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, directional_shadow.depth, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
|
||||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
|
||||||
ERR_PRINT("Directional shadow framebuffer status invalid");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SHADOW ATLAS API */
|
|
||||||
|
|
||||||
RID RasterizerSceneGLES2::shadow_atlas_create() {
|
|
||||||
ShadowAtlas *shadow_atlas = memnew(ShadowAtlas);
|
|
||||||
shadow_atlas->fbo = 0;
|
|
||||||
shadow_atlas->depth = 0;
|
|
||||||
shadow_atlas->color = 0;
|
|
||||||
shadow_atlas->size = 0;
|
|
||||||
shadow_atlas->smallest_subdiv = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
shadow_atlas->size_order[i] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return shadow_atlas_owner.make_rid(shadow_atlas);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RasterizerSceneGLES2::shadow_atlas_set_size(RID p_atlas, int p_size) {
|
|
||||||
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) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// erase the old atlast
|
|
||||||
if (shadow_atlas->fbo) {
|
|
||||||
if (storage->config.use_rgba_3d_shadows) {
|
|
||||||
glDeleteRenderbuffers(1, &shadow_atlas->depth);
|
|
||||||
} else {
|
|
||||||
glDeleteTextures(1, &shadow_atlas->depth);
|
|
||||||
}
|
|
||||||
glDeleteFramebuffers(1, &shadow_atlas->fbo);
|
|
||||||
if (shadow_atlas->color) {
|
|
||||||
glDeleteTextures(1, &shadow_atlas->color);
|
|
||||||
}
|
|
||||||
|
|
||||||
shadow_atlas->fbo = 0;
|
|
||||||
shadow_atlas->depth = 0;
|
|
||||||
shadow_atlas->color = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
shadow_atlas->shadow_owners.clear();
|
|
||||||
|
|
||||||
shadow_atlas->size = p_size;
|
|
||||||
|
|
||||||
if (shadow_atlas->size) {
|
|
||||||
glGenFramebuffers(1, &shadow_atlas->fbo);
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, shadow_atlas->fbo);
|
|
||||||
|
|
||||||
if (shadow_atlas->size > storage->config.max_viewport_dimensions[0] || shadow_atlas->size > storage->config.max_viewport_dimensions[1]) {
|
|
||||||
WARN_PRINT("Cannot set shadow atlas 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.");
|
|
||||||
shadow_atlas->size = MIN(shadow_atlas->size, storage->config.max_viewport_dimensions[0]);
|
|
||||||
shadow_atlas->size = MIN(shadow_atlas->size, storage->config.max_viewport_dimensions[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a depth texture
|
|
||||||
WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
|
|
||||||
|
|
||||||
if (storage->config.use_rgba_3d_shadows) {
|
|
||||||
//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);
|
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, shadow_atlas->depth);
|
|
||||||
|
|
||||||
glGenTextures(1, &shadow_atlas->color);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, shadow_atlas->color);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, shadow_atlas->size, shadow_atlas->size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, shadow_atlas->color, 0);
|
|
||||||
} else {
|
|
||||||
//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);
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadow_atlas->depth, 0);
|
|
||||||
}
|
|
||||||
glViewport(0, 0, shadow_atlas->size, shadow_atlas->size);
|
|
||||||
|
|
||||||
glDepthMask(GL_TRUE);
|
|
||||||
|
|
||||||
glClearDepth(0.0f);
|
|
||||||
glClear(GL_DEPTH_BUFFER_BIT);
|
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RasterizerSceneGLES2::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) {
|
|
||||||
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas);
|
|
||||||
ERR_FAIL_COND(!shadow_atlas);
|
|
||||||
ERR_FAIL_INDEX(p_quadrant, 4);
|
|
||||||
ERR_FAIL_INDEX(p_subdivision, 16384);
|
|
||||||
|
|
||||||
uint32_t subdiv = next_power_of_2(p_subdivision);
|
|
||||||
if (subdiv & 0xaaaaaaaa) { // sqrt(subdiv) must be integer
|
|
||||||
subdiv <<= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
subdiv = int(Math::sqrt((float)subdiv));
|
|
||||||
|
|
||||||
if (shadow_atlas->quadrants[p_quadrant].shadows.size() == (int)subdiv) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
shadow_atlas->quadrants[p_quadrant].shadows.resize(0);
|
|
||||||
shadow_atlas->quadrants[p_quadrant].shadows.resize(subdiv);
|
|
||||||
shadow_atlas->quadrants[p_quadrant].subdivision = subdiv;
|
|
||||||
|
|
||||||
// cache the smallest subdivision for faster allocations
|
|
||||||
|
|
||||||
shadow_atlas->smallest_subdiv = 1 << 30;
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
if (shadow_atlas->quadrants[i].subdivision) {
|
|
||||||
shadow_atlas->smallest_subdiv = MIN(shadow_atlas->smallest_subdiv, shadow_atlas->quadrants[i].subdivision);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shadow_atlas->smallest_subdiv == 1 << 30) {
|
|
||||||
shadow_atlas->smallest_subdiv = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// re-sort the quadrants
|
|
||||||
|
|
||||||
int swaps = 0;
|
|
||||||
do {
|
|
||||||
swaps = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
if (shadow_atlas->quadrants[shadow_atlas->size_order[i]].subdivision < shadow_atlas->quadrants[shadow_atlas->size_order[i + 1]].subdivision) {
|
|
||||||
SWAP(shadow_atlas->size_order[i], shadow_atlas->size_order[i + 1]);
|
|
||||||
swaps++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} while (swaps > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RasterizerSceneGLES2::_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) {
|
|
||||||
for (int i = p_quadrant_count - 1; i >= 0; i--) {
|
|
||||||
int qidx = p_in_quadrants[i];
|
|
||||||
|
|
||||||
if (shadow_atlas->quadrants[qidx].subdivision == (uint32_t)p_current_subdiv) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// look for an empty space
|
|
||||||
|
|
||||||
int sc = shadow_atlas->quadrants[qidx].shadows.size();
|
|
||||||
|
|
||||||
ShadowAtlas::Quadrant::Shadow *sarr = shadow_atlas->quadrants[qidx].shadows.ptrw();
|
|
||||||
|
|
||||||
int found_free_idx = -1; // found a free one
|
|
||||||
int found_used_idx = -1; // found an existing one, must steal it
|
|
||||||
uint64_t min_pass = 0; // pass of the existing one, try to use the least recently
|
|
||||||
|
|
||||||
if (found_free_idx == -1 && found_used_idx == -1) {
|
|
||||||
continue; // nothing found
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found_free_idx == -1 && found_used_idx != -1) {
|
|
||||||
found_free_idx = found_used_idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_quadrant = qidx;
|
|
||||||
r_shadow = found_free_idx;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RasterizerSceneGLES2::shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) {
|
|
||||||
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas);
|
|
||||||
ERR_FAIL_COND_V(!shadow_atlas, false);
|
|
||||||
|
|
||||||
if (shadow_atlas->size == 0 || shadow_atlas->smallest_subdiv == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t quad_size = shadow_atlas->size >> 1;
|
|
||||||
int desired_fit = MIN(quad_size / shadow_atlas->smallest_subdiv, next_power_of_2(quad_size * p_coverage));
|
|
||||||
|
|
||||||
int valid_quadrants[4];
|
|
||||||
int valid_quadrant_count = 0;
|
|
||||||
int best_size = -1;
|
|
||||||
int best_subdiv = -1;
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
int q = shadow_atlas->size_order[i];
|
|
||||||
int sd = shadow_atlas->quadrants[q].subdivision;
|
|
||||||
|
|
||||||
if (sd == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int max_fit = quad_size / sd;
|
|
||||||
|
|
||||||
if (best_size != -1 && max_fit > best_size) {
|
|
||||||
break; // what we asked for is bigger than this.
|
|
||||||
}
|
|
||||||
|
|
||||||
valid_quadrants[valid_quadrant_count] = q;
|
|
||||||
valid_quadrant_count++;
|
|
||||||
|
|
||||||
best_subdiv = sd;
|
|
||||||
|
|
||||||
if (max_fit >= desired_fit) {
|
|
||||||
best_size = max_fit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ERR_FAIL_COND_V(valid_quadrant_count == 0, false); // no suitable block available
|
|
||||||
|
|
||||||
uint64_t tick = OS::get_singleton()->get_ticks_msec();
|
|
||||||
|
|
||||||
if (shadow_atlas->shadow_owners.has(p_light_intance)) {
|
|
||||||
// light was already known!
|
|
||||||
|
|
||||||
uint32_t key = shadow_atlas->shadow_owners[p_light_intance];
|
|
||||||
uint32_t q = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
|
|
||||||
uint32_t s = key & ShadowAtlas::SHADOW_INDEX_MASK;
|
|
||||||
|
|
||||||
bool should_realloc = shadow_atlas->quadrants[q].subdivision != (uint32_t)best_subdiv && (shadow_atlas->quadrants[q].shadows[s].alloc_tick - tick > shadow_atlas_realloc_tolerance_msec);
|
|
||||||
|
|
||||||
bool should_redraw = shadow_atlas->quadrants[q].shadows[s].version != p_light_version;
|
|
||||||
|
|
||||||
if (!should_realloc) {
|
|
||||||
shadow_atlas->quadrants[q].shadows.write[s].version = p_light_version;
|
|
||||||
return should_redraw;
|
|
||||||
}
|
|
||||||
|
|
||||||
int new_quadrant;
|
|
||||||
int new_shadow;
|
|
||||||
|
|
||||||
// find a better place
|
|
||||||
|
|
||||||
if (_shadow_atlas_find_shadow(shadow_atlas, valid_quadrants, valid_quadrant_count, shadow_atlas->quadrants[q].subdivision, tick, new_quadrant, new_shadow)) {
|
|
||||||
// found a better place
|
|
||||||
|
|
||||||
ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_shadow];
|
|
||||||
if (sh->owner.is_valid()) {
|
|
||||||
// it is take but invalid, so we can take it
|
|
||||||
|
|
||||||
shadow_atlas->shadow_owners.erase(sh->owner);
|
|
||||||
}
|
|
||||||
|
|
||||||
// erase previous
|
|
||||||
shadow_atlas->quadrants[q].shadows.write[s].version = 0;
|
|
||||||
shadow_atlas->quadrants[q].shadows.write[s].owner = RID();
|
|
||||||
|
|
||||||
sh->owner = p_light_intance;
|
|
||||||
sh->alloc_tick = tick;
|
|
||||||
sh->version = p_light_version;
|
|
||||||
|
|
||||||
// make a new key
|
|
||||||
key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT;
|
|
||||||
key |= new_shadow;
|
|
||||||
|
|
||||||
// update it in the map
|
|
||||||
shadow_atlas->shadow_owners[p_light_intance] = key;
|
|
||||||
|
|
||||||
// make it dirty, so we redraw
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// no better place found, so we keep the current place
|
|
||||||
|
|
||||||
shadow_atlas->quadrants[q].shadows.write[s].version = p_light_version;
|
|
||||||
|
|
||||||
return should_redraw;
|
|
||||||
}
|
|
||||||
|
|
||||||
int new_quadrant;
|
|
||||||
int new_shadow;
|
|
||||||
|
|
||||||
if (_shadow_atlas_find_shadow(shadow_atlas, valid_quadrants, valid_quadrant_count, -1, tick, new_quadrant, new_shadow)) {
|
|
||||||
// found a better place
|
|
||||||
|
|
||||||
ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_shadow];
|
|
||||||
if (sh->owner.is_valid()) {
|
|
||||||
// it is take but invalid, so we can take it
|
|
||||||
|
|
||||||
shadow_atlas->shadow_owners.erase(sh->owner);
|
|
||||||
}
|
|
||||||
|
|
||||||
sh->owner = p_light_intance;
|
|
||||||
sh->alloc_tick = tick;
|
|
||||||
sh->version = p_light_version;
|
|
||||||
|
|
||||||
// make a new key
|
|
||||||
uint32_t key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT;
|
|
||||||
key |= new_shadow;
|
|
||||||
|
|
||||||
// update it in the map
|
|
||||||
shadow_atlas->shadow_owners[p_light_intance] = key;
|
|
||||||
|
|
||||||
// make it dirty, so we redraw
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RasterizerSceneGLES2::set_directional_shadow_count(int p_count) {
|
|
||||||
directional_shadow.light_count = p_count;
|
|
||||||
directional_shadow.current_light = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int RasterizerSceneGLES2::get_directional_light_shadow_size(RID p_light_intance) {
|
|
||||||
ERR_FAIL_COND_V(directional_shadow.light_count == 0, 0);
|
|
||||||
|
|
||||||
int shadow_size;
|
|
||||||
|
|
||||||
if (directional_shadow.light_count == 1) {
|
|
||||||
shadow_size = directional_shadow.size;
|
|
||||||
} else {
|
|
||||||
shadow_size = directional_shadow.size / 2; //more than 4 not supported anyway
|
|
||||||
}
|
|
||||||
|
|
||||||
return shadow_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
|
|
||||||
void RasterizerSceneGLES2::_add_geometry(RasterizerStorageGLES2::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES2::GeometryOwner *p_owner, int p_material, bool p_depth_pass, bool p_shadow_pass) {
|
void RasterizerSceneGLES2::_add_geometry(RasterizerStorageGLES2::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES2::GeometryOwner *p_owner, int p_material, bool p_depth_pass) {
|
||||||
RasterizerStorageGLES2::Material *material = nullptr;
|
RasterizerStorageGLES2::Material *material = nullptr;
|
||||||
RID material_src;
|
RID material_src;
|
||||||
|
|
||||||
@ -487,7 +80,7 @@ void RasterizerSceneGLES2::_add_geometry(RasterizerStorageGLES2::Geometry *p_geo
|
|||||||
|
|
||||||
ERR_FAIL_COND(!material);
|
ERR_FAIL_COND(!material);
|
||||||
|
|
||||||
_add_geometry_with_material(p_geometry, p_instance, p_owner, material, p_depth_pass, p_shadow_pass);
|
_add_geometry_with_material(p_geometry, p_instance, p_owner, material, p_depth_pass);
|
||||||
|
|
||||||
while (material->next_pass.is_valid()) {
|
while (material->next_pass.is_valid()) {
|
||||||
material = storage->material_owner.getornull(material->next_pass);
|
material = storage->material_owner.getornull(material->next_pass);
|
||||||
@ -496,7 +89,7 @@ void RasterizerSceneGLES2::_add_geometry(RasterizerStorageGLES2::Geometry *p_geo
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
_add_geometry_with_material(p_geometry, p_instance, p_owner, material, p_depth_pass, p_shadow_pass);
|
_add_geometry_with_material(p_geometry, p_instance, p_owner, material, p_depth_pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Repeat the "nested chain" logic also for the overlay
|
// Repeat the "nested chain" logic also for the overlay
|
||||||
@ -507,7 +100,7 @@ void RasterizerSceneGLES2::_add_geometry(RasterizerStorageGLES2::Geometry *p_geo
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_add_geometry_with_material(p_geometry, p_instance, p_owner, material, p_depth_pass, p_shadow_pass);
|
_add_geometry_with_material(p_geometry, p_instance, p_owner, material, p_depth_pass);
|
||||||
|
|
||||||
while (material->next_pass.is_valid()) {
|
while (material->next_pass.is_valid()) {
|
||||||
material = storage->material_owner.getornull(material->next_pass);
|
material = storage->material_owner.getornull(material->next_pass);
|
||||||
@ -516,11 +109,11 @@ void RasterizerSceneGLES2::_add_geometry(RasterizerStorageGLES2::Geometry *p_geo
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
_add_geometry_with_material(p_geometry, p_instance, p_owner, material, p_depth_pass, p_shadow_pass);
|
_add_geometry_with_material(p_geometry, p_instance, p_owner, material, p_depth_pass);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES2::GeometryOwner *p_owner, RasterizerStorageGLES2::Material *p_material, bool p_depth_pass, bool p_shadow_pass) {
|
void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES2::GeometryOwner *p_owner, RasterizerStorageGLES2::Material *p_material, bool p_depth_pass) {
|
||||||
bool has_base_alpha = (p_material->shader->spatial.uses_alpha && !p_material->shader->spatial.uses_alpha_scissor) || p_material->shader->spatial.uses_screen_texture || p_material->shader->spatial.uses_depth_texture;
|
bool has_base_alpha = (p_material->shader->spatial.uses_alpha && !p_material->shader->spatial.uses_alpha_scissor) || p_material->shader->spatial.uses_screen_texture || p_material->shader->spatial.uses_depth_texture;
|
||||||
bool has_blend_alpha = p_material->shader->spatial.blend_mode != RasterizerStorageGLES2::Shader::Spatial::BLEND_MODE_MIX;
|
bool has_blend_alpha = p_material->shader->spatial.blend_mode != RasterizerStorageGLES2::Shader::Spatial::BLEND_MODE_MIX;
|
||||||
bool has_alpha = has_base_alpha || has_blend_alpha;
|
bool has_alpha = has_base_alpha || has_blend_alpha;
|
||||||
@ -548,12 +141,7 @@ void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::G
|
|||||||
|
|
||||||
if (!p_material->shader->spatial.uses_alpha_scissor && !p_material->shader->spatial.writes_modelview_or_projection && !p_material->shader->spatial.uses_vertex && !p_material->shader->spatial.uses_discard && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) {
|
if (!p_material->shader->spatial.uses_alpha_scissor && !p_material->shader->spatial.writes_modelview_or_projection && !p_material->shader->spatial.uses_vertex && !p_material->shader->spatial.uses_discard && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) {
|
||||||
//shader does not use discard and does not write a vertex position, use generic material
|
//shader does not use discard and does not write a vertex position, use generic material
|
||||||
if (p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED) {
|
p_material = storage->material_owner.getptr(p_material->shader->spatial.uses_world_coordinates ? default_worldcoord_material : default_material);
|
||||||
p_material = storage->material_owner.getptr(!p_shadow_pass && p_material->shader->spatial.uses_world_coordinates ? default_worldcoord_material_twosided : default_material_twosided);
|
|
||||||
mirror = false;
|
|
||||||
} else {
|
|
||||||
p_material = storage->material_owner.getptr(!p_shadow_pass && p_material->shader->spatial.uses_world_coordinates ? default_worldcoord_material : default_material);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
has_alpha = false;
|
has_alpha = false;
|
||||||
@ -613,7 +201,6 @@ void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::G
|
|||||||
//add directional lights
|
//add directional lights
|
||||||
|
|
||||||
e->light_mode = LIGHTMODE_UNSHADED;
|
e->light_mode = LIGHTMODE_UNSHADED;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// do not add anything here, as lights are duplicated elements..
|
// do not add anything here, as lights are duplicated elements..
|
||||||
@ -646,12 +233,10 @@ void RasterizerSceneGLES2::_copy_texture_to_buffer(GLuint p_texture, GLuint p_bu
|
|||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerSceneGLES2::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass, bool p_shadow_pass) {
|
void RasterizerSceneGLES2::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass) {
|
||||||
render_pass++;
|
render_pass++;
|
||||||
current_material_index = 0;
|
current_material_index = 0;
|
||||||
current_geometry_index = 0;
|
current_geometry_index = 0;
|
||||||
current_light_index = 0;
|
|
||||||
current_refprobe_index = 0;
|
|
||||||
current_shader_index = 0;
|
current_shader_index = 0;
|
||||||
|
|
||||||
for (int i = 0; i < p_cull_count; i++) {
|
for (int i = 0; i < p_cull_count; i++) {
|
||||||
@ -669,7 +254,7 @@ void RasterizerSceneGLES2::_fill_render_list(InstanceBase **p_cull_result, int p
|
|||||||
|
|
||||||
RasterizerStorageGLES2::Surface *surface = mesh->surfaces[j];
|
RasterizerStorageGLES2::Surface *surface = mesh->surfaces[j];
|
||||||
|
|
||||||
_add_geometry(surface, instance, nullptr, material_index, p_depth_pass, p_shadow_pass);
|
_add_geometry(surface, instance, nullptr, material_index, p_depth_pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
@ -691,7 +276,7 @@ void RasterizerSceneGLES2::_fill_render_list(InstanceBase **p_cull_result, int p
|
|||||||
|
|
||||||
for (int j = 0; j < ssize; j++) {
|
for (int j = 0; j < ssize; j++) {
|
||||||
RasterizerStorageGLES2::Surface *s = mesh->surfaces[j];
|
RasterizerStorageGLES2::Surface *s = mesh->surfaces[j];
|
||||||
_add_geometry(s, instance, multi_mesh, -1, p_depth_pass, p_shadow_pass);
|
_add_geometry(s, instance, multi_mesh, -1, p_depth_pass);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@ -1033,9 +618,7 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, int p_element_count, const Transform &p_view_transform, const Projection &p_projection, const int p_eye, RID p_shadow_atlas, float p_shadow_bias, float p_shadow_normal_bias, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow) {
|
void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, int p_element_count, const Transform &p_view_transform, const Projection &p_projection, const int p_eye, bool p_reverse_cull, bool p_alpha_pass) {
|
||||||
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
|
|
||||||
|
|
||||||
Vector2 viewport_size = state.viewport_size;
|
Vector2 viewport_size = state.viewport_size;
|
||||||
|
|
||||||
Vector2 screen_pixel_size = state.screen_pixel_size;
|
Vector2 screen_pixel_size = state.screen_pixel_size;
|
||||||
@ -1083,9 +666,8 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
|
|||||||
bool rebind = false;
|
bool rebind = false;
|
||||||
bool accum_pass = *e->use_accum_ptr;
|
bool accum_pass = *e->use_accum_ptr;
|
||||||
*e->use_accum_ptr = true; //set to accum for next time this is found
|
*e->use_accum_ptr = true; //set to accum for next time this is found
|
||||||
bool rebind_light = false;
|
|
||||||
|
|
||||||
if (!p_shadow && material->shader) {
|
if (material->shader) {
|
||||||
bool unshaded = material->shader->spatial.unshaded;
|
bool unshaded = material->shader->spatial.unshaded;
|
||||||
|
|
||||||
if (unshaded != prev_unshaded) {
|
if (unshaded != prev_unshaded) {
|
||||||
@ -1213,30 +795,17 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
|
|||||||
_set_cull(e->front_facing, material->shader->spatial.cull_mode == RasterizerStorageGLES2::Shader::Spatial::CULL_MODE_DISABLED, p_reverse_cull);
|
_set_cull(e->front_facing, material->shader->spatial.cull_mode == RasterizerStorageGLES2::Shader::Spatial::CULL_MODE_DISABLED, p_reverse_cull);
|
||||||
|
|
||||||
if (i == 0 || shader_rebind) { //first time must rebind
|
if (i == 0 || shader_rebind) { //first time must rebind
|
||||||
|
if (use_radiance_map) {
|
||||||
if (p_shadow) {
|
// would be a bit weird if we don't have this...
|
||||||
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_BIAS, p_shadow_bias);
|
state.scene_shader.set_uniform(SceneShaderGLES2::RADIANCE_INVERSE_XFORM, p_view_transform);
|
||||||
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_NORMAL_BIAS, p_shadow_normal_bias);
|
|
||||||
if (state.shadow_is_dual_parabolloid) {
|
|
||||||
state.scene_shader.set_uniform(SceneShaderGLES2::SHADOW_DUAL_PARABOLOID_RENDER_SIDE, state.dual_parbolloid_direction);
|
|
||||||
state.scene_shader.set_uniform(SceneShaderGLES2::SHADOW_DUAL_PARABOLOID_RENDER_ZFAR, state.dual_parbolloid_zfar);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (use_radiance_map) {
|
|
||||||
// would be a bit weird if we don't have this...
|
|
||||||
state.scene_shader.set_uniform(SceneShaderGLES2::RADIANCE_INVERSE_XFORM, p_view_transform);
|
|
||||||
}
|
|
||||||
|
|
||||||
state.scene_shader.set_uniform(SceneShaderGLES2::BG_ENERGY, 1.0);
|
|
||||||
state.scene_shader.set_uniform(SceneShaderGLES2::BG_COLOR, state.default_bg);
|
|
||||||
state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_SKY_CONTRIBUTION, 1.0);
|
|
||||||
state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_COLOR, state.default_ambient);
|
|
||||||
state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_ENERGY, 1.0);
|
|
||||||
|
|
||||||
//rebind all these
|
|
||||||
rebind_light = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state.scene_shader.set_uniform(SceneShaderGLES2::BG_ENERGY, 1.0);
|
||||||
|
state.scene_shader.set_uniform(SceneShaderGLES2::BG_COLOR, state.default_bg);
|
||||||
|
state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_SKY_CONTRIBUTION, 1.0);
|
||||||
|
state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_COLOR, state.default_ambient);
|
||||||
|
state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_ENERGY, 1.0);
|
||||||
|
|
||||||
state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_MATRIX, p_view_transform);
|
state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_MATRIX, p_view_transform);
|
||||||
state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_INVERSE_MATRIX, view_transform_inverse);
|
state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_INVERSE_MATRIX, view_transform_inverse);
|
||||||
state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_MATRIX, p_projection);
|
state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_MATRIX, p_projection);
|
||||||
@ -1376,7 +945,7 @@ void RasterizerSceneGLES2::_post_process(const Projection &p_cam_projection) {
|
|||||||
state.tonemap_shader.set_conditional(TonemapShaderGLES2::DISABLE_ALPHA, false);
|
state.tonemap_shader.set_conditional(TonemapShaderGLES2::DISABLE_ALPHA, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const Projection &p_cam_projection, const int p_eye, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID p_shadow_atlas) {
|
void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const Projection &p_cam_projection, const int p_eye, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count) {
|
||||||
Transform cam_transform = p_cam_transform;
|
Transform cam_transform = p_cam_transform;
|
||||||
|
|
||||||
storage->info.render.object_count += p_cull_count;
|
storage->info.render.object_count += p_cull_count;
|
||||||
@ -1422,7 +991,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
|
|||||||
// render list stuff
|
// render list stuff
|
||||||
|
|
||||||
render_list.clear();
|
render_list.clear();
|
||||||
_fill_render_list(p_cull_result, p_cull_count, false, false);
|
_fill_render_list(p_cull_result, p_cull_count, false);
|
||||||
|
|
||||||
// other stuff
|
// other stuff
|
||||||
|
|
||||||
@ -1478,7 +1047,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
|
|||||||
|
|
||||||
// render opaque things first
|
// render opaque things first
|
||||||
render_list.sort_by_key(false);
|
render_list.sort_by_key(false);
|
||||||
_render_render_list(render_list.elements, render_list.element_count, cam_transform, p_cam_projection, p_eye, p_shadow_atlas, 0.0, 0.0, reverse_cull, false, false);
|
_render_render_list(render_list.elements, render_list.element_count, cam_transform, p_cam_projection, p_eye, reverse_cull, false);
|
||||||
|
|
||||||
if (storage->frame.current_rt && state.used_screen_texture) {
|
if (storage->frame.current_rt && state.used_screen_texture) {
|
||||||
//copy screen texture
|
//copy screen texture
|
||||||
@ -1524,142 +1093,21 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
|
|||||||
|
|
||||||
render_list.sort_by_reverse_depth_and_priority(true);
|
render_list.sort_by_reverse_depth_and_priority(true);
|
||||||
|
|
||||||
_render_render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, cam_transform, p_cam_projection, p_eye, p_shadow_atlas, 0.0, 0.0, reverse_cull, true, false);
|
_render_render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, cam_transform, p_cam_projection, p_eye, reverse_cull, true);
|
||||||
|
|
||||||
//post process
|
//post process
|
||||||
_post_process(p_cam_projection);
|
_post_process(p_cam_projection);
|
||||||
|
|
||||||
//#define GLES2_SHADOW_ATLAS_DEBUG_VIEW
|
|
||||||
|
|
||||||
#ifdef GLES2_SHADOW_ATLAS_DEBUG_VIEW
|
|
||||||
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
|
|
||||||
if (shadow_atlas) {
|
|
||||||
WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
|
|
||||||
|
|
||||||
glViewport(0, 0, storage->frame.current_rt->width / 4, storage->frame.current_rt->height / 4);
|
|
||||||
storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_CUBEMAP, false);
|
|
||||||
storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_COPY_SECTION, false);
|
|
||||||
storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_CUSTOM_ALPHA, false);
|
|
||||||
storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_MULTIPLIER, false);
|
|
||||||
storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_PANORAMA, false);
|
|
||||||
storage->shaders.copy.bind();
|
|
||||||
|
|
||||||
storage->_copy_screen();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//#define GLES2_SHADOW_DIRECTIONAL_DEBUG_VIEW
|
|
||||||
|
|
||||||
#ifdef GLES2_SHADOW_DIRECTIONAL_DEBUG_VIEW
|
|
||||||
if (true) {
|
|
||||||
WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
|
|
||||||
|
|
||||||
glViewport(0, 0, storage->frame.current_rt->width / 4, storage->frame.current_rt->height / 4);
|
|
||||||
storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_CUBEMAP, false);
|
|
||||||
storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_COPY_SECTION, false);
|
|
||||||
storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_CUSTOM_ALPHA, false);
|
|
||||||
storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_MULTIPLIER, false);
|
|
||||||
storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_PANORAMA, false);
|
|
||||||
storage->shaders.copy.bind();
|
|
||||||
|
|
||||||
storage->_copy_screen();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// return to default
|
// return to default
|
||||||
state.scene_shader.set_conditional(SceneShaderGLES2::OUTPUT_LINEAR, false);
|
state.scene_shader.set_conditional(SceneShaderGLES2::OUTPUT_LINEAR, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {
|
|
||||||
state.render_no_shadows = false;
|
|
||||||
|
|
||||||
uint32_t x;
|
|
||||||
uint32_t y;
|
|
||||||
uint32_t width;
|
|
||||||
uint32_t height;
|
|
||||||
|
|
||||||
float zfar = 0;
|
|
||||||
bool flip_facing = false;
|
|
||||||
int custom_vp_size = 0;
|
|
||||||
GLuint fbo = 0;
|
|
||||||
state.shadow_is_dual_parabolloid = false;
|
|
||||||
state.dual_parbolloid_direction = 0.0;
|
|
||||||
|
|
||||||
int current_cubemap = -1;
|
|
||||||
float bias = 0;
|
|
||||||
float normal_bias = 0;
|
|
||||||
|
|
||||||
Projection light_projection;
|
|
||||||
Transform light_transform;
|
|
||||||
|
|
||||||
render_list.clear();
|
|
||||||
|
|
||||||
_fill_render_list(p_cull_result, p_cull_count, true, true);
|
|
||||||
|
|
||||||
render_list.sort_by_depth(false);
|
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
|
||||||
glDisable(GL_DITHER);
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
|
||||||
|
|
||||||
glDepthMask(GL_TRUE);
|
|
||||||
if (!storage->config.use_rgba_3d_shadows) {
|
|
||||||
glColorMask(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (custom_vp_size) {
|
|
||||||
glViewport(0, 0, custom_vp_size, custom_vp_size);
|
|
||||||
glScissor(0, 0, custom_vp_size, custom_vp_size);
|
|
||||||
} else {
|
|
||||||
glViewport(x, y, width, height);
|
|
||||||
glScissor(x, y, width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
glEnable(GL_SCISSOR_TEST);
|
|
||||||
glClearDepth(1.0f);
|
|
||||||
glClear(GL_DEPTH_BUFFER_BIT);
|
|
||||||
if (storage->config.use_rgba_3d_shadows) {
|
|
||||||
glClearColor(1.0, 1.0, 1.0, 1.0);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
|
||||||
}
|
|
||||||
glDisable(GL_SCISSOR_TEST);
|
|
||||||
|
|
||||||
state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH, true);
|
|
||||||
state.scene_shader.set_conditional(SceneShaderGLES2::OUTPUT_LINEAR, false); // just in case, should be false already
|
|
||||||
|
|
||||||
_render_render_list(render_list.elements, render_list.element_count, light_transform, light_projection, 0, RID(), bias, normal_bias, flip_facing, false, true);
|
|
||||||
|
|
||||||
state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH, false);
|
|
||||||
state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH_DUAL_PARABOLOID, false);
|
|
||||||
|
|
||||||
if (storage->frame.current_rt) {
|
|
||||||
glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
|
|
||||||
}
|
|
||||||
if (!storage->config.use_rgba_3d_shadows) {
|
|
||||||
glColorMask(1, 1, 1, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RasterizerSceneGLES2::set_scene_pass(uint64_t p_pass) {
|
void RasterizerSceneGLES2::set_scene_pass(uint64_t p_pass) {
|
||||||
scene_pass = p_pass;
|
scene_pass = p_pass;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RasterizerSceneGLES2::free(RID p_rid) {
|
bool RasterizerSceneGLES2::free(RID p_rid) {
|
||||||
if (shadow_atlas_owner.owns(p_rid)) {
|
return false;
|
||||||
ShadowAtlas *shadow_atlas = shadow_atlas_owner.get(p_rid);
|
|
||||||
shadow_atlas_set_size(p_rid, 0);
|
|
||||||
shadow_atlas_owner.free(p_rid);
|
|
||||||
memdelete(shadow_atlas);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerSceneGLES2::set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) {
|
void RasterizerSceneGLES2::set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) {
|
||||||
@ -1677,8 +1125,6 @@ void RasterizerSceneGLES2::initialize() {
|
|||||||
|
|
||||||
render_pass = 1;
|
render_pass = 1;
|
||||||
|
|
||||||
shadow_atlas_realloc_tolerance_msec = 500;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
//default material and shader
|
//default material and shader
|
||||||
|
|
||||||
@ -1732,67 +1178,16 @@ void RasterizerSceneGLES2::initialize() {
|
|||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// cubemaps for shadows
|
|
||||||
if (storage->config.support_shadow_cubemaps) { //not going to be used
|
|
||||||
int max_shadow_cubemap_sampler_size = MIN(int(GLOBAL_GET("rendering/quality/shadow_atlas/cubemap_size")), storage->config.max_cubemap_texture_size);
|
|
||||||
|
|
||||||
int cube_size = max_shadow_cubemap_sampler_size;
|
|
||||||
|
|
||||||
WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
|
|
||||||
|
|
||||||
while (cube_size >= 32) {
|
|
||||||
ShadowCubeMap cube;
|
|
||||||
|
|
||||||
cube.size = cube_size;
|
|
||||||
|
|
||||||
glGenTextures(1, &cube.cubemap);
|
|
||||||
glBindTexture(GL_TEXTURE_CUBE_MAP, cube.cubemap);
|
|
||||||
|
|
||||||
for (int i = 0; i < 6; i++) {
|
|
||||||
glTexImage2D(_cube_side_enum[i], 0, storage->config.depth_internalformat, cube_size, cube_size, 0, GL_DEPTH_COMPONENT, storage->config.depth_type, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
|
|
||||||
glGenFramebuffers(6, cube.fbo);
|
|
||||||
for (int i = 0; i < 6; i++) {
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, cube.fbo[i]);
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, _cube_side_enum[i], cube.cubemap, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
shadow_cubemaps.push_back(cube);
|
|
||||||
|
|
||||||
cube_size >>= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
directional_shadow_create();
|
|
||||||
|
|
||||||
shadow_filter_mode = SHADOW_FILTER_NEAREST;
|
|
||||||
|
|
||||||
glFrontFace(GL_CW);
|
glFrontFace(GL_CW);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerSceneGLES2::iteration() {
|
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) {
|
|
||||||
directional_shadow_size = directional_shadow_size_new;
|
|
||||||
directional_shadow_create();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerSceneGLES2::finalize() {
|
void RasterizerSceneGLES2::finalize() {
|
||||||
}
|
}
|
||||||
|
|
||||||
RasterizerSceneGLES2::RasterizerSceneGLES2() {
|
RasterizerSceneGLES2::RasterizerSceneGLES2() {
|
||||||
_light_counter = 0;
|
|
||||||
directional_shadow_size = next_power_of_2(int(GLOBAL_GET("rendering/quality/directional_shadow/size")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RasterizerSceneGLES2::~RasterizerSceneGLES2() {
|
RasterizerSceneGLES2::~RasterizerSceneGLES2() {
|
||||||
|
@ -53,19 +53,11 @@
|
|||||||
|
|
||||||
class RasterizerSceneGLES2 : public RasterizerScene {
|
class RasterizerSceneGLES2 : public RasterizerScene {
|
||||||
public:
|
public:
|
||||||
enum ShadowFilterMode {
|
|
||||||
SHADOW_FILTER_NEAREST,
|
|
||||||
SHADOW_FILTER_PCF5,
|
|
||||||
SHADOW_FILTER_PCF13,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
INSTANCE_ATTRIB_BASE = 8,
|
INSTANCE_ATTRIB_BASE = 8,
|
||||||
INSTANCE_BONE_BASE = 13,
|
INSTANCE_BONE_BASE = 13,
|
||||||
};
|
};
|
||||||
|
|
||||||
ShadowFilterMode shadow_filter_mode;
|
|
||||||
|
|
||||||
RID default_material;
|
RID default_material;
|
||||||
RID default_material_twosided;
|
RID default_material_twosided;
|
||||||
RID default_shader;
|
RID default_shader;
|
||||||
@ -84,7 +76,6 @@ public:
|
|||||||
uint32_t current_material_index;
|
uint32_t current_material_index;
|
||||||
uint32_t current_geometry_index;
|
uint32_t current_geometry_index;
|
||||||
uint32_t current_light_index;
|
uint32_t current_light_index;
|
||||||
uint32_t current_refprobe_index;
|
|
||||||
uint32_t current_shader_index;
|
uint32_t current_shader_index;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -128,83 +119,6 @@ public:
|
|||||||
Vector2 screen_pixel_size;
|
Vector2 screen_pixel_size;
|
||||||
} state;
|
} state;
|
||||||
|
|
||||||
/* SHADOW ATLAS API */
|
|
||||||
|
|
||||||
uint64_t shadow_atlas_realloc_tolerance_msec;
|
|
||||||
|
|
||||||
struct ShadowAtlas : public RID_Data {
|
|
||||||
enum {
|
|
||||||
QUADRANT_SHIFT = 27,
|
|
||||||
SHADOW_INDEX_MASK = (1 << QUADRANT_SHIFT) - 1,
|
|
||||||
SHADOW_INVALID = 0xFFFFFFFF,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Quadrant {
|
|
||||||
uint32_t subdivision;
|
|
||||||
|
|
||||||
struct Shadow {
|
|
||||||
RID owner;
|
|
||||||
uint64_t version;
|
|
||||||
uint64_t alloc_tick;
|
|
||||||
|
|
||||||
Shadow() {
|
|
||||||
version = 0;
|
|
||||||
alloc_tick = 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Vector<Shadow> shadows;
|
|
||||||
|
|
||||||
Quadrant() {
|
|
||||||
subdivision = 0;
|
|
||||||
}
|
|
||||||
} quadrants[4];
|
|
||||||
|
|
||||||
int size_order[4];
|
|
||||||
uint32_t smallest_subdiv;
|
|
||||||
|
|
||||||
int size;
|
|
||||||
|
|
||||||
GLuint fbo;
|
|
||||||
GLuint depth;
|
|
||||||
GLuint color;
|
|
||||||
|
|
||||||
RBMap<RID, uint32_t> shadow_owners;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ShadowCubeMap {
|
|
||||||
GLuint fbo[6];
|
|
||||||
GLuint cubemap;
|
|
||||||
uint32_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
Vector<ShadowCubeMap> shadow_cubemaps;
|
|
||||||
|
|
||||||
RID_Owner<ShadowAtlas> shadow_atlas_owner;
|
|
||||||
|
|
||||||
int directional_shadow_size;
|
|
||||||
|
|
||||||
void directional_shadow_create();
|
|
||||||
|
|
||||||
RID shadow_atlas_create();
|
|
||||||
void shadow_atlas_set_size(RID p_atlas, int p_size);
|
|
||||||
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);
|
|
||||||
|
|
||||||
struct DirectionalShadow {
|
|
||||||
GLuint fbo = 0;
|
|
||||||
GLuint depth = 0;
|
|
||||||
GLuint color = 0;
|
|
||||||
|
|
||||||
int light_count = 0;
|
|
||||||
int size = 0;
|
|
||||||
int current_light = 0;
|
|
||||||
} directional_shadow;
|
|
||||||
|
|
||||||
virtual int get_directional_light_shadow_size(RID p_light_intance);
|
|
||||||
virtual void set_directional_shadow_count(int p_count);
|
|
||||||
|
|
||||||
/* RENDER LIST */
|
/* RENDER LIST */
|
||||||
|
|
||||||
enum LightMode {
|
enum LightMode {
|
||||||
@ -377,21 +291,17 @@ public:
|
|||||||
|
|
||||||
RenderList render_list;
|
RenderList render_list;
|
||||||
|
|
||||||
void _add_geometry(RasterizerStorageGLES2::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES2::GeometryOwner *p_owner, int p_material, bool p_depth_pass, bool p_shadow_pass);
|
void _add_geometry(RasterizerStorageGLES2::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES2::GeometryOwner *p_owner, int p_material, bool p_depth_pass);
|
||||||
void _add_geometry_with_material(RasterizerStorageGLES2::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES2::GeometryOwner *p_owner, RasterizerStorageGLES2::Material *p_material, bool p_depth_pass, bool p_shadow_pass);
|
void _add_geometry_with_material(RasterizerStorageGLES2::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES2::GeometryOwner *p_owner, RasterizerStorageGLES2::Material *p_material, bool p_depth_pass);
|
||||||
|
|
||||||
void _copy_texture_to_buffer(GLuint p_texture, GLuint p_buffer);
|
void _copy_texture_to_buffer(GLuint p_texture, GLuint p_buffer);
|
||||||
void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass, bool p_shadow_pass);
|
void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass);
|
||||||
void _render_render_list(RenderList::Element **p_elements, int p_element_count,
|
void _render_render_list(RenderList::Element **p_elements, int p_element_count,
|
||||||
const Transform &p_view_transform,
|
const Transform &p_view_transform,
|
||||||
const Projection &p_projection,
|
const Projection &p_projection,
|
||||||
const int p_eye,
|
const int p_eye,
|
||||||
RID p_shadow_atlas,
|
|
||||||
float p_shadow_bias,
|
|
||||||
float p_shadow_normal_bias,
|
|
||||||
bool p_reverse_cull,
|
bool p_reverse_cull,
|
||||||
bool p_alpha_pass,
|
bool p_alpha_pass);
|
||||||
bool p_shadow);
|
|
||||||
|
|
||||||
_FORCE_INLINE_ void _set_cull(bool p_front, bool p_disabled, bool p_reverse_cull);
|
_FORCE_INLINE_ void _set_cull(bool p_front, bool p_disabled, bool p_reverse_cull);
|
||||||
_FORCE_INLINE_ bool _setup_material(RasterizerStorageGLES2::Material *p_material, bool p_alpha_pass, Size2i p_skeleton_tex_size = Size2i(0, 0));
|
_FORCE_INLINE_ bool _setup_material(RasterizerStorageGLES2::Material *p_material, bool p_alpha_pass, Size2i p_skeleton_tex_size = Size2i(0, 0));
|
||||||
@ -400,8 +310,7 @@ public:
|
|||||||
|
|
||||||
void _post_process(const Projection &p_cam_projection);
|
void _post_process(const Projection &p_cam_projection);
|
||||||
|
|
||||||
virtual void render_scene(const Transform &p_cam_transform, const Projection &p_cam_projection, const int p_eye, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID p_shadow_atlas);
|
virtual void render_scene(const Transform &p_cam_transform, const Projection &p_cam_projection, const int p_eye, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count);
|
||||||
virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count);
|
|
||||||
virtual bool free(RID p_rid);
|
virtual bool free(RID p_rid);
|
||||||
|
|
||||||
virtual void set_scene_pass(uint64_t p_pass);
|
virtual void set_scene_pass(uint64_t p_pass);
|
||||||
|
@ -2002,17 +2002,6 @@ bool Main::start() {
|
|||||||
// It can still be overridden by the user in a script.
|
// It can still be overridden by the user in a script.
|
||||||
OS::get_singleton()->set_min_window_size(Size2(64, 64));
|
OS::get_singleton()->set_min_window_size(Size2(64, 64));
|
||||||
|
|
||||||
int shadow_atlas_size = GLOBAL_GET("rendering/quality/shadow_atlas/size");
|
|
||||||
int shadow_atlas_q0_subdiv = GLOBAL_GET("rendering/quality/shadow_atlas/quadrant_0_subdiv");
|
|
||||||
int shadow_atlas_q1_subdiv = GLOBAL_GET("rendering/quality/shadow_atlas/quadrant_1_subdiv");
|
|
||||||
int shadow_atlas_q2_subdiv = GLOBAL_GET("rendering/quality/shadow_atlas/quadrant_2_subdiv");
|
|
||||||
int shadow_atlas_q3_subdiv = GLOBAL_GET("rendering/quality/shadow_atlas/quadrant_3_subdiv");
|
|
||||||
|
|
||||||
sml->get_root()->set_shadow_atlas_size(shadow_atlas_size);
|
|
||||||
sml->get_root()->set_shadow_atlas_quadrant_subdiv(0, Viewport::ShadowAtlasQuadrantSubdiv(shadow_atlas_q0_subdiv));
|
|
||||||
sml->get_root()->set_shadow_atlas_quadrant_subdiv(1, Viewport::ShadowAtlasQuadrantSubdiv(shadow_atlas_q1_subdiv));
|
|
||||||
sml->get_root()->set_shadow_atlas_quadrant_subdiv(2, Viewport::ShadowAtlasQuadrantSubdiv(shadow_atlas_q2_subdiv));
|
|
||||||
sml->get_root()->set_shadow_atlas_quadrant_subdiv(3, Viewport::ShadowAtlasQuadrantSubdiv(shadow_atlas_q3_subdiv));
|
|
||||||
Viewport::Usage usage = Viewport::Usage(int(GLOBAL_GET("rendering/quality/intended_usage/framebuffer_allocation")));
|
Viewport::Usage usage = Viewport::Usage(int(GLOBAL_GET("rendering/quality/intended_usage/framebuffer_allocation")));
|
||||||
sml->get_root()->set_usage(usage);
|
sml->get_root()->set_usage(usage);
|
||||||
|
|
||||||
|
@ -892,36 +892,6 @@ Viewport::ClearMode Viewport::get_clear_mode() const {
|
|||||||
return clear_mode;
|
return clear_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Viewport::set_shadow_atlas_size(int p_size) {
|
|
||||||
if (shadow_atlas_size == p_size) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
shadow_atlas_size = p_size;
|
|
||||||
RS::get_singleton()->viewport_set_shadow_atlas_size(viewport, p_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Viewport::get_shadow_atlas_size() const {
|
|
||||||
return shadow_atlas_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
if (shadow_atlas_quadrant_subdiv[p_quadrant] == p_subdiv) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
shadow_atlas_quadrant_subdiv[p_quadrant] = p_subdiv;
|
|
||||||
static const int subdiv[SHADOW_ATLAS_QUADRANT_SUBDIV_MAX] = { 0, 1, 4, 16, 64, 256, 1024 };
|
|
||||||
|
|
||||||
RS::get_singleton()->viewport_set_shadow_atlas_quadrant_subdivision(viewport, p_quadrant, subdiv[p_subdiv]);
|
|
||||||
}
|
|
||||||
Viewport::ShadowAtlasQuadrantSubdiv Viewport::get_shadow_atlas_quadrant_subdiv(int p_quadrant) const {
|
|
||||||
ERR_FAIL_INDEX_V(p_quadrant, 4, SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED);
|
|
||||||
return shadow_atlas_quadrant_subdiv[p_quadrant];
|
|
||||||
}
|
|
||||||
|
|
||||||
Transform2D Viewport::_get_input_pre_xform() const {
|
Transform2D Viewport::_get_input_pre_xform() const {
|
||||||
Transform2D pre_xf;
|
Transform2D pre_xf;
|
||||||
@ -2821,15 +2791,9 @@ void Viewport::_bind_methods() {
|
|||||||
ClassDB::bind_method(D_METHOD("_gui_remove_focus"), &Viewport::_gui_remove_focus);
|
ClassDB::bind_method(D_METHOD("_gui_remove_focus"), &Viewport::_gui_remove_focus);
|
||||||
ClassDB::bind_method(D_METHOD("_post_gui_grab_click_focus"), &Viewport::_post_gui_grab_click_focus);
|
ClassDB::bind_method(D_METHOD("_post_gui_grab_click_focus"), &Viewport::_post_gui_grab_click_focus);
|
||||||
|
|
||||||
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_snap_controls_to_pixels", "enabled"), &Viewport::set_snap_controls_to_pixels);
|
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);
|
ClassDB::bind_method(D_METHOD("is_snap_controls_to_pixels_enabled"), &Viewport::is_snap_controls_to_pixels_enabled);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_shadow_atlas_quadrant_subdiv", "quadrant", "subdiv"), &Viewport::set_shadow_atlas_quadrant_subdiv);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_shadow_atlas_quadrant_subdiv", "quadrant"), &Viewport::get_shadow_atlas_quadrant_subdiv);
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_input_as_handled"), &Viewport::set_input_as_handled);
|
ClassDB::bind_method(D_METHOD("set_input_as_handled"), &Viewport::set_input_as_handled);
|
||||||
ClassDB::bind_method(D_METHOD("is_input_handled"), &Viewport::is_input_handled);
|
ClassDB::bind_method(D_METHOD("is_input_handled"), &Viewport::is_input_handled);
|
||||||
|
|
||||||
@ -2874,12 +2838,6 @@ void Viewport::_bind_methods() {
|
|||||||
ADD_GROUP("GUI", "gui_");
|
ADD_GROUP("GUI", "gui_");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_disable_input"), "set_disable_input", "is_input_disabled");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_disable_input"), "set_disable_input", "is_input_disabled");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_snap_controls_to_pixels"), "set_snap_controls_to_pixels", "is_snap_controls_to_pixels_enabled");
|
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_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);
|
|
||||||
ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_3", 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", 3);
|
|
||||||
|
|
||||||
ADD_SIGNAL(MethodInfo("size_changed"));
|
ADD_SIGNAL(MethodInfo("size_changed"));
|
||||||
ADD_SIGNAL(MethodInfo("gui_focus_changed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Control")));
|
ADD_SIGNAL(MethodInfo("gui_focus_changed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Control")));
|
||||||
@ -2889,15 +2847,6 @@ void Viewport::_bind_methods() {
|
|||||||
BIND_ENUM_CONSTANT(UPDATE_WHEN_VISIBLE);
|
BIND_ENUM_CONSTANT(UPDATE_WHEN_VISIBLE);
|
||||||
BIND_ENUM_CONSTANT(UPDATE_ALWAYS);
|
BIND_ENUM_CONSTANT(UPDATE_ALWAYS);
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED);
|
|
||||||
BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_1);
|
|
||||||
BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_4);
|
|
||||||
BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_16);
|
|
||||||
BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_64);
|
|
||||||
BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_256);
|
|
||||||
BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_1024);
|
|
||||||
BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_MAX);
|
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(RENDER_INFO_OBJECTS_IN_FRAME);
|
BIND_ENUM_CONSTANT(RENDER_INFO_OBJECTS_IN_FRAME);
|
||||||
BIND_ENUM_CONSTANT(RENDER_INFO_VERTICES_IN_FRAME);
|
BIND_ENUM_CONSTANT(RENDER_INFO_VERTICES_IN_FRAME);
|
||||||
BIND_ENUM_CONSTANT(RENDER_INFO_MATERIAL_CHANGES_IN_FRAME);
|
BIND_ENUM_CONSTANT(RENDER_INFO_MATERIAL_CHANGES_IN_FRAME);
|
||||||
@ -2999,15 +2948,6 @@ Viewport::Viewport() {
|
|||||||
physics_has_last_mousepos = false;
|
physics_has_last_mousepos = false;
|
||||||
physics_last_mousepos = Vector2(Math_INF, Math_INF);
|
physics_last_mousepos = Vector2(Math_INF, Math_INF);
|
||||||
|
|
||||||
shadow_atlas_size = 0;
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
shadow_atlas_quadrant_subdiv[i] = SHADOW_ATLAS_QUADRANT_SUBDIV_MAX;
|
|
||||||
}
|
|
||||||
set_shadow_atlas_quadrant_subdiv(0, SHADOW_ATLAS_QUADRANT_SUBDIV_4);
|
|
||||||
set_shadow_atlas_quadrant_subdiv(1, SHADOW_ATLAS_QUADRANT_SUBDIV_4);
|
|
||||||
set_shadow_atlas_quadrant_subdiv(2, SHADOW_ATLAS_QUADRANT_SUBDIV_16);
|
|
||||||
set_shadow_atlas_quadrant_subdiv(3, SHADOW_ATLAS_QUADRANT_SUBDIV_64);
|
|
||||||
|
|
||||||
String id = itos(get_instance_id());
|
String id = itos(get_instance_id());
|
||||||
input_group = "_vp_input" + id;
|
input_group = "_vp_input" + id;
|
||||||
gui_input_group = "_vp_gui_input" + id;
|
gui_input_group = "_vp_gui_input" + id;
|
||||||
|
@ -97,18 +97,6 @@ public:
|
|||||||
UPDATE_ALWAYS
|
UPDATE_ALWAYS
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ShadowAtlasQuadrantSubdiv {
|
|
||||||
SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED,
|
|
||||||
SHADOW_ATLAS_QUADRANT_SUBDIV_1,
|
|
||||||
SHADOW_ATLAS_QUADRANT_SUBDIV_4,
|
|
||||||
SHADOW_ATLAS_QUADRANT_SUBDIV_16,
|
|
||||||
SHADOW_ATLAS_QUADRANT_SUBDIV_64,
|
|
||||||
SHADOW_ATLAS_QUADRANT_SUBDIV_256,
|
|
||||||
SHADOW_ATLAS_QUADRANT_SUBDIV_1024,
|
|
||||||
SHADOW_ATLAS_QUADRANT_SUBDIV_MAX,
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
enum MSAA {
|
enum MSAA {
|
||||||
MSAA_DISABLED,
|
MSAA_DISABLED,
|
||||||
MSAA_2X,
|
MSAA_2X,
|
||||||
@ -202,12 +190,6 @@ public:
|
|||||||
UpdateMode get_update_mode() const;
|
UpdateMode get_update_mode() const;
|
||||||
Ref<ViewportTexture> get_texture() const;
|
Ref<ViewportTexture> get_texture() const;
|
||||||
|
|
||||||
void set_shadow_atlas_size(int p_size);
|
|
||||||
int get_shadow_atlas_size() const;
|
|
||||||
|
|
||||||
void set_shadow_atlas_quadrant_subdiv(int p_quadrant, ShadowAtlasQuadrantSubdiv p_subdiv);
|
|
||||||
ShadowAtlasQuadrantSubdiv get_shadow_atlas_quadrant_subdiv(int p_quadrant) const;
|
|
||||||
|
|
||||||
void set_msaa(MSAA p_msaa);
|
void set_msaa(MSAA p_msaa);
|
||||||
MSAA get_msaa() const;
|
MSAA get_msaa() const;
|
||||||
|
|
||||||
@ -391,9 +373,6 @@ private:
|
|||||||
|
|
||||||
Usage usage;
|
Usage usage;
|
||||||
|
|
||||||
int shadow_atlas_size;
|
|
||||||
ShadowAtlasQuadrantSubdiv shadow_atlas_quadrant_subdiv[4];
|
|
||||||
|
|
||||||
MSAA msaa;
|
MSAA msaa;
|
||||||
bool use_fxaa;
|
bool use_fxaa;
|
||||||
bool use_debanding;
|
bool use_debanding;
|
||||||
@ -524,7 +503,6 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
VARIANT_ENUM_CAST(Viewport::UpdateMode);
|
VARIANT_ENUM_CAST(Viewport::UpdateMode);
|
||||||
VARIANT_ENUM_CAST(Viewport::ShadowAtlasQuadrantSubdiv);
|
|
||||||
VARIANT_ENUM_CAST(Viewport::MSAA);
|
VARIANT_ENUM_CAST(Viewport::MSAA);
|
||||||
VARIANT_ENUM_CAST(Viewport::Usage);
|
VARIANT_ENUM_CAST(Viewport::Usage);
|
||||||
VARIANT_ENUM_CAST(Viewport::DebugDraw);
|
VARIANT_ENUM_CAST(Viewport::DebugDraw);
|
||||||
|
@ -38,16 +38,6 @@
|
|||||||
|
|
||||||
class RasterizerScene {
|
class RasterizerScene {
|
||||||
public:
|
public:
|
||||||
/* SHADOW ATLAS API */
|
|
||||||
|
|
||||||
virtual RID shadow_atlas_create() = 0;
|
|
||||||
virtual void shadow_atlas_set_size(RID p_atlas, int p_size) = 0;
|
|
||||||
virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) = 0;
|
|
||||||
virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) = 0;
|
|
||||||
|
|
||||||
virtual int get_directional_light_shadow_size(RID p_light_intance) = 0;
|
|
||||||
virtual void set_directional_shadow_count(int p_count) = 0;
|
|
||||||
|
|
||||||
struct InstanceBase : RID_Data {
|
struct InstanceBase : RID_Data {
|
||||||
RS::InstanceType base_type;
|
RS::InstanceType base_type;
|
||||||
RID base;
|
RID base;
|
||||||
@ -76,8 +66,6 @@ public:
|
|||||||
|
|
||||||
PoolVector<float> blend_values;
|
PoolVector<float> blend_values;
|
||||||
|
|
||||||
RS::ShadowCastingSetting cast_shadows;
|
|
||||||
|
|
||||||
//fit in 32 bits
|
//fit in 32 bits
|
||||||
bool mirror : 1;
|
bool mirror : 1;
|
||||||
bool receive_shadows : 1;
|
bool receive_shadows : 1;
|
||||||
@ -103,7 +91,6 @@ public:
|
|||||||
InstanceBase() :
|
InstanceBase() :
|
||||||
dependency_item(this) {
|
dependency_item(this) {
|
||||||
base_type = RS::INSTANCE_NONE;
|
base_type = RS::INSTANCE_NONE;
|
||||||
cast_shadows = RS::SHADOW_CASTING_SETTING_ON;
|
|
||||||
receive_shadows = true;
|
receive_shadows = true;
|
||||||
visible = true;
|
visible = true;
|
||||||
depth_layer = 0;
|
depth_layer = 0;
|
||||||
@ -118,9 +105,8 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void render_scene(const Transform &p_cam_transform, const Projection &p_cam_projection, const int p_eye, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID p_shadow_atlas) = 0;
|
virtual void render_scene(const Transform &p_cam_transform, const Projection &p_cam_projection, const int p_eye, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count) = 0;
|
||||||
virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) = 0;
|
|
||||||
|
|
||||||
virtual void set_scene_pass(uint64_t p_pass) = 0;
|
virtual void set_scene_pass(uint64_t p_pass) = 0;
|
||||||
virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0;
|
virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0;
|
||||||
|
|
||||||
|
@ -339,8 +339,6 @@ public:
|
|||||||
|
|
||||||
BIND2(viewport_set_global_canvas_transform, RID, const Transform2D &)
|
BIND2(viewport_set_global_canvas_transform, RID, const Transform2D &)
|
||||||
BIND4(viewport_set_canvas_stacking, RID, RID, int, int)
|
BIND4(viewport_set_canvas_stacking, RID, RID, int, int)
|
||||||
BIND2(viewport_set_shadow_atlas_size, RID, int)
|
|
||||||
BIND3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
|
|
||||||
BIND2(viewport_set_msaa, RID, ViewportMSAA)
|
BIND2(viewport_set_msaa, RID, ViewportMSAA)
|
||||||
BIND2(viewport_set_use_fxaa, RID, bool)
|
BIND2(viewport_set_use_fxaa, RID, bool)
|
||||||
BIND2(viewport_set_use_debanding, RID, bool)
|
BIND2(viewport_set_use_debanding, RID, bool)
|
||||||
@ -362,9 +360,6 @@ public:
|
|||||||
BIND0R(RID, scenario_create)
|
BIND0R(RID, scenario_create)
|
||||||
|
|
||||||
BIND2(scenario_set_debug, RID, ScenarioDebugMode)
|
BIND2(scenario_set_debug, RID, ScenarioDebugMode)
|
||||||
BIND2(scenario_set_environment, RID, RID)
|
|
||||||
BIND3(scenario_set_reflection_atlas_size, RID, int, int)
|
|
||||||
BIND2(scenario_set_fallback_environment, RID, RID)
|
|
||||||
|
|
||||||
/* INSTANCING API */
|
/* INSTANCING API */
|
||||||
|
|
||||||
@ -398,7 +393,6 @@ public:
|
|||||||
BIND2RC(Vector<ObjectID>, instances_cull_convex, const Vector<Plane> &, RID)
|
BIND2RC(Vector<ObjectID>, instances_cull_convex, const Vector<Plane> &, RID)
|
||||||
|
|
||||||
BIND3(instance_geometry_set_flag, RID, InstanceFlags, bool)
|
BIND3(instance_geometry_set_flag, RID, InstanceFlags, bool)
|
||||||
BIND2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting)
|
|
||||||
BIND2(instance_geometry_set_material_override, RID, RID)
|
BIND2(instance_geometry_set_material_override, RID, RID)
|
||||||
BIND2(instance_geometry_set_material_overlay, RID, RID)
|
BIND2(instance_geometry_set_material_overlay, RID, RID)
|
||||||
|
|
||||||
|
@ -328,13 +328,6 @@ RID RenderingServerScene::scenario_create() {
|
|||||||
scenario->sps->set_pair_callback(_instance_pair, this);
|
scenario->sps->set_pair_callback(_instance_pair, this);
|
||||||
scenario->sps->set_unpair_callback(_instance_unpair, this);
|
scenario->sps->set_unpair_callback(_instance_unpair, this);
|
||||||
|
|
||||||
scenario->shadow_atlas = RSG::scene_render->shadow_atlas_create();
|
|
||||||
RSG::scene_render->shadow_atlas_set_size(scenario->shadow_atlas, 1024); //make enough shadows for close distance, don't bother with rest
|
|
||||||
RSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->shadow_atlas, 0, 4);
|
|
||||||
RSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->shadow_atlas, 1, 4);
|
|
||||||
RSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->shadow_atlas, 2, 4);
|
|
||||||
RSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->shadow_atlas, 3, 8);
|
|
||||||
|
|
||||||
return scenario_rid;
|
return scenario_rid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,21 +356,6 @@ void RenderingServerScene::scenario_set_debug(RID p_scenario, RS::ScenarioDebugM
|
|||||||
scenario->debug = p_debug_mode;
|
scenario->debug = p_debug_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingServerScene::scenario_set_environment(RID p_scenario, RID p_environment) {
|
|
||||||
Scenario *scenario = scenario_owner.get(p_scenario);
|
|
||||||
ERR_FAIL_COND(!scenario);
|
|
||||||
scenario->environment = p_environment;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderingServerScene::scenario_set_fallback_environment(RID p_scenario, RID p_environment) {
|
|
||||||
Scenario *scenario = scenario_owner.get(p_scenario);
|
|
||||||
ERR_FAIL_COND(!scenario);
|
|
||||||
scenario->fallback_environment = p_environment;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderingServerScene::scenario_set_reflection_atlas_size(RID p_scenario, int p_size, int p_subdiv) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* INSTANCING API */
|
/* INSTANCING API */
|
||||||
|
|
||||||
void RenderingServerScene::_instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_materials) {
|
void RenderingServerScene::_instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_materials) {
|
||||||
@ -1019,13 +997,6 @@ void RenderingServerScene::instance_geometry_set_flag(RID p_instance, RS::Instan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void RenderingServerScene::instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting) {
|
|
||||||
Instance *instance = instance_owner.get(p_instance);
|
|
||||||
ERR_FAIL_COND(!instance);
|
|
||||||
|
|
||||||
instance->cast_shadows = p_shadow_casting_setting;
|
|
||||||
instance->base_changed(false, true); // to actually compute if shadows are visible or not
|
|
||||||
}
|
|
||||||
void RenderingServerScene::instance_geometry_set_material_override(RID p_instance, RID p_material) {
|
void RenderingServerScene::instance_geometry_set_material_override(RID p_instance, RID p_material) {
|
||||||
Instance *instance = instance_owner.get(p_instance);
|
Instance *instance = instance_owner.get(p_instance);
|
||||||
ERR_FAIL_COND(!instance);
|
ERR_FAIL_COND(!instance);
|
||||||
@ -1176,80 +1147,47 @@ void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
|
|||||||
if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
|
if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
|
||||||
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
|
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
|
||||||
|
|
||||||
bool can_cast_shadows = true;
|
|
||||||
bool is_animated = false;
|
bool is_animated = false;
|
||||||
|
|
||||||
if (p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_OFF) {
|
if (p_instance->material_override.is_valid()) {
|
||||||
can_cast_shadows = false;
|
|
||||||
} else if (p_instance->material_override.is_valid()) {
|
|
||||||
can_cast_shadows = RSG::storage->material_casts_shadows(p_instance->material_override);
|
|
||||||
is_animated = RSG::storage->material_is_animated(p_instance->material_override);
|
is_animated = RSG::storage->material_is_animated(p_instance->material_override);
|
||||||
} else {
|
} else {
|
||||||
if (p_instance->base_type == RS::INSTANCE_MESH) {
|
if (p_instance->base_type == RS::INSTANCE_MESH) {
|
||||||
RID mesh = p_instance->base;
|
RID mesh = p_instance->base;
|
||||||
|
|
||||||
if (mesh.is_valid()) {
|
if (mesh.is_valid()) {
|
||||||
bool cast_shadows = false;
|
|
||||||
|
|
||||||
for (int i = 0; i < p_instance->materials.size(); i++) {
|
for (int i = 0; i < p_instance->materials.size(); i++) {
|
||||||
RID mat = p_instance->materials[i].is_valid() ? p_instance->materials[i] : RSG::storage->mesh_surface_get_material(mesh, i);
|
RID mat = p_instance->materials[i].is_valid() ? p_instance->materials[i] : RSG::storage->mesh_surface_get_material(mesh, i);
|
||||||
|
|
||||||
if (!mat.is_valid()) {
|
if (mat.is_valid()) {
|
||||||
cast_shadows = true;
|
|
||||||
} else {
|
|
||||||
if (RSG::storage->material_casts_shadows(mat)) {
|
|
||||||
cast_shadows = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RSG::storage->material_is_animated(mat)) {
|
if (RSG::storage->material_is_animated(mat)) {
|
||||||
is_animated = true;
|
is_animated = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cast_shadows) {
|
|
||||||
can_cast_shadows = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (p_instance->base_type == RS::INSTANCE_MULTIMESH) {
|
} else if (p_instance->base_type == RS::INSTANCE_MULTIMESH) {
|
||||||
RID mesh = RSG::storage->multimesh_get_mesh(p_instance->base);
|
RID mesh = RSG::storage->multimesh_get_mesh(p_instance->base);
|
||||||
if (mesh.is_valid()) {
|
if (mesh.is_valid()) {
|
||||||
bool cast_shadows = false;
|
|
||||||
|
|
||||||
int sc = RSG::storage->mesh_get_surface_count(mesh);
|
int sc = RSG::storage->mesh_get_surface_count(mesh);
|
||||||
for (int i = 0; i < sc; i++) {
|
for (int i = 0; i < sc; i++) {
|
||||||
RID mat = RSG::storage->mesh_surface_get_material(mesh, i);
|
RID mat = RSG::storage->mesh_surface_get_material(mesh, i);
|
||||||
|
|
||||||
if (!mat.is_valid()) {
|
if (mat.is_valid()) {
|
||||||
cast_shadows = true;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (RSG::storage->material_casts_shadows(mat)) {
|
|
||||||
cast_shadows = true;
|
|
||||||
}
|
|
||||||
if (RSG::storage->material_is_animated(mat)) {
|
if (RSG::storage->material_is_animated(mat)) {
|
||||||
is_animated = true;
|
is_animated = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cast_shadows) {
|
|
||||||
can_cast_shadows = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_instance->material_overlay.is_valid()) {
|
if (p_instance->material_overlay.is_valid()) {
|
||||||
can_cast_shadows = can_cast_shadows || RSG::storage->material_casts_shadows(p_instance->material_overlay);
|
|
||||||
is_animated = is_animated || RSG::storage->material_is_animated(p_instance->material_overlay);
|
is_animated = is_animated || RSG::storage->material_is_animated(p_instance->material_overlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (can_cast_shadows != geom->can_cast_shadows) {
|
|
||||||
geom->can_cast_shadows = can_cast_shadows;
|
|
||||||
}
|
|
||||||
|
|
||||||
geom->material_is_animated = is_animated;
|
geom->material_is_animated = is_animated;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1262,7 +1200,7 @@ void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
|
|||||||
p_instance->update_materials = false;
|
p_instance->update_materials = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingServerScene::render_camera(RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) {
|
void RenderingServerScene::render_camera(RID p_camera, RID p_scenario, Size2 p_viewport_size) {
|
||||||
// render to mono camera
|
// render to mono camera
|
||||||
#ifndef _3D_DISABLED
|
#ifndef _3D_DISABLED
|
||||||
|
|
||||||
@ -1307,18 +1245,16 @@ void RenderingServerScene::render_camera(RID p_camera, RID p_scenario, Size2 p_v
|
|||||||
|
|
||||||
Transform camera_transform = _interpolation_data.interpolation_enabled ? camera->get_transform_interpolated() : camera->transform;
|
Transform camera_transform = _interpolation_data.interpolation_enabled ? camera->get_transform_interpolated() : camera->transform;
|
||||||
|
|
||||||
_prepare_scene(camera_transform, camera_matrix, ortho, camera->env, camera->visible_layers, p_scenario, p_shadow_atlas, RID(), camera->previous_room_id_hint);
|
_prepare_scene(camera_transform, camera_matrix, ortho, camera->env, camera->visible_layers, p_scenario, camera->previous_room_id_hint);
|
||||||
_render_scene(camera_transform, camera_matrix, 0, ortho, camera->env, p_scenario, p_shadow_atlas);
|
_render_scene(camera_transform, camera_matrix, 0, ortho, camera->env, p_scenario);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int32_t &r_previous_room_id_hint) {
|
void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, int32_t &r_previous_room_id_hint) {
|
||||||
// Note, in stereo rendering:
|
// Note, in stereo rendering:
|
||||||
// - p_cam_transform will be a transform in the middle of our two eyes
|
// - p_cam_transform will be a transform in the middle of our two eyes
|
||||||
// - p_cam_projection is a wider frustrum that encompasses both eyes
|
// - p_cam_projection is a wider frustrum that encompasses both eyes
|
||||||
|
|
||||||
Scenario *scenario = scenario_owner.getornull(p_scenario);
|
|
||||||
|
|
||||||
render_pass++;
|
render_pass++;
|
||||||
uint32_t camera_layer_mask = p_visible_layers;
|
uint32_t camera_layer_mask = p_visible_layers;
|
||||||
|
|
||||||
@ -1333,7 +1269,6 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
|
|||||||
|
|
||||||
/* STEP 2 - CULL */
|
/* STEP 2 - CULL */
|
||||||
instance_cull_count = 0;
|
instance_cull_count = 0;
|
||||||
light_cull_count = 0;
|
|
||||||
|
|
||||||
//light_samplers_culled=0;
|
//light_samplers_culled=0;
|
||||||
|
|
||||||
@ -1356,7 +1291,7 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
|
|||||||
|
|
||||||
if ((camera_layer_mask & ins->layer_mask) == 0) {
|
if ((camera_layer_mask & ins->layer_mask) == 0) {
|
||||||
//failure
|
//failure
|
||||||
} else if (((1 << ins->base_type) & RS::INSTANCE_GEOMETRY_MASK) && ins->visible && ins->cast_shadows != RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) {
|
} else if (((1 << ins->base_type) & RS::INSTANCE_GEOMETRY_MASK) && ins->visible) {
|
||||||
keep = true;
|
keep = true;
|
||||||
|
|
||||||
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(ins->base_data);
|
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(ins->base_data);
|
||||||
@ -1366,7 +1301,6 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (geom->lighting_dirty) {
|
if (geom->lighting_dirty) {
|
||||||
int l = 0;
|
|
||||||
//only called when lights AABB enter/exit this geometry
|
//only called when lights AABB enter/exit this geometry
|
||||||
ins->light_instances.resize(geom->lighting.size());
|
ins->light_instances.resize(geom->lighting.size());
|
||||||
geom->lighting_dirty = false;
|
geom->lighting_dirty = false;
|
||||||
@ -1387,14 +1321,11 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
|
|||||||
|
|
||||||
/* STEP 5 - PROCESS LIGHTS */
|
/* STEP 5 - PROCESS LIGHTS */
|
||||||
|
|
||||||
RID *directional_light_ptr = &light_instance_cull_result[light_cull_count];
|
|
||||||
directional_light_count = 0;
|
|
||||||
|
|
||||||
// Calculate instance->depth from the camera, after shadow calculation has stopped overwriting instance->depth
|
// Calculate instance->depth from the camera, after shadow calculation has stopped overwriting instance->depth
|
||||||
for (int i = 0; i < instance_cull_count; i++) {
|
for (int i = 0; i < instance_cull_count; i++) {
|
||||||
Instance *ins = instance_cull_result[i];
|
Instance *ins = instance_cull_result[i];
|
||||||
|
|
||||||
if (((1 << ins->base_type) & RS::INSTANCE_GEOMETRY_MASK) && ins->visible && ins->cast_shadows != RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) {
|
if (((1 << ins->base_type) & RS::INSTANCE_GEOMETRY_MASK) && ins->visible) {
|
||||||
Vector3 center = ins->transform.origin;
|
Vector3 center = ins->transform.origin;
|
||||||
if (ins->use_aabb_center) {
|
if (ins->use_aabb_center) {
|
||||||
center = ins->transformed_aabb.position + (ins->transformed_aabb.size * 0.5);
|
center = ins->transformed_aabb.position + (ins->transformed_aabb.size * 0.5);
|
||||||
@ -1409,37 +1340,15 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingServerScene::_render_scene(const Transform p_cam_transform, const Projection &p_cam_projection, const int p_eye, bool p_cam_orthogonal, RID p_force_environment, RID p_scenario, RID p_shadow_atlas) {
|
void RenderingServerScene::_render_scene(const Transform p_cam_transform, const Projection &p_cam_projection, const int p_eye, bool p_cam_orthogonal, RID p_force_environment, RID p_scenario) {
|
||||||
Scenario *scenario = scenario_owner.getornull(p_scenario);
|
|
||||||
|
|
||||||
/* ENVIRONMENT */
|
|
||||||
|
|
||||||
RID environment;
|
|
||||||
if (p_force_environment.is_valid()) { //camera has more environment priority
|
|
||||||
environment = p_force_environment;
|
|
||||||
} else if (scenario->environment.is_valid()) {
|
|
||||||
environment = scenario->environment;
|
|
||||||
} else {
|
|
||||||
environment = scenario->fallback_environment;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* PROCESS GEOMETRY AND DRAW SCENE */
|
/* PROCESS GEOMETRY AND DRAW SCENE */
|
||||||
|
|
||||||
RSG::scene_render->render_scene(p_cam_transform, p_cam_projection, p_eye, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, p_shadow_atlas);
|
RSG::scene_render->render_scene(p_cam_transform, p_cam_projection, p_eye, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingServerScene::render_empty_scene(RID p_scenario, RID p_shadow_atlas) {
|
void RenderingServerScene::render_empty_scene(RID p_scenario) {
|
||||||
#ifndef _3D_DISABLED
|
#ifndef _3D_DISABLED
|
||||||
|
RSG::scene_render->render_scene(Transform(), Projection(), 0, true, nullptr, 0);
|
||||||
Scenario *scenario = scenario_owner.getornull(p_scenario);
|
|
||||||
|
|
||||||
RID environment;
|
|
||||||
if (scenario->environment.is_valid()) {
|
|
||||||
environment = scenario->environment;
|
|
||||||
} else {
|
|
||||||
environment = scenario->fallback_environment;
|
|
||||||
}
|
|
||||||
RSG::scene_render->render_scene(Transform(), Projection(), 0, true, nullptr, 0, nullptr, 0, p_shadow_atlas);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1475,7 +1384,7 @@ bool RenderingServerScene::free(RID p_rid) {
|
|||||||
while (scenario->instances.first()) {
|
while (scenario->instances.first()) {
|
||||||
instance_set_scenario(scenario->instances.first()->self()->self, RID());
|
instance_set_scenario(scenario->instances.first()->self()->self, RID());
|
||||||
}
|
}
|
||||||
RSG::scene_render->free(scenario->shadow_atlas);
|
|
||||||
scenario_owner.free(p_rid);
|
scenario_owner.free(p_rid);
|
||||||
memdelete(scenario);
|
memdelete(scenario);
|
||||||
|
|
||||||
|
@ -270,11 +270,6 @@ public:
|
|||||||
|
|
||||||
SpatialPartitioningScene *sps;
|
SpatialPartitioningScene *sps;
|
||||||
|
|
||||||
List<Instance *> directional_lights;
|
|
||||||
RID environment;
|
|
||||||
RID fallback_environment;
|
|
||||||
RID shadow_atlas;
|
|
||||||
|
|
||||||
SelfList<Instance>::List instances;
|
SelfList<Instance>::List instances;
|
||||||
|
|
||||||
Scenario();
|
Scenario();
|
||||||
@ -289,9 +284,6 @@ public:
|
|||||||
virtual RID scenario_create();
|
virtual RID scenario_create();
|
||||||
|
|
||||||
virtual void scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode);
|
virtual void scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode);
|
||||||
virtual void scenario_set_environment(RID p_scenario, RID p_environment);
|
|
||||||
virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment);
|
|
||||||
virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_size, int p_subdiv);
|
|
||||||
|
|
||||||
/* INSTANCING API */
|
/* INSTANCING API */
|
||||||
|
|
||||||
@ -416,45 +408,16 @@ public:
|
|||||||
struct InstanceGeometryData : public InstanceBaseData {
|
struct InstanceGeometryData : public InstanceBaseData {
|
||||||
List<Instance *> lighting;
|
List<Instance *> lighting;
|
||||||
bool lighting_dirty;
|
bool lighting_dirty;
|
||||||
bool can_cast_shadows;
|
|
||||||
bool material_is_animated;
|
bool material_is_animated;
|
||||||
|
|
||||||
InstanceGeometryData() {
|
InstanceGeometryData() {
|
||||||
lighting_dirty = true;
|
lighting_dirty = true;
|
||||||
can_cast_shadows = true;
|
|
||||||
material_is_animated = true;
|
material_is_animated = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InstanceReflectionProbeData : public InstanceBaseData {
|
|
||||||
Instance *owner;
|
|
||||||
|
|
||||||
struct PairInfo {
|
|
||||||
List<Instance *>::Element *L; //reflection iterator in geometry
|
|
||||||
Instance *geometry;
|
|
||||||
};
|
|
||||||
List<PairInfo> geometries;
|
|
||||||
|
|
||||||
RID instance;
|
|
||||||
SelfList<InstanceReflectionProbeData> update_list;
|
|
||||||
|
|
||||||
int render_step;
|
|
||||||
int32_t previous_room_id_hint;
|
|
||||||
|
|
||||||
InstanceReflectionProbeData() :
|
|
||||||
update_list(this) {
|
|
||||||
render_step = -1;
|
|
||||||
previous_room_id_hint = -1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int instance_cull_count;
|
int instance_cull_count;
|
||||||
Instance *instance_cull_result[MAX_INSTANCE_CULL];
|
Instance *instance_cull_result[MAX_INSTANCE_CULL];
|
||||||
Instance *instance_shadow_cull_result[MAX_INSTANCE_CULL]; //used for generating shadowmaps
|
|
||||||
Instance *light_cull_result[MAX_LIGHTS_CULLED];
|
|
||||||
RID light_instance_cull_result[MAX_LIGHTS_CULLED];
|
|
||||||
int light_cull_count;
|
|
||||||
int directional_light_count;
|
|
||||||
|
|
||||||
RID_Owner<Instance> instance_owner;
|
RID_Owner<Instance> instance_owner;
|
||||||
|
|
||||||
@ -491,7 +454,6 @@ public:
|
|||||||
virtual Vector<ObjectID> instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario = RID()) const;
|
virtual Vector<ObjectID> instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario = RID()) const;
|
||||||
|
|
||||||
virtual void instance_geometry_set_flag(RID p_instance, RS::InstanceFlags p_flags, bool p_enabled);
|
virtual void instance_geometry_set_flag(RID p_instance, RS::InstanceFlags p_flags, bool p_enabled);
|
||||||
virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting);
|
|
||||||
virtual void instance_geometry_set_material_override(RID p_instance, RID p_material);
|
virtual void instance_geometry_set_material_override(RID p_instance, RID p_material);
|
||||||
virtual void instance_geometry_set_material_overlay(RID p_instance, RID p_material);
|
virtual void instance_geometry_set_material_overlay(RID p_instance, RID p_material);
|
||||||
|
|
||||||
@ -502,11 +464,11 @@ public:
|
|||||||
_FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance);
|
_FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance);
|
||||||
_FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance);
|
_FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance);
|
||||||
|
|
||||||
void _prepare_scene(const Transform p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int32_t &r_previous_room_id_hint);
|
void _prepare_scene(const Transform p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, int32_t &r_previous_room_id_hint);
|
||||||
void _render_scene(const Transform p_cam_transform, const Projection &p_cam_projection, const int p_eye, bool p_cam_orthogonal, RID p_force_environment, RID p_scenario, RID p_shadow_atlas);
|
void _render_scene(const Transform p_cam_transform, const Projection &p_cam_projection, const int p_eye, bool p_cam_orthogonal, RID p_force_environment, RID p_scenario);
|
||||||
void render_empty_scene(RID p_scenario, RID p_shadow_atlas);
|
void render_empty_scene(RID p_scenario);
|
||||||
|
|
||||||
void render_camera(RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas);
|
void render_camera(RID p_camera, RID p_scenario, Size2 p_viewport_size);
|
||||||
void update_dirty_instances();
|
void update_dirty_instances();
|
||||||
|
|
||||||
// interpolation
|
// interpolation
|
||||||
|
@ -65,7 +65,7 @@ static Transform2D _canvas_get_transform(RenderingServerViewport::Viewport *p_vi
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RenderingServerViewport::_draw_3d(Viewport *p_viewport) {
|
void RenderingServerViewport::_draw_3d(Viewport *p_viewport) {
|
||||||
RSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
|
RSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingServerViewport::_draw_viewport(Viewport *p_viewport) {
|
void RenderingServerViewport::_draw_viewport(Viewport *p_viewport) {
|
||||||
@ -103,7 +103,7 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport) {
|
|||||||
|
|
||||||
if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().get_layer() > scenario_canvas_max_layer) {
|
if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().get_layer() > scenario_canvas_max_layer) {
|
||||||
if (!can_draw_3d) {
|
if (!can_draw_3d) {
|
||||||
RSG::scene->render_empty_scene(p_viewport->scenario, p_viewport->shadow_atlas);
|
RSG::scene->render_empty_scene(p_viewport->scenario);
|
||||||
} else {
|
} else {
|
||||||
_draw_3d(p_viewport);
|
_draw_3d(p_viewport);
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport) {
|
|||||||
|
|
||||||
if (scenario_draw_canvas_bg && E->key().get_layer() >= scenario_canvas_max_layer) {
|
if (scenario_draw_canvas_bg && E->key().get_layer() >= scenario_canvas_max_layer) {
|
||||||
if (!can_draw_3d) {
|
if (!can_draw_3d) {
|
||||||
RSG::scene->render_empty_scene(p_viewport->scenario, p_viewport->shadow_atlas);
|
RSG::scene->render_empty_scene(p_viewport->scenario);
|
||||||
} else {
|
} else {
|
||||||
_draw_3d(p_viewport);
|
_draw_3d(p_viewport);
|
||||||
}
|
}
|
||||||
@ -132,7 +132,7 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport) {
|
|||||||
|
|
||||||
if (scenario_draw_canvas_bg) {
|
if (scenario_draw_canvas_bg) {
|
||||||
if (!can_draw_3d) {
|
if (!can_draw_3d) {
|
||||||
RSG::scene->render_empty_scene(p_viewport->scenario, p_viewport->shadow_atlas);
|
RSG::scene->render_empty_scene(p_viewport->scenario);
|
||||||
} else {
|
} else {
|
||||||
_draw_3d(p_viewport);
|
_draw_3d(p_viewport);
|
||||||
}
|
}
|
||||||
@ -210,7 +210,6 @@ RID RenderingServerViewport::viewport_create() {
|
|||||||
viewport->hide_scenario = false;
|
viewport->hide_scenario = false;
|
||||||
viewport->hide_canvas = false;
|
viewport->hide_canvas = false;
|
||||||
viewport->render_target = RSG::storage->render_target_create();
|
viewport->render_target = RSG::storage->render_target_create();
|
||||||
viewport->shadow_atlas = RSG::scene_render->shadow_atlas_create();
|
|
||||||
viewport->viewport_render_direct_to_screen = false;
|
viewport->viewport_render_direct_to_screen = false;
|
||||||
|
|
||||||
return rid;
|
return rid;
|
||||||
@ -429,22 +428,6 @@ void RenderingServerViewport::viewport_set_canvas_stacking(RID p_viewport, RID p
|
|||||||
viewport->canvas_map[p_canvas].sublayer = p_sublayer;
|
viewport->canvas_map[p_canvas].sublayer = p_sublayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingServerViewport::viewport_set_shadow_atlas_size(RID p_viewport, int p_size) {
|
|
||||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
|
||||||
ERR_FAIL_COND(!viewport);
|
|
||||||
|
|
||||||
viewport->shadow_atlas_size = p_size;
|
|
||||||
|
|
||||||
RSG::scene_render->shadow_atlas_set_size(viewport->shadow_atlas, viewport->shadow_atlas_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderingServerViewport::viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) {
|
|
||||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
|
||||||
ERR_FAIL_COND(!viewport);
|
|
||||||
|
|
||||||
RSG::scene_render->shadow_atlas_set_quadrant_subdivision(viewport->shadow_atlas, p_quadrant, p_subdiv);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderingServerViewport::viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa) {
|
void RenderingServerViewport::viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa) {
|
||||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||||
ERR_FAIL_COND(!viewport);
|
ERR_FAIL_COND(!viewport);
|
||||||
|
@ -175,9 +175,6 @@ public:
|
|||||||
void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform);
|
void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform);
|
||||||
void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer);
|
void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer);
|
||||||
|
|
||||||
void viewport_set_shadow_atlas_size(RID p_viewport, int p_size);
|
|
||||||
void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv);
|
|
||||||
|
|
||||||
void viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa);
|
void viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa);
|
||||||
void viewport_set_use_fxaa(RID p_viewport, bool p_fxaa);
|
void viewport_set_use_fxaa(RID p_viewport, bool p_fxaa);
|
||||||
void viewport_set_use_debanding(RID p_viewport, bool p_debanding);
|
void viewport_set_use_debanding(RID p_viewport, bool p_debanding);
|
||||||
|
@ -258,8 +258,6 @@ public:
|
|||||||
|
|
||||||
FUNC2(viewport_set_global_canvas_transform, RID, const Transform2D &)
|
FUNC2(viewport_set_global_canvas_transform, RID, const Transform2D &)
|
||||||
FUNC4(viewport_set_canvas_stacking, RID, RID, int, int)
|
FUNC4(viewport_set_canvas_stacking, RID, RID, int, int)
|
||||||
FUNC2(viewport_set_shadow_atlas_size, RID, int)
|
|
||||||
FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
|
|
||||||
FUNC2(viewport_set_msaa, RID, ViewportMSAA)
|
FUNC2(viewport_set_msaa, RID, ViewportMSAA)
|
||||||
FUNC2(viewport_set_use_fxaa, RID, bool)
|
FUNC2(viewport_set_use_fxaa, RID, bool)
|
||||||
FUNC2(viewport_set_use_debanding, RID, bool)
|
FUNC2(viewport_set_use_debanding, RID, bool)
|
||||||
@ -280,9 +278,6 @@ public:
|
|||||||
FUNCRID(scenario)
|
FUNCRID(scenario)
|
||||||
|
|
||||||
FUNC2(scenario_set_debug, RID, ScenarioDebugMode)
|
FUNC2(scenario_set_debug, RID, ScenarioDebugMode)
|
||||||
FUNC2(scenario_set_environment, RID, RID)
|
|
||||||
FUNC3(scenario_set_reflection_atlas_size, RID, int, int)
|
|
||||||
FUNC2(scenario_set_fallback_environment, RID, RID)
|
|
||||||
|
|
||||||
/* INSTANCING API */
|
/* INSTANCING API */
|
||||||
FUNCRID(instance)
|
FUNCRID(instance)
|
||||||
@ -315,7 +310,6 @@ public:
|
|||||||
FUNC2RC(Vector<ObjectID>, instances_cull_convex, const Vector<Plane> &, RID)
|
FUNC2RC(Vector<ObjectID>, instances_cull_convex, const Vector<Plane> &, RID)
|
||||||
|
|
||||||
FUNC3(instance_geometry_set_flag, RID, InstanceFlags, bool)
|
FUNC3(instance_geometry_set_flag, RID, InstanceFlags, bool)
|
||||||
FUNC2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting)
|
|
||||||
FUNC2(instance_geometry_set_material_override, RID, RID)
|
FUNC2(instance_geometry_set_material_override, RID, RID)
|
||||||
FUNC2(instance_geometry_set_material_overlay, RID, RID)
|
FUNC2(instance_geometry_set_material_overlay, RID, RID)
|
||||||
|
|
||||||
|
@ -1954,8 +1954,6 @@ void RenderingServer::_bind_methods() {
|
|||||||
ClassDB::bind_method(D_METHOD("viewport_set_transparent_background", "viewport", "enabled"), &RenderingServer::viewport_set_transparent_background);
|
ClassDB::bind_method(D_METHOD("viewport_set_transparent_background", "viewport", "enabled"), &RenderingServer::viewport_set_transparent_background);
|
||||||
ClassDB::bind_method(D_METHOD("viewport_set_global_canvas_transform", "viewport", "transform"), &RenderingServer::viewport_set_global_canvas_transform);
|
ClassDB::bind_method(D_METHOD("viewport_set_global_canvas_transform", "viewport", "transform"), &RenderingServer::viewport_set_global_canvas_transform);
|
||||||
ClassDB::bind_method(D_METHOD("viewport_set_canvas_stacking", "viewport", "canvas", "layer", "sublayer"), &RenderingServer::viewport_set_canvas_stacking);
|
ClassDB::bind_method(D_METHOD("viewport_set_canvas_stacking", "viewport", "canvas", "layer", "sublayer"), &RenderingServer::viewport_set_canvas_stacking);
|
||||||
ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_size", "viewport", "size"), &RenderingServer::viewport_set_shadow_atlas_size);
|
|
||||||
ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_quadrant_subdivision", "viewport", "quadrant", "subdivision"), &RenderingServer::viewport_set_shadow_atlas_quadrant_subdivision);
|
|
||||||
ClassDB::bind_method(D_METHOD("viewport_set_msaa", "viewport", "msaa"), &RenderingServer::viewport_set_msaa);
|
ClassDB::bind_method(D_METHOD("viewport_set_msaa", "viewport", "msaa"), &RenderingServer::viewport_set_msaa);
|
||||||
ClassDB::bind_method(D_METHOD("viewport_set_use_fxaa", "viewport", "fxaa"), &RenderingServer::viewport_set_use_fxaa);
|
ClassDB::bind_method(D_METHOD("viewport_set_use_fxaa", "viewport", "fxaa"), &RenderingServer::viewport_set_use_fxaa);
|
||||||
ClassDB::bind_method(D_METHOD("viewport_set_use_debanding", "viewport", "debanding"), &RenderingServer::viewport_set_use_debanding);
|
ClassDB::bind_method(D_METHOD("viewport_set_use_debanding", "viewport", "debanding"), &RenderingServer::viewport_set_use_debanding);
|
||||||
@ -1968,9 +1966,6 @@ void RenderingServer::_bind_methods() {
|
|||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("scenario_create"), &RenderingServer::scenario_create);
|
ClassDB::bind_method(D_METHOD("scenario_create"), &RenderingServer::scenario_create);
|
||||||
ClassDB::bind_method(D_METHOD("scenario_set_debug", "scenario", "debug_mode"), &RenderingServer::scenario_set_debug);
|
ClassDB::bind_method(D_METHOD("scenario_set_debug", "scenario", "debug_mode"), &RenderingServer::scenario_set_debug);
|
||||||
ClassDB::bind_method(D_METHOD("scenario_set_environment", "scenario", "environment"), &RenderingServer::scenario_set_environment);
|
|
||||||
ClassDB::bind_method(D_METHOD("scenario_set_reflection_atlas_size", "scenario", "size", "subdiv"), &RenderingServer::scenario_set_reflection_atlas_size);
|
|
||||||
ClassDB::bind_method(D_METHOD("scenario_set_fallback_environment", "scenario", "environment"), &RenderingServer::scenario_set_fallback_environment);
|
|
||||||
|
|
||||||
#ifndef _3D_DISABLED
|
#ifndef _3D_DISABLED
|
||||||
|
|
||||||
@ -1991,7 +1986,6 @@ void RenderingServer::_bind_methods() {
|
|||||||
ClassDB::bind_method(D_METHOD("instance_set_exterior", "instance", "enabled"), &RenderingServer::instance_set_exterior);
|
ClassDB::bind_method(D_METHOD("instance_set_exterior", "instance", "enabled"), &RenderingServer::instance_set_exterior);
|
||||||
ClassDB::bind_method(D_METHOD("instance_set_extra_visibility_margin", "instance", "margin"), &RenderingServer::instance_set_extra_visibility_margin);
|
ClassDB::bind_method(D_METHOD("instance_set_extra_visibility_margin", "instance", "margin"), &RenderingServer::instance_set_extra_visibility_margin);
|
||||||
ClassDB::bind_method(D_METHOD("instance_geometry_set_flag", "instance", "flag", "enabled"), &RenderingServer::instance_geometry_set_flag);
|
ClassDB::bind_method(D_METHOD("instance_geometry_set_flag", "instance", "flag", "enabled"), &RenderingServer::instance_geometry_set_flag);
|
||||||
ClassDB::bind_method(D_METHOD("instance_geometry_set_cast_shadows_setting", "instance", "shadow_casting_setting"), &RenderingServer::instance_geometry_set_cast_shadows_setting);
|
|
||||||
ClassDB::bind_method(D_METHOD("instance_geometry_set_material_override", "instance", "material"), &RenderingServer::instance_geometry_set_material_override);
|
ClassDB::bind_method(D_METHOD("instance_geometry_set_material_override", "instance", "material"), &RenderingServer::instance_geometry_set_material_override);
|
||||||
ClassDB::bind_method(D_METHOD("instance_geometry_set_material_overlay", "instance", "material"), &RenderingServer::instance_geometry_set_material_overlay);
|
ClassDB::bind_method(D_METHOD("instance_geometry_set_material_overlay", "instance", "material"), &RenderingServer::instance_geometry_set_material_overlay);
|
||||||
ClassDB::bind_method(D_METHOD("instance_geometry_set_draw_range", "instance", "min", "max", "min_margin", "max_margin"), &RenderingServer::instance_geometry_set_draw_range);
|
ClassDB::bind_method(D_METHOD("instance_geometry_set_draw_range", "instance", "min", "max", "min_margin", "max_margin"), &RenderingServer::instance_geometry_set_draw_range);
|
||||||
@ -2208,11 +2202,6 @@ void RenderingServer::_bind_methods() {
|
|||||||
BIND_ENUM_CONSTANT(INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE);
|
BIND_ENUM_CONSTANT(INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE);
|
||||||
BIND_ENUM_CONSTANT(INSTANCE_FLAG_MAX);
|
BIND_ENUM_CONSTANT(INSTANCE_FLAG_MAX);
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_OFF);
|
|
||||||
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_ON);
|
|
||||||
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_DOUBLE_SIDED);
|
|
||||||
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_SHADOWS_ONLY);
|
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(NINE_PATCH_STRETCH);
|
BIND_ENUM_CONSTANT(NINE_PATCH_STRETCH);
|
||||||
BIND_ENUM_CONSTANT(NINE_PATCH_TILE);
|
BIND_ENUM_CONSTANT(NINE_PATCH_TILE);
|
||||||
BIND_ENUM_CONSTANT(NINE_PATCH_TILE_FIT);
|
BIND_ENUM_CONSTANT(NINE_PATCH_TILE_FIT);
|
||||||
@ -2335,23 +2324,6 @@ RenderingServer::RenderingServer() {
|
|||||||
GLOBAL_DEF("rendering/limits/time/time_rollover_secs", 3600);
|
GLOBAL_DEF("rendering/limits/time/time_rollover_secs", 3600);
|
||||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/time/time_rollover_secs", PropertyInfo(Variant::REAL, "rendering/limits/time/time_rollover_secs", PROPERTY_HINT_RANGE, "0,10000,1,or_greater"));
|
ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/time/time_rollover_secs", PropertyInfo(Variant::REAL, "rendering/limits/time/time_rollover_secs", PROPERTY_HINT_RANGE, "0,10000,1,or_greater"));
|
||||||
|
|
||||||
GLOBAL_DEF("rendering/quality/directional_shadow/size", 4096);
|
|
||||||
GLOBAL_DEF("rendering/quality/directional_shadow/size.mobile", 2048);
|
|
||||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/directional_shadow/size", PropertyInfo(Variant::INT, "rendering/quality/directional_shadow/size", PROPERTY_HINT_RANGE, "256,16384,256"));
|
|
||||||
GLOBAL_DEF_RST("rendering/quality/shadow_atlas/size", 4096);
|
|
||||||
GLOBAL_DEF("rendering/quality/shadow_atlas/size.mobile", 2048);
|
|
||||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/size", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/size", PROPERTY_HINT_RANGE, "256,16384,256"));
|
|
||||||
GLOBAL_DEF_RST("rendering/quality/shadow_atlas/cubemap_size", 512);
|
|
||||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/cubemap_size", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/cubemap_size", PROPERTY_HINT_RANGE, "64,16384,64"));
|
|
||||||
GLOBAL_DEF("rendering/quality/shadow_atlas/quadrant_0_subdiv", 1);
|
|
||||||
GLOBAL_DEF("rendering/quality/shadow_atlas/quadrant_1_subdiv", 2);
|
|
||||||
GLOBAL_DEF("rendering/quality/shadow_atlas/quadrant_2_subdiv", 3);
|
|
||||||
GLOBAL_DEF("rendering/quality/shadow_atlas/quadrant_3_subdiv", 4);
|
|
||||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/quadrant_0_subdiv", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/quadrant_0_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
|
|
||||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/quadrant_1_subdiv", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/quadrant_1_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
|
|
||||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/quadrant_2_subdiv", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/quadrant_2_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
|
|
||||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/quadrant_3_subdiv", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/quadrant_3_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
|
|
||||||
|
|
||||||
GLOBAL_DEF("rendering/quality/shadows/filter_mode", 1);
|
GLOBAL_DEF("rendering/quality/shadows/filter_mode", 1);
|
||||||
GLOBAL_DEF("rendering/quality/shadows/filter_mode.mobile", 0);
|
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,PCF5,PCF13"));
|
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadows/filter_mode", PropertyInfo(Variant::INT, "rendering/quality/shadows/filter_mode", PROPERTY_HINT_ENUM, "Disabled,PCF5,PCF13"));
|
||||||
|
@ -458,9 +458,6 @@ public:
|
|||||||
virtual void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform) = 0;
|
virtual void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform) = 0;
|
||||||
virtual void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer) = 0;
|
virtual void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer) = 0;
|
||||||
|
|
||||||
virtual void viewport_set_shadow_atlas_size(RID p_viewport, int p_size) = 0;
|
|
||||||
virtual void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) = 0;
|
|
||||||
|
|
||||||
enum ViewportMSAA {
|
enum ViewportMSAA {
|
||||||
VIEWPORT_MSAA_DISABLED,
|
VIEWPORT_MSAA_DISABLED,
|
||||||
VIEWPORT_MSAA_2X,
|
VIEWPORT_MSAA_2X,
|
||||||
@ -528,9 +525,6 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
virtual void scenario_set_debug(RID p_scenario, ScenarioDebugMode p_debug_mode) = 0;
|
virtual void scenario_set_debug(RID p_scenario, ScenarioDebugMode p_debug_mode) = 0;
|
||||||
virtual void scenario_set_environment(RID p_scenario, RID p_environment) = 0;
|
|
||||||
virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_size, int p_subdiv) = 0;
|
|
||||||
virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment) = 0;
|
|
||||||
|
|
||||||
/* INSTANCING API */
|
/* INSTANCING API */
|
||||||
|
|
||||||
@ -584,15 +578,7 @@ public:
|
|||||||
INSTANCE_FLAG_MAX
|
INSTANCE_FLAG_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ShadowCastingSetting {
|
|
||||||
SHADOW_CASTING_SETTING_OFF,
|
|
||||||
SHADOW_CASTING_SETTING_ON,
|
|
||||||
SHADOW_CASTING_SETTING_DOUBLE_SIDED,
|
|
||||||
SHADOW_CASTING_SETTING_SHADOWS_ONLY,
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual void instance_geometry_set_flag(RID p_instance, InstanceFlags p_flags, bool p_enabled) = 0;
|
virtual void instance_geometry_set_flag(RID p_instance, InstanceFlags p_flags, bool p_enabled) = 0;
|
||||||
virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, ShadowCastingSetting p_shadow_casting_setting) = 0;
|
|
||||||
virtual void instance_geometry_set_material_override(RID p_instance, RID p_material) = 0;
|
virtual void instance_geometry_set_material_override(RID p_instance, RID p_material) = 0;
|
||||||
virtual void instance_geometry_set_material_overlay(RID p_instance, RID p_material) = 0;
|
virtual void instance_geometry_set_material_overlay(RID p_instance, RID p_material) = 0;
|
||||||
|
|
||||||
@ -795,7 +781,6 @@ VARIANT_ENUM_CAST(RenderingServer::MultimeshColorFormat);
|
|||||||
VARIANT_ENUM_CAST(RenderingServer::MultimeshCustomDataFormat);
|
VARIANT_ENUM_CAST(RenderingServer::MultimeshCustomDataFormat);
|
||||||
VARIANT_ENUM_CAST(RenderingServer::MultimeshPhysicsInterpolationQuality);
|
VARIANT_ENUM_CAST(RenderingServer::MultimeshPhysicsInterpolationQuality);
|
||||||
VARIANT_ENUM_CAST(RenderingServer::InstanceFlags);
|
VARIANT_ENUM_CAST(RenderingServer::InstanceFlags);
|
||||||
VARIANT_ENUM_CAST(RenderingServer::ShadowCastingSetting);
|
|
||||||
VARIANT_ENUM_CAST(RenderingServer::TextureType);
|
VARIANT_ENUM_CAST(RenderingServer::TextureType);
|
||||||
VARIANT_ENUM_CAST(RenderingServer::ChangedPriority);
|
VARIANT_ENUM_CAST(RenderingServer::ChangedPriority);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user