summaryrefslogtreecommitdiff
path: root/drivers/gles3
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gles3')
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp38
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp45
-rw-r--r--drivers/gles3/rasterizer_gles3.h3
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp71
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h7
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp231
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h15
-rw-r--r--drivers/gles3/shader_compiler_gles3.cpp20
-rw-r--r--drivers/gles3/shader_gles3.cpp2
-rw-r--r--drivers/gles3/shaders/canvas.glsl14
-rw-r--r--drivers/gles3/shaders/scene.glsl93
-rw-r--r--drivers/gles3/shaders/tonemap.glsl448
12 files changed, 579 insertions, 408 deletions
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index bb4c8ab4d7..5e13bed198 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -211,6 +211,10 @@ RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(con
} else {
+ if (texture->redraw_if_visible) { //check before proxy, because this is usually used with proxies
+ VisualServerRaster::redraw_request();
+ }
+
texture = texture->get_ptr();
if (texture->render_target)
@@ -248,6 +252,10 @@ RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(con
} else {
+ if (normal_map->redraw_if_visible) { //check before proxy, because this is usually used with proxies
+ VisualServerRaster::redraw_request();
+ }
+
normal_map = normal_map->get_ptr();
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, normal_map->tex_id);
@@ -832,6 +840,9 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur
if (!particles)
break;
+ if (particles->inactive && !particles->emitting)
+ break;
+
glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); //not used, so keep white
VisualServerRaster::redraw_request();
@@ -997,13 +1008,11 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur
glEnable(GL_SCISSOR_TEST);
//glScissor(viewport.x+current_clip->final_clip_rect.pos.x,viewport.y+ (viewport.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.height)),
//current_clip->final_clip_rect.size.width,current_clip->final_clip_rect.size.height);
-
- int x = current_clip->final_clip_rect.position.x;
int y = storage->frame.current_rt->height - (current_clip->final_clip_rect.position.y + current_clip->final_clip_rect.size.y);
- int w = current_clip->final_clip_rect.size.x;
- int h = current_clip->final_clip_rect.size.y;
+ if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP])
+ y = current_clip->final_clip_rect.position.y;
- glScissor(x, y, w, h);
+ glScissor(current_clip->final_clip_rect.position.x, y, current_clip->final_clip_rect.size.x, current_clip->final_clip_rect.size.y);
reclip = false;
}
@@ -1138,7 +1147,11 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
if (current_clip) {
glEnable(GL_SCISSOR_TEST);
- glScissor(current_clip->final_clip_rect.position.x, (rt_size.height - (current_clip->final_clip_rect.position.y + current_clip->final_clip_rect.size.height)), current_clip->final_clip_rect.size.width, current_clip->final_clip_rect.size.height);
+ int y = storage->frame.current_rt->height - (current_clip->final_clip_rect.position.y + current_clip->final_clip_rect.size.y);
+ if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP])
+ y = current_clip->final_clip_rect.position.y;
+
+ glScissor(current_clip->final_clip_rect.position.x, y, current_clip->final_clip_rect.size.x, current_clip->final_clip_rect.size.y);
} else {
@@ -1261,6 +1274,10 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
continue;
}
+ if (t->redraw_if_visible) { //check before proxy, because this is usually used with proxies
+ VisualServerRaster::redraw_request();
+ }
+
t = t->get_ptr();
if (storage->config.srgb_decode_supported && t->using_srgb) {
@@ -1515,7 +1532,10 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
if (reclip) {
glEnable(GL_SCISSOR_TEST);
- glScissor(current_clip->final_clip_rect.position.x, (rt_size.height - (current_clip->final_clip_rect.position.y + current_clip->final_clip_rect.size.height)), current_clip->final_clip_rect.size.width, current_clip->final_clip_rect.size.height);
+ int y = storage->frame.current_rt->height - (current_clip->final_clip_rect.position.y + current_clip->final_clip_rect.size.y);
+ if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP])
+ y = current_clip->final_clip_rect.position.y;
+ glScissor(current_clip->final_clip_rect.position.x, y, current_clip->final_clip_rect.size.width, current_clip->final_clip_rect.size.height);
}
p_item_list = p_item_list->next;
@@ -1875,7 +1895,7 @@ void RasterizerCanvasGLES3::initialize() {
}
{
- uint32_t poly_size = GLOBAL_DEF("rendering/limits/buffers/canvas_polygon_buffer_size_kb", 128);
+ uint32_t poly_size = GLOBAL_DEF_RST("rendering/limits/buffers/canvas_polygon_buffer_size_kb", 128);
poly_size *= 1024; //kb
poly_size = MAX(poly_size, (2 + 2 + 4) * 4 * sizeof(float));
glGenBuffers(1, &data.polygon_buffer);
@@ -1922,7 +1942,7 @@ void RasterizerCanvasGLES3::initialize() {
glGenVertexArrays(1, &data.polygon_buffer_pointer_array);
- uint32_t index_size = GLOBAL_DEF("rendering/limits/buffers/canvas_polygon_index_buffer_size_kb", 128);
+ uint32_t index_size = GLOBAL_DEF_RST("rendering/limits/buffers/canvas_polygon_index_buffer_size_kb", 128);
index_size *= 1024; //kb
glGenBuffers(1, &data.polygon_index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer);
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index 1abdaa5f80..97c4a98aab 100644
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ b/drivers/gles3/rasterizer_gles3.cpp
@@ -192,22 +192,15 @@ void RasterizerGLES3::initialize() {
scene->initialize();
}
-void RasterizerGLES3::begin_frame() {
+void RasterizerGLES3::begin_frame(double frame_step) {
- uint64_t tick = OS::get_singleton()->get_ticks_usec();
+ time_total += frame_step;
- double delta = double(tick - prev_ticks) / 1000000.0;
- delta *= Engine::get_singleton()->get_time_scale();
-
- time_total += delta;
-
- if (delta == 0) {
+ if (frame_step == 0) {
//to avoid hiccups
- delta = 0.001;
+ frame_step = 0.001;
}
- prev_ticks = tick;
-
double time_roll_over = GLOBAL_GET("rendering/limits/time/time_rollover_secs");
if (time_total > time_roll_over)
time_total = 0; //roll over every day (should be customz
@@ -217,9 +210,7 @@ void RasterizerGLES3::begin_frame() {
storage->frame.time[2] = Math::fmod(time_total, 900);
storage->frame.time[3] = Math::fmod(time_total, 60);
storage->frame.count++;
- storage->frame.delta = delta;
-
- storage->frame.prev_tick = tick;
+ storage->frame.delta = frame_step;
storage->update_dirty_resources();
@@ -281,7 +272,7 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c
if (p_image.is_null() || p_image->empty())
return;
- begin_frame();
+ begin_frame(0.0);
int window_w = OS::get_singleton()->get_video_mode(0).width;
int window_h = OS::get_singleton()->get_video_mode(0).height;
@@ -333,28 +324,7 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c
storage->free(texture); // free since it's only one frame that stays there
- if (OS::get_singleton()->is_layered_allowed()) {
- if (OS::get_singleton()->get_window_per_pixel_transparency_enabled()) {
-#if (defined WINDOWS_ENABLED) && !(defined UWP_ENABLED)
- Size2 wndsize = OS::get_singleton()->get_layered_buffer_size();
- uint8_t *data = OS::get_singleton()->get_layered_buffer_data();
- if (data) {
- glReadPixels(0, 0, wndsize.x, wndsize.y, GL_BGRA, GL_UNSIGNED_BYTE, data);
- OS::get_singleton()->swap_layered_buffer();
-
- return;
- }
-#endif
- } else {
- //clear alpha
- glColorMask(false, false, false, true);
- glClearColor(0, 0, 0, 1);
- glClear(GL_COLOR_BUFFER_BIT);
- glColorMask(true, true, true, true);
- }
- }
-
- OS::get_singleton()->swap_buffers();
+ end_frame(true);
}
void RasterizerGLES3::blit_render_target_to_screen(RID p_render_target, const Rect2 &p_screen_rect, int p_screen) {
@@ -451,7 +421,6 @@ RasterizerGLES3::RasterizerGLES3() {
scene->storage = storage;
storage->scene = scene;
- prev_ticks = 0;
time_total = 0;
}
diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h
index 5213101778..f4449ac0f9 100644
--- a/drivers/gles3/rasterizer_gles3.h
+++ b/drivers/gles3/rasterizer_gles3.h
@@ -44,7 +44,6 @@ class RasterizerGLES3 : public Rasterizer {
RasterizerCanvasGLES3 *canvas;
RasterizerSceneGLES3 *scene;
- uint64_t prev_ticks;
double time_total;
public:
@@ -55,7 +54,7 @@ public:
virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale);
virtual void initialize();
- virtual void begin_frame();
+ virtual void begin_frame(double frame_step);
virtual void set_current_render_target(RID p_render_target);
virtual void restore_render_target();
virtual void clear_render_target(const Color &p_color);
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 03ff84c093..d01ba2ddcc 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -355,7 +355,7 @@ bool RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_light_in
bool should_redraw = shadow_atlas->quadrants[q].shadows[s].version != p_light_version;
if (!should_realloc) {
- shadow_atlas->quadrants[q].shadows[s].version = p_light_version;
+ shadow_atlas->quadrants[q].shadows.write[s].version = p_light_version;
//already existing, see if it should redraw or it's just OK
return should_redraw;
}
@@ -365,7 +365,7 @@ bool RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_light_in
//find a better place
if (_shadow_atlas_find_shadow(shadow_atlas, valid_quadrants, valid_quadrant_count, shadow_atlas->quadrants[q].subdivision, tick, new_quadrant, new_shadow)) {
//found a better place!
- ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows[new_shadow];
+ ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_shadow];
if (sh->owner.is_valid()) {
//is taken, but is invalid, erasing it
shadow_atlas->shadow_owners.erase(sh->owner);
@@ -374,8 +374,8 @@ bool RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_light_in
}
//erase previous
- shadow_atlas->quadrants[q].shadows[s].version = 0;
- shadow_atlas->quadrants[q].shadows[s].owner = RID();
+ shadow_atlas->quadrants[q].shadows.write[s].version = 0;
+ shadow_atlas->quadrants[q].shadows.write[s].owner = RID();
sh->owner = p_light_intance;
sh->alloc_tick = tick;
@@ -395,7 +395,7 @@ bool RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_light_in
//already existing, see if it should redraw or it's just OK
- shadow_atlas->quadrants[q].shadows[s].version = p_light_version;
+ shadow_atlas->quadrants[q].shadows.write[s].version = p_light_version;
return should_redraw;
}
@@ -405,7 +405,7 @@ bool RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_light_in
//find a better place
if (_shadow_atlas_find_shadow(shadow_atlas, valid_quadrants, valid_quadrant_count, -1, tick, new_quadrant, new_shadow)) {
//found a better place!
- ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows[new_shadow];
+ ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_shadow];
if (sh->owner.is_valid()) {
//is taken, but is invalid, erasing it
shadow_atlas->shadow_owners.erase(sh->owner);
@@ -502,7 +502,7 @@ void RasterizerSceneGLES3::reflection_atlas_set_size(RID p_ref_atlas, int p_size
//erase probes reference to this
if (reflection_atlas->reflections[i].owner.is_valid()) {
ReflectionProbeInstance *reflection_probe_instance = reflection_probe_instance_owner.getornull(reflection_atlas->reflections[i].owner);
- reflection_atlas->reflections[i].owner = RID();
+ reflection_atlas->reflections.write[i].owner = RID();
ERR_CONTINUE(!reflection_probe_instance);
reflection_probe_instance->reflection_atlas_index = -1;
@@ -574,7 +574,7 @@ void RasterizerSceneGLES3::reflection_atlas_set_subdivision(RID p_ref_atlas, int
//erase probes reference to this
if (reflection_atlas->reflections[i].owner.is_valid()) {
ReflectionProbeInstance *reflection_probe_instance = reflection_probe_instance_owner.getornull(reflection_atlas->reflections[i].owner);
- reflection_atlas->reflections[i].owner = RID();
+ reflection_atlas->reflections.write[i].owner = RID();
ERR_CONTINUE(!reflection_probe_instance);
reflection_probe_instance->reflection_atlas_index = -1;
@@ -629,7 +629,7 @@ void RasterizerSceneGLES3::reflection_probe_release_atlas_index(RID p_instance)
ERR_FAIL_COND(reflection_atlas->reflections[rpi->reflection_atlas_index].owner != rpi->self);
- reflection_atlas->reflections[rpi->reflection_atlas_index].owner = RID();
+ reflection_atlas->reflections.write[rpi->reflection_atlas_index].owner = RID();
rpi->reflection_atlas_index = -1;
rpi->atlas = RID();
@@ -701,8 +701,8 @@ bool RasterizerSceneGLES3::reflection_probe_instance_begin_render(RID p_instance
victim_rpi->reflection_atlas_index = -1;
}
- reflection_atlas->reflections[best_free].owner = p_instance;
- reflection_atlas->reflections[best_free].last_frame = storage->frame.count;
+ reflection_atlas->reflections.write[best_free].owner = p_instance;
+ reflection_atlas->reflections.write[best_free].last_frame = storage->frame.count;
rpi->reflection_atlas_index = best_free;
rpi->atlas = p_reflection_atlas;
@@ -896,7 +896,7 @@ void RasterizerSceneGLES3::environment_set_ssr(RID p_env, bool p_enable, int p_m
env->ssr_roughness = p_roughness;
}
-void RasterizerSceneGLES3::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, const Color &p_color, VS::EnvironmentSSAOQuality p_quality, VisualServer::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) {
+void RasterizerSceneGLES3::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, float p_ao_channel_affect, const Color &p_color, VS::EnvironmentSSAOQuality p_quality, VisualServer::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) {
Environment *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
@@ -908,6 +908,7 @@ void RasterizerSceneGLES3::environment_set_ssao(RID p_env, bool p_enable, float
env->ssao_intensity2 = p_intensity2;
env->ssao_bias = p_bias;
env->ssao_light_affect = p_light_affect;
+ env->ssao_ao_channel_affect = p_ao_channel_affect;
env->ssao_color = p_color;
env->ssao_filter = p_blur;
env->ssao_quality = p_quality;
@@ -1224,7 +1225,12 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m
} else {
+ if (t->redraw_if_visible) { //must check before proxy because this is often used with proxies
+ VisualServerRaster::redraw_request();
+ }
+
t = t->get_ptr(); //resolve for proxies
+
#ifdef TOOLS_ENABLED
if (t->detect_3d) {
t->detect_3d(t->detect_3d_ud);
@@ -1335,7 +1341,7 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transfo
glBindBuffer(GL_ARRAY_BUFFER, multi_mesh->buffer); //modify the buffer
- int stride = (multi_mesh->xform_floats + multi_mesh->color_floats) * 4;
+ int stride = (multi_mesh->xform_floats + multi_mesh->color_floats + multi_mesh->custom_data_floats) * 4;
glEnableVertexAttribArray(8);
glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 0);
glVertexAttribDivisor(8, 1);
@@ -1356,6 +1362,8 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transfo
color_ofs = 8 * 4;
}
+ int custom_data_ofs = color_ofs;
+
switch (multi_mesh->color_format) {
case VS::MULTIMESH_COLOR_NONE: {
@@ -1366,12 +1374,33 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transfo
glEnableVertexAttribArray(11);
glVertexAttribPointer(11, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, ((uint8_t *)NULL) + color_ofs);
glVertexAttribDivisor(11, 1);
+ custom_data_ofs += 4;
} break;
case VS::MULTIMESH_COLOR_FLOAT: {
glEnableVertexAttribArray(11);
glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + color_ofs);
glVertexAttribDivisor(11, 1);
+ custom_data_ofs += 4 * 4;
+ } break;
+ }
+
+ switch (multi_mesh->custom_data_format) {
+
+ case VS::MULTIMESH_CUSTOM_DATA_NONE: {
+ glDisableVertexAttribArray(12);
+ glVertexAttrib4f(12, 1, 1, 1, 1);
+ } break;
+ case VS::MULTIMESH_CUSTOM_DATA_8BIT: {
+ glEnableVertexAttribArray(12);
+ glVertexAttribPointer(12, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, ((uint8_t *)NULL) + custom_data_ofs);
+ glVertexAttribDivisor(12, 1);
+
+ } break;
+ case VS::MULTIMESH_CUSTOM_DATA_FLOAT: {
+ glEnableVertexAttribArray(12);
+ glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + custom_data_ofs);
+ glVertexAttribDivisor(12, 1);
} break;
}
@@ -1545,6 +1574,11 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) {
RasterizerStorageGLES3::Texture *t = storage->texture_owner.get(c.texture);
t = t->get_ptr(); //resolve for proxies
+
+ if (t->redraw_if_visible) {
+ VisualServerRaster::redraw_request();
+ }
+
#ifdef TOOLS_ENABLED
if (t->detect_3d) {
t->detect_3d(t->detect_3d_ud);
@@ -2507,6 +2541,7 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatr
state.env_radiance_data.ambient_contribution = env->ambient_sky_contribution;
state.ubo_data.ambient_occlusion_affect_light = env->ssao_light_affect;
+ state.ubo_data.ambient_occlusion_affect_ssao = env->ssao_ao_channel_affect;
//fog
@@ -3813,8 +3848,8 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_END, false);
//last step, swap with the framebuffer exposure, so the right exposure is kept int he framebuffer
- SWAP(exposure_shrink[exposure_shrink.size() - 1].fbo, storage->frame.current_rt->exposure.fbo);
- SWAP(exposure_shrink[exposure_shrink.size() - 1].color, storage->frame.current_rt->exposure.color);
+ SWAP(exposure_shrink.write[exposure_shrink.size() - 1].fbo, storage->frame.current_rt->exposure.fbo);
+ SWAP(exposure_shrink.write[exposure_shrink.size() - 1].color, storage->frame.current_rt->exposure.color);
glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
@@ -4051,6 +4086,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
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;
+ state.ubo_data.opaque_prepass_threshold = 0.99;
p_cam_projection.get_viewport_size(state.ubo_data.viewport_size[0], state.ubo_data.viewport_size[1]);
@@ -4663,6 +4699,7 @@ void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_
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;
+ state.ubo_data.opaque_prepass_threshold = 0.1;
_setup_environment(NULL, light_projection, light_transform);
@@ -4741,7 +4778,7 @@ bool RasterizerSceneGLES3::free(RID p_rid) {
uint32_t q = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
uint32_t s = key & ShadowAtlas::SHADOW_INDEX_MASK;
- shadow_atlas->quadrants[q].shadows[s].owner = RID();
+ shadow_atlas->quadrants[q].shadows.write[s].owner = RID();
shadow_atlas->shadow_owners.erase(p_rid);
}
@@ -4831,7 +4868,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/limits/rendering/max_renderable_elements", (int)RenderList::DEFAULT_MAX_ELEMENTS);
+ render_list.max_elements = GLOBAL_DEF_RST("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)
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index a6faeef473..cf387a69bc 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -140,6 +140,8 @@ public:
float reflection_multiplier;
float subsurface_scatter_width;
float ambient_occlusion_affect_light;
+ float ambient_occlusion_affect_ssao;
+ float opaque_prepass_threshold;
uint32_t fog_depth_enabled;
float fog_depth_begin;
@@ -151,6 +153,7 @@ public:
float fog_height_max;
float fog_height_curve;
// make sure this struct is padded to be a multiple of 16 bytes for webgl
+ float pad[2];
} ubo_data;
@@ -385,6 +388,7 @@ public:
float ssao_radius2;
float ssao_bias;
float ssao_light_affect;
+ float ssao_ao_channel_affect;
Color ssao_color;
VS::EnvironmentSSAOQuality ssao_quality;
float ssao_bilateral_sharpness;
@@ -465,6 +469,7 @@ public:
ssao_radius2 = 0.0;
ssao_bias = 0.01;
ssao_light_affect = 0;
+ ssao_ao_channel_affect = 0;
ssao_filter = VS::ENV_SSAO_BLUR_3x3;
ssao_quality = VS::ENV_SSAO_QUALITY_LOW;
ssao_bilateral_sharpness = 4;
@@ -543,7 +548,7 @@ public:
virtual void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture);
virtual void 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);
- virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, const Color &p_color, VS::EnvironmentSSAOQuality p_quality, VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness);
+ virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, float p_ao_channel_affect, const Color &p_color, VS::EnvironmentSSAOQuality p_quality, VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness);
virtual void environment_set_tonemap(RID p_env, VS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale);
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 11ab957458..c1c1b2a009 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -1328,6 +1328,13 @@ void RasterizerStorageGLES3::texture_set_proxy(RID p_texture, RID p_proxy) {
}
}
+void RasterizerStorageGLES3::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) {
+
+ Texture *texture = texture_owner.get(p_texture);
+ ERR_FAIL_COND(!texture);
+ texture->redraw_if_visible = p_enable;
+}
+
RID RasterizerStorageGLES3::sky_create() {
Sky *sky = memnew(Sky);
@@ -2663,7 +2670,7 @@ void RasterizerStorageGLES3::_update_material(Material *material) {
}
}
- material->textures[E->get().texture_order] = texture;
+ material->textures.write[E->get().texture_order] = texture;
}
} else {
@@ -2968,9 +2975,9 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
for (int i = 0; i < surface->skeleton_bone_used.size(); i++) {
if (surface->skeleton_bone_aabb[i].size.x < 0 || surface->skeleton_bone_aabb[i].size.y < 0 || surface->skeleton_bone_aabb[i].size.z < 0) {
- surface->skeleton_bone_used[i] = false;
+ surface->skeleton_bone_used.write[i] = false;
} else {
- surface->skeleton_bone_used[i] = true;
+ surface->skeleton_bone_used.write[i] = true;
}
}
@@ -3233,7 +3240,7 @@ void RasterizerStorageGLES3::mesh_surface_update_region(RID p_mesh, int p_surfac
PoolVector<uint8_t>::Read r = p_data.read();
- glBindBuffer(GL_ARRAY_BUFFER, mesh->surfaces[p_surface]->array_id);
+ glBindBuffer(GL_ARRAY_BUFFER, mesh->surfaces[p_surface]->vertex_id);
glBufferSubData(GL_ARRAY_BUFFER, p_offset, total_size, r.ptr());
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
}
@@ -3397,6 +3404,7 @@ Vector<PoolVector<uint8_t> > RasterizerStorageGLES3::mesh_surface_get_blend_shap
return bsarr;
}
+
Vector<AABB> RasterizerStorageGLES3::mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const {
const Mesh *mesh = mesh_owner.getornull(p_mesh);
@@ -3448,6 +3456,7 @@ void RasterizerStorageGLES3::mesh_remove_surface(RID p_mesh, int p_surface) {
mesh->instance_change_notify();
}
+
int RasterizerStorageGLES3::mesh_get_surface_count(RID p_mesh) const {
const Mesh *mesh = mesh_owner.getornull(p_mesh);
@@ -3461,6 +3470,7 @@ void RasterizerStorageGLES3::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb
ERR_FAIL_COND(!mesh);
mesh->custom_aabb = p_aabb;
+ mesh->instance_change_notify();
}
AABB RasterizerStorageGLES3::mesh_get_custom_aabb(RID p_mesh) const {
@@ -3816,12 +3826,12 @@ RID RasterizerStorageGLES3::multimesh_create() {
return multimesh_owner.make_rid(multimesh);
}
-void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format) {
+void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format, VS::MultimeshCustomDataFormat p_data_format) {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND(!multimesh);
- if (multimesh->size == p_instances && multimesh->transform_format == p_transform_format && multimesh->color_format == p_color_format)
+ if (multimesh->size == p_instances && multimesh->transform_format == p_transform_format && multimesh->color_format == p_color_format && multimesh->custom_data_format == p_data_format)
return;
if (multimesh->buffer) {
@@ -3832,6 +3842,7 @@ void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances
multimesh->size = p_instances;
multimesh->transform_format = p_transform_format;
multimesh->color_format = p_color_format;
+ multimesh->custom_data_format = p_data_format;
if (multimesh->size) {
@@ -3849,36 +3860,49 @@ void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances
multimesh->color_floats = 4;
}
- int format_floats = multimesh->color_floats + multimesh->xform_floats;
+ if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_NONE) {
+ multimesh->custom_data_floats = 0;
+ } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) {
+ multimesh->custom_data_floats = 1;
+ } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) {
+ multimesh->custom_data_floats = 4;
+ }
+
+ int format_floats = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
+
multimesh->data.resize(format_floats * p_instances);
- for (int i = 0; i < p_instances; i += format_floats) {
+
+ for (int i = 0; i < p_instances * format_floats; i += format_floats) {
int color_from = 0;
+ int custom_data_from = 0;
if (multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D) {
- multimesh->data[i + 0] = 1.0;
- multimesh->data[i + 1] = 0.0;
- multimesh->data[i + 2] = 0.0;
- multimesh->data[i + 3] = 0.0;
- multimesh->data[i + 4] = 0.0;
- multimesh->data[i + 5] = 1.0;
- multimesh->data[i + 6] = 0.0;
- multimesh->data[i + 7] = 0.0;
+ multimesh->data.write[i + 0] = 1.0;
+ multimesh->data.write[i + 1] = 0.0;
+ multimesh->data.write[i + 2] = 0.0;
+ multimesh->data.write[i + 3] = 0.0;
+ multimesh->data.write[i + 4] = 0.0;
+ multimesh->data.write[i + 5] = 1.0;
+ multimesh->data.write[i + 6] = 0.0;
+ multimesh->data.write[i + 7] = 0.0;
color_from = 8;
+ custom_data_from = 8;
} else {
- multimesh->data[i + 0] = 1.0;
- multimesh->data[i + 1] = 0.0;
- multimesh->data[i + 2] = 0.0;
- multimesh->data[i + 3] = 0.0;
- multimesh->data[i + 4] = 0.0;
- multimesh->data[i + 5] = 1.0;
- multimesh->data[i + 6] = 0.0;
- multimesh->data[i + 7] = 0.0;
- multimesh->data[i + 8] = 0.0;
- multimesh->data[i + 9] = 0.0;
- multimesh->data[i + 10] = 1.0;
- multimesh->data[i + 11] = 0.0;
+ multimesh->data.write[i + 0] = 1.0;
+ multimesh->data.write[i + 1] = 0.0;
+ multimesh->data.write[i + 2] = 0.0;
+ multimesh->data.write[i + 3] = 0.0;
+ multimesh->data.write[i + 4] = 0.0;
+ multimesh->data.write[i + 5] = 1.0;
+ multimesh->data.write[i + 6] = 0.0;
+ multimesh->data.write[i + 7] = 0.0;
+ multimesh->data.write[i + 8] = 0.0;
+ multimesh->data.write[i + 9] = 0.0;
+ multimesh->data.write[i + 10] = 1.0;
+ multimesh->data.write[i + 11] = 0.0;
color_from = 12;
+ custom_data_from = 12;
}
if (multimesh->color_format == VS::MULTIMESH_COLOR_NONE) {
@@ -3891,13 +3915,34 @@ void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances
} cu;
cu.colu = 0xFFFFFFFF;
- multimesh->data[i + color_from + 0] = cu.colf;
+ multimesh->data.write[i + color_from + 0] = cu.colf;
+ custom_data_from = color_from + 1;
} else if (multimesh->color_format == VS::MULTIMESH_COLOR_FLOAT) {
- multimesh->data[i + color_from + 0] = 1.0;
- multimesh->data[i + color_from + 1] = 1.0;
- multimesh->data[i + color_from + 2] = 1.0;
- multimesh->data[i + color_from + 3] = 1.0;
+ multimesh->data.write[i + color_from + 0] = 1.0;
+ multimesh->data.write[i + color_from + 1] = 1.0;
+ multimesh->data.write[i + color_from + 2] = 1.0;
+ multimesh->data.write[i + color_from + 3] = 1.0;
+ custom_data_from = color_from + 4;
+ }
+
+ if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_NONE) {
+ //none
+ } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) {
+
+ union {
+ uint32_t colu;
+ float colf;
+ } cu;
+
+ cu.colu = 0;
+ multimesh->data.write[i + custom_data_from + 0] = cu.colf;
+
+ } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) {
+ multimesh->data.write[i + custom_data_from + 0] = 0.0;
+ multimesh->data.write[i + custom_data_from + 1] = 0.0;
+ multimesh->data.write[i + custom_data_from + 2] = 0.0;
+ multimesh->data.write[i + custom_data_from + 3] = 0.0;
}
}
@@ -3958,8 +4003,8 @@ void RasterizerStorageGLES3::multimesh_instance_set_transform(RID p_multimesh, i
ERR_FAIL_INDEX(p_index, multimesh->size);
ERR_FAIL_COND(multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D);
- int stride = multimesh->color_floats + multimesh->xform_floats;
- float *dataptr = &multimesh->data[stride * p_index];
+ int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
+ float *dataptr = &multimesh->data.write[stride * p_index];
dataptr[0] = p_transform.basis.elements[0][0];
dataptr[1] = p_transform.basis.elements[0][1];
@@ -3989,8 +4034,8 @@ void RasterizerStorageGLES3::multimesh_instance_set_transform_2d(RID p_multimesh
ERR_FAIL_INDEX(p_index, multimesh->size);
ERR_FAIL_COND(multimesh->transform_format == VS::MULTIMESH_TRANSFORM_3D);
- int stride = multimesh->color_floats + multimesh->xform_floats;
- float *dataptr = &multimesh->data[stride * p_index];
+ int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
+ float *dataptr = &multimesh->data.write[stride * p_index];
dataptr[0] = p_transform.elements[0][0];
dataptr[1] = p_transform.elements[1][0];
@@ -4015,8 +4060,8 @@ void RasterizerStorageGLES3::multimesh_instance_set_color(RID p_multimesh, int p
ERR_FAIL_INDEX(p_index, multimesh->size);
ERR_FAIL_COND(multimesh->color_format == VS::MULTIMESH_COLOR_NONE);
- int stride = multimesh->color_floats + multimesh->xform_floats;
- float *dataptr = &multimesh->data[stride * p_index + multimesh->xform_floats];
+ int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
+ float *dataptr = &multimesh->data.write[stride * p_index + multimesh->xform_floats];
if (multimesh->color_format == VS::MULTIMESH_COLOR_8BIT) {
@@ -4041,6 +4086,38 @@ void RasterizerStorageGLES3::multimesh_instance_set_color(RID p_multimesh, int p
}
}
+void RasterizerStorageGLES3::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_custom_data) {
+
+ MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+ ERR_FAIL_INDEX(p_index, multimesh->size);
+ ERR_FAIL_COND(multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_NONE);
+
+ int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
+ float *dataptr = &multimesh->data.write[stride * p_index + multimesh->xform_floats + multimesh->color_floats];
+
+ if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) {
+
+ uint8_t *data8 = (uint8_t *)dataptr;
+ data8[0] = CLAMP(p_custom_data.r * 255.0, 0, 255);
+ data8[1] = CLAMP(p_custom_data.g * 255.0, 0, 255);
+ data8[2] = CLAMP(p_custom_data.b * 255.0, 0, 255);
+ data8[3] = CLAMP(p_custom_data.a * 255.0, 0, 255);
+
+ } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) {
+ dataptr[0] = p_custom_data.r;
+ dataptr[1] = p_custom_data.g;
+ dataptr[2] = p_custom_data.b;
+ dataptr[3] = p_custom_data.a;
+ }
+
+ multimesh->dirty_data = true;
+ multimesh->dirty_aabb = true;
+
+ if (!multimesh->update_list.in_list()) {
+ multimesh_update_list.add(&multimesh->update_list);
+ }
+}
RID RasterizerStorageGLES3::multimesh_get_mesh(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
@@ -4056,8 +4133,8 @@ Transform RasterizerStorageGLES3::multimesh_instance_get_transform(RID p_multime
ERR_FAIL_INDEX_V(p_index, multimesh->size, Transform());
ERR_FAIL_COND_V(multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D, Transform());
- int stride = multimesh->color_floats + multimesh->xform_floats;
- float *dataptr = &multimesh->data[stride * p_index];
+ int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
+ float *dataptr = &multimesh->data.write[stride * p_index];
Transform xform;
@@ -4083,8 +4160,8 @@ Transform2D RasterizerStorageGLES3::multimesh_instance_get_transform_2d(RID p_mu
ERR_FAIL_INDEX_V(p_index, multimesh->size, Transform2D());
ERR_FAIL_COND_V(multimesh->transform_format == VS::MULTIMESH_TRANSFORM_3D, Transform2D());
- int stride = multimesh->color_floats + multimesh->xform_floats;
- float *dataptr = &multimesh->data[stride * p_index];
+ int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
+ float *dataptr = &multimesh->data.write[stride * p_index];
Transform2D xform;
@@ -4105,8 +4182,8 @@ Color RasterizerStorageGLES3::multimesh_instance_get_color(RID p_multimesh, int
ERR_FAIL_INDEX_V(p_index, multimesh->size, Color());
ERR_FAIL_COND_V(multimesh->color_format == VS::MULTIMESH_COLOR_NONE, Color());
- int stride = multimesh->color_floats + multimesh->xform_floats;
- float *dataptr = &multimesh->data[stride * p_index + multimesh->xform_floats];
+ int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
+ float *dataptr = &multimesh->data.write[stride * p_index + multimesh->xform_floats];
if (multimesh->color_format == VS::MULTIMESH_COLOR_8BIT) {
union {
@@ -4131,6 +4208,59 @@ Color RasterizerStorageGLES3::multimesh_instance_get_color(RID p_multimesh, int
return Color();
}
+Color RasterizerStorageGLES3::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const {
+
+ MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, Color());
+ ERR_FAIL_INDEX_V(p_index, multimesh->size, Color());
+ ERR_FAIL_COND_V(multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_NONE, Color());
+
+ int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
+ float *dataptr = &multimesh->data.write[stride * p_index + multimesh->xform_floats + multimesh->color_floats];
+
+ if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) {
+ union {
+ uint32_t colu;
+ float colf;
+ } cu;
+
+ cu.colf = dataptr[0];
+
+ return Color::hex(BSWAP32(cu.colu));
+
+ } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) {
+ Color c;
+ c.r = dataptr[0];
+ c.g = dataptr[1];
+ c.b = dataptr[2];
+ c.a = dataptr[3];
+
+ return c;
+ }
+
+ return Color();
+}
+
+void RasterizerStorageGLES3::multimesh_set_as_bulk_array(RID p_multimesh, const PoolVector<float> &p_array) {
+
+ MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+
+ int dsize = multimesh->data.size();
+
+ ERR_FAIL_COND(dsize != p_array.size());
+
+ PoolVector<float>::Read r = p_array.read();
+ copymem(multimesh->data.ptrw(), r.ptr(), dsize * sizeof(float));
+
+ multimesh->dirty_data = true;
+ multimesh->dirty_aabb = true;
+
+ if (!multimesh->update_list.in_list()) {
+ multimesh_update_list.add(&multimesh->update_list);
+ }
+}
+
void RasterizerStorageGLES3::multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
@@ -4179,7 +4309,7 @@ void RasterizerStorageGLES3::update_dirty_multimeshes() {
mesh_aabb.size += Vector3(0.001, 0.001, 0.001);
}
- int stride = multimesh->color_floats + multimesh->xform_floats;
+ int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
int count = multimesh->data.size();
float *data = multimesh->data.ptrw();
@@ -5642,7 +5772,7 @@ void RasterizerStorageGLES3::particles_set_draw_pass_mesh(RID p_particles, int p
Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND(!particles);
ERR_FAIL_INDEX(p_pass, particles->draw_passes.size());
- particles->draw_passes[p_pass] = p_mesh;
+ particles->draw_passes.write[p_pass] = p_mesh;
}
void RasterizerStorageGLES3::particles_restart(RID p_particles) {
@@ -6516,7 +6646,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) {
for (int j = 0; j < rt->effects.mip_maps[i].sizes.size(); j++) {
- RenderTarget::Effects::MipMaps::Size &mm = rt->effects.mip_maps[i].sizes[j];
+ RenderTarget::Effects::MipMaps::Size &mm = rt->effects.mip_maps[i].sizes.write[j];
glGenFramebuffers(1, &mm.fbo);
glBindFramebuffer(GL_FRAMEBUFFER, mm.fbo);
@@ -6928,7 +7058,7 @@ bool RasterizerStorageGLES3::free(RID p_rid) {
for (int i = 0; i < ins->materials.size(); i++) {
if (ins->materials[i] == p_rid) {
- ins->materials[i] = RID();
+ ins->materials.write[i] = RID();
}
}
}
@@ -7336,7 +7466,7 @@ void RasterizerStorageGLES3::initialize() {
{
//transform feedback buffers
- uint32_t xf_feedback_size = GLOBAL_DEF("rendering/limits/buffers/blend_shape_max_buffer_size_kb", 4096);
+ uint32_t xf_feedback_size = GLOBAL_DEF_RST("rendering/limits/buffers/blend_shape_max_buffer_size_kb", 4096);
for (int i = 0; i < 2; i++) {
glGenBuffers(1, &resources.transform_feedback_buffers[i]);
@@ -7359,7 +7489,6 @@ void RasterizerStorageGLES3::initialize() {
#endif
frame.count = 0;
- frame.prev_tick = 0;
frame.delta = 0;
frame.current_rt = NULL;
config.keep_original_textures = false;
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index 6b626cbd00..d9c770d1b7 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -268,6 +268,7 @@ public:
GLuint tex_id;
bool using_srgb;
+ bool redraw_if_visible;
uint16_t stored_cube_sides;
@@ -306,6 +307,7 @@ public:
detect_normal = NULL;
detect_normal_ud = NULL;
proxy = NULL;
+ redraw_if_visible = false;
}
_ALWAYS_INLINE_ Texture *get_ptr() {
@@ -366,6 +368,7 @@ public:
virtual void texture_set_detect_normal_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata);
virtual void texture_set_proxy(RID p_texture, RID p_proxy);
+ virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable);
/* SKY API */
@@ -690,7 +693,6 @@ public:
AABB custom_aabb;
mutable uint64_t last_pass;
SelfList<MultiMesh>::List multimeshes;
-
_FORCE_INLINE_ void update_multimeshes() {
SelfList<MultiMesh> *mm = multimeshes.first();
@@ -756,6 +758,7 @@ public:
int size;
VS::MultimeshTransformFormat transform_format;
VS::MultimeshColorFormat color_format;
+ VS::MultimeshCustomDataFormat custom_data_format;
Vector<float> data;
AABB aabb;
SelfList<MultiMesh> update_list;
@@ -765,6 +768,7 @@ public:
int xform_floats;
int color_floats;
+ int custom_data_floats;
bool dirty_aabb;
bool dirty_data;
@@ -776,11 +780,13 @@ public:
dirty_data = true;
xform_floats = 0;
color_floats = 0;
+ custom_data_floats = 0;
visible_instances = -1;
size = 0;
buffer = 0;
transform_format = VS::MULTIMESH_TRANSFORM_2D;
color_format = VS::MULTIMESH_COLOR_NONE;
+ custom_data_format = VS::MULTIMESH_CUSTOM_DATA_NONE;
}
};
@@ -792,19 +798,23 @@ public:
virtual RID multimesh_create();
- virtual void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format);
+ virtual void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format, VS::MultimeshCustomDataFormat p_data_format = VS::MULTIMESH_CUSTOM_DATA_NONE);
virtual int multimesh_get_instance_count(RID p_multimesh) const;
virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh);
virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform);
virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform);
virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color);
+ virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color);
virtual RID multimesh_get_mesh(RID p_multimesh) const;
virtual Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const;
virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const;
virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const;
+ virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const;
+
+ virtual void multimesh_set_as_bulk_array(RID p_multimesh, const PoolVector<float> &p_array);
virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible);
virtual int multimesh_get_visible_instances(RID p_multimesh) const;
@@ -1417,7 +1427,6 @@ public:
int canvas_draw_commands;
float time[4];
float delta;
- uint64_t prev_tick;
uint64_t count;
} frame;
diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp
index eb8d6c485b..4ff8c72e13 100644
--- a/drivers/gles3/shader_compiler_gles3.cpp
+++ b/drivers/gles3/shader_compiler_gles3.cpp
@@ -365,17 +365,17 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
if (SL::is_sampler_type(E->get().type)) {
r_gen_code.vertex_global += ucode;
r_gen_code.fragment_global += ucode;
- r_gen_code.texture_uniforms[E->get().texture_order] = _mkid(E->key());
- r_gen_code.texture_hints[E->get().texture_order] = E->get().hint;
+ r_gen_code.texture_uniforms.write[E->get().texture_order] = _mkid(E->key());
+ r_gen_code.texture_hints.write[E->get().texture_order] = E->get().hint;
} else {
if (!uses_uniforms) {
r_gen_code.defines.push_back(String("#define USE_MATERIAL\n").ascii());
uses_uniforms = true;
}
- uniform_defines[E->get().order] = ucode;
- uniform_sizes[E->get().order] = _get_datatype_size(E->get().type);
- uniform_alignments[E->get().order] = _get_datatype_alignment(E->get().type);
+ uniform_defines.write[E->get().order] = ucode;
+ uniform_sizes.write[E->get().order] = _get_datatype_size(E->get().type);
+ uniform_alignments.write[E->get().order] = _get_datatype_alignment(E->get().type);
}
p_actions.uniforms->insert(E->key(), E->get());
@@ -780,8 +780,6 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL"] = "normal";
actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP"] = "normal_map";
actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP_DEPTH"] = "normal_depth";
- actions[VS::SHADER_CANVAS_ITEM].renames["UV"] = "uv_interp";
- actions[VS::SHADER_CANVAS_ITEM].renames["COLOR"] = "color";
actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE"] = "color_texture";
actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE_PIXEL_SIZE"] = "color_texpixel_size";
actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL_TEXTURE"] = "normal_texture";
@@ -824,7 +822,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].renames["UV2"] = "uv2_interp";
actions[VS::SHADER_SPATIAL].renames["COLOR"] = "color_interp";
actions[VS::SHADER_SPATIAL].renames["POINT_SIZE"] = "gl_PointSize";
- //actions[VS::SHADER_SPATIAL].renames["INSTANCE_ID"]=ShaderLanguage::TYPE_INT;
+ actions[VS::SHADER_SPATIAL].renames["INSTANCE_ID"] = "gl_InstanceID";
//builtins
@@ -846,13 +844,11 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].renames["CLEARCOAT_GLOSS"] = "clearcoat_gloss";
actions[VS::SHADER_SPATIAL].renames["ANISOTROPY"] = "anisotropy";
actions[VS::SHADER_SPATIAL].renames["ANISOTROPY_FLOW"] = "anisotropy_flow";
- //actions[VS::SHADER_SPATIAL].renames["SSS_SPREAD"] = "sss_spread";
actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength";
actions[VS::SHADER_SPATIAL].renames["TRANSMISSION"] = "transmission";
actions[VS::SHADER_SPATIAL].renames["AO"] = "ao";
actions[VS::SHADER_SPATIAL].renames["AO_LIGHT_AFFECT"] = "ao_light_affect";
actions[VS::SHADER_SPATIAL].renames["EMISSION"] = "emission";
- //actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2;
actions[VS::SHADER_SPATIAL].renames["POINT_COORD"] = "gl_PointCoord";
actions[VS::SHADER_SPATIAL].renames["INSTANCE_CUSTOM"] = "instance_custom";
actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"] = "screen_uv";
@@ -894,10 +890,9 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n";
actions[VS::SHADER_SPATIAL].usage_defines["SPECULAR_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n";
- actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength";
-
actions[VS::SHADER_SPATIAL].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n";
+ actions[VS::SHADER_SPATIAL].render_mode_defines["ensure_correct_normals"] = "#define ENSURE_CORRECT_NORMALS\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n";
@@ -912,6 +907,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n";
+ actions[VS::SHADER_SPATIAL].render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n";
/* PARTICLES SHADER */
diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp
index 08b8a1cc26..ca0ce5cd3e 100644
--- a/drivers/gles3/shader_gles3.cpp
+++ b/drivers/gles3/shader_gles3.cpp
@@ -554,7 +554,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() {
v.texture_uniform_locations.resize(cc->texture_uniforms.size());
for (int i = 0; i < cc->texture_uniforms.size(); i++) {
- v.texture_uniform_locations[i] = glGetUniformLocation(v.id, String(cc->texture_uniforms[i]).ascii().get_data());
+ v.texture_uniform_locations.write[i] = glGetUniformLocation(v.id, String(cc->texture_uniforms[i]).ascii().get_data());
glUniform1i(v.texture_uniform_locations[i], i + base_material_tex_index);
}
}
diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl
index 326aab4c7c..e7828d265c 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -82,6 +82,7 @@ layout(std140) uniform LightData { //ubo:1
out vec4 light_uv_interp;
+out vec2 transformed_light_uv;
out vec4 local_rot;
@@ -236,6 +237,13 @@ VERTEX_SHADER_CODE
light_uv_interp.xy = (light_matrix * outvec).xy;
light_uv_interp.zw =(light_local_matrix * outvec).xy;
+
+ mat3 inverse_light_matrix = mat3(inverse(light_matrix));
+ inverse_light_matrix[0] = normalize(inverse_light_matrix[0]);
+ inverse_light_matrix[1] = normalize(inverse_light_matrix[1]);
+ inverse_light_matrix[2] = normalize(inverse_light_matrix[2]);
+ transformed_light_uv = (inverse_light_matrix * vec3(light_uv_interp.zw,0.0)).xy; //for normal mapping
+
#ifdef USE_SHADOWS
pos=outvec.xy;
#endif
@@ -304,6 +312,7 @@ layout(std140) uniform LightData {
uniform lowp sampler2D light_texture; // texunit:-1
in vec4 light_uv_interp;
+in vec2 transformed_light_uv;
in vec4 local_rot;
@@ -518,10 +527,9 @@ FRAGMENT_SHADER_CODE
-
#ifdef USE_LIGHTING
- vec2 light_vec = light_uv_interp.zw;; //for shadow and normal mapping
+ vec2 light_vec = transformed_light_uv;
if (normal_used) {
normal.xy = mat2(local_rot.xy,local_rot.zw) * normal.xy;
@@ -567,7 +575,7 @@ FRAGMENT_SHADER_CODE
color*=light;
#ifdef USE_SHADOWS
-
+ light_vec = light_uv_interp.zw; //for shadows
float angle_to_light = -atan(light_vec.x,light_vec.y);
float PI = 3.14159265358979323846264;
/*int i = int(mod(floor((angle_to_light+7.0*PI/6.0)/(4.0*PI/6.0))+1.0, 3.0)); // +1 pq os indices estao em ordem 2,0,1 nos arrays
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index f5481c597c..6fd85cc1dd 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -90,6 +90,8 @@ layout(std140) uniform SceneData { //ubo:0
mediump float reflection_multiplier;
mediump float subsurface_scatter_width;
mediump float ambient_occlusion_affect_light;
+ mediump float ambient_occlusion_affect_ao_channel;
+ mediump float opaque_prepass_threshold;
bool fog_depth_enabled;
highp float fog_depth_begin;
@@ -322,7 +324,13 @@ void main() {
#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED)
vertex = world_matrix * vertex;
+
+#if defined(ENSURE_CORRECT_NORMALS)
+ mat3 normal_matrix = mat3(transpose(inverse(world_matrix)));
+ normal = normal_matrix * normal;
+#else
normal = normalize((world_matrix * vec4(normal,0.0)).xyz);
+#endif
#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
@@ -394,7 +402,13 @@ VERTEX_SHADER_CODE
#if !defined(SKIP_TRANSFORM_USED) && !defined(VERTEX_WORLD_COORDS_USED)
vertex = modelview * vertex;
+
+#if defined(ENSURE_CORRECT_NORMALS)
+ mat3 normal_matrix = mat3(transpose(inverse(modelview)));
+ normal = normal_matrix * normal;
+#else
normal = normalize((modelview * vec4(normal,0.0)).xyz);
+#endif
#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
@@ -558,11 +572,6 @@ in vec3 normal_interp;
/* PBR CHANNELS */
-//used on forward mainly
-uniform bool no_ambient_light;
-
-
-
#ifdef USE_RADIANCE_MAP
@@ -670,6 +679,8 @@ layout(std140) uniform SceneData {
mediump float reflection_multiplier;
mediump float subsurface_scatter_width;
mediump float ambient_occlusion_affect_light;
+ mediump float ambient_occlusion_affect_ao_channel;
+ mediump float opaque_prepass_threshold;
bool fog_depth_enabled;
highp float fog_depth_begin;
@@ -1017,12 +1028,11 @@ LIGHT_SHADER_CODE
diffuse_brdf_NL = cNdotL * (1.0 / M_PI);
#endif
-#if defined(TRANSMISSION_USED)
- diffuse_light += light_color * diffuse_color * mix(vec3(diffuse_brdf_NL), vec3(M_PI), transmission) * attenuation;
-#else
diffuse_light += light_color * diffuse_color * diffuse_brdf_NL * attenuation;
-#endif
+#if defined(TRANSMISSION_USED)
+ diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * transmission * attenuation;
+#endif
#if defined(LIGHT_USE_RIM)
@@ -1619,7 +1629,7 @@ void main() {
float alpha = 1.0;
#if defined(DO_SIDE_CHECK)
- float side=float(gl_FrontFacing)*2.0-1.0;
+ float side=gl_FrontFacing ? 1.0 : -1.0;
#else
float side=1.0;
#endif
@@ -1681,9 +1691,10 @@ FRAGMENT_SHADER_CODE
#ifdef USE_OPAQUE_PREPASS
- if (alpha<0.99) {
+ if (alpha<opaque_prepass_threshold) {
discard;
}
+
#endif
#if defined(ENABLE_NORMALMAP)
@@ -1738,42 +1749,43 @@ FRAGMENT_SHADER_CODE
#ifdef USE_RADIANCE_MAP
- if (no_ambient_light) {
- ambient_light=vec3(0.0,0.0,0.0);
- } else {
- {
-
- { //read radiance from dual paraboloid
+#ifdef AMBIENT_LIGHT_DISABLED
+ ambient_light=vec3(0.0,0.0,0.0);
+#else
+ {
- vec3 ref_vec = reflect(-eye_vec,normal); //2.0 * ndotv * normal - view; // reflect(v, n);
- ref_vec=normalize((radiance_inverse_xform * vec4(ref_vec,0.0)).xyz);
- vec3 radiance = textureDualParaboloid(radiance_map,ref_vec,roughness) * bg_energy;
- env_reflection_light = radiance;
+ { //read radiance from dual paraboloid
- }
- //no longer a cubemap
- //vec3 radiance = textureLod(radiance_cube, r, lod).xyz * ( brdf.x + brdf.y);
+ vec3 ref_vec = reflect(-eye_vec,normal); //2.0 * ndotv * normal - view; // reflect(v, n);
+ ref_vec=normalize((radiance_inverse_xform * vec4(ref_vec,0.0)).xyz);
+ vec3 radiance = textureDualParaboloid(radiance_map,ref_vec,roughness) * bg_energy;
+ env_reflection_light = radiance;
}
+ //no longer a cubemap
+ //vec3 radiance = textureLod(radiance_cube, r, lod).xyz * ( brdf.x + brdf.y);
+
+ }
#ifndef USE_LIGHTMAP
- {
+ {
- vec3 ambient_dir=normalize((radiance_inverse_xform * vec4(normal,0.0)).xyz);
- vec3 env_ambient=textureDualParaboloid(radiance_map,ambient_dir,1.0) * bg_energy;
+ vec3 ambient_dir=normalize((radiance_inverse_xform * vec4(normal,0.0)).xyz);
+ vec3 env_ambient=textureDualParaboloid(radiance_map,ambient_dir,1.0) * bg_energy;
- ambient_light=mix(ambient_light_color.rgb,env_ambient,radiance_ambient_contribution);
- //ambient_light=vec3(0.0,0.0,0.0);
- }
-#endif
+ ambient_light=mix(ambient_light_color.rgb,env_ambient,radiance_ambient_contribution);
+ //ambient_light=vec3(0.0,0.0,0.0);
}
+#endif
+#endif //AMBIENT_LIGHT_DISABLED
#else
- if (no_ambient_light){
- ambient_light=vec3(0.0,0.0,0.0);
- } else {
- ambient_light=ambient_light_color.rgb;
- }
+#ifdef AMBIENT_LIGHT_DISABLED
+ ambient_light=vec3(0.0,0.0,0.0);
+#else
+ ambient_light=ambient_light_color.rgb;
+#endif //AMBIENT_LIGHT_DISABLED
+
#endif
ambient_light*=ambient_energy;
@@ -2128,18 +2140,18 @@ FRAGMENT_SHADER_CODE
#else
-#if defined(ENABLE_AO)
- float ambient_scale=0.0; // AO is supplied by material
-#else
+
//approximate ambient scale for SSAO, since we will lack full ambient
float max_emission=max(emission.r,max(emission.g,emission.b));
float max_ambient=max(ambient_light.r,max(ambient_light.g,ambient_light.b));
float max_diffuse=max(diffuse_light.r,max(diffuse_light.g,diffuse_light.b));
float total_ambient = max_ambient+max_diffuse+max_emission;
float ambient_scale = (total_ambient>0.0) ? (max_ambient+ambient_occlusion_affect_light*max_diffuse)/total_ambient : 0.0;
-#endif //ENABLE_AO
+#if defined(ENABLE_AO)
+ ambient_scale=mix(0.0,ambient_scale,ambient_occlusion_affect_ao_channel);
+#endif
diffuse_buffer=vec4(emission+diffuse_light+ambient_light,ambient_scale);
specular_buffer=vec4(specular_light,metallic);
@@ -2161,7 +2173,6 @@ FRAGMENT_SHADER_CODE
frag_color=vec4(emission+ambient_light+diffuse_light+specular_light,alpha);
#endif //SHADELESS
-
#endif //USE_MULTIPLE_RENDER_TARGETS
diff --git a/drivers/gles3/shaders/tonemap.glsl b/drivers/gles3/shaders/tonemap.glsl
index a75871f08e..63475c9039 100644
--- a/drivers/gles3/shaders/tonemap.glsl
+++ b/drivers/gles3/shaders/tonemap.glsl
@@ -1,28 +1,27 @@
[vertex]
-
-layout(location=0) in highp vec4 vertex_attrib;
-layout(location=4) in vec2 uv_in;
+layout (location = 0) in highp vec4 vertex_attrib;
+layout (location = 4) in vec2 uv_in;
out vec2 uv_interp;
-void main() {
-
+void main()
+{
gl_Position = vertex_attrib;
+
uv_interp = uv_in;
-#ifdef V_FLIP
- uv_interp.y = 1.0-uv_interp.y;
-#endif
+ #ifdef V_FLIP
+ uv_interp.y = 1.0f - uv_interp.y;
+ #endif
}
[fragment]
#if !defined(GLES_OVER_GL)
-precision mediump float;
+ precision mediump float;
#endif
-
in vec2 uv_interp;
uniform highp sampler2D source; //texunit:0
@@ -31,297 +30,286 @@ uniform float exposure;
uniform float white;
#ifdef USE_AUTO_EXPOSURE
-
-uniform highp sampler2D source_auto_exposure; //texunit:1
-uniform highp float auto_exposure_grey;
-
+ uniform highp sampler2D source_auto_exposure; //texunit:1
+ uniform highp float auto_exposure_grey;
#endif
#if defined(USE_GLOW_LEVEL1) || defined(USE_GLOW_LEVEL2) || defined(USE_GLOW_LEVEL3) || defined(USE_GLOW_LEVEL4) || defined(USE_GLOW_LEVEL5) || defined(USE_GLOW_LEVEL6) || defined(USE_GLOW_LEVEL7)
+ #define USING_GLOW // only use glow when at least one glow level is selected
-uniform highp sampler2D source_glow; //texunit:2
-uniform highp float glow_intensity;
-
+ uniform highp sampler2D source_glow; //texunit:2
+ uniform highp float glow_intensity;
#endif
#ifdef USE_BCS
-
-uniform vec3 bcs;
-
+ uniform vec3 bcs;
#endif
#ifdef USE_COLOR_CORRECTION
-
-uniform sampler2D color_correction; //texunit:3
-
+ uniform sampler2D color_correction; //texunit:3
#endif
-
-layout(location = 0) out vec4 frag_color;
+layout (location = 0) out vec4 frag_color;
#ifdef USE_GLOW_FILTER_BICUBIC
+ // w0, w1, w2, and w3 are the four cubic B-spline basis functions
+ float w0(float a)
+ {
+ return (1.0f / 6.0f) * (a * (a * (-a + 3.0f) - 3.0f) + 1.0f);
+ }
-// w0, w1, w2, and w3 are the four cubic B-spline basis functions
-float w0(float a)
-{
- return (1.0/6.0)*(a*(a*(-a + 3.0) - 3.0) + 1.0);
-}
-
-float w1(float a)
-{
- return (1.0/6.0)*(a*a*(3.0*a - 6.0) + 4.0);
-}
-
-float w2(float a)
-{
- return (1.0/6.0)*(a*(a*(-3.0*a + 3.0) + 3.0) + 1.0);
-}
-
-float w3(float a)
-{
- return (1.0/6.0)*(a*a*a);
-}
-
-// g0 and g1 are the two amplitude functions
-float g0(float a)
-{
- return w0(a) + w1(a);
-}
+ float w1(float a)
+ {
+ return (1.0f / 6.0f) * (a * a * (3.0f * a - 6.0f) + 4.0f);
+ }
-float g1(float a)
-{
- return w2(a) + w3(a);
-}
+ float w2(float a)
+ {
+ return (1.0f / 6.0f) * (a * (a * (-3.0f * a + 3.0f) + 3.0f) + 1.0f);
+ }
-// h0 and h1 are the two offset functions
-float h0(float a)
-{
- return -1.0 + w1(a) / (w0(a) + w1(a));
-}
+ float w3(float a)
+ {
+ return (1.0f / 6.0f) * (a * a * a);
+ }
-float h1(float a)
-{
- return 1.0 + w3(a) / (w2(a) + w3(a));
-}
+ // g0 and g1 are the two amplitude functions
+ float g0(float a)
+ {
+ return w0(a) + w1(a);
+ }
-uniform ivec2 glow_texture_size;
+ float g1(float a)
+ {
+ return w2(a) + w3(a);
+ }
-vec4 texture2D_bicubic(sampler2D tex, vec2 uv,int p_lod)
-{
- float lod=float(p_lod);
- vec2 tex_size = vec2(glow_texture_size >> p_lod);
- vec2 pixel_size =1.0/tex_size;
- uv = uv*tex_size + 0.5;
- vec2 iuv = floor( uv );
- vec2 fuv = fract( uv );
-
- float g0x = g0(fuv.x);
- float g1x = g1(fuv.x);
- float h0x = h0(fuv.x);
- float h1x = h1(fuv.x);
- float h0y = h0(fuv.y);
- float h1y = h1(fuv.y);
-
- vec2 p0 = (vec2(iuv.x + h0x, iuv.y + h0y) - 0.5) * pixel_size;
- vec2 p1 = (vec2(iuv.x + h1x, iuv.y + h0y) - 0.5) * pixel_size;
- vec2 p2 = (vec2(iuv.x + h0x, iuv.y + h1y) - 0.5) * pixel_size;
- vec2 p3 = (vec2(iuv.x + h1x, iuv.y + h1y) - 0.5) * pixel_size;
-
- return g0(fuv.y) * (g0x * textureLod(tex, p0,lod) +
- g1x * textureLod(tex, p1,lod)) +
- g1(fuv.y) * (g0x * textureLod(tex, p2,lod) +
- g1x * textureLod(tex, p3,lod));
-}
+ // h0 and h1 are the two offset functions
+ float h0(float a)
+ {
+ return -1.0f + w1(a) / (w0(a) + w1(a));
+ }
+ float h1(float a)
+ {
+ return 1.0f + w3(a) / (w2(a) + w3(a));
+ }
+ uniform ivec2 glow_texture_size;
-#define GLOW_TEXTURE_SAMPLE(m_tex,m_uv,m_lod) texture2D_bicubic(m_tex,m_uv,m_lod)
+ vec4 texture2D_bicubic(sampler2D tex, vec2 uv, int p_lod)
+ {
+ float lod = float(p_lod);
+ vec2 tex_size = vec2(glow_texture_size >> p_lod);
+ vec2 pixel_size = vec2(1.0f) / tex_size;
+
+ uv = uv * tex_size + vec2(0.5f);
+
+ vec2 iuv = floor(uv);
+ vec2 fuv = fract(uv);
+
+ float g0x = g0(fuv.x);
+ float g1x = g1(fuv.x);
+ float h0x = h0(fuv.x);
+ float h1x = h1(fuv.x);
+ float h0y = h0(fuv.y);
+ float h1y = h1(fuv.y);
+
+ vec2 p0 = (vec2(iuv.x + h0x, iuv.y + h0y) - vec2(0.5f)) * pixel_size;
+ vec2 p1 = (vec2(iuv.x + h1x, iuv.y + h0y) - vec2(0.5f)) * pixel_size;
+ vec2 p2 = (vec2(iuv.x + h0x, iuv.y + h1y) - vec2(0.5f)) * pixel_size;
+ vec2 p3 = (vec2(iuv.x + h1x, iuv.y + h1y) - vec2(0.5f)) * pixel_size;
+
+ return g0(fuv.y) * (g0x * textureLod(tex, p0,lod) +
+ g1x * textureLod(tex, p1,lod)) +
+ g1(fuv.y) * (g0x * textureLod(tex, p2,lod) +
+ g1x * textureLod(tex, p3,lod));
+ }
+ #define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) texture2D_bicubic(m_tex, m_uv, m_lod)
#else
-
-#define GLOW_TEXTURE_SAMPLE(m_tex,m_uv,m_lod) textureLod(m_tex,m_uv,float(m_lod))
-
+ #define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) textureLod(m_tex, m_uv, float(m_lod))
#endif
+vec3 tonemap_filmic(vec3 color, float white)
+{
+ const float A = 0.15f;
+ const float B = 0.50f;
+ const float C = 0.10f;
+ const float D = 0.20f;
+ const float E = 0.02f;
+ const float F = 0.30f;
+ const float W = 11.2f;
+
+ vec3 color_tonemapped = ((color * (A * color + C * B) + D * E) / (color * (A * color + B) + D * F)) - E / F;
+ float white_tonemapped = ((white * (A * white + C * B) + D * E) / (white * (A * white + B) + D * F)) - E / F;
+
+ return clamp(color_tonemapped / white_tonemapped, vec3(0.0f), vec3(1.0f));
+}
-vec3 tonemap_filmic(vec3 color,float white) {
-
- float A = 0.15;
- float B = 0.50;
- float C = 0.10;
- float D = 0.20;
- float E = 0.02;
- float F = 0.30;
- float W = 11.2;
-
- vec3 coltn = ((color*(A*color+C*B)+D*E)/(color*(A*color+B)+D*F))-E/F;
- float whitetn = ((white*(A*white+C*B)+D*E)/(white*(A*white+B)+D*F))-E/F;
+vec3 tonemap_aces(vec3 color, float white)
+{
+ const float A = 2.51f;
+ const float B = 0.03f;
+ const float C = 2.43f;
+ const float D = 0.59f;
+ const float E = 0.14f;
- return coltn/whitetn;
+ vec3 color_tonemapped = (color * (A * color + B)) / (color * (C * color + D) + E);
+ float white_tonemapped = (white * (A * white + B)) / (white * (C * white + D) + E);
+ return clamp(color_tonemapped / white_tonemapped, vec3(0.0f), vec3(1.0f));
}
-vec3 tonemap_aces(vec3 color) {
- float a = 2.51f;
- float b = 0.03f;
- float c = 2.43f;
- float d = 0.59f;
- float e = 0.14f;
- return color = clamp((color*(a*color+b))/(color*(c*color+d)+e),vec3(0.0),vec3(1.0));
+vec3 tonemap_reindhart(vec3 color, float white)
+{
+ return clamp((color) / (1.0f + color) * (1.0f + (color / (white))), vec3(0.0f), vec3(1.0f)); // whitepoint is probably not in linear space here!
}
-vec3 tonemap_reindhart(vec3 color,float white) {
-
- return ( color * ( 1.0 + ( color / ( white) ) ) ) / ( 1.0 + color );
+vec3 linear_to_srgb(vec3 color) // convert linear rgb to srgb, assumes clamped input in range [0;1]
+{
+ const vec3 a = vec3(0.055f);
+ return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f)));
}
-void main() {
-
- vec4 color = textureLod(source, uv_interp, 0.0);
-
-#ifdef USE_AUTO_EXPOSURE
-
- color/=texelFetch(source_auto_exposure,ivec2(0,0),0).r/auto_exposure_grey;
-#endif
-
- color*=exposure;
-
-#if defined(USE_GLOW_LEVEL1) || defined(USE_GLOW_LEVEL2) || defined(USE_GLOW_LEVEL3) || defined(USE_GLOW_LEVEL4) || defined(USE_GLOW_LEVEL5) || defined(USE_GLOW_LEVEL6) || defined(USE_GLOW_LEVEL7)
-#define USING_GLOW
-#endif
-
-#if defined(USING_GLOW)
- vec3 glow = vec3(0.0);
-
-#ifdef USE_GLOW_LEVEL1
-
- glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,1).rgb;
-#endif
-
-#ifdef USE_GLOW_LEVEL2
- glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,2).rgb;
-#endif
-
-#ifdef USE_GLOW_LEVEL3
- glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,3).rgb;
-#endif
-
-#ifdef USE_GLOW_LEVEL4
- glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,4).rgb;
-#endif
-
-#ifdef USE_GLOW_LEVEL5
- glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,5).rgb;
-#endif
-
-#ifdef USE_GLOW_LEVEL6
- glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,6).rgb;
-#endif
-
-#ifdef USE_GLOW_LEVEL7
- glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,7).rgb;
-#endif
-
-
- glow *= glow_intensity;
+vec3 apply_tonemapping(vec3 color, float white) // inputs are LINEAR, always outputs clamped [0;1] color
+{
+ #ifdef USE_REINDHART_TONEMAPPER
+ return tonemap_reindhart(color, white);
+ #endif
-#endif
+ #ifdef USE_FILMIC_TONEMAPPER
+ return tonemap_filmic(color, white);
+ #endif
+ #ifdef USE_ACES_TONEMAPPER
+ return tonemap_aces(color, white);
+ #endif
-#ifdef USE_REINDHART_TONEMAPPER
+ return clamp(color, vec3(0.0f), vec3(1.0f)); // no other seleced -> linear
+}
- color.rgb = tonemap_reindhart(color.rgb,white);
+vec3 gather_glow(sampler2D tex, vec2 uv) // sample all selected glow levels
+{
+ vec3 glow = vec3(0.0f);
-# if defined(USING_GLOW)
- glow = tonemap_reindhart(glow,white);
-# endif
+ #ifdef USE_GLOW_LEVEL1
+ glow += GLOW_TEXTURE_SAMPLE(tex, uv, 1).rgb;
+ #endif
-#endif
+ #ifdef USE_GLOW_LEVEL2
+ glow += GLOW_TEXTURE_SAMPLE(tex, uv, 2).rgb;
+ #endif
-#ifdef USE_FILMIC_TONEMAPPER
+ #ifdef USE_GLOW_LEVEL3
+ glow += GLOW_TEXTURE_SAMPLE(tex, uv, 3).rgb;
+ #endif
- color.rgb = tonemap_filmic(color.rgb,white);
+ #ifdef USE_GLOW_LEVEL4
+ glow += GLOW_TEXTURE_SAMPLE(tex, uv, 4).rgb;
+ #endif
-# if defined(USING_GLOW)
- glow = tonemap_filmic(glow,white);
-# endif
+ #ifdef USE_GLOW_LEVEL5
+ glow += GLOW_TEXTURE_SAMPLE(tex, uv, 5).rgb;
+ #endif
-#endif
+ #ifdef USE_GLOW_LEVEL6
+ glow += GLOW_TEXTURE_SAMPLE(tex, uv, 6).rgb;
+ #endif
-#ifdef USE_ACES_TONEMAPPER
+ #ifdef USE_GLOW_LEVEL7
+ glow += GLOW_TEXTURE_SAMPLE(tex, uv, 7).rgb;
+ #endif
- color.rgb = tonemap_aces(color.rgb);
+ return glow;
+}
-# if defined(USING_GLOW)
- glow = tonemap_aces(glow);
-# endif
+vec3 apply_glow(vec3 color, vec3 glow) // apply glow using the selected blending mode
+{
+ #ifdef USE_GLOW_REPLACE
+ color = glow;
+ #endif
-#endif
+ #ifdef USE_GLOW_SCREEN
+ color = max((color + glow) - (color * glow), vec3(0.0));
+ #endif
-#ifdef KEEP_3D_LINEAR
- // leave color as is...
-#else
- //regular Linear -> SRGB conversion
- vec3 a = vec3(0.055);
- color.rgb = mix( (vec3(1.0)+a)*pow(color.rgb,vec3(1.0/2.4))-a , 12.92*color.rgb , lessThan(color.rgb,vec3(0.0031308)));
-#endif
+ #ifdef USE_GLOW_SOFTLIGHT
+ glow = glow * vec3(0.5f) + vec3(0.5f);
-#if defined(USING_GLOW)
- glow = mix( (vec3(1.0)+a)*pow(glow,vec3(1.0/2.4))-a , 12.92*glow , lessThan(glow,vec3(0.0031308)));
-#endif
+ color.r = (glow.r <= 0.5f) ? (color.r - (1.0f - 2.0f * glow.r) * color.r * (1.0f - color.r)) : (((glow.r > 0.5f) && (color.r <= 0.25f)) ? (color.r + (2.0f * glow.r - 1.0f) * (4.0f * color.r * (4.0f * color.r + 1.0f) * (color.r - 1.0f) + 7.0f * color.r)) : (color.r + (2.0f * glow.r - 1.0f) * (sqrt(color.r) - color.r)));
+ color.g = (glow.g <= 0.5f) ? (color.g - (1.0f - 2.0f * glow.g) * color.g * (1.0f - color.g)) : (((glow.g > 0.5f) && (color.g <= 0.25f)) ? (color.g + (2.0f * glow.g - 1.0f) * (4.0f * color.g * (4.0f * color.g + 1.0f) * (color.g - 1.0f) + 7.0f * color.g)) : (color.g + (2.0f * glow.g - 1.0f) * (sqrt(color.g) - color.g)));
+ color.b = (glow.b <= 0.5f) ? (color.b - (1.0f - 2.0f * glow.b) * color.b * (1.0f - color.b)) : (((glow.b > 0.5f) && (color.b <= 0.25f)) ? (color.b + (2.0f * glow.b - 1.0f) * (4.0f * color.b * (4.0f * color.b + 1.0f) * (color.b - 1.0f) + 7.0f * color.b)) : (color.b + (2.0f * glow.b - 1.0f) * (sqrt(color.b) - color.b)));
+ #endif
-//glow needs to be added in SRGB space (together with image space effects)
+ #if !defined(USE_GLOW_SCREEN) && !defined(USE_GLOW_SOFTLIGHT) && !defined(USE_GLOW_REPLACE) // no other selected -> additive
+ color += glow;
+ #endif
- color.rgb = clamp(color.rgb,0.0,1.0);
+ return color;
+}
-#if defined(USING_GLOW)
- glow = clamp(glow,0.0,1.0);
-#endif
+vec3 apply_bcs(vec3 color, vec3 bcs)
+{
+ color = mix(vec3(0.0f), color, bcs.x);
+ color = mix(vec3(0.5f), color, bcs.y);
+ color = mix(vec3(dot(vec3(1.0f), color) * 0.33333f), color, bcs.z);
-#ifdef USE_GLOW_REPLACE
+ return color;
+}
- color.rgb = glow;
+vec3 apply_color_correction(vec3 color, sampler2D correction_tex)
+{
+ color.r = texture(correction_tex, vec2(color.r, 0.0f)).r;
+ color.g = texture(correction_tex, vec2(color.g, 0.0f)).g;
+ color.b = texture(correction_tex, vec2(color.b, 0.0f)).b;
-#endif
+ return color;
+}
-#ifdef USE_GLOW_SCREEN
+void main()
+{
+ vec3 color = textureLod(source, uv_interp, 0.0f).rgb;
- color.rgb = max((color.rgb + glow) - (color.rgb * glow), vec3(0.0));
+ // Exposure
-#endif
+ #ifdef USE_AUTO_EXPOSURE
+ color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / auto_exposure_grey;
+ #endif
-#ifdef USE_GLOW_SOFTLIGHT
+ color *= exposure;
- {
+ // Early Tonemap & SRGB Conversion
- glow = (glow * 0.5) + 0.5;
- color.r = (glow.r <= 0.5) ? (color.r - (1.0 - 2.0 * glow.r) * color.r * (1.0 - color.r)) : (((glow.r > 0.5) && (color.r <= 0.25)) ? (color.r + (2.0 * glow.r - 1.0) * (4.0 * color.r * (4.0 * color.r + 1.0) * (color.r - 1.0) + 7.0 * color.r)) : (color.r + (2.0 * glow.r - 1.0) * (sqrt(color.r) - color.r)));
- color.g = (glow.g <= 0.5) ? (color.g - (1.0 - 2.0 * glow.g) * color.g * (1.0 - color.g)) : (((glow.g > 0.5) && (color.g <= 0.25)) ? (color.g + (2.0 * glow.g - 1.0) * (4.0 * color.g * (4.0 * color.g + 1.0) * (color.g - 1.0) + 7.0 * color.g)) : (color.g + (2.0 * glow.g - 1.0) * (sqrt(color.g) - color.g)));
- color.b = (glow.b <= 0.5) ? (color.b - (1.0 - 2.0 * glow.b) * color.b * (1.0 - color.b)) : (((glow.b > 0.5) && (color.b <= 0.25)) ? (color.b + (2.0 * glow.b - 1.0) * (4.0 * color.b * (4.0 * color.b + 1.0) * (color.b - 1.0) + 7.0 * color.b)) : (color.b + (2.0 * glow.b - 1.0) * (sqrt(color.b) - color.b)));
- }
+ color = apply_tonemapping(color, white);
-#endif
+ #ifdef KEEP_3D_LINEAR
+ // leave color as is (-> don't convert to SRGB)
+ #else
+ color = linear_to_srgb(color); // regular linear -> SRGB conversion
+ #endif
-#if defined(USING_GLOW) && !defined(USE_GLOW_SCREEN) && !defined(USE_GLOW_SOFTLIGHT) && !defined(USE_GLOW_REPLACE)
- //additive
- color.rgb+=glow;
-#endif
+ // Glow
-#ifdef USE_BCS
+ #ifdef USING_GLOW
+ vec3 glow = gather_glow(source_glow, uv_interp) * glow_intensity;
- color.rgb = mix(vec3(0.0),color.rgb,bcs.x);
- color.rgb = mix(vec3(0.5),color.rgb,bcs.y);
- color.rgb = mix(vec3(dot(vec3(1.0),color.rgb)*0.33333),color.rgb,bcs.z);
+ // high dynamic range -> SRGB
+ glow = apply_tonemapping(glow, white);
+ glow = linear_to_srgb(glow);
-#endif
+ color = apply_glow(color, glow);
+ #endif
-#ifdef USE_COLOR_CORRECTION
+ // Additional effects
- color.r = texture(color_correction,vec2(color.r,0.0)).r;
- color.g = texture(color_correction,vec2(color.g,0.0)).g;
- color.b = texture(color_correction,vec2(color.b,0.0)).b;
-#endif
+ #ifdef USE_BCS
+ color = apply_bcs(color, bcs);
+ #endif
+ #ifdef USE_COLOR_CORRECTION
+ color = apply_color_correction(color, color_correction);
+ #endif
- frag_color=vec4(color.rgb,1.0);
+ frag_color = vec4(color, 1.0f);
}