WIP: eevee-next-world-irradiance #108304
|
@ -491,6 +491,7 @@ set(GLSL_SRC
|
|||
engines/eevee_next/shaders/eevee_shadow_tilemap_init_comp.glsl
|
||||
engines/eevee_next/shaders/eevee_shadow_tilemap_lib.glsl
|
||||
engines/eevee_next/shaders/eevee_spherical_harmonics_lib.glsl
|
||||
engines/eevee_next/shaders/eevee_surf_capture_frag.glsl
|
||||
engines/eevee_next/shaders/eevee_surf_deferred_frag.glsl
|
||||
engines/eevee_next/shaders/eevee_surf_depth_frag.glsl
|
||||
engines/eevee_next/shaders/eevee_surf_forward_frag.glsl
|
||||
|
|
|
@ -122,6 +122,10 @@
|
|||
#define LIGHT_BUF_SLOT 1
|
||||
#define LIGHT_ZBIN_BUF_SLOT 2
|
||||
#define LIGHT_TILE_BUF_SLOT 3
|
||||
/* Only during surface capture. */
|
||||
#define SURFEL_BUF_SLOT 4
|
||||
/* Only during surface capture. */
|
||||
#define CAPTURE_BUF_SLOT 5
|
||||
/* Only during surface shading. */
|
||||
#define RBUFS_AOV_BUF_SLOT 5
|
||||
/* Only during shadow rendering. */
|
||||
|
|
|
@ -249,6 +249,8 @@ void Instance::render_sample()
|
|||
|
||||
main_view.render();
|
||||
|
||||
irradiance_cache.create_surfels();
|
||||
|
||||
motion_blur.step();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,38 +1,13 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_rand.hh"
|
||||
#include "eevee_instance.hh"
|
||||
|
||||
#include "eevee_irradiance_cache.hh"
|
||||
|
||||
namespace blender::eevee {
|
||||
|
||||
void IrradianceCache::generate_random_surfels()
|
||||
{
|
||||
const int surfels_len = 256;
|
||||
debug_surfels.resize(surfels_len);
|
||||
|
||||
RandomNumberGenerator rng;
|
||||
rng.seed(0);
|
||||
|
||||
for (DebugSurfel &surfel : debug_surfels) {
|
||||
float3 random = rng.get_unit_float3();
|
||||
surfel.position = random * 3.0f;
|
||||
surfel.normal = random;
|
||||
surfel.color = float4(rng.get_float(), rng.get_float(), rng.get_float(), 1.0f);
|
||||
}
|
||||
|
||||
debug_surfels.push_update();
|
||||
}
|
||||
|
||||
void IrradianceCache::init()
|
||||
{
|
||||
if (debug_surfels_sh_ == nullptr) {
|
||||
debug_surfels_sh_ = inst_.shaders.static_shader_get(DEBUG_SURFELS);
|
||||
}
|
||||
|
||||
/* TODO: Remove this. */
|
||||
generate_random_surfels();
|
||||
}
|
||||
|
||||
void IrradianceCache::sync()
|
||||
|
@ -42,24 +17,114 @@ void IrradianceCache::sync()
|
|||
|
||||
void IrradianceCache::debug_pass_sync()
|
||||
{
|
||||
if (inst_.debug_mode == eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS) {
|
||||
debug_surfels_ps_.init();
|
||||
debug_surfels_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
|
||||
DRW_STATE_DEPTH_LESS_EQUAL);
|
||||
debug_surfels_ps_.shader_set(debug_surfels_sh_);
|
||||
debug_surfels_ps_.bind_ssbo("surfels_buf", debug_surfels);
|
||||
debug_surfels_ps_.push_constant("surfel_radius", 0.25f);
|
||||
debug_surfels_ps_.draw_procedural(GPU_PRIM_TRI_STRIP, debug_surfels.size(), 4);
|
||||
if (!ELEM(inst_.debug_mode,
|
||||
eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_NORMAL,
|
||||
eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_IRRADIANCE)) {
|
||||
return;
|
||||
}
|
||||
debug_surfels_ps_.init();
|
||||
debug_surfels_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
|
||||
DRW_STATE_DEPTH_LESS_EQUAL);
|
||||
debug_surfels_ps_.shader_set(inst_.shaders.static_shader_get(DEBUG_SURFELS));
|
||||
debug_surfels_ps_.bind_ssbo("surfels_buf", surfels_buf_);
|
||||
debug_surfels_ps_.push_constant("surfel_radius", 0.5f / 4.0f);
|
||||
debug_surfels_ps_.push_constant("debug_mode", static_cast<int>(inst_.debug_mode));
|
||||
debug_surfels_ps_.draw_procedural(GPU_PRIM_TRI_STRIP, surfels_buf_.size(), 4);
|
||||
}
|
||||
|
||||
void IrradianceCache::debug_draw(View &view, GPUFrameBuffer *view_fb)
|
||||
{
|
||||
if (inst_.debug_mode == eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS) {
|
||||
inst_.info = "Debug Mode: Irradiance Cache Surfels";
|
||||
GPU_framebuffer_bind(view_fb);
|
||||
inst_.manager->submit(debug_surfels_ps_, view);
|
||||
switch (inst_.debug_mode) {
|
||||
case eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_NORMAL:
|
||||
inst_.info = "Debug Mode: Surfels Normal";
|
||||
break;
|
||||
case eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_IRRADIANCE:
|
||||
inst_.info = "Debug Mode: Surfels Irradiance";
|
||||
break;
|
||||
default:
|
||||
/* Nothing to display. */
|
||||
return;
|
||||
}
|
||||
|
||||
GPU_framebuffer_bind(view_fb);
|
||||
inst_.manager->submit(debug_surfels_ps_, view);
|
||||
}
|
||||
|
||||
void IrradianceCache::create_surfels()
|
||||
{
|
||||
/**
|
||||
* We rasterize the scene along the 3 axes. Each generated fragment will write a surface element
|
||||
* so raster grid density need to match the desired surfel density. We do a first pass to know
|
||||
* how much surfel to allocate then render again to create the surfels.
|
||||
*/
|
||||
using namespace blender::math;
|
||||
|
||||
/* Attachment-less frame-buffer. */
|
||||
empty_raster_fb_.ensure(int2(40 * 4));
|
||||
|
||||
/** We could use multi-view rendering here to avoid multiple submissions but it is unlikely to
|
||||
* make any difference. The bottleneck is still the light propagation loop. */
|
||||
auto render_axis = [&](Axis axis) {
|
||||
/* TODO(fclem): get scene bounds GPU or CPU side. Or use the irradiance grid extents. */
|
||||
float4x4 winmat = math::projection::orthographic(-20.0f, 20.0f, -20.0f, 20.0f, -20.0f, 20.0f);
|
||||
|
||||
CartesianBasis basis = from_orthonormal_axes(AxisSigned(axis).next_after(), axis);
|
||||
view_.sync(from_rotation<float4x4>(basis), winmat);
|
||||
view_.visibility_test(false);
|
||||
|
||||
inst_.pipelines.capture.render(view_);
|
||||
};
|
||||
|
||||
DRW_stats_group_start("IrradianceBake.SurfelsCount");
|
||||
|
||||
/* Raster the scene to query the number of surfel needed. */
|
||||
capture_info_buf_.do_surfel_count = true;
|
||||
capture_info_buf_.do_surfel_output = false;
|
||||
capture_info_buf_.surfel_len = 0u;
|
||||
capture_info_buf_.push_update();
|
||||
render_axis(Axis::X);
|
||||
render_axis(Axis::Y);
|
||||
render_axis(Axis::Z);
|
||||
|
||||
DRW_stats_group_end();
|
||||
|
||||
/* Allocate surfel pool. */
|
||||
capture_info_buf_.read();
|
||||
if (capture_info_buf_.surfel_len == 0) {
|
||||
/* Not surfel to allocated. */
|
||||
return;
|
||||
}
|
||||
/* 1000000 for testing. */
|
||||
if (capture_info_buf_.surfel_len * sizeof(Surfel) > 1000000) {
|
||||
/* TODO(fclem): Display error message. */
|
||||
/* Not enough GPU memory to fit all needed surfels. */
|
||||
return;
|
||||
}
|
||||
surfels_buf_.resize(capture_info_buf_.surfel_len);
|
||||
|
||||
DRW_stats_group_start("IrradianceBake.SurfelsCreate");
|
||||
|
||||
/* Raster the scene to generate the surfels. */
|
||||
capture_info_buf_.do_surfel_count = true;
|
||||
capture_info_buf_.do_surfel_output = true;
|
||||
capture_info_buf_.surfel_len = 0u;
|
||||
capture_info_buf_.push_update();
|
||||
render_axis(Axis::X);
|
||||
render_axis(Axis::Y);
|
||||
render_axis(Axis::Z);
|
||||
|
||||
DRW_stats_group_end();
|
||||
|
||||
/* TODO(fclem): Resize at the end of the light propagation. */
|
||||
}
|
||||
|
||||
void IrradianceCache::propagate_light()
|
||||
{
|
||||
/* Evaluate direct lighting (and also clear the surfels radiance). */
|
||||
/* For every ray direction over the sphere. */
|
||||
/* Create the surfels lists. */
|
||||
/* Sort the surfels lists. */
|
||||
/* Propagate light. */
|
||||
}
|
||||
|
||||
} // namespace blender::eevee
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup eevee
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "eevee_shader_shared.hh"
|
||||
|
@ -7,14 +11,23 @@
|
|||
namespace blender::eevee {
|
||||
|
||||
class Instance;
|
||||
class CapturePipeline;
|
||||
|
||||
class IrradianceCache {
|
||||
friend CapturePipeline;
|
||||
|
||||
private:
|
||||
Instance &inst_;
|
||||
|
||||
DebugSurfelBuf debug_surfels;
|
||||
/** Surface elements that represent the scene. */
|
||||
SurfelBuf surfels_buf_;
|
||||
/** Capture state. */
|
||||
CaptureInfoBuf capture_info_buf_;
|
||||
|
||||
PassSimple debug_surfels_ps_ = {"IrradianceCache.Debug"};
|
||||
GPUShader *debug_surfels_sh_ = nullptr;
|
||||
|
||||
Framebuffer empty_raster_fb_ = {"empty_raster_fb_"};
|
||||
View view_ = {"ortho_raster_view"};
|
||||
|
||||
/* TODO: Remove this. */
|
||||
void generate_random_surfels();
|
||||
|
@ -26,6 +39,9 @@ class IrradianceCache {
|
|||
void init();
|
||||
void sync();
|
||||
|
||||
void create_surfels();
|
||||
void propagate_light();
|
||||
|
||||
void debug_pass_sync();
|
||||
void debug_draw(View &view, GPUFrameBuffer *view_fb);
|
||||
};
|
||||
|
|
|
@ -242,6 +242,11 @@ Material &MaterialModule::material_sync(Object *ob,
|
|||
/* Order is important for transparent. */
|
||||
mat.prepass = material_pass_get(ob, blender_mat, prepass_pipe, geometry_type);
|
||||
mat.shading = material_pass_get(ob, blender_mat, surface_pipe, geometry_type);
|
||||
if (true) {
|
||||
/* TODO(fclem): This can be expensive since it can trigger a shader compilation. So better
|
||||
* avoid this if we can. */
|
||||
mat.capture = material_pass_get(ob, blender_mat, MAT_PIPE_CAPTURE, geometry_type);
|
||||
}
|
||||
if (blender_mat->blend_shadow == MA_BS_NONE) {
|
||||
mat.shadow = MaterialPass();
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ enum eMaterialPipeline {
|
|||
MAT_PIPE_FORWARD_PREPASS_VELOCITY,
|
||||
MAT_PIPE_VOLUME,
|
||||
MAT_PIPE_SHADOW,
|
||||
MAT_PIPE_CAPTURE,
|
||||
};
|
||||
|
||||
enum eMaterialGeometry {
|
||||
|
@ -48,16 +49,16 @@ static inline void material_type_from_shader_uuid(uint64_t shader_uuid,
|
|||
eMaterialPipeline &pipeline_type,
|
||||
eMaterialGeometry &geometry_type)
|
||||
{
|
||||
const uint64_t geometry_mask = ((1u << 3u) - 1u);
|
||||
const uint64_t pipeline_mask = ((1u << 3u) - 1u);
|
||||
const uint64_t geometry_mask = ((1u << 4u) - 1u);
|
||||
const uint64_t pipeline_mask = ((1u << 4u) - 1u);
|
||||
geometry_type = static_cast<eMaterialGeometry>(shader_uuid & geometry_mask);
|
||||
pipeline_type = static_cast<eMaterialPipeline>((shader_uuid >> 3u) & pipeline_mask);
|
||||
pipeline_type = static_cast<eMaterialPipeline>((shader_uuid >> 4u) & pipeline_mask);
|
||||
}
|
||||
|
||||
static inline uint64_t shader_uuid_from_material_type(eMaterialPipeline pipeline_type,
|
||||
eMaterialGeometry geometry_type)
|
||||
{
|
||||
return geometry_type | (pipeline_type << 3);
|
||||
return geometry_type | (pipeline_type << 4);
|
||||
}
|
||||
|
||||
ENUM_OPERATORS(eClosureBits, CLOSURE_AMBIENT_OCCLUSION)
|
||||
|
@ -209,7 +210,7 @@ struct MaterialPass {
|
|||
|
||||
struct Material {
|
||||
bool is_alpha_blend_transparent;
|
||||
MaterialPass shadow, shading, prepass;
|
||||
MaterialPass shadow, shading, prepass, capture;
|
||||
};
|
||||
|
||||
struct MaterialArray {
|
||||
|
|
|
@ -503,4 +503,37 @@ void DeferredPipeline::render(View &view,
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Capture Pipeline
|
||||
*
|
||||
* \{ */
|
||||
|
||||
void CapturePipeline::sync()
|
||||
{
|
||||
surface_ps_.init();
|
||||
/* Surfel output is done using a SSBO, so no need for a fragment shader output color or depth. */
|
||||
/* WORKAROUND: Avoid rasterizer discard, but the shaders actually use no fragment output. */
|
||||
surface_ps_.state_set(DRW_STATE_WRITE_STENCIL);
|
||||
surface_ps_.framebuffer_set(&inst_.irradiance_cache.empty_raster_fb_);
|
||||
|
||||
surface_ps_.bind_ssbo(SURFEL_BUF_SLOT, &inst_.irradiance_cache.surfels_buf_);
|
||||
surface_ps_.bind_ssbo(CAPTURE_BUF_SLOT, &inst_.irradiance_cache.capture_info_buf_);
|
||||
|
||||
surface_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
|
||||
/* TODO(fclem): Remove. There should be no view dependent behavior during capture. */
|
||||
surface_ps_.bind_ubo(CAMERA_BUF_SLOT, inst_.camera.ubo_get());
|
||||
}
|
||||
|
||||
PassMain::Sub *CapturePipeline::surface_material_add(GPUMaterial *gpumat)
|
||||
{
|
||||
return &surface_ps_.sub(GPU_material_get_name(gpumat));
|
||||
}
|
||||
|
||||
void CapturePipeline::render(View &view)
|
||||
{
|
||||
inst_.manager->submit(surface_ps_, view);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender::eevee
|
||||
|
|
|
@ -184,6 +184,28 @@ class DeferredPipeline {
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Capture Pipeline
|
||||
*
|
||||
* \{ */
|
||||
|
||||
class CapturePipeline {
|
||||
private:
|
||||
Instance &inst_;
|
||||
|
||||
PassMain surface_ps_ = {"Capture.Surface"};
|
||||
|
||||
public:
|
||||
CapturePipeline(Instance &inst) : inst_(inst){};
|
||||
|
||||
PassMain::Sub *surface_material_add(GPUMaterial *gpumat);
|
||||
|
||||
void sync();
|
||||
void render(View &view);
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Utility texture
|
||||
*
|
||||
|
@ -271,17 +293,20 @@ class PipelineModule {
|
|||
DeferredPipeline deferred;
|
||||
ForwardPipeline forward;
|
||||
ShadowPipeline shadow;
|
||||
CapturePipeline capture;
|
||||
|
||||
UtilityTexture utility_tx;
|
||||
|
||||
public:
|
||||
PipelineModule(Instance &inst) : world(inst), deferred(inst), forward(inst), shadow(inst){};
|
||||
PipelineModule(Instance &inst)
|
||||
: world(inst), deferred(inst), forward(inst), shadow(inst), capture(inst){};
|
||||
|
||||
void begin_sync()
|
||||
{
|
||||
deferred.begin_sync();
|
||||
forward.sync();
|
||||
shadow.sync();
|
||||
capture.sync();
|
||||
}
|
||||
|
||||
void end_sync()
|
||||
|
@ -324,6 +349,8 @@ class PipelineModule {
|
|||
return nullptr;
|
||||
case MAT_PIPE_SHADOW:
|
||||
return shadow.surface_material_add(gpumat);
|
||||
case MAT_PIPE_CAPTURE:
|
||||
return capture.surface_material_add(gpumat);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -414,7 +414,6 @@ void ShaderModule::material_create_info_ammend(GPUMaterial *gpumat, GPUCodegenOu
|
|||
info.additional_info("eevee_geom_curves");
|
||||
break;
|
||||
case MAT_GEOM_MESH:
|
||||
default:
|
||||
info.additional_info("eevee_geom_mesh");
|
||||
break;
|
||||
}
|
||||
|
@ -439,6 +438,9 @@ void ShaderModule::material_create_info_ammend(GPUMaterial *gpumat, GPUCodegenOu
|
|||
case MAT_PIPE_SHADOW:
|
||||
info.additional_info("eevee_surf_shadow");
|
||||
break;
|
||||
case MAT_PIPE_CAPTURE:
|
||||
info.additional_info("eevee_surf_capture");
|
||||
break;
|
||||
case MAT_PIPE_DEFERRED:
|
||||
info.additional_info("eevee_surf_deferred");
|
||||
break;
|
||||
|
@ -446,7 +448,7 @@ void ShaderModule::material_create_info_ammend(GPUMaterial *gpumat, GPUCodegenOu
|
|||
info.additional_info("eevee_surf_forward");
|
||||
break;
|
||||
default:
|
||||
BLI_assert(0);
|
||||
BLI_assert_unreachable();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -51,7 +51,8 @@ enum eDebugMode : uint32_t {
|
|||
/**
|
||||
* Display IrradianceCache surfels.
|
||||
*/
|
||||
DEBUG_IRRADIANCE_CACHE_SURFELS = 3u,
|
||||
DEBUG_IRRADIANCE_CACHE_SURFELS_NORMAL = 3u,
|
||||
DEBUG_IRRADIANCE_CACHE_SURFELS_IRRADIANCE = 4u,
|
||||
/**
|
||||
* Show tiles depending on their status.
|
||||
*/
|
||||
|
@ -826,17 +827,48 @@ static inline ShadowTileDataPacked shadow_tile_pack(ShadowTileData tile)
|
|||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Debug
|
||||
/** \name Irradiance Cache
|
||||
* \{ */
|
||||
|
||||
struct DebugSurfel {
|
||||
struct Surfel {
|
||||
/** World position of the surfel. */
|
||||
packed_float3 position;
|
||||
int _pad0;
|
||||
/** World orientation of the surface. */
|
||||
packed_float3 normal;
|
||||
int _pad1;
|
||||
float4 color;
|
||||
/** Surface albedo to apply to incoming radiance. */
|
||||
packed_float3 albedo;
|
||||
int _pad2;
|
||||
/** Accumulated reflected radiance at this point. */
|
||||
packed_float3 radiance;
|
||||
int _pad3;
|
||||
};
|
||||
BLI_STATIC_ASSERT_ALIGN(DebugSurfel, 16)
|
||||
BLI_STATIC_ASSERT_ALIGN(Surfel, 16)
|
||||
|
||||
struct CaptureInfoData {
|
||||
/** True if the surface shader needs to write the surfel data. */
|
||||
bool1 do_surfel_output;
|
||||
/** True if the surface shader needs to increment the surfel_len. */
|
||||
bool1 do_surfel_count;
|
||||
/** Number of surfels inside the surfel buffer or the needed len. */
|
||||
uint surfel_len;
|
||||
int _pad0;
|
||||
};
|
||||
BLI_STATIC_ASSERT_ALIGN(CaptureInfoData, 16)
|
||||
|
||||
enum SurfelListEntryType : uint32_t {
|
||||
ENTRY_SURFEL = 0u,
|
||||
ENTRY_IRRADIANCE_SAMPLE = 1u,
|
||||
};
|
||||
|
||||
struct SurfelListEntry {
|
||||
uint next_entry_index;
|
||||
SurfelListEntryType type;
|
||||
uint payload;
|
||||
uint _pad0;
|
||||
};
|
||||
BLI_STATIC_ASSERT_ALIGN(SurfelListEntry, 16)
|
||||
|
||||
/** \} */
|
||||
|
||||
|
@ -947,7 +979,6 @@ using DepthOfFieldDataBuf = draw::UniformBuffer<DepthOfFieldData>;
|
|||
using DepthOfFieldScatterListBuf = draw::StorageArrayBuffer<ScatterRect, 16, true>;
|
||||
using DrawIndirectBuf = draw::StorageBuffer<DrawCommand, true>;
|
||||
using FilmDataBuf = draw::UniformBuffer<FilmData>;
|
||||
using DebugSurfelBuf = draw::StorageArrayBuffer<DebugSurfel, 64>;
|
||||
using HiZDataBuf = draw::UniformBuffer<HiZData>;
|
||||
using LightCullingDataBuf = draw::StorageBuffer<LightCullingData>;
|
||||
using LightCullingKeyBuf = draw::StorageArrayBuffer<uint, LIGHT_CHUNK, true>;
|
||||
|
@ -965,6 +996,8 @@ using ShadowPageCacheBuf = draw::StorageArrayBuffer<uint2, SHADOW_MAX_PAGE, true
|
|||
using ShadowTileMapDataBuf = draw::StorageVectorBuffer<ShadowTileMapData, SHADOW_MAX_TILEMAP>;
|
||||
using ShadowTileMapClipBuf = draw::StorageArrayBuffer<ShadowTileMapClip, SHADOW_MAX_TILEMAP, true>;
|
||||
using ShadowTileDataBuf = draw::StorageArrayBuffer<ShadowTileDataPacked, SHADOW_MAX_TILE, true>;
|
||||
using SurfelBuf = draw::StorageArrayBuffer<Surfel, 64, true>;
|
||||
using CaptureInfoBuf = draw::StorageBuffer<CaptureInfoData>;
|
||||
using VelocityGeometryBuf = draw::StorageArrayBuffer<float4, 16, true>;
|
||||
using VelocityIndexBuf = draw::StorageArrayBuffer<VelocityIndex, 16>;
|
||||
using VelocityObjectBuf = draw::StorageArrayBuffer<float4x4, 16>;
|
||||
|
|
|
@ -131,6 +131,7 @@ void SyncModule::sync_mesh(Object *ob,
|
|||
geometry_call(material.shading.sub_pass, geom, res_handle);
|
||||
geometry_call(material.prepass.sub_pass, geom, res_handle);
|
||||
geometry_call(material.shadow.sub_pass, geom, res_handle);
|
||||
geometry_call(material.capture.sub_pass, geom, res_handle);
|
||||
|
||||
is_shadow_caster = is_shadow_caster || material.shadow.sub_pass != nullptr;
|
||||
is_alpha_blend = is_alpha_blend || material.is_alpha_blend_transparent;
|
||||
|
|
|
@ -134,7 +134,6 @@ void ShadingView::render()
|
|||
inst_.lights.debug_draw(render_view_new_, combined_fb_);
|
||||
inst_.hiz_buffer.debug_draw(render_view_new_, combined_fb_);
|
||||
inst_.shadows.debug_draw(render_view_new_, combined_fb_);
|
||||
|
||||
inst_.irradiance_cache.debug_draw(render_view_new_, combined_fb_);
|
||||
|
||||
GPUTexture *combined_final_tx = render_postfx(rbufs.combined_tx);
|
||||
|
|
|
@ -1,8 +1,17 @@
|
|||
|
||||
void main()
|
||||
{
|
||||
DebugSurfel surfel = surfels_buf[surfel_index];
|
||||
out_color = surfel.color;
|
||||
Surfel surfel = surfels_buf[surfel_index];
|
||||
|
||||
switch (eDebugMode(debug_mode)) {
|
||||
default:
|
||||
case DEBUG_IRRADIANCE_CACHE_SURFELS_NORMAL:
|
||||
out_color = vec4(surfel.normal, 1.0);
|
||||
break;
|
||||
case DEBUG_IRRADIANCE_CACHE_SURFELS_IRRADIANCE:
|
||||
out_color = vec4(surfel.radiance, 1.0);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Display surfels as circles. */
|
||||
if (distance(P, surfel.position) > surfel_radius) {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
void main()
|
||||
{
|
||||
surfel_index = gl_InstanceID;
|
||||
DebugSurfel surfel = surfels_buf[surfel_index];
|
||||
Surfel surfel = surfels_buf[surfel_index];
|
||||
|
||||
vec3 lP;
|
||||
|
||||
|
@ -35,4 +35,5 @@ void main()
|
|||
P = (model_matrix * vec4(lP, 1)).xyz;
|
||||
|
||||
gl_Position = point_world_to_ndc(P);
|
||||
gl_Position.z -= 2.5e-5;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
|
||||
/**
|
||||
* Surface Capture: Output surface parameters to diverse storage.
|
||||
*
|
||||
* This is a separate shader to allow custom closure behavior and avoid putting more complexity
|
||||
* into other surface shaders.
|
||||
*/
|
||||
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_math_vector_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_gbuffer_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(common_hair_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_surf_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_nodetree_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl)
|
||||
|
||||
vec4 closure_to_rgba(Closure cl)
|
||||
{
|
||||
return vec4(0.0);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
init_globals();
|
||||
|
||||
/* TODO(fclem): Remove random sampling for capture and accumulate color. */
|
||||
g_closure_rand = 0.5;
|
||||
|
||||
nodetree_surface();
|
||||
|
||||
g_diffuse_data.color *= g_diffuse_data.weight;
|
||||
g_reflection_data.color *= g_reflection_data.weight;
|
||||
g_refraction_data.color *= g_refraction_data.weight;
|
||||
|
||||
vec3 albedo = g_diffuse_data.color + g_reflection_data.color;
|
||||
|
||||
/* ----- Surfel output ----- */
|
||||
|
||||
if (capture_info_buf.do_surfel_count) {
|
||||
/* Generate a surfel only once. This check allow cases where no axis is dominant. */
|
||||
bool is_surface_view_aligned = dominant_axis(g_data.Ng) == dominant_axis(cameraForward);
|
||||
if (is_surface_view_aligned) {
|
||||
uint surfel_id = atomicAdd(capture_info_buf.surfel_len, 1u);
|
||||
if (capture_info_buf.do_surfel_output) {
|
||||
surfel_buf[surfel_id].position = g_data.P;
|
||||
surfel_buf[surfel_id].normal = gl_FrontFacing ? g_data.Ng : -g_data.Ng;
|
||||
surfel_buf[surfel_id].albedo = albedo;
|
||||
surfel_buf[surfel_id].radiance = g_emission;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@ GPU_SHADER_CREATE_INFO(eevee_debug_surfels)
|
|||
.vertex_out(eeve_debug_surfel_iface)
|
||||
.fragment_source("eevee_debug_surfels_frag.glsl")
|
||||
.fragment_out(0, Type::VEC4, "out_color")
|
||||
.storage_buf(0, Qualifier::READ, "DebugSurfel", "surfels_buf[]")
|
||||
.storage_buf(0, Qualifier::READ, "Surfel", "surfels_buf[]")
|
||||
.push_constant(Type::FLOAT, "surfel_radius")
|
||||
.push_constant(Type::INT, "debug_mode")
|
||||
.do_static_compilation(true);
|
||||
|
|
|
@ -147,6 +147,13 @@ GPU_SHADER_CREATE_INFO(eevee_surf_forward)
|
|||
// "eevee_render_pass_out",
|
||||
);
|
||||
|
||||
GPU_SHADER_CREATE_INFO(eevee_surf_capture)
|
||||
.vertex_out(eevee_surf_iface)
|
||||
.storage_buf(SURFEL_BUF_SLOT, Qualifier::WRITE, "Surfel", "surfel_buf[]")
|
||||
.storage_buf(CAPTURE_BUF_SLOT, Qualifier::READ_WRITE, "CaptureInfoData", "capture_info_buf")
|
||||
.fragment_source("eevee_surf_capture_frag.glsl")
|
||||
.additional_info("eevee_camera", "eevee_utility_texture");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(eevee_surf_depth)
|
||||
.vertex_out(eevee_surf_iface)
|
||||
.fragment_source("eevee_surf_depth_frag.glsl")
|
||||
|
@ -233,6 +240,7 @@ GPU_SHADER_CREATE_INFO(eevee_material_stub).define("EEVEE_MATERIAL_STUBS");
|
|||
EEVEE_MAT_GEOM_VARIATIONS(name##_depth, "eevee_surf_depth", __VA_ARGS__) \
|
||||
EEVEE_MAT_GEOM_VARIATIONS(name##_deferred, "eevee_surf_deferred", __VA_ARGS__) \
|
||||
EEVEE_MAT_GEOM_VARIATIONS(name##_forward, "eevee_surf_forward", __VA_ARGS__) \
|
||||
EEVEE_MAT_GEOM_VARIATIONS(name##_capture, "eevee_surf_capture", __VA_ARGS__) \
|
||||
EEVEE_MAT_GEOM_VARIATIONS(name##_shadow, "eevee_surf_shadow", __VA_ARGS__)
|
||||
|
||||
EEVEE_MAT_PIPE_VARIATIONS(eevee_surface, "eevee_material_stub")
|
||||
|
|
Loading…
Reference in New Issue