This is the first step of moving the create infos back inside shader sources. All info files are now treated as source files. However, they are not considered in the include tree yet. This will come in another following PR. Each shader source file now generate a `.info` file containing only the create info declarations. This renames all info files so that they do not conflict with their previous versions that were copied (non-generated). Pull Request: https://projects.blender.org/blender/blender/pulls/146676
155 lines
4.6 KiB
GLSL
155 lines
4.6 KiB
GLSL
/* SPDX-FileCopyrightText: 2022-2023 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#pragma once
|
|
|
|
#include "infos/eevee_material_infos.hh"
|
|
|
|
SHADER_LIBRARY_CREATE_INFO(eevee_geom_mesh)
|
|
SHADER_LIBRARY_CREATE_INFO(eevee_global_ubo)
|
|
|
|
#include "draw_view_lib.glsl"
|
|
#include "gpu_shader_codegen_lib.glsl"
|
|
#include "gpu_shader_math_base_lib.glsl"
|
|
#include "gpu_shader_math_vector_safe_lib.glsl"
|
|
|
|
#if defined(USE_BARYCENTRICS) && defined(GPU_FRAGMENT_SHADER) && defined(MAT_GEOM_MESH)
|
|
float3 barycentric_distances_get()
|
|
{
|
|
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));
|
|
float rate_of_change = wp_delta / bc_delta;
|
|
return rate_of_change * (1.0f - gpu_BaryCoord);
|
|
}
|
|
#endif
|
|
|
|
void init_globals_mesh()
|
|
{
|
|
#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
|
|
}
|
|
|
|
void init_globals_curves()
|
|
{
|
|
#if defined(MAT_GEOM_CURVES)
|
|
/* Shade as a cylinder. */
|
|
float cos_theta = curve_interp.time_width / curve_interp.radius;
|
|
float sin_theta = sin_from_cos(cos_theta);
|
|
g_data.N = g_data.Ni = normalize(interp.N * sin_theta + curve_interp.binormal * cos_theta);
|
|
|
|
/* Costly, but follows cycles per pixel tangent space (not following curve shape). */
|
|
float3 V = drw_world_incident_vector(g_data.P);
|
|
g_data.curve_T = -curve_interp.tangent;
|
|
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));
|
|
|
|
g_data.is_strand = true;
|
|
g_data.hair_diameter = curve_interp.radius * 2.0;
|
|
g_data.hair_strand_id = curve_interp_flat.strand_id;
|
|
# if defined(USE_BARYCENTRICS) && defined(GPU_FRAGMENT_SHADER)
|
|
g_data.barycentric_coords.y = fract(curve_interp.point_id);
|
|
g_data.barycentric_coords.x = 1.0 - g_data.barycentric_coords.y;
|
|
# endif
|
|
#endif
|
|
}
|
|
|
|
void init_globals()
|
|
{
|
|
/* Default values. */
|
|
g_data.P = interp.P;
|
|
g_data.Ni = interp.N;
|
|
g_data.N = safe_normalize(interp.N);
|
|
g_data.Ng = g_data.N;
|
|
g_data.is_strand = false;
|
|
g_data.hair_diameter = 0.0f;
|
|
g_data.hair_strand_id = 0;
|
|
#if defined(MAT_SHADOW)
|
|
g_data.ray_type = RAY_TYPE_SHADOW;
|
|
#elif defined(MAT_CAPTURE)
|
|
g_data.ray_type = RAY_TYPE_DIFFUSE;
|
|
#else
|
|
if (uniform_buf.pipeline.is_sphere_probe) {
|
|
g_data.ray_type = RAY_TYPE_GLOSSY;
|
|
}
|
|
else {
|
|
g_data.ray_type = RAY_TYPE_CAMERA;
|
|
}
|
|
#endif
|
|
g_data.ray_depth = 0.0f;
|
|
g_data.ray_length = distance(g_data.P, drw_view_position());
|
|
g_data.barycentric_coords = float2(0.0f);
|
|
g_data.barycentric_dists = float3(0.0f);
|
|
|
|
#ifdef GPU_FRAGMENT_SHADER
|
|
g_data.N = (gl_FrontFacing) ? g_data.N : -g_data.N;
|
|
g_data.Ni = (gl_FrontFacing) ? g_data.Ni : -g_data.Ni;
|
|
g_data.Ng = safe_normalize(cross(gpu_dfdx(g_data.P), gpu_dfdy(g_data.P)));
|
|
#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
|
|
interp.P = float3(0.0f);
|
|
interp.N = float3(0.0f);
|
|
drw_ResourceID_iface.resource_index = drw_resource_id_raw();
|
|
#endif
|
|
}
|
|
|
|
#if defined(GPU_VERTEX_SHADER) && defined(MAT_SHADOW)
|
|
void shadow_viewport_layer_set(int view_id, int lod)
|
|
{
|
|
# ifdef SHADOW_UPDATE_ATOMIC_RASTER
|
|
shadow_iface.shadow_view_id = view_id;
|
|
# else
|
|
/* We still render to a layered frame-buffer in the case of Metal + Tile Based Renderer.
|
|
* 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;
|
|
# endif
|
|
gpu_ViewportIndex = lod;
|
|
}
|
|
|
|
float3 shadow_position_vector_get(float3 view_position, ShadowRenderView view)
|
|
{
|
|
if (view.is_directional) {
|
|
return float3(0.0f, 0.0f, -view_position.z - view.clip_near);
|
|
}
|
|
return view_position;
|
|
}
|
|
|
|
/* 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. */
|
|
float3 shadow_clip_vector_get(float3 view_position, float clip_distance_inv)
|
|
{
|
|
if (clip_distance_inv == 0.0f) {
|
|
/* No clipping. */
|
|
return float3(2.0f);
|
|
}
|
|
/* Punctual shadow case. */
|
|
return view_position * clip_distance_inv;
|
|
}
|
|
#endif
|
|
|
|
#if defined(GPU_FRAGMENT_SHADER) && defined(MAT_SHADOW)
|
|
int shadow_view_id_get()
|
|
{
|
|
# ifdef SHADOW_UPDATE_ATOMIC_RASTER
|
|
return shadow_iface.shadow_view_id;
|
|
# else
|
|
return gpu_Layer;
|
|
# endif
|
|
}
|
|
#endif
|