Merge pull request #60547 from BastiaanOlij/split_tonemapper_effect
Splitting tonemapper into its own class
This commit is contained in:
commit
cab171c54e
|
@ -4,6 +4,7 @@ Import("env")
|
||||||
|
|
||||||
env.add_source_files(env.servers_sources, "*.cpp")
|
env.add_source_files(env.servers_sources, "*.cpp")
|
||||||
|
|
||||||
|
SConscript("effects/SCsub")
|
||||||
SConscript("forward_clustered/SCsub")
|
SConscript("forward_clustered/SCsub")
|
||||||
SConscript("forward_mobile/SCsub")
|
SConscript("forward_mobile/SCsub")
|
||||||
SConscript("shaders/SCsub")
|
SConscript("shaders/SCsub")
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
Import("env")
|
||||||
|
|
||||||
|
env.add_source_files(env.servers_sources, "*.cpp")
|
|
@ -0,0 +1,280 @@
|
||||||
|
/*************************************************************************/
|
||||||
|
/* tone_mapper.cpp */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2022 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 */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#include "tone_mapper.h"
|
||||||
|
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
|
||||||
|
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
|
||||||
|
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
|
||||||
|
|
||||||
|
using namespace RendererRD;
|
||||||
|
|
||||||
|
ToneMapper::ToneMapper() {
|
||||||
|
{
|
||||||
|
// Initialize tonemapper
|
||||||
|
Vector<String> tonemap_modes;
|
||||||
|
tonemap_modes.push_back("\n");
|
||||||
|
tonemap_modes.push_back("\n#define USE_GLOW_FILTER_BICUBIC\n");
|
||||||
|
tonemap_modes.push_back("\n#define USE_1D_LUT\n");
|
||||||
|
tonemap_modes.push_back("\n#define USE_GLOW_FILTER_BICUBIC\n#define USE_1D_LUT\n");
|
||||||
|
tonemap_modes.push_back("\n#define SUBPASS\n");
|
||||||
|
tonemap_modes.push_back("\n#define SUBPASS\n#define USE_1D_LUT\n");
|
||||||
|
|
||||||
|
// multiview versions of our shaders
|
||||||
|
tonemap_modes.push_back("\n#define MULTIVIEW\n");
|
||||||
|
tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_GLOW_FILTER_BICUBIC\n");
|
||||||
|
tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_1D_LUT\n");
|
||||||
|
tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_GLOW_FILTER_BICUBIC\n#define USE_1D_LUT\n");
|
||||||
|
tonemap_modes.push_back("\n#define MULTIVIEW\n#define SUBPASS\n");
|
||||||
|
tonemap_modes.push_back("\n#define MULTIVIEW\n#define SUBPASS\n#define USE_1D_LUT\n");
|
||||||
|
|
||||||
|
tonemap.shader.initialize(tonemap_modes);
|
||||||
|
|
||||||
|
if (!RendererCompositorRD::singleton->is_xr_enabled()) {
|
||||||
|
tonemap.shader.set_variant_enabled(TONEMAP_MODE_NORMAL_MULTIVIEW, false);
|
||||||
|
tonemap.shader.set_variant_enabled(TONEMAP_MODE_BICUBIC_GLOW_FILTER_MULTIVIEW, false);
|
||||||
|
tonemap.shader.set_variant_enabled(TONEMAP_MODE_1D_LUT_MULTIVIEW, false);
|
||||||
|
tonemap.shader.set_variant_enabled(TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT_MULTIVIEW, false);
|
||||||
|
tonemap.shader.set_variant_enabled(TONEMAP_MODE_SUBPASS_MULTIVIEW, false);
|
||||||
|
tonemap.shader.set_variant_enabled(TONEMAP_MODE_SUBPASS_1D_LUT_MULTIVIEW, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
tonemap.shader_version = tonemap.shader.version_create();
|
||||||
|
|
||||||
|
for (int i = 0; i < TONEMAP_MODE_MAX; i++) {
|
||||||
|
if (tonemap.shader.is_variant_enabled(i)) {
|
||||||
|
tonemap.pipelines[i].setup(tonemap.shader.version_get_shader(tonemap.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
|
||||||
|
} else {
|
||||||
|
tonemap.pipelines[i].clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO maybe centralise this in mesh_storage?
|
||||||
|
{ //create index array for copy shaders
|
||||||
|
Vector<uint8_t> pv;
|
||||||
|
pv.resize(6 * 4);
|
||||||
|
{
|
||||||
|
uint8_t *w = pv.ptrw();
|
||||||
|
int *p32 = (int *)w;
|
||||||
|
p32[0] = 0;
|
||||||
|
p32[1] = 1;
|
||||||
|
p32[2] = 2;
|
||||||
|
p32[3] = 0;
|
||||||
|
p32[4] = 2;
|
||||||
|
p32[5] = 3;
|
||||||
|
}
|
||||||
|
index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv);
|
||||||
|
index_array = RD::get_singleton()->index_array_create(index_buffer, 0, 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ToneMapper::~ToneMapper() {
|
||||||
|
RD::get_singleton()->free(index_buffer); //array gets freed as dependency
|
||||||
|
tonemap.shader.version_free(tonemap.shader_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings) {
|
||||||
|
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
|
||||||
|
ERR_FAIL_NULL(uniform_set_cache);
|
||||||
|
MaterialStorage *material_storage = MaterialStorage::get_singleton();
|
||||||
|
ERR_FAIL_NULL(material_storage);
|
||||||
|
|
||||||
|
memset(&tonemap.push_constant, 0, sizeof(TonemapPushConstant));
|
||||||
|
|
||||||
|
tonemap.push_constant.use_bcs = p_settings.use_bcs;
|
||||||
|
tonemap.push_constant.bcs[0] = p_settings.brightness;
|
||||||
|
tonemap.push_constant.bcs[1] = p_settings.contrast;
|
||||||
|
tonemap.push_constant.bcs[2] = p_settings.saturation;
|
||||||
|
|
||||||
|
tonemap.push_constant.use_glow = p_settings.use_glow;
|
||||||
|
tonemap.push_constant.glow_intensity = p_settings.glow_intensity;
|
||||||
|
tonemap.push_constant.glow_map_strength = p_settings.glow_map_strength;
|
||||||
|
tonemap.push_constant.glow_levels[0] = p_settings.glow_levels[0]; // clean this up to just pass by pointer or something
|
||||||
|
tonemap.push_constant.glow_levels[1] = p_settings.glow_levels[1];
|
||||||
|
tonemap.push_constant.glow_levels[2] = p_settings.glow_levels[2];
|
||||||
|
tonemap.push_constant.glow_levels[3] = p_settings.glow_levels[3];
|
||||||
|
tonemap.push_constant.glow_levels[4] = p_settings.glow_levels[4];
|
||||||
|
tonemap.push_constant.glow_levels[5] = p_settings.glow_levels[5];
|
||||||
|
tonemap.push_constant.glow_levels[6] = p_settings.glow_levels[6];
|
||||||
|
tonemap.push_constant.glow_texture_size[0] = p_settings.glow_texture_size.x;
|
||||||
|
tonemap.push_constant.glow_texture_size[1] = p_settings.glow_texture_size.y;
|
||||||
|
tonemap.push_constant.glow_mode = p_settings.glow_mode;
|
||||||
|
|
||||||
|
int mode = p_settings.glow_use_bicubic_upscale ? TONEMAP_MODE_BICUBIC_GLOW_FILTER : TONEMAP_MODE_NORMAL;
|
||||||
|
if (p_settings.use_1d_color_correction) {
|
||||||
|
mode += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
tonemap.push_constant.tonemapper = p_settings.tonemap_mode;
|
||||||
|
tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure;
|
||||||
|
tonemap.push_constant.exposure = p_settings.exposure;
|
||||||
|
tonemap.push_constant.white = p_settings.white;
|
||||||
|
tonemap.push_constant.auto_exposure_grey = p_settings.auto_exposure_grey;
|
||||||
|
tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;
|
||||||
|
|
||||||
|
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
|
||||||
|
|
||||||
|
tonemap.push_constant.use_fxaa = p_settings.use_fxaa;
|
||||||
|
tonemap.push_constant.use_debanding = p_settings.use_debanding;
|
||||||
|
tonemap.push_constant.pixel_size[0] = 1.0 / p_settings.texture_size.x;
|
||||||
|
tonemap.push_constant.pixel_size[1] = 1.0 / p_settings.texture_size.y;
|
||||||
|
|
||||||
|
if (p_settings.view_count > 1) {
|
||||||
|
// Use MULTIVIEW versions
|
||||||
|
mode += 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
RID default_shader = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||||
|
RID default_mipmap_shader = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||||
|
|
||||||
|
RD::Uniform u_source_color;
|
||||||
|
u_source_color.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
|
||||||
|
u_source_color.binding = 0;
|
||||||
|
u_source_color.append_id(default_shader);
|
||||||
|
u_source_color.append_id(p_source_color);
|
||||||
|
|
||||||
|
RD::Uniform u_exposure_texture;
|
||||||
|
u_exposure_texture.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
|
||||||
|
u_exposure_texture.binding = 0;
|
||||||
|
u_exposure_texture.append_id(default_shader);
|
||||||
|
u_exposure_texture.append_id(p_settings.exposure_texture);
|
||||||
|
|
||||||
|
RD::Uniform u_glow_texture;
|
||||||
|
u_glow_texture.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
|
||||||
|
u_glow_texture.binding = 0;
|
||||||
|
u_glow_texture.append_id(default_mipmap_shader);
|
||||||
|
u_glow_texture.append_id(p_settings.glow_texture);
|
||||||
|
|
||||||
|
RD::Uniform u_glow_map;
|
||||||
|
u_glow_map.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
|
||||||
|
u_glow_map.binding = 1;
|
||||||
|
u_glow_map.append_id(default_mipmap_shader);
|
||||||
|
u_glow_map.append_id(p_settings.glow_map);
|
||||||
|
|
||||||
|
RD::Uniform u_color_correction_texture;
|
||||||
|
u_color_correction_texture.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
|
||||||
|
u_color_correction_texture.binding = 0;
|
||||||
|
u_color_correction_texture.append_id(default_shader);
|
||||||
|
u_color_correction_texture.append_id(p_settings.color_correction_texture);
|
||||||
|
|
||||||
|
RID shader = tonemap.shader.version_get_shader(tonemap.shader_version, mode);
|
||||||
|
ERR_FAIL_COND(shader.is_null());
|
||||||
|
|
||||||
|
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD);
|
||||||
|
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer), false, RD::get_singleton()->draw_list_get_current_pass()));
|
||||||
|
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_color), 0);
|
||||||
|
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_exposure_texture), 1);
|
||||||
|
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 2, u_glow_texture, u_glow_map), 2);
|
||||||
|
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 3, u_color_correction_texture), 3);
|
||||||
|
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
|
||||||
|
|
||||||
|
RD::get_singleton()->draw_list_set_push_constant(draw_list, &tonemap.push_constant, sizeof(TonemapPushConstant));
|
||||||
|
RD::get_singleton()->draw_list_draw(draw_list, true);
|
||||||
|
RD::get_singleton()->draw_list_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ToneMapper::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_color, RD::FramebufferFormatID p_dst_format_id, const TonemapSettings &p_settings) {
|
||||||
|
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
|
||||||
|
ERR_FAIL_NULL(uniform_set_cache);
|
||||||
|
MaterialStorage *material_storage = MaterialStorage::get_singleton();
|
||||||
|
ERR_FAIL_NULL(material_storage);
|
||||||
|
|
||||||
|
memset(&tonemap.push_constant, 0, sizeof(TonemapPushConstant));
|
||||||
|
|
||||||
|
tonemap.push_constant.use_bcs = p_settings.use_bcs;
|
||||||
|
tonemap.push_constant.bcs[0] = p_settings.brightness;
|
||||||
|
tonemap.push_constant.bcs[1] = p_settings.contrast;
|
||||||
|
tonemap.push_constant.bcs[2] = p_settings.saturation;
|
||||||
|
|
||||||
|
ERR_FAIL_COND_MSG(p_settings.use_glow, "Glow is not supported when using subpasses.");
|
||||||
|
tonemap.push_constant.use_glow = p_settings.use_glow;
|
||||||
|
|
||||||
|
int mode = p_settings.use_1d_color_correction ? TONEMAP_MODE_SUBPASS_1D_LUT : TONEMAP_MODE_SUBPASS;
|
||||||
|
if (p_settings.view_count > 1) {
|
||||||
|
// Use MULTIVIEW versions
|
||||||
|
mode += 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
tonemap.push_constant.tonemapper = p_settings.tonemap_mode;
|
||||||
|
tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure;
|
||||||
|
tonemap.push_constant.exposure = p_settings.exposure;
|
||||||
|
tonemap.push_constant.white = p_settings.white;
|
||||||
|
tonemap.push_constant.auto_exposure_grey = p_settings.auto_exposure_grey;
|
||||||
|
|
||||||
|
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
|
||||||
|
|
||||||
|
tonemap.push_constant.use_debanding = p_settings.use_debanding;
|
||||||
|
tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;
|
||||||
|
|
||||||
|
RID default_shader = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||||
|
RID default_mipmap_shader = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||||
|
|
||||||
|
RD::Uniform u_source_color;
|
||||||
|
u_source_color.uniform_type = RD::UNIFORM_TYPE_INPUT_ATTACHMENT;
|
||||||
|
u_source_color.binding = 0;
|
||||||
|
u_source_color.append_id(p_source_color);
|
||||||
|
|
||||||
|
RD::Uniform u_exposure_texture;
|
||||||
|
u_exposure_texture.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
|
||||||
|
u_exposure_texture.binding = 0;
|
||||||
|
u_exposure_texture.append_id(default_shader);
|
||||||
|
u_exposure_texture.append_id(p_settings.exposure_texture);
|
||||||
|
|
||||||
|
RD::Uniform u_glow_texture;
|
||||||
|
u_glow_texture.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
|
||||||
|
u_glow_texture.binding = 0;
|
||||||
|
u_glow_texture.append_id(default_mipmap_shader);
|
||||||
|
u_glow_texture.append_id(p_settings.glow_texture);
|
||||||
|
|
||||||
|
RD::Uniform u_glow_map;
|
||||||
|
u_glow_map.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
|
||||||
|
u_glow_map.binding = 1;
|
||||||
|
u_glow_map.append_id(default_mipmap_shader);
|
||||||
|
u_glow_map.append_id(p_settings.glow_map);
|
||||||
|
|
||||||
|
RD::Uniform u_color_correction_texture;
|
||||||
|
u_color_correction_texture.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
|
||||||
|
u_color_correction_texture.binding = 0;
|
||||||
|
u_color_correction_texture.append_id(default_shader);
|
||||||
|
u_color_correction_texture.append_id(p_settings.color_correction_texture);
|
||||||
|
|
||||||
|
RID shader = tonemap.shader.version_get_shader(tonemap.shader_version, mode);
|
||||||
|
ERR_FAIL_COND(shader.is_null());
|
||||||
|
|
||||||
|
RD::get_singleton()->draw_list_bind_render_pipeline(p_subpass_draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, p_dst_format_id, false, RD::get_singleton()->draw_list_get_current_pass()));
|
||||||
|
RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, uniform_set_cache->get_cache(shader, 0, u_source_color), 0);
|
||||||
|
RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, uniform_set_cache->get_cache(shader, 1, u_exposure_texture), 1); // should be set to a default texture, it's ignored
|
||||||
|
RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, uniform_set_cache->get_cache(shader, 2, u_glow_texture, u_glow_map), 2); // should be set to a default texture, it's ignored
|
||||||
|
RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, uniform_set_cache->get_cache(shader, 3, u_color_correction_texture), 3);
|
||||||
|
RD::get_singleton()->draw_list_bind_index_array(p_subpass_draw_list, index_array);
|
||||||
|
|
||||||
|
RD::get_singleton()->draw_list_set_push_constant(p_subpass_draw_list, &tonemap.push_constant, sizeof(TonemapPushConstant));
|
||||||
|
RD::get_singleton()->draw_list_draw(p_subpass_draw_list, true);
|
||||||
|
}
|
|
@ -0,0 +1,155 @@
|
||||||
|
/*************************************************************************/
|
||||||
|
/* tone_mapper.h */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2022 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 */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#ifndef TONE_MAPPER_RD_H
|
||||||
|
#define TONE_MAPPER_RD_H
|
||||||
|
|
||||||
|
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
|
||||||
|
#include "servers/rendering/renderer_rd/shaders/effects/tonemap.glsl.gen.h"
|
||||||
|
#include "servers/rendering/renderer_scene_render.h"
|
||||||
|
|
||||||
|
#include "servers/rendering_server.h"
|
||||||
|
|
||||||
|
namespace RendererRD {
|
||||||
|
|
||||||
|
class ToneMapper {
|
||||||
|
private:
|
||||||
|
enum TonemapMode {
|
||||||
|
TONEMAP_MODE_NORMAL,
|
||||||
|
TONEMAP_MODE_BICUBIC_GLOW_FILTER,
|
||||||
|
TONEMAP_MODE_1D_LUT,
|
||||||
|
TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT,
|
||||||
|
TONEMAP_MODE_SUBPASS,
|
||||||
|
TONEMAP_MODE_SUBPASS_1D_LUT,
|
||||||
|
|
||||||
|
TONEMAP_MODE_NORMAL_MULTIVIEW,
|
||||||
|
TONEMAP_MODE_BICUBIC_GLOW_FILTER_MULTIVIEW,
|
||||||
|
TONEMAP_MODE_1D_LUT_MULTIVIEW,
|
||||||
|
TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT_MULTIVIEW,
|
||||||
|
TONEMAP_MODE_SUBPASS_MULTIVIEW,
|
||||||
|
TONEMAP_MODE_SUBPASS_1D_LUT_MULTIVIEW,
|
||||||
|
|
||||||
|
TONEMAP_MODE_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TonemapPushConstant {
|
||||||
|
float bcs[3]; // 12 - 12
|
||||||
|
uint32_t use_bcs; // 4 - 16
|
||||||
|
|
||||||
|
uint32_t use_glow; // 4 - 20
|
||||||
|
uint32_t use_auto_exposure; // 4 - 24
|
||||||
|
uint32_t use_color_correction; // 4 - 28
|
||||||
|
uint32_t tonemapper; // 4 - 32
|
||||||
|
|
||||||
|
uint32_t glow_texture_size[2]; // 8 - 40
|
||||||
|
float glow_intensity; // 4 - 44
|
||||||
|
float glow_map_strength; // 4 - 48
|
||||||
|
|
||||||
|
uint32_t glow_mode; // 4 - 52
|
||||||
|
float glow_levels[7]; // 28 - 80
|
||||||
|
|
||||||
|
float exposure; // 4 - 84
|
||||||
|
float white; // 4 - 88
|
||||||
|
float auto_exposure_grey; // 4 - 92
|
||||||
|
float luminance_multiplier; // 4 - 96
|
||||||
|
|
||||||
|
float pixel_size[2]; // 8 - 104
|
||||||
|
uint32_t use_fxaa; // 4 - 108
|
||||||
|
uint32_t use_debanding; // 4 - 112
|
||||||
|
};
|
||||||
|
|
||||||
|
/* tonemap actually writes to a framebuffer, which is
|
||||||
|
* better to do using the raster pipeline rather than
|
||||||
|
* compute, as that framebuffer might be in different formats
|
||||||
|
*/
|
||||||
|
struct Tonemap {
|
||||||
|
TonemapPushConstant push_constant;
|
||||||
|
TonemapShaderRD shader;
|
||||||
|
RID shader_version;
|
||||||
|
PipelineCacheRD pipelines[TONEMAP_MODE_MAX];
|
||||||
|
} tonemap;
|
||||||
|
|
||||||
|
RID index_buffer;
|
||||||
|
RID index_array;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ToneMapper();
|
||||||
|
~ToneMapper();
|
||||||
|
|
||||||
|
struct TonemapSettings {
|
||||||
|
bool use_glow = false;
|
||||||
|
enum GlowMode {
|
||||||
|
GLOW_MODE_ADD,
|
||||||
|
GLOW_MODE_SCREEN,
|
||||||
|
GLOW_MODE_SOFTLIGHT,
|
||||||
|
GLOW_MODE_REPLACE,
|
||||||
|
GLOW_MODE_MIX
|
||||||
|
};
|
||||||
|
|
||||||
|
GlowMode glow_mode = GLOW_MODE_ADD;
|
||||||
|
float glow_intensity = 1.0;
|
||||||
|
float glow_map_strength = 0.0f;
|
||||||
|
float glow_levels[7] = { 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0 };
|
||||||
|
Vector2i glow_texture_size;
|
||||||
|
bool glow_use_bicubic_upscale = false;
|
||||||
|
RID glow_texture;
|
||||||
|
RID glow_map;
|
||||||
|
|
||||||
|
RS::EnvironmentToneMapper tonemap_mode = RS::ENV_TONE_MAPPER_LINEAR;
|
||||||
|
float exposure = 1.0;
|
||||||
|
float white = 1.0;
|
||||||
|
|
||||||
|
bool use_auto_exposure = false;
|
||||||
|
float auto_exposure_grey = 0.5;
|
||||||
|
RID exposure_texture;
|
||||||
|
float luminance_multiplier = 1.0;
|
||||||
|
|
||||||
|
bool use_bcs = false;
|
||||||
|
float brightness = 1.0;
|
||||||
|
float contrast = 1.0;
|
||||||
|
float saturation = 1.0;
|
||||||
|
|
||||||
|
bool use_color_correction = false;
|
||||||
|
bool use_1d_color_correction = false;
|
||||||
|
RID color_correction_texture;
|
||||||
|
|
||||||
|
bool use_fxaa = false;
|
||||||
|
bool use_debanding = false;
|
||||||
|
Vector2i texture_size;
|
||||||
|
uint32_t view_count = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
void tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings);
|
||||||
|
void tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_color, RD::FramebufferFormatID p_dst_format_id, const TonemapSettings &p_settings);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace RendererRD
|
||||||
|
|
||||||
|
#endif // !TONE_MAPPER_RD_H
|
|
@ -70,28 +70,6 @@ RID EffectsRD::_get_uniform_set_from_image(RID p_image) {
|
||||||
return uniform_set;
|
return uniform_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
RID EffectsRD::_get_uniform_set_for_input(RID p_texture) {
|
|
||||||
if (input_to_uniform_set_cache.has(p_texture)) {
|
|
||||||
RID uniform_set = input_to_uniform_set_cache[p_texture];
|
|
||||||
if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
|
|
||||||
return uniform_set;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector<RD::Uniform> uniforms;
|
|
||||||
RD::Uniform u;
|
|
||||||
u.uniform_type = RD::UNIFORM_TYPE_INPUT_ATTACHMENT;
|
|
||||||
u.binding = 0;
|
|
||||||
u.append_id(p_texture);
|
|
||||||
uniforms.push_back(u);
|
|
||||||
// This is specific to our subpass shader
|
|
||||||
RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, tonemap.shader.version_get_shader(tonemap.shader_version, TONEMAP_MODE_SUBPASS), 0);
|
|
||||||
|
|
||||||
input_to_uniform_set_cache[p_texture] = uniform_set;
|
|
||||||
|
|
||||||
return uniform_set;
|
|
||||||
}
|
|
||||||
|
|
||||||
RID EffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) {
|
RID EffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) {
|
||||||
if (texture_to_uniform_set_cache.has(p_texture)) {
|
if (texture_to_uniform_set_cache.has(p_texture)) {
|
||||||
RID uniform_set = texture_to_uniform_set_cache[p_texture];
|
RID uniform_set = texture_to_uniform_set_cache[p_texture];
|
||||||
|
@ -108,50 +86,13 @@ RID EffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps)
|
||||||
u.append_id(p_texture);
|
u.append_id(p_texture);
|
||||||
uniforms.push_back(u);
|
uniforms.push_back(u);
|
||||||
// anything with the same configuration (one texture in binding 0 for set 0), is good
|
// anything with the same configuration (one texture in binding 0 for set 0), is good
|
||||||
RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, tonemap.shader.version_get_shader(tonemap.shader_version, 0), 0);
|
RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, 0), 0);
|
||||||
|
|
||||||
texture_to_uniform_set_cache[p_texture] = uniform_set;
|
texture_to_uniform_set_cache[p_texture] = uniform_set;
|
||||||
|
|
||||||
return uniform_set;
|
return uniform_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
RID EffectsRD::_get_uniform_set_from_texture_pair(RID p_texture1, RID p_texture2, bool p_use_mipmaps) {
|
|
||||||
TexturePair tp;
|
|
||||||
tp.texture1 = p_texture1;
|
|
||||||
tp.texture2 = p_texture2;
|
|
||||||
|
|
||||||
if (texture_pair_to_uniform_set_cache.has(tp)) {
|
|
||||||
RID uniform_set = texture_pair_to_uniform_set_cache[tp];
|
|
||||||
if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
|
|
||||||
return uniform_set;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector<RD::Uniform> uniforms;
|
|
||||||
{
|
|
||||||
RD::Uniform u;
|
|
||||||
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
|
|
||||||
u.binding = 0;
|
|
||||||
u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
|
|
||||||
u.append_id(p_texture1);
|
|
||||||
uniforms.push_back(u);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
RD::Uniform u;
|
|
||||||
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
|
|
||||||
u.binding = 1;
|
|
||||||
u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
|
|
||||||
u.append_id(p_texture2);
|
|
||||||
uniforms.push_back(u);
|
|
||||||
}
|
|
||||||
// anything with the same configuration (one texture in binding 0 for set 0), is good
|
|
||||||
RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, tonemap.shader.version_get_shader(tonemap.shader_version, 0), 2);
|
|
||||||
|
|
||||||
texture_pair_to_uniform_set_cache[tp] = uniform_set;
|
|
||||||
|
|
||||||
return uniform_set;
|
|
||||||
}
|
|
||||||
|
|
||||||
RID EffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) {
|
RID EffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) {
|
||||||
if (texture_to_compute_uniform_set_cache.has(p_texture)) {
|
if (texture_to_compute_uniform_set_cache.has(p_texture)) {
|
||||||
RID uniform_set = texture_to_compute_uniform_set_cache[p_texture];
|
RID uniform_set = texture_to_compute_uniform_set_cache[p_texture];
|
||||||
|
@ -851,105 +792,6 @@ void EffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffe
|
||||||
RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_TRANSFER);
|
RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_TRANSFER);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings) {
|
|
||||||
memset(&tonemap.push_constant, 0, sizeof(TonemapPushConstant));
|
|
||||||
|
|
||||||
tonemap.push_constant.use_bcs = p_settings.use_bcs;
|
|
||||||
tonemap.push_constant.bcs[0] = p_settings.brightness;
|
|
||||||
tonemap.push_constant.bcs[1] = p_settings.contrast;
|
|
||||||
tonemap.push_constant.bcs[2] = p_settings.saturation;
|
|
||||||
|
|
||||||
tonemap.push_constant.use_glow = p_settings.use_glow;
|
|
||||||
tonemap.push_constant.glow_intensity = p_settings.glow_intensity;
|
|
||||||
tonemap.push_constant.glow_map_strength = p_settings.glow_map_strength;
|
|
||||||
tonemap.push_constant.glow_levels[0] = p_settings.glow_levels[0]; // clean this up to just pass by pointer or something
|
|
||||||
tonemap.push_constant.glow_levels[1] = p_settings.glow_levels[1];
|
|
||||||
tonemap.push_constant.glow_levels[2] = p_settings.glow_levels[2];
|
|
||||||
tonemap.push_constant.glow_levels[3] = p_settings.glow_levels[3];
|
|
||||||
tonemap.push_constant.glow_levels[4] = p_settings.glow_levels[4];
|
|
||||||
tonemap.push_constant.glow_levels[5] = p_settings.glow_levels[5];
|
|
||||||
tonemap.push_constant.glow_levels[6] = p_settings.glow_levels[6];
|
|
||||||
tonemap.push_constant.glow_texture_size[0] = p_settings.glow_texture_size.x;
|
|
||||||
tonemap.push_constant.glow_texture_size[1] = p_settings.glow_texture_size.y;
|
|
||||||
tonemap.push_constant.glow_mode = p_settings.glow_mode;
|
|
||||||
|
|
||||||
int mode = p_settings.glow_use_bicubic_upscale ? TONEMAP_MODE_BICUBIC_GLOW_FILTER : TONEMAP_MODE_NORMAL;
|
|
||||||
if (p_settings.use_1d_color_correction) {
|
|
||||||
mode += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
tonemap.push_constant.tonemapper = p_settings.tonemap_mode;
|
|
||||||
tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure;
|
|
||||||
tonemap.push_constant.exposure = p_settings.exposure;
|
|
||||||
tonemap.push_constant.white = p_settings.white;
|
|
||||||
tonemap.push_constant.auto_exposure_grey = p_settings.auto_exposure_grey;
|
|
||||||
tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;
|
|
||||||
|
|
||||||
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
|
|
||||||
|
|
||||||
tonemap.push_constant.use_fxaa = p_settings.use_fxaa;
|
|
||||||
tonemap.push_constant.use_debanding = p_settings.use_debanding;
|
|
||||||
tonemap.push_constant.pixel_size[0] = 1.0 / p_settings.texture_size.x;
|
|
||||||
tonemap.push_constant.pixel_size[1] = 1.0 / p_settings.texture_size.y;
|
|
||||||
|
|
||||||
if (p_settings.view_count > 1) {
|
|
||||||
// Use MULTIVIEW versions
|
|
||||||
mode += 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD);
|
|
||||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer), false, RD::get_singleton()->draw_list_get_current_pass()));
|
|
||||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_color), 0);
|
|
||||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.exposure_texture), 1);
|
|
||||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture_pair(p_settings.glow_texture, p_settings.glow_map, true), 2);
|
|
||||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.color_correction_texture), 3);
|
|
||||||
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
|
|
||||||
|
|
||||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, &tonemap.push_constant, sizeof(TonemapPushConstant));
|
|
||||||
RD::get_singleton()->draw_list_draw(draw_list, true);
|
|
||||||
RD::get_singleton()->draw_list_end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EffectsRD::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_color, RD::FramebufferFormatID p_dst_format_id, const TonemapSettings &p_settings) {
|
|
||||||
memset(&tonemap.push_constant, 0, sizeof(TonemapPushConstant));
|
|
||||||
|
|
||||||
tonemap.push_constant.use_bcs = p_settings.use_bcs;
|
|
||||||
tonemap.push_constant.bcs[0] = p_settings.brightness;
|
|
||||||
tonemap.push_constant.bcs[1] = p_settings.contrast;
|
|
||||||
tonemap.push_constant.bcs[2] = p_settings.saturation;
|
|
||||||
|
|
||||||
ERR_FAIL_COND_MSG(p_settings.use_glow, "Glow is not supported when using subpasses.");
|
|
||||||
tonemap.push_constant.use_glow = p_settings.use_glow;
|
|
||||||
|
|
||||||
int mode = p_settings.use_1d_color_correction ? TONEMAP_MODE_SUBPASS_1D_LUT : TONEMAP_MODE_SUBPASS;
|
|
||||||
if (p_settings.view_count > 1) {
|
|
||||||
// Use MULTIVIEW versions
|
|
||||||
mode += 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
tonemap.push_constant.tonemapper = p_settings.tonemap_mode;
|
|
||||||
tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure;
|
|
||||||
tonemap.push_constant.exposure = p_settings.exposure;
|
|
||||||
tonemap.push_constant.white = p_settings.white;
|
|
||||||
tonemap.push_constant.auto_exposure_grey = p_settings.auto_exposure_grey;
|
|
||||||
|
|
||||||
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
|
|
||||||
|
|
||||||
tonemap.push_constant.use_debanding = p_settings.use_debanding;
|
|
||||||
tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;
|
|
||||||
|
|
||||||
RD::get_singleton()->draw_list_bind_render_pipeline(p_subpass_draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, p_dst_format_id, false, RD::get_singleton()->draw_list_get_current_pass()));
|
|
||||||
RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_for_input(p_source_color), 0);
|
|
||||||
RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_from_texture(p_settings.exposure_texture), 1); // should be set to a default texture, it's ignored
|
|
||||||
RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_from_texture_pair(p_settings.glow_texture, p_settings.glow_map, true), 2); // should be set to a default texture, it's ignored
|
|
||||||
RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_from_texture(p_settings.color_correction_texture), 3);
|
|
||||||
|
|
||||||
RD::get_singleton()->draw_list_bind_index_array(p_subpass_draw_list, index_array);
|
|
||||||
|
|
||||||
RD::get_singleton()->draw_list_set_push_constant(p_subpass_draw_list, &tonemap.push_constant, sizeof(TonemapPushConstant));
|
|
||||||
RD::get_singleton()->draw_list_draw(p_subpass_draw_list, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) {
|
void EffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) {
|
||||||
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of luminance reduction with the mobile renderer.");
|
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of luminance reduction with the mobile renderer.");
|
||||||
|
|
||||||
|
@ -2420,46 +2262,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
// Initialize tonemapper
|
|
||||||
Vector<String> tonemap_modes;
|
|
||||||
tonemap_modes.push_back("\n");
|
|
||||||
tonemap_modes.push_back("\n#define USE_GLOW_FILTER_BICUBIC\n");
|
|
||||||
tonemap_modes.push_back("\n#define USE_1D_LUT\n");
|
|
||||||
tonemap_modes.push_back("\n#define USE_GLOW_FILTER_BICUBIC\n#define USE_1D_LUT\n");
|
|
||||||
tonemap_modes.push_back("\n#define SUBPASS\n");
|
|
||||||
tonemap_modes.push_back("\n#define SUBPASS\n#define USE_1D_LUT\n");
|
|
||||||
|
|
||||||
// multiview versions of our shaders
|
|
||||||
tonemap_modes.push_back("\n#define MULTIVIEW\n");
|
|
||||||
tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_GLOW_FILTER_BICUBIC\n");
|
|
||||||
tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_1D_LUT\n");
|
|
||||||
tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_GLOW_FILTER_BICUBIC\n#define USE_1D_LUT\n");
|
|
||||||
tonemap_modes.push_back("\n#define MULTIVIEW\n#define SUBPASS\n");
|
|
||||||
tonemap_modes.push_back("\n#define MULTIVIEW\n#define SUBPASS\n#define USE_1D_LUT\n");
|
|
||||||
|
|
||||||
tonemap.shader.initialize(tonemap_modes);
|
|
||||||
|
|
||||||
if (!RendererCompositorRD::singleton->is_xr_enabled()) {
|
|
||||||
tonemap.shader.set_variant_enabled(TONEMAP_MODE_NORMAL_MULTIVIEW, false);
|
|
||||||
tonemap.shader.set_variant_enabled(TONEMAP_MODE_BICUBIC_GLOW_FILTER_MULTIVIEW, false);
|
|
||||||
tonemap.shader.set_variant_enabled(TONEMAP_MODE_1D_LUT_MULTIVIEW, false);
|
|
||||||
tonemap.shader.set_variant_enabled(TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT_MULTIVIEW, false);
|
|
||||||
tonemap.shader.set_variant_enabled(TONEMAP_MODE_SUBPASS_MULTIVIEW, false);
|
|
||||||
tonemap.shader.set_variant_enabled(TONEMAP_MODE_SUBPASS_1D_LUT_MULTIVIEW, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
tonemap.shader_version = tonemap.shader.version_create();
|
|
||||||
|
|
||||||
for (int i = 0; i < TONEMAP_MODE_MAX; i++) {
|
|
||||||
if (tonemap.shader.is_variant_enabled(i)) {
|
|
||||||
tonemap.pipelines[i].setup(tonemap.shader.version_get_shader(tonemap.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
|
|
||||||
} else {
|
|
||||||
tonemap.pipelines[i].clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prefer_raster_effects) {
|
if (prefer_raster_effects) {
|
||||||
Vector<String> luminance_reduce_modes;
|
Vector<String> luminance_reduce_modes;
|
||||||
luminance_reduce_modes.push_back("\n#define FIRST_PASS\n"); // LUMINANCE_REDUCE_FRAGMENT_FIRST
|
luminance_reduce_modes.push_back("\n#define FIRST_PASS\n"); // LUMINANCE_REDUCE_FRAGMENT_FIRST
|
||||||
|
@ -3076,5 +2878,4 @@ EffectsRD::~EffectsRD() {
|
||||||
copy_to_fb.shader.version_free(copy_to_fb.shader_version);
|
copy_to_fb.shader.version_free(copy_to_fb.shader_version);
|
||||||
cube_to_dp.shader.version_free(cube_to_dp.shader_version);
|
cube_to_dp.shader.version_free(cube_to_dp.shader_version);
|
||||||
sort.shader.version_free(sort.shader_version);
|
sort.shader.version_free(sort.shader_version);
|
||||||
tonemap.shader.version_free(tonemap.shader_version);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,6 @@
|
||||||
#include "servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl.gen.h"
|
#include "servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl.gen.h"
|
||||||
#include "servers/rendering/renderer_rd/shaders/ssil_interleave.glsl.gen.h"
|
#include "servers/rendering/renderer_rd/shaders/ssil_interleave.glsl.gen.h"
|
||||||
#include "servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl.gen.h"
|
#include "servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl.gen.h"
|
||||||
#include "servers/rendering/renderer_rd/shaders/tonemap.glsl.gen.h"
|
|
||||||
#include "servers/rendering/renderer_scene_render.h"
|
#include "servers/rendering/renderer_scene_render.h"
|
||||||
|
|
||||||
#include "servers/rendering_server.h"
|
#include "servers/rendering_server.h"
|
||||||
|
@ -248,61 +247,6 @@ private:
|
||||||
PipelineCacheRD raster_pipeline;
|
PipelineCacheRD raster_pipeline;
|
||||||
} roughness;
|
} roughness;
|
||||||
|
|
||||||
enum TonemapMode {
|
|
||||||
TONEMAP_MODE_NORMAL,
|
|
||||||
TONEMAP_MODE_BICUBIC_GLOW_FILTER,
|
|
||||||
TONEMAP_MODE_1D_LUT,
|
|
||||||
TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT,
|
|
||||||
TONEMAP_MODE_SUBPASS,
|
|
||||||
TONEMAP_MODE_SUBPASS_1D_LUT,
|
|
||||||
|
|
||||||
TONEMAP_MODE_NORMAL_MULTIVIEW,
|
|
||||||
TONEMAP_MODE_BICUBIC_GLOW_FILTER_MULTIVIEW,
|
|
||||||
TONEMAP_MODE_1D_LUT_MULTIVIEW,
|
|
||||||
TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT_MULTIVIEW,
|
|
||||||
TONEMAP_MODE_SUBPASS_MULTIVIEW,
|
|
||||||
TONEMAP_MODE_SUBPASS_1D_LUT_MULTIVIEW,
|
|
||||||
|
|
||||||
TONEMAP_MODE_MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TonemapPushConstant {
|
|
||||||
float bcs[3]; // 12 - 12
|
|
||||||
uint32_t use_bcs; // 4 - 16
|
|
||||||
|
|
||||||
uint32_t use_glow; // 4 - 20
|
|
||||||
uint32_t use_auto_exposure; // 4 - 24
|
|
||||||
uint32_t use_color_correction; // 4 - 28
|
|
||||||
uint32_t tonemapper; // 4 - 32
|
|
||||||
|
|
||||||
uint32_t glow_texture_size[2]; // 8 - 40
|
|
||||||
float glow_intensity; // 4 - 44
|
|
||||||
float glow_map_strength; // 4 - 48
|
|
||||||
|
|
||||||
uint32_t glow_mode; // 4 - 52
|
|
||||||
float glow_levels[7]; // 28 - 80
|
|
||||||
|
|
||||||
float exposure; // 4 - 84
|
|
||||||
float white; // 4 - 88
|
|
||||||
float auto_exposure_grey; // 4 - 92
|
|
||||||
float luminance_multiplier; // 4 - 96
|
|
||||||
|
|
||||||
float pixel_size[2]; // 8 - 104
|
|
||||||
uint32_t use_fxaa; // 4 - 108
|
|
||||||
uint32_t use_debanding; // 4 - 112
|
|
||||||
};
|
|
||||||
|
|
||||||
/* tonemap actually writes to a framebuffer, which is
|
|
||||||
* better to do using the raster pipeline rather than
|
|
||||||
* compute, as that framebuffer might be in different formats
|
|
||||||
*/
|
|
||||||
struct Tonemap {
|
|
||||||
TonemapPushConstant push_constant;
|
|
||||||
TonemapShaderRD shader;
|
|
||||||
RID shader_version;
|
|
||||||
PipelineCacheRD pipelines[TONEMAP_MODE_MAX];
|
|
||||||
} tonemap;
|
|
||||||
|
|
||||||
enum LuminanceReduceMode {
|
enum LuminanceReduceMode {
|
||||||
LUMINANCE_REDUCE_READ,
|
LUMINANCE_REDUCE_READ,
|
||||||
LUMINANCE_REDUCE,
|
LUMINANCE_REDUCE,
|
||||||
|
@ -884,9 +828,7 @@ private:
|
||||||
Map<TextureSamplerPair, RID> texture_sampler_to_compute_uniform_set_cache;
|
Map<TextureSamplerPair, RID> texture_sampler_to_compute_uniform_set_cache;
|
||||||
|
|
||||||
RID _get_uniform_set_from_image(RID p_texture);
|
RID _get_uniform_set_from_image(RID p_texture);
|
||||||
RID _get_uniform_set_for_input(RID p_texture);
|
|
||||||
RID _get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false);
|
RID _get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false);
|
||||||
RID _get_uniform_set_from_texture_pair(RID p_texture1, RID p_texture2, bool p_use_mipmaps = false);
|
|
||||||
RID _get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false);
|
RID _get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false);
|
||||||
RID _get_compute_uniform_set_from_texture_and_sampler(RID p_texture, RID p_sampler);
|
RID _get_compute_uniform_set_from_texture_and_sampler(RID p_texture, RID p_sampler);
|
||||||
RID _get_compute_uniform_set_from_texture_pair(RID p_texture, RID p_texture2, bool p_use_mipmaps = false);
|
RID _get_compute_uniform_set_from_texture_pair(RID p_texture, RID p_texture2, bool p_use_mipmaps = false);
|
||||||
|
@ -936,49 +878,6 @@ public:
|
||||||
void bokeh_dof(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RS::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
|
void bokeh_dof(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RS::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
|
||||||
void bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
|
void bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
|
||||||
|
|
||||||
struct TonemapSettings {
|
|
||||||
bool use_glow = false;
|
|
||||||
enum GlowMode {
|
|
||||||
GLOW_MODE_ADD,
|
|
||||||
GLOW_MODE_SCREEN,
|
|
||||||
GLOW_MODE_SOFTLIGHT,
|
|
||||||
GLOW_MODE_REPLACE,
|
|
||||||
GLOW_MODE_MIX
|
|
||||||
};
|
|
||||||
|
|
||||||
GlowMode glow_mode = GLOW_MODE_ADD;
|
|
||||||
float glow_intensity = 1.0;
|
|
||||||
float glow_map_strength = 0.0f;
|
|
||||||
float glow_levels[7] = { 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0 };
|
|
||||||
Vector2i glow_texture_size;
|
|
||||||
bool glow_use_bicubic_upscale = false;
|
|
||||||
RID glow_texture;
|
|
||||||
RID glow_map;
|
|
||||||
|
|
||||||
RS::EnvironmentToneMapper tonemap_mode = RS::ENV_TONE_MAPPER_LINEAR;
|
|
||||||
float exposure = 1.0;
|
|
||||||
float white = 1.0;
|
|
||||||
|
|
||||||
bool use_auto_exposure = false;
|
|
||||||
float auto_exposure_grey = 0.5;
|
|
||||||
RID exposure_texture;
|
|
||||||
float luminance_multiplier = 1.0;
|
|
||||||
|
|
||||||
bool use_bcs = false;
|
|
||||||
float brightness = 1.0;
|
|
||||||
float contrast = 1.0;
|
|
||||||
float saturation = 1.0;
|
|
||||||
|
|
||||||
bool use_color_correction = false;
|
|
||||||
bool use_1d_color_correction = false;
|
|
||||||
RID color_correction_texture;
|
|
||||||
|
|
||||||
bool use_fxaa = false;
|
|
||||||
bool use_debanding = false;
|
|
||||||
Vector2i texture_size;
|
|
||||||
uint32_t view_count = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SSAOSettings {
|
struct SSAOSettings {
|
||||||
float radius = 1.0;
|
float radius = 1.0;
|
||||||
float intensity = 2.0;
|
float intensity = 2.0;
|
||||||
|
@ -1017,9 +916,6 @@ public:
|
||||||
Size2i quarter_screen_size = Size2i();
|
Size2i quarter_screen_size = Size2i();
|
||||||
};
|
};
|
||||||
|
|
||||||
void tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings);
|
|
||||||
void tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_color, RD::FramebufferFormatID p_dst_format_id, const TonemapSettings &p_settings);
|
|
||||||
|
|
||||||
void downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const CameraMatrix &p_projection);
|
void downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const CameraMatrix &p_projection);
|
||||||
|
|
||||||
void gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set);
|
void gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set);
|
||||||
|
|
|
@ -2486,7 +2486,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
||||||
{
|
{
|
||||||
RD::get_singleton()->draw_command_begin_label("Tonemap");
|
RD::get_singleton()->draw_command_begin_label("Tonemap");
|
||||||
|
|
||||||
EffectsRD::TonemapSettings tonemap;
|
RendererRD::ToneMapper::TonemapSettings tonemap;
|
||||||
|
|
||||||
if (can_use_effects && env && env->auto_exposure && rb->luminance.current.is_valid()) {
|
if (can_use_effects && env && env->auto_exposure && rb->luminance.current.is_valid()) {
|
||||||
tonemap.use_auto_exposure = true;
|
tonemap.use_auto_exposure = true;
|
||||||
|
@ -2498,7 +2498,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
||||||
|
|
||||||
if (can_use_effects && env && env->glow_enabled) {
|
if (can_use_effects && env && env->glow_enabled) {
|
||||||
tonemap.use_glow = true;
|
tonemap.use_glow = true;
|
||||||
tonemap.glow_mode = EffectsRD::TonemapSettings::GlowMode(env->glow_blend_mode);
|
tonemap.glow_mode = RendererRD::ToneMapper::TonemapSettings::GlowMode(env->glow_blend_mode);
|
||||||
tonemap.glow_intensity = env->glow_blend_mode == RS::ENV_GLOW_BLEND_MODE_MIX ? env->glow_mix : env->glow_intensity;
|
tonemap.glow_intensity = env->glow_blend_mode == RS::ENV_GLOW_BLEND_MODE_MIX ? env->glow_mix : env->glow_intensity;
|
||||||
for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) {
|
for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) {
|
||||||
tonemap.glow_levels[i] = env->glow_levels[i];
|
tonemap.glow_levels[i] = env->glow_levels[i];
|
||||||
|
@ -2556,7 +2556,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
||||||
tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
|
tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
|
||||||
tonemap.view_count = p_render_data->view_count;
|
tonemap.view_count = p_render_data->view_count;
|
||||||
|
|
||||||
storage->get_effects()->tonemapper(rb->internal_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
|
tone_mapper->tonemapper(rb->internal_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
|
||||||
|
|
||||||
RD::get_singleton()->draw_command_end_label();
|
RD::get_singleton()->draw_command_end_label();
|
||||||
}
|
}
|
||||||
|
@ -2587,7 +2587,7 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
|
||||||
|
|
||||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass();
|
RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass();
|
||||||
|
|
||||||
EffectsRD::TonemapSettings tonemap;
|
RendererRD::ToneMapper::TonemapSettings tonemap;
|
||||||
|
|
||||||
if (env) {
|
if (env) {
|
||||||
tonemap.tonemap_mode = env->tone_mapper;
|
tonemap.tonemap_mode = env->tone_mapper;
|
||||||
|
@ -2637,7 +2637,7 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
|
||||||
tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
|
tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
|
||||||
tonemap.view_count = p_render_data->view_count;
|
tonemap.view_count = p_render_data->view_count;
|
||||||
|
|
||||||
storage->get_effects()->tonemapper(draw_list, p_source_texture, RD::get_singleton()->framebuffer_get_format(p_framebuffer), tonemap);
|
tone_mapper->tonemapper(draw_list, p_source_texture, RD::get_singleton()->framebuffer_get_format(p_framebuffer), tonemap);
|
||||||
|
|
||||||
RD::get_singleton()->draw_command_end_label();
|
RD::get_singleton()->draw_command_end_label();
|
||||||
}
|
}
|
||||||
|
@ -5838,11 +5838,17 @@ void fog() {
|
||||||
light_projectors_set_filter(RS::LightProjectorFilter(int(GLOBAL_GET("rendering/textures/light_projectors/filter"))));
|
light_projectors_set_filter(RS::LightProjectorFilter(int(GLOBAL_GET("rendering/textures/light_projectors/filter"))));
|
||||||
|
|
||||||
cull_argument.set_page_pool(&cull_argument_pool);
|
cull_argument.set_page_pool(&cull_argument_pool);
|
||||||
|
|
||||||
|
tone_mapper = memnew(RendererRD::ToneMapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
RendererSceneRenderRD::~RendererSceneRenderRD() {
|
RendererSceneRenderRD::~RendererSceneRenderRD() {
|
||||||
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
|
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
|
||||||
|
|
||||||
|
if (tone_mapper) {
|
||||||
|
memdelete(tone_mapper);
|
||||||
|
}
|
||||||
|
|
||||||
for (const KeyValue<int, ShadowCubemap> &E : shadow_cubemaps) {
|
for (const KeyValue<int, ShadowCubemap> &E : shadow_cubemaps) {
|
||||||
RD::get_singleton()->free(E.value.cubemap);
|
RD::get_singleton()->free(E.value.cubemap);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "core/templates/rid_owner.h"
|
#include "core/templates/rid_owner.h"
|
||||||
#include "servers/rendering/renderer_compositor.h"
|
#include "servers/rendering/renderer_compositor.h"
|
||||||
#include "servers/rendering/renderer_rd/cluster_builder_rd.h"
|
#include "servers/rendering/renderer_rd/cluster_builder_rd.h"
|
||||||
|
#include "servers/rendering/renderer_rd/effects/tone_mapper.h"
|
||||||
#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h"
|
#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h"
|
||||||
#include "servers/rendering/renderer_rd/renderer_scene_gi_rd.h"
|
#include "servers/rendering/renderer_rd/renderer_scene_gi_rd.h"
|
||||||
#include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h"
|
#include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h"
|
||||||
|
@ -93,6 +94,7 @@ class RendererSceneRenderRD : public RendererSceneRender {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
RendererStorageRD *storage = nullptr;
|
RendererStorageRD *storage = nullptr;
|
||||||
|
RendererRD::ToneMapper *tone_mapper = nullptr;
|
||||||
double time;
|
double time;
|
||||||
double time_step = 0;
|
double time_step = 0;
|
||||||
|
|
||||||
|
|
|
@ -15,3 +15,5 @@ if "RD_GLSL" in env["BUILDERS"]:
|
||||||
# compile shaders
|
# compile shaders
|
||||||
for glsl_file in glsl_files:
|
for glsl_file in glsl_files:
|
||||||
env.RD_GLSL(glsl_file)
|
env.RD_GLSL(glsl_file)
|
||||||
|
|
||||||
|
SConscript("effects/SCsub")
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
Import("env")
|
||||||
|
|
||||||
|
if "RD_GLSL" in env["BUILDERS"]:
|
||||||
|
# find all include files
|
||||||
|
gl_include_files = [str(f) for f in Glob("*_inc.glsl")]
|
||||||
|
|
||||||
|
# find all shader code(all glsl files excluding our include files)
|
||||||
|
glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files]
|
||||||
|
|
||||||
|
# make sure we recompile shaders if include files change
|
||||||
|
env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files)
|
||||||
|
|
||||||
|
# compile shaders
|
||||||
|
for glsl_file in glsl_files:
|
||||||
|
env.RD_GLSL(glsl_file)
|
Loading…
Reference in New Issue