Reflection probe support in GLES2 back-end.
This commit is contained in:
parent
40c3c8745d
commit
f2ed26d71e
|
@ -517,6 +517,7 @@ public:
|
|||
void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {}
|
||||
void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) {}
|
||||
void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {}
|
||||
void reflection_probe_set_resolution(RID p_probe, int p_resolution) {}
|
||||
|
||||
AABB reflection_probe_get_aabb(RID p_probe) const { return AABB(); }
|
||||
VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const { return VisualServer::REFLECTION_PROBE_UPDATE_ONCE; }
|
||||
|
|
|
@ -437,29 +437,182 @@ void RasterizerSceneGLES2::reflection_atlas_set_subdivision(RID p_ref_atlas, int
|
|||
////////////////////////////////////////////////////
|
||||
|
||||
RID RasterizerSceneGLES2::reflection_probe_instance_create(RID p_probe) {
|
||||
return RID();
|
||||
|
||||
RasterizerStorageGLES2::ReflectionProbe *probe = storage->reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!probe, RID());
|
||||
|
||||
ReflectionProbeInstance *rpi = memnew(ReflectionProbeInstance);
|
||||
|
||||
rpi->probe_ptr = probe;
|
||||
rpi->self = reflection_probe_instance_owner.make_rid(rpi);
|
||||
rpi->probe = p_probe;
|
||||
rpi->reflection_atlas_index = -1;
|
||||
rpi->render_step = -1;
|
||||
rpi->last_pass = 0;
|
||||
rpi->current_resolution = 0;
|
||||
rpi->dirty = true;
|
||||
|
||||
rpi->last_pass = 0;
|
||||
rpi->index = 0;
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
glGenFramebuffers(1, &rpi->fbo[i]);
|
||||
}
|
||||
|
||||
glGenFramebuffers(1, &rpi->fbo_blur);
|
||||
glGenRenderbuffers(1, &rpi->depth);
|
||||
glGenTextures(1, &rpi->cubemap);
|
||||
|
||||
return rpi->self;
|
||||
}
|
||||
|
||||
void RasterizerSceneGLES2::reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) {
|
||||
|
||||
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
|
||||
ERR_FAIL_COND(!rpi);
|
||||
rpi->transform = p_transform;
|
||||
}
|
||||
|
||||
void RasterizerSceneGLES2::reflection_probe_release_atlas_index(RID p_instance) {
|
||||
}
|
||||
|
||||
bool RasterizerSceneGLES2::reflection_probe_instance_needs_redraw(RID p_instance) {
|
||||
return false;
|
||||
const ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
|
||||
ERR_FAIL_COND_V(!rpi, false);
|
||||
|
||||
bool need_redraw = rpi->probe_ptr->resolution != rpi->current_resolution || rpi->dirty || rpi->probe_ptr->update_mode == VS::REFLECTION_PROBE_UPDATE_ALWAYS;
|
||||
rpi->dirty = false;
|
||||
return need_redraw;
|
||||
}
|
||||
|
||||
bool RasterizerSceneGLES2::reflection_probe_instance_has_reflection(RID p_instance) {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RasterizerSceneGLES2::reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) {
|
||||
return false;
|
||||
|
||||
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
|
||||
ERR_FAIL_COND_V(!rpi, false);
|
||||
|
||||
rpi->render_step = 0;
|
||||
|
||||
if (rpi->probe_ptr->resolution != rpi->current_resolution) {
|
||||
|
||||
//update cubemap if resolution changed
|
||||
int size = rpi->probe_ptr->resolution;
|
||||
rpi->current_resolution = size;
|
||||
|
||||
int lod = 0;
|
||||
|
||||
GLenum internal_format = GL_RGBA;
|
||||
GLenum format = GL_RGBA;
|
||||
GLenum type = GL_UNSIGNED_BYTE;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, rpi->cubemap);
|
||||
|
||||
// Set the initial (empty) mipmaps, all need to be set for this to work in GLES2, even if later wont be used.
|
||||
while (size >= 1) {
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
glTexImage2D(_cube_side_enum[i], lod, internal_format, size, size, 0, format, type, NULL);
|
||||
if (size == rpi->current_resolution) {
|
||||
//adjust framebuffer
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, rpi->fbo[i]);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _cube_side_enum[i], rpi->cubemap, 0);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rpi->depth);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, size, size);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rpi->depth);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
lod++;
|
||||
|
||||
size >>= 1;
|
||||
}
|
||||
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_instance) {
|
||||
return false;
|
||||
|
||||
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
|
||||
ERR_FAIL_COND_V(!rpi, false);
|
||||
|
||||
int size = rpi->probe_ptr->resolution;
|
||||
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
for (int i = 0; i < VS::ARRAY_MAX - 1; i++) {
|
||||
glDisableVertexAttribArray(i);
|
||||
}
|
||||
}
|
||||
|
||||
//vdc cache
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, storage->resources.radical_inverse_vdc_cache_tex);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, rpi->fbo_blur);
|
||||
// now render to the framebuffer, mipmap level for mipmap level
|
||||
int lod = 1;
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, rpi->cubemap);
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //use linear, no mipmaps so it does not read from what is being written to
|
||||
|
||||
size >>= 1;
|
||||
int mipmaps = 6;
|
||||
int mm_level = mipmaps - 1;
|
||||
|
||||
storage->shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_SOURCE_PANORAMA, false);
|
||||
storage->shaders.cubemap_filter.bind();
|
||||
|
||||
//blur
|
||||
while (size >= 1) {
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _cube_side_enum[i], rpi->cubemap, lod);
|
||||
|
||||
glViewport(0, 0, size, size);
|
||||
storage->bind_quad_array();
|
||||
storage->shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::FACE_ID, i);
|
||||
float roughness = CLAMP(lod / (float)(mipmaps - 1), 0, 1);
|
||||
storage->shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::ROUGHNESS, roughness);
|
||||
storage->shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::Z_FLIP, false);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
}
|
||||
|
||||
size >>= 1;
|
||||
|
||||
mm_level--;
|
||||
|
||||
lod++;
|
||||
}
|
||||
|
||||
// restore ranges
|
||||
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ENVIRONMENT API */
|
||||
|
@ -779,17 +932,37 @@ void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::G
|
|||
|
||||
e->material_index = e->material->index;
|
||||
|
||||
e->refprobe_0_index = 0xFF; //refprobe disabled by default
|
||||
e->refprobe_1_index = 0xFF; //refprobe disabled by default
|
||||
e->refprobe_0_index = RenderList::MAX_REFLECTION_PROBES; //refprobe disabled by default
|
||||
e->refprobe_1_index = RenderList::MAX_REFLECTION_PROBES; //refprobe disabled by default
|
||||
|
||||
if (!p_depth_pass) {
|
||||
|
||||
e->depth_layer = e->instance->depth_layer;
|
||||
e->priority = p_material->render_priority;
|
||||
|
||||
//if (e->instance->reflection_probe_instances.size() > 0 ) {
|
||||
// RasterizerStorageGLES2::
|
||||
//}
|
||||
int rpsize = e->instance->reflection_probe_instances.size();
|
||||
if (rpsize > 0) {
|
||||
bool first = true;
|
||||
for (int i = 0; i < rpsize; i++) {
|
||||
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(e->instance->reflection_probe_instances[i]);
|
||||
if (rpi->last_pass != render_pass) {
|
||||
continue;
|
||||
}
|
||||
if (first) {
|
||||
e->refprobe_0_index = rpi->index;
|
||||
first = false;
|
||||
} else {
|
||||
e->refprobe_1_index = rpi->index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (e->refprobe_0_index > e->refprobe_1_index) { //if both are valid, swap them to keep order as best as possible
|
||||
uint16_t tmp = e->refprobe_0_index;
|
||||
e->refprobe_0_index = e->refprobe_1_index;
|
||||
e->refprobe_1_index = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
//add directional lights
|
||||
|
||||
|
@ -1505,7 +1678,7 @@ void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas
|
|||
}
|
||||
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, p_light->light_ptr->directional_blend_splits);
|
||||
if (p_light->light_ptr->shadow) {
|
||||
if (!state.render_no_shadows && p_light->light_ptr->shadow) {
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, true);
|
||||
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
|
||||
glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
|
||||
|
@ -1517,7 +1690,7 @@ void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas
|
|||
case VS::LIGHT_OMNI: {
|
||||
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_OMNI, true);
|
||||
if (shadow_atlas && p_light->light_ptr->shadow) {
|
||||
if (!state.render_no_shadows && shadow_atlas && p_light->light_ptr->shadow) {
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, true);
|
||||
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
|
||||
glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
|
||||
|
@ -1528,7 +1701,7 @@ void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas
|
|||
case VS::LIGHT_SPOT: {
|
||||
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_SPOT, true);
|
||||
if (shadow_atlas && p_light->light_ptr->shadow) {
|
||||
if (!state.render_no_shadows && shadow_atlas && p_light->light_ptr->shadow) {
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, true);
|
||||
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
|
||||
glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
|
||||
|
@ -1562,7 +1735,7 @@ void RasterizerSceneGLES2::_setup_light(LightInstance *light, ShadowAtlas *shado
|
|||
|
||||
CameraMatrix matrices[4];
|
||||
|
||||
if (light_ptr->shadow && directional_shadow.depth) {
|
||||
if (!state.render_no_shadows && light_ptr->shadow && directional_shadow.depth) {
|
||||
|
||||
int shadow_count = 0;
|
||||
Color split_offsets;
|
||||
|
@ -1657,7 +1830,7 @@ void RasterizerSceneGLES2::_setup_light(LightInstance *light, ShadowAtlas *shado
|
|||
attenuation.a = light_ptr->param[VS::LIGHT_PARAM_ATTENUATION];
|
||||
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_ATTENUATION, attenuation);
|
||||
|
||||
if (light_ptr->shadow && shadow_atlas->shadow_owners.has(light->self)) {
|
||||
if (!state.render_no_shadows && light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(light->self)) {
|
||||
|
||||
uint32_t key = shadow_atlas->shadow_owners[light->self];
|
||||
|
||||
|
@ -1719,7 +1892,7 @@ void RasterizerSceneGLES2::_setup_light(LightInstance *light, ShadowAtlas *shado
|
|||
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPOT_ANGLE, angle);
|
||||
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_RANGE, range);
|
||||
|
||||
if (light->light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(light->self)) {
|
||||
if (!state.render_no_shadows && light->light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(light->self)) {
|
||||
uint32_t key = shadow_atlas->shadow_owners[light->self];
|
||||
|
||||
uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x03;
|
||||
|
@ -1768,13 +1941,60 @@ void RasterizerSceneGLES2::_setup_light(LightInstance *light, ShadowAtlas *shado
|
|||
}
|
||||
}
|
||||
|
||||
void RasterizerSceneGLES2::_setup_refprobes(ReflectionProbeInstance *p_refprobe1, ReflectionProbeInstance *p_refprobe2, const Transform &p_view_transform, Environment *p_env) {
|
||||
|
||||
if (p_refprobe1) {
|
||||
state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE1_USE_BOX_PROJECT, p_refprobe1->probe_ptr->box_projection);
|
||||
state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE1_BOX_EXTENTS, p_refprobe1->probe_ptr->extents);
|
||||
state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE1_BOX_OFFSET, p_refprobe1->probe_ptr->origin_offset);
|
||||
state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE1_EXTERIOR, !p_refprobe1->probe_ptr->interior);
|
||||
state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE1_INTENSITY, p_refprobe1->probe_ptr->intensity);
|
||||
|
||||
Color ambient;
|
||||
if (p_refprobe1->probe_ptr->interior) {
|
||||
ambient = p_refprobe1->probe_ptr->interior_ambient * p_refprobe1->probe_ptr->interior_ambient_energy;
|
||||
ambient.a = p_refprobe1->probe_ptr->interior_ambient_probe_contrib;
|
||||
} else if (p_env) {
|
||||
ambient = p_env->ambient_color * p_env->ambient_energy;
|
||||
ambient.a = p_env->ambient_sky_contribution;
|
||||
}
|
||||
|
||||
state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE1_AMBIENT, ambient);
|
||||
|
||||
Transform proj = (p_view_transform.inverse() * p_refprobe1->transform).affine_inverse();
|
||||
|
||||
state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE1_LOCAL_MATRIX, proj);
|
||||
}
|
||||
|
||||
if (p_refprobe2) {
|
||||
state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_USE_BOX_PROJECT, p_refprobe2->probe_ptr->box_projection);
|
||||
state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_BOX_EXTENTS, p_refprobe2->probe_ptr->extents);
|
||||
state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_BOX_OFFSET, p_refprobe2->probe_ptr->origin_offset);
|
||||
state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_EXTERIOR, !p_refprobe2->probe_ptr->interior);
|
||||
state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_INTENSITY, p_refprobe2->probe_ptr->intensity);
|
||||
|
||||
Color ambient;
|
||||
if (p_refprobe2->probe_ptr->interior) {
|
||||
ambient = p_refprobe2->probe_ptr->interior_ambient * p_refprobe2->probe_ptr->interior_ambient_energy;
|
||||
ambient.a = p_refprobe2->probe_ptr->interior_ambient_probe_contrib;
|
||||
} else if (p_env) {
|
||||
ambient = p_env->ambient_color * p_env->ambient_energy;
|
||||
ambient.a = p_env->ambient_sky_contribution;
|
||||
}
|
||||
|
||||
state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_AMBIENT, ambient);
|
||||
|
||||
Transform proj = (p_view_transform.inverse() * p_refprobe2->transform).affine_inverse();
|
||||
|
||||
state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_LOCAL_MATRIX, proj);
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, int p_element_count, const Transform &p_view_transform, const CameraMatrix &p_projection, RID p_shadow_atlas, Environment *p_env, GLuint p_base_env, float p_shadow_bias, float p_shadow_normal_bias, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow) {
|
||||
|
||||
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
|
||||
|
||||
Vector2 screen_pixel_size;
|
||||
screen_pixel_size.x = 1.0 / storage->frame.current_rt->width;
|
||||
screen_pixel_size.y = 1.0 / storage->frame.current_rt->height;
|
||||
Vector2 screen_pixel_size = state.screen_pixel_size;
|
||||
|
||||
bool use_radiance_map = false;
|
||||
if (!p_shadow && p_base_env) {
|
||||
|
@ -1797,6 +2017,8 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
|
|||
bool prev_base_pass = false;
|
||||
LightInstance *prev_light = NULL;
|
||||
bool prev_vertex_lit = false;
|
||||
ReflectionProbeInstance *prev_refprobe_1 = NULL;
|
||||
ReflectionProbeInstance *prev_refprobe_2 = NULL;
|
||||
|
||||
int prev_blend_mode = -2; //will always catch the first go
|
||||
|
||||
|
@ -1815,6 +2037,8 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
|
|||
bool accum_pass = *e->use_accum_ptr;
|
||||
*e->use_accum_ptr = true; //set to accum for next time this is found
|
||||
LightInstance *light = NULL;
|
||||
ReflectionProbeInstance *refprobe_1 = NULL;
|
||||
ReflectionProbeInstance *refprobe_2 = NULL;
|
||||
|
||||
if (!p_shadow) {
|
||||
|
||||
|
@ -1911,6 +2135,27 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
|
|||
state.scene_shader.set_conditional(SceneShaderGLES2::USE_VERTEX_LIGHTING, vertex_lit);
|
||||
prev_vertex_lit = vertex_lit;
|
||||
}
|
||||
|
||||
if (!unshaded && !accum_pass && e->refprobe_0_index != RenderList::MAX_REFLECTION_PROBES) {
|
||||
refprobe_1 = reflection_probe_instances[e->refprobe_0_index];
|
||||
}
|
||||
if (!unshaded && !accum_pass && e->refprobe_1_index != RenderList::MAX_REFLECTION_PROBES) {
|
||||
refprobe_2 = reflection_probe_instances[e->refprobe_1_index];
|
||||
}
|
||||
|
||||
if (refprobe_1 != prev_refprobe_1 || refprobe_2 != prev_refprobe_2) {
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE1, refprobe_1 != NULL);
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE2, refprobe_2 != NULL);
|
||||
if (refprobe_1 != NULL && refprobe_1 != prev_refprobe_1) {
|
||||
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, refprobe_1->cubemap);
|
||||
}
|
||||
if (refprobe_2 != NULL && refprobe_2 != prev_refprobe_2) {
|
||||
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 5);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, refprobe_2->cubemap);
|
||||
}
|
||||
rebind = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool instancing = e->instancing;
|
||||
|
@ -1975,6 +2220,10 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
|
|||
if (light) {
|
||||
_setup_light(light, shadow_atlas, p_view_transform);
|
||||
}
|
||||
|
||||
if (refprobe_1 || refprobe_2) {
|
||||
_setup_refprobes(refprobe_1, refprobe_2, p_view_transform, p_env);
|
||||
}
|
||||
}
|
||||
|
||||
state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_MATRIX, view_transform_inverse);
|
||||
|
@ -1997,6 +2246,8 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
|
|||
prev_skeleton = skeleton;
|
||||
prev_instancing = instancing;
|
||||
prev_light = light;
|
||||
prev_refprobe_1 = refprobe_1;
|
||||
prev_refprobe_2 = refprobe_2;
|
||||
}
|
||||
|
||||
_setup_light_type(NULL, NULL); //clear light stuff
|
||||
|
@ -2007,6 +2258,8 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
|
|||
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, false);
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, false);
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::USE_VERTEX_LIGHTING, false);
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE1, false);
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE2, false);
|
||||
}
|
||||
|
||||
void RasterizerSceneGLES2::_draw_sky(RasterizerStorageGLES2::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy) {
|
||||
|
@ -2101,6 +2354,36 @@ void RasterizerSceneGLES2::_draw_sky(RasterizerStorageGLES2::Sky *p_sky, const C
|
|||
|
||||
void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
|
||||
|
||||
GLuint current_fb = 0;
|
||||
Environment *env = NULL;
|
||||
|
||||
int viewport_width, viewport_height;
|
||||
|
||||
if (p_reflection_probe.is_valid()) {
|
||||
ReflectionProbeInstance *probe = reflection_probe_instance_owner.getornull(p_reflection_probe);
|
||||
ERR_FAIL_COND(!probe);
|
||||
state.render_no_shadows = !probe->probe_ptr->enable_shadows;
|
||||
|
||||
if (!probe->probe_ptr->interior) { //use env only if not interior
|
||||
env = environment_owner.getornull(p_environment);
|
||||
}
|
||||
|
||||
current_fb = probe->fbo[p_reflection_probe_pass];
|
||||
state.screen_pixel_size.x = 1.0 / probe->probe_ptr->resolution;
|
||||
state.screen_pixel_size.y = 1.0 / probe->probe_ptr->resolution;
|
||||
|
||||
viewport_width = probe->probe_ptr->resolution;
|
||||
viewport_height = probe->probe_ptr->resolution;
|
||||
|
||||
} else {
|
||||
state.render_no_shadows = false;
|
||||
current_fb = storage->frame.current_rt->fbo;
|
||||
env = environment_owner.getornull(p_environment);
|
||||
state.screen_pixel_size.x = 1.0 / storage->frame.current_rt->width;
|
||||
state.screen_pixel_size.y = 1.0 / storage->frame.current_rt->height;
|
||||
viewport_width = storage->frame.current_rt->width;
|
||||
viewport_height = storage->frame.current_rt->height;
|
||||
}
|
||||
//push back the directional lights
|
||||
|
||||
if (p_light_cull_count) {
|
||||
|
@ -2133,10 +2416,21 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
|
|||
render_light_instance_count = 0;
|
||||
}
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
if (p_reflection_probe_cull_count) {
|
||||
|
||||
GLuint current_fb = storage->frame.current_rt->fbo;
|
||||
Environment *env = environment_owner.getornull(p_environment);
|
||||
reflection_probe_instances = (ReflectionProbeInstance **)alloca(sizeof(ReflectionProbeInstance *) * p_reflection_probe_cull_count);
|
||||
|
||||
for (int i = 0; i < p_reflection_probe_cull_count; i++) {
|
||||
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_reflection_probe_cull_result[i]);
|
||||
ERR_CONTINUE(!rpi);
|
||||
rpi->last_pass = render_pass + 1; //will be incremented later
|
||||
rpi->index = i;
|
||||
reflection_probe_instances[i] = rpi;
|
||||
}
|
||||
|
||||
} else {
|
||||
reflection_probe_instances = NULL;
|
||||
}
|
||||
|
||||
// render list stuff
|
||||
|
||||
|
@ -2146,6 +2440,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
|
|||
// other stuff
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, current_fb);
|
||||
glViewport(0, 0, viewport_width, viewport_height);
|
||||
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glDepthMask(GL_TRUE);
|
||||
|
@ -2247,6 +2542,8 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
|
|||
|
||||
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;
|
||||
|
||||
LightInstance *light_instance = light_instance_owner.getornull(p_light);
|
||||
ERR_FAIL_COND(!light_instance);
|
||||
|
||||
|
|
|
@ -204,6 +204,9 @@ public:
|
|||
float dual_parbolloid_direction;
|
||||
float dual_parbolloid_zfar;
|
||||
|
||||
bool render_no_shadows;
|
||||
|
||||
Vector2 screen_pixel_size;
|
||||
} state;
|
||||
|
||||
/* SHADOW ATLAS API */
|
||||
|
@ -287,6 +290,37 @@ public:
|
|||
|
||||
/* REFLECTION PROBE INSTANCE */
|
||||
|
||||
struct ReflectionProbeInstance : public RID_Data {
|
||||
|
||||
RasterizerStorageGLES2::ReflectionProbe *probe_ptr;
|
||||
RID probe;
|
||||
RID self;
|
||||
RID atlas;
|
||||
|
||||
int reflection_atlas_index;
|
||||
|
||||
int render_step;
|
||||
int reflection_index;
|
||||
|
||||
GLuint fbo[6];
|
||||
GLuint cubemap;
|
||||
GLuint depth;
|
||||
|
||||
GLuint fbo_blur;
|
||||
|
||||
int current_resolution;
|
||||
mutable bool dirty;
|
||||
|
||||
uint64_t last_pass;
|
||||
uint32_t index;
|
||||
|
||||
Transform transform;
|
||||
};
|
||||
|
||||
mutable RID_Owner<ReflectionProbeInstance> reflection_probe_instance_owner;
|
||||
|
||||
ReflectionProbeInstance **reflection_probe_instances;
|
||||
|
||||
virtual RID reflection_probe_instance_create(RID p_probe);
|
||||
virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform);
|
||||
virtual void reflection_probe_release_atlas_index(RID p_instance);
|
||||
|
@ -424,6 +458,7 @@ public:
|
|||
|
||||
enum {
|
||||
MAX_LIGHTS = 255,
|
||||
MAX_REFLECTION_PROBES = 255,
|
||||
DEFAULT_MAX_ELEMENTS = 65536
|
||||
};
|
||||
|
||||
|
@ -587,6 +622,7 @@ public:
|
|||
_FORCE_INLINE_ void _setup_geometry(RenderList::Element *p_element, RasterizerStorageGLES2::Skeleton *p_skeleton);
|
||||
_FORCE_INLINE_ void _setup_light_type(LightInstance *p_light, ShadowAtlas *shadow_atlas);
|
||||
_FORCE_INLINE_ void _setup_light(LightInstance *p_light, ShadowAtlas *shadow_atlas, const Transform &p_view_transform);
|
||||
_FORCE_INLINE_ void _setup_refprobes(ReflectionProbeInstance *p_refprobe1, ReflectionProbeInstance *p_refprobe2, const Transform &p_view_transform, Environment *p_env);
|
||||
_FORCE_INLINE_ void _render_geometry(RenderList::Element *p_element);
|
||||
|
||||
virtual void render_scene(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
|
||||
|
|
|
@ -3307,69 +3307,194 @@ AABB RasterizerStorageGLES2::light_get_aabb(RID p_light) const {
|
|||
/* PROBE API */
|
||||
|
||||
RID RasterizerStorageGLES2::reflection_probe_create() {
|
||||
return RID();
|
||||
|
||||
ReflectionProbe *reflection_probe = memnew(ReflectionProbe);
|
||||
|
||||
reflection_probe->intensity = 1.0;
|
||||
reflection_probe->interior_ambient = Color();
|
||||
reflection_probe->interior_ambient_energy = 1.0;
|
||||
reflection_probe->max_distance = 0;
|
||||
reflection_probe->extents = Vector3(1, 1, 1);
|
||||
reflection_probe->origin_offset = Vector3(0, 0, 0);
|
||||
reflection_probe->interior = false;
|
||||
reflection_probe->box_projection = false;
|
||||
reflection_probe->enable_shadows = false;
|
||||
reflection_probe->cull_mask = (1 << 20) - 1;
|
||||
reflection_probe->update_mode = VS::REFLECTION_PROBE_UPDATE_ONCE;
|
||||
reflection_probe->resolution = 128;
|
||||
|
||||
return reflection_probe_owner.make_rid(reflection_probe);
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode) {
|
||||
|
||||
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!reflection_probe);
|
||||
|
||||
reflection_probe->update_mode = p_mode;
|
||||
reflection_probe->instance_change_notify();
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::reflection_probe_set_intensity(RID p_probe, float p_intensity) {
|
||||
|
||||
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!reflection_probe);
|
||||
|
||||
reflection_probe->intensity = p_intensity;
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient) {
|
||||
|
||||
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!reflection_probe);
|
||||
|
||||
reflection_probe->interior_ambient = p_ambient;
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) {
|
||||
|
||||
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!reflection_probe);
|
||||
|
||||
reflection_probe->interior_ambient_energy = p_energy;
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) {
|
||||
|
||||
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!reflection_probe);
|
||||
|
||||
reflection_probe->interior_ambient_probe_contrib = p_contrib;
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::reflection_probe_set_max_distance(RID p_probe, float p_distance) {
|
||||
}
|
||||
|
||||
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!reflection_probe);
|
||||
|
||||
reflection_probe->max_distance = p_distance;
|
||||
reflection_probe->instance_change_notify();
|
||||
}
|
||||
void RasterizerStorageGLES2::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {
|
||||
}
|
||||
|
||||
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!reflection_probe);
|
||||
|
||||
reflection_probe->extents = p_extents;
|
||||
reflection_probe->instance_change_notify();
|
||||
}
|
||||
void RasterizerStorageGLES2::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {
|
||||
|
||||
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!reflection_probe);
|
||||
|
||||
reflection_probe->origin_offset = p_offset;
|
||||
reflection_probe->instance_change_notify();
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::reflection_probe_set_as_interior(RID p_probe, bool p_enable) {
|
||||
}
|
||||
|
||||
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!reflection_probe);
|
||||
|
||||
reflection_probe->interior = p_enable;
|
||||
}
|
||||
void RasterizerStorageGLES2::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
|
||||
|
||||
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!reflection_probe);
|
||||
|
||||
reflection_probe->box_projection = p_enable;
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) {
|
||||
|
||||
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!reflection_probe);
|
||||
|
||||
reflection_probe->enable_shadows = p_enable;
|
||||
reflection_probe->instance_change_notify();
|
||||
}
|
||||
void RasterizerStorageGLES2::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {
|
||||
|
||||
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!reflection_probe);
|
||||
|
||||
reflection_probe->cull_mask = p_layers;
|
||||
reflection_probe->instance_change_notify();
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {
|
||||
void RasterizerStorageGLES2::reflection_probe_set_resolution(RID p_probe, int p_resolution) {
|
||||
|
||||
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!reflection_probe);
|
||||
|
||||
reflection_probe->resolution = p_resolution;
|
||||
}
|
||||
|
||||
AABB RasterizerStorageGLES2::reflection_probe_get_aabb(RID p_probe) const {
|
||||
return AABB();
|
||||
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!reflection_probe, AABB());
|
||||
|
||||
AABB aabb;
|
||||
aabb.position = -reflection_probe->extents;
|
||||
aabb.size = reflection_probe->extents * 2.0;
|
||||
|
||||
return aabb;
|
||||
}
|
||||
VS::ReflectionProbeUpdateMode RasterizerStorageGLES2::reflection_probe_get_update_mode(RID p_probe) const {
|
||||
return VS::REFLECTION_PROBE_UPDATE_ALWAYS;
|
||||
|
||||
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!reflection_probe, VS::REFLECTION_PROBE_UPDATE_ALWAYS);
|
||||
|
||||
return reflection_probe->update_mode;
|
||||
}
|
||||
|
||||
uint32_t RasterizerStorageGLES2::reflection_probe_get_cull_mask(RID p_probe) const {
|
||||
return 0;
|
||||
|
||||
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!reflection_probe, 0);
|
||||
|
||||
return reflection_probe->cull_mask;
|
||||
}
|
||||
|
||||
Vector3 RasterizerStorageGLES2::reflection_probe_get_extents(RID p_probe) const {
|
||||
return Vector3();
|
||||
|
||||
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!reflection_probe, Vector3());
|
||||
|
||||
return reflection_probe->extents;
|
||||
}
|
||||
Vector3 RasterizerStorageGLES2::reflection_probe_get_origin_offset(RID p_probe) const {
|
||||
return Vector3();
|
||||
|
||||
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!reflection_probe, Vector3());
|
||||
|
||||
return reflection_probe->origin_offset;
|
||||
}
|
||||
|
||||
bool RasterizerStorageGLES2::reflection_probe_renders_shadows(RID p_probe) const {
|
||||
return false;
|
||||
|
||||
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!reflection_probe, false);
|
||||
|
||||
return reflection_probe->enable_shadows;
|
||||
}
|
||||
|
||||
float RasterizerStorageGLES2::reflection_probe_get_origin_max_distance(RID p_probe) const {
|
||||
return 0;
|
||||
|
||||
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!reflection_probe, 0);
|
||||
|
||||
return reflection_probe->max_distance;
|
||||
}
|
||||
|
||||
int RasterizerStorageGLES2::reflection_probe_get_resolution(RID p_probe) const {
|
||||
|
||||
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!reflection_probe, 0);
|
||||
|
||||
return reflection_probe->resolution;
|
||||
}
|
||||
|
||||
RID RasterizerStorageGLES2::gi_probe_create() {
|
||||
|
@ -3601,15 +3726,115 @@ void RasterizerStorageGLES2::update_particles() {
|
|||
////////
|
||||
|
||||
void RasterizerStorageGLES2::instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) {
|
||||
|
||||
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
|
||||
ERR_FAIL_COND(!skeleton);
|
||||
|
||||
skeleton->instances.insert(p_instance);
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::instance_remove_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) {
|
||||
|
||||
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
|
||||
ERR_FAIL_COND(!skeleton);
|
||||
|
||||
skeleton->instances.erase(p_instance);
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::instance_add_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) {
|
||||
|
||||
Instanciable *inst = NULL;
|
||||
switch (p_instance->base_type) {
|
||||
case VS::INSTANCE_MESH: {
|
||||
inst = mesh_owner.getornull(p_base);
|
||||
ERR_FAIL_COND(!inst);
|
||||
} break;
|
||||
case VS::INSTANCE_MULTIMESH: {
|
||||
inst = multimesh_owner.getornull(p_base);
|
||||
ERR_FAIL_COND(!inst);
|
||||
} break;
|
||||
case VS::INSTANCE_IMMEDIATE: {
|
||||
inst = immediate_owner.getornull(p_base);
|
||||
ERR_FAIL_COND(!inst);
|
||||
} break;
|
||||
/*case VS::INSTANCE_PARTICLES: {
|
||||
inst = particles_owner.getornull(p_base);
|
||||
ERR_FAIL_COND(!inst);
|
||||
} break;*/
|
||||
case VS::INSTANCE_REFLECTION_PROBE: {
|
||||
inst = reflection_probe_owner.getornull(p_base);
|
||||
ERR_FAIL_COND(!inst);
|
||||
} break;
|
||||
case VS::INSTANCE_LIGHT: {
|
||||
inst = light_owner.getornull(p_base);
|
||||
ERR_FAIL_COND(!inst);
|
||||
} break;
|
||||
/*case VS::INSTANCE_GI_PROBE: {
|
||||
inst = gi_probe_owner.getornull(p_base);
|
||||
ERR_FAIL_COND(!inst);
|
||||
} break;*/
|
||||
/*case VS::INSTANCE_LIGHTMAP_CAPTURE: {
|
||||
inst = lightmap_capture_data_owner.getornull(p_base);
|
||||
ERR_FAIL_COND(!inst);
|
||||
} break;*/
|
||||
default: {
|
||||
if (!inst) {
|
||||
ERR_FAIL();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inst->instance_list.add(&p_instance->dependency_item);
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::instance_remove_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) {
|
||||
|
||||
Instanciable *inst = NULL;
|
||||
|
||||
switch (p_instance->base_type) {
|
||||
case VS::INSTANCE_MESH: {
|
||||
inst = mesh_owner.getornull(p_base);
|
||||
ERR_FAIL_COND(!inst);
|
||||
} break;
|
||||
case VS::INSTANCE_MULTIMESH: {
|
||||
inst = multimesh_owner.getornull(p_base);
|
||||
ERR_FAIL_COND(!inst);
|
||||
} break;
|
||||
case VS::INSTANCE_IMMEDIATE: {
|
||||
inst = immediate_owner.getornull(p_base);
|
||||
ERR_FAIL_COND(!inst);
|
||||
} break;
|
||||
/*case VS::INSTANCE_PARTICLES: {
|
||||
inst = particles_owner.getornull(p_base);
|
||||
ERR_FAIL_COND(!inst);
|
||||
} break;*/
|
||||
case VS::INSTANCE_REFLECTION_PROBE: {
|
||||
inst = reflection_probe_owner.getornull(p_base);
|
||||
ERR_FAIL_COND(!inst);
|
||||
} break;
|
||||
case VS::INSTANCE_LIGHT: {
|
||||
inst = light_owner.getornull(p_base);
|
||||
ERR_FAIL_COND(!inst);
|
||||
} break;
|
||||
/*case VS::INSTANCE_GI_PROBE: {
|
||||
inst = gi_probe_owner.getornull(p_base);
|
||||
ERR_FAIL_COND(!inst);
|
||||
} break;
|
||||
case VS::INSTANCE_LIGHTMAP_CAPTURE: {
|
||||
inst = lightmap_capture_data_owner.getornull(p_base);
|
||||
ERR_FAIL_COND(!inst);
|
||||
} break;*/
|
||||
default: {
|
||||
|
||||
if (!inst) {
|
||||
ERR_FAIL();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ERR_FAIL_COND(!inst);
|
||||
|
||||
inst->instance_list.remove(&p_instance->dependency_item);
|
||||
}
|
||||
|
||||
/* RENDER TARGET */
|
||||
|
@ -3867,6 +4092,8 @@ VS::InstanceType RasterizerStorageGLES2::get_base_type(RID p_rid) const {
|
|||
return VS::INSTANCE_MULTIMESH;
|
||||
} else if (immediate_owner.owns(p_rid)) {
|
||||
return VS::INSTANCE_IMMEDIATE;
|
||||
} else if (reflection_probe_owner.owns(p_rid)) {
|
||||
return VS::INSTANCE_REFLECTION_PROBE;
|
||||
} else {
|
||||
return VS::INSTANCE_NONE;
|
||||
}
|
||||
|
@ -4044,6 +4271,17 @@ bool RasterizerStorageGLES2::free(RID p_rid) {
|
|||
memdelete(light);
|
||||
|
||||
return true;
|
||||
} else if (reflection_probe_owner.owns(p_rid)) {
|
||||
|
||||
// delete the texture
|
||||
ReflectionProbe *reflection_probe = reflection_probe_owner.get(p_rid);
|
||||
reflection_probe->instance_remove_deps();
|
||||
|
||||
reflection_probe_owner.free(p_rid);
|
||||
memdelete(reflection_probe);
|
||||
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -4095,6 +4333,7 @@ void RasterizerStorageGLES2::initialize() {
|
|||
}
|
||||
|
||||
config.shrink_textures_x2 = false;
|
||||
|
||||
config.float_texture_supported = config.extensions.has("GL_ARB_texture_float") || config.extensions.has("GL_OES_texture_float");
|
||||
config.s3tc_supported = config.extensions.has("GL_EXT_texture_compression_s3tc");
|
||||
config.etc1_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture");
|
||||
|
|
|
@ -955,6 +955,26 @@ public:
|
|||
virtual uint64_t light_get_version(RID p_light) const;
|
||||
|
||||
/* PROBE API */
|
||||
|
||||
struct ReflectionProbe : Instanciable {
|
||||
|
||||
VS::ReflectionProbeUpdateMode update_mode;
|
||||
float intensity;
|
||||
Color interior_ambient;
|
||||
float interior_ambient_energy;
|
||||
float interior_ambient_probe_contrib;
|
||||
float max_distance;
|
||||
Vector3 extents;
|
||||
Vector3 origin_offset;
|
||||
bool interior;
|
||||
bool box_projection;
|
||||
bool enable_shadows;
|
||||
uint32_t cull_mask;
|
||||
int resolution;
|
||||
};
|
||||
|
||||
mutable RID_Owner<ReflectionProbe> reflection_probe_owner;
|
||||
|
||||
virtual RID reflection_probe_create();
|
||||
|
||||
virtual void reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode);
|
||||
|
@ -969,11 +989,14 @@ public:
|
|||
virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable);
|
||||
virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable);
|
||||
virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers);
|
||||
virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution);
|
||||
|
||||
virtual AABB reflection_probe_get_aabb(RID p_probe) const;
|
||||
virtual VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const;
|
||||
virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const;
|
||||
|
||||
virtual int reflection_probe_get_resolution(RID p_probe) const;
|
||||
|
||||
virtual Vector3 reflection_probe_get_extents(RID p_probe) const;
|
||||
virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const;
|
||||
virtual float reflection_probe_get_origin_max_distance(RID p_probe) const;
|
||||
|
|
|
@ -176,7 +176,6 @@ void main() {
|
|||
#ifdef USE_SOURCE_PANORAMA
|
||||
sum.rgb += texturePanorama(source_panorama, L).rgb * NdotL;
|
||||
#else
|
||||
L.y = -L.y;
|
||||
sum.rgb += textureCubeLod(source_cube, L, 0.0).rgb * NdotL;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -262,6 +262,35 @@ void light_compute(
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef USE_VERTEX_LIGHTING
|
||||
|
||||
#ifdef USE_REFLECTION_PROBE1
|
||||
|
||||
uniform mat4 refprobe1_local_matrix;
|
||||
varying mediump vec4 refprobe1_reflection_normal_blend;
|
||||
uniform vec3 refprobe1_box_extents;
|
||||
|
||||
#ifndef USE_LIGHTMAP
|
||||
varying mediump vec3 refprobe1_ambient_normal;
|
||||
#endif
|
||||
|
||||
#endif //reflection probe1
|
||||
|
||||
#ifdef USE_REFLECTION_PROBE2
|
||||
|
||||
uniform mat4 refprobe2_local_matrix;
|
||||
varying mediump vec4 refprobe2_reflection_normal_blend;
|
||||
uniform vec3 refprobe2_box_extents;
|
||||
|
||||
#ifndef USE_LIGHTMAP
|
||||
varying mediump vec3 refprobe2_ambient_normal;
|
||||
#endif
|
||||
|
||||
#endif //reflection probe2
|
||||
|
||||
#endif //vertex lighting for refprobes
|
||||
|
||||
|
||||
void main() {
|
||||
|
||||
highp vec4 vertex = vertex_attrib;
|
||||
|
@ -498,6 +527,52 @@ VERTEX_SHADER_CODE
|
|||
|
||||
#endif //use shadow and use lighting
|
||||
|
||||
#ifdef USE_VERTEX_LIGHTING
|
||||
|
||||
#ifdef USE_REFLECTION_PROBE1
|
||||
{
|
||||
vec3 ref_normal = normalize(reflect(vertex_interp, normal_interp));
|
||||
vec3 local_pos = (refprobe1_local_matrix * vec4(vertex_interp, 1.0)).xyz;
|
||||
vec3 inner_pos = abs(local_pos / refprobe1_box_extents);
|
||||
float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z));
|
||||
|
||||
{
|
||||
vec3 local_ref_vec = (refprobe1_local_matrix * vec4(ref_normal, 0.0)).xyz;
|
||||
refprobe1_reflection_normal_blend.xyz = local_ref_vec;
|
||||
refprobe1_reflection_normal_blend.a = blend;
|
||||
|
||||
}
|
||||
#ifndef USE_LIGHTMAP
|
||||
|
||||
refprobe1_ambient_normal = (refprobe1_local_matrix * vec4(normal_interp, 0.0)).xyz;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif //USE_REFLECTION_PROBE1
|
||||
|
||||
|
||||
#ifdef USE_REFLECTION_PROBE2
|
||||
{
|
||||
vec3 ref_normal = normalize(reflect(vertex_interp, normal_interp));
|
||||
vec3 local_pos = (refprobe2_local_matrix * vec4(vertex_interp, 1.0)).xyz;
|
||||
vec3 inner_pos = abs(local_pos / refprobe2_box_extents);
|
||||
float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z));
|
||||
|
||||
{
|
||||
vec3 local_ref_vec = (refprobe2_local_matrix * vec4(ref_normal, 0.0)).xyz;
|
||||
refprobe2_reflection_normal_blend.xyz = local_ref_vec;
|
||||
refprobe2_reflection_normal_blend.a = blend;
|
||||
|
||||
}
|
||||
#ifndef USE_LIGHTMAP
|
||||
|
||||
refprobe2_ambient_normal = (refprobe2_local_matrix * vec4(normal_interp, 0.0)).xyz;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif //USE_REFLECTION_PROBE2
|
||||
|
||||
#endif //use vertex lighting
|
||||
gl_Position = projection_matrix * vec4(vertex_interp, 1.0);
|
||||
}
|
||||
|
||||
|
@ -548,10 +623,161 @@ uniform vec2 screen_pixel_size;
|
|||
uniform highp sampler2D screen_texture; //texunit:-4
|
||||
#endif
|
||||
|
||||
#ifdef USE_RADIANCE_MAP
|
||||
#ifdef USE_REFLECTION_PROBE1
|
||||
|
||||
#ifdef USE_VERTEX_LIGHTING
|
||||
|
||||
varying mediump vec4 refprobe1_reflection_normal_blend;
|
||||
#ifndef USE_LIGHTMAP
|
||||
varying mediump vec3 refprobe1_ambient_normal;
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
uniform bool refprobe1_use_box_project;
|
||||
uniform vec3 refprobe1_box_extents;
|
||||
uniform vec3 refprobe1_box_offset;
|
||||
uniform mat4 refprobe1_local_matrix;
|
||||
|
||||
#endif //use vertex lighting
|
||||
|
||||
uniform bool refprobe1_exterior;
|
||||
|
||||
uniform highp samplerCube reflection_probe1; //texunit:-4
|
||||
|
||||
uniform float refprobe1_intensity;
|
||||
uniform vec4 refprobe1_ambient;
|
||||
|
||||
#endif //USE_REFLECTION_PROBE1
|
||||
|
||||
#ifdef USE_REFLECTION_PROBE2
|
||||
|
||||
#ifdef USE_VERTEX_LIGHTING
|
||||
|
||||
varying mediump vec4 refprobe2_reflection_normal_blend;
|
||||
#ifndef USE_LIGHTMAP
|
||||
varying mediump vec3 refprobe2_ambient_normal;
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
uniform bool refprobe2_use_box_project;
|
||||
uniform vec3 refprobe2_box_extents;
|
||||
uniform vec3 refprobe2_box_offset;
|
||||
uniform mat4 refprobe2_local_matrix;
|
||||
|
||||
#endif //use vertex lighting
|
||||
|
||||
uniform bool refprobe2_exterior;
|
||||
|
||||
uniform highp samplerCube reflection_probe2; //texunit:-5
|
||||
|
||||
uniform float refprobe2_intensity;
|
||||
uniform vec4 refprobe2_ambient;
|
||||
|
||||
#endif //USE_REFLECTION_PROBE2
|
||||
|
||||
#define RADIANCE_MAX_LOD 6.0
|
||||
|
||||
#if defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2)
|
||||
|
||||
void reflection_process(samplerCube reflection_map,
|
||||
#ifdef USE_VERTEX_LIGHTING
|
||||
vec3 ref_normal,
|
||||
#ifndef USE_LIGHTMAP
|
||||
vec3 amb_normal,
|
||||
#endif
|
||||
float ref_blend,
|
||||
|
||||
#else //no vertex lighting
|
||||
vec3 normal, vec3 vertex,
|
||||
mat4 local_matrix,
|
||||
bool use_box_project, vec3 box_extents, vec3 box_offset,
|
||||
#endif //vertex lighting
|
||||
bool exterior,float intensity, vec4 ref_ambient, float roughness, vec3 ambient, vec3 skybox, inout highp vec4 reflection_accum, inout highp vec4 ambient_accum) {
|
||||
|
||||
vec4 reflection;
|
||||
|
||||
#ifdef USE_VERTEX_LIGHTING
|
||||
|
||||
reflection.rgb = textureCubeLod(reflection_map, ref_normal, roughness * RADIANCE_MAX_LOD).rgb;
|
||||
|
||||
float blend = ref_blend; //crappier blend formula for vertex
|
||||
blend *= blend;
|
||||
blend = max(0.0, 1.0 - blend);
|
||||
|
||||
#else //fragment lighting
|
||||
|
||||
vec3 local_pos = (local_matrix * vec4(vertex, 1.0)).xyz;
|
||||
|
||||
if (any(greaterThan(abs(local_pos), box_extents))) { //out of the reflection box
|
||||
return;
|
||||
}
|
||||
|
||||
vec3 inner_pos = abs(local_pos / box_extents);
|
||||
float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z));
|
||||
blend = mix(length(inner_pos), blend, blend);
|
||||
blend *= blend;
|
||||
blend = max(0.0, 1.0 - blend);
|
||||
|
||||
//reflect and make local
|
||||
vec3 ref_normal = normalize(reflect(vertex, normal));
|
||||
ref_normal = (local_matrix * vec4(ref_normal, 0.0)).xyz;
|
||||
|
||||
if (use_box_project) { //box project
|
||||
|
||||
vec3 nrdir = normalize(ref_normal);
|
||||
vec3 rbmax = (box_extents - local_pos) / nrdir;
|
||||
vec3 rbmin = (-box_extents - local_pos) / nrdir;
|
||||
|
||||
vec3 rbminmax = mix(rbmin, rbmax, vec3(greaterThan(nrdir, vec3(0.0, 0.0, 0.0))));
|
||||
|
||||
float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z);
|
||||
vec3 posonbox = local_pos + nrdir * fa;
|
||||
ref_normal = posonbox - box_offset.xyz;
|
||||
}
|
||||
|
||||
reflection.rgb = textureCubeLod(reflection_map, ref_normal, roughness * RADIANCE_MAX_LOD).rgb;
|
||||
#endif
|
||||
|
||||
if (exterior) {
|
||||
reflection.rgb = mix(skybox, reflection.rgb, blend);
|
||||
}
|
||||
reflection.rgb *= intensity;
|
||||
reflection.a = blend;
|
||||
reflection.rgb *= blend;
|
||||
|
||||
reflection_accum += reflection;
|
||||
|
||||
|
||||
#ifndef USE_LIGHTMAP
|
||||
|
||||
vec4 ambient_out;
|
||||
#ifndef USE_VERTEX_LIGHTING
|
||||
|
||||
vec3 amb_normal = (local_matrix * vec4(normal, 0.0)).xyz;
|
||||
#endif
|
||||
|
||||
ambient_out.rgb = textureCubeLod(reflection_map, amb_normal, RADIANCE_MAX_LOD).rgb;
|
||||
ambient_out.a = blend;
|
||||
ambient_out.rgb = mix(ref_ambient.rgb, ambient_out.rgb, ref_ambient.a);
|
||||
if (exterior) {
|
||||
ambient_out.rgb = mix(ambient, ambient_out.rgb, blend);
|
||||
}
|
||||
|
||||
ambient_out.rgb *= blend;
|
||||
ambient_accum += ambient_out;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif //use refprobe 1 or 2
|
||||
|
||||
|
||||
|
||||
#ifdef USE_RADIANCE_MAP
|
||||
|
||||
|
||||
uniform samplerCube radiance_map; // texunit:-2
|
||||
|
||||
uniform mat4 radiance_inverse_xform;
|
||||
|
@ -660,6 +886,8 @@ vec3 metallic_to_specular_color(float metallic, float specular, vec3 albedo) {
|
|||
return mix(vec3(dielectric), albedo, metallic); // TODO: reference?
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
FRAGMENT_SHADER_GLOBALS
|
||||
|
@ -1123,6 +1351,59 @@ FRAGMENT_SHADER_CODE
|
|||
|
||||
ambient_light *= ambient_energy;
|
||||
|
||||
|
||||
|
||||
#ifdef USE_REFLECTION_PROBE1
|
||||
|
||||
vec4 ambient_accum = vec4(0.0);
|
||||
vec4 reflection_accum = vec4(0.0);
|
||||
|
||||
|
||||
reflection_process(reflection_probe1,
|
||||
#ifdef USE_VERTEX_LIGHTING
|
||||
refprobe1_reflection_normal_blend.rgb,
|
||||
#ifndef USE_LIGHTMAP
|
||||
refprobe1_ambient_normal,
|
||||
#endif
|
||||
refprobe1_reflection_normal_blend.a,
|
||||
#else
|
||||
normal_interp,vertex_interp,refprobe1_local_matrix,
|
||||
refprobe1_use_box_project,refprobe1_box_extents,refprobe1_box_offset,
|
||||
#endif
|
||||
refprobe1_exterior,refprobe1_intensity, refprobe1_ambient, roughness,
|
||||
ambient_light, specular_light, reflection_accum, ambient_accum);
|
||||
|
||||
|
||||
#ifdef USE_REFLECTION_PROBE2
|
||||
|
||||
reflection_process(reflection_probe2,
|
||||
#ifdef USE_VERTEX_LIGHTING
|
||||
refprobe2_reflection_normal_blend.rgb,
|
||||
#ifndef USE_LIGHTMAP
|
||||
refprobe2_ambient_normal,
|
||||
#endif
|
||||
refprobe2_reflection_normal_blend.a,
|
||||
#else
|
||||
normal_interp,vertex_interp,refprobe2_local_matrix,
|
||||
refprobe2_use_box_project,refprobe2_box_extents,refprobe2_box_offset,
|
||||
#endif
|
||||
refprobe2_exterior,refprobe2_intensity, refprobe2_ambient, roughness,
|
||||
ambient_light, specular_light, reflection_accum, ambient_accum);
|
||||
|
||||
#endif // USE_REFLECTION_PROBE2
|
||||
|
||||
if (reflection_accum.a > 0.0) {
|
||||
specular_light = reflection_accum.rgb / reflection_accum.a;
|
||||
}
|
||||
|
||||
#ifndef USE_LIGHTMAP
|
||||
if (ambient_accum.a > 0.0) {
|
||||
ambient_light = ambient_accum.rgb / ambient_accum.a;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //use reflection probe 1
|
||||
|
||||
#endif //BASE PASS
|
||||
|
||||
//
|
||||
|
|
|
@ -5295,6 +5295,9 @@ void RasterizerStorageGLES3::reflection_probe_set_cull_mask(RID p_probe, uint32_
|
|||
reflection_probe->instance_change_notify();
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES3::reflection_probe_set_resolution(RID p_probe, int p_resolution) {
|
||||
}
|
||||
|
||||
AABB RasterizerStorageGLES3::reflection_probe_get_aabb(RID p_probe) const {
|
||||
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!reflection_probe, AABB());
|
||||
|
|
|
@ -1005,6 +1005,7 @@ public:
|
|||
virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable);
|
||||
virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable);
|
||||
virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers);
|
||||
virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution);
|
||||
|
||||
virtual AABB reflection_probe_get_aabb(RID p_probe) const;
|
||||
virtual VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const;
|
||||
|
|
|
@ -4523,6 +4523,16 @@ void EditorNode::_bottom_panel_raise_toggled(bool p_pressed) {
|
|||
}
|
||||
}
|
||||
|
||||
void EditorNode::_update_video_driver_color() {
|
||||
|
||||
//todo probably should de-harcode this and add to editor settings
|
||||
if (video_driver->get_text() == "GLES2") {
|
||||
video_driver->add_color_override("font_color", Color::hex(0x5586a4ff));
|
||||
} else if (video_driver->get_text() == "GLES3") {
|
||||
video_driver->add_color_override("font_color", Color::hex(0xa5557dff));
|
||||
}
|
||||
}
|
||||
|
||||
void EditorNode::_video_driver_selected(int p_which) {
|
||||
|
||||
String driver = video_driver->get_item_metadata(p_which);
|
||||
|
@ -4536,6 +4546,7 @@ void EditorNode::_video_driver_selected(int p_which) {
|
|||
video_driver_request = driver;
|
||||
video_restart_dialog->popup_centered_minsize();
|
||||
video_driver->select(video_driver_current);
|
||||
_update_video_driver_color();
|
||||
}
|
||||
|
||||
void EditorNode::_bind_methods() {
|
||||
|
@ -5398,6 +5409,7 @@ EditorNode::EditorNode() {
|
|||
video_driver->set_focus_mode(Control::FOCUS_NONE);
|
||||
video_driver->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
|
||||
video_driver->connect("item_selected", this, "_video_driver_selected");
|
||||
video_driver->add_font_override("font", gui_base->get_font("bold", "EditorFonts"));
|
||||
menu_hb->add_child(video_driver);
|
||||
|
||||
String video_drivers = ProjectSettings::get_singleton()->get_custom_property_info()["rendering/quality/driver/driver_name"].hint_string;
|
||||
|
@ -5414,6 +5426,8 @@ EditorNode::EditorNode() {
|
|||
}
|
||||
}
|
||||
|
||||
_update_video_driver_color();
|
||||
|
||||
video_restart_dialog = memnew(ConfirmationDialog);
|
||||
video_restart_dialog->set_text(TTR("Changing the video driver requires restarting the editor."));
|
||||
video_restart_dialog->get_ok()->set_text(TTR("Save & Restart"));
|
||||
|
|
|
@ -208,6 +208,7 @@ private:
|
|||
int video_driver_current;
|
||||
String video_driver_request;
|
||||
void _video_driver_selected(int);
|
||||
void _update_video_driver_color();
|
||||
|
||||
// Split containers
|
||||
|
||||
|
|
|
@ -397,6 +397,7 @@ public:
|
|||
virtual RID reflection_probe_create() = 0;
|
||||
|
||||
virtual void reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode) = 0;
|
||||
virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0;
|
||||
virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) = 0;
|
||||
virtual void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient) = 0;
|
||||
virtual void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) = 0;
|
||||
|
|
|
@ -337,6 +337,7 @@ public:
|
|||
BIND2(reflection_probe_set_enable_box_projection, RID, bool)
|
||||
BIND2(reflection_probe_set_enable_shadows, RID, bool)
|
||||
BIND2(reflection_probe_set_cull_mask, RID, uint32_t)
|
||||
BIND2(reflection_probe_set_resolution, RID, int)
|
||||
|
||||
/* BAKED LIGHT API */
|
||||
|
||||
|
|
|
@ -2141,6 +2141,8 @@ bool VisualServerScene::_render_reflection_probe_step(Instance *p_instance, int
|
|||
Scenario *scenario = p_instance->scenario;
|
||||
ERR_FAIL_COND_V(!scenario, true);
|
||||
|
||||
VisualServerRaster::redraw_request(); //update, so it updates in editor
|
||||
|
||||
if (p_step == 0) {
|
||||
|
||||
if (!VSG::scene_render->reflection_probe_instance_begin_render(reflection_probe->instance, scenario->reflection_atlas)) {
|
||||
|
|
|
@ -271,6 +271,7 @@ public:
|
|||
FUNC2(reflection_probe_set_enable_box_projection, RID, bool)
|
||||
FUNC2(reflection_probe_set_enable_shadows, RID, bool)
|
||||
FUNC2(reflection_probe_set_cull_mask, RID, uint32_t)
|
||||
FUNC2(reflection_probe_set_resolution, RID, int)
|
||||
|
||||
/* BAKED LIGHT API */
|
||||
|
||||
|
|
|
@ -490,6 +490,7 @@ public:
|
|||
virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) = 0;
|
||||
virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) = 0;
|
||||
virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0;
|
||||
virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0;
|
||||
|
||||
/* GI PROBE API */
|
||||
|
||||
|
|
Loading…
Reference in New Issue