diff options
author | Juan Linietsky <juan@godotengine.org> | 2019-02-25 21:46:24 -0300 |
---|---|---|
committer | Juan Linietsky <juan@godotengine.org> | 2019-02-25 21:47:29 -0300 |
commit | a32b26dfa26f2a039bf9c84b90d10666bcf785c9 (patch) | |
tree | 71ba0cf141b34b242edbe39f266ef36d6054a761 /drivers | |
parent | 51c1d55cf9089cefbde034893b4784a5d554ddcc (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.cpp | 1 | ||||
-rw-r--r-- | drivers/gles2/rasterizer_scene_gles2.cpp | 132 | ||||
-rw-r--r-- | drivers/gles2/rasterizer_scene_gles2.h | 7 | ||||
-rw-r--r-- | drivers/gles2/rasterizer_storage_gles2.cpp | 98 | ||||
-rw-r--r-- | drivers/gles2/rasterizer_storage_gles2.h | 4 | ||||
-rw-r--r-- | drivers/gles2/shaders/cubemap_filter.glsl | 13 | ||||
-rw-r--r-- | drivers/gles2/shaders/scene.glsl | 46 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.cpp | 1 |
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) { |