2023-08-24 10:54:59 +10:00
|
|
|
/* SPDX-FileCopyrightText: 2022-2023 Blender Authors
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2022-05-02 09:22:14 +02:00
|
|
|
|
2024-10-04 15:48:22 +02:00
|
|
|
#pragma once
|
|
|
|
|
|
2025-09-25 10:57:02 +02:00
|
|
|
#include "infos/eevee_material_infos.hh"
|
2024-12-02 21:26:15 +01:00
|
|
|
|
|
|
|
|
SHADER_LIBRARY_CREATE_INFO(eevee_geom_mesh)
|
2025-09-23 17:21:56 +02:00
|
|
|
SHADER_LIBRARY_CREATE_INFO(eevee_global_ubo)
|
2024-12-02 21:26:15 +01:00
|
|
|
|
2025-09-23 17:21:56 +02:00
|
|
|
#include "draw_view_lib.glsl"
|
2024-10-04 15:48:22 +02:00
|
|
|
#include "gpu_shader_codegen_lib.glsl"
|
|
|
|
|
#include "gpu_shader_math_base_lib.glsl"
|
2025-09-15 12:07:26 +02:00
|
|
|
#include "gpu_shader_math_vector_safe_lib.glsl"
|
2022-05-02 09:22:14 +02:00
|
|
|
|
|
|
|
|
#if defined(USE_BARYCENTRICS) && defined(GPU_FRAGMENT_SHADER) && defined(MAT_GEOM_MESH)
|
2025-04-14 13:46:41 +02:00
|
|
|
float3 barycentric_distances_get()
|
2022-05-02 09:22:14 +02:00
|
|
|
{
|
2025-05-05 09:59:00 +02:00
|
|
|
float wp_delta = length(gpu_dfdx(interp.P)) + length(gpu_dfdy(interp.P));
|
|
|
|
|
float bc_delta = length(gpu_dfdx(gpu_BaryCoord)) + length(gpu_dfdy(gpu_BaryCoord));
|
2023-10-13 18:00:46 +02:00
|
|
|
float rate_of_change = wp_delta / bc_delta;
|
2025-04-11 18:28:45 +02:00
|
|
|
return rate_of_change * (1.0f - gpu_BaryCoord);
|
2022-05-02 09:22:14 +02:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2022-05-05 11:55:13 +02:00
|
|
|
void init_globals_mesh()
|
2022-05-02 09:22:14 +02:00
|
|
|
{
|
|
|
|
|
#if defined(USE_BARYCENTRICS) && defined(GPU_FRAGMENT_SHADER) && defined(MAT_GEOM_MESH)
|
|
|
|
|
g_data.barycentric_coords = gpu_BaryCoord.xy;
|
|
|
|
|
g_data.barycentric_dists = barycentric_distances_get();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-05 11:55:13 +02:00
|
|
|
void init_globals_curves()
|
2022-05-02 09:22:14 +02:00
|
|
|
{
|
2023-10-03 15:56:41 +02:00
|
|
|
#if defined(MAT_GEOM_CURVES)
|
2022-05-02 09:22:14 +02:00
|
|
|
/* Shade as a cylinder. */
|
2025-08-27 09:49:43 +02:00
|
|
|
float cos_theta = curve_interp.time_width / curve_interp.radius;
|
|
|
|
|
float sin_theta = sin_from_cos(cos_theta);
|
2023-10-03 15:56:41 +02:00
|
|
|
g_data.N = g_data.Ni = normalize(interp.N * sin_theta + curve_interp.binormal * cos_theta);
|
2022-05-02 09:22:14 +02:00
|
|
|
|
2022-05-09 19:20:39 +02:00
|
|
|
/* Costly, but follows cycles per pixel tangent space (not following curve shape). */
|
2025-04-14 13:46:41 +02:00
|
|
|
float3 V = drw_world_incident_vector(g_data.P);
|
2023-10-03 15:56:41 +02:00
|
|
|
g_data.curve_T = -curve_interp.tangent;
|
2022-05-09 19:20:39 +02:00
|
|
|
g_data.curve_B = cross(V, g_data.curve_T);
|
|
|
|
|
g_data.curve_N = safe_normalize(cross(g_data.curve_T, g_data.curve_B));
|
|
|
|
|
|
2022-05-02 09:22:14 +02:00
|
|
|
g_data.is_strand = true;
|
2025-08-27 09:49:43 +02:00
|
|
|
g_data.hair_diameter = curve_interp.radius * 2.0;
|
2023-10-03 15:56:41 +02:00
|
|
|
g_data.hair_strand_id = curve_interp_flat.strand_id;
|
|
|
|
|
# if defined(USE_BARYCENTRICS) && defined(GPU_FRAGMENT_SHADER)
|
2025-08-27 09:49:43 +02:00
|
|
|
g_data.barycentric_coords.y = fract(curve_interp.point_id);
|
|
|
|
|
g_data.barycentric_coords.x = 1.0 - g_data.barycentric_coords.y;
|
2023-10-03 15:56:41 +02:00
|
|
|
# endif
|
2022-05-02 09:22:14 +02:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-05 11:55:13 +02:00
|
|
|
void init_globals()
|
2022-05-02 09:22:14 +02:00
|
|
|
{
|
|
|
|
|
/* Default values. */
|
|
|
|
|
g_data.P = interp.P;
|
2022-09-02 18:13:54 +02:00
|
|
|
g_data.Ni = interp.N;
|
2022-05-02 09:22:14 +02:00
|
|
|
g_data.N = safe_normalize(interp.N);
|
|
|
|
|
g_data.Ng = g_data.N;
|
|
|
|
|
g_data.is_strand = false;
|
2025-08-27 09:49:43 +02:00
|
|
|
g_data.hair_diameter = 0.0f;
|
2022-05-02 09:22:14 +02:00
|
|
|
g_data.hair_strand_id = 0;
|
2023-12-12 21:27:18 +01:00
|
|
|
#if defined(MAT_SHADOW)
|
|
|
|
|
g_data.ray_type = RAY_TYPE_SHADOW;
|
|
|
|
|
#elif defined(MAT_CAPTURE)
|
|
|
|
|
g_data.ray_type = RAY_TYPE_DIFFUSE;
|
|
|
|
|
#else
|
2024-05-30 00:15:43 +02:00
|
|
|
if (uniform_buf.pipeline.is_sphere_probe) {
|
2023-12-12 21:27:18 +01:00
|
|
|
g_data.ray_type = RAY_TYPE_GLOSSY;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
g_data.ray_type = RAY_TYPE_CAMERA;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2025-04-11 18:28:45 +02:00
|
|
|
g_data.ray_depth = 0.0f;
|
2023-10-13 17:59:46 +02:00
|
|
|
g_data.ray_length = distance(g_data.P, drw_view_position());
|
2025-04-14 13:46:41 +02:00
|
|
|
g_data.barycentric_coords = float2(0.0f);
|
|
|
|
|
g_data.barycentric_dists = float3(0.0f);
|
2022-05-02 09:22:14 +02:00
|
|
|
|
|
|
|
|
#ifdef GPU_FRAGMENT_SHADER
|
2025-09-23 17:21:56 +02:00
|
|
|
g_data.N = (gl_FrontFacing) ? g_data.N : -g_data.N;
|
|
|
|
|
g_data.Ni = (gl_FrontFacing) ? g_data.Ni : -g_data.Ni;
|
2025-05-05 09:59:00 +02:00
|
|
|
g_data.Ng = safe_normalize(cross(gpu_dfdx(g_data.P), gpu_dfdy(g_data.P)));
|
2022-05-02 09:22:14 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(MAT_GEOM_MESH)
|
|
|
|
|
init_globals_mesh();
|
|
|
|
|
#elif defined(MAT_GEOM_CURVES)
|
|
|
|
|
init_globals_curves();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Avoid some compiler issue with non set interface parameters. */
|
|
|
|
|
void init_interface()
|
|
|
|
|
{
|
|
|
|
|
#ifdef GPU_VERTEX_SHADER
|
2025-04-14 13:46:41 +02:00
|
|
|
interp.P = float3(0.0f);
|
|
|
|
|
interp.N = float3(0.0f);
|
2025-08-11 12:05:18 +02:00
|
|
|
drw_ResourceID_iface.resource_index = drw_resource_id_raw();
|
2022-05-02 09:22:14 +02:00
|
|
|
#endif
|
|
|
|
|
}
|
2023-08-17 17:35:19 +02:00
|
|
|
|
2023-09-04 19:40:23 +02:00
|
|
|
#if defined(GPU_VERTEX_SHADER) && defined(MAT_SHADOW)
|
2023-08-17 17:35:19 +02:00
|
|
|
void shadow_viewport_layer_set(int view_id, int lod)
|
|
|
|
|
{
|
2023-12-24 12:19:18 +01:00
|
|
|
# ifdef SHADOW_UPDATE_ATOMIC_RASTER
|
|
|
|
|
shadow_iface.shadow_view_id = view_id;
|
|
|
|
|
# else
|
2023-08-29 15:09:33 +10:00
|
|
|
/* We still render to a layered frame-buffer in the case of Metal + Tile Based Renderer.
|
2023-08-17 17:35:19 +02:00
|
|
|
* Since it needs correct depth buffering, each view needs to not overlap each others.
|
|
|
|
|
* It doesn't matter much for other platform, so we use that as a way to pass the view id. */
|
|
|
|
|
gpu_Layer = view_id;
|
2023-12-24 12:19:18 +01:00
|
|
|
# endif
|
2023-08-17 17:35:19 +02:00
|
|
|
gpu_ViewportIndex = lod;
|
|
|
|
|
}
|
2024-04-24 17:08:12 +02:00
|
|
|
|
2025-04-14 13:46:41 +02:00
|
|
|
float3 shadow_position_vector_get(float3 view_position, ShadowRenderView view)
|
2024-05-07 14:52:47 +02:00
|
|
|
{
|
2024-05-08 20:57:05 +10:00
|
|
|
if (view.is_directional) {
|
2025-04-14 13:46:41 +02:00
|
|
|
return float3(0.0f, 0.0f, -view_position.z - view.clip_near);
|
2024-05-07 14:52:47 +02:00
|
|
|
}
|
|
|
|
|
return view_position;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-24 17:08:12 +02:00
|
|
|
/* In order to support physical clipping, we pass a vector to the fragment shader that then clips
|
|
|
|
|
* each fragment using a unit sphere test. This allows to support both point light and area light
|
|
|
|
|
* clipping at the same time. */
|
2025-04-14 13:46:41 +02:00
|
|
|
float3 shadow_clip_vector_get(float3 view_position, float clip_distance_inv)
|
2024-04-24 17:08:12 +02:00
|
|
|
{
|
2025-04-11 18:28:45 +02:00
|
|
|
if (clip_distance_inv == 0.0f) {
|
2024-04-24 17:08:12 +02:00
|
|
|
/* No clipping. */
|
2025-04-14 13:46:41 +02:00
|
|
|
return float3(2.0f);
|
2024-04-24 17:08:12 +02:00
|
|
|
}
|
2024-05-23 15:35:16 +02:00
|
|
|
/* Punctual shadow case. */
|
2024-04-24 17:08:12 +02:00
|
|
|
return view_position * clip_distance_inv;
|
|
|
|
|
}
|
2023-08-17 17:35:19 +02:00
|
|
|
#endif
|
|
|
|
|
|
2023-09-04 19:40:23 +02:00
|
|
|
#if defined(GPU_FRAGMENT_SHADER) && defined(MAT_SHADOW)
|
2023-08-17 17:35:19 +02:00
|
|
|
int shadow_view_id_get()
|
|
|
|
|
{
|
2023-12-24 12:19:18 +01:00
|
|
|
# ifdef SHADOW_UPDATE_ATOMIC_RASTER
|
|
|
|
|
return shadow_iface.shadow_view_id;
|
|
|
|
|
# else
|
2023-08-17 17:35:19 +02:00
|
|
|
return gpu_Layer;
|
2023-12-24 12:19:18 +01:00
|
|
|
# endif
|
2023-08-17 17:35:19 +02:00
|
|
|
}
|
|
|
|
|
#endif
|