1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-11 13:10:58 +00:00

GIProbes working.

This commit is contained in:
Juan Linietsky
2019-10-03 17:39:08 -03:00
parent 52f96abd8b
commit acf0f6c8a7
51 changed files with 5085 additions and 5109 deletions

View File

@@ -619,6 +619,10 @@ bool RasterizerSceneRD::reflection_probe_instance_begin_render(RID p_instance, R
atlas->reflections.write[i].fbs[j] = RD::get_singleton()->framebuffer_create(fb);
}
}
Vector<RID> fb;
fb.push_back(atlas->depth_buffer);
atlas->depth_fb = RD::get_singleton()->framebuffer_create(fb);
}
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
@@ -700,6 +704,16 @@ RID RasterizerSceneRD::reflection_probe_instance_get_framebuffer(RID p_instance,
return atlas->reflections[rpi->atlas_index].fbs[p_index];
}
RID RasterizerSceneRD::reflection_probe_instance_get_depth_framebuffer(RID p_instance, int p_index) {
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
ERR_FAIL_COND_V(!rpi, RID());
ERR_FAIL_INDEX_V(p_index, 6, RID());
ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas);
ERR_FAIL_COND_V(!atlas, RID());
return atlas->depth_fb;
}
///////////////////////////////////////////////////////////
RID RasterizerSceneRD::shadow_atlas_create() {
@@ -1192,6 +1206,454 @@ RasterizerSceneRD::ShadowMap *RasterizerSceneRD::_get_shadow_map(const Size2i &p
return &shadow_maps[p_size];
}
/////////////////////////////////
RID RasterizerSceneRD::gi_probe_instance_create(RID p_base) {
//find a free slot
int index = -1;
for (int i = 0; i < gi_probe_slots.size(); i++) {
if (gi_probe_slots[i] == RID()) {
index = i;
break;
}
}
ERR_FAIL_COND_V(index == -1, RID());
GIProbeInstance gi_probe;
gi_probe.slot = index;
gi_probe.probe = p_base;
RID rid = gi_probe_instance_owner.make_rid(gi_probe);
gi_probe_slots.write[index] = rid;
return rid;
}
void RasterizerSceneRD::gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) {
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
ERR_FAIL_COND(!gi_probe);
gi_probe->transform = p_xform;
}
bool RasterizerSceneRD::gi_probe_needs_update(RID p_probe) const {
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
ERR_FAIL_COND_V(!gi_probe, false);
//return true;
return gi_probe->last_probe_version != storage->gi_probe_get_version(gi_probe->probe);
}
void RasterizerSceneRD::gi_probe_update(RID p_probe, const Vector<RID> &p_light_instances) {
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
ERR_FAIL_COND(!gi_probe);
uint32_t data_version = storage->gi_probe_get_data_version(gi_probe->probe);
// (RE)CREATE IF NEEDED
if (gi_probe->last_probe_data_version != data_version) {
//need to re-create everything
if (gi_probe->texture.is_valid()) {
RD::get_singleton()->free(gi_probe->texture);
if (gi_probe_use_anisotropy) {
RD::get_singleton()->free(gi_probe->anisotropy[0]);
RD::get_singleton()->free(gi_probe->anisotropy[1]);
}
RD::get_singleton()->free(gi_probe->write_buffer);
gi_probe->mipmaps.clear();
}
Vector3i octree_size = storage->gi_probe_get_octree_size(gi_probe->probe);
if (octree_size != Vector3i()) {
//can create a 3D texture
PoolVector<int> levels = storage->gi_probe_get_level_counts(gi_probe->probe);
for (int i = 0; i < levels.size(); i++) {
print_line("level " + itos(i) + ": " + itos(levels[i]));
}
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
tf.width = octree_size.x;
tf.height = octree_size.y;
tf.depth = octree_size.z;
tf.type = RD::TEXTURE_TYPE_3D;
tf.mipmaps = levels.size();
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
gi_probe->texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
RD::get_singleton()->texture_clear(gi_probe->texture, Color(0, 0, 0, 0), 0, levels.size(), 0, 1, false);
if (gi_probe_use_anisotropy) {
tf.format = RD::DATA_FORMAT_R5G6B5_UNORM_PACK16;
tf.shareable_formats.push_back(RD::DATA_FORMAT_R5G6B5_UNORM_PACK16);
tf.shareable_formats.push_back(RD::DATA_FORMAT_R16_UINT);
gi_probe->anisotropy[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
gi_probe->anisotropy[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
RD::get_singleton()->texture_clear(gi_probe->anisotropy[0], Color(0, 0, 0, 0), 0, levels.size(), 0, 1, false);
RD::get_singleton()->texture_clear(gi_probe->anisotropy[1], Color(0, 0, 0, 0), 0, levels.size(), 0, 1, false);
}
{
int total_elements = 0;
for (int i = 0; i < levels.size(); i++) {
total_elements += levels[i];
}
if (gi_probe_use_anisotropy) {
total_elements *= 6;
}
gi_probe->write_buffer = RD::get_singleton()->storage_buffer_create(total_elements * 16);
}
for (int i = 0; i < levels.size(); i++) {
GIProbeInstance::Mipmap mipmap;
mipmap.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), gi_probe->texture, 0, i, RD::TEXTURE_SLICE_3D);
if (gi_probe_use_anisotropy) {
RD::TextureView tv;
tv.format_override = RD::DATA_FORMAT_R16_UINT;
mipmap.anisotropy[0] = RD::get_singleton()->texture_create_shared_from_slice(tv, gi_probe->anisotropy[0], 0, i, RD::TEXTURE_SLICE_3D);
mipmap.anisotropy[1] = RD::get_singleton()->texture_create_shared_from_slice(tv, gi_probe->anisotropy[1], 0, i, RD::TEXTURE_SLICE_3D);
}
mipmap.level = levels.size() - i - 1;
mipmap.cell_offset = 0;
for (uint32_t j = 0; j < mipmap.level; j++) {
mipmap.cell_offset += levels[j];
}
mipmap.cell_count = levels[mipmap.level];
Vector<RD::Uniform> uniforms;
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 1;
u.ids.push_back(storage->gi_probe_get_octree_buffer(gi_probe->probe));
uniforms.push_back(u);
}
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 2;
u.ids.push_back(storage->gi_probe_get_data_buffer(gi_probe->probe));
uniforms.push_back(u);
}
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 4;
u.ids.push_back(gi_probe->write_buffer);
uniforms.push_back(u);
}
{
Vector<RD::Uniform> copy_uniforms = uniforms;
if (i == 0) {
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 3;
u.ids.push_back(gi_probe_lights_uniform);
copy_uniforms.push_back(u);
}
mipmap.uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT], 0);
copy_uniforms = uniforms; //restore
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 5;
u.ids.push_back(gi_probe->texture);
copy_uniforms.push_back(u);
}
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_SAMPLER;
u.binding = 6;
u.ids.push_back(storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
copy_uniforms.push_back(u);
}
if (gi_probe_use_anisotropy) {
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 7;
u.ids.push_back(gi_probe->anisotropy[0]);
copy_uniforms.push_back(u);
}
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 8;
u.ids.push_back(gi_probe->anisotropy[1]);
copy_uniforms.push_back(u);
}
}
mipmap.second_bounce_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE], 0);
} else {
mipmap.uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_MIPMAP], 0);
}
}
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 5;
u.ids.push_back(mipmap.texture);
uniforms.push_back(u);
}
if (gi_probe_use_anisotropy) {
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 6;
u.ids.push_back(mipmap.anisotropy[0]);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 7;
u.ids.push_back(mipmap.anisotropy[1]);
uniforms.push_back(u);
}
}
mipmap.write_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_WRITE_TEXTURE], 0);
gi_probe->mipmaps.push_back(mipmap);
}
}
gi_probe->last_probe_data_version = data_version;
}
// UDPDATE TIME
uint32_t light_count = MIN(gi_probe_max_lights, (uint32_t)p_light_instances.size());
{
Transform to_cell = storage->gi_probe_get_to_cell_xform(gi_probe->probe);
Transform to_probe_xform = (gi_probe->transform * to_cell.affine_inverse()).affine_inverse();
//update lights
for (uint32_t i = 0; i < light_count; i++) {
GIProbeLight &l = gi_probe_lights[i];
RID light_instance = p_light_instances[i];
RID light = light_instance_get_base_light(light_instance);
l.type = storage->light_get_type(light);
l.attenuation = storage->light_get_param(light, VS::LIGHT_PARAM_ATTENUATION);
l.energy = storage->light_get_param(light, VS::LIGHT_PARAM_ENERGY) * storage->light_get_param(light, VS::LIGHT_PARAM_INDIRECT_ENERGY);
l.radius = to_cell.basis.xform(Vector3(storage->light_get_param(light, VS::LIGHT_PARAM_RANGE), 0, 0)).length();
Color color = storage->light_get_color(light).to_linear();
l.color[0] = color.r;
l.color[1] = color.g;
l.color[2] = color.b;
l.spot_angle_radians = Math::deg2rad(storage->light_get_param(light, VS::LIGHT_PARAM_SPOT_ANGLE));
l.spot_attenuation = storage->light_get_param(light, VS::LIGHT_PARAM_SPOT_ATTENUATION);
Transform xform = light_instance_get_base_transform(light_instance);
Vector3 pos = to_probe_xform.xform(xform.origin);
Vector3 dir = to_probe_xform.basis.xform(-xform.basis.get_axis(2)).normalized();
l.position[0] = pos.x;
l.position[1] = pos.y;
l.position[2] = pos.z;
l.direction[0] = dir.x;
l.direction[1] = dir.y;
l.direction[2] = dir.z;
l.has_shadow = storage->light_has_shadow(light);
}
RD::get_singleton()->buffer_update(gi_probe_lights_uniform, 0, sizeof(GIProbeLight) * light_count, gi_probe_lights, true);
}
// PROCESS MIPMAPS
if (gi_probe->mipmaps.size()) {
//can update mipmaps
Vector3i probe_size = storage->gi_probe_get_octree_size(gi_probe->probe);
GIProbePushConstant push_constant;
push_constant.limits[0] = probe_size.x;
push_constant.limits[1] = probe_size.y;
push_constant.limits[2] = probe_size.z;
push_constant.stack_size = gi_probe->mipmaps.size();
push_constant.emission_scale = 1.0;
push_constant.propagation = storage->gi_probe_get_propagation(gi_probe->probe);
push_constant.dynamic_range = storage->gi_probe_get_dynamic_range(gi_probe->probe);
push_constant.light_count = light_count;
push_constant.aniso_strength = storage->gi_probe_get_anisotropy_strength(gi_probe->probe);
/* print_line("probe update to version " + itos(gi_probe->last_probe_version));
print_line("propagation " + rtos(push_constant.propagation));
print_line("dynrange " + rtos(push_constant.dynamic_range));
*/
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
int passes = storage->gi_probe_is_using_two_bounces(gi_probe->probe) ? 2 : 1;
for (int pass = 0; pass < passes; pass++) {
for (int i = 0; i < gi_probe->mipmaps.size(); i++) {
if (i == 0) {
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[pass == 0 ? GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT : GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE]);
} else if (i == 1) {
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_COMPUTE_MIPMAP]);
}
if (pass == 1 || i > 0) {
RD::get_singleton()->compute_list_add_barrier(compute_list); //wait til previous step is done
}
if (pass == 0 || i > 0) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi_probe->mipmaps[i].uniform_set, 0);
} else {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi_probe->mipmaps[i].second_bounce_uniform_set, 0);
}
push_constant.cell_offset = gi_probe->mipmaps[i].cell_offset;
push_constant.cell_count = gi_probe->mipmaps[i].cell_count;
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbePushConstant));
RD::get_singleton()->compute_list_dispatch(compute_list, (gi_probe->mipmaps[i].cell_count - 1) / 64 + 1, 1, 1);
}
RD::get_singleton()->compute_list_add_barrier(compute_list); //wait til previous step is done
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_WRITE_TEXTURE]);
for (int i = 0; i < gi_probe->mipmaps.size(); i++) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi_probe->mipmaps[i].write_uniform_set, 0);
push_constant.cell_offset = gi_probe->mipmaps[i].cell_offset;
push_constant.cell_count = gi_probe->mipmaps[i].cell_count;
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbePushConstant));
RD::get_singleton()->compute_list_dispatch(compute_list, (gi_probe->mipmaps[i].cell_count - 1) / 64 + 1, 1, 1);
}
}
RD::get_singleton()->compute_list_end();
}
gi_probe->last_probe_version = storage->gi_probe_get_version(gi_probe->probe);
print_line("update GI");
}
void RasterizerSceneRD::_debug_giprobe(RID p_gi_probe, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, float p_alpha) {
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_gi_probe);
ERR_FAIL_COND(!gi_probe);
if (gi_probe->mipmaps.size() == 0) {
return;
}
CameraMatrix transform = (p_camera_with_transform * CameraMatrix(gi_probe->transform)) * CameraMatrix(storage->gi_probe_get_to_cell_xform(gi_probe->probe).affine_inverse());
int level = 0;
GIProbeDebugPushConstant push_constant;
push_constant.alpha = p_alpha;
push_constant.dynamic_range = storage->gi_probe_get_dynamic_range(gi_probe->probe);
push_constant.cell_offset = gi_probe->mipmaps[level].cell_offset;
push_constant.level = level;
int cell_count = gi_probe->mipmaps[level].cell_count;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
push_constant.projection[i * 4 + j] = transform.matrix[i][j];
}
}
if (giprobe_debug_uniform_set.is_valid()) {
RD::get_singleton()->free(giprobe_debug_uniform_set);
}
Vector<RD::Uniform> uniforms;
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 1;
u.ids.push_back(storage->gi_probe_get_data_buffer(gi_probe->probe));
uniforms.push_back(u);
}
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 2;
u.ids.push_back(gi_probe->texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_SAMPLER;
u.binding = 3;
u.ids.push_back(storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
}
if (gi_probe_use_anisotropy) {
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 4;
u.ids.push_back(gi_probe->anisotropy[0]);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 5;
u.ids.push_back(gi_probe->anisotropy[1]);
uniforms.push_back(u);
}
}
giprobe_debug_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_debug_shader_version_shaders[0], 0);
RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, giprobe_debug_shader_version_pipelines[p_lighting ? GI_PROBE_DEBUG_LIGHT : GI_PROBE_DEBUG_COLOR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, giprobe_debug_uniform_set, 0);
RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(GIProbeDebugPushConstant));
RD::get_singleton()->draw_list_draw(p_draw_list, false, cell_count, 36);
}
const Vector<RID> &RasterizerSceneRD::gi_probe_get_slots() const {
return gi_probe_slots;
}
bool RasterizerSceneRD::gi_probe_slots_are_dirty() const {
return gi_probe_slots_dirty;
}
void RasterizerSceneRD::gi_probe_slots_make_not_dirty() {
gi_probe_slots_dirty = false;
}
bool RasterizerSceneRD::gi_probe_is_high_quality() const {
return gi_probe_use_6_cones;
}
////////////////////////////////
RID RasterizerSceneRD::render_buffers_create() {
@@ -1218,12 +1680,12 @@ bool RasterizerSceneRD::is_using_radiance_cubemap_array() const {
return sky_use_cubemap_array;
}
void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
ERR_FAIL_COND(!rb && p_render_buffers.is_valid());
_render_scene(rb ? rb->data : (RenderBufferData *)NULL, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_light_cull_result, p_light_cull_count, p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_environment, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass);
_render_scene(rb ? rb->data : (RenderBufferData *)NULL, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_light_cull_result, p_light_cull_count, p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_gi_probe_cull_result, p_gi_probe_cull_count, p_environment, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass);
}
void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {
@@ -1418,6 +1880,20 @@ bool RasterizerSceneRD::free(RID p_rid) {
//ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_rid);
reflection_probe_release_atlas_index(p_rid);
reflection_probe_instance_owner.free(p_rid);
} else if (gi_probe_instance_owner.owns(p_rid)) {
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_rid);
if (gi_probe->texture.is_valid()) {
RD::get_singleton()->free(gi_probe->texture);
RD::get_singleton()->free(gi_probe->write_buffer);
}
if (gi_probe->anisotropy[0].is_valid()) {
RD::get_singleton()->free(gi_probe->anisotropy[0]);
RD::get_singleton()->free(gi_probe->anisotropy[1]);
}
gi_probe_slots.write[gi_probe->slot] = RID();
gi_probe_instance_owner.free(p_rid);
} else if (sky_owner.owns(p_rid)) {
_update_dirty_skys();
Sky *sky = sky_owner.getornull(p_rid);
@@ -1470,13 +1946,83 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
sky_use_cubemap_array = GLOBAL_GET("rendering/quality/reflections/texture_array_reflections");
// sky_use_cubemap_array = false;
uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
{
String defines = "";
//kinda complicated to compute the amount of slots, we try to use as many as we can
gi_probe_max_lights = 32;
gi_probe_lights = memnew_arr(GIProbeLight, gi_probe_max_lights);
gi_probe_lights_uniform = RD::get_singleton()->uniform_buffer_create(gi_probe_max_lights * sizeof(GIProbeLight));
gi_probe_use_anisotropy = GLOBAL_GET("rendering/quality/gi_probes/anisotropic");
gi_probe_use_6_cones = GLOBAL_GET("rendering/quality/gi_probes/high_quality");
if (textures_per_stage <= 16) {
gi_probe_slots.resize(2); //thats all you can get
gi_probe_use_anisotropy = false;
} else if (textures_per_stage <= 31) {
gi_probe_slots.resize(4); //thats all you can get, iOS
gi_probe_use_anisotropy = false;
} else if (textures_per_stage <= 128) {
gi_probe_slots.resize(32); //old intel
gi_probe_use_anisotropy = false;
} else if (textures_per_stage <= 256) {
gi_probe_slots.resize(64); //old intel too
gi_probe_use_anisotropy = false;
} else {
if (gi_probe_use_anisotropy) {
gi_probe_slots.resize(1024 / 3); //needs 3 textures
} else {
gi_probe_slots.resize(1024); //modern intel, nvidia, 8192 or greater
}
}
String defines = "\n#define MAX_LIGHTS " + itos(gi_probe_max_lights) + "\n";
if (gi_probe_use_anisotropy) {
defines += "\n#define MODE_ANISOTROPIC\n";
}
Vector<String> versions;
versions.push_back("");
giprobe_lighting_shader.initialize(versions, defines);
giprobe_lighting_shader_version = giprobe_lighting_shader.version_create();
giprobe_lighting_shader_version_shader = giprobe_lighting_shader.version_get_shader(giprobe_lighting_shader_version, 0);
versions.push_back("\n#define MODE_COMPUTE_LIGHT\n");
versions.push_back("\n#define MODE_SECOND_BOUNCE\n");
versions.push_back("\n#define MODE_UPDATE_MIPMAPS\n");
versions.push_back("\n#define MODE_WRITE_TEXTURE\n");
giprobe_shader.initialize(versions, defines);
giprobe_lighting_shader_version = giprobe_shader.version_create();
for (int i = 0; i < GI_PROBE_SHADER_VERSION_MAX; i++) {
giprobe_lighting_shader_version_shaders[i] = giprobe_shader.version_get_shader(giprobe_lighting_shader_version, i);
giprobe_lighting_shader_version_pipelines[i] = RD::get_singleton()->compute_pipeline_create(giprobe_lighting_shader_version_shaders[i]);
}
}
{
String defines;
if (gi_probe_use_anisotropy) {
defines += "\n#define USE_ANISOTROPY\n";
}
Vector<String> versions;
versions.push_back("\n#define MODE_DEBUG_COLOR\n");
versions.push_back("\n#define MODE_DEBUG_LIGHT\n");
giprobe_debug_shader.initialize(versions, defines);
giprobe_debug_shader_version = giprobe_debug_shader.version_create();
for (int i = 0; i < GI_PROBE_DEBUG_MAX; i++) {
giprobe_debug_shader_version_shaders[i] = giprobe_debug_shader.version_get_shader(giprobe_debug_shader_version, i);
RD::PipelineRasterizationState rs;
rs.cull_mode = RD::POLYGON_CULL_FRONT;
RD::PipelineDepthStencilState ds;
ds.enable_depth_test = true;
ds.enable_depth_write = true;
ds.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL;
giprobe_debug_shader_version_pipelines[i].setup(giprobe_debug_shader_version_shaders[i], RD::RENDER_PRIMITIVE_TRIANGLES, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0);
}
}
}
@@ -1489,4 +2035,7 @@ RasterizerSceneRD::~RasterizerSceneRD() {
for (Map<int, ShadowCubemap>::Element *E = shadow_cubemaps.front(); E; E = E->next()) {
RD::get_singleton()->free(E->get().cubemap);
}
RD::get_singleton()->free(gi_probe_lights_uniform);
memdelete_arr(gi_probe_lights);
}