summaryrefslogtreecommitdiff
path: root/drivers/gles2/rasterizer_scene_gles2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gles2/rasterizer_scene_gles2.cpp')
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.cpp188
1 files changed, 157 insertions, 31 deletions
diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp
index e790d5b031..50cb39b13f 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;
@@ -1018,6 +1027,7 @@ void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::G
e->light_index = RenderList::MAX_LIGHTS;
e->use_accum_ptr = &e->use_accum;
e->instancing = (e->instance->base_type == VS::INSTANCE_MULTIMESH) ? 1 : 0;
+ e->front_facing = false;
if (e->geometry->last_pass != render_pass) {
e->geometry->last_pass = render_pass;
@@ -1037,6 +1047,10 @@ void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::G
e->material_index = e->material->index;
+ if (mirror) {
+ e->front_facing = true;
+ }
+
e->refprobe_0_index = RenderList::MAX_REFLECTION_PROBES; //refprobe disabled by default
e->refprobe_1_index = RenderList::MAX_REFLECTION_PROBES; //refprobe disabled by default
@@ -1149,6 +1163,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++;
@@ -1224,7 +1262,29 @@ static const GLenum gl_primitive[] = {
GL_TRIANGLE_FAN
};
-bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_material, bool p_reverse_cull, bool p_alpha_pass, Size2i p_skeleton_tex_size) {
+void RasterizerSceneGLES2::_set_cull(bool p_front, bool p_disabled, bool p_reverse_cull) {
+
+ bool front = p_front;
+ if (p_reverse_cull)
+ front = !front;
+
+ if (p_disabled != state.cull_disabled) {
+ if (p_disabled)
+ glDisable(GL_CULL_FACE);
+ else
+ glEnable(GL_CULL_FACE);
+
+ state.cull_disabled = p_disabled;
+ }
+
+ if (front != state.cull_front) {
+
+ glCullFace(front ? GL_FRONT : GL_BACK);
+ state.cull_front = front;
+ }
+}
+
+bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_material, bool p_alpha_pass, Size2i p_skeleton_tex_size) {
// material parameters
@@ -1262,21 +1322,6 @@ bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m
} break;
}
- switch (p_material->shader->spatial.cull_mode) {
- case RasterizerStorageGLES2::Shader::Spatial::CULL_MODE_DISABLED: {
- glDisable(GL_CULL_FACE);
- } break;
-
- case RasterizerStorageGLES2::Shader::Spatial::CULL_MODE_BACK: {
- glEnable(GL_CULL_FACE);
- glCullFace(p_reverse_cull ? GL_FRONT : GL_BACK);
- } break;
- case RasterizerStorageGLES2::Shader::Spatial::CULL_MODE_FRONT: {
- glEnable(GL_CULL_FACE);
- glCullFace(p_reverse_cull ? GL_BACK : GL_FRONT);
- } break;
- }
-
int tc = p_material->textures.size();
const Pair<StringName, RID> *textures = p_material->textures.ptr();
@@ -2169,6 +2214,11 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
int prev_blend_mode = -2; //will always catch the first go
+ state.cull_front = false;
+ state.cull_disabled = false;
+ glCullFace(GL_BACK);
+ glEnable(GL_CULL_FACE);
+
if (p_alpha_pass) {
glEnable(GL_BLEND);
} else {
@@ -2408,12 +2458,14 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
if (rebind || material != prev_material) {
storage->info.render.material_switch_count++;
- shader_rebind = _setup_material(material, p_reverse_cull, p_alpha_pass, Size2i(skeleton ? skeleton->size * 3 : 0, 0));
+ shader_rebind = _setup_material(material, p_alpha_pass, Size2i(skeleton ? skeleton->size * 3 : 0, 0));
if (shader_rebind) {
storage->info.render.shader_rebind_count++;
}
}
+ _set_cull(e->front_facing, material->shader->spatial.cull_mode == RasterizerStorageGLES2::Shader::Spatial::CULL_MODE_DISABLED, p_reverse_cull);
+
if (i == 0 || shader_rebind) { //first time must rebind
if (p_shadow) {
@@ -2436,6 +2488,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 +2496,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 +2599,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 +2714,8 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
Environment *env = NULL;
int viewport_width, viewport_height;
+ int viewport_x = 0;
+ int viewport_y = 0;
bool probe_interior = false;
bool reverse_cull = false;
@@ -2690,12 +2745,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 +2827,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 +2864,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 +2898,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