You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-05 12:10:55 +00:00
Implement Physical Light Units as an optional setting.
This allows light sources to be specified in physical light units in addition to the regular energy multiplier. In order to avoid loss of precision at high values, brightness values are premultiplied by an exposure normalization value. In support of Physical Light Units this PR also renames CameraEffects to CameraAttributes.
This commit is contained in:
@@ -33,6 +33,8 @@
|
||||
#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"
|
||||
#include "servers/rendering/rendering_server_default.h"
|
||||
#include "servers/rendering/storage/camera_attributes_storage.h"
|
||||
|
||||
using namespace RendererRD;
|
||||
|
||||
@@ -84,7 +86,7 @@ BokehDOF::~BokehDOF() {
|
||||
}
|
||||
}
|
||||
|
||||
void BokehDOF::bokeh_dof_compute(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, RenderingServer::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 BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, RID p_camera_attributes, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
|
||||
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of bokeh depth of field with the mobile renderer.");
|
||||
|
||||
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
|
||||
@@ -92,22 +94,39 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
|
||||
MaterialStorage *material_storage = MaterialStorage::get_singleton();
|
||||
ERR_FAIL_NULL(material_storage);
|
||||
|
||||
bool dof_far = RSG::camera_attributes->camera_attributes_get_dof_far_enabled(p_camera_attributes);
|
||||
float dof_far_begin = RSG::camera_attributes->camera_attributes_get_dof_far_distance(p_camera_attributes);
|
||||
float dof_far_size = RSG::camera_attributes->camera_attributes_get_dof_far_transition(p_camera_attributes);
|
||||
bool dof_near = RSG::camera_attributes->camera_attributes_get_dof_near_enabled(p_camera_attributes);
|
||||
float dof_near_begin = RSG::camera_attributes->camera_attributes_get_dof_near_distance(p_camera_attributes);
|
||||
float dof_near_size = RSG::camera_attributes->camera_attributes_get_dof_near_transition(p_camera_attributes);
|
||||
float bokeh_size = RSG::camera_attributes->camera_attributes_get_dof_blur_amount(p_camera_attributes) * 64; // Base 64 pixel radius.
|
||||
|
||||
bool use_jitter = RSG::camera_attributes->camera_attributes_get_dof_blur_use_jitter();
|
||||
RS::DOFBokehShape bokeh_shape = RSG::camera_attributes->camera_attributes_get_dof_blur_bokeh_shape();
|
||||
RS::DOFBlurQuality blur_quality = RSG::camera_attributes->camera_attributes_get_dof_blur_quality();
|
||||
|
||||
// setup our push constant
|
||||
memset(&bokeh.push_constant, 0, sizeof(BokehPushConstant));
|
||||
bokeh.push_constant.blur_far_active = p_dof_far;
|
||||
bokeh.push_constant.blur_far_begin = p_dof_far_begin;
|
||||
bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size;
|
||||
bokeh.push_constant.blur_far_active = dof_far;
|
||||
bokeh.push_constant.blur_far_begin = dof_far_begin;
|
||||
bokeh.push_constant.blur_far_end = dof_far_begin + dof_far_size; // Only used with non-physically-based.
|
||||
bokeh.push_constant.use_physical_far = dof_far_size < 0.0;
|
||||
bokeh.push_constant.blur_size_far = bokeh_size; // Only used with physically-based.
|
||||
|
||||
bokeh.push_constant.blur_near_active = p_dof_near;
|
||||
bokeh.push_constant.blur_near_begin = p_dof_near_begin;
|
||||
bokeh.push_constant.blur_near_end = MAX(0, p_dof_near_begin - p_dof_near_size);
|
||||
bokeh.push_constant.use_jitter = p_use_jitter;
|
||||
bokeh.push_constant.blur_near_active = dof_near;
|
||||
bokeh.push_constant.blur_near_begin = dof_near_begin;
|
||||
bokeh.push_constant.blur_near_end = dof_near_begin - dof_near_size; // Only used with non-physically-based.
|
||||
bokeh.push_constant.use_physical_near = dof_near_size < 0.0;
|
||||
bokeh.push_constant.blur_size_near = bokeh_size; // Only used with physically-based.
|
||||
|
||||
bokeh.push_constant.use_jitter = use_jitter;
|
||||
bokeh.push_constant.jitter_seed = Math::randf() * 1000.0;
|
||||
|
||||
bokeh.push_constant.z_near = p_cam_znear;
|
||||
bokeh.push_constant.z_far = p_cam_zfar;
|
||||
bokeh.push_constant.orthogonal = p_cam_orthogonal;
|
||||
bokeh.push_constant.blur_size = p_bokeh_size;
|
||||
bokeh.push_constant.blur_size = (dof_near_size < 0.0 && dof_far_size < 0.0) ? 32 : bokeh_size; // Cap with physically-based to keep performance reasonable.
|
||||
|
||||
bokeh.push_constant.second_pass = false;
|
||||
bokeh.push_constant.half_size = false;
|
||||
@@ -150,9 +169,9 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1);
|
||||
RD::get_singleton()->compute_list_add_barrier(compute_list);
|
||||
|
||||
if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
|
||||
if (bokeh_shape == RS::DOF_BOKEH_BOX || bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
|
||||
//second pass
|
||||
BokehMode mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
|
||||
BokehMode mode = bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
|
||||
shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, mode);
|
||||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
@@ -160,9 +179,9 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
|
||||
|
||||
static const int quality_samples[4] = { 6, 12, 12, 24 };
|
||||
|
||||
bokeh.push_constant.steps = quality_samples[p_quality];
|
||||
bokeh.push_constant.steps = quality_samples[blur_quality];
|
||||
|
||||
if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
|
||||
if (blur_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || blur_quality == RS::DOF_BLUR_QUALITY_LOW) {
|
||||
//box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes)
|
||||
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_half_image0), 0);
|
||||
@@ -187,7 +206,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
|
||||
//third pass
|
||||
bokeh.push_constant.second_pass = true;
|
||||
|
||||
if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
|
||||
if (blur_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || blur_quality == RS::DOF_BLUR_QUALITY_LOW) {
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_half_image1), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_half_texture0), 1);
|
||||
} else {
|
||||
@@ -200,7 +219,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1);
|
||||
RD::get_singleton()->compute_list_add_barrier(compute_list);
|
||||
|
||||
if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
|
||||
if (blur_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || blur_quality == RS::DOF_BLUR_QUALITY_LOW) {
|
||||
//forth pass, upscale for low quality
|
||||
|
||||
shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, BOKEH_COMPOSITE);
|
||||
@@ -232,7 +251,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
|
||||
static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 };
|
||||
|
||||
bokeh.push_constant.steps = 0;
|
||||
bokeh.push_constant.blur_scale = quality_scale[p_quality];
|
||||
bokeh.push_constant.blur_scale = quality_scale[blur_quality];
|
||||
|
||||
//circle always runs in half size, otherwise too expensive
|
||||
|
||||
@@ -273,7 +292,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
|
||||
RD::get_singleton()->compute_list_end();
|
||||
}
|
||||
|
||||
void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
|
||||
void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attributes, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
|
||||
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't blur-based depth of field with the clustered renderer.");
|
||||
|
||||
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
|
||||
@@ -281,6 +300,17 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
|
||||
MaterialStorage *material_storage = MaterialStorage::get_singleton();
|
||||
ERR_FAIL_NULL(material_storage);
|
||||
|
||||
bool dof_far = RSG::camera_attributes->camera_attributes_get_dof_far_enabled(p_camera_attributes);
|
||||
float dof_far_begin = RSG::camera_attributes->camera_attributes_get_dof_far_distance(p_camera_attributes);
|
||||
float dof_far_size = RSG::camera_attributes->camera_attributes_get_dof_far_transition(p_camera_attributes);
|
||||
bool dof_near = RSG::camera_attributes->camera_attributes_get_dof_near_enabled(p_camera_attributes);
|
||||
float dof_near_begin = RSG::camera_attributes->camera_attributes_get_dof_near_distance(p_camera_attributes);
|
||||
float dof_near_size = RSG::camera_attributes->camera_attributes_get_dof_near_transition(p_camera_attributes);
|
||||
float bokeh_size = RSG::camera_attributes->camera_attributes_get_dof_blur_amount(p_camera_attributes) * 64; // Base 64 pixel radius.
|
||||
|
||||
RS::DOFBokehShape bokeh_shape = RSG::camera_attributes->camera_attributes_get_dof_blur_bokeh_shape();
|
||||
RS::DOFBlurQuality blur_quality = RSG::camera_attributes->camera_attributes_get_dof_blur_quality();
|
||||
|
||||
// setup our base push constant
|
||||
memset(&bokeh.push_constant, 0, sizeof(BokehPushConstant));
|
||||
|
||||
@@ -292,7 +322,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
|
||||
|
||||
bokeh.push_constant.second_pass = false;
|
||||
bokeh.push_constant.half_size = false;
|
||||
bokeh.push_constant.blur_size = p_dof_blur_amount;
|
||||
bokeh.push_constant.blur_size = bokeh_size;
|
||||
|
||||
// setup our uniforms
|
||||
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
@@ -307,17 +337,17 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
|
||||
RD::Uniform u_weight_texture2(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[2] }));
|
||||
RD::Uniform u_weight_texture3(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[3] }));
|
||||
|
||||
if (p_dof_far || p_dof_near) {
|
||||
if (p_dof_far) {
|
||||
if (dof_far || dof_near) {
|
||||
if (dof_far) {
|
||||
bokeh.push_constant.blur_far_active = true;
|
||||
bokeh.push_constant.blur_far_begin = p_dof_far_begin;
|
||||
bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size;
|
||||
bokeh.push_constant.blur_far_begin = dof_far_begin;
|
||||
bokeh.push_constant.blur_far_end = dof_far_begin + dof_far_size;
|
||||
}
|
||||
|
||||
if (p_dof_near) {
|
||||
if (dof_near) {
|
||||
bokeh.push_constant.blur_near_active = true;
|
||||
bokeh.push_constant.blur_near_begin = p_dof_near_begin;
|
||||
bokeh.push_constant.blur_near_end = p_dof_near_begin - p_dof_near_size;
|
||||
bokeh.push_constant.blur_near_begin = dof_near_begin;
|
||||
bokeh.push_constant.blur_near_end = dof_near_begin - dof_near_size;
|
||||
}
|
||||
|
||||
{
|
||||
@@ -337,14 +367,14 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
|
||||
if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
|
||||
if (bokeh_shape == RS::DOF_BOKEH_BOX || bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
|
||||
// double pass approach
|
||||
BokehMode mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
|
||||
BokehMode mode = bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
|
||||
|
||||
RID shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode);
|
||||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
|
||||
if (blur_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || blur_quality == RS::DOF_BLUR_QUALITY_LOW) {
|
||||
//box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes)
|
||||
bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
|
||||
bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
|
||||
@@ -354,7 +384,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
|
||||
|
||||
static const int quality_samples[4] = { 6, 12, 12, 24 };
|
||||
bokeh.push_constant.blur_scale = 0.5;
|
||||
bokeh.push_constant.steps = quality_samples[p_quality];
|
||||
bokeh.push_constant.steps = quality_samples[blur_quality];
|
||||
|
||||
RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb;
|
||||
|
||||
@@ -373,7 +403,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
|
||||
// Pass 2
|
||||
if (!bokeh.push_constant.half_size) {
|
||||
// do not output weight, we're writing back into our base buffer
|
||||
mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX_NOWEIGHT : BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT;
|
||||
mode = bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX_NOWEIGHT : BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT;
|
||||
|
||||
shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode);
|
||||
ERR_FAIL_COND(shader.is_null());
|
||||
@@ -432,7 +462,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
|
||||
}
|
||||
|
||||
static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 };
|
||||
bokeh.push_constant.blur_scale = quality_scale[p_quality];
|
||||
bokeh.push_constant.blur_scale = quality_scale[blur_quality];
|
||||
bokeh.push_constant.steps = 0.0;
|
||||
|
||||
RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb;
|
||||
|
||||
Reference in New Issue
Block a user