diff options
Diffstat (limited to 'drivers/gles2')
-rw-r--r-- | drivers/gles2/rasterizer_gles2.cpp | 4 | ||||
-rw-r--r-- | drivers/gles2/rasterizer_scene_gles2.cpp | 92 | ||||
-rw-r--r-- | drivers/gles2/rasterizer_scene_gles2.h | 2 | ||||
-rw-r--r-- | drivers/gles2/rasterizer_storage_gles2.cpp | 279 | ||||
-rw-r--r-- | drivers/gles2/rasterizer_storage_gles2.h | 12 | ||||
-rw-r--r-- | drivers/gles2/shaders/scene.glsl | 42 |
6 files changed, 345 insertions, 86 deletions
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 99eb0665d6..3b3fbf9ed5 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, @@ -1148,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++; @@ -2435,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); @@ -2442,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); @@ -2544,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); } @@ -2689,7 +2724,11 @@ 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); @@ -2791,6 +2830,7 @@ 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); @@ -2830,6 +2870,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 + state.default_bg = Color(0, 0, 0, 1); //black as default background for interior } // render opaque things first @@ -2838,7 +2879,38 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const 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 @@ -2851,6 +2923,22 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const 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 48672991d1..d805984dca 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; @@ -670,6 +671,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 13fdd1db73..d709056709 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); @@ -4552,95 +4571,174 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) { 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 - - 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; + } - texture_set_flags(rt->texture, texture->flags); + //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); + + } else { + rt->multisample_active = false; + } glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -4669,7 +4767,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); @@ -4728,6 +4826,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() { @@ -4929,6 +5041,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); @@ -5452,6 +5569,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 d6130849fb..3134082e2a 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; @@ -1132,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? @@ -1182,6 +1188,10 @@ public: fbo(0), color(0), depth(0), + multisample_fbo(0), + multisample_color(0), + multisample_depth(0), + multisample_active(false), width(0), height(0), used_in_frame(false), diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl index 1c35b455c4..0fa290e57c 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; @@ -1558,7 +1562,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; @@ -1569,6 +1572,7 @@ FRAGMENT_SHADER_CODE #else ambient_light = ambient_color.rgb; + specular_light = bg_color.rgb * bg_energy; #endif @@ -1628,6 +1632,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; @@ -1699,6 +1716,8 @@ FRAGMENT_SHADER_CODE #endif +#if !defined(SHADOWS_DISABLED) + #ifdef USE_SHADOW { highp vec4 splane = shadow_coord; @@ -1729,6 +1748,8 @@ FRAGMENT_SHADER_CODE } #endif +#endif //SHADOWS_DISABLED + #endif //type omni #ifdef LIGHT_MODE_DIRECTIONAL @@ -1739,6 +1760,8 @@ FRAGMENT_SHADER_CODE #endif float depth_z = -vertex.z; +#if !defined(SHADOWS_DISABLED) + #ifdef USE_SHADOW #ifdef USE_VERTEX_LIGHTING @@ -1957,6 +1980,8 @@ FRAGMENT_SHADER_CODE #endif //use shadow +#endif // SHADOWS_DISABLED + #endif #ifdef LIGHT_MODE_SPOT @@ -1993,6 +2018,8 @@ FRAGMENT_SHADER_CODE #endif +#if !defined(SHADOWS_DISABLED) + #ifdef USE_SHADOW { highp vec4 splane = shadow_coord; @@ -2002,6 +2029,8 @@ FRAGMENT_SHADER_CODE } #endif +#endif // SHADOWS_DISABLED + #endif // LIGHT_MODE_SPOT #ifdef USE_VERTEX_LIGHTING @@ -2065,17 +2094,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 } |