summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorJuan Linietsky <juan@godotengine.org>2019-02-25 21:46:24 -0300
committerJuan Linietsky <juan@godotengine.org>2019-02-25 21:47:29 -0300
commita32b26dfa26f2a039bf9c84b90d10666bcf785c9 (patch)
tree71ba0cf141b34b242edbe39f266ef36d6054a761 /drivers
parent51c1d55cf9089cefbde034893b4784a5d554ddcc (diff)
Several fixes to make GLES2 on HTML5 work much better.
Changed math class error reporting to be a bit less paranoid.
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gles2/rasterizer_canvas_gles2.cpp1
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.cpp132
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.h7
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.cpp98
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.h4
-rw-r--r--drivers/gles2/shaders/cubemap_filter.glsl13
-rw-r--r--drivers/gles2/shaders/scene.glsl46
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp1
8 files changed, 237 insertions, 65 deletions
diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp
index 320242b773..e922320e08 100644
--- a/drivers/gles2/rasterizer_canvas_gles2.cpp
+++ b/drivers/gles2/rasterizer_canvas_gles2.cpp
@@ -2019,6 +2019,7 @@ void RasterizerCanvasGLES2::initialize() {
state.canvas_shader.init();
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, true);
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_RGBA_SHADOWS, storage->config.use_rgba_2d_shadows);
state.canvas_shader.bind();
diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp
index a7becdde24..de77c2c63e 100644
--- a/drivers/gles2/rasterizer_scene_gles2.cpp
+++ b/drivers/gles2/rasterizer_scene_gles2.cpp
@@ -62,6 +62,7 @@ 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;
@@ -86,9 +87,13 @@ void RasterizerSceneGLES2::shadow_atlas_set_size(RID p_atlas, int p_size) {
if (shadow_atlas->fbo) {
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;
}
// erase shadow atlast references from lights
@@ -119,6 +124,16 @@ void RasterizerSceneGLES2::shadow_atlas_set_size(RID p_atlas, int p_size) {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadow_atlas->depth, 0);
+ if (storage->config.use_rgba_3d_shadows) {
+ 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, NULL);
+ 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);
+ }
glViewport(0, 0, shadow_atlas->size, shadow_atlas->size);
glDepthMask(GL_TRUE);
@@ -459,10 +474,10 @@ RID RasterizerSceneGLES2::reflection_probe_instance_create(RID p_probe) {
for (int i = 0; i < 6; i++) {
glGenFramebuffers(1, &rpi->fbo[i]);
+ glGenTextures(1, &rpi->color[i]);
}
- glGenFramebuffers(1, &rpi->fbo_blur);
- glGenRenderbuffers(1, &rpi->depth);
+ glGenTextures(1, &rpi->depth);
rpi->cubemap = 0;
//glGenTextures(1, &rpi->cubemap);
@@ -510,9 +525,14 @@ bool RasterizerSceneGLES2::reflection_probe_instance_begin_render(RID p_instance
GLenum type = GL_UNSIGNED_BYTE;
glActiveTexture(GL_TEXTURE0);
+
+ glBindTexture(GL_TEXTURE_2D, rpi->depth);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size, size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+
if (rpi->cubemap != 0) {
glDeleteTextures(1, &rpi->cubemap);
}
+
glGenTextures(1, &rpi->cubemap);
glBindTexture(GL_TEXTURE_CUBE_MAP, rpi->cubemap);
#if 1
@@ -523,17 +543,15 @@ bool RasterizerSceneGLES2::reflection_probe_instance_begin_render(RID p_instance
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
- glBindRenderbuffer(GL_RENDERBUFFER, rpi->depth); //resize depth buffer
-#ifdef JAVASCRIPT_ENABLED
- glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, size, size);
-#else
- glRenderbufferStorage(GL_RENDERBUFFER, _DEPTH_COMPONENT24_OES, size, size);
-#endif
-
+ //Generate framebuffers for rendering
for (int i = 0; i < 6; i++) {
glBindFramebuffer(GL_FRAMEBUFFER, rpi->fbo[i]);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _cube_side_enum[i], rpi->cubemap, 0);
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rpi->depth);
+ glBindTexture(GL_TEXTURE_2D, rpi->color[i]);
+ glTexImage2D(GL_TEXTURE_2D, 0, internal_format, size, size, 0, format, type, NULL);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rpi->color[i], 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rpi->depth, 0);
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE);
}
#else
@@ -570,6 +588,8 @@ bool RasterizerSceneGLES2::reflection_probe_instance_begin_render(RID p_instance
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);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo);
}
return true;
@@ -579,6 +599,7 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
ERR_FAIL_COND_V(!rpi, false);
+ ERR_FAIL_COND_V(rpi->current_resolution == 0, false);
int size = rpi->probe_ptr->resolution;
@@ -596,16 +617,23 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst
}
}
+ 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
+
+ //first of all, copy rendered textures to cubemap
+ for (int i = 0; i < 6; i++) {
+ glBindFramebuffer(GL_FRAMEBUFFER, rpi->fbo[i]);
+ glViewport(0, 0, size, size);
+ glCopyTexImage2D(_cube_side_enum[i], 0, GL_RGB, 0, 0, size, size, 0);
+ }
+ //do filtering
//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;
@@ -613,13 +641,20 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst
storage->shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_SOURCE_PANORAMA, false);
storage->shaders.cubemap_filter.bind();
+ glBindFramebuffer(GL_FRAMEBUFFER, storage->resources.mipmap_blur_fbo);
+
//blur
while (size >= 1) {
+ glActiveTexture(GL_TEXTURE3);
+ glBindTexture(GL_TEXTURE_2D, storage->resources.mipmap_blur_color);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, storage->resources.mipmap_blur_color, 0);
+ glViewport(0, 0, size, size);
+ glActiveTexture(GL_TEXTURE0);
+
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);
@@ -627,6 +662,7 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst
storage->shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::Z_FLIP, false);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ glCopyTexImage2D(_cube_side_enum[i], lod, GL_RGB, 0, 0, size, size, 0);
}
size >>= 1;
@@ -635,9 +671,14 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst
}
// restore ranges
-
+ glActiveTexture(GL_TEXTURE0);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glActiveTexture(GL_TEXTURE3); //back to panorama
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo);
return true;
}
@@ -1751,7 +1792,11 @@ void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas
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);
+ if (storage->config.use_rgba_3d_shadows) {
+ glBindTexture(GL_TEXTURE_2D, directional_shadow.color);
+ } else {
+ glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
+ }
state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_5, shadow_filter_mode == SHADOW_FILTER_PCF5);
state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_13, shadow_filter_mode == SHADOW_FILTER_PCF13);
}
@@ -1763,7 +1808,11 @@ void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas
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);
+ if (storage->config.use_rgba_3d_shadows) {
+ glBindTexture(GL_TEXTURE_2D, shadow_atlas->color);
+ } else {
+ glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
+ }
state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_5, shadow_filter_mode == SHADOW_FILTER_PCF5);
state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_13, shadow_filter_mode == SHADOW_FILTER_PCF13);
}
@@ -1774,7 +1823,11 @@ void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas
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);
+ if (storage->config.use_rgba_3d_shadows) {
+ glBindTexture(GL_TEXTURE_2D, shadow_atlas->color);
+ } else {
+ glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
+ }
state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_5, shadow_filter_mode == SHADOW_FILTER_PCF5);
state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_13, shadow_filter_mode == SHADOW_FILTER_PCF13);
}
@@ -2041,7 +2094,7 @@ void RasterizerSceneGLES2::_setup_refprobes(ReflectionProbeInstance *p_refprobe1
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_EXTERIOR, p_refprobe2->probe_ptr->interior);
state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_INTENSITY, p_refprobe2->probe_ptr->intensity);
Color ambient;
@@ -2737,6 +2790,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
if (probe_interior) {
env_radiance_tex = 0; //do not use radiance texture on interiors
+ state.default_ambient = Color(0, 0, 0, 1); //black as default ambient for interior
}
// render opaque things first
@@ -2994,7 +3048,9 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glDepthMask(GL_TRUE);
- glColorMask(0, 0, 0, 0);
+ 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);
@@ -3070,7 +3126,9 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_
if (storage->frame.current_rt) {
glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
}
- glColorMask(1, 1, 1, 1);
+ if (!storage->config.use_rgba_3d_shadows) {
+ glColorMask(1, 1, 1, 1);
+ }
}
void RasterizerSceneGLES2::set_scene_pass(uint64_t p_pass) {
@@ -3108,6 +3166,16 @@ bool RasterizerSceneGLES2::free(RID p_rid) {
ReflectionProbeInstance *reflection_instance = reflection_probe_instance_owner.get(p_rid);
+ for (int i = 0; i < 6; i++) {
+ glDeleteFramebuffers(1, &reflection_instance->fbo[i]);
+ glDeleteTextures(1, &reflection_instance->color[i]);
+ }
+
+ if (reflection_instance->cubemap != 0) {
+ glDeleteTextures(1, &reflection_instance->cubemap);
+ }
+ glDeleteTextures(1, &reflection_instance->depth);
+
reflection_probe_release_atlas_index(p_rid);
reflection_probe_instance_owner.free(p_rid);
memdelete(reflection_instance);
@@ -3124,6 +3192,8 @@ void RasterizerSceneGLES2::set_debug_draw_mode(VS::ViewportDebugDraw p_debug_dra
void RasterizerSceneGLES2::initialize() {
state.scene_shader.init();
+
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_RGBA_SHADOWS, storage->config.use_rgba_3d_shadows);
state.cube_to_dp_shader.init();
render_list.init();
@@ -3202,6 +3272,7 @@ void RasterizerSceneGLES2::initialize() {
glBindTexture(GL_TEXTURE_CUBE_MAP, cube.cubemap);
for (int i = 0; i < 6; i++) {
+
glTexImage2D(_cube_side_enum[i], 0, GL_DEPTH_COMPONENT, cube_size, cube_size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
}
@@ -3245,6 +3316,17 @@ void RasterizerSceneGLES2::initialize() {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, directional_shadow.depth, 0);
+ if (storage->config.use_rgba_3d_shadows) {
+ 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, NULL);
+ 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);
+ }
+
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
ERR_PRINT("Directional shadow framebuffer status invalid");
diff --git a/drivers/gles2/rasterizer_scene_gles2.h b/drivers/gles2/rasterizer_scene_gles2.h
index aab9ae0fdc..fbb8b7e9e5 100644
--- a/drivers/gles2/rasterizer_scene_gles2.h
+++ b/drivers/gles2/rasterizer_scene_gles2.h
@@ -256,6 +256,7 @@ public:
GLuint fbo;
GLuint depth;
+ GLuint color;
Map<RID, uint32_t> shadow_owners;
};
@@ -279,6 +280,7 @@ public:
struct DirectionalShadow {
GLuint fbo;
GLuint depth;
+ GLuint color;
int light_count;
int size;
@@ -311,10 +313,9 @@ public:
int reflection_index;
GLuint fbo[6];
- GLuint cubemap;
+ GLuint color[6];
GLuint depth;
-
- GLuint fbo_blur;
+ GLuint cubemap;
int current_resolution;
mutable bool dirty;
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp
index 29e125e8a2..0acbb8cf51 100644
--- a/drivers/gles2/rasterizer_storage_gles2.cpp
+++ b/drivers/gles2/rasterizer_storage_gles2.cpp
@@ -1026,18 +1026,8 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
glGenTextures(1, &sky->radiance);
glBindTexture(GL_TEXTURE_CUBE_MAP, sky->radiance);
- // Now we create a new framebuffer. The new cubemap images will be used as
- // attachements for it, so we can fill them by issuing draw calls.
- GLuint tmp_fb;
-
int size = p_radiance_size / 4; //divide by four because its a cubemap (this is an approximation because GLES3 uses a dual paraboloid)
- int lod = 0;
-
- int mipmaps = 6;
-
- int mm_level = mipmaps;
-
GLenum internal_format = GL_RGB;
GLenum format = GL_RGB;
GLenum type = GL_UNSIGNED_BYTE;
@@ -1050,6 +1040,12 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
}
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
+ //no filters for now
+ glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_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);
+
#else
while (size >= 1) {
@@ -1063,39 +1059,50 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
}
#endif
//framebuffer
- glGenFramebuffers(1, &tmp_fb);
- glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb);
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_SOURCE_PANORAMA, texture->target == GL_TEXTURE_2D);
-
- shaders.cubemap_filter.bind();
- lod = 0;
- mm_level = mipmaps;
+ glBindFramebuffer(GL_FRAMEBUFFER, resources.mipmap_blur_fbo);
+ int mipmaps = 6;
+ int lod = 0;
+ int mm_level = mipmaps;
size = p_radiance_size;
+ shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_SOURCE_PANORAMA, true);
+ shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_DIRECT_WRITE, true);
+ shaders.cubemap_filter.bind();
- // now render to the framebuffer, mipmap level for mipmap level
+ // third, render to the framebuffer using separate textures, then copy to mipmaps
while (size >= 1) {
+ //make framebuffer size the texture size, need to use a separate texture for compatibility
+ glActiveTexture(GL_TEXTURE3);
+ glBindTexture(GL_TEXTURE_2D, resources.mipmap_blur_color);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resources.mipmap_blur_color, 0);
+ if (lod == 1) {
+ //bind panorama for smaller lods
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, sky->radiance);
+ shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_SOURCE_PANORAMA, false);
+ shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_DIRECT_WRITE, false);
+ shaders.cubemap_filter.bind();
+ }
+ glViewport(0, 0, size, size);
+ bind_quad_array();
- for (int i = 0; i < 6; i++) {
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _cube_side_enum[i], sky->radiance, lod);
-
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- break; //may be too small
- }
-
- glViewport(0, 0, size, size);
+ glActiveTexture(GL_TEXTURE2); //back to panorama
- bind_quad_array();
+ for (int i = 0; i < 6; i++) {
shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::FACE_ID, i);
- float roughness = mm_level ? lod / (float)(mipmaps - 1) : 1;
+ float roughness = mm_level >= 0 ? lod / (float)(mipmaps - 1) : 1;
roughness = MIN(1.0, roughness); //keep max at 1
shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::ROUGHNESS, roughness);
+ shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::Z_FLIP, false);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ glCopyTexImage2D(_cube_side_enum[i], lod, GL_RGB, 0, 0, size, size, 0);
}
size >>= 1;
@@ -1105,16 +1112,28 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
lod++;
}
+ shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_SOURCE_PANORAMA, false);
+ shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_DIRECT_WRITE, false);
+
// restore ranges
+ glActiveTexture(GL_TEXTURE2); //back to panorama
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);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glActiveTexture(GL_TEXTURE3); //back to panorama
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
// Framebuffer did its job. thank mr framebuffer
+ glActiveTexture(GL_TEXTURE0); //back to panorama
glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo);
- glDeleteFramebuffers(1, &tmp_fb);
}
/* SHADER API */
@@ -2438,7 +2457,6 @@ AABB RasterizerStorageGLES2::mesh_surface_get_aabb(RID p_mesh, int p_surface) co
}
Vector<PoolVector<uint8_t> > RasterizerStorageGLES2::mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const {
- WARN_PRINT("GLES2 mesh_surface_get_blend_shapes is not implemented");
return Vector<PoolVector<uint8_t> >();
}
Vector<AABB> RasterizerStorageGLES2::mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const {
@@ -3662,6 +3680,7 @@ RID RasterizerStorageGLES2::reflection_probe_create() {
reflection_probe->intensity = 1.0;
reflection_probe->interior_ambient = Color();
reflection_probe->interior_ambient_energy = 1.0;
+ reflection_probe->interior_ambient_probe_contrib = 0.0;
reflection_probe->max_distance = 0;
reflection_probe->extents = Vector3(1, 1, 1);
reflection_probe->origin_offset = Vector3(0, 0, 0);
@@ -3747,6 +3766,7 @@ void RasterizerStorageGLES2::reflection_probe_set_as_interior(RID p_probe, bool
ERR_FAIL_COND(!reflection_probe);
reflection_probe->interior = p_enable;
+ reflection_probe->instance_change_notify(true, false);
}
void RasterizerStorageGLES2::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
@@ -4962,8 +4982,10 @@ void RasterizerStorageGLES2::initialize() {
#endif
#ifdef GLES_OVER_GL
config.use_rgba_2d_shadows = false;
+ config.use_rgba_3d_shadows = false;
#else
config.use_rgba_2d_shadows = !(config.float_texture_supported && config.extensions.has("GL_EXT_texture_rg"));
+ config.use_rgba_3d_shadows = config.extensions.has("GL_OES_depth_texture");
#endif
#ifdef GLES_OVER_GL
@@ -4974,6 +4996,8 @@ void RasterizerStorageGLES2::initialize() {
#ifdef GLES_OVER_GL
config.support_write_depth = true;
+#elif defined(JAVASCRIPT_ENABLED)
+ config.support_write_depth = false;
#else
config.support_write_depth = config.extensions.has("GL_EXT_frag_depth");
#endif
@@ -4995,7 +5019,7 @@ void RasterizerStorageGLES2::initialize() {
shaders.copy.init();
shaders.cubemap_filter.init();
- bool ggx_hq = GLOBAL_GET("rendering/quality/reflections/high_quality_ggx.mobile");
+ bool ggx_hq = GLOBAL_GET("rendering/quality/reflections/high_quality_ggx");
shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::LOW_QUALITY, !ggx_hq);
{
@@ -5115,10 +5139,20 @@ void RasterizerStorageGLES2::initialize() {
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 512, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, radical_inverse);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //need this for proper sampling
glBindTexture(GL_TEXTURE_2D, 0);
}
+ {
+
+ glGenFramebuffers(1, &resources.mipmap_blur_fbo);
+ glGenTextures(1, &resources.mipmap_blur_color);
+ }
+
#ifdef GLES_OVER_GL
//this needs to be enabled manually in OpenGL 2.1
diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h
index 0f1d81f70d..8e177ba57f 100644
--- a/drivers/gles2/rasterizer_storage_gles2.h
+++ b/drivers/gles2/rasterizer_storage_gles2.h
@@ -78,6 +78,7 @@ public:
bool force_vertex_shading;
bool use_rgba_2d_shadows;
+ bool use_rgba_3d_shadows;
bool support_32_bits_indices;
bool support_write_depth;
@@ -92,6 +93,9 @@ public:
GLuint normal_tex;
GLuint aniso_tex;
+ GLuint mipmap_blur_fbo;
+ GLuint mipmap_blur_color;
+
GLuint radical_inverse_vdc_cache_tex;
bool use_rgba_2d_shadows;
diff --git a/drivers/gles2/shaders/cubemap_filter.glsl b/drivers/gles2/shaders/cubemap_filter.glsl
index 7643297a14..c32aabc4bf 100644
--- a/drivers/gles2/shaders/cubemap_filter.glsl
+++ b/drivers/gles2/shaders/cubemap_filter.glsl
@@ -187,6 +187,18 @@ void main() {
vec2 uv = (uv_interp * 2.0) - 1.0;
vec3 N = texelCoordToVec(uv, face_id);
+#ifdef USE_DIRECT_WRITE
+
+#ifdef USE_SOURCE_PANORAMA
+
+ gl_FragColor = vec4(texturePanorama(source_panorama, N).rgb, 1.0);
+#else
+
+ gl_FragColor = vec4(textureCube(source_cube,N).rgb, 1.0);
+#endif //USE_SOURCE_PANORAMA
+
+#else
+
vec4 sum = vec4(0.0);
for (int sample_num = 0; sample_num < SAMPLE_COUNT; sample_num++) {
@@ -221,4 +233,5 @@ void main() {
sum.rgb = mix((vec3(1.0) + a) * pow(sum.rgb, vec3(1.0 / 2.4)) - a, 12.92 * sum.rgb, vec3(lessThan(sum.rgb, vec3(0.0031308))));
gl_FragColor = vec4(sum.rgb, 1.0);
+#endif
}
diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl
index f90c6a6651..e638e94402 100644
--- a/drivers/gles2/shaders/scene.glsl
+++ b/drivers/gles2/shaders/scene.glsl
@@ -96,6 +96,10 @@ uniform float light_normal_bias;
// varyings
//
+#if defined(RENDER_DEPTH) && defined(USE_RGBA_SHADOWS)
+varying highp vec4 position_interp;
+#endif
+
varying highp vec3 vertex_interp;
varying vec3 normal_interp;
@@ -355,7 +359,7 @@ void main() {
uv2_interp = uv2_attrib;
#endif
-#ifdef OVERRIDE_POSITION
+#if defined(OVERRIDE_POSITION)
highp vec4 position;
#endif
@@ -647,11 +651,16 @@ VERTEX_SHADER_CODE
#endif //use vertex lighting
-#ifdef OVERRIDE_POSITION
+#if defined(OVERRIDE_POSITION)
gl_Position = position;
#else
gl_Position = projection_matrix * vec4(vertex_interp, 1.0);
#endif
+
+#if defined(RENDER_DEPTH) && defined(USE_RGBA_SHADOWS)
+ position_interp = gl_Position;
+#endif
+
}
/* clang-format off */
@@ -975,6 +984,10 @@ uniform vec4 light_clamp;
// varyings
//
+#if defined(RENDER_DEPTH) && defined(USE_RGBA_SHADOWS)
+varying highp vec4 position_interp;
+#endif
+
varying highp vec3 vertex_interp;
varying vec3 normal_interp;
@@ -1335,8 +1348,21 @@ LIGHT_SHADER_CODE
#ifdef USE_SHADOW
-#define SAMPLE_SHADOW_TEXEL(p_shadow, p_pos, p_depth) step(p_depth, texture2D(p_shadow, p_pos).r)
-#define SAMPLE_SHADOW_TEXEL_PROJ(p_shadow, p_pos) step(p_pos.z, texture2DProj(p_shadow, p_pos).r)
+#ifdef USE_RGBA_SHADOWS
+
+#define SHADOW_DEPTH(m_val) dot(m_val, vec4(1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0))
+
+#else
+
+#define SHADOW_DEPTH(m_val) (m_val).r
+
+#endif
+
+
+#define SAMPLE_SHADOW_TEXEL(p_shadow, p_pos, p_depth) step(p_depth, SHADOW_DEPTH(texture2D(p_shadow, p_pos)))
+#define SAMPLE_SHADOW_TEXEL_PROJ(p_shadow, p_pos) step(p_pos.z, SHADOW_DEPTH(texture2DProj(p_shadow, p_pos)))
+
+
float sample_shadow(highp sampler2D shadow, highp vec4 spos) {
@@ -2105,5 +2131,15 @@ FRAGMENT_SHADER_CODE
#endif // defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED)
-#endif // not RENDER_DEPTH
+#else // not RENDER_DEPTH
+//depth render
+#ifdef USE_RGBA_SHADOWS
+
+ highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0; // bias
+ highp vec4 comp = fract(depth * vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0));
+ comp -= comp.xxyz * vec4(0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);
+ gl_FragColor = comp;
+
+#endif
+#endif
}
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 99e594d242..ccd5fff99f 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -5522,6 +5522,7 @@ void RasterizerStorageGLES3::reflection_probe_set_as_interior(RID p_probe, bool
ERR_FAIL_COND(!reflection_probe);
reflection_probe->interior = p_enable;
+ reflection_probe->instance_change_notify(true, false);
}
void RasterizerStorageGLES3::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {