Merge pull request #50942 from BastiaanOlij/cubemap_raster
Porting cubemap compute shaders to raster for the mobile renderer
This commit is contained in:
commit
dbd1a90bd4
|
@ -37,6 +37,10 @@
|
|||
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
|
||||
#include "thirdparty/misc/cubemap_coeffs.h"
|
||||
|
||||
bool EffectsRD::get_prefer_raster_effects() {
|
||||
return prefer_raster_effects;
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
|
@ -454,7 +458,7 @@ void EffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const
|
|||
}
|
||||
|
||||
void EffectsRD::gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
|
||||
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the fragment version of the gaussian glow with the clustered renderer.");
|
||||
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian glow with the clustered renderer.");
|
||||
|
||||
memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
|
||||
|
||||
|
@ -832,7 +836,7 @@ void EffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_
|
|||
}
|
||||
|
||||
void EffectsRD::luminance_reduction_raster(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, Vector<RID> p_fb, 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 fragment version of luminance reduction with the clustered renderer.");
|
||||
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use raster version of luminance reduction with the clustered renderer.");
|
||||
ERR_FAIL_COND_MSG(p_reduce.size() != p_fb.size(), "Incorrect frame buffer account for luminance reduction.");
|
||||
|
||||
luminance_reduce_raster.push_constant.max_luminance = p_max_luminance;
|
||||
|
@ -1447,7 +1451,9 @@ void EffectsRD::roughness_limit(RID p_source_normal, RID p_roughness, const Size
|
|||
RD::get_singleton()->compute_list_end();
|
||||
}
|
||||
|
||||
void EffectsRD::cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size) {
|
||||
void EffectsRD::cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size) {
|
||||
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute based cubemap roughness with the mobile renderer.");
|
||||
|
||||
memset(&roughness.push_constant, 0, sizeof(CubemapRoughnessPushConstant));
|
||||
|
||||
roughness.push_constant.face_id = p_face_id > 9 ? 0 : p_face_id;
|
||||
|
@ -1457,10 +1463,10 @@ void EffectsRD::cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffe
|
|||
roughness.push_constant.face_size = p_size;
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, roughness.pipeline);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, roughness.compute_pipeline);
|
||||
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_framebuffer), 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 1);
|
||||
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &roughness.push_constant, sizeof(CubemapRoughnessPushConstant));
|
||||
|
||||
|
@ -1472,11 +1478,37 @@ void EffectsRD::cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffe
|
|||
RD::get_singleton()->compute_list_end();
|
||||
}
|
||||
|
||||
void EffectsRD::cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size) {
|
||||
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use raster based cubemap roughness with the clustered renderer.");
|
||||
ERR_FAIL_COND_MSG(p_face_id >= 6, "Raster implementation of cubemap roughness must process one side at a time.");
|
||||
|
||||
memset(&roughness.push_constant, 0, sizeof(CubemapRoughnessPushConstant));
|
||||
|
||||
roughness.push_constant.face_id = p_face_id;
|
||||
roughness.push_constant.roughness = p_roughness;
|
||||
roughness.push_constant.sample_count = p_sample_count;
|
||||
roughness.push_constant.use_direct_write = p_roughness == 0.0;
|
||||
roughness.push_constant.face_size = p_size;
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, roughness.raster_pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
|
||||
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
|
||||
|
||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, &roughness.push_constant, sizeof(CubemapRoughnessPushConstant));
|
||||
|
||||
RD::get_singleton()->draw_list_draw(draw_list, true);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
|
||||
void EffectsRD::cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size) {
|
||||
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute based cubemap downsample with the mobile renderer.");
|
||||
|
||||
cubemap_downsampler.push_constant.face_size = p_size.x;
|
||||
cubemap_downsampler.push_constant.face_id = 0; // we render all 6 sides to each layer in one call
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, cubemap_downsampler.pipeline);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, cubemap_downsampler.compute_pipeline);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_cubemap), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_cubemap), 1);
|
||||
|
||||
|
@ -1490,7 +1522,27 @@ void EffectsRD::cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, con
|
|||
RD::get_singleton()->compute_list_end();
|
||||
}
|
||||
|
||||
void EffectsRD::cubemap_downsample_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, const Size2i &p_size) {
|
||||
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use raster based cubemap downsample with the clustered renderer.");
|
||||
ERR_FAIL_COND_MSG(p_face_id >= 6, "Raster implementation of cubemap downsample must process one side at a time.");
|
||||
|
||||
cubemap_downsampler.push_constant.face_size = p_size.x;
|
||||
cubemap_downsampler.push_constant.face_id = p_face_id;
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, cubemap_downsampler.raster_pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_cubemap), 0);
|
||||
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
|
||||
|
||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, &cubemap_downsampler.push_constant, sizeof(CubemapDownsamplerPushConstant));
|
||||
|
||||
RD::get_singleton()->draw_list_draw(draw_list, true);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
|
||||
void EffectsRD::cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array) {
|
||||
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute based cubemap filter with the mobile renderer.");
|
||||
|
||||
Vector<RD::Uniform> uniforms;
|
||||
for (int i = 0; i < p_dest_cubemap.size(); i++) {
|
||||
RD::Uniform u;
|
||||
|
@ -1502,12 +1554,12 @@ void EffectsRD::cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap,
|
|||
if (RD::get_singleton()->uniform_set_is_valid(filter.image_uniform_set)) {
|
||||
RD::get_singleton()->free(filter.image_uniform_set);
|
||||
}
|
||||
filter.image_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.shader.version_get_shader(filter.shader_version, 0), 2);
|
||||
filter.image_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.compute_shader.version_get_shader(filter.shader_version, 0), 2);
|
||||
|
||||
int pipeline = p_use_array ? FILTER_MODE_HIGH_QUALITY_ARRAY : FILTER_MODE_HIGH_QUALITY;
|
||||
pipeline = filter.use_high_quality ? pipeline : pipeline + 1;
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, filter.pipelines[pipeline]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, filter.compute_pipelines[pipeline]);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_cubemap, true), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, filter.uniform_set, 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, filter.image_uniform_set, 2);
|
||||
|
@ -1519,6 +1571,29 @@ void EffectsRD::cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap,
|
|||
RD::get_singleton()->compute_list_end();
|
||||
}
|
||||
|
||||
void EffectsRD::cubemap_filter_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_mip_level) {
|
||||
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use raster based cubemap filter with the clustered renderer.");
|
||||
ERR_FAIL_COND_MSG(p_face_id >= 6, "Raster implementation of cubemap filter must process one side at a time.");
|
||||
|
||||
// TODO implement!
|
||||
CubemapFilterRasterPushConstant push_constant;
|
||||
push_constant.mip_level = p_mip_level;
|
||||
push_constant.face_id = p_face_id;
|
||||
|
||||
CubemapFilterMode mode = filter.use_high_quality ? FILTER_MODE_HIGH_QUALITY : FILTER_MODE_LOW_QUALITY;
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, filter.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_cubemap), 0);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, filter.uniform_set, 1);
|
||||
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
|
||||
|
||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(CubemapFilterRasterPushConstant));
|
||||
|
||||
RD::get_singleton()->draw_list_draw(draw_list, true);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
|
||||
void EffectsRD::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier) {
|
||||
ResolvePushConstant push_constant;
|
||||
push_constant.screen_size[0] = p_screen_size.x;
|
||||
|
@ -1713,11 +1788,22 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
|
|||
// Initialize roughness
|
||||
Vector<String> cubemap_roughness_modes;
|
||||
cubemap_roughness_modes.push_back("");
|
||||
roughness.shader.initialize(cubemap_roughness_modes);
|
||||
|
||||
roughness.shader_version = roughness.shader.version_create();
|
||||
if (prefer_raster_effects) {
|
||||
roughness.raster_shader.initialize(cubemap_roughness_modes);
|
||||
|
||||
roughness.pipeline = RD::get_singleton()->compute_pipeline_create(roughness.shader.version_get_shader(roughness.shader_version, 0));
|
||||
roughness.shader_version = roughness.raster_shader.version_create();
|
||||
|
||||
roughness.raster_pipeline.setup(roughness.raster_shader.version_get_shader(roughness.shader_version, 0), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
|
||||
|
||||
} else {
|
||||
roughness.compute_shader.initialize(cubemap_roughness_modes);
|
||||
|
||||
roughness.shader_version = roughness.compute_shader.version_create();
|
||||
|
||||
roughness.compute_pipeline = RD::get_singleton()->compute_pipeline_create(roughness.compute_shader.version_get_shader(roughness.shader_version, 0));
|
||||
roughness.raster_pipeline.clear();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -1983,11 +2069,21 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
|
|||
//Initialize cubemap downsampler
|
||||
Vector<String> cubemap_downsampler_modes;
|
||||
cubemap_downsampler_modes.push_back("");
|
||||
cubemap_downsampler.shader.initialize(cubemap_downsampler_modes);
|
||||
|
||||
cubemap_downsampler.shader_version = cubemap_downsampler.shader.version_create();
|
||||
if (prefer_raster_effects) {
|
||||
cubemap_downsampler.raster_shader.initialize(cubemap_downsampler_modes);
|
||||
|
||||
cubemap_downsampler.pipeline = RD::get_singleton()->compute_pipeline_create(cubemap_downsampler.shader.version_get_shader(cubemap_downsampler.shader_version, 0));
|
||||
cubemap_downsampler.shader_version = cubemap_downsampler.raster_shader.version_create();
|
||||
|
||||
cubemap_downsampler.raster_pipeline.setup(cubemap_downsampler.raster_shader.version_get_shader(cubemap_downsampler.shader_version, 0), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
|
||||
} else {
|
||||
cubemap_downsampler.compute_shader.initialize(cubemap_downsampler_modes);
|
||||
|
||||
cubemap_downsampler.shader_version = cubemap_downsampler.compute_shader.version_create();
|
||||
|
||||
cubemap_downsampler.compute_pipeline = RD::get_singleton()->compute_pipeline_create(cubemap_downsampler.compute_shader.version_get_shader(cubemap_downsampler.shader_version, 0));
|
||||
cubemap_downsampler.raster_pipeline.clear();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -1999,12 +2095,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
|
|||
cubemap_filter_modes.push_back("\n#define USE_LOW_QUALITY\n");
|
||||
cubemap_filter_modes.push_back("\n#define USE_HIGH_QUALITY\n#define USE_TEXTURE_ARRAY\n");
|
||||
cubemap_filter_modes.push_back("\n#define USE_LOW_QUALITY\n#define USE_TEXTURE_ARRAY\n");
|
||||
filter.shader.initialize(cubemap_filter_modes);
|
||||
filter.shader_version = filter.shader.version_create();
|
||||
|
||||
for (int i = 0; i < FILTER_MODE_MAX; i++) {
|
||||
filter.pipelines[i] = RD::get_singleton()->compute_pipeline_create(filter.shader.version_get_shader(filter.shader_version, i));
|
||||
}
|
||||
|
||||
if (filter.use_high_quality) {
|
||||
filter.coefficient_buffer = RD::get_singleton()->storage_buffer_create(sizeof(high_quality_coeffs));
|
||||
|
@ -2014,15 +2104,50 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
|
|||
RD::get_singleton()->buffer_update(filter.coefficient_buffer, 0, sizeof(low_quality_coeffs), &low_quality_coeffs[0]);
|
||||
}
|
||||
|
||||
Vector<RD::Uniform> uniforms;
|
||||
{
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
|
||||
u.binding = 0;
|
||||
u.ids.push_back(filter.coefficient_buffer);
|
||||
uniforms.push_back(u);
|
||||
if (prefer_raster_effects) {
|
||||
filter.raster_shader.initialize(cubemap_filter_modes);
|
||||
filter.shader_version = filter.raster_shader.version_create();
|
||||
|
||||
// array variants are not supported in raster
|
||||
filter.raster_shader.set_variant_enabled(FILTER_MODE_HIGH_QUALITY_ARRAY, false);
|
||||
filter.raster_shader.set_variant_enabled(FILTER_MODE_LOW_QUALITY_ARRAY, false);
|
||||
|
||||
for (int i = 0; i < FILTER_MODE_MAX; i++) {
|
||||
if (filter.raster_shader.is_variant_enabled(i)) {
|
||||
filter.raster_pipelines[i].setup(filter.raster_shader.version_get_shader(filter.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
|
||||
} else {
|
||||
filter.raster_pipelines[i].clear();
|
||||
}
|
||||
}
|
||||
|
||||
Vector<RD::Uniform> uniforms;
|
||||
{
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
|
||||
u.binding = 0;
|
||||
u.ids.push_back(filter.coefficient_buffer);
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.raster_shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1);
|
||||
} else {
|
||||
filter.compute_shader.initialize(cubemap_filter_modes);
|
||||
filter.shader_version = filter.compute_shader.version_create();
|
||||
|
||||
for (int i = 0; i < FILTER_MODE_MAX; i++) {
|
||||
filter.compute_pipelines[i] = RD::get_singleton()->compute_pipeline_create(filter.compute_shader.version_get_shader(filter.shader_version, i));
|
||||
filter.raster_pipelines[i].clear();
|
||||
}
|
||||
|
||||
Vector<RD::Uniform> uniforms;
|
||||
{
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
|
||||
u.binding = 0;
|
||||
u.ids.push_back(filter.coefficient_buffer);
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.compute_shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1);
|
||||
}
|
||||
filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1);
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -2199,17 +2324,20 @@ EffectsRD::~EffectsRD() {
|
|||
if (prefer_raster_effects) {
|
||||
blur_raster.shader.version_free(blur_raster.shader_version);
|
||||
luminance_reduce_raster.shader.version_free(luminance_reduce_raster.shader_version);
|
||||
roughness.raster_shader.version_free(roughness.shader_version);
|
||||
cubemap_downsampler.raster_shader.version_free(cubemap_downsampler.shader_version);
|
||||
filter.raster_shader.version_free(filter.shader_version);
|
||||
} else {
|
||||
bokeh.shader.version_free(bokeh.shader_version);
|
||||
luminance_reduce.shader.version_free(luminance_reduce.shader_version);
|
||||
roughness.compute_shader.version_free(roughness.shader_version);
|
||||
cubemap_downsampler.compute_shader.version_free(cubemap_downsampler.shader_version);
|
||||
filter.compute_shader.version_free(filter.shader_version);
|
||||
}
|
||||
copy.shader.version_free(copy.shader_version);
|
||||
copy_to_fb.shader.version_free(copy_to_fb.shader_version);
|
||||
cube_to_dp.shader.version_free(cube_to_dp.shader_version);
|
||||
cubemap_downsampler.shader.version_free(cubemap_downsampler.shader_version);
|
||||
filter.shader.version_free(filter.shader_version);
|
||||
resolve.shader.version_free(resolve.shader_version);
|
||||
roughness.shader.version_free(roughness.shader_version);
|
||||
roughness_limiter.shader.version_free(roughness_limiter.shader_version);
|
||||
sort.shader.version_free(sort.shader_version);
|
||||
specular_merge.shader.version_free(specular_merge.shader_version);
|
||||
|
|
|
@ -39,8 +39,11 @@
|
|||
#include "servers/rendering/renderer_rd/shaders/copy_to_fb.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/cube_to_dp.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/cubemap_downsampler_raster.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/cubemap_filter.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/cubemap_filter_raster.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/cubemap_roughness_raster.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/luminance_reduce.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/resolve.glsl.gen.h"
|
||||
|
@ -62,6 +65,9 @@
|
|||
#include "servers/rendering_server.h"
|
||||
|
||||
class EffectsRD {
|
||||
private:
|
||||
bool prefer_raster_effects;
|
||||
|
||||
enum BlurRasterMode {
|
||||
BLUR_MODE_GAUSSIAN_BLUR,
|
||||
BLUR_MODE_GAUSSIAN_GLOW,
|
||||
|
@ -220,9 +226,11 @@ class EffectsRD {
|
|||
|
||||
struct CubemapRoughness {
|
||||
CubemapRoughnessPushConstant push_constant;
|
||||
CubemapRoughnessShaderRD shader;
|
||||
CubemapRoughnessShaderRD compute_shader;
|
||||
CubemapRoughnessRasterShaderRD raster_shader;
|
||||
RID shader_version;
|
||||
RID pipeline;
|
||||
RID compute_pipeline;
|
||||
PipelineCacheRD raster_pipeline;
|
||||
} roughness;
|
||||
|
||||
enum TonemapMode {
|
||||
|
@ -508,15 +516,17 @@ class EffectsRD {
|
|||
|
||||
struct CubemapDownsamplerPushConstant {
|
||||
uint32_t face_size;
|
||||
float pad[3];
|
||||
uint32_t face_id;
|
||||
float pad[2];
|
||||
};
|
||||
|
||||
struct CubemapDownsampler {
|
||||
CubemapDownsamplerPushConstant push_constant;
|
||||
CubemapDownsamplerShaderRD shader;
|
||||
CubemapDownsamplerShaderRD compute_shader;
|
||||
CubemapDownsamplerRasterShaderRD raster_shader;
|
||||
RID shader_version;
|
||||
RID pipeline;
|
||||
|
||||
RID compute_pipeline;
|
||||
PipelineCacheRD raster_pipeline;
|
||||
} cubemap_downsampler;
|
||||
|
||||
enum CubemapFilterMode {
|
||||
|
@ -527,10 +537,19 @@ class EffectsRD {
|
|||
FILTER_MODE_MAX,
|
||||
};
|
||||
|
||||
struct CubemapFilterRasterPushConstant {
|
||||
uint32_t mip_level;
|
||||
uint32_t face_id;
|
||||
float pad[2];
|
||||
};
|
||||
|
||||
struct CubemapFilter {
|
||||
CubemapFilterShaderRD shader;
|
||||
CubemapFilterShaderRD compute_shader;
|
||||
CubemapFilterRasterShaderRD raster_shader;
|
||||
RID shader_version;
|
||||
RID pipelines[FILTER_MODE_MAX];
|
||||
RID compute_pipelines[FILTER_MODE_MAX];
|
||||
PipelineCacheRD raster_pipelines[FILTER_MODE_MAX];
|
||||
|
||||
RID uniform_set;
|
||||
RID image_uniform_set;
|
||||
RID coefficient_buffer;
|
||||
|
@ -738,9 +757,9 @@ class EffectsRD {
|
|||
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_image_pair(RID p_texture, RID p_texture2);
|
||||
|
||||
bool prefer_raster_effects;
|
||||
|
||||
public:
|
||||
bool get_prefer_raster_effects();
|
||||
|
||||
void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID());
|
||||
void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false, bool p_alpha_to_one = false);
|
||||
void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array);
|
||||
|
@ -752,7 +771,8 @@ public:
|
|||
void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
|
||||
void gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
|
||||
|
||||
void cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
|
||||
void cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
|
||||
void cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
|
||||
void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
|
||||
void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_texture, const Rect2 &p_rect, float p_z_near, float p_z_far, bool p_dp_flip);
|
||||
void 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 = false);
|
||||
|
@ -828,7 +848,9 @@ public:
|
|||
|
||||
void roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve);
|
||||
void cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size);
|
||||
void cubemap_downsample_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, const Size2i &p_size);
|
||||
void cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array);
|
||||
void cubemap_filter_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_mip_level);
|
||||
|
||||
void screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera);
|
||||
void merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection);
|
||||
|
|
|
@ -2325,6 +2325,8 @@ RenderForwardMobile::RenderForwardMobile(RendererStorageRD *p_storage) :
|
|||
RendererSceneRenderRD(p_storage) {
|
||||
singleton = this;
|
||||
|
||||
sky.set_texture_format(_render_buffers_get_color_format());
|
||||
|
||||
String defines;
|
||||
|
||||
defines += "\n#define MAX_ROUGHNESS_LOD " + itos(get_roughness_layers() - 1) + ".0\n";
|
||||
|
|
|
@ -629,6 +629,8 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc
|
|||
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
|
||||
ERR_FAIL_COND_V(!rpi, false);
|
||||
|
||||
RD::get_singleton()->draw_command_begin_label("Reflection probe render");
|
||||
|
||||
if (storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->size != 256) {
|
||||
WARN_PRINT("ReflectionProbes set to UPDATE_ALWAYS must have an atlas size of 256. Please update the atlas size in the ProjectSettings.");
|
||||
reflection_atlas_set_size(p_reflection_atlas, 256, atlas->count);
|
||||
|
@ -675,7 +677,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc
|
|||
}
|
||||
atlas->reflections.resize(atlas->count);
|
||||
for (int i = 0; i < atlas->count; i++) {
|
||||
atlas->reflections.write[i].data.update_reflection_data(atlas->size, mipmaps, false, atlas->reflection, i * 6, storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS, sky.roughness_layers);
|
||||
atlas->reflections.write[i].data.update_reflection_data(storage, atlas->size, mipmaps, false, atlas->reflection, i * 6, storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS, sky.roughness_layers, _render_buffers_get_color_format());
|
||||
for (int j = 0; j < 6; j++) {
|
||||
Vector<RID> fb;
|
||||
fb.push_back(atlas->reflections.write[i].data.layers[0].mipmaps[0].views[j]);
|
||||
|
@ -721,6 +723,8 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc
|
|||
rpi->processing_layer = 1;
|
||||
rpi->processing_side = 0;
|
||||
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -313,12 +313,16 @@ void RendererSceneSkyRD::ReflectionData::clear_reflection_data() {
|
|||
coefficient_buffer = RID();
|
||||
}
|
||||
|
||||
void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers) {
|
||||
void RendererSceneSkyRD::ReflectionData::update_reflection_data(RendererStorageRD *p_storage, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format) {
|
||||
//recreate radiance and all data
|
||||
|
||||
int mipmaps = p_mipmaps;
|
||||
uint32_t w = p_size, h = p_size;
|
||||
|
||||
EffectsRD *effects = p_storage->get_effects();
|
||||
ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialised");
|
||||
bool prefer_raster_effects = effects->get_prefer_raster_effects();
|
||||
|
||||
if (p_use_array) {
|
||||
int num_layers = p_low_quality ? 8 : p_roughness_layers;
|
||||
|
||||
|
@ -377,9 +381,9 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int
|
|||
}
|
||||
|
||||
radiance_base_cubemap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer, 0, RD::TEXTURE_SLICE_CUBEMAP);
|
||||
|
||||
RD::get_singleton()->set_resource_name(radiance_base_cubemap, "radiance base cubemap");
|
||||
RD::TextureFormat tf;
|
||||
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
tf.format = p_texture_format;
|
||||
tf.width = 64; // Always 64x64
|
||||
tf.height = 64;
|
||||
tf.texture_type = RD::TEXTURE_TYPE_CUBE;
|
||||
|
@ -388,6 +392,7 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int
|
|||
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
|
||||
downsampled_radiance_cubemap = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
RD::get_singleton()->set_resource_name(downsampled_radiance_cubemap, "downsampled radiance cubemap");
|
||||
{
|
||||
uint32_t mmw = 64;
|
||||
uint32_t mmh = 64;
|
||||
|
@ -397,6 +402,18 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int
|
|||
mm.size.width = mmw;
|
||||
mm.size.height = mmh;
|
||||
mm.view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), downsampled_radiance_cubemap, 0, j, RD::TEXTURE_SLICE_CUBEMAP);
|
||||
RD::get_singleton()->set_resource_name(mm.view, "Downsampled Radiance Cubemap Mip " + itos(j) + " ");
|
||||
if (prefer_raster_effects) {
|
||||
// we need a framebuffer for each side of our cubemap
|
||||
|
||||
for (int k = 0; k < 6; k++) {
|
||||
mm.views[k] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), downsampled_radiance_cubemap, k, j);
|
||||
RD::get_singleton()->set_resource_name(mm.view, "Downsampled Radiance Cubemap Mip: " + itos(j) + " Face: " + itos(k) + " ");
|
||||
Vector<RID> fbtex;
|
||||
fbtex.push_back(mm.views[k]);
|
||||
mm.framebuffers[k] = RD::get_singleton()->framebuffer_create(fbtex);
|
||||
}
|
||||
}
|
||||
|
||||
mmw = MAX(1, mmw >> 1);
|
||||
mmh = MAX(1, mmh >> 1);
|
||||
|
@ -405,50 +422,128 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int
|
|||
}
|
||||
|
||||
void RendererSceneSkyRD::ReflectionData::create_reflection_fast_filter(RendererStorageRD *p_storage, bool p_use_arrays) {
|
||||
p_storage->get_effects()->cubemap_downsample(radiance_base_cubemap, downsampled_layer.mipmaps[0].view, downsampled_layer.mipmaps[0].size);
|
||||
EffectsRD *effects = p_storage->get_effects();
|
||||
ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialised");
|
||||
bool prefer_raster_effects = effects->get_prefer_raster_effects();
|
||||
|
||||
for (int i = 1; i < downsampled_layer.mipmaps.size(); i++) {
|
||||
p_storage->get_effects()->cubemap_downsample(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].view, downsampled_layer.mipmaps[i].size);
|
||||
}
|
||||
|
||||
Vector<RID> views;
|
||||
if (p_use_arrays) {
|
||||
for (int i = 1; i < layers.size(); i++) {
|
||||
views.push_back(layers[i].views[0]);
|
||||
if (prefer_raster_effects) {
|
||||
RD::get_singleton()->draw_command_begin_label("Downsample radiance map");
|
||||
for (int k = 0; k < 6; k++) {
|
||||
effects->cubemap_downsample_raster(radiance_base_cubemap, downsampled_layer.mipmaps[0].framebuffers[k], k, downsampled_layer.mipmaps[0].size);
|
||||
}
|
||||
|
||||
for (int i = 1; i < downsampled_layer.mipmaps.size(); i++) {
|
||||
for (int k = 0; k < 6; k++) {
|
||||
effects->cubemap_downsample_raster(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].framebuffers[k], k, downsampled_layer.mipmaps[i].size);
|
||||
}
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label(); // Downsample Radiance
|
||||
|
||||
if (p_use_arrays) {
|
||||
RD::get_singleton()->draw_command_begin_label("filter radiance map into array heads");
|
||||
for (int i = 0; i < layers.size(); i++) {
|
||||
for (int k = 0; k < 6; k++) {
|
||||
effects->cubemap_filter_raster(downsampled_radiance_cubemap, layers[i].mipmaps[0].framebuffers[k], k, i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
RD::get_singleton()->draw_command_begin_label("filter radiance map into mipmaps directly");
|
||||
for (int j = 0; j < layers[0].mipmaps.size(); j++) {
|
||||
for (int k = 0; k < 6; k++) {
|
||||
effects->cubemap_filter_raster(downsampled_radiance_cubemap, layers[0].mipmaps[j].framebuffers[k], k, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label(); // Filter radiance
|
||||
} else {
|
||||
for (int i = 1; i < layers[0].views.size(); i++) {
|
||||
views.push_back(layers[0].views[i]);
|
||||
}
|
||||
}
|
||||
effects->cubemap_downsample(radiance_base_cubemap, downsampled_layer.mipmaps[0].view, downsampled_layer.mipmaps[0].size);
|
||||
|
||||
p_storage->get_effects()->cubemap_filter(downsampled_radiance_cubemap, views, p_use_arrays);
|
||||
for (int i = 1; i < downsampled_layer.mipmaps.size(); i++) {
|
||||
effects->cubemap_downsample(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].view, downsampled_layer.mipmaps[i].size);
|
||||
}
|
||||
|
||||
Vector<RID> views;
|
||||
if (p_use_arrays) {
|
||||
for (int i = 1; i < layers.size(); i++) {
|
||||
views.push_back(layers[i].views[0]);
|
||||
}
|
||||
} else {
|
||||
for (int i = 1; i < layers[0].views.size(); i++) {
|
||||
views.push_back(layers[0].views[i]);
|
||||
}
|
||||
}
|
||||
|
||||
effects->cubemap_filter(downsampled_radiance_cubemap, views, p_use_arrays);
|
||||
}
|
||||
}
|
||||
|
||||
void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(RendererStorageRD *p_storage, bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality) {
|
||||
if (p_use_arrays) {
|
||||
//render directly to the layers
|
||||
p_storage->get_effects()->cubemap_roughness(radiance_base_cubemap, layers[p_base_layer].views[0], p_cube_side, p_sky_ggx_samples_quality, float(p_base_layer) / (layers.size() - 1.0), layers[p_base_layer].mipmaps[0].size.x);
|
||||
EffectsRD *effects = p_storage->get_effects();
|
||||
ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialised");
|
||||
bool prefer_raster_effects = effects->get_prefer_raster_effects();
|
||||
|
||||
if (prefer_raster_effects) {
|
||||
// Need to ask clayjohn but p_cube_side is set to 10, looks like in the compute shader we're doing all 6 sides in one call
|
||||
// here we need to do them one by one so ignoring p_cube_side
|
||||
if (p_use_arrays) {
|
||||
for (int k = 0; k < 6; k++) {
|
||||
effects->cubemap_roughness_raster(
|
||||
radiance_base_cubemap,
|
||||
layers[p_base_layer].mipmaps[0].framebuffers[k],
|
||||
k,
|
||||
p_sky_ggx_samples_quality,
|
||||
float(p_base_layer) / (layers.size() - 1.0),
|
||||
layers[p_base_layer].mipmaps[0].size.x);
|
||||
}
|
||||
} else {
|
||||
for (int k = 0; k < 6; k++) {
|
||||
effects->cubemap_roughness_raster(
|
||||
layers[0].views[p_base_layer - 1],
|
||||
layers[0].mipmaps[p_base_layer].framebuffers[k],
|
||||
k,
|
||||
p_sky_ggx_samples_quality,
|
||||
float(p_base_layer) / (layers[0].mipmaps.size() - 1.0),
|
||||
layers[0].mipmaps[p_base_layer].size.x);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
p_storage->get_effects()->cubemap_roughness(
|
||||
layers[0].views[p_base_layer - 1],
|
||||
layers[0].views[p_base_layer],
|
||||
p_cube_side,
|
||||
p_sky_ggx_samples_quality,
|
||||
float(p_base_layer) / (layers[0].mipmaps.size() - 1.0),
|
||||
layers[0].mipmaps[p_base_layer].size.x);
|
||||
if (p_use_arrays) {
|
||||
//render directly to the layers
|
||||
effects->cubemap_roughness(radiance_base_cubemap, layers[p_base_layer].views[0], p_cube_side, p_sky_ggx_samples_quality, float(p_base_layer) / (layers.size() - 1.0), layers[p_base_layer].mipmaps[0].size.x);
|
||||
} else {
|
||||
effects->cubemap_roughness(
|
||||
layers[0].views[p_base_layer - 1],
|
||||
layers[0].views[p_base_layer],
|
||||
p_cube_side,
|
||||
p_sky_ggx_samples_quality,
|
||||
float(p_base_layer) / (layers[0].mipmaps.size() - 1.0),
|
||||
layers[0].mipmaps[p_base_layer].size.x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RendererSceneSkyRD::ReflectionData::update_reflection_mipmaps(RendererStorageRD *p_storage, int p_start, int p_end) {
|
||||
EffectsRD *effects = p_storage->get_effects();
|
||||
ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialised");
|
||||
bool prefer_raster_effects = effects->get_prefer_raster_effects();
|
||||
|
||||
RD::get_singleton()->draw_command_begin_label("Update Radiance Cubemap Array Mipmaps");
|
||||
for (int i = p_start; i < p_end; i++) {
|
||||
for (int j = 0; j < layers[i].views.size() - 1; j++) {
|
||||
RID view = layers[i].views[j];
|
||||
RID texture = layers[i].views[j + 1];
|
||||
Size2i size = layers[i].mipmaps[j + 1].size;
|
||||
p_storage->get_effects()->cubemap_downsample(view, texture, size);
|
||||
if (prefer_raster_effects) {
|
||||
for (int k = 0; k < 6; k++) {
|
||||
RID framebuffer = layers[i].mipmaps[j + 1].framebuffers[k];
|
||||
effects->cubemap_downsample_raster(view, framebuffer, k, size);
|
||||
}
|
||||
} else {
|
||||
RID texture = layers[i].views[j + 1];
|
||||
effects->cubemap_downsample(view, texture, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -902,6 +997,10 @@ void sky() {
|
|||
}
|
||||
}
|
||||
|
||||
void RendererSceneSkyRD::set_texture_format(RD::DataFormat p_texture_format) {
|
||||
texture_format = p_texture_format;
|
||||
}
|
||||
|
||||
RendererSceneSkyRD::~RendererSceneSkyRD() {
|
||||
// TODO cleanup anything created in init...
|
||||
|
||||
|
@ -1170,6 +1269,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
|
|||
cm = correction * cm;
|
||||
|
||||
if (shader_data->uses_quarter_res) {
|
||||
RD::get_singleton()->draw_command_begin_label("Render Sky to Quarter Res Cubemap");
|
||||
PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_QUARTER_RES];
|
||||
|
||||
Vector<Color> clear_colors;
|
||||
|
@ -1185,9 +1285,11 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
|
|||
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view.basis, multiplier, p_transform.origin);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
|
||||
if (shader_data->uses_half_res) {
|
||||
RD::get_singleton()->draw_command_begin_label("Render Sky to Half Res Cubemap");
|
||||
PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_HALF_RES];
|
||||
|
||||
Vector<Color> clear_colors;
|
||||
|
@ -1203,11 +1305,13 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
|
|||
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view.basis, multiplier, p_transform.origin);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
|
||||
RD::DrawListID cubemap_draw_list;
|
||||
PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP];
|
||||
|
||||
RD::get_singleton()->draw_command_begin_label("Render Sky Cubemap");
|
||||
for (int i = 0; i < 6; i++) {
|
||||
Transform3D local_view;
|
||||
local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]);
|
||||
|
@ -1217,6 +1321,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
|
|||
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view.basis, multiplier, p_transform.origin);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
|
||||
if (sky_mode == RS::SKY_MODE_REALTIME) {
|
||||
sky->reflection.create_reflection_fast_filter(storage, sky_use_cubemap_array);
|
||||
|
@ -1393,7 +1498,7 @@ void RendererSceneSkyRD::update_dirty_skys() {
|
|||
//array (higher quality, 6 times more memory)
|
||||
RD::TextureFormat tf;
|
||||
tf.array_layers = layers * 6;
|
||||
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
tf.format = texture_format;
|
||||
tf.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY;
|
||||
tf.mipmaps = mipmaps;
|
||||
tf.width = w;
|
||||
|
@ -1402,13 +1507,13 @@ void RendererSceneSkyRD::update_dirty_skys() {
|
|||
|
||||
sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
|
||||
sky->reflection.update_reflection_data(sky->radiance_size, mipmaps, true, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers);
|
||||
sky->reflection.update_reflection_data(storage, sky->radiance_size, mipmaps, true, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers, texture_format);
|
||||
|
||||
} else {
|
||||
//regular cubemap, lower quality (aliasing, less memory)
|
||||
RD::TextureFormat tf;
|
||||
tf.array_layers = 6;
|
||||
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
tf.format = texture_format;
|
||||
tf.texture_type = RD::TEXTURE_TYPE_CUBE;
|
||||
tf.mipmaps = MIN(mipmaps, layers);
|
||||
tf.width = w;
|
||||
|
@ -1417,7 +1522,7 @@ void RendererSceneSkyRD::update_dirty_skys() {
|
|||
|
||||
sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
|
||||
sky->reflection.update_reflection_data(sky->radiance_size, MIN(mipmaps, layers), false, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers);
|
||||
sky->reflection.update_reflection_data(storage, sky->radiance_size, MIN(mipmaps, layers), false, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers, texture_format);
|
||||
}
|
||||
texture_set_dirty = true;
|
||||
}
|
||||
|
@ -1425,7 +1530,7 @@ void RendererSceneSkyRD::update_dirty_skys() {
|
|||
// Create subpass buffers if they haven't been created already
|
||||
if (sky->half_res_pass.is_null() && !RD::get_singleton()->texture_is_valid(sky->half_res_pass) && sky->screen_size.x >= 4 && sky->screen_size.y >= 4) {
|
||||
RD::TextureFormat tformat;
|
||||
tformat.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
tformat.format = texture_format;
|
||||
tformat.width = sky->screen_size.x / 2;
|
||||
tformat.height = sky->screen_size.y / 2;
|
||||
tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
|
@ -1440,7 +1545,7 @@ void RendererSceneSkyRD::update_dirty_skys() {
|
|||
|
||||
if (sky->quarter_res_pass.is_null() && !RD::get_singleton()->texture_is_valid(sky->quarter_res_pass) && sky->screen_size.x >= 4 && sky->screen_size.y >= 4) {
|
||||
RD::TextureFormat tformat;
|
||||
tformat.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
tformat.format = texture_format;
|
||||
tformat.width = sky->screen_size.x / 4;
|
||||
tformat.height = sky->screen_size.y / 4;
|
||||
tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
|
|
|
@ -64,6 +64,7 @@ public:
|
|||
|
||||
private:
|
||||
RendererStorageRD *storage;
|
||||
RD::DataFormat texture_format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
|
||||
RID index_buffer;
|
||||
RID index_array;
|
||||
|
@ -190,6 +191,10 @@ public:
|
|||
struct Mipmap {
|
||||
RID view;
|
||||
Size2i size;
|
||||
|
||||
// for mobile only
|
||||
RID views[6];
|
||||
RID framebuffers[6];
|
||||
};
|
||||
Vector<Mipmap> mipmaps;
|
||||
};
|
||||
|
@ -204,7 +209,7 @@ public:
|
|||
Vector<Layer> layers;
|
||||
|
||||
void clear_reflection_data();
|
||||
void update_reflection_data(int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers);
|
||||
void update_reflection_data(RendererStorageRD *p_storage, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format);
|
||||
void create_reflection_fast_filter(RendererStorageRD *p_storage, bool p_use_arrays);
|
||||
void create_reflection_importance_sample(RendererStorageRD *p_storage, bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality);
|
||||
void update_reflection_mipmaps(RendererStorageRD *p_storage, int p_start, int p_end);
|
||||
|
@ -284,6 +289,7 @@ public:
|
|||
|
||||
RendererSceneSkyRD();
|
||||
void init(RendererStorageRD *p_storage);
|
||||
void set_texture_format(RD::DataFormat p_texture_format);
|
||||
~RendererSceneSkyRD();
|
||||
|
||||
void setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
|
||||
|
|
|
@ -32,53 +32,7 @@ layout(set = 0, binding = 0) uniform samplerCube source_cubemap;
|
|||
|
||||
layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly imageCube dest_cubemap;
|
||||
|
||||
layout(push_constant, binding = 1, std430) uniform Params {
|
||||
uint face_size;
|
||||
}
|
||||
params;
|
||||
|
||||
#define M_PI 3.14159265359
|
||||
|
||||
void get_dir_0(out vec3 dir, in float u, in float v) {
|
||||
dir[0] = 1.0;
|
||||
dir[1] = v;
|
||||
dir[2] = -u;
|
||||
}
|
||||
|
||||
void get_dir_1(out vec3 dir, in float u, in float v) {
|
||||
dir[0] = -1.0;
|
||||
dir[1] = v;
|
||||
dir[2] = u;
|
||||
}
|
||||
|
||||
void get_dir_2(out vec3 dir, in float u, in float v) {
|
||||
dir[0] = u;
|
||||
dir[1] = 1.0;
|
||||
dir[2] = -v;
|
||||
}
|
||||
|
||||
void get_dir_3(out vec3 dir, in float u, in float v) {
|
||||
dir[0] = u;
|
||||
dir[1] = -1.0;
|
||||
dir[2] = v;
|
||||
}
|
||||
|
||||
void get_dir_4(out vec3 dir, in float u, in float v) {
|
||||
dir[0] = u;
|
||||
dir[1] = v;
|
||||
dir[2] = 1.0;
|
||||
}
|
||||
|
||||
void get_dir_5(out vec3 dir, in float u, in float v) {
|
||||
dir[0] = -u;
|
||||
dir[1] = v;
|
||||
dir[2] = -1.0;
|
||||
}
|
||||
|
||||
float calcWeight(float u, float v) {
|
||||
float val = u * u + v * v + 1.0;
|
||||
return val * sqrt(val);
|
||||
}
|
||||
#include "cubemap_downsampler_inc.glsl"
|
||||
|
||||
void main() {
|
||||
uvec3 id = gl_GlobalInvocationID;
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
layout(push_constant, binding = 1, std430) uniform Params {
|
||||
uint face_size;
|
||||
uint face_id; // only used in raster shader
|
||||
}
|
||||
params;
|
||||
|
||||
#define M_PI 3.14159265359
|
||||
|
||||
void get_dir_0(out vec3 dir, in float u, in float v) {
|
||||
dir[0] = 1.0;
|
||||
dir[1] = v;
|
||||
dir[2] = -u;
|
||||
}
|
||||
|
||||
void get_dir_1(out vec3 dir, in float u, in float v) {
|
||||
dir[0] = -1.0;
|
||||
dir[1] = v;
|
||||
dir[2] = u;
|
||||
}
|
||||
|
||||
void get_dir_2(out vec3 dir, in float u, in float v) {
|
||||
dir[0] = u;
|
||||
dir[1] = 1.0;
|
||||
dir[2] = -v;
|
||||
}
|
||||
|
||||
void get_dir_3(out vec3 dir, in float u, in float v) {
|
||||
dir[0] = u;
|
||||
dir[1] = -1.0;
|
||||
dir[2] = v;
|
||||
}
|
||||
|
||||
void get_dir_4(out vec3 dir, in float u, in float v) {
|
||||
dir[0] = u;
|
||||
dir[1] = v;
|
||||
dir[2] = 1.0;
|
||||
}
|
||||
|
||||
void get_dir_5(out vec3 dir, in float u, in float v) {
|
||||
dir[0] = -u;
|
||||
dir[1] = v;
|
||||
dir[2] = -1.0;
|
||||
}
|
||||
|
||||
float calcWeight(float u, float v) {
|
||||
float val = u * u + v * v + 1.0;
|
||||
return val * sqrt(val);
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
// Copyright 2016 Activision Publishing, Inc.
|
||||
//
|
||||
// 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.
|
||||
|
||||
/* clang-format off */
|
||||
#[vertex]
|
||||
|
||||
#version 450
|
||||
|
||||
#VERSION_DEFINES
|
||||
|
||||
#include "cubemap_downsampler_inc.glsl"
|
||||
|
||||
layout(location = 0) out vec2 uv_interp;
|
||||
/* clang-format on */
|
||||
|
||||
void main() {
|
||||
vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
|
||||
uv_interp = base_arr[gl_VertexIndex] * float(params.face_size);
|
||||
gl_Position = vec4(base_arr[gl_VertexIndex] * 2.0 - 1.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
#[fragment]
|
||||
|
||||
#version 450
|
||||
|
||||
#VERSION_DEFINES
|
||||
|
||||
#include "cubemap_downsampler_inc.glsl"
|
||||
|
||||
layout(set = 0, binding = 0) uniform samplerCube source_cubemap;
|
||||
|
||||
layout(location = 0) in vec2 uv_interp;
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
/* clang-format on */
|
||||
|
||||
void main() {
|
||||
// Converted from compute shader which uses absolute coordinates.
|
||||
// Could possibly simplify this
|
||||
float face_size = float(params.face_size);
|
||||
|
||||
if (uv_interp.x < face_size && uv_interp.y < face_size) {
|
||||
float inv_face_size = 1.0 / face_size;
|
||||
|
||||
float u0 = (uv_interp.x * 2.0 + 1.0 - 0.75) * inv_face_size - 1.0;
|
||||
float u1 = (uv_interp.x * 2.0 + 1.0 + 0.75) * inv_face_size - 1.0;
|
||||
|
||||
float v0 = (uv_interp.y * 2.0 + 1.0 - 0.75) * -inv_face_size + 1.0;
|
||||
float v1 = (uv_interp.y * 2.0 + 1.0 + 0.75) * -inv_face_size + 1.0;
|
||||
|
||||
float weights[4];
|
||||
weights[0] = calcWeight(u0, v0);
|
||||
weights[1] = calcWeight(u1, v0);
|
||||
weights[2] = calcWeight(u0, v1);
|
||||
weights[3] = calcWeight(u1, v1);
|
||||
|
||||
const float wsum = 0.5 / (weights[0] + weights[1] + weights[2] + weights[3]);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
weights[i] = weights[i] * wsum + .125;
|
||||
}
|
||||
|
||||
vec3 dir;
|
||||
vec4 color;
|
||||
switch (params.face_id) {
|
||||
case 0:
|
||||
get_dir_0(dir, u0, v0);
|
||||
color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
|
||||
|
||||
get_dir_0(dir, u1, v0);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
|
||||
|
||||
get_dir_0(dir, u0, v1);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
|
||||
|
||||
get_dir_0(dir, u1, v1);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
|
||||
break;
|
||||
case 1:
|
||||
get_dir_1(dir, u0, v0);
|
||||
color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
|
||||
|
||||
get_dir_1(dir, u1, v0);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
|
||||
|
||||
get_dir_1(dir, u0, v1);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
|
||||
|
||||
get_dir_1(dir, u1, v1);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
|
||||
break;
|
||||
case 2:
|
||||
get_dir_2(dir, u0, v0);
|
||||
color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
|
||||
|
||||
get_dir_2(dir, u1, v0);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
|
||||
|
||||
get_dir_2(dir, u0, v1);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
|
||||
|
||||
get_dir_2(dir, u1, v1);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
|
||||
break;
|
||||
case 3:
|
||||
get_dir_3(dir, u0, v0);
|
||||
color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
|
||||
|
||||
get_dir_3(dir, u1, v0);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
|
||||
|
||||
get_dir_3(dir, u0, v1);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
|
||||
|
||||
get_dir_3(dir, u1, v1);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
|
||||
break;
|
||||
case 4:
|
||||
get_dir_4(dir, u0, v0);
|
||||
color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
|
||||
|
||||
get_dir_4(dir, u1, v0);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
|
||||
|
||||
get_dir_4(dir, u0, v1);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
|
||||
|
||||
get_dir_4(dir, u1, v1);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
|
||||
break;
|
||||
default:
|
||||
get_dir_5(dir, u0, v0);
|
||||
color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
|
||||
|
||||
get_dir_5(dir, u1, v0);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
|
||||
|
||||
get_dir_5(dir, u0, v1);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
|
||||
|
||||
get_dir_5(dir, u1, v1);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
|
||||
break;
|
||||
}
|
||||
frag_color = color;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,256 @@
|
|||
// Copyright 2016 Activision Publishing, Inc.
|
||||
//
|
||||
// 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.
|
||||
|
||||
/* clang-format off */
|
||||
#[vertex]
|
||||
|
||||
#version 450
|
||||
|
||||
#VERSION_DEFINES
|
||||
|
||||
layout(push_constant, binding = 1, std430) uniform Params {
|
||||
int mip_level;
|
||||
uint face_id;
|
||||
}
|
||||
params;
|
||||
|
||||
layout(location = 0) out vec2 uv_interp;
|
||||
/* clang-format on */
|
||||
|
||||
void main() {
|
||||
vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
|
||||
uv_interp = base_arr[gl_VertexIndex];
|
||||
gl_Position = vec4(base_arr[gl_VertexIndex] * 2.0 - 1.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
#[fragment]
|
||||
|
||||
#version 450
|
||||
|
||||
#VERSION_DEFINES
|
||||
|
||||
layout(push_constant, binding = 1, std430) uniform Params {
|
||||
int mip_level;
|
||||
uint face_id;
|
||||
}
|
||||
params;
|
||||
|
||||
layout(set = 0, binding = 0) uniform samplerCube source_cubemap;
|
||||
|
||||
layout(location = 0) in vec2 uv_interp;
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
#ifdef USE_HIGH_QUALITY
|
||||
#define NUM_TAPS 32
|
||||
#else
|
||||
#define NUM_TAPS 8
|
||||
#endif
|
||||
|
||||
#define BASE_RESOLUTION 128
|
||||
|
||||
#ifdef USE_HIGH_QUALITY
|
||||
layout(set = 1, binding = 0, std430) buffer restrict readonly Data {
|
||||
vec4[7][5][3][24] coeffs;
|
||||
}
|
||||
data;
|
||||
#else
|
||||
layout(set = 1, binding = 0, std430) buffer restrict readonly Data {
|
||||
vec4[7][5][6] coeffs;
|
||||
}
|
||||
data;
|
||||
#endif
|
||||
|
||||
void get_dir(out vec3 dir, in vec2 uv, in uint face) {
|
||||
switch (face) {
|
||||
case 0:
|
||||
dir = vec3(1.0, uv[1], -uv[0]);
|
||||
break;
|
||||
case 1:
|
||||
dir = vec3(-1.0, uv[1], uv[0]);
|
||||
break;
|
||||
case 2:
|
||||
dir = vec3(uv[0], 1.0, -uv[1]);
|
||||
break;
|
||||
case 3:
|
||||
dir = vec3(uv[0], -1.0, uv[1]);
|
||||
break;
|
||||
case 4:
|
||||
dir = vec3(uv[0], uv[1], 1.0);
|
||||
break;
|
||||
default:
|
||||
dir = vec3(-uv[0], uv[1], -1.0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
// determine dir / pos for the texel
|
||||
vec3 dir, adir, frameZ;
|
||||
{
|
||||
vec2 uv;
|
||||
uv.x = uv_interp.x;
|
||||
uv.y = 1.0 - uv_interp.y;
|
||||
uv = uv * 2.0 - 1.0;
|
||||
|
||||
get_dir(dir, uv, params.face_id);
|
||||
frameZ = normalize(dir);
|
||||
|
||||
adir = abs(dir);
|
||||
}
|
||||
|
||||
// determine which texel this is
|
||||
// NOTE (macOS/MoltenVK): Do not rename, "level" variable name conflicts with the Metal "level(float lod)" mipmap sampling function name.
|
||||
int mip_level = 0;
|
||||
|
||||
if (params.mip_level < 0) {
|
||||
// return as is
|
||||
frag_color.rgb = textureLod(source_cubemap, frameZ, 0.0).rgb;
|
||||
frag_color.a = 1.0;
|
||||
return;
|
||||
} else if (params.mip_level > 6) {
|
||||
// maximum level
|
||||
mip_level = 6;
|
||||
} else {
|
||||
mip_level = params.mip_level;
|
||||
}
|
||||
|
||||
// GGX gather colors
|
||||
vec4 color = vec4(0.0);
|
||||
for (int axis = 0; axis < 3; axis++) {
|
||||
const int otherAxis0 = 1 - (axis & 1) - (axis >> 1);
|
||||
const int otherAxis1 = 2 - (axis >> 1);
|
||||
|
||||
float frameweight = (max(adir[otherAxis0], adir[otherAxis1]) - .75) / .25;
|
||||
if (frameweight > 0.0) {
|
||||
// determine frame
|
||||
vec3 UpVector;
|
||||
switch (axis) {
|
||||
case 0:
|
||||
UpVector = vec3(1, 0, 0);
|
||||
break;
|
||||
case 1:
|
||||
UpVector = vec3(0, 1, 0);
|
||||
break;
|
||||
default:
|
||||
UpVector = vec3(0, 0, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
vec3 frameX = normalize(cross(UpVector, frameZ));
|
||||
vec3 frameY = cross(frameZ, frameX);
|
||||
|
||||
// calculate parametrization for polynomial
|
||||
float Nx = dir[otherAxis0];
|
||||
float Ny = dir[otherAxis1];
|
||||
float Nz = adir[axis];
|
||||
|
||||
float NmaxXY = max(abs(Ny), abs(Nx));
|
||||
Nx /= NmaxXY;
|
||||
Ny /= NmaxXY;
|
||||
|
||||
float theta;
|
||||
if (Ny < Nx) {
|
||||
if (Ny <= -0.999)
|
||||
theta = Nx;
|
||||
else
|
||||
theta = Ny;
|
||||
} else {
|
||||
if (Ny >= 0.999)
|
||||
theta = -Nx;
|
||||
else
|
||||
theta = -Ny;
|
||||
}
|
||||
|
||||
float phi;
|
||||
if (Nz <= -0.999)
|
||||
phi = -NmaxXY;
|
||||
else if (Nz >= 0.999)
|
||||
phi = NmaxXY;
|
||||
else
|
||||
phi = Nz;
|
||||
|
||||
float theta2 = theta * theta;
|
||||
float phi2 = phi * phi;
|
||||
|
||||
// sample
|
||||
for (int iSuperTap = 0; iSuperTap < NUM_TAPS / 4; iSuperTap++) {
|
||||
const int index = (NUM_TAPS / 4) * axis + iSuperTap;
|
||||
|
||||
#ifdef USE_HIGH_QUALITY
|
||||
vec4 coeffsDir0[3];
|
||||
vec4 coeffsDir1[3];
|
||||
vec4 coeffsDir2[3];
|
||||
vec4 coeffsLevel[3];
|
||||
vec4 coeffsWeight[3];
|
||||
|
||||
for (int iCoeff = 0; iCoeff < 3; iCoeff++) {
|
||||
coeffsDir0[iCoeff] = data.coeffs[mip_level][0][iCoeff][index];
|
||||
coeffsDir1[iCoeff] = data.coeffs[mip_level][1][iCoeff][index];
|
||||
coeffsDir2[iCoeff] = data.coeffs[mip_level][2][iCoeff][index];
|
||||
coeffsLevel[iCoeff] = data.coeffs[mip_level][3][iCoeff][index];
|
||||
coeffsWeight[iCoeff] = data.coeffs[mip_level][4][iCoeff][index];
|
||||
}
|
||||
|
||||
for (int iSubTap = 0; iSubTap < 4; iSubTap++) {
|
||||
// determine sample attributes (dir, weight, mip_level)
|
||||
vec3 sample_dir = frameX * (coeffsDir0[0][iSubTap] + coeffsDir0[1][iSubTap] * theta2 + coeffsDir0[2][iSubTap] * phi2) + frameY * (coeffsDir1[0][iSubTap] + coeffsDir1[1][iSubTap] * theta2 + coeffsDir1[2][iSubTap] * phi2) + frameZ * (coeffsDir2[0][iSubTap] + coeffsDir2[1][iSubTap] * theta2 + coeffsDir2[2][iSubTap] * phi2);
|
||||
|
||||
float sample_level = coeffsLevel[0][iSubTap] + coeffsLevel[1][iSubTap] * theta2 + coeffsLevel[2][iSubTap] * phi2;
|
||||
|
||||
float sample_weight = coeffsWeight[0][iSubTap] + coeffsWeight[1][iSubTap] * theta2 + coeffsWeight[2][iSubTap] * phi2;
|
||||
#else
|
||||
vec4 coeffsDir0 = data.coeffs[mip_level][0][index];
|
||||
vec4 coeffsDir1 = data.coeffs[mip_level][1][index];
|
||||
vec4 coeffsDir2 = data.coeffs[mip_level][2][index];
|
||||
vec4 coeffsLevel = data.coeffs[mip_level][3][index];
|
||||
vec4 coeffsWeight = data.coeffs[mip_level][4][index];
|
||||
|
||||
for (int iSubTap = 0; iSubTap < 4; iSubTap++) {
|
||||
// determine sample attributes (dir, weight, mip_level)
|
||||
vec3 sample_dir = frameX * coeffsDir0[iSubTap] + frameY * coeffsDir1[iSubTap] + frameZ * coeffsDir2[iSubTap];
|
||||
|
||||
float sample_level = coeffsLevel[iSubTap];
|
||||
|
||||
float sample_weight = coeffsWeight[iSubTap];
|
||||
#endif
|
||||
|
||||
sample_weight *= frameweight;
|
||||
|
||||
// adjust for jacobian
|
||||
sample_dir /= max(abs(sample_dir[0]), max(abs(sample_dir[1]), abs(sample_dir[2])));
|
||||
sample_level += 0.75 * log2(dot(sample_dir, sample_dir));
|
||||
// sample cubemap
|
||||
color.xyz += textureLod(source_cubemap, normalize(sample_dir), sample_level).xyz * sample_weight;
|
||||
color.w += sample_weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
color /= color.w;
|
||||
|
||||
// write color
|
||||
color.xyz = max(vec3(0.0), color.xyz);
|
||||
color.w = 1.0;
|
||||
|
||||
frag_color = color;
|
||||
}
|
|
@ -12,100 +12,7 @@ layout(set = 0, binding = 0) uniform samplerCube source_cube;
|
|||
|
||||
layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly imageCube dest_cubemap;
|
||||
|
||||
layout(push_constant, binding = 1, std430) uniform Params {
|
||||
uint face_id;
|
||||
uint sample_count;
|
||||
float roughness;
|
||||
bool use_direct_write;
|
||||
float face_size;
|
||||
}
|
||||
params;
|
||||
|
||||
#define M_PI 3.14159265359
|
||||
|
||||
vec3 texelCoordToVec(vec2 uv, uint faceID) {
|
||||
mat3 faceUvVectors[6];
|
||||
|
||||
// -x
|
||||
faceUvVectors[1][0] = vec3(0.0, 0.0, 1.0); // u -> +z
|
||||
faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y
|
||||
faceUvVectors[1][2] = vec3(-1.0, 0.0, 0.0); // -x face
|
||||
|
||||
// +x
|
||||
faceUvVectors[0][0] = vec3(0.0, 0.0, -1.0); // u -> -z
|
||||
faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y
|
||||
faceUvVectors[0][2] = vec3(1.0, 0.0, 0.0); // +x face
|
||||
|
||||
// -y
|
||||
faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x
|
||||
faceUvVectors[3][1] = vec3(0.0, 0.0, -1.0); // v -> -z
|
||||
faceUvVectors[3][2] = vec3(0.0, -1.0, 0.0); // -y face
|
||||
|
||||
// +y
|
||||
faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x
|
||||
faceUvVectors[2][1] = vec3(0.0, 0.0, 1.0); // v -> +z
|
||||
faceUvVectors[2][2] = vec3(0.0, 1.0, 0.0); // +y face
|
||||
|
||||
// -z
|
||||
faceUvVectors[5][0] = vec3(-1.0, 0.0, 0.0); // u -> -x
|
||||
faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y
|
||||
faceUvVectors[5][2] = vec3(0.0, 0.0, -1.0); // -z face
|
||||
|
||||
// +z
|
||||
faceUvVectors[4][0] = vec3(1.0, 0.0, 0.0); // u -> +x
|
||||
faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y
|
||||
faceUvVectors[4][2] = vec3(0.0, 0.0, 1.0); // +z face
|
||||
|
||||
// out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2].
|
||||
vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2];
|
||||
return normalize(result);
|
||||
}
|
||||
|
||||
vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) {
|
||||
float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph]
|
||||
|
||||
// Compute distribution direction
|
||||
float Phi = 2.0 * M_PI * Xi.x;
|
||||
float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y));
|
||||
float SinTheta = sqrt(1.0 - CosTheta * CosTheta);
|
||||
|
||||
// Convert to spherical direction
|
||||
vec3 H;
|
||||
H.x = SinTheta * cos(Phi);
|
||||
H.y = SinTheta * sin(Phi);
|
||||
H.z = CosTheta;
|
||||
|
||||
vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
|
||||
vec3 TangentX = normalize(cross(UpVector, N));
|
||||
vec3 TangentY = cross(N, TangentX);
|
||||
|
||||
// Tangent to world space
|
||||
return TangentX * H.x + TangentY * H.y + N * H.z;
|
||||
}
|
||||
|
||||
// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
|
||||
float GGX(float NdotV, float a) {
|
||||
float k = a / 2.0;
|
||||
return NdotV / (NdotV * (1.0 - k) + k);
|
||||
}
|
||||
|
||||
// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
|
||||
float G_Smith(float a, float nDotV, float nDotL) {
|
||||
return GGX(nDotL, a * a) * GGX(nDotV, a * a);
|
||||
}
|
||||
|
||||
float radicalInverse_VdC(uint bits) {
|
||||
bits = (bits << 16u) | (bits >> 16u);
|
||||
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
||||
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
||||
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
||||
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
||||
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
|
||||
}
|
||||
|
||||
vec2 Hammersley(uint i, uint N) {
|
||||
return vec2(float(i) / float(N), radicalInverse_VdC(i));
|
||||
}
|
||||
#include "cubemap_roughness_inc.glsl"
|
||||
|
||||
void main() {
|
||||
uvec3 id = gl_GlobalInvocationID;
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
#define M_PI 3.14159265359
|
||||
|
||||
layout(push_constant, binding = 1, std430) uniform Params {
|
||||
uint face_id;
|
||||
uint sample_count;
|
||||
float roughness;
|
||||
bool use_direct_write;
|
||||
float face_size;
|
||||
}
|
||||
params;
|
||||
|
||||
vec3 texelCoordToVec(vec2 uv, uint faceID) {
|
||||
mat3 faceUvVectors[6];
|
||||
|
||||
// -x
|
||||
faceUvVectors[1][0] = vec3(0.0, 0.0, 1.0); // u -> +z
|
||||
faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y
|
||||
faceUvVectors[1][2] = vec3(-1.0, 0.0, 0.0); // -x face
|
||||
|
||||
// +x
|
||||
faceUvVectors[0][0] = vec3(0.0, 0.0, -1.0); // u -> -z
|
||||
faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y
|
||||
faceUvVectors[0][2] = vec3(1.0, 0.0, 0.0); // +x face
|
||||
|
||||
// -y
|
||||
faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x
|
||||
faceUvVectors[3][1] = vec3(0.0, 0.0, -1.0); // v -> -z
|
||||
faceUvVectors[3][2] = vec3(0.0, -1.0, 0.0); // -y face
|
||||
|
||||
// +y
|
||||
faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x
|
||||
faceUvVectors[2][1] = vec3(0.0, 0.0, 1.0); // v -> +z
|
||||
faceUvVectors[2][2] = vec3(0.0, 1.0, 0.0); // +y face
|
||||
|
||||
// -z
|
||||
faceUvVectors[5][0] = vec3(-1.0, 0.0, 0.0); // u -> -x
|
||||
faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y
|
||||
faceUvVectors[5][2] = vec3(0.0, 0.0, -1.0); // -z face
|
||||
|
||||
// +z
|
||||
faceUvVectors[4][0] = vec3(1.0, 0.0, 0.0); // u -> +x
|
||||
faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y
|
||||
faceUvVectors[4][2] = vec3(0.0, 0.0, 1.0); // +z face
|
||||
|
||||
// out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2].
|
||||
vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2];
|
||||
return normalize(result);
|
||||
}
|
||||
|
||||
vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) {
|
||||
float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph]
|
||||
|
||||
// Compute distribution direction
|
||||
float Phi = 2.0 * M_PI * Xi.x;
|
||||
float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y));
|
||||
float SinTheta = sqrt(1.0 - CosTheta * CosTheta);
|
||||
|
||||
// Convert to spherical direction
|
||||
vec3 H;
|
||||
H.x = SinTheta * cos(Phi);
|
||||
H.y = SinTheta * sin(Phi);
|
||||
H.z = CosTheta;
|
||||
|
||||
vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
|
||||
vec3 TangentX = normalize(cross(UpVector, N));
|
||||
vec3 TangentY = cross(N, TangentX);
|
||||
|
||||
// Tangent to world space
|
||||
return TangentX * H.x + TangentY * H.y + N * H.z;
|
||||
}
|
||||
|
||||
// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
|
||||
float GGX(float NdotV, float a) {
|
||||
float k = a / 2.0;
|
||||
return NdotV / (NdotV * (1.0 - k) + k);
|
||||
}
|
||||
|
||||
// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
|
||||
float G_Smith(float a, float nDotV, float nDotL) {
|
||||
return GGX(nDotL, a * a) * GGX(nDotV, a * a);
|
||||
}
|
||||
|
||||
float radicalInverse_VdC(uint bits) {
|
||||
bits = (bits << 16u) | (bits >> 16u);
|
||||
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
||||
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
||||
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
||||
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
||||
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
|
||||
}
|
||||
|
||||
vec2 Hammersley(uint i, uint N) {
|
||||
return vec2(float(i) / float(N), radicalInverse_VdC(i));
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/* clang-format off */
|
||||
#[vertex]
|
||||
|
||||
#version 450
|
||||
|
||||
#VERSION_DEFINES
|
||||
|
||||
#include "cubemap_roughness_inc.glsl"
|
||||
|
||||
layout(location = 0) out vec2 uv_interp;
|
||||
/* clang-format on */
|
||||
|
||||
void main() {
|
||||
vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
|
||||
uv_interp = base_arr[gl_VertexIndex];
|
||||
gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
#[fragment]
|
||||
|
||||
#version 450
|
||||
|
||||
#VERSION_DEFINES
|
||||
|
||||
#include "cubemap_roughness_inc.glsl"
|
||||
|
||||
layout(location = 0) in vec2 uv_interp;
|
||||
|
||||
layout(set = 0, binding = 0) uniform samplerCube source_cube;
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
/* clang-format on */
|
||||
|
||||
void main() {
|
||||
vec3 N = texelCoordToVec(uv_interp * 2.0 - 1.0, params.face_id);
|
||||
|
||||
//vec4 color = color_interp;
|
||||
|
||||
if (params.use_direct_write) {
|
||||
frag_color = vec4(texture(source_cube, N).rgb, 1.0);
|
||||
} else {
|
||||
vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
for (uint sampleNum = 0u; sampleNum < params.sample_count; sampleNum++) {
|
||||
vec2 xi = Hammersley(sampleNum, params.sample_count);
|
||||
|
||||
vec3 H = ImportanceSampleGGX(xi, params.roughness, N);
|
||||
vec3 V = N;
|
||||
vec3 L = (2.0 * dot(V, H) * H - V);
|
||||
|
||||
float ndotl = clamp(dot(N, L), 0.0, 1.0);
|
||||
|
||||
if (ndotl > 0.0) {
|
||||
sum.rgb += textureLod(source_cube, L, 0.0).rgb * ndotl;
|
||||
sum.a += ndotl;
|
||||
}
|
||||
}
|
||||
sum /= sum.a;
|
||||
|
||||
frag_color = vec4(sum.rgb, 1.0);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue