diff options
Diffstat (limited to 'drivers/gles3/rasterizer_scene_gles3.cpp')
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.cpp | 1397 |
1 files changed, 823 insertions, 574 deletions
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index d3936801dd..30c0d65ff3 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -28,8 +29,8 @@ /*************************************************************************/ #include "rasterizer_scene_gles3.h" -#include "global_config.h" #include "os/os.h" +#include "project_settings.h" #include "rasterizer_canvas_gles3.h" #ifndef GLES_OVER_GL @@ -124,14 +125,13 @@ void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas, int p_size) { if (p_size == shadow_atlas->size) return; + // erasing atlas if (shadow_atlas->fbo) { glDeleteTextures(1, &shadow_atlas->depth); glDeleteFramebuffers(1, &shadow_atlas->fbo); shadow_atlas->depth = 0; shadow_atlas->fbo = 0; - - print_line("erasing atlas"); } for (int i = 0; i < 4; i++) { //clear subdivisions @@ -521,13 +521,7 @@ void RasterizerSceneGLES3::reflection_atlas_set_size(RID p_ref_atlas, int p_size glBindTexture(GL_TEXTURE_2D, reflection_atlas->color); int mmsize = reflection_atlas->size; - - for (int i = 0; i < 6; i++) { - glTexImage2D(GL_TEXTURE_2D, i, internal_format, mmsize, mmsize, 0, - format, type, NULL); - - mmsize >>= 1; - } + glTexStorage2DCustom(GL_TEXTURE_2D, 6, internal_format, mmsize, mmsize, format, type); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -537,8 +531,6 @@ void RasterizerSceneGLES3::reflection_atlas_set_size(RID p_ref_atlas, int p_size glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 5); - mmsize = reflection_atlas->size; - for (int i = 0; i < 6; i++) { glGenFramebuffers(1, &reflection_atlas->fbo[i]); glBindFramebuffer(GL_FRAMEBUFFER, reflection_atlas->fbo[i]); @@ -761,7 +753,7 @@ bool RasterizerSceneGLES3::reflection_probe_instance_postprocess_step(RID p_inst storage->shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::LOW_QUALITY, rpi->probe_ptr->update_mode == VS::REFLECTION_PROBE_UPDATE_ALWAYS); for (int i = 0; i < 2; i++) { - storage->shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::Z_FLIP, i > 0); + storage->shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::Z_FLIP, i == 0); storage->shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::ROUGHNESS, rpi->render_step / 5.0); uint32_t local_width = width, local_height = height; @@ -798,20 +790,20 @@ void RasterizerSceneGLES3::environment_set_background(RID p_env, VS::Environment env->bg_mode = p_bg; } -void RasterizerSceneGLES3::environment_set_skybox(RID p_env, RID p_skybox) { +void RasterizerSceneGLES3::environment_set_sky(RID p_env, RID p_sky) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); - env->skybox = p_skybox; + env->sky = p_sky; } -void RasterizerSceneGLES3::environment_set_skybox_scale(RID p_env, float p_scale) { +void RasterizerSceneGLES3::environment_set_sky_scale(RID p_env, float p_scale) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); - env->skybox_scale = p_scale; + env->sky_scale = p_scale; } void RasterizerSceneGLES3::environment_set_bg_color(RID p_env, const Color &p_color) { @@ -836,14 +828,14 @@ void RasterizerSceneGLES3::environment_set_canvas_max_layer(RID p_env, int p_max env->canvas_max_layer = p_max_layer; } -void RasterizerSceneGLES3::environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy, float p_skybox_contribution) { +void RasterizerSceneGLES3::environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy, float p_sky_contribution) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); env->ambient_color = p_color; env->ambient_energy = p_energy; - env->ambient_skybox_contribution = p_skybox_contribution; + env->ambient_sky_contribution = p_sky_contribution; } void RasterizerSceneGLES3::environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality) { @@ -869,7 +861,7 @@ void RasterizerSceneGLES3::environment_set_dof_blur_near(RID p_env, bool p_enabl env->dof_blur_near_amount = p_amount; env->dof_blur_near_quality = p_quality; } -void RasterizerSceneGLES3::environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_treshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, bool p_bicubic_upscale) { +void RasterizerSceneGLES3::environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, bool p_bicubic_upscale) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); @@ -878,26 +870,25 @@ void RasterizerSceneGLES3::environment_set_glow(RID p_env, bool p_enable, int p_ env->glow_levels = p_level_flags; env->glow_intensity = p_intensity; env->glow_strength = p_strength; - env->glow_bloom = p_bloom_treshold; + env->glow_bloom = p_bloom_threshold; env->glow_blend_mode = p_blend_mode; - env->glow_hdr_bleed_treshold = p_hdr_bleed_treshold; + env->glow_hdr_bleed_threshold = p_hdr_bleed_threshold; env->glow_hdr_bleed_scale = p_hdr_bleed_scale; env->glow_bicubic_upscale = p_bicubic_upscale; } void RasterizerSceneGLES3::environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) { } -void RasterizerSceneGLES3::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_accel, float p_fade, float p_depth_tolerance, bool p_smooth, bool p_roughness) { +void RasterizerSceneGLES3::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_in, float p_fade_out, float p_depth_tolerance, bool p_roughness) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); env->ssr_enabled = p_enable; env->ssr_max_steps = p_max_steps; - env->ssr_accel = p_accel; - env->ssr_fade = p_fade; + env->ssr_fade_in = p_fade_in; + env->ssr_fade_out = p_fade_out; env->ssr_depth_tolerance = p_depth_tolerance; - env->ssr_smooth = p_smooth; env->ssr_roughness = p_roughness; } @@ -933,6 +924,70 @@ void RasterizerSceneGLES3::environment_set_tonemap(RID p_env, VS::EnvironmentTon } void RasterizerSceneGLES3::environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) { + + Environment *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->adjustments_enabled = p_enable; + env->adjustments_brightness = p_brightness; + env->adjustments_contrast = p_contrast; + env->adjustments_saturation = p_saturation; + env->color_correction = p_ramp; +} + +void RasterizerSceneGLES3::environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) { + + Environment *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->fog_enabled = p_enable; + env->fog_color = p_color; + env->fog_sun_color = p_sun_color; + env->fog_sun_amount = p_sun_amount; +} + +void RasterizerSceneGLES3::environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_curve, bool p_transmit, float p_transmit_curve) { + + Environment *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->fog_depth_enabled = p_enable; + env->fog_depth_begin = p_depth_begin; + env->fog_depth_curve = p_depth_curve; + env->fog_transmit_enabled = p_transmit; + env->fog_transmit_curve = p_transmit_curve; +} + +void RasterizerSceneGLES3::environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) { + + Environment *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->fog_height_enabled = p_enable; + env->fog_height_min = p_min_height; + env->fog_height_max = p_max_height; + env->fog_height_curve = p_height_curve; +} + +bool RasterizerSceneGLES3::is_environment(RID p_env) { + + return environment_owner.owns(p_env); +} + +VS::EnvironmentBG RasterizerSceneGLES3::environment_get_background(RID p_env) { + + const Environment *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, VS::ENV_BG_MAX); + + return env->bg_mode; +} + +int RasterizerSceneGLES3::environment_get_canvas_max_layer(RID p_env) { + + const Environment *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, -1); + + return env->canvas_max_layer; } RID RasterizerSceneGLES3::light_instance_create(RID p_light) { @@ -961,7 +1016,7 @@ void RasterizerSceneGLES3::light_instance_set_transform(RID p_light_instance, co light_instance->transform = p_transform; } -void RasterizerSceneGLES3::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass) { +void RasterizerSceneGLES3::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale) { LightInstance *light_instance = light_instance_owner.getornull(p_light_instance); ERR_FAIL_COND(!light_instance); @@ -976,6 +1031,7 @@ void RasterizerSceneGLES3::light_instance_set_shadow_transform(RID p_light_insta light_instance->shadow_transform[p_pass].transform = p_transform; light_instance->shadow_transform[p_pass].farplane = p_far; light_instance->shadow_transform[p_pass].split = p_split; + light_instance->shadow_transform[p_pass].bias_scale = p_bias_scale; } void RasterizerSceneGLES3::light_instance_mark_visible(RID p_light_instance) { @@ -1164,6 +1220,7 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m } break; case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: { tex = storage->resources.normal_tex; + } break; default: { tex = storage->resources.white_tex; @@ -1177,29 +1234,14 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m t->detect_3d(t->detect_3d_ud); } #endif - if (storage->config.srgb_decode_supported) { - //if SRGB decode extension is present, simply switch the texture to whathever is needed - bool must_srgb = false; - - if (t->srgb && (texture_hints[i] == ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || texture_hints[i] == ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO)) { - must_srgb = true; - } - if (t->using_srgb != must_srgb) { - if (must_srgb) { - glTexParameteri(t->target, _TEXTURE_SRGB_DECODE_EXT, _DECODE_EXT); #ifdef TOOLS_ENABLED - if (t->detect_srgb) { - t->detect_srgb(t->detect_srgb_ud); - } -#endif - - } else { - glTexParameteri(t->target, _TEXTURE_SRGB_DECODE_EXT, _SKIP_DECODE_EXT); - } - t->using_srgb = must_srgb; - } + if (t->detect_normal && texture_hints[i] == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL) { + t->detect_normal(t->detect_normal_ud); } +#endif + if (t->render_target) + t->render_target->used_in_frame = true; target = t->target; tex = t->tex_id; @@ -1207,6 +1249,30 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m glBindTexture(target, tex); + if (t && storage->config.srgb_decode_supported) { + //if SRGB decode extension is present, simply switch the texture to whathever is needed + bool must_srgb = false; + + if (t->srgb && (texture_hints[i] == ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || texture_hints[i] == ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO)) { + must_srgb = true; + } + + if (t->using_srgb != must_srgb) { + if (must_srgb) { + glTexParameteri(t->target, _TEXTURE_SRGB_DECODE_EXT, _DECODE_EXT); +#ifdef TOOLS_ENABLED + if (t->detect_srgb) { + t->detect_srgb(t->detect_srgb_ud); + } +#endif + + } else { + glTexParameteri(t->target, _TEXTURE_SRGB_DECODE_EXT, _SKIP_DECODE_EXT); + } + t->using_srgb = must_srgb; + } + } + if (i == 0) { state.current_main_tex = tex; } @@ -1215,7 +1281,26 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m return rebind; } -void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e) { +struct RasterizerGLES3Particle { + + float color[4]; + float velocity_active[4]; + float custom[4]; + float xform_1[4]; + float xform_2[4]; + float xform_3[4]; +}; + +struct RasterizerGLES3ParticleSort { + + Vector3 z_dir; + bool operator()(const RasterizerGLES3Particle &p_a, const RasterizerGLES3Particle &p_b) const { + + return z_dir.dot(Vector3(p_a.xform_1[3], p_a.xform_2[3], p_a.xform_3[3])) < z_dir.dot(Vector3(p_b.xform_1[3], p_b.xform_2[3], p_b.xform_3[3])); + } +}; + +void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transform &p_view_transform) { switch (e->instance->base_type) { @@ -1228,8 +1313,11 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e) { storage->mesh_render_blend_shapes(s, e->instance->blend_values.ptr()); //rebind shader state.scene_shader.bind(); +#ifdef DEBUG_ENABLED + } else if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->array_wireframe_id) { + glBindVertexArray(s->array_wireframe_id); // everything is so easy nowadays +#endif } else { - glBindVertexArray(s->array_id); // everything is so easy nowadays } @@ -1239,7 +1327,16 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e) { RasterizerStorageGLES3::MultiMesh *multi_mesh = static_cast<RasterizerStorageGLES3::MultiMesh *>(e->owner); RasterizerStorageGLES3::Surface *s = static_cast<RasterizerStorageGLES3::Surface *>(e->geometry); - glBindVertexArray(s->instancing_array_id); // use the instancing array ID +#ifdef DEBUG_ENABLED + if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->instancing_array_wireframe_id) { + + glBindVertexArray(s->instancing_array_wireframe_id); // use the instancing array ID + } else +#endif + { + glBindVertexArray(s->instancing_array_id); // use the instancing array ID + } + glBindBuffer(GL_ARRAY_BUFFER, multi_mesh->buffer); //modify the buffer int stride = (multi_mesh->xform_floats + multi_mesh->color_floats) * 4; @@ -1283,6 +1380,74 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e) { } } break; + case VS::INSTANCE_PARTICLES: { + + RasterizerStorageGLES3::Particles *particles = static_cast<RasterizerStorageGLES3::Particles *>(e->owner); + RasterizerStorageGLES3::Surface *s = static_cast<RasterizerStorageGLES3::Surface *>(e->geometry); + + if (particles->draw_order == VS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->particle_valid_histories[1]) { + + glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffer_histories[1]); //modify the buffer, this was used 2 frames ago so it should be good enough for flushing + RasterizerGLES3Particle *particle_array = (RasterizerGLES3Particle *)glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 24 * sizeof(float), GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); + + SortArray<RasterizerGLES3Particle, RasterizerGLES3ParticleSort> sorter; + + if (particles->use_local_coords) { + sorter.compare.z_dir = e->instance->transform.affine_inverse().xform(p_view_transform.basis.get_axis(2)).normalized(); + } else { + sorter.compare.z_dir = p_view_transform.basis.get_axis(2).normalized(); + } + + sorter.sort(particle_array, particles->amount); + + glUnmapBuffer(GL_ARRAY_BUFFER); +#ifdef DEBUG_ENABLED + if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->instancing_array_wireframe_id) { + glBindVertexArray(s->instancing_array_wireframe_id); // use the wireframe instancing array ID + } else +#endif + { + + glBindVertexArray(s->instancing_array_id); // use the instancing array ID + } + glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffer_histories[1]); //modify the buffer + + } else { +#ifdef DEBUG_ENABLED + if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->instancing_array_wireframe_id) { + glBindVertexArray(s->instancing_array_wireframe_id); // use the wireframe instancing array ID + } else +#endif + { + glBindVertexArray(s->instancing_array_id); // use the instancing array ID + } + glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); //modify the buffer + } + + int stride = sizeof(float) * 4 * 6; + + //transform + + if (particles->draw_order != VS::PARTICLES_DRAW_ORDER_LIFETIME) { + + glEnableVertexAttribArray(8); //xform x + glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 3); + glVertexAttribDivisor(8, 1); + glEnableVertexAttribArray(9); //xform y + glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 4); + glVertexAttribDivisor(9, 1); + glEnableVertexAttribArray(10); //xform z + glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 5); + glVertexAttribDivisor(10, 1); + glEnableVertexAttribArray(11); //color + glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 0); + glVertexAttribDivisor(11, 1); + glEnableVertexAttribArray(12); //custom + glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 2); + glVertexAttribDivisor(12, 1); + } + + } break; } } @@ -1304,17 +1469,25 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { RasterizerStorageGLES3::Surface *s = static_cast<RasterizerStorageGLES3::Surface *>(e->geometry); - if (s->index_array_len > 0) { +#ifdef DEBUG_ENABLED + + if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->array_wireframe_id) { + + glDrawElements(GL_LINES, s->index_wireframe_len, GL_UNSIGNED_INT, 0); + storage->info.render.vertices_count += s->index_array_len; + } else +#endif + if (s->index_array_len > 0) { glDrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0); - storage->info.render_vertices_count += s->index_array_len; + storage->info.render.vertices_count += s->index_array_len; } else { glDrawArrays(gl_primitive[s->primitive], 0, s->array_len); - storage->info.render_vertices_count += s->array_len; + storage->info.render.vertices_count += s->array_len; } } break; @@ -1325,17 +1498,25 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { int amount = MAX(multi_mesh->size, multi_mesh->visible_instances); - if (s->index_array_len > 0) { +#ifdef DEBUG_ENABLED + + if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->array_wireframe_id) { + + glDrawElementsInstanced(GL_LINES, s->index_wireframe_len, GL_UNSIGNED_INT, 0, amount); + storage->info.render.vertices_count += s->index_array_len * amount; + } else +#endif + if (s->index_array_len > 0) { glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount); - storage->info.render_vertices_count += s->index_array_len * amount; + storage->info.render.vertices_count += s->index_array_len * amount; } else { glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount); - storage->info.render_vertices_count += s->array_len * amount; + storage->info.render.vertices_count += s->array_len * amount; } } break; @@ -1361,7 +1542,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { int vertices = c.vertices.size(); uint32_t buf_ofs = 0; - storage->info.render_vertices_count += vertices; + storage->info.render.vertices_count += vertices; if (c.texture.is_valid() && storage->texture_owner.owns(c.texture)) { @@ -1380,7 +1561,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { if (!c.normals.empty()) { glEnableVertexAttribArray(VS::ARRAY_NORMAL); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vector3) * vertices, c.normals.ptr()); + glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector3) * vertices, c.normals.ptr()); glVertexAttribPointer(VS::ARRAY_NORMAL, 3, GL_FLOAT, false, sizeof(Vector3) * vertices, ((uint8_t *)NULL) + buf_ofs); buf_ofs += sizeof(Vector3) * vertices; @@ -1392,7 +1573,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { if (!c.tangents.empty()) { glEnableVertexAttribArray(VS::ARRAY_TANGENT); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Plane) * vertices, c.tangents.ptr()); + glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Plane) * vertices, c.tangents.ptr()); glVertexAttribPointer(VS::ARRAY_TANGENT, 4, GL_FLOAT, false, sizeof(Plane) * vertices, ((uint8_t *)NULL) + buf_ofs); buf_ofs += sizeof(Plane) * vertices; @@ -1404,7 +1585,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { if (!c.colors.empty()) { glEnableVertexAttribArray(VS::ARRAY_COLOR); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Color) * vertices, c.colors.ptr()); + glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Color) * vertices, c.colors.ptr()); glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(Color), ((uint8_t *)NULL) + buf_ofs); buf_ofs += sizeof(Color) * vertices; @@ -1417,7 +1598,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { if (!c.uvs.empty()) { glEnableVertexAttribArray(VS::ARRAY_TEX_UV); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vector2) * vertices, c.uvs.ptr()); + glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector2) * vertices, c.uvs.ptr()); glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(Vector2), ((uint8_t *)NULL) + buf_ofs); buf_ofs += sizeof(Vector2) * vertices; @@ -1429,7 +1610,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { if (!c.uvs2.empty()) { glEnableVertexAttribArray(VS::ARRAY_TEX_UV2); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vector2) * vertices, c.uvs2.ptr()); + glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector2) * vertices, c.uvs2.ptr()); glVertexAttribPointer(VS::ARRAY_TEX_UV2, 2, GL_FLOAT, false, sizeof(Vector2), ((uint8_t *)NULL) + buf_ofs); buf_ofs += sizeof(Vector2) * vertices; @@ -1439,7 +1620,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { } glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vector3) * vertices, c.vertices.ptr()); + glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector3) * vertices, c.vertices.ptr()); glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, false, sizeof(Vector3), ((uint8_t *)NULL) + buf_ofs); glDrawArrays(gl_primitive[c.primitive], 0, c.vertices.size()); } @@ -1451,6 +1632,123 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { restore_tex = false; } } break; + case VS::INSTANCE_PARTICLES: { + + RasterizerStorageGLES3::Particles *particles = static_cast<RasterizerStorageGLES3::Particles *>(e->owner); + RasterizerStorageGLES3::Surface *s = static_cast<RasterizerStorageGLES3::Surface *>(e->geometry); + + if (!particles->use_local_coords) //not using local coordinates? then clear transform.. + state.scene_shader.set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, Transform()); + + int amount = particles->amount; + + if (particles->draw_order == VS::PARTICLES_DRAW_ORDER_LIFETIME) { + //split + + int stride = sizeof(float) * 4 * 6; + int split = int(Math::ceil(particles->phase * particles->amount)); + + if (amount - split > 0) { + glEnableVertexAttribArray(8); //xform x + glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + sizeof(float) * 4 * 3); + glVertexAttribDivisor(8, 1); + glEnableVertexAttribArray(9); //xform y + glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + sizeof(float) * 4 * 4); + glVertexAttribDivisor(9, 1); + glEnableVertexAttribArray(10); //xform z + glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + sizeof(float) * 4 * 5); + glVertexAttribDivisor(10, 1); + glEnableVertexAttribArray(11); //color + glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + 0); + glVertexAttribDivisor(11, 1); + glEnableVertexAttribArray(12); //custom + glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + sizeof(float) * 4 * 2); + glVertexAttribDivisor(12, 1); +#ifdef DEBUG_ENABLED + + if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->array_wireframe_id) { + + glDrawElementsInstanced(GL_LINES, s->index_wireframe_len, GL_UNSIGNED_INT, 0, amount - split); + storage->info.render.vertices_count += s->index_array_len * (amount - split); + } else +#endif + if (s->index_array_len > 0) { + + glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount - split); + + storage->info.render.vertices_count += s->index_array_len * (amount - split); + + } else { + + glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount - split); + + storage->info.render.vertices_count += s->array_len * (amount - split); + } + } + + if (split > 0) { + glEnableVertexAttribArray(8); //xform x + glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 3); + glVertexAttribDivisor(8, 1); + glEnableVertexAttribArray(9); //xform y + glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 4); + glVertexAttribDivisor(9, 1); + glEnableVertexAttribArray(10); //xform z + glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 5); + glVertexAttribDivisor(10, 1); + glEnableVertexAttribArray(11); //color + glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 0); + glVertexAttribDivisor(11, 1); + glEnableVertexAttribArray(12); //custom + glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 2); + glVertexAttribDivisor(12, 1); +#ifdef DEBUG_ENABLED + + if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->array_wireframe_id) { + + glDrawElementsInstanced(GL_LINES, s->index_wireframe_len, GL_UNSIGNED_INT, 0, split); + storage->info.render.vertices_count += s->index_array_len * split; + } else +#endif + if (s->index_array_len > 0) { + + glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, split); + + storage->info.render.vertices_count += s->index_array_len * split; + + } else { + + glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, split); + + storage->info.render.vertices_count += s->array_len * split; + } + } + + } else { + +#ifdef DEBUG_ENABLED + + if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->array_wireframe_id) { + + glDrawElementsInstanced(GL_LINES, s->index_wireframe_len, GL_UNSIGNED_INT, 0, amount); + storage->info.render.vertices_count += s->index_array_len * amount; + } else +#endif + if (s->index_array_len > 0) { + + glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount); + + storage->info.render.vertices_count += s->index_array_len * amount; + + } else { + + glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount); + + storage->info.render.vertices_count += s->array_len * amount; + } + } + + } break; } } @@ -1528,25 +1826,28 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e, const Transform GIProbeInstance *gipi = gi_probe_instance_owner.getptr(ridp[0]); - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 10); + float bias_scale = e->instance->baked_light ? 1 : 0; + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 9); glBindTexture(GL_TEXTURE_3D, gipi->tex_cache); state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_XFORM1, gipi->transform_to_data * p_view_transform); state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BOUNDS1, gipi->bounds); state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_MULTIPLIER1, gipi->probe ? gipi->probe->dynamic_range * gipi->probe->energy : 0.0); - state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BIAS1, gipi->probe ? gipi->probe->bias : 0.0); + state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BIAS1, gipi->probe ? gipi->probe->bias * bias_scale : 0.0); + state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_NORMAL_BIAS1, gipi->probe ? gipi->probe->normal_bias * bias_scale : 0.0); state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BLEND_AMBIENT1, gipi->probe ? !gipi->probe->interior : false); state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_CELL_SIZE1, gipi->cell_size_cache); if (gi_probe_count > 1) { GIProbeInstance *gipi2 = gi_probe_instance_owner.getptr(ridp[1]); - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 11); + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 10); glBindTexture(GL_TEXTURE_3D, gipi2->tex_cache); state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_XFORM2, gipi2->transform_to_data * p_view_transform); state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BOUNDS2, gipi2->bounds); state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_CELL_SIZE2, gipi2->cell_size_cache); state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_MULTIPLIER2, gipi2->probe ? gipi2->probe->dynamic_range * gipi2->probe->energy : 0.0); - state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BIAS2, gipi2->probe ? gipi2->probe->bias : 0.0); + state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BIAS2, gipi2->probe ? gipi2->probe->bias * bias_scale : 0.0); + state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_NORMAL_BIAS2, gipi2->probe ? gipi2->probe->normal_bias * bias_scale : 0.0); state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BLEND_AMBIENT2, gipi2->probe ? !gipi2->probe->interior : false); state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE2_ENABLED, true); } else { @@ -1556,61 +1857,6 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e, const Transform } } -void RasterizerSceneGLES3::_setup_transform(InstanceBase *p_instance, const Transform &p_view_transform, const CameraMatrix &p_projection) { - - if (p_instance->billboard || p_instance->billboard_y || p_instance->depth_scale) { - - Transform xf = p_instance->transform; - if (p_instance->depth_scale) { - - if (p_projection.matrix[3][3]) { - //orthogonal matrix, try to do about the same - //with viewport size - //real_t w = Math::abs( 1.0/(2.0*(p_projection.matrix[0][0])) ); - real_t h = Math::abs(1.0 / (2.0 * p_projection.matrix[1][1])); - float sc = (h * 2.0); //consistent with Y-fov - xf.basis.scale(Vector3(sc, sc, sc)); - } else { - //just scale by depth - real_t sc = Plane(p_view_transform.origin, -p_view_transform.get_basis().get_axis(2)).distance_to(xf.origin); - xf.basis.scale(Vector3(sc, sc, sc)); - } - } - - if (p_instance->billboard && storage->frame.current_rt) { - - Vector3 scale = xf.basis.get_scale(); - - if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) { - xf.set_look_at(xf.origin, xf.origin + p_view_transform.get_basis().get_axis(2), -p_view_transform.get_basis().get_axis(1)); - } else { - xf.set_look_at(xf.origin, xf.origin + p_view_transform.get_basis().get_axis(2), p_view_transform.get_basis().get_axis(1)); - } - - xf.basis.scale(scale); - } - - if (p_instance->billboard_y && storage->frame.current_rt) { - - Vector3 scale = xf.basis.get_scale(); - Vector3 look_at = p_view_transform.get_origin(); - look_at.y = 0.0; - Vector3 look_at_norm = look_at.normalized(); - - if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) { - xf.set_look_at(xf.origin, xf.origin + look_at_norm, Vector3(0.0, -1.0, 0.0)); - } else { - xf.set_look_at(xf.origin, xf.origin + look_at_norm, Vector3(0.0, 1.0, 0.0)); - } - xf.basis.scale(scale); - } - state.scene_shader.set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, xf); - - } else { - state.scene_shader.set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, p_instance->transform); - } -} - void RasterizerSceneGLES3::_set_cull(bool p_front, bool p_reverse_cull) { bool front = p_front; @@ -1626,30 +1872,31 @@ void RasterizerSceneGLES3::_set_cull(bool p_front, bool p_reverse_cull) { void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_element_count, const Transform &p_view_transform, const CameraMatrix &p_projection, GLuint p_base_env, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows) { - if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) { - //p_reverse_cull=!p_reverse_cull; - glFrontFace(GL_CCW); - } else { - glFrontFace(GL_CW); - } - glBindBufferBase(GL_UNIFORM_BUFFER, 0, state.scene_ubo); //bind globals ubo + bool use_radiance_map = false; if (!p_shadow && !p_directional_add) { glBindBufferBase(GL_UNIFORM_BUFFER, 2, state.env_radiance_ubo); //bind environment radiance info - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); - glBindTexture(GL_TEXTURE_2D, state.brdf_texture); if (p_base_env) { glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2); - glBindTexture(GL_TEXTURE_2D, p_base_env); + if (storage->config.use_texture_array_environment) { + glBindTexture(GL_TEXTURE_2D_ARRAY, p_base_env); + } else { + glBindTexture(GL_TEXTURE_2D, p_base_env); + } + state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP, true); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP_ARRAY, storage->config.use_texture_array_environment); + use_radiance_map = true; } else { state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP, false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP_ARRAY, false); } } else { state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP, false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP_ARRAY, false); } state.cull_front = false; @@ -1677,8 +1924,9 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS, true); //by default unshaded (easier to set) bool first = true; + bool prev_use_instancing = false; - storage->info.render_object_count += p_element_count; + storage->info.render.draw_call_count += p_element_count; for (int i = 0; i < p_element_count; i++) { @@ -1693,7 +1941,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ if (!p_shadow) { if (p_directional_add) { - if (e->sort_key & RenderList::SORT_KEY_UNSHADED_FLAG || !(e->instance->layer_mask & directional_light->light_ptr->cull_mask)) { + if (e->sort_key & SORT_KEY_UNSHADED_FLAG || !(e->instance->layer_mask & directional_light->light_ptr->cull_mask)) { continue; } @@ -1702,10 +1950,11 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ if (shading != prev_shading) { - if (e->sort_key & RenderList::SORT_KEY_UNSHADED_FLAG) { + if (e->sort_key & SORT_KEY_UNSHADED_FLAG) { state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS, true); state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING, false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_VERTEX_LIGHTING, false); state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL, false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW, false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4, false); @@ -1715,6 +1964,8 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_5, false); state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_13, false); state.scene_shader.set_conditional(SceneShaderGLES3::USE_GI_PROBES, false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP, false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_CONTACT_SHADOWS, false); //state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,true); } else { @@ -1722,7 +1973,10 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ state.scene_shader.set_conditional(SceneShaderGLES3::USE_GI_PROBES, e->instance->gi_probe_instances.size() > 0); state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS, false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING, !p_directional_add); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_VERTEX_LIGHTING, (e->sort_key & SORT_KEY_VERTEX_LIT_FLAG)); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL, false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW, false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4, false); @@ -1730,8 +1984,10 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND, false); state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_5, shadow_filter_mode == SHADOW_FILTER_PCF5); state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_13, shadow_filter_mode == SHADOW_FILTER_PCF13); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP, use_radiance_map); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_CONTACT_SHADOWS, state.used_contact_shadows); - if (p_directional_add || (directional_light && (e->sort_key & RenderList::SORT_KEY_NO_DIRECTIONAL_FLAG) == 0)) { + if (p_directional_add || (directional_light && (e->sort_key & SORT_KEY_NO_DIRECTIONAL_FLAG) == 0)) { state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL, true); if (p_directional_shadows && directional_light->light_ptr->shadow) { @@ -1804,10 +2060,10 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ } } + bool use_instancing = e->instance->base_type == VS::INSTANCE_MULTIMESH || e->instance->base_type == VS::INSTANCE_PARTICLES; - - if ((prev_base_type == VS::INSTANCE_MULTIMESH) != (e->instance->base_type == VS::INSTANCE_MULTIMESH)) { - state.scene_shader.set_conditional(SceneShaderGLES3::USE_INSTANCING, e->instance->base_type == VS::INSTANCE_MULTIMESH); + if (use_instancing != prev_use_instancing) { + state.scene_shader.set_conditional(SceneShaderGLES3::USE_INSTANCING, use_instancing); rebind = true; } @@ -1819,39 +2075,36 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ if (skeleton.is_valid()) { RasterizerStorageGLES3::Skeleton *sk = storage->skeleton_owner.getornull(skeleton); - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6); - glBindTexture(GL_TEXTURE_2D,sk->texture); + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); + glBindTexture(GL_TEXTURE_2D, sk->texture); } } if (material != prev_material || rebind) { - storage->info.render_material_switch_count++; + storage->info.render.material_switch_count++; rebind = _setup_material(material, p_alpha_pass); if (rebind) { - storage->info.render_shader_rebind_count++; + storage->info.render.shader_rebind_count++; } } - - - if (!(e->sort_key & RenderList::SORT_KEY_UNSHADED_FLAG) && !p_directional_add && !p_shadow) { + if (!(e->sort_key & SORT_KEY_UNSHADED_FLAG) && !p_directional_add && !p_shadow) { _setup_light(e, p_view_transform); } if (e->owner != prev_owner || prev_base_type != e->instance->base_type || prev_geometry != e->geometry) { - _setup_geometry(e); - storage->info.render_surface_switch_count++; + _setup_geometry(e, p_view_transform); + storage->info.render.surface_switch_count++; } _set_cull(e->sort_key & RenderList::SORT_KEY_MIRROR_FLAG, p_reverse_cull); state.scene_shader.set_uniform(SceneShaderGLES3::NORMAL_MULT, e->instance->mirror ? -1.0 : 1.0); - - _setup_transform(e->instance, p_view_transform, p_projection); + state.scene_shader.set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, e->instance->transform); _render_geometry(e); @@ -1861,6 +2114,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ prev_owner = e->owner; prev_shading = shading; prev_skeleton = skeleton; + prev_use_instancing = use_instancing; first = false; } @@ -1880,6 +2134,8 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_5, false); state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_13, false); state.scene_shader.set_conditional(SceneShaderGLES3::USE_GI_PROBES, false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_CONTACT_SHADOWS, false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_VERTEX_LIGHTING, false); } void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_shadow) { @@ -1887,6 +2143,10 @@ void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geo RasterizerStorageGLES3::Material *m = NULL; RID m_src = p_instance->material_override.is_valid() ? p_instance->material_override : (p_material >= 0 ? p_instance->materials[p_material] : p_geometry->material); + if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { + m_src = default_overdraw_material; + } + /* #ifdef DEBUG_ENABLED if (current_debug==VS::SCENARIO_DEBUG_OVERDRAW) { @@ -1899,7 +2159,7 @@ void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geo if (m_src.is_valid()) { m = storage->material_owner.getornull(m_src); - if (!m->shader) { + if (!m->shader || !m->shader->valid) { m = NULL; } } @@ -1910,32 +2170,48 @@ void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geo ERR_FAIL_COND(!m); - bool has_base_alpha = (m->shader->spatial.uses_alpha); - bool has_blend_alpha = m->shader->spatial.blend_mode != RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX || m->shader->spatial.ontop; + _add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_shadow); + + while (m->next_pass.is_valid()) { + m = storage->material_owner.getornull(m->next_pass); + if (!m) + break; + _add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_shadow); + } +} + +void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_shadow) { + + bool has_base_alpha = (p_material->shader->spatial.uses_alpha && !p_material->shader->spatial.uses_alpha_scissor) || p_material->shader->spatial.uses_screen_texture || p_material->shader->spatial.unshaded; + bool has_blend_alpha = p_material->shader->spatial.blend_mode != RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX || p_material->shader->spatial.ontop; bool has_alpha = has_base_alpha || has_blend_alpha; bool shadow = false; bool mirror = p_instance->mirror; - if (m->shader->spatial.cull_mode == RasterizerStorageGLES3::Shader::Spatial::CULL_MODE_FRONT) { + if (p_material->shader->spatial.cull_mode == RasterizerStorageGLES3::Shader::Spatial::CULL_MODE_FRONT) { mirror = !mirror; } - if (m->shader->spatial.uses_sss) { + if (p_material->shader->spatial.uses_sss) { state.used_sss = true; } + if (p_material->shader->spatial.uses_screen_texture) { + state.used_screen_texture = true; + } + if (p_shadow) { - if (has_blend_alpha || (has_base_alpha && m->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) + if (has_blend_alpha || (has_base_alpha && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) return; //bye - if (!m->shader->spatial.uses_vertex && !m->shader->spatial.uses_discard && m->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { + if (!p_material->shader->spatial.uses_alpha_scissor && !p_material->shader->spatial.writes_modelview_or_projection && !p_material->shader->spatial.uses_vertex && !p_material->shader->spatial.uses_discard && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { //shader does not use discard and does not write a vertex position, use generic material if (p_instance->cast_shadows == VS::SHADOW_CASTING_SETTING_DOUBLE_SIDED) - m = storage->material_owner.getptr(default_material_twosided); + p_material = storage->material_owner.getptr(default_material_twosided); else - m = storage->material_owner.getptr(default_material); + p_material = storage->material_owner.getptr(default_material); } has_alpha = false; @@ -1947,7 +2223,7 @@ void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geo return; e->geometry = p_geometry; - e->material = m; + e->material = p_material; e->instance = p_instance; e->owner = p_owner; e->sort_key = 0; @@ -1958,7 +2234,7 @@ void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geo } if (!p_shadow && directional_light && (directional_light->light_ptr->cull_mask & e->instance->layer_mask) == 0) { - e->sort_key |= RenderList::SORT_KEY_NO_DIRECTIONAL_FLAG; + e->sort_key |= SORT_KEY_NO_DIRECTIONAL_FLAG; } e->sort_key |= uint64_t(e->geometry->index) << RenderList::SORT_KEY_GEOMETRY_INDEX_SHIFT; @@ -1974,7 +2250,7 @@ void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geo e->sort_key |= uint64_t(e->material->index) << RenderList::SORT_KEY_MATERIAL_INDEX_SHIFT; e->sort_key |= uint64_t(e->instance->depth_layer) << RenderList::SORT_KEY_DEPTH_LAYER_SHIFT; - if (!has_blend_alpha && has_alpha && m->shader->spatial.depth_draw_mode == RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { + if (!has_blend_alpha && has_alpha && p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { //if nothing exists, add this element as opaque too RenderList::Element *oe = render_list.add_element(); @@ -1986,7 +2262,7 @@ void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geo } if (e->instance->gi_probe_instances.size()) { - e->sort_key |= RenderList::SORT_KEY_GI_PROBES_FLAG; + e->sort_key |= SORT_KEY_GI_PROBES_FLAG; } } @@ -2001,18 +2277,23 @@ void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geo //e->light_type=0xFF; // no lights! - if (shadow || m->shader->spatial.unshaded /*|| current_debug==VS::SCENARIO_DEBUG_SHADELESS*/) { + if (shadow || p_material->shader->spatial.unshaded || state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_UNSHADED) { + + e->sort_key |= SORT_KEY_UNSHADED_FLAG; + } + + if (!shadow && (p_material->shader->spatial.uses_vertex_lighting || storage->config.force_vertex_shading)) { - e->sort_key |= RenderList::SORT_KEY_UNSHADED_FLAG; + e->sort_key |= SORT_KEY_VERTEX_LIT_FLAG; } } -void RasterizerSceneGLES3::_draw_skybox(RasterizerStorageGLES3::SkyBox *p_skybox, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_scale) { +void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_scale, float p_energy) { - if (!p_skybox) + if (!p_sky) return; - RasterizerStorageGLES3::Texture *tex = storage->texture_owner.getornull(p_skybox->cubemap); + RasterizerStorageGLES3::Texture *tex = storage->texture_owner.getornull(p_sky->panorama); ERR_FAIL_COND(!tex); glActiveTexture(GL_TEXTURE0); @@ -2051,7 +2332,7 @@ void RasterizerSceneGLES3::_draw_skybox(RasterizerStorageGLES3::SkyBox *p_skybox }; - //skybox uv vectors + //sky uv vectors float vw, vh, zn; p_projection.get_viewport_size(vw, vh); zn = p_projection.get_z_near(); @@ -2068,21 +2349,24 @@ void RasterizerSceneGLES3::_draw_skybox(RasterizerStorageGLES3::SkyBox *p_skybox vertices[i * 2 + 1].z = -vertices[i * 2 + 1].z; } - glBindBuffer(GL_ARRAY_BUFFER, state.skybox_verts); + glBindBuffer(GL_ARRAY_BUFFER, state.sky_verts); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vector3) * 8, vertices); glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind - glBindVertexArray(state.skybox_array); + glBindVertexArray(state.sky_array); - storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_CUBEMAP, true); + storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_PANORAMA, true); + storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_MULTIPLIER, true); storage->shaders.copy.bind(); + storage->shaders.copy.set_uniform(CopyShaderGLES3::MULTIPLIER, p_energy); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glBindVertexArray(0); glColorMask(1, 1, 1, 1); - storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_CUBEMAP, false); + storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_MULTIPLIER, false); + storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_PANORAMA, false); } void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform) { @@ -2093,10 +2377,9 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatr store_transform(p_cam_transform.affine_inverse(), state.ubo_data.camera_inverse_matrix); //time global variables - for (int i = 0; i < 4; i++) { - state.ubo_data.time[i] = storage->frame.time[i]; - } + state.ubo_data.time = storage->frame.time[0]; + state.ubo_data.z_far = p_cam_projection.get_z_far(); //bg and ambient if (env) { state.ubo_data.bg_energy = env->bg_energy; @@ -2126,8 +2409,32 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatr state.ubo_data.bg_color[2] = bg_color.b; state.ubo_data.bg_color[3] = bg_color.a; - state.env_radiance_data.ambient_contribution = env->ambient_skybox_contribution; + state.env_radiance_data.ambient_contribution = env->ambient_sky_contribution; state.ubo_data.ambient_occlusion_affect_light = env->ssao_light_affect; + + //fog + + Color linear_fog = env->fog_color.to_linear(); + state.ubo_data.fog_color_enabled[0] = linear_fog.r; + state.ubo_data.fog_color_enabled[1] = linear_fog.g; + state.ubo_data.fog_color_enabled[2] = linear_fog.b; + state.ubo_data.fog_color_enabled[3] = env->fog_enabled ? 1.0 : 0.0; + + Color linear_sun = env->fog_sun_color.to_linear(); + state.ubo_data.fog_sun_color_amount[0] = linear_sun.r; + state.ubo_data.fog_sun_color_amount[1] = linear_sun.g; + state.ubo_data.fog_sun_color_amount[2] = linear_sun.b; + state.ubo_data.fog_sun_color_amount[3] = env->fog_sun_amount; + state.ubo_data.fog_depth_enabled = env->fog_depth_enabled; + state.ubo_data.fog_depth_begin = env->fog_depth_begin; + state.ubo_data.fog_depth_curve = env->fog_depth_curve; + state.ubo_data.fog_transmit_enabled = env->fog_transmit_enabled; + state.ubo_data.fog_transmit_curve = env->fog_transmit_curve; + state.ubo_data.fog_height_enabled = env->fog_height_enabled; + state.ubo_data.fog_height_min = env->fog_height_min; + state.ubo_data.fog_height_max = env->fog_height_max; + state.ubo_data.fog_height_curve = env->fog_height_curve; + } else { state.ubo_data.bg_energy = 1.0; state.ubo_data.ambient_energy = 1.0; @@ -2145,6 +2452,8 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatr state.env_radiance_data.ambient_contribution = 0; state.ubo_data.ambient_occlusion_affect_light = 0; + + state.ubo_data.fog_color_enabled[3] = 0.0; } { @@ -2227,8 +2536,8 @@ void RasterizerSceneGLES3::_setup_directional_light(int p_index, const Transform for (int j = 0; j < shadow_count; j++) { - uint32_t x = li->directional_rect.pos.x; - uint32_t y = li->directional_rect.pos.y; + uint32_t x = li->directional_rect.position.x; + uint32_t y = li->directional_rect.position.y; uint32_t width = li->directional_rect.size.x; uint32_t height = li->directional_rect.size.y; @@ -2273,8 +2582,8 @@ void RasterizerSceneGLES3::_setup_directional_light(int p_index, const Transform store_camera(shadow_mtx, &ubo_data.shadow_matrix1[16 * j]); - ubo_data.light_clamp[0] = atlas_rect.pos.x; - ubo_data.light_clamp[1] = atlas_rect.pos.y; + ubo_data.light_clamp[0] = atlas_rect.position.x; + ubo_data.light_clamp[1] = atlas_rect.position.y; ubo_data.light_clamp[2] = atlas_rect.size.x; ubo_data.light_clamp[3] = atlas_rect.size.y; } @@ -2463,8 +2772,8 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result, int p_light_c Rect2 rect(float(x) / atlas_size, float(y) / atlas_size, float(width) / atlas_size, float(height) / atlas_size); ubo_data.light_params[3] = 1.0; //means it has shadow - ubo_data.light_clamp[0] = rect.pos.x; - ubo_data.light_clamp[1] = rect.pos.y; + ubo_data.light_clamp[0] = rect.position.x; + ubo_data.light_clamp[1] = rect.position.y; ubo_data.light_clamp[2] = rect.size.x; ubo_data.light_clamp[3] = rect.size.y; @@ -2570,7 +2879,7 @@ void RasterizerSceneGLES3::_setup_reflections(RID *p_reflection_probe_cull_resul ambient_linear.r *= p_env->ambient_energy; ambient_linear.g *= p_env->ambient_energy; ambient_linear.b *= p_env->ambient_energy; - contrib = p_env->ambient_skybox_contribution; + contrib = p_env->ambient_sky_contribution; } reflection_ubo.ambient[0] = ambient_linear.r; @@ -2588,7 +2897,7 @@ void RasterizerSceneGLES3::_setup_reflections(RID *p_reflection_probe_cull_resul reflection_ubo.atlas_clamp[0] = float(x) / reflection_atlas->size; reflection_ubo.atlas_clamp[1] = float(y) / reflection_atlas->size; reflection_ubo.atlas_clamp[2] = float(width) / reflection_atlas->size; - reflection_ubo.atlas_clamp[3] = float(height / 2) / reflection_atlas->size; + reflection_ubo.atlas_clamp[3] = float(height) / reflection_atlas->size; Transform proj = (p_camera_inverse_transform * rpi->transform).inverse(); store_transform(proj, reflection_ubo.local_matrix); @@ -2608,7 +2917,19 @@ void RasterizerSceneGLES3::_setup_reflections(RID *p_reflection_probe_cull_resul glBindBufferBase(GL_UNIFORM_BUFFER, 6, state.reflection_array_ubo); } -void RasterizerSceneGLES3::_copy_screen() { +void RasterizerSceneGLES3::_copy_screen(bool p_invalidate_color, bool p_invalidate_depth) { + +#ifndef GLES_OVER_GL + if (p_invalidate_color) { + + GLenum attachments[2] = { + GL_COLOR_ATTACHMENT0, + GL_DEPTH_STENCIL_ATTACHMENT + }; + + glInvalidateFramebuffer(GL_FRAMEBUFFER, p_invalidate_depth ? 2 : 1, attachments); + } +#endif glBindVertexArray(storage->resources.quadie_array); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -2681,6 +3002,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p current_geometry_index = 0; current_material_index = 0; state.used_sss = false; + state.used_screen_texture = false; //fill list @@ -2729,11 +3051,73 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p } break; case VS::INSTANCE_IMMEDIATE: { + RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getptr(inst->base); + ERR_CONTINUE(!immediate); + + _add_geometry(immediate, inst, NULL, -1, p_shadow); + + } break; + case VS::INSTANCE_PARTICLES: { + + RasterizerStorageGLES3::Particles *particles = storage->particles_owner.getptr(inst->base); + ERR_CONTINUE(!particles); + + for (int i = 0; i < particles->draw_passes.size(); i++) { + + RID pmesh = particles->draw_passes[i]; + if (!pmesh.is_valid()) + continue; + RasterizerStorageGLES3::Mesh *mesh = storage->mesh_owner.get(pmesh); + if (!mesh) + continue; //mesh not assigned + + int ssize = mesh->surfaces.size(); + + for (int j = 0; j < ssize; j++) { + + RasterizerStorageGLES3::Surface *s = mesh->surfaces[j]; + _add_geometry(s, inst, particles, -1, p_shadow); + } + } + } break; } } } +void RasterizerSceneGLES3::_blur_effect_buffer() { + + //blur diffuse into effect mipmaps using separatable convolution + //storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true); + for (int i = 0; i < storage->frame.current_rt->effects.mip_maps[1].sizes.size(); i++) { + + int vp_w = storage->frame.current_rt->effects.mip_maps[1].sizes[i].width; + int vp_h = storage->frame.current_rt->effects.mip_maps[1].sizes[i].height; + glViewport(0, 0, vp_w, vp_h); + //horizontal pass + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_HORIZONTAL, true); + state.effect_blur_shader.bind(); + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h)); + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i)); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); //previous level, since mipmaps[0] starts one level bigger + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[1].sizes[i].fbo); + _copy_screen(true); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_HORIZONTAL, false); + + //vertical pass + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_VERTICAL, true); + state.effect_blur_shader.bind(); + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h)); + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i)); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[1].color); + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[i + 1].fbo); //next level, since mipmaps[0] starts one level bigger + _copy_screen(true); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_VERTICAL, false); + } +} + void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_cam_projection) { glDepthMask(GL_FALSE); @@ -2777,7 +3161,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_ glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.ssao.depth_mipmap_fbos[i]); //copy to front first glViewport(0, 0, ss[0], ss[1]); - _copy_screen(); + _copy_screen(true); } ss[0] = storage->frame.current_rt->width; ss[1] = storage->frame.current_rt->height; @@ -2829,7 +3213,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_ Color white(1, 1, 1, 1); glClearBufferfv(GL_COLOR, 0, white.components); // specular - _copy_screen(); + _copy_screen(true); //do the batm, i mean blur @@ -2850,7 +3234,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_ if (i == 0) { glClearBufferfv(GL_COLOR, 0, white.components); // specular } - _copy_screen(); + _copy_screen(true); } } @@ -2867,7 +3251,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_ glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.ssao.blur_red[0]); //previous level, since mipmaps[0] starts one level bigger glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level - _copy_screen(); + _copy_screen(true); state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SSAO_MERGE, false); } else { @@ -2888,8 +3272,8 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_ //copy normal and roughness to effect buffer glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); glReadBuffer(GL_COLOR_ATTACHMENT3); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->buffers.effect_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_NEAREST); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->effects.ssao.blur_fbo[0]); + 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_LINEAR); state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_11_SAMPLES, subsurface_scatter_quality == SSS_QUALITY_LOW); state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_17_SAMPLES, subsurface_scatter_quality == SSS_QUALITY_MEDIUM); @@ -2905,21 +3289,29 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_ glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //disable filter (fixes bugs on AMD) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->buffers.effect); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.ssao.blur_red[0]); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); //copy to front first - _copy_screen(); + _copy_screen(true); glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::DIR, Vector2(0, 1)); glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level - _copy_screen(); + _copy_screen(true); + + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); //restore filter + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); } if (env->ssr_enabled) { @@ -2932,38 +3324,11 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_ //blur diffuse into effect mipmaps using separatable convolution //storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true); - for (int i = 0; i < storage->frame.current_rt->effects.mip_maps[1].sizes.size(); i++) { - - int vp_w = storage->frame.current_rt->effects.mip_maps[1].sizes[i].width; - int vp_h = storage->frame.current_rt->effects.mip_maps[1].sizes[i].height; - glViewport(0, 0, vp_w, vp_h); - //horizontal pass - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_HORIZONTAL, true); - state.effect_blur_shader.bind(); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h)); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i)); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); //previous level, since mipmaps[0] starts one level bigger - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[1].sizes[i].fbo); - _copy_screen(); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_HORIZONTAL, false); - - //vertical pass - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_VERTICAL, true); - state.effect_blur_shader.bind(); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h)); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i)); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[1].color); - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[i + 1].fbo); //next level, since mipmaps[0] starts one level bigger - _copy_screen(); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_VERTICAL, false); - } + _blur_effect_buffer(); //perform SSR - state.ssr_shader.set_conditional(ScreenSpaceReflectionShaderGLES3::SMOOTH_ACCEL, env->ssr_accel > 0 && env->ssr_smooth); - state.ssr_shader.set_conditional(ScreenSpaceReflectionShaderGLES3::REFLECT_ROUGHNESS, env->ssr_accel > 0 && env->ssr_roughness); + state.ssr_shader.set_conditional(ScreenSpaceReflectionShaderGLES3::REFLECT_ROUGHNESS, env->ssr_roughness); state.ssr_shader.bind(); @@ -2979,9 +3344,9 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_ //state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::FRAME_INDEX,int(render_pass)); state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::FILTER_MIPMAP_LEVELS, float(storage->frame.current_rt->effects.mip_maps[0].sizes.size())); state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::NUM_STEPS, env->ssr_max_steps); - state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::ACCELERATION, env->ssr_accel); state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::DEPTH_TOLERANCE, env->ssr_depth_tolerance); - state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::DISTANCE_FADE, env->ssr_fade); + state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::DISTANCE_FADE, env->ssr_fade_out); + state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::CURVE_FADE_IN, env->ssr_fade_in); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); @@ -2994,7 +3359,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_ glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[1].sizes[0].fbo); glViewport(0, 0, ssr_w, ssr_h); - _copy_screen(); + _copy_screen(true); glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); } @@ -3011,6 +3376,8 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_ //copy reflection over diffuse, resolving SSR if needed state.resolve_shader.set_conditional(ResolveShaderGLES3::USE_SSR, env->ssr_enabled); state.resolve_shader.bind(); + state.resolve_shader.set_uniform(ResolveShaderGLES3::PIXEL_SIZE, Vector2(1.0 / storage->frame.current_rt->width, 1.0 / storage->frame.current_rt->height)); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); if (env->ssr_enabled) { @@ -3023,10 +3390,17 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_ glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_ONE, GL_ONE); //use additive to accumulate one over the other - _copy_screen(); + _copy_screen(true); glDisable(GL_BLEND); //end additive + if (state.used_screen_texture) { + _blur_effect_buffer(); + //restored framebuffer + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); + glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); + } + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SIMPLE_COPY, true); state.effect_blur_shader.bind(); state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(0)); @@ -3040,7 +3414,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_ glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); - _copy_screen(); + _copy_screen(true); state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SIMPLE_COPY, false); } @@ -3061,27 +3435,32 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p //copy specular to front buffer //copy diffuse to effect buffer - glReadBuffer(GL_COLOR_ATTACHMENT0); - glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].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_NEAREST); + if (storage->frame.current_rt->buffers.active) { + //transfer to effect buffer if using buffers, also resolve MSAA + glReadBuffer(GL_COLOR_ATTACHMENT0); + glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].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_NEAREST); - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + } - if (!env) { - //no environment, simply return and convert to SRGB + if (!env || storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + //no environment or transparent render, simply return and convert to SRGB glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, true); - storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, true); + storage->shaders.copy.set_conditional(CopyShaderGLES3::V_FLIP, storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]); + storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]); storage->shaders.copy.bind(); - _copy_screen(); + _copy_screen(true); storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, false); storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false); //compute luminance + storage->shaders.copy.set_conditional(CopyShaderGLES3::V_FLIP, false); return; } @@ -3133,7 +3512,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); //copy to front first - _copy_screen(); + _copy_screen(true); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); @@ -3142,7 +3521,6 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p _copy_screen(); state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_FAR_BLUR, false); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_FAR_BLUR, false); state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW, false); state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM, false); state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH, false); @@ -3220,7 +3598,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->buffers.diffuse); } - _copy_screen(); + _copy_screen(true); if (composite_from != storage->frame.current_rt->buffers.diffuse) { @@ -3237,6 +3615,16 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p composite_from = storage->frame.current_rt->effects.mip_maps[0].color; } + if (env->dof_blur_near_enabled || env->dof_blur_far_enabled) { + //these needed to disable filtering, reenamble + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + if (env->auto_exposure) { //compute auto exposure @@ -3255,12 +3643,12 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p glUniform2iv(state.exposure_shader.get_uniform(ExposureShaderGLES3::SOURCE_RENDER_SIZE), 1, ss); glUniform2iv(state.exposure_shader.get_uniform(ExposureShaderGLES3::TARGET_SIZE), 1, ds); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->buffers.diffuse); + glBindTexture(GL_TEXTURE_2D, composite_from); glBindFramebuffer(GL_FRAMEBUFFER, exposure_shrink[0].fbo); glViewport(0, 0, exposure_shrink_size, exposure_shrink_size); - _copy_screen(); + _copy_screen(true); //second step, shrink to 2x2 pixels state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_BEGIN, false); @@ -3304,7 +3692,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p state.exposure_shader.set_uniform(ExposureShaderGLES3::MAX_LUMINANCE, env->auto_exposure_max); state.exposure_shader.set_uniform(ExposureShaderGLES3::MIN_LUMINANCE, env->auto_exposure_min); - _copy_screen(); + _copy_screen(true); state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_FORCE_SET, false); state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_END, false); @@ -3368,14 +3756,14 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->exposure.color); state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_BLOOM, env->glow_bloom); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_HDR_TRESHOLD, env->glow_hdr_bleed_treshold); + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_HDR_THRESHOLD, env->glow_hdr_bleed_threshold); state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_HDR_SCALE, env->glow_hdr_bleed_scale); } else { glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); //previous level, since mipmaps[0] starts one level bigger } glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[1].sizes[i].fbo); - _copy_screen(); + _copy_screen(true); state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_GAUSSIAN_HORIZONTAL, false); state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_FIRST_PASS, false); state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_USE_AUTO_EXPOSURE, false); @@ -3444,6 +3832,18 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); } + if (env->adjustments_enabled) { + + state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_BCS, true); + RasterizerStorageGLES3::Texture *tex = storage->texture_owner.getornull(env->color_correction); + if (tex) { + state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_COLOR_CORRECTION, true); + glActiveTexture(GL_TEXTURE3); + glBindTexture(tex->target, tex->tex_id); + } + } + + state.tonemap_shader.set_conditional(TonemapShaderGLES3::V_FLIP, storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]); state.tonemap_shader.bind(); state.tonemap_shader.set_uniform(TonemapShaderGLES3::EXPOSURE, env->tone_mapper_exposure); @@ -3466,7 +3866,12 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p state.tonemap_shader.set_uniform(TonemapShaderGLES3::AUTO_EXPOSURE_GREY, env->auto_exposure_grey); } - _copy_screen(); + if (env->adjustments_enabled) { + + state.tonemap_shader.set_uniform(TonemapShaderGLES3::BCS, Vector3(env->adjustments_brightness, env->adjustments_contrast, env->adjustments_saturation)); + } + + _copy_screen(true, true); //turn off everything used state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_AUTO_EXPOSURE, false); @@ -3484,6 +3889,9 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_SCREEN, false); state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_SOFTLIGHT, false); state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_FILTER_BICUBIC, false); + state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_BCS, false); + state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_COLOR_CORRECTION, false); + state.tonemap_shader.set_conditional(TonemapShaderGLES3::V_FLIP, false); } void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) { @@ -3493,12 +3901,14 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const //fill up ubo + storage->info.render.object_count += p_cull_count; + Environment *env = environment_owner.getornull(p_environment); ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_reflection_atlas); if (shadow_atlas && shadow_atlas->size) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 5); glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS); @@ -3507,7 +3917,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const } if (reflection_atlas && reflection_atlas->size) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 5); + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); glBindTexture(GL_TEXTURE_2D, reflection_atlas->color); } @@ -3519,8 +3929,8 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const state.ubo_data.subsurface_scatter_width = subsurface_scatter_size; - state.ubo_data.shadow_z_offset = 0; - state.ubo_data.shadow_slope_scale = 0; + state.ubo_data.z_offset = 0; + state.ubo_data.z_slope_scale = 0; state.ubo_data.shadow_dual_paraboloid_render_side = 0; state.ubo_data.shadow_dual_paraboloid_render_zfar = 0; @@ -3537,7 +3947,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const state.used_contact_shadows = true; - if (storage->frame.current_rt && true) { //detect with state.used_contact_shadows too + if (!storage->config.no_depth_prepass && storage->frame.current_rt && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { //detect with state.used_contact_shadows too //pre z pass glDisable(GL_BLEND); @@ -3551,7 +3961,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const glColorMask(0, 0, 0, 0); glClearDepth(1.0f); - glClear(GL_DEPTH_BUFFER_BIT); + glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); render_list.clear(); _fill_render_list(p_cull_result, p_cull_count, true); @@ -3571,12 +3981,15 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); //bind depth for read - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 9); + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 8); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth); } fb_cleared = true; render_pass++; + state.using_contact_shadows = true; + } else { + state.using_contact_shadows = false; } _setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_cam_projection, p_shadow_atlas); @@ -3624,7 +4037,12 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const } else { - use_mrt = state.used_sss || (env && (env->ssao_enabled || env->ssr_enabled)); //only enable MRT rendering if any of these is enabled + use_mrt = env && (state.used_sss || env->ssao_enabled || env->ssr_enabled); //only enable MRT rendering if any of these is enabled + //effects disabled and transparency also prevent using MRTs + use_mrt = use_mrt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]; + use_mrt = use_mrt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS]; + use_mrt = use_mrt && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW; + use_mrt = use_mrt && env && (env->bg_mode != VS::ENV_BG_KEEP && env->bg_mode != VS::ENV_BG_CANVAS); glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); @@ -3653,8 +4071,13 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const } else { - current_fbo = storage->frame.current_rt->buffers.fbo; - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); + if (storage->frame.current_rt->buffers.active) { + current_fbo = storage->frame.current_rt->buffers.fbo; + } else { + current_fbo = storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo; + } + + glBindFramebuffer(GL_FRAMEBUFFER, current_fbo); state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS, false); Vector<GLenum> draw_buffers; @@ -3664,16 +4087,22 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const } if (!fb_cleared) { - glClearDepth(1.0f); - glClear(GL_DEPTH_BUFFER_BIT); + glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0, 0); } Color clear_color(0, 0, 0, 0); - RasterizerStorageGLES3::SkyBox *skybox = NULL; + RasterizerStorageGLES3::Sky *sky = NULL; GLuint env_radiance_tex = 0; - if (!env || env->bg_mode == VS::ENV_BG_CLEAR_COLOR) { + if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { + clear_color = Color(0, 0, 0, 0); + storage->frame.clear_request = false; + } else if (!probe && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + clear_color = Color(0, 0, 0, 0); + storage->frame.clear_request = false; + + } else if (!env || env->bg_mode == VS::ENV_BG_CLEAR_COLOR) { if (storage->frame.clear_request) { @@ -3681,16 +4110,20 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const storage->frame.clear_request = false; } + } else if (env->bg_mode == VS::ENV_BG_CANVAS) { + + clear_color = env->bg_color.to_linear(); + storage->frame.clear_request = false; } else if (env->bg_mode == VS::ENV_BG_COLOR) { clear_color = env->bg_color.to_linear(); storage->frame.clear_request = false; - } else if (env->bg_mode == VS::ENV_BG_SKYBOX) { + } else if (env->bg_mode == VS::ENV_BG_SKY) { - skybox = storage->skybox_owner.getornull(env->skybox); + sky = storage->sky_owner.getornull(env->sky); - if (skybox) { - env_radiance_tex = skybox->radiance; + if (sky) { + env_radiance_tex = sky->radiance; } storage->frame.clear_request = false; @@ -3698,28 +4131,54 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const storage->frame.clear_request = false; } - glClearBufferfv(GL_COLOR, 0, clear_color.components); // specular + if (!env || env->bg_mode != VS::ENV_BG_KEEP) { + glClearBufferfv(GL_COLOR, 0, clear_color.components); // specular + } - state.texscreen_copied = false; + if (env && env->bg_mode == VS::ENV_BG_CANVAS) { + //copy canvas to 3d buffer and convert it to linear - glBlendEquation(GL_FUNC_ADD); + glDisable(GL_BLEND); + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); - if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } else { - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); + + storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, true); + + storage->shaders.copy.set_conditional(CopyShaderGLES3::SRGB_TO_LINEAR, true); + + storage->shaders.copy.bind(); + + _copy_screen(true, true); + + //turn off everything used + storage->shaders.copy.set_conditional(CopyShaderGLES3::SRGB_TO_LINEAR, false); + storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false); + + //restore + glEnable(GL_BLEND); + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); } - glDisable(GL_BLEND); + state.texscreen_copied = false; - render_list.sort_by_key(false); + glBlendEquation(GL_FUNC_ADD); if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); } else { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_BLEND); } + render_list.sort_by_key(false); + if (state.directional_light_count == 0) { directional_light = NULL; _render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, env_radiance_tex, false, false, false, false, shadow_atlas != NULL); @@ -3741,14 +4200,14 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const glDrawBuffers(1, &gldb); } - if (env && env->bg_mode == VS::ENV_BG_SKYBOX) { + if (env && env->bg_mode == VS::ENV_BG_SKY && (!storage->frame.current_rt || (!storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT] && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW))) { /* if (use_mrt) { - glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo); //switch to alpha fbo for skybox, only diffuse/ambient matters + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo); //switch to alpha fbo for sky, only diffuse/ambient matters */ - _draw_skybox(skybox, p_cam_projection, p_cam_transform, storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP], env->skybox_scale); + _draw_sky(sky, p_cam_projection, p_cam_transform, false, env->sky_scale, env->bg_energy); } //_render_list_forward(&alpha_render_list,camera_transform,camera_transform_inverse,camera_projection,false,fragment_lighting,true); @@ -3758,6 +4217,25 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const if (use_mrt) { _render_mrts(env, p_cam_projection); + } else { + //FIXME: check that this is possible to use + if (storage->frame.current_rt && storage->frame.current_rt->buffers.active && state.used_screen_texture) { + glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].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); + _blur_effect_buffer(); + //restored framebuffer + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); + glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); + } + } + + if (storage->frame.current_rt && state.used_screen_texture && storage->frame.current_rt->buffers.active) { + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 7); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); } glEnable(GL_BLEND); @@ -3765,7 +4243,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const glEnable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); - render_list.sort_by_depth(true); + render_list.sort_by_reverse_depth(true); if (state.directional_light_count == 0) { directional_light = NULL; @@ -3830,153 +4308,14 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const storage->canvas->canvas_begin(); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, env_radiance_tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } -#if 0 - if (use_fb) { - - - - for(int i=0;i<VS::ARRAY_MAX;i++) { - glDisableVertexAttribArray(i); - } - glBindBuffer(GL_ARRAY_BUFFER,0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); - glDisable(GL_BLEND); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - glDisable(GL_SCISSOR_TEST); - glDepthMask(false); - - if (current_env && current_env->fx_enabled[VS::ENV_FX_HDR]) { - - int hdr_tm = current_env->fx_param[VS::ENV_FX_PARAM_HDR_TONEMAPPER]; - switch(hdr_tm) { - case VS::ENV_FX_HDR_TONE_MAPPER_LINEAR: { - - - } break; - case VS::ENV_FX_HDR_TONE_MAPPER_LOG: { - copy_shader.set_conditional(CopyShaderGLES2::USE_LOG_TONEMAPPER,true); - - } break; - case VS::ENV_FX_HDR_TONE_MAPPER_REINHARDT: { - copy_shader.set_conditional(CopyShaderGLES2::USE_REINHARDT_TONEMAPPER,true); - } break; - case VS::ENV_FX_HDR_TONE_MAPPER_REINHARDT_AUTOWHITE: { - - copy_shader.set_conditional(CopyShaderGLES2::USE_REINHARDT_TONEMAPPER,true); - copy_shader.set_conditional(CopyShaderGLES2::USE_AUTOWHITE,true); - } break; - } - - - _process_hdr(); - } - if (current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]) { - _process_glow_bloom(); - int glow_transfer_mode=current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_BLEND_MODE]; - if (glow_transfer_mode==1) - copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SCREEN,true); - if (glow_transfer_mode==2) - copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SOFTLIGHT,true); - } - - glBindFramebuffer(GL_FRAMEBUFFER, current_rt?current_rt->fbo:base_framebuffer); - - Size2 size; - if (current_rt) { - glBindFramebuffer(GL_FRAMEBUFFER, current_rt->fbo); - glViewport( 0,0,viewport.width,viewport.height); - size=Size2(viewport.width,viewport.height); - } else { - glBindFramebuffer(GL_FRAMEBUFFER, base_framebuffer); - glViewport( viewport.x, window_size.height-(viewport.height+viewport.y), viewport.width,viewport.height ); - size=Size2(viewport.width,viewport.height); - } - - //time to copy!!! - copy_shader.set_conditional(CopyShaderGLES2::USE_BCS,current_env && current_env->fx_enabled[VS::ENV_FX_BCS]); - copy_shader.set_conditional(CopyShaderGLES2::USE_SRGB,current_env && current_env->fx_enabled[VS::ENV_FX_SRGB]); - copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW,current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]); - copy_shader.set_conditional(CopyShaderGLES2::USE_HDR,current_env && current_env->fx_enabled[VS::ENV_FX_HDR]); - copy_shader.set_conditional(CopyShaderGLES2::USE_NO_ALPHA,true); - copy_shader.set_conditional(CopyShaderGLES2::USE_FXAA,current_env && current_env->fx_enabled[VS::ENV_FX_FXAA]); - - copy_shader.bind(); - //copy_shader.set_uniform(CopyShaderGLES2::SOURCE,0); - - if (current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]) { - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, framebuffer.blur[0].color ); - glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::GLOW_SOURCE),1); - - } - - if (current_env && current_env->fx_enabled[VS::ENV_FX_HDR]) { - - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, current_vd->lum_color ); - glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::HDR_SOURCE),2); - copy_shader.set_uniform(CopyShaderGLES2::TONEMAP_EXPOSURE,float(current_env->fx_param[VS::ENV_FX_PARAM_HDR_EXPOSURE])); - copy_shader.set_uniform(CopyShaderGLES2::TONEMAP_WHITE,float(current_env->fx_param[VS::ENV_FX_PARAM_HDR_WHITE])); - - } - - if (current_env && current_env->fx_enabled[VS::ENV_FX_FXAA]) - copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,Size2(1.0/size.x,1.0/size.y)); - - - if (current_env && current_env->fx_enabled[VS::ENV_FX_BCS]) { - - Vector3 bcs; - bcs.x=current_env->fx_param[VS::ENV_FX_PARAM_BCS_BRIGHTNESS]; - bcs.y=current_env->fx_param[VS::ENV_FX_PARAM_BCS_CONTRAST]; - bcs.z=current_env->fx_param[VS::ENV_FX_PARAM_BCS_SATURATION]; - copy_shader.set_uniform(CopyShaderGLES2::BCS,bcs); - } - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, framebuffer.color ); - glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE),0); - - _copy_screen_quad(); - - copy_shader.set_conditional(CopyShaderGLES2::USE_BCS,false); - copy_shader.set_conditional(CopyShaderGLES2::USE_SRGB,false); - copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW,false); - copy_shader.set_conditional(CopyShaderGLES2::USE_HDR,false); - copy_shader.set_conditional(CopyShaderGLES2::USE_NO_ALPHA,false); - copy_shader.set_conditional(CopyShaderGLES2::USE_FXAA,false); - copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SCREEN,false); - copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SOFTLIGHT,false); - copy_shader.set_conditional(CopyShaderGLES2::USE_REINHARDT_TONEMAPPER,false); - copy_shader.set_conditional(CopyShaderGLES2::USE_AUTOWHITE,false); - copy_shader.set_conditional(CopyShaderGLES2::USE_LOG_TONEMAPPER,false); - - state.scene_shader.set_conditional(SceneShaderGLES3::USE_8BIT_HDR,false); - - - if (current_env && current_env->fx_enabled[VS::ENV_FX_HDR] && GLOBAL_DEF("rasterizer/debug_hdr",false)) { - _debug_luminances(); - } - } - - current_env=NULL; - current_debug=VS::SCENARIO_DEBUG_DISABLED; - if (GLOBAL_DEF("rasterizer/debug_shadow_maps",false)) { - _debug_shadows(); - } - //_debug_luminances(); - //_debug_samplers(); - - if (using_canvas_bg) { - using_canvas_bg=false; - glColorMask(1,1,1,1); //don't touch alpha - } -#endif + //disable all stuff } void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) { @@ -4001,6 +4340,8 @@ void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_ float bias = 0; float normal_bias = 0; + state.using_contact_shadows = false; + CameraMatrix light_projection; Transform light_transform; @@ -4017,15 +4358,15 @@ void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_ } else if (directional_shadow.light_count == 2) { light_instance->directional_rect = Rect2(0, 0, directional_shadow.size, directional_shadow.size / 2); if (light_instance->light_directional_index == 1) { - light_instance->directional_rect.pos.x += light_instance->directional_rect.size.x; + light_instance->directional_rect.position.x += light_instance->directional_rect.size.x; } } else { //3 and 4 light_instance->directional_rect = Rect2(0, 0, directional_shadow.size / 2, directional_shadow.size / 2); if (light_instance->light_directional_index & 1) { - light_instance->directional_rect.pos.x += light_instance->directional_rect.size.x; + light_instance->directional_rect.position.x += light_instance->directional_rect.size.x; } if (light_instance->light_directional_index / 2) { - light_instance->directional_rect.pos.y += light_instance->directional_rect.size.y; + light_instance->directional_rect.position.y += light_instance->directional_rect.size.y; } } } @@ -4033,8 +4374,8 @@ void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_ light_projection = light_instance->shadow_transform[p_pass].camera; light_transform = light_instance->shadow_transform[p_pass].transform; - x = light_instance->directional_rect.pos.x; - y = light_instance->directional_rect.pos.y; + x = light_instance->directional_rect.position.x; + y = light_instance->directional_rect.position.y; width = light_instance->directional_rect.size.x; height = light_instance->directional_rect.size.y; @@ -4066,8 +4407,8 @@ void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_ } zfar = light->param[VS::LIGHT_PARAM_RANGE]; - bias = light->param[VS::LIGHT_PARAM_SHADOW_BIAS]; - normal_bias = light->param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS]; + bias = light->param[VS::LIGHT_PARAM_SHADOW_BIAS] * light_instance->shadow_transform[p_pass].bias_scale; + normal_bias = light->param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] * light_instance->shadow_transform[p_pass].bias_scale; fbo = directional_shadow.fbo; vp_height = directional_shadow.size; @@ -4185,8 +4526,8 @@ void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_ glClear(GL_DEPTH_BUFFER_BIT); glDisable(GL_SCISSOR_TEST); - state.ubo_data.shadow_z_offset = bias; - state.ubo_data.shadow_slope_scale = normal_bias; + state.ubo_data.z_offset = bias; + state.ubo_data.z_slope_scale = normal_bias; state.ubo_data.shadow_dual_paraboloid_render_side = dp_direction; state.ubo_data.shadow_dual_paraboloid_render_zfar = zfar; @@ -4298,135 +4639,39 @@ bool RasterizerSceneGLES3::free(RID p_rid) { return true; } -// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html -static _FORCE_INLINE_ float radicalInverse_VdC(uint32_t bits) { - bits = (bits << 16u) | (bits >> 16u); - bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); - bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); - bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); - bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); - return float(bits) * 2.3283064365386963e-10f; // / 0x100000000 -} +void RasterizerSceneGLES3::set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw) { -static _FORCE_INLINE_ Vector2 Hammersley(uint32_t i, uint32_t N) { - return Vector2(float(i) / float(N), radicalInverse_VdC(i)); + state.debug_draw = p_debug_draw; } -static _FORCE_INLINE_ Vector3 ImportanceSampleGGX(Vector2 Xi, float Roughness, Vector3 N) { - float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph] - - // Compute distribution direction - float Phi = 2.0f * Math_PI * Xi.x; - float CosTheta = Math::sqrt((float)(1.0f - Xi.y) / (1.0f + (a * a - 1.0f) * Xi.y)); - float SinTheta = Math::sqrt((float)Math::abs(1.0f - CosTheta * CosTheta)); - - // Convert to spherical direction - Vector3 H; - H.x = SinTheta * Math::cos(Phi); - H.y = SinTheta * Math::sin(Phi); - H.z = CosTheta; - - Vector3 UpVector = Math::abs(N.z) < 0.999 ? Vector3(0.0, 0.0, 1.0) : Vector3(1.0, 0.0, 0.0); - Vector3 TangentX = UpVector.cross(N); - TangentX.normalize(); - Vector3 TangentY = N.cross(TangentX); - - // Tangent to world space - return TangentX * H.x + TangentY * H.y + N * H.z; -} - -static _FORCE_INLINE_ float GGX(float NdotV, float a) { - float k = a / 2.0; - return NdotV / (NdotV * (1.0 - k) + k); -} - -// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html -float _FORCE_INLINE_ G_Smith(float a, float nDotV, float nDotL) { - return GGX(nDotL, a * a) * GGX(nDotV, a * a); -} - -void RasterizerSceneGLES3::_generate_brdf() { - - int brdf_size = GLOBAL_DEF("rendering/gles3/brdf_texture_size", 64); - - PoolVector<uint8_t> brdf; - brdf.resize(brdf_size * brdf_size * 2); - - PoolVector<uint8_t>::Write w = brdf.write(); - - for (int i = 0; i < brdf_size; i++) { - for (int j = 0; j < brdf_size; j++) { - - float Roughness = float(j) / (brdf_size - 1); - float NoV = float(i + 1) / (brdf_size); //avoid storing nov0 - - Vector3 V; - V.x = Math::sqrt(1.0f - NoV * NoV); - V.y = 0.0; - V.z = NoV; - - Vector3 N = Vector3(0.0, 0.0, 1.0); - - float A = 0; - float B = 0; - - for (int s = 0; s < 512; s++) { - - Vector2 xi = Hammersley(s, 512); - Vector3 H = ImportanceSampleGGX(xi, Roughness, N); - Vector3 L = 2.0 * V.dot(H) * H - V; +void RasterizerSceneGLES3::initialize() { - float NoL = CLAMP(L.z, 0.0, 1.0); - float NoH = CLAMP(H.z, 0.0, 1.0); - float VoH = CLAMP(V.dot(H), 0.0, 1.0); + render_pass = 0; - if (NoL > 0.0) { - float G = G_Smith(Roughness, NoV, NoL); - float G_Vis = G * VoH / (NoH * NoV); - float Fc = pow(1.0 - VoH, 5.0); + state.scene_shader.init(); - A += (1.0 - Fc) * G_Vis; - B += Fc * G_Vis; - } - } + { + //default material and shader - A /= 512.0; - B /= 512.0; + default_shader = storage->shader_create(); + storage->shader_set_code(default_shader, "shader_type spatial;\n"); + default_material = storage->material_create(); + storage->material_set_shader(default_material, default_shader); - int tofs = ((brdf_size - j - 1) * brdf_size + i) * 2; - w[tofs + 0] = CLAMP(A * 255, 0, 255); - w[tofs + 1] = CLAMP(B * 255, 0, 255); - } + default_shader_twosided = storage->shader_create(); + default_material_twosided = storage->material_create(); + storage->shader_set_code(default_shader_twosided, "shader_type spatial; render_mode cull_disabled;\n"); + storage->material_set_shader(default_material_twosided, default_shader_twosided); } - //set up brdf texture - - glGenTextures(1, &state.brdf_texture); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, state.brdf_texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, brdf_size, brdf_size, 0, GL_RG, GL_UNSIGNED_BYTE, w.ptr()); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glBindTexture(GL_TEXTURE_2D, 0); -} - -void RasterizerSceneGLES3::initialize() { - - render_pass = 0; - - state.scene_shader.init(); - - default_shader = storage->shader_create(VS::SHADER_SPATIAL); - default_material = storage->material_create(); - storage->material_set_shader(default_material, default_shader); + { + //default material and shader - default_shader_twosided = storage->shader_create(VS::SHADER_SPATIAL); - default_material_twosided = storage->material_create(); - storage->shader_set_code(default_shader_twosided, "render_mode cull_disabled;\n"); - storage->material_set_shader(default_material_twosided, default_shader_twosided); + default_overdraw_shader = storage->shader_create(); + storage->shader_set_code(default_overdraw_shader, "shader_type spatial;\nrender_mode blend_add,unshaded;\n void fragment() { ALBEDO=vec3(0.4,0.8,0.8); ALPHA=0.2; }"); + default_overdraw_material = storage->material_create(); + storage->material_set_shader(default_overdraw_material, default_overdraw_shader); + } glGenBuffers(1, &state.scene_ubo); glBindBuffer(GL_UNIFORM_BUFFER, state.scene_ubo); @@ -4438,7 +4683,7 @@ void RasterizerSceneGLES3::initialize() { glBufferData(GL_UNIFORM_BUFFER, sizeof(State::EnvironmentRadianceUBO), &state.env_radiance_ubo, GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); - render_list.max_elements = GLOBAL_DEF("rendering/gles3/max_renderable_elements", (int)RenderList::DEFAULT_MAX_ELEMENTS); + render_list.max_elements = GLOBAL_DEF("rendering/limits/rendering/max_renderable_elements", (int)RenderList::DEFAULT_MAX_ELEMENTS); if (render_list.max_elements > 1000000) render_list.max_elements = 1000000; if (render_list.max_elements < 1024) @@ -4447,14 +4692,14 @@ void RasterizerSceneGLES3::initialize() { { //quad buffers - glGenBuffers(1, &state.skybox_verts); - glBindBuffer(GL_ARRAY_BUFFER, state.skybox_verts); + glGenBuffers(1, &state.sky_verts); + glBindBuffer(GL_ARRAY_BUFFER, state.sky_verts); glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * 8, NULL, GL_DYNAMIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind - glGenVertexArrays(1, &state.skybox_array); - glBindVertexArray(state.skybox_array); - glBindBuffer(GL_ARRAY_BUFFER, state.skybox_verts); + glGenVertexArrays(1, &state.sky_array); + glBindVertexArray(state.sky_array); + glBindBuffer(GL_ARRAY_BUFFER, state.sky_verts); glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3) * 2, 0); glEnableVertexAttribArray(VS::ARRAY_VERTEX); glVertexAttribPointer(VS::ARRAY_TEX_UV, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3) * 2, ((uint8_t *)NULL) + sizeof(Vector3)); @@ -4464,7 +4709,6 @@ void RasterizerSceneGLES3::initialize() { } render_list.init(); state.cube_to_dp_shader.init(); - _generate_brdf(); shadow_atlas_realloc_tolerance_msec = 500; @@ -4513,7 +4757,7 @@ void RasterizerSceneGLES3::initialize() { { //directional light shadow directional_shadow.light_count = 0; - directional_shadow.size = nearest_power_of_2(GLOBAL_DEF("rendering/shadows/directional_shadow_size", 2048)); + directional_shadow.size = nearest_power_of_2(GLOBAL_GET("rendering/quality/directional_shadow/size")); glGenFramebuffers(1, &directional_shadow.fbo); glBindFramebuffer(GL_FRAMEBUFFER, directional_shadow.fbo); glGenTextures(1, &directional_shadow.depth); @@ -4539,7 +4783,7 @@ void RasterizerSceneGLES3::initialize() { const int ubo_light_size = 160; state.ubo_light_size = ubo_light_size; state.max_ubo_lights = MIN(RenderList::MAX_LIGHTS, max_ubo_size / ubo_light_size); - print_line("max ubo light: " + itos(state.max_ubo_lights)); + print_line("GLES3: max ubo light: " + itos(state.max_ubo_lights)); state.spot_array_tmp = (uint8_t *)memalloc(ubo_light_size * state.max_ubo_lights); state.omni_array_tmp = (uint8_t *)memalloc(ubo_light_size * state.max_ubo_lights); @@ -4565,7 +4809,7 @@ void RasterizerSceneGLES3::initialize() { state.scene_shader.add_custom_define("#define MAX_FORWARD_LIGHTS " + itos(state.max_forward_lights_per_object) + "\n"); state.max_ubo_reflections = MIN(RenderList::MAX_REFLECTIONS, max_ubo_size / sizeof(ReflectionProbeDataUBO)); - print_line("max ubo reflections: " + itos(state.max_ubo_reflections) + " ubo size: " + itos(sizeof(ReflectionProbeDataUBO))); + print_line("GLES3: max ubo reflections: " + itos(state.max_ubo_reflections) + ", ubo size: " + itos(sizeof(ReflectionProbeDataUBO))); state.reflection_array_tmp = (uint8_t *)memalloc(sizeof(ReflectionProbeDataUBO) * state.max_ubo_reflections); @@ -4580,8 +4824,6 @@ void RasterizerSceneGLES3::initialize() { state.scene_shader.add_custom_define("#define MAX_SKELETON_BONES " + itos(state.max_skeleton_bones) + "\n"); } - GLOBAL_DEF("rendering/gles3/shadow_filter_mode", 1); - GlobalConfig::get_singleton()->set_custom_property_info("rendering/gles3/shadow_filter_mode", PropertyInfo(Variant::INT, "rendering/gles3/shadow_filter_mode", PROPERTY_HINT_ENUM, "Disabled,PCF5,PCF13")); shadow_filter_mode = SHADOW_FILTER_NEAREST; { //reflection cubemaps @@ -4645,7 +4887,7 @@ void RasterizerSceneGLES3::initialize() { { - uint32_t immediate_buffer_size = GLOBAL_DEF("rendering/buffers/immediate_buffer_size_kb", 2048); + uint32_t immediate_buffer_size = GLOBAL_DEF("rendering/limits/buffers/immediate_buffer_size_kb", 2048); glGenBuffers(1, &state.immediate_buffer); glBindBuffer(GL_ARRAY_BUFFER, state.immediate_buffer); @@ -4672,13 +4914,13 @@ void RasterizerSceneGLES3::initialize() { state.tonemap_shader.init(); { - GLOBAL_DEF("rendering/ssurf_scattering/quality", 1); - GlobalConfig::get_singleton()->set_custom_property_info("rendering/ssurf_scattering/quality", PropertyInfo(Variant::INT, "rendering/ssurf_scattering/quality", PROPERTY_HINT_ENUM, "Low,Medium,High")); - GLOBAL_DEF("rendering/ssurf_scattering/max_size", 1.0); - GlobalConfig::get_singleton()->set_custom_property_info("rendering/ssurf_scattering/max_size", PropertyInfo(Variant::INT, "rendering/ssurf_scattering/max_size", PROPERTY_HINT_RANGE, "0.01,8,0.01")); - GLOBAL_DEF("rendering/ssurf_scattering/follow_surface", false); + GLOBAL_DEF("rendering/quality/subsurface_scattering/quality", 1); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/subsurface_scattering/quality", PropertyInfo(Variant::INT, "rendering/quality/subsurface_scattering/quality", PROPERTY_HINT_ENUM, "Low,Medium,High")); + GLOBAL_DEF("rendering/quality/subsurface_scattering/scale", 1.0); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/subsurface_scattering/scale", PropertyInfo(Variant::INT, "rendering/quality/subsurface_scattering/scale", PROPERTY_HINT_RANGE, "0.01,8,0.01")); + GLOBAL_DEF("rendering/quality/subsurface_scattering/follow_surface", false); - GLOBAL_DEF("rendering/reflections/high_quality_vct_gi", true); + GLOBAL_DEF("rendering/quality/voxel_cone_tracing/high_quality", true); } exposure_shrink_size = 243; @@ -4693,7 +4935,12 @@ void RasterizerSceneGLES3::initialize() { glGenTextures(1, &e.color); glBindTexture(GL_TEXTURE_2D, e.color); +#ifdef IPHONE_ENABLED + ///@TODO ugly hack to get around iOS not supporting 32bit single channel floating point textures... + glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, max_exposure_shrink_size, max_exposure_shrink_size, 0, GL_RED, GL_FLOAT, NULL); +#else glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, max_exposure_shrink_size, max_exposure_shrink_size, 0, GL_RED, GL_FLOAT, NULL); +#endif glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, e.color, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -4706,16 +4953,18 @@ void RasterizerSceneGLES3::initialize() { GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE); } + + state.debug_draw = VS::VIEWPORT_DEBUG_DRAW_DISABLED; } void RasterizerSceneGLES3::iteration() { - shadow_filter_mode = ShadowFilterMode(int(GlobalConfig::get_singleton()->get("rendering/gles3/shadow_filter_mode"))); - subsurface_scatter_follow_surface = GlobalConfig::get_singleton()->get("rendering/ssurf_scattering/follow_surface"); - subsurface_scatter_quality = SubSurfaceScatterQuality(int(GlobalConfig::get_singleton()->get("rendering/ssurf_scattering/quality"))); - subsurface_scatter_size = GlobalConfig::get_singleton()->get("rendering/ssurf_scattering/max_size"); + shadow_filter_mode = ShadowFilterMode(int(ProjectSettings::get_singleton()->get("rendering/quality/shadows/filter_mode"))); + subsurface_scatter_follow_surface = ProjectSettings::get_singleton()->get("rendering/quality/subsurface_scattering/follow_surface"); + subsurface_scatter_quality = SubSurfaceScatterQuality(int(ProjectSettings::get_singleton()->get("rendering/quality/subsurface_scattering/quality"))); + subsurface_scatter_size = ProjectSettings::get_singleton()->get("rendering/quality/subsurface_scattering/scale"); - state.scene_shader.set_conditional(SceneShaderGLES3::VCT_QUALITY_HIGH, GlobalConfig::get_singleton()->get("rendering/reflections/high_quality_vct_gi")); + state.scene_shader.set_conditional(SceneShaderGLES3::VCT_QUALITY_HIGH, ProjectSettings::get_singleton()->get("rendering/quality/voxel_cone_tracing/high_quality")); } void RasterizerSceneGLES3::finalize() { |