diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index ad2291cfb8b..6382e4ed669 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -154,6 +154,7 @@ set(SRC engines/eevee_next/eevee_material.cc engines/eevee_next/eevee_motion_blur.cc engines/eevee_next/eevee_pipeline.cc + engines/eevee_next/eevee_reflection_probes.cc engines/eevee_next/eevee_renderbuffers.cc engines/eevee_next/eevee_sampling.cc engines/eevee_next/eevee_shader.cc @@ -296,6 +297,7 @@ set(SRC engines/eevee_next/eevee_material.hh engines/eevee_next/eevee_motion_blur.hh engines/eevee_next/eevee_pipeline.hh + engines/eevee_next/eevee_reflection_probes.hh engines/eevee_next/eevee_renderbuffers.hh engines/eevee_next/eevee_sampling.hh engines/eevee_next/eevee_shader.hh @@ -511,6 +513,7 @@ set(GLSL_SRC engines/eevee_next/shaders/eevee_motion_blur_gather_comp.glsl engines/eevee_next/shaders/eevee_motion_blur_lib.glsl engines/eevee_next/shaders/eevee_nodetree_lib.glsl + engines/eevee_next/shaders/eevee_reflection_probe_lib.glsl engines/eevee_next/shaders/eevee_sampling_lib.glsl engines/eevee_next/shaders/eevee_shadow_debug_frag.glsl engines/eevee_next/shaders/eevee_shadow_lib.glsl diff --git a/source/blender/draw/engines/eevee_next/eevee_defines.hh b/source/blender/draw/engines/eevee_next/eevee_defines.hh index 0969638dcab..e0d985f5d45 100644 --- a/source/blender/draw/engines/eevee_next/eevee_defines.hh +++ b/source/blender/draw/engines/eevee_next/eevee_defines.hh @@ -108,6 +108,7 @@ #define SHADOW_ATLAS_TEX_SLOT 5 #define SSS_TRANSMITTANCE_TEX_SLOT 6 #define IRRADIANCE_ATLAS_TEX_SLOT 7 +#define REFLECTION_PROBE_TEX_SLOT 8 /* Only during shadow rendering. */ #define SHADOW_RENDER_MAP_SLOT 4 diff --git a/source/blender/draw/engines/eevee_next/eevee_instance.cc b/source/blender/draw/engines/eevee_next/eevee_instance.cc index 2094e1ec585..fa400dc4f7d 100644 --- a/source/blender/draw/engines/eevee_next/eevee_instance.cc +++ b/source/blender/draw/engines/eevee_next/eevee_instance.cc @@ -70,6 +70,7 @@ void Instance::init(const int2 &output_res, motion_blur.init(); main_view.init(); irradiance_cache.init(); + reflection_probes.init(); } void Instance::init_light_bake(Depsgraph *depsgraph, draw::Manager *manager) @@ -290,6 +291,7 @@ void Instance::render_sample() sampling.step(); + capture_view.render(); main_view.render(); motion_blur.step(); diff --git a/source/blender/draw/engines/eevee_next/eevee_instance.hh b/source/blender/draw/engines/eevee_next/eevee_instance.hh index 5c95a35503d..777f3f34d74 100644 --- a/source/blender/draw/engines/eevee_next/eevee_instance.hh +++ b/source/blender/draw/engines/eevee_next/eevee_instance.hh @@ -27,6 +27,7 @@ #include "eevee_material.hh" #include "eevee_motion_blur.hh" #include "eevee_pipeline.hh" +#include "eevee_reflection_probes.hh" #include "eevee_renderbuffers.hh" #include "eevee_sampling.hh" #include "eevee_shader.hh" @@ -54,6 +55,7 @@ class Instance { PipelineModule pipelines; ShadowModule shadows; LightModule lights; + ReflectionProbeModule reflection_probes; VelocityModule velocity; MotionBlurModule motion_blur; DepthOfField depth_of_field; @@ -65,6 +67,7 @@ class Instance { Film film; RenderBuffers render_buffers; MainView main_view; + CaptureView capture_view; World world; LightProbeModule light_probes; IrradianceCache irradiance_cache; @@ -105,6 +108,7 @@ class Instance { pipelines(*this), shadows(*this), lights(*this), + reflection_probes(*this), velocity(*this), motion_blur(*this), depth_of_field(*this), @@ -115,6 +119,7 @@ class Instance { film(*this), render_buffers(*this), main_view(*this), + capture_view(*this), world(*this), light_probes(*this), irradiance_cache(*this){}; diff --git a/source/blender/draw/engines/eevee_next/eevee_pipeline.cc b/source/blender/draw/engines/eevee_next/eevee_pipeline.cc index 738a9002a3c..94173a8f4ce 100644 --- a/source/blender/draw/engines/eevee_next/eevee_pipeline.cc +++ b/source/blender/draw/engines/eevee_next/eevee_pipeline.cc @@ -56,6 +56,56 @@ void BackgroundPipeline::render(View &view) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name World Probe Pipeline + * \{ */ + +void WorldPipeline::sync(GPUMaterial *gpumat) +{ + const int2 extent(1); + constexpr eGPUTextureUsage usage = GPU_TEXTURE_USAGE_SHADER_WRITE; + dummy_cryptomatte_tx_.ensure_2d(GPU_RGBA32F, extent, usage); + dummy_renderpass_tx_.ensure_2d(GPU_RGBA16F, extent, usage); + dummy_aov_color_tx_.ensure_2d_array(GPU_RGBA16F, extent, 1, usage); + dummy_aov_value_tx_.ensure_2d_array(GPU_R16F, extent, 1, usage); + + PassSimple &pass = cubemap_face_ps_; + pass.init(); + pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_ALWAYS); + + Manager &manager = *inst_.manager; + ResourceHandle handle = manager.resource_handle(float4x4::identity()); + pass.material_set(manager, gpumat); + pass.push_constant("world_opacity_fade", 1.0f); + + pass.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx); + pass.bind_ubo(CAMERA_BUF_SLOT, inst_.camera.ubo_get()); + pass.bind_ubo(RBUFS_BUF_SLOT, &inst_.render_buffers.data); + pass.bind_image("rp_normal_img", dummy_renderpass_tx_); + pass.bind_image("rp_light_img", dummy_renderpass_tx_); + pass.bind_image("rp_diffuse_color_img", dummy_renderpass_tx_); + pass.bind_image("rp_specular_color_img", dummy_renderpass_tx_); + pass.bind_image("rp_emission_img", dummy_renderpass_tx_); + pass.bind_image("rp_cryptomatte_img", dummy_cryptomatte_tx_); + pass.bind_image("rp_color_img", dummy_aov_color_tx_); + pass.bind_image("rp_value_img", dummy_aov_value_tx_); + /* Required by validation layers. */ + inst_.cryptomatte.bind_resources(&pass); + + pass.bind_image("aov_color_img", dummy_aov_color_tx_); + pass.bind_image("aov_value_img", dummy_aov_value_tx_); + pass.bind_ssbo("aov_buf", &inst_.film.aovs_info); + + pass.draw(DRW_cache_fullscreen_quad_get(), handle); +} + +void WorldPipeline::render(View &view) +{ + inst_.manager->submit(cubemap_face_ps_, view); +} + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Shadow Pipeline * @@ -371,6 +421,7 @@ void DeferredLayer::end_sync() inst_.shadows.bind_resources(&eval_light_ps_); inst_.sampling.bind_resources(&eval_light_ps_); inst_.hiz_buffer.bind_resources(&eval_light_ps_); + inst_.reflection_probes.bind_resources(&eval_light_ps_); inst_.irradiance_cache.bind_resources(&eval_light_ps_); eval_light_ps_.barrier(GPU_BARRIER_TEXTURE_FETCH | GPU_BARRIER_SHADER_IMAGE_ACCESS); diff --git a/source/blender/draw/engines/eevee_next/eevee_pipeline.hh b/source/blender/draw/engines/eevee_next/eevee_pipeline.hh index 13d126e0c94..f8f7b53cb15 100644 --- a/source/blender/draw/engines/eevee_next/eevee_pipeline.hh +++ b/source/blender/draw/engines/eevee_next/eevee_pipeline.hh @@ -43,6 +43,34 @@ class BackgroundPipeline { /** \} */ +/* -------------------------------------------------------------------- */ +/** \name World Probe Pipeline + * + * Renders a single side for the world reflection probe. + * \{ */ + +class WorldPipeline { + private: + Instance &inst_; + + /* Dummy textures: required to reuse background shader and avoid another shader variation. */ + Texture dummy_renderpass_tx_; + Texture dummy_cryptomatte_tx_; + Texture dummy_aov_color_tx_; + Texture dummy_aov_value_tx_; + + PassSimple cubemap_face_ps_ = {"World.Probe"}; + + public: + WorldPipeline(Instance &inst) : inst_(inst){}; + + void sync(GPUMaterial *gpumat); + void render(View &view); + +}; // namespace blender::eevee + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Shadow Pass * @@ -288,6 +316,7 @@ class UtilityTexture : public Texture { class PipelineModule { public: BackgroundPipeline background; + WorldPipeline world; DeferredPipeline deferred; ForwardPipeline forward; ShadowPipeline shadow; @@ -297,7 +326,12 @@ class PipelineModule { public: PipelineModule(Instance &inst) - : background(inst), deferred(inst), forward(inst), shadow(inst), capture(inst){}; + : background(inst), + world(inst), + deferred(inst), + forward(inst), + shadow(inst), + capture(inst){}; void begin_sync() { diff --git a/source/blender/draw/engines/eevee_next/eevee_reflection_probes.cc b/source/blender/draw/engines/eevee_next/eevee_reflection_probes.cc new file mode 100644 index 00000000000..56fabb4fb05 --- /dev/null +++ b/source/blender/draw/engines/eevee_next/eevee_reflection_probes.cc @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2023 Blender Foundation. */ + +#include "eevee_reflection_probes.hh" +#include "eevee_instance.hh" + +namespace blender::eevee { + +void ReflectionProbeModule::init() +{ + if (!initialized_) { + cubemaps_tx_.ensure_cube_array(GPU_RGBA16F, + max_resolution_, + max_probes_, + GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_ATTACHMENT, + NULL, + max_mipmap_levels_); + GPU_texture_mipmap_mode(cubemaps_tx_, true, true); + initialized_ = true; + } +} + +} // namespace blender::eevee diff --git a/source/blender/draw/engines/eevee_next/eevee_reflection_probes.hh b/source/blender/draw/engines/eevee_next/eevee_reflection_probes.hh new file mode 100644 index 00000000000..2f24bb777b0 --- /dev/null +++ b/source/blender/draw/engines/eevee_next/eevee_reflection_probes.hh @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2023 Blender Foundation. */ + +/** \file + * \ingroup eevee + */ + +#pragma once + +#include "eevee_shader_shared.hh" + +#include "BKE_cryptomatte.hh" + +extern "C" { +struct Material; +} + +namespace blender::eevee { + +class Instance; +class CaptureView; + +/* -------------------------------------------------------------------- */ +/** \name Reflection Probes + * \{ */ + +class ReflectionProbeModule { + private: + /** The max number of probes to track. */ + static constexpr int max_probes_ = 1; + + /** + * The maximum resolution of a cubemap side. + * + * Must be a power of two; intension to be used as a cubemap atlas. + */ + static constexpr int max_resolution_ = 2048; + static constexpr int max_mipmap_levels_ = log(max_resolution_) + 1; + + Instance &instance_; + + Texture cubemaps_tx_ = {"Probes"}; + + bool initialized_ = false; + + bool do_world_update_ = false; + + public: + ReflectionProbeModule(Instance &instance) : instance_(instance) {} + + void init(); + + template void bind_resources(draw::detail::PassBase *pass) + { + pass->bind_texture(REFLECTION_PROBE_TEX_SLOT, cubemaps_tx_); + } + + void do_world_update_set(bool value) + { + do_world_update_ = value; + } + + private: + bool do_world_update_get() const + { + return do_world_update_; + } + + /* Capture View requires access to the cubemaps texture for framebuffer configuration. */ + friend class CaptureView; +}; + +} // namespace blender::eevee diff --git a/source/blender/draw/engines/eevee_next/eevee_view.cc b/source/blender/draw/engines/eevee_next/eevee_view.cc index a3ad7584477..e3b6cd39c2d 100644 --- a/source/blender/draw/engines/eevee_next/eevee_view.cc +++ b/source/blender/draw/engines/eevee_next/eevee_view.cc @@ -125,8 +125,6 @@ void ShadingView::render() inst_.pipelines.deferred.render(render_view_new_, prepass_fb_, combined_fb_, extent_); - // inst_.lightprobes.draw_cache_display(); - // inst_.lookdev.render_overlay(view_fb_); inst_.pipelines.forward.render(render_view_new_, prepass_fb_, combined_fb_, rbufs.combined_tx); @@ -191,4 +189,35 @@ void ShadingView::update_view() /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Capture View + * \{ */ + +void CaptureView::render() +{ + if (!inst_.reflection_probes.do_world_update_get()) { + return; + } + inst_.reflection_probes.do_world_update_set(false); + + GPU_debug_group_begin("World.Capture"); + View view = {"World.Capture.View"}; + + for (int face : IndexRange(6)) { + capture_fb_.ensure( + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE_CUBEFACE(inst_.reflection_probes.cubemaps_tx_, face)); + GPU_framebuffer_bind(capture_fb_); + + float4x4 view_m4 = cubeface_mat(face); + float4x4 win_m4 = math::projection::perspective(-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 10.0f); + view.sync(view_m4, win_m4); + inst_.pipelines.world.render(view); + } + GPU_texture_update_mipmap_chain(inst_.reflection_probes.cubemaps_tx_); + GPU_debug_group_end(); +} + +/** \} */ + } // namespace blender::eevee diff --git a/source/blender/draw/engines/eevee_next/eevee_view.hh b/source/blender/draw/engines/eevee_next/eevee_view.hh index 9d312f49b4b..c115dbce871 100644 --- a/source/blender/draw/engines/eevee_next/eevee_view.hh +++ b/source/blender/draw/engines/eevee_next/eevee_view.hh @@ -142,4 +142,22 @@ class MainView { /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Capture View + * + * View for capturing cubemap renders outside a ShadingView. + * \{ */ + +class CaptureView { + private: + Instance &inst_; + Framebuffer capture_fb_ = {"World.Capture"}; + + public: + CaptureView(Instance &inst) : inst_(inst) {} + void render(); +}; + +/** \} */ + } // namespace blender::eevee diff --git a/source/blender/draw/engines/eevee_next/eevee_world.cc b/source/blender/draw/engines/eevee_next/eevee_world.cc index 58323ed0a84..908b6491210 100644 --- a/source/blender/draw/engines/eevee_next/eevee_world.cc +++ b/source/blender/draw/engines/eevee_next/eevee_world.cc @@ -90,7 +90,7 @@ void World::sync() WorldHandle &wo_handle = inst_.sync.sync_world(bl_world); if (wo_handle.recalc != 0) { - // inst_.lightprobes.set_world_dirty(); + inst_.reflection_probes.do_world_update_set(true); } wo_handle.reset_recalc_flag(); @@ -109,6 +109,7 @@ void World::sync() inst_.manager->register_layer_attributes(gpumat); inst_.pipelines.background.sync(gpumat); + inst_.pipelines.world.sync(gpumat); } /** \} */ diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_deferred_light_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_deferred_light_frag.glsl index 9781486fe2d..e8a760f5b33 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_deferred_light_frag.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_deferred_light_frag.glsl @@ -9,6 +9,7 @@ #pragma BLENDER_REQUIRE(eevee_gbuffer_lib.glsl) #pragma BLENDER_REQUIRE(common_view_lib.glsl) #pragma BLENDER_REQUIRE(eevee_light_eval_lib.glsl) +#pragma BLENDER_REQUIRE(eevee_reflection_probe_lib.glsl) #pragma BLENDER_REQUIRE(eevee_lightprobe_eval_lib.glsl) void main() @@ -54,6 +55,7 @@ void main() vec3 reflection_light = vec3(0.0); float shadow = 1.0; + light_world_eval(reflection_data, P, V, reflection_light); lightprobe_eval(diffuse_data, reflection_data, P, Ng, V, diffuse_light, reflection_light); light_eval(diffuse_data, diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_reflection_probe_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_reflection_probe_lib.glsl new file mode 100644 index 00000000000..b795da48798 --- /dev/null +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_reflection_probe_lib.glsl @@ -0,0 +1,61 @@ +#pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl) + +void light_world_eval(ClosureReflection reflection, vec3 P, vec3 V, inout vec3 out_specular) +{ + ivec3 texture_size = textureSize(reflectionProbes, 0); + /* TODO: This should be based by actual resolution. Currently the resolution is fixed but + * eventually this should based on a user setting and part of the reflection probe data that will + * be introduced by the reflection probe patch. */ + float lod_cube_max = 12.0; + + /* Pow2f to distributed across lod more evenly */ + float roughness = clamp(pow2f(reflection.roughness), 1e-4f, 0.9999f); + +#if defined(GPU_COMPUTE_SHADER) + vec2 frag_coord = vec2(gl_GlobalInvocationID.xy) + 0.5; +#else + vec2 frag_coord = gl_FragCoord.xy; +#endif + vec2 noise = utility_tx_fetch(utility_tx, frag_coord, UTIL_BLUE_NOISE_LAYER).gb; + vec2 rand = fract(noise + sampling_rng_2D_get(SAMPLING_RAYTRACE_U)); + + vec3 Xi = sample_cylinder(rand); + + /* Microfacet normal */ + vec3 T, B; + make_orthonormal_basis(reflection.N, T, B); + float pdf; + vec3 H = sample_ggx(Xi, roughness, V, reflection.N, T, B, pdf); + + vec3 L = -reflect(V, H); + float NL = dot(reflection.N, L); + + if (NL > 0.0) { + /* Coarse Approximation of the mapping distortion + * Unit Sphere -> Cubemap Face */ + const float dist = 4.0 * M_PI / 6.0; + + /* http://http.developer.nvidia.com/GPUGems3/gpugems3_ch20.html : Equation 13 */ + /* TODO: lod_factor should be precalculated and stored inside the reflection probe data. */ + const float bias = 0; + const float lod_factor = bias + 0.5 * log(float(square_i(texture_size.x))) / log(2); + /* -2: Don't use LOD levels that are smaller than 4x4 pixels. */ + float lod = clamp(lod_factor - 0.5 * log2(pdf * dist), 0.0, lod_cube_max - 2.0); + + vec3 l_col = textureLod_cubemapArray(reflectionProbes, vec4(L, 0.0), lod).rgb; + + /* Clamped brightness. */ + /* For artistic freedom this should be read from the scene/reflection probe. + * Note: Eevee-legacy read the firefly_factor from gi_glossy_clamp. + * Note: Firefly removal should be moved to a different shader and also take SSR into + * account.*/ + float luma = max(1e-8, max_v3(l_col)); + const float firefly_factor = 1e16; + l_col *= 1.0 - max(0.0, luma - firefly_factor) / luma; + + /* TODO: for artistic freedom want to read this from the reflection probe. That will be part of + * the reflection probe patch. */ + const float intensity_factor = 1.0; + out_specular += vec3(intensity_factor * l_col); + } +} diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_sampling_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_sampling_lib.glsl index a54133167ac..e235b795277 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_sampling_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_sampling_lib.glsl @@ -5,6 +5,7 @@ **/ #pragma BLENDER_REQUIRE(common_math_lib.glsl) +#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) /* -------------------------------------------------------------------- */ /** \name Sampling data. @@ -102,3 +103,86 @@ vec3 sample_cylinder(vec2 rand) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Microfacet GGX distribution + * \{ */ + +#define USE_VISIBLE_NORMAL 1 + +float D_ggx_opti(float NH, float a2) +{ + float tmp = (NH * a2 - NH) * NH + 1.0; + return M_PI * tmp * tmp; /* Doing RCP and mul a2 at the end */ +} + +float G1_Smith_GGX_opti(float NX, float a2) +{ + /* Using Brian Karis approach and refactoring by NX/NX + * this way the (2*NL)*(2*NV) in G = G1(V) * G1(L) gets canceled by the brdf denominator 4*NL*NV + * Rcp is done on the whole G later + * Note that this is not convenient for the transmission formula */ + return NX + sqrt(NX * (NX - NX * a2) + a2); + /* return 2 / (1 + sqrt(1 + a2 * (1 - NX*NX) / (NX*NX) ) ); /* Reference function */ +} + +float pdf_ggx_reflect(float NH, float NV, float VH, float alpha) +{ + float a2 = sqr(alpha); +#if USE_VISIBLE_NORMAL + float D = a2 / D_ggx_opti(NH, a2); + float G1 = NV * 2.0 / G1_Smith_GGX_opti(NV, a2); + return G1 * VH * D / NV; +#else + return NH * a2 / D_ggx_opti(NH, a2); +#endif +} + +vec3 sample_ggx(vec3 rand, float alpha, vec3 Vt) +{ +#if USE_VISIBLE_NORMAL + /* From: + * "A Simpler and Exact Sampling Routine for the GGXDistribution of Visible Normals" + * by Eric Heitz. + * http://jcgt.org/published/0007/04/01/slides.pdf + * View vector is expected to be in tangent space. */ + + /* Stretch view. */ + vec3 Th, Bh, Vh = normalize(vec3(alpha * Vt.xy, Vt.z)); + make_orthonormal_basis(Vh, Th, Bh); + /* Sample point with polar coordinates (r, phi). */ + float r = sqrt(rand.x); + float x = r * rand.y; + float y = r * rand.z; + float s = 0.5 * (1.0 + Vh.z); + y = (1.0 - s) * sqrt(1.0 - x * x) + s * y; + float z = sqrt(saturate(1.0 - x * x - y * y)); + /* Compute normal. */ + vec3 Hh = x * Th + y * Bh + z * Vh; + /* Unstretch. */ + vec3 Ht = normalize(vec3(alpha * Hh.xy, saturate(Hh.z))); + /* Microfacet Normal. */ + return Ht; +#else + /* Theta is the cone angle. */ + float z = sqrt((1.0 - rand.x) / (1.0 + sqr(alpha) * rand.x - rand.x)); /* cos theta */ + float r = sqrt(max(0.0, 1.0 - z * z)); /* sin theta */ + float x = r * rand.y; + float y = r * rand.z; + /* Microfacet Normal */ + return vec3(x, y, z); +#endif +} + +vec3 sample_ggx(vec3 rand, float alpha, vec3 V, vec3 N, vec3 T, vec3 B, out float pdf) +{ + vec3 Vt = world_to_tangent(V, N, T, B); + vec3 Ht = sample_ggx(rand, alpha, Vt); + float NH = saturate(Ht.z); + float NV = saturate(Vt.z); + float VH = saturate(dot(Vt, Ht)); + pdf = pdf_ggx_reflect(NH, NV, VH, alpha); + return tangent_to_world(Ht, N, T, B); +} + +/** \} */ diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh index aeae90b61c6..660a5970f46 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh @@ -36,7 +36,9 @@ GPU_SHADER_CREATE_INFO(eevee_deferred_light) .sampler(1, ImageType::FLOAT_2D_ARRAY, "gbuffer_color_tx") .additional_info("eevee_shared", "eevee_utility_texture", + "eevee_sampling_data", "eevee_light_data", + "eevee_reflection_probe_data", "eevee_lightprobe_data", "eevee_shadow_data", "eevee_deferred_base", diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_reflection_probe_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_reflection_probe_info.hh new file mode 100644 index 00000000000..9eac2f05e89 --- /dev/null +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_reflection_probe_info.hh @@ -0,0 +1,11 @@ +#include "eevee_defines.hh" +#include "gpu_shader_create_info.hh" + +/* -------------------------------------------------------------------- */ +/** \name Shared + * \{ */ + +GPU_SHADER_CREATE_INFO(eevee_reflection_probe_data) + .sampler(REFLECTION_PROBE_TEX_SLOT, ImageType::FLOAT_CUBE_ARRAY, "reflectionProbes"); + +/** \} */ diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index b710e9e6605..8dffeed99cd 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -651,6 +651,7 @@ set(SRC_SHADER_CREATE_INFOS ../draw/engines/eevee_next/shaders/infos/eevee_light_culling_info.hh ../draw/engines/eevee_next/shaders/infos/eevee_material_info.hh ../draw/engines/eevee_next/shaders/infos/eevee_motion_blur_info.hh + ../draw/engines/eevee_next/shaders/infos/eevee_reflection_probe_info.hh ../draw/engines/eevee_next/shaders/infos/eevee_shadow_info.hh ../draw/engines/eevee_next/shaders/infos/eevee_subsurface_info.hh ../draw/engines/eevee_next/shaders/infos/eevee_velocity_info.hh