summaryrefslogtreecommitdiff
path: root/drivers/gles2
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gles2')
-rw-r--r--drivers/gles2/rasterizer_canvas_gles2.cpp26
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp4
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.cpp134
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.h26
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.cpp323
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.h20
-rw-r--r--drivers/gles2/shader_compiler_gles2.cpp10
-rw-r--r--drivers/gles2/shaders/canvas.glsl2
-rw-r--r--drivers/gles2/shaders/effect_blur.glsl5
-rw-r--r--drivers/gles2/shaders/scene.glsl102
10 files changed, 535 insertions, 117 deletions
diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp
index 7232d2d95a..ee722e9d6c 100644
--- a/drivers/gles2/rasterizer_canvas_gles2.cpp
+++ b/drivers/gles2/rasterizer_canvas_gles2.cpp
@@ -113,9 +113,22 @@ void RasterizerCanvasGLES2::canvas_begin() {
state.canvas_shader.bind();
state.using_transparent_rt = false;
+ int viewport_x, viewport_y, viewport_width, viewport_height;
+
if (storage->frame.current_rt) {
glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
state.using_transparent_rt = storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT];
+
+ if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN]) {
+ // set Viewport and Scissor when rendering directly to screen
+ viewport_width = storage->frame.current_rt->width;
+ viewport_height = storage->frame.current_rt->height;
+ viewport_x = storage->frame.current_rt->x;
+ viewport_y = OS::get_singleton()->get_window_size().height - viewport_height - storage->frame.current_rt->y;
+ glScissor(viewport_x, viewport_y, viewport_width, viewport_height);
+ glViewport(viewport_x, viewport_y, viewport_width, viewport_height);
+ glEnable(GL_SCISSOR_TEST);
+ }
}
if (storage->frame.clear_request) {
@@ -179,6 +192,14 @@ void RasterizerCanvasGLES2::canvas_end() {
glDisableVertexAttribArray(i);
}
+ if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN]) {
+ //reset viewport to full window size
+ int viewport_width = OS::get_singleton()->get_window_size().width;
+ int viewport_height = OS::get_singleton()->get_window_size().height;
+ glViewport(0, 0, viewport_width, viewport_height);
+ glScissor(0, 0, viewport_width, viewport_height);
+ }
+
state.using_texture_rect = false;
state.using_skeleton = false;
state.using_ninepatch = false;
@@ -1192,6 +1213,11 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
void RasterizerCanvasGLES2::_copy_screen(const Rect2 &p_rect) {
+ if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN]) {
+ ERR_PRINT_ONCE("Cannot use screen texture copying in render target set to render direct to screen");
+ return;
+ }
+
if (storage->frame.current_rt->copy_screen_effect.color == 0) {
ERR_EXPLAIN("Can't use screen texture copying in a render target configured without copy buffers");
ERR_FAIL();
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index d3c6b041a8..f49f52e47b 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -202,6 +202,10 @@ Error RasterizerGLES2::is_viable() {
return ERR_UNAVAILABLE;
}
}
+
+ if (GLAD_GL_EXT_framebuffer_multisample) {
+ glRenderbufferStorageMultisample = glRenderbufferStorageMultisampleEXT;
+ }
#endif // GLES_OVER_GL
#endif // GLAD_ENABLED
diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp
index e790d5b031..268b0f1c90 100644
--- a/drivers/gles2/rasterizer_scene_gles2.cpp
+++ b/drivers/gles2/rasterizer_scene_gles2.cpp
@@ -42,6 +42,16 @@
#define glClearDepth glClearDepthf
#endif
+#ifndef GLES_OVER_GL
+#ifdef IPHONE_ENABLED
+#include <OpenGLES/ES2/glext.h>
+//void *glResolveMultisampleFramebufferAPPLE;
+
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#endif
+#endif
+
static const GLenum _cube_side_enum[6] = {
GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
@@ -480,7 +490,6 @@ RID RasterizerSceneGLES2::reflection_probe_instance_create(RID p_probe) {
rpi->current_resolution = 0;
rpi->dirty = true;
- rpi->last_pass = 0;
rpi->index = 0;
for (int i = 0; i < 6; i++) {
@@ -571,7 +580,7 @@ bool RasterizerSceneGLES2::reflection_probe_instance_begin_render(RID p_instance
//the approach below is fatal for powervr
- // Set the initial (empty) mipmaps, all need to be set for this to work in GLES2, even if later wont be used.
+ // Set the initial (empty) mipmaps, all need to be set for this to work in GLES2, even if they won't be used later.
while (size >= 1) {
for (int i = 0; i < 6; i++) {
@@ -1002,7 +1011,7 @@ void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::G
has_alpha = false;
}
- RenderList::Element *e = has_alpha ? render_list.add_alpha_element() : render_list.add_element();
+ RenderList::Element *e = (has_alpha || p_material->shader->spatial.no_depth_test) ? render_list.add_alpha_element() : render_list.add_element();
if (!e) {
return;
@@ -1149,6 +1158,30 @@ void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::G
}
}
+void RasterizerSceneGLES2::_copy_texture_to_front_buffer(GLuint p_texture) {
+
+ //copy to front buffer
+ glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
+
+ glDepthMask(GL_FALSE);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_BLEND);
+ glDepthFunc(GL_LEQUAL);
+ glColorMask(1, 1, 1, 1);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, p_texture);
+
+ glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
+
+ storage->shaders.copy.bind();
+
+ storage->bind_quad_array();
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
void RasterizerSceneGLES2::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass, bool p_shadow_pass) {
render_pass++;
@@ -2436,6 +2469,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
if (p_env) {
state.scene_shader.set_uniform(SceneShaderGLES2::BG_ENERGY, p_env->bg_energy);
+ state.scene_shader.set_uniform(SceneShaderGLES2::BG_COLOR, p_env->bg_color);
state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_SKY_CONTRIBUTION, p_env->ambient_sky_contribution);
state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_COLOR, p_env->ambient_color);
@@ -2443,6 +2477,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
} else {
state.scene_shader.set_uniform(SceneShaderGLES2::BG_ENERGY, 1.0);
+ state.scene_shader.set_uniform(SceneShaderGLES2::BG_COLOR, state.default_bg);
state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_SKY_CONTRIBUTION, 1.0);
state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_COLOR, state.default_ambient);
state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_ENERGY, 1.0);
@@ -2545,7 +2580,6 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTMAP_CAPTURE, false);
state.scene_shader.set_conditional(SceneShaderGLES2::FOG_DEPTH_ENABLED, false);
state.scene_shader.set_conditional(SceneShaderGLES2::FOG_HEIGHT_ENABLED, false);
- state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, false);
state.scene_shader.set_conditional(SceneShaderGLES2::USE_DEPTH_PREPASS, false);
}
@@ -2661,6 +2695,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
Environment *env = NULL;
int viewport_width, viewport_height;
+ int viewport_x, viewport_y;
bool probe_interior = false;
bool reverse_cull = false;
@@ -2690,12 +2725,23 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
if (storage->frame.current_rt->external.fbo != 0) {
current_fb = storage->frame.current_rt->external.fbo;
} else {
- current_fb = storage->frame.current_rt->fbo;
+ if (storage->frame.current_rt->multisample_active) {
+ current_fb = storage->frame.current_rt->multisample_fbo;
+ } else {
+ current_fb = storage->frame.current_rt->fbo;
+ }
}
env = environment_owner.getornull(p_environment);
viewport_width = storage->frame.current_rt->width;
viewport_height = storage->frame.current_rt->height;
+ viewport_x = storage->frame.current_rt->x;
+
+ if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN]) {
+ viewport_y = OS::get_singleton()->get_window_size().height - viewport_height - storage->frame.current_rt->y;
+ } else {
+ viewport_y = storage->frame.current_rt->y;
+ }
}
state.used_screen_texture = false;
@@ -2761,7 +2807,13 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
// other stuff
glBindFramebuffer(GL_FRAMEBUFFER, current_fb);
- glViewport(0, 0, viewport_width, viewport_height);
+ glViewport(viewport_x, viewport_y, viewport_width, viewport_height);
+
+ if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN]) {
+
+ glScissor(viewport_x, viewport_y, viewport_width, viewport_height);
+ glEnable(GL_SCISSOR_TEST);
+ }
glDepthFunc(GL_LEQUAL);
glDepthMask(GL_TRUE);
@@ -2792,9 +2844,14 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
}
state.default_ambient = Color(clear_color.r, clear_color.g, clear_color.b, 1.0);
+ state.default_bg = Color(clear_color.r, clear_color.g, clear_color.b, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN]) {
+ glDisable(GL_SCISSOR_TEST);
+ }
+
glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
glBlendEquation(GL_FUNC_ADD);
@@ -2821,37 +2878,86 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
}
}
- if (env && env->bg_mode == VS::ENV_BG_SKY && (!storage->frame.current_rt || !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT])) {
-
- if (sky && sky->panorama.is_valid()) {
- _draw_sky(sky, p_cam_projection, cam_transform, false, env->sky_custom_fov, env->bg_energy, env->sky_orientation);
- }
- }
-
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
+ state.default_bg = Color(0, 0, 0, 1); //black as default background for interior
}
// render opaque things first
render_list.sort_by_key(false);
_render_render_list(render_list.elements, render_list.element_count, cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, reverse_cull, false, false);
+ // then draw the sky after
+ if (env && env->bg_mode == VS::ENV_BG_SKY && (!storage->frame.current_rt || !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT])) {
+
+ if (sky && sky->panorama.is_valid()) {
+ _draw_sky(sky, p_cam_projection, cam_transform, false, env->sky_custom_fov, env->bg_energy, env->sky_orientation);
+ }
+ }
+
if (storage->frame.current_rt && state.used_screen_texture) {
//copy screen texture
+
+ if (storage->frame.current_rt && storage->frame.current_rt->multisample_active) {
+ // Resolve framebuffer to front buffer before copying
+#ifdef GLES_OVER_GL
+
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->multisample_fbo);
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo);
+ glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+#elif IPHONE_ENABLED
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->multisample_fbo);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo);
+ glResolveMultisampleFramebufferAPPLE();
+
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+#else
+ // In GLES2 Blit is not available, so just copy color texture manually
+ _copy_texture_to_front_buffer(storage->frame.current_rt->multisample_color);
+#endif
+ }
+
storage->canvas->_copy_screen(Rect2());
+
+ if (storage->frame.current_rt && storage->frame.current_rt->multisample_active) {
+ // Rebind the current framebuffer
+ glBindFramebuffer(GL_FRAMEBUFFER, current_fb);
+ glViewport(0, 0, viewport_width, viewport_height);
+ }
}
// alpha pass
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- render_list.sort_by_depth(true);
+ render_list.sort_by_reverse_depth_and_priority(true);
_render_render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, reverse_cull, true, false);
glDisable(GL_DEPTH_TEST);
+ if (storage->frame.current_rt && storage->frame.current_rt->multisample_active) {
+#ifdef GLES_OVER_GL
+
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->multisample_fbo);
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo);
+ glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+#else
+ // In GLES2 Blit is not available, so just copy color texture manually
+ _copy_texture_to_front_buffer(storage->frame.current_rt->multisample_color);
+#endif
+ }
+
//#define GLES2_SHADOW_ATLAS_DEBUG_VIEW
#ifdef GLES2_SHADOW_ATLAS_DEBUG_VIEW
diff --git a/drivers/gles2/rasterizer_scene_gles2.h b/drivers/gles2/rasterizer_scene_gles2.h
index f23e45b52f..bd1a61688c 100644
--- a/drivers/gles2/rasterizer_scene_gles2.h
+++ b/drivers/gles2/rasterizer_scene_gles2.h
@@ -104,6 +104,7 @@ public:
GLuint immediate_buffer;
Color default_ambient;
+ Color default_bg;
// ResolveShaderGLES3 resolve_shader;
// ScreenSpaceReflectionShaderGLES3 ssr_shader;
@@ -502,7 +503,8 @@ public:
enum {
MAX_LIGHTS = 255,
MAX_REFLECTION_PROBES = 255,
- DEFAULT_MAX_ELEMENTS = 65536
+ DEFAULT_MAX_ELEMENTS = 65536,
+ SORT_KEY_PRIORITY_SHIFT = 56
};
int max_elements;
@@ -598,6 +600,27 @@ public:
}
}
+ struct SortByReverseDepthAndPriority {
+
+ _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
+ if (A->priority == B->priority) {
+ return A->instance->depth > B->instance->depth;
+ } else {
+ return A->priority < B->priority;
+ }
+ }
+ };
+
+ void sort_by_reverse_depth_and_priority(bool p_alpha) { //used for alpha
+
+ SortArray<Element *, SortByReverseDepthAndPriority> sorter;
+ if (p_alpha) {
+ sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
+ } else {
+ sorter.sort(elements, element_count);
+ }
+ }
+
// element adding and stuff
_FORCE_INLINE_ Element *add_element() {
@@ -646,6 +669,7 @@ public:
void _add_geometry(RasterizerStorageGLES2::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES2::GeometryOwner *p_owner, int p_material, bool p_depth_pass, bool p_shadow_pass);
void _add_geometry_with_material(RasterizerStorageGLES2::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES2::GeometryOwner *p_owner, RasterizerStorageGLES2::Material *p_material, bool p_depth_pass, bool p_shadow_pass);
+ void _copy_texture_to_front_buffer(GLuint texture);
void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass, bool p_shadow_pass);
void _render_render_list(RenderList::Element **p_elements, int p_element_count,
const Transform &p_view_transform,
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp
index 1e32d8166f..c610f31bc1 100644
--- a/drivers/gles2/rasterizer_storage_gles2.cpp
+++ b/drivers/gles2/rasterizer_storage_gles2.cpp
@@ -81,6 +81,28 @@ GLuint RasterizerStorageGLES2::system_fbo = 0;
#define _DEPTH_COMPONENT24_OES 0x81A6
+#ifndef GLES_OVER_GL
+// enable extensions manually for android and ios
+#include <dlfcn.h> // needed to load extensions
+
+#ifdef IPHONE_ENABLED
+
+#include <OpenGLES/ES2/glext.h>
+//void *glRenderbufferStorageMultisampleAPPLE;
+//void *glResolveMultisampleFramebufferAPPLE;
+#define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleAPPLE
+#else
+
+#include <GLES2/gl2ext.h>
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT;
+PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC glFramebufferTexture2DMultisampleEXT;
+#define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleEXT
+#define glFramebufferTexture2DMultisample glFramebufferTexture2DMultisampleEXT
+#endif
+
+#define GL_MAX_SAMPLES 0x8D57
+#endif //!GLES_OVER_GL
+
void RasterizerStorageGLES2::bind_quad_array() const {
glBindBuffer(GL_ARRAY_BUFFER, resources.quadie);
glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0);
@@ -774,10 +796,7 @@ Ref<Image> RasterizerStorageGLES2::texture_get_data(RID p_texture, int p_layer)
for (int i = 0; i < texture->mipmaps; i++) {
- int ofs = 0;
- if (i > 0) {
- ofs = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, i - 1);
- }
+ int ofs = Image::get_image_mipmap_offset(texture->alloc_width, texture->alloc_height, real_format, i);
if (texture->compressed) {
glPixelStorei(GL_PACK_ALIGNMENT, 4);
@@ -3712,6 +3731,7 @@ RID RasterizerStorageGLES2::light_create(VS::LightType p_type) {
light->directional_blend_splits = false;
light->directional_range_mode = VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE;
light->reverse_cull = false;
+ light->use_gi = true;
light->version = 0;
return light_owner.make_rid(light);
@@ -3799,6 +3819,16 @@ void RasterizerStorageGLES2::light_set_reverse_cull_face_mode(RID p_light, bool
light->instance_change_notify(true, false);
}
+void RasterizerStorageGLES2::light_set_use_gi(RID p_light, bool p_enabled) {
+ Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->use_gi = p_enabled;
+
+ light->version++;
+ light->instance_change_notify(true, false);
+}
+
void RasterizerStorageGLES2::light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
@@ -3894,6 +3924,13 @@ Color RasterizerStorageGLES2::light_get_color(RID p_light) {
return light->color;
}
+bool RasterizerStorageGLES2::light_get_use_gi(RID p_light) {
+ Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light, false);
+
+ return light->use_gi;
+}
+
bool RasterizerStorageGLES2::light_has_shadow(RID p_light) const {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, false);
@@ -4531,98 +4568,184 @@ void RasterizerStorageGLES2::instance_remove_dependency(RID p_base, RasterizerSc
void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) {
+ // do not allocate a render target with no size
if (rt->width <= 0 || rt->height <= 0)
return;
- Texture *texture = texture_owner.getornull(rt->texture);
- ERR_FAIL_COND(!texture);
-
- // create fbo
-
- glGenFramebuffers(1, &rt->fbo);
- glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
-
- // color
+ // do not allocate a render target that is attached to the screen
+ if (rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) {
+ rt->fbo = RasterizerStorageGLES2::system_fbo;
+ return;
+ }
- glGenTextures(1, &rt->color);
- glBindTexture(GL_TEXTURE_2D, rt->color);
+ GLuint color_internal_format;
+ GLuint color_format;
+ GLuint color_type = GL_UNSIGNED_BYTE;
if (rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rt->width, rt->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ color_internal_format = GL_RGBA;
+ color_format = GL_RGBA;
} else {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, rt->width, rt->height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+ color_internal_format = GL_RGB;
+ color_format = GL_RGB;
}
- if (texture->flags & VS::TEXTURE_FLAG_FILTER) {
+ {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- } else {
+ /* Front FBO */
- 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);
+ Texture *texture = texture_owner.getornull(rt->texture);
+ ERR_FAIL_COND(!texture);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
+ // framebuffer
+ glGenFramebuffers(1, &rt->fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
- // depth
+ // color
+ glGenTextures(1, &rt->color);
+ glBindTexture(GL_TEXTURE_2D, rt->color);
- if (config.support_depth_texture) {
- glGenTextures(1, &rt->depth);
- glBindTexture(GL_TEXTURE_2D, rt->depth);
- glTexImage2D(GL_TEXTURE_2D, 0, config.depth_internalformat, rt->width, rt->height, 0, GL_DEPTH_COMPONENT, config.depth_type, NULL);
+ glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, color_format, color_type, NULL);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ if (texture->flags & VS::TEXTURE_FLAG_FILTER) {
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
- } else {
- glGenRenderbuffers(1, &rt->depth);
- glBindRenderbuffer(GL_RENDERBUFFER, rt->depth);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ } else {
- glRenderbufferStorage(GL_RENDERBUFFER, config.depth_internalformat, rt->width, rt->height);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ }
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
- }
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
+ // depth
- glDeleteFramebuffers(1, &rt->fbo);
if (config.support_depth_texture) {
- glDeleteTextures(1, &rt->depth);
+
+ glGenTextures(1, &rt->depth);
+ glBindTexture(GL_TEXTURE_2D, rt->depth);
+ glTexImage2D(GL_TEXTURE_2D, 0, config.depth_internalformat, rt->width, rt->height, 0, GL_DEPTH_COMPONENT, config.depth_type, NULL);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
} else {
- glDeleteRenderbuffers(1, &rt->depth);
+
+ glGenRenderbuffers(1, &rt->depth);
+ glBindRenderbuffer(GL_RENDERBUFFER, rt->depth);
+
+ glRenderbufferStorage(GL_RENDERBUFFER, config.depth_internalformat, rt->width, rt->height);
+
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
}
- glDeleteTextures(1, &rt->color);
- rt->fbo = 0;
- rt->width = 0;
- rt->height = 0;
- rt->color = 0;
- rt->depth = 0;
- texture->tex_id = 0;
- texture->active = false;
- WARN_PRINT("Could not create framebuffer!!");
- return;
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+
+ glDeleteFramebuffers(1, &rt->fbo);
+ if (config.support_depth_texture) {
+
+ glDeleteTextures(1, &rt->depth);
+ } else {
+
+ glDeleteRenderbuffers(1, &rt->depth);
+ }
+
+ glDeleteTextures(1, &rt->color);
+ rt->fbo = 0;
+ rt->width = 0;
+ rt->height = 0;
+ rt->color = 0;
+ rt->depth = 0;
+ texture->tex_id = 0;
+ texture->active = false;
+ WARN_PRINT("Could not create framebuffer!!");
+ return;
+ }
+
+ texture->format = Image::FORMAT_RGBA8;
+ texture->gl_format_cache = GL_RGBA;
+ texture->gl_type_cache = GL_UNSIGNED_BYTE;
+ texture->gl_internal_format_cache = GL_RGBA;
+ texture->tex_id = rt->color;
+ texture->width = rt->width;
+ texture->alloc_width = rt->width;
+ texture->height = rt->height;
+ texture->alloc_height = rt->height;
+ texture->active = true;
+
+ texture_set_flags(rt->texture, texture->flags);
}
- texture->format = Image::FORMAT_RGBA8;
- texture->gl_format_cache = GL_RGBA;
- texture->gl_type_cache = GL_UNSIGNED_BYTE;
- texture->gl_internal_format_cache = GL_RGBA;
- texture->tex_id = rt->color;
- texture->width = rt->width;
- texture->alloc_width = rt->width;
- texture->height = rt->height;
- texture->alloc_height = rt->height;
- texture->active = true;
+ /* BACK FBO */
+ /* For MSAA */
+
+ if (rt->msaa != VS::VIEWPORT_MSAA_DISABLED && config.multisample_supported) {
+
+ rt->multisample_active = true;
+
+ static const int msaa_value[] = { 0, 2, 4, 8, 16 };
+ int msaa = msaa_value[rt->msaa];
+
+ int max_samples = 0;
+ glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
+ if (msaa > max_samples) {
+ WARN_PRINTS("MSAA must be <= GL_MAX_SAMPLES, falling-back to GL_MAX_SAMPLES = " + itos(max_samples));
+ msaa = max_samples;
+ }
+
+ //regular fbo
+ glGenFramebuffers(1, &rt->multisample_fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, rt->multisample_fbo);
+
+ glGenRenderbuffers(1, &rt->multisample_depth);
+ glBindRenderbuffer(GL_RENDERBUFFER, rt->multisample_depth);
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, config.depth_internalformat, rt->width, rt->height);
+
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->multisample_depth);
+
+#if defined(GLES_OVER_GL) || defined(IPHONE_ENABLED)
+
+ glGenRenderbuffers(1, &rt->multisample_color);
+ glBindRenderbuffer(GL_RENDERBUFFER, rt->multisample_color);
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, color_internal_format, rt->width, rt->height);
+
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rt->multisample_color);
+#else
+ // Render to a texture in android
+ glGenTextures(1, &rt->multisample_color);
+ glBindTexture(GL_TEXTURE_2D, rt->multisample_color);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, color_format, color_type, NULL);
+
+ // multisample buffer is same size as front buffer, so just use nearest
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+ glFramebufferTexture2DMultisample(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0, msaa);
+#endif
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ printf("err status: %x\n", status);
+ _render_target_clear(rt);
+ ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
+ }
+
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
- texture_set_flags(rt->texture, texture->flags);
+ } else {
+ rt->multisample_active = false;
+ }
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -4651,7 +4774,7 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) {
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
- status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
_render_target_clear(rt);
ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
@@ -4663,6 +4786,10 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) {
void RasterizerStorageGLES2::_render_target_clear(RenderTarget *rt) {
+ // there is nothing to clear when DIRECT_TO_SCREEN is used
+ if (rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN])
+ return;
+
if (rt->fbo) {
glDeleteFramebuffers(1, &rt->fbo);
glDeleteTextures(1, &rt->color);
@@ -4710,6 +4837,20 @@ void RasterizerStorageGLES2::_render_target_clear(RenderTarget *rt) {
glDeleteTextures(1, &rt->copy_screen_effect.color);
rt->copy_screen_effect.color = 0;
}
+
+ if (rt->multisample_active) {
+ glDeleteFramebuffers(1, &rt->multisample_fbo);
+ rt->multisample_fbo = 0;
+
+ glDeleteRenderbuffers(1, &rt->multisample_depth);
+ rt->multisample_depth = 0;
+#ifdef GLES_OVER_GL
+ glDeleteRenderbuffers(1, &rt->multisample_color);
+#else
+ glDeleteTextures(1, &rt->multisample_color);
+#endif
+ rt->multisample_color = 0;
+ }
}
RID RasterizerStorageGLES2::render_target_create() {
@@ -4743,6 +4884,15 @@ RID RasterizerStorageGLES2::render_target_create() {
return render_target_owner.make_rid(rt);
}
+void RasterizerStorageGLES2::render_target_set_position(RID p_render_target, int p_x, int p_y) {
+
+ RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ rt->x = p_x;
+ rt->y = p_y;
+}
+
void RasterizerStorageGLES2::render_target_set_size(RID p_render_target, int p_width, int p_height) {
RenderTarget *rt = render_target_owner.getornull(p_render_target);
@@ -4872,6 +5022,14 @@ void RasterizerStorageGLES2::render_target_set_flag(RID p_render_target, RenderT
RenderTarget *rt = render_target_owner.getornull(p_render_target);
ERR_FAIL_COND(!rt);
+ // When setting DIRECT_TO_SCREEN, you need to clear before the value is set, but allocate after as
+ // those functions change how they operate depending on the value of DIRECT_TO_SCREEN
+ if (p_flag == RENDER_TARGET_DIRECT_TO_SCREEN && p_value != rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) {
+ _render_target_clear(rt);
+ rt->flags[p_flag] = p_value;
+ _render_target_allocate(rt);
+ }
+
rt->flags[p_flag] = p_value;
switch (p_flag) {
@@ -4911,6 +5069,11 @@ void RasterizerStorageGLES2::render_target_set_msaa(RID p_render_target, VS::Vie
if (rt->msaa == p_msaa)
return;
+ if (!config.multisample_supported) {
+ ERR_PRINT("MSAA not supported on this hardware.");
+ return;
+ }
+
_render_target_clear(rt);
rt->msaa = p_msaa;
_render_target_allocate(rt);
@@ -5434,6 +5597,26 @@ void RasterizerStorageGLES2::initialize() {
config.support_npot_repeat_mipmap = config.extensions.has("GL_OES_texture_npot");
#endif
+
+#ifndef GLES_OVER_GL
+ //Manually load extensions for android and ios
+
+#ifdef IPHONE_ENABLED
+
+ //void *gles2_lib = dlopen(NULL, RTLD_LAZY);
+ //glRenderbufferStorageMultisampleAPPLE = dlsym(gles2_lib, "glRenderbufferStorageMultisampleAPPLE");
+ //glResolveMultisampleFramebufferAPPLE = dlsym(gles2_lib, "glResolveMultisampleFramebufferAPPLE");
+#else
+
+ void *gles2_lib = dlopen("libGLESv2.so", RTLD_LAZY);
+ glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)dlsym(gles2_lib, "glRenderbufferStorageMultisampleEXT");
+ glFramebufferTexture2DMultisampleEXT = (PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC)dlsym(gles2_lib, "glFramebufferTexture2DMultisampleEXT");
+#endif
+#endif
+
+ // Check for multisample support
+ config.multisample_supported = config.extensions.has("GL_EXT_framebuffer_multisample") || config.extensions.has("GL_EXT_multisampled_render_to_texture") || config.extensions.has("GL_APPLE_framebuffer_multisample");
+
#ifdef GLES_OVER_GL
config.use_rgba_2d_shadows = false;
config.support_depth_texture = true;
diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h
index 2ac68fa47a..af57aa3d9b 100644
--- a/drivers/gles2/rasterizer_storage_gles2.h
+++ b/drivers/gles2/rasterizer_storage_gles2.h
@@ -92,6 +92,8 @@ public:
bool support_shadow_cubemaps;
+ bool multisample_supported;
+
GLuint depth_internalformat;
GLuint depth_type;
@@ -910,6 +912,7 @@ public:
bool shadow;
bool negative;
bool reverse_cull;
+ bool use_gi;
uint32_t cull_mask;
@@ -936,6 +939,7 @@ public:
virtual void light_set_negative(RID p_light, bool p_enable);
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask);
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled);
+ virtual void light_set_use_gi(RID p_light, bool p_enabled);
virtual void light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode);
virtual void light_omni_set_shadow_detail(RID p_light, VS::LightOmniShadowDetail p_detail);
@@ -955,6 +959,7 @@ public:
virtual VS::LightType light_get_type(RID p_light) const;
virtual float light_get_param(RID p_light, VS::LightParam p_param);
virtual Color light_get_color(RID p_light);
+ virtual bool light_get_use_gi(RID p_light);
virtual AABB light_get_aabb(RID p_light) const;
virtual uint64_t light_get_version(RID p_light) const;
@@ -1129,10 +1134,14 @@ public:
struct RenderTarget : public RID_Data {
GLuint fbo;
-
GLuint color;
GLuint depth;
+ GLuint multisample_fbo;
+ GLuint multisample_color;
+ GLuint multisample_depth;
+ bool multisample_active;
+
// TODO post processing effects?
// TODO HDR?
@@ -1166,7 +1175,7 @@ public:
}
} external;
- int width, height;
+ int x, y, width, height;
bool flags[RENDER_TARGET_FLAG_MAX];
@@ -1179,6 +1188,12 @@ public:
fbo(0),
color(0),
depth(0),
+ multisample_fbo(0),
+ multisample_color(0),
+ multisample_depth(0),
+ multisample_active(false),
+ x(0),
+ y(0),
width(0),
height(0),
used_in_frame(false),
@@ -1196,6 +1211,7 @@ public:
void _render_target_allocate(RenderTarget *rt);
virtual RID render_target_create();
+ virtual void render_target_set_position(RID p_render_target, int p_x, int p_y);
virtual void render_target_set_size(RID p_render_target, int p_width, int p_height);
virtual RID render_target_get_texture(RID p_render_target) const;
virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id);
diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp
index d00b03fb8a..9778d39a21 100644
--- a/drivers/gles2/shader_compiler_gles2.cpp
+++ b/drivers/gles2/shader_compiler_gles2.cpp
@@ -316,9 +316,14 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
for (Map<StringName, SL::ShaderNode::Uniform>::Element *E = snode->uniforms.front(); E; E = E->next()) {
StringBuffer<> uniform_code;
- uniform_code += "uniform ";
+ // use highp if no precision is specified to prevent different default values in fragment and vertex shader
+ SL::DataPrecision precision = E->get().precision;
+ if (precision == SL::PRECISION_DEFAULT) {
+ precision = SL::PRECISION_HIGHP;
+ }
- uniform_code += _prestr(E->get().precision);
+ uniform_code += "uniform ";
+ uniform_code += _prestr(precision);
uniform_code += _typestr(E->get().type);
uniform_code += " ";
uniform_code += _mkid(E->key());
@@ -934,6 +939,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
actions[VS::SHADER_SPATIAL].render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n";
+ actions[VS::SHADER_SPATIAL].render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n";
// No defines for particle shaders in GLES2, there are no GPU particles
diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl
index 7ba2856216..7dce784f52 100644
--- a/drivers/gles2/shaders/canvas.glsl
+++ b/drivers/gles2/shaders/canvas.glsl
@@ -347,7 +347,7 @@ void main() {
vec4 color = color_interp;
vec2 uv = uv_interp;
#ifdef USE_FORCE_REPEAT
- //needs to use this to workaround GLES2/WebGL1 forcing tiling that textures that dont support it
+ //needs to use this to workaround GLES2/WebGL1 forcing tiling that textures that don't support it
uv = mod(uv, vec2(1.0, 1.0));
#endif
diff --git a/drivers/gles2/shaders/effect_blur.glsl b/drivers/gles2/shaders/effect_blur.glsl
index a531802c75..df79e89931 100644
--- a/drivers/gles2/shaders/effect_blur.glsl
+++ b/drivers/gles2/shaders/effect_blur.glsl
@@ -116,12 +116,13 @@ void main() {
#ifdef GAUSSIAN_HORIZONTAL
vec2 pix_size = pixel_size;
pix_size *= 0.5; //reading from larger buffer, so use more samples
+ // sigma 2
vec4 color = textureLod(source_color, uv_interp + vec2(0.0, 0.0) * pix_size, lod) * 0.214607;
color += textureLod(source_color, uv_interp + vec2(1.0, 0.0) * pix_size, lod) * 0.189879;
- color += textureLod(source_color, uv_interp + vec2(2.0, 0.0) * pix_size, lod) * 0.157305;
+ color += textureLod(source_color, uv_interp + vec2(2.0, 0.0) * pix_size, lod) * 0.131514;
color += textureLod(source_color, uv_interp + vec2(3.0, 0.0) * pix_size, lod) * 0.071303;
color += textureLod(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size, lod) * 0.189879;
- color += textureLod(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size, lod) * 0.157305;
+ color += textureLod(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size, lod) * 0.131514;
color += textureLod(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size, lod) * 0.071303;
frag_color = color;
#endif
diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl
index 5d21c679ba..2aef913ae8 100644
--- a/drivers/gles2/shaders/scene.glsl
+++ b/drivers/gles2/shaders/scene.glsl
@@ -424,9 +424,12 @@ void main() {
#endif
+ mat4 local_projection_matrix = projection_matrix;
+
mat4 modelview = camera_inverse_matrix * world_matrix;
float roughness = 1.0;
+#define projection_matrix local_projection_matrix
#define world_transform world_matrix
{
@@ -911,6 +914,7 @@ uniform mat4 radiance_inverse_xform;
#endif
+uniform vec4 bg_color;
uniform float bg_energy;
uniform float ambient_sky_contribution;
@@ -1147,7 +1151,8 @@ void light_compute(
float clearcoat_gloss,
float anisotropy,
inout vec3 diffuse_light,
- inout vec3 specular_light) {
+ inout vec3 specular_light,
+ inout float alpha) {
//this makes lights behave closer to linear, but then addition of lights looks bad
//better left disabled
@@ -1302,10 +1307,10 @@ LIGHT_SHADER_CODE
// shlick+ggx as default
#if defined(LIGHT_USE_ANISOTROPY)
- float alpha = roughness * roughness;
+ float alpha_ggx = roughness * roughness;
float aspect = sqrt(1.0 - anisotropy * 0.9);
- float ax = alpha / aspect;
- float ay = alpha * aspect;
+ float ax = alpha_ggx / aspect;
+ float ay = alpha_ggx * aspect;
float XdotH = dot(T, H);
float YdotH = dot(B, H);
float D = D_GGX_anisotropic(cNdotH, ax, ay, XdotH, YdotH, cNdotH);
@@ -1313,10 +1318,10 @@ LIGHT_SHADER_CODE
float G = V_GGX_anisotropic(ax, ay, dot(T, V), dot(T, L), dot(B, V), dot(B, L), cNdotV, cNdotL);
#else
- float alpha = roughness * roughness;
- float D = D_GGX(cNdotH, alpha);
- //float G = G_GGX_2cos(cNdotL, alpha) * G_GGX_2cos(cNdotV, alpha);
- float G = V_GGX(cNdotL, cNdotV, alpha);
+ float alpha_ggx = roughness * roughness;
+ float D = D_GGX(cNdotH, alpha_ggx);
+ //float G = G_GGX_2cos(cNdotL, alpha_ggx) * G_GGX_2cos(cNdotV, alpha_ggx);
+ float G = V_GGX(cNdotL, cNdotV, alpha_ggx);
#endif
// F
vec3 f0 = F0(metallic, specular, diffuse_color);
@@ -1346,6 +1351,10 @@ LIGHT_SHADER_CODE
#endif
}
+#ifdef USE_SHADOW_TO_OPACITY
+ alpha = min(alpha, clamp(1.0 - length(attenuation), 0.0, 1.0));
+#endif
+
#endif //defined(USE_LIGHT_SHADER_CODE)
}
@@ -1531,20 +1540,29 @@ FRAGMENT_SHADER_CODE
vec3 eye_position = view;
+#if !defined(USE_SHADOW_TO_OPACITY)
+
#if defined(ALPHA_SCISSOR_USED)
if (alpha < alpha_scissor) {
discard;
}
-#endif
+#endif // ALPHA_SCISSOR_USED
#ifdef USE_DEPTH_PREPASS
if (alpha < 0.99) {
discard;
}
-#endif
+#endif // USE_DEPTH_PREPASS
+
+#endif // !USE_SHADOW_TO_OPACITY
#ifdef BASE_PASS
//none
+
+#ifdef AMBIENT_LIGHT_DISABLED
+ ambient_light = vec3(0.0, 0.0, 0.0);
+#else
+
#ifdef USE_RADIANCE_MAP
vec3 ref_vec = reflect(-eye_position, N);
@@ -1553,7 +1571,6 @@ FRAGMENT_SHADER_CODE
ref_vec.z *= -1.0;
specular_light = textureCubeLod(radiance_map, ref_vec, roughness * RADIANCE_MAX_LOD).xyz * bg_energy;
-
{
vec3 ambient_dir = normalize((radiance_inverse_xform * vec4(normal, 0.0)).xyz);
vec3 env_ambient = textureCubeLod(radiance_map, ambient_dir, RADIANCE_MAX_LOD).xyz * bg_energy;
@@ -1564,9 +1581,11 @@ FRAGMENT_SHADER_CODE
#else
ambient_light = ambient_color.rgb;
+ specular_light = bg_color.rgb * bg_energy;
#endif
+#endif // AMBIENT_LIGHT_DISABLED
ambient_light *= ambient_energy;
#if defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2)
@@ -1622,6 +1641,19 @@ FRAGMENT_SHADER_CODE
#endif // defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2)
+ // scales the specular reflections, needs to be be computed before lighting happens,
+ // but after environment and reflection probes are added
+ //TODO: this curve is not really designed for gammaspace, should be adjusted
+ const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022);
+ const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04);
+ vec4 r = roughness * c0 + c1;
+ float ndotv = clamp(dot(normal, eye_position), 0.0, 1.0);
+ float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y;
+ vec2 env = vec2(-1.04, 1.04) * a004 + r.zw;
+
+ vec3 f0 = F0(metallic, specular, albedo);
+ specular_light *= env.x * f0 + env.y;
+
#ifdef USE_LIGHTMAP
//ambient light will come entirely from lightmap is lightmap is used
ambient_light = texture2D(lightmap, uv2_interp).rgb * lightmap_energy;
@@ -1693,6 +1725,8 @@ FRAGMENT_SHADER_CODE
#endif
+#if !defined(SHADOWS_DISABLED)
+
#ifdef USE_SHADOW
{
highp vec4 splane = shadow_coord;
@@ -1723,6 +1757,8 @@ FRAGMENT_SHADER_CODE
}
#endif
+#endif //SHADOWS_DISABLED
+
#endif //type omni
#ifdef LIGHT_MODE_DIRECTIONAL
@@ -1733,6 +1769,8 @@ FRAGMENT_SHADER_CODE
#endif
float depth_z = -vertex.z;
+#if !defined(SHADOWS_DISABLED)
+
#ifdef USE_SHADOW
#ifdef USE_VERTEX_LIGHTING
@@ -1951,6 +1989,8 @@ FRAGMENT_SHADER_CODE
#endif //use shadow
+#endif // SHADOWS_DISABLED
+
#endif
#ifdef LIGHT_MODE_SPOT
@@ -1987,6 +2027,8 @@ FRAGMENT_SHADER_CODE
#endif
+#if !defined(SHADOWS_DISABLED)
+
#ifdef USE_SHADOW
{
highp vec4 splane = shadow_coord;
@@ -1996,6 +2038,8 @@ FRAGMENT_SHADER_CODE
}
#endif
+#endif // SHADOWS_DISABLED
+
#endif // LIGHT_MODE_SPOT
#ifdef USE_VERTEX_LIGHTING
@@ -2026,13 +2070,32 @@ FRAGMENT_SHADER_CODE
clearcoat_gloss,
anisotropy,
diffuse_light,
- specular_light);
+ specular_light,
+ alpha);
#endif //vertex lighting
#endif //USE_LIGHTING
//compute and merge
+#ifdef USE_SHADOW_TO_OPACITY
+
+ alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0));
+
+#if defined(ALPHA_SCISSOR_USED)
+ if (alpha < alpha_scissor) {
+ discard;
+ }
+#endif // ALPHA_SCISSOR_USED
+
+#ifdef USE_DEPTH_PREPASS
+ if (alpha < 0.99) {
+ discard;
+ }
+#endif // USE_DEPTH_PREPASS
+
+#endif // !USE_SHADOW_TO_OPACITY
+
#ifndef RENDER_DEPTH
#ifdef SHADELESS
@@ -2059,17 +2122,6 @@ FRAGMENT_SHADER_CODE
#if defined(DIFFUSE_TOON)
//simplify for toon, as
specular_light *= specular * metallic * albedo * 2.0;
-#else
- //TODO: this curve is not really designed for gammaspace, should be adjusted
- const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022);
- const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04);
- vec4 r = roughness * c0 + c1;
- float ndotv = clamp(dot(normal, eye_position), 0.0, 1.0);
- float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y;
- vec2 env = vec2(-1.04, 1.04) * a004 + r.zw;
-
- vec3 f0 = F0(metallic, specular, albedo);
- specular_light *= env.x * f0 + env.y;
#endif
}
@@ -2081,8 +2133,6 @@ FRAGMENT_SHADER_CODE
#endif
// gl_FragColor = vec4(normal, 1.0);
-#endif //unshaded
-
//apply fog
#if defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED)
@@ -2137,6 +2187,8 @@ FRAGMENT_SHADER_CODE
#endif // defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED)
+#endif //unshaded
+
#else // not RENDER_DEPTH
//depth render
#ifdef USE_RGBA_SHADOWS