Merge pull request #60547 from BastiaanOlij/split_tonemapper_effect

Splitting tonemapper into its own class
This commit is contained in:
Rémi Verschelde 2022-04-28 08:33:44 +02:00 committed by GitHub
commit cab171c54e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 474 additions and 309 deletions

View File

@ -4,6 +4,7 @@ Import("env")
env.add_source_files(env.servers_sources, "*.cpp")
SConscript("effects/SCsub")
SConscript("forward_clustered/SCsub")
SConscript("forward_mobile/SCsub")
SConscript("shaders/SCsub")

View File

@ -0,0 +1,5 @@
#!/usr/bin/env python
Import("env")
env.add_source_files(env.servers_sources, "*.cpp")

View File

@ -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);
}

View File

@ -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

View File

@ -70,28 +70,6 @@ RID EffectsRD::_get_uniform_set_from_image(RID p_image) {
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) {
if (texture_to_uniform_set_cache.has(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);
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), 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;
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) {
if (texture_to_compute_uniform_set_cache.has(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);
}
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) {
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) {
Vector<String> luminance_reduce_modes;
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);
cube_to_dp.shader.version_free(cube_to_dp.shader_version);
sort.shader.version_free(sort.shader_version);
tonemap.shader.version_free(tonemap.shader_version);
}

View File

@ -65,7 +65,6 @@
#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/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_server.h"
@ -248,61 +247,6 @@ private:
PipelineCacheRD raster_pipeline;
} 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 {
LUMINANCE_REDUCE_READ,
LUMINANCE_REDUCE,
@ -884,9 +828,7 @@ private:
Map<TextureSamplerPair, RID> texture_sampler_to_compute_uniform_set_cache;
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_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_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);
@ -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_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 {
float radius = 1.0;
float intensity = 2.0;
@ -1017,9 +916,6 @@ public:
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 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);

View File

@ -2486,7 +2486,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
{
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()) {
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) {
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;
for (int i = 0; i < RS::MAX_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.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();
}
@ -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();
EffectsRD::TonemapSettings tonemap;
RendererRD::ToneMapper::TonemapSettings tonemap;
if (env) {
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.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();
}
@ -5838,11 +5838,17 @@ void fog() {
light_projectors_set_filter(RS::LightProjectorFilter(int(GLOBAL_GET("rendering/textures/light_projectors/filter"))));
cull_argument.set_page_pool(&cull_argument_pool);
tone_mapper = memnew(RendererRD::ToneMapper);
}
RendererSceneRenderRD::~RendererSceneRenderRD() {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
if (tone_mapper) {
memdelete(tone_mapper);
}
for (const KeyValue<int, ShadowCubemap> &E : shadow_cubemaps) {
RD::get_singleton()->free(E.value.cubemap);
}

View File

@ -35,6 +35,7 @@
#include "core/templates/rid_owner.h"
#include "servers/rendering/renderer_compositor.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_gi_rd.h"
#include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h"
@ -93,6 +94,7 @@ class RendererSceneRenderRD : public RendererSceneRender {
protected:
RendererStorageRD *storage = nullptr;
RendererRD::ToneMapper *tone_mapper = nullptr;
double time;
double time_step = 0;

View File

@ -15,3 +15,5 @@ if "RD_GLSL" in env["BUILDERS"]:
# compile shaders
for glsl_file in glsl_files:
env.RD_GLSL(glsl_file)
SConscript("effects/SCsub")

View File

@ -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)