UI: Window Title With Version #111998
|
@ -514,7 +514,7 @@ check_spelling_shaders: .FORCE
|
|||
PYTHONIOENCODING=utf_8 $(PYTHON) \
|
||||
"$(BLENDER_DIR)/tools/check_source/check_spelling.py" \
|
||||
--cache-file=$(CHECK_SPELLING_CACHE) \
|
||||
--match=".*\.(osl|msl|glsl)$$" \
|
||||
--match=".*\.(osl|metal|msl|glsl)$$" \
|
||||
"$(BLENDER_DIR)/intern/" \
|
||||
"$(BLENDER_DIR)/source/"
|
||||
|
||||
|
|
|
@ -12,6 +12,9 @@ if(DEFINED HIP_ROOT_DIR AND HIP_ROOT_DIR)
|
|||
# Pass.
|
||||
elseif(DEFINED ENV{HIP_ROOT_DIR})
|
||||
set(HIP_ROOT_DIR $ENV{HIP_ROOT_DIR})
|
||||
elseif(DEFINED ENV{HIP_PATH})
|
||||
# Built-in environment variable from SDK.
|
||||
set(HIP_ROOT_DIR $ENV{HIP_PATH})
|
||||
else()
|
||||
set(HIP_ROOT_DIR "")
|
||||
endif()
|
||||
|
|
|
@ -12,6 +12,9 @@ if(DEFINED HIPRT_ROOT_DIR AND HIPRT_ROOT_DIR)
|
|||
# Pass.
|
||||
elseif(DEFINED ENV{HIPRT_ROOT_DIR})
|
||||
set(HIPRT_ROOT_DIR $ENV{HIPRT_ROOT_DIR})
|
||||
elseif(DEFINED ENV{HIP_PATH})
|
||||
# Built-in environment variable from SDK.
|
||||
set(HIPRT_ROOT_DIR $ENV{HIP_PATH})
|
||||
else()
|
||||
set(HIPRT_ROOT_DIR "")
|
||||
endif()
|
||||
|
@ -24,6 +27,7 @@ find_path(HIPRT_INCLUDE_DIR
|
|||
NAMES
|
||||
hiprt/hiprt.h
|
||||
HINTS
|
||||
${_hiprt_SEARCH_DIRS}/include
|
||||
${_hiprt_SEARCH_DIRS}
|
||||
)
|
||||
|
||||
|
@ -36,6 +40,7 @@ if(HIPRT_INCLUDE_DIR)
|
|||
NAMES
|
||||
hiprt${_hiprt_version}_amd_lib_win.bc
|
||||
HINTS
|
||||
${HIPRT_ROOT_DIR}/bin
|
||||
${HIPRT_ROOT_DIR}/dist/bin/Release
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
|
|
@ -21,28 +21,28 @@ extern void *AUD_createSet(void);
|
|||
|
||||
/**
|
||||
* Deletes a set.
|
||||
* \param set The set to delete.
|
||||
* \param set: The set to delete.
|
||||
*/
|
||||
extern void AUD_destroySet(void *set);
|
||||
|
||||
/**
|
||||
* Removes an entry from a set.
|
||||
* \param set The set work on.
|
||||
* \param entry The entry to remove.
|
||||
* \param set: The set work on.
|
||||
* \param entry: The entry to remove.
|
||||
* \return Whether the entry was in the set or not.
|
||||
*/
|
||||
extern char AUD_removeSet(void *set, void *entry);
|
||||
|
||||
/**
|
||||
* Adds a new entry to a set.
|
||||
* \param set The set work on.
|
||||
* \param entry The entry to add.
|
||||
* \param set: The set work on.
|
||||
* \param entry: The entry to add.
|
||||
*/
|
||||
extern void AUD_addSet(void *set, void *entry);
|
||||
|
||||
/**
|
||||
* Removes one entry from a set and returns it.
|
||||
* \param set The set work on.
|
||||
* \param set: The set work on.
|
||||
* \return The entry or NULL if the set is empty.
|
||||
*/
|
||||
extern void *AUD_getSet(void *set);
|
||||
|
|
|
@ -55,6 +55,9 @@ bool device_oneapi_init()
|
|||
if (getenv("SYCL_PI_LEVEL_ZERO_USE_COPY_ENGINE_FOR_IN_ORDER_QUEUE") == nullptr) {
|
||||
_putenv_s("SYCL_PI_LEVEL_ZERO_USE_COPY_ENGINE_FOR_IN_ORDER_QUEUE", "0");
|
||||
}
|
||||
if (getenv("SYCL_PI_LEVEL_ZERO_USE_COPY_ENGINE") == nullptr) {
|
||||
_putenv_s("SYCL_PI_LEVEL_ZERO_USE_COPY_ENGINE", "0");
|
||||
}
|
||||
# elif __linux__
|
||||
setenv("SYCL_CACHE_PERSISTENT", "1", false);
|
||||
setenv("SYCL_CACHE_THRESHOLD", "0", false);
|
||||
|
@ -66,6 +69,7 @@ bool device_oneapi_init()
|
|||
}
|
||||
setenv("SYCL_ENABLE_PCI", "1", false);
|
||||
setenv("SYCL_PI_LEVEL_ZERO_USE_COPY_ENGINE_FOR_IN_ORDER_QUEUE", "0", false);
|
||||
setenv("SYCL_PI_LEVEL_ZERO_USE_COPY_ENGINE", "0", false);
|
||||
# endif
|
||||
|
||||
return true;
|
||||
|
|
|
@ -1000,6 +1000,7 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
|
|||
-L"${WINDOWS_KIT_DIR}/ucrt/x64")
|
||||
else() # Add Linux specific compiler flags.
|
||||
list(APPEND sycl_compiler_flags -fPIC)
|
||||
list(APPEND sycl_compiler_flags -fvisibility=hidden)
|
||||
|
||||
# We avoid getting __FAST_MATH__ to be defined when building on CentOS-7 and Rocky-8
|
||||
# until the compilation issues it triggers at either AoT or JIT stages gets fixed.
|
||||
|
|
|
@ -459,6 +459,7 @@ ccl_device_inline
|
|||
{
|
||||
Spectrum eval = zero_spectrum();
|
||||
*pdf = 0.f;
|
||||
const float3 Ng = (sd->type & PRIMITIVE_CURVE) ? sc->N : sd->Ng;
|
||||
|
||||
switch (sc->type) {
|
||||
case CLOSURE_BSDF_DIFFUSE_ID:
|
||||
|
@ -486,15 +487,15 @@ ccl_device_inline
|
|||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID:
|
||||
eval = bsdf_microfacet_ggx_eval(sc, sd->N, sd->wi, wo, pdf);
|
||||
eval = bsdf_microfacet_ggx_eval(sc, Ng, sd->wi, wo, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID:
|
||||
eval = bsdf_microfacet_beckmann_eval(sc, sd->N, sd->wi, wo, pdf);
|
||||
eval = bsdf_microfacet_beckmann_eval(sc, Ng, sd->wi, wo, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
|
||||
eval = bsdf_ashikhmin_shirley_eval(sc, sd->N, sd->wi, wo, pdf);
|
||||
eval = bsdf_ashikhmin_shirley_eval(sc, Ng, sd->wi, wo, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
|
||||
eval = bsdf_ashikhmin_velvet_eval(sc, sd->wi, wo, pdf);
|
||||
|
|
|
@ -207,7 +207,7 @@ ccl_device int bsdf_ashikhmin_shirley_sample(ccl_private const ShaderClosure *sc
|
|||
}
|
||||
else {
|
||||
/* leave the rest to eval */
|
||||
*eval = bsdf_ashikhmin_shirley_eval(sc, N, wi, *wo, pdf);
|
||||
*eval = bsdf_ashikhmin_shirley_eval(sc, Ng, wi, *wo, pdf);
|
||||
}
|
||||
|
||||
return label;
|
||||
|
|
|
@ -329,7 +329,11 @@ ccl_device_inline void microfacet_ggx_preserve_energy(KernelGlobals kg,
|
|||
* code for that), but e.g. a reflection-only closure with Fresnel applied can end up having
|
||||
* a very low overall albedo.
|
||||
* This is used to adjust the sample weight, as well as for the Diff/Gloss/Trans Color pass
|
||||
* and the Denoising Albedo pass. */
|
||||
* and the Denoising Albedo pass.
|
||||
* Use lookup tables for generalized Schlick. Otherwise assuming that the surface is smooth. */
|
||||
/* TODO: The Schlick LUT seems to assume energy preservation, which is not true for GGX. if
|
||||
* energy-preserving then transmission should just be `1 - reflection`. For dielectric we could
|
||||
* probably split the LUT for multiGGX if smooth assumption is not good enough. */
|
||||
ccl_device Spectrum bsdf_microfacet_estimate_albedo(KernelGlobals kg,
|
||||
ccl_private const ShaderData *sd,
|
||||
ccl_private const MicrofacetBsdf *bsdf,
|
||||
|
@ -362,8 +366,6 @@ ccl_device Spectrum bsdf_microfacet_estimate_albedo(KernelGlobals kg,
|
|||
albedo += mix(fresnel->f0, fresnel->f90, s) * fresnel->reflection_tint;
|
||||
}
|
||||
else {
|
||||
/* If we don't (yet) have a way to estimate albedo in a way that accounts for roughness,
|
||||
* fall back to assuming that the surface is smooth. */
|
||||
albedo += microfacet_fresnel(bsdf, sd->wi, bsdf->N, false);
|
||||
}
|
||||
}
|
||||
|
@ -513,6 +515,9 @@ ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc,
|
|||
}
|
||||
|
||||
/* Compute half vector. */
|
||||
/* TODO: deal with the case when `bsdf->ior` is close to one. */
|
||||
/* TODO: check if the refraction configuration is valid. See `btdf_ggx()` in
|
||||
* `eevee_bxdf_lib.glsl`. */
|
||||
float3 H = is_transmission ? -(bsdf->ior * wo + wi) : (wi + wo);
|
||||
const float inv_len_H = 1.0f / len(H);
|
||||
H *= inv_len_H;
|
||||
|
@ -520,7 +525,8 @@ ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc,
|
|||
const float cos_NH = dot(N, H);
|
||||
float D, lambdaI, lambdaO;
|
||||
|
||||
/* TODO: add support for anisotropic transmission. */
|
||||
/* NOTE: we could add support for anisotropic transmission, although it will make dispersion
|
||||
* harder to compute. */
|
||||
if (alpha_x == alpha_y || is_transmission) { /* Isotropic. */
|
||||
float alpha2 = alpha_x * alpha_y;
|
||||
|
||||
|
@ -559,8 +565,7 @@ ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc,
|
|||
float lobe_pdf = 1.0f;
|
||||
if (m_glass) {
|
||||
float fresnel = fresnel_dielectric_cos(dot(H, wi), bsdf->ior);
|
||||
float reflect_pdf = (fresnel == 1.0f) ? 1.0f : clamp(fresnel, 0.125f, 0.875f);
|
||||
lobe_pdf = is_transmission ? (1.0f - reflect_pdf) : reflect_pdf;
|
||||
lobe_pdf = is_transmission ? (1.0f - fresnel) : fresnel;
|
||||
}
|
||||
|
||||
*pdf = common * lobe_pdf / (1.0f + lambdaI);
|
||||
|
@ -583,32 +588,29 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc,
|
|||
{
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
|
||||
const float3 N = bsdf->N;
|
||||
const float cos_NI = dot(N, wi);
|
||||
if (cos_NI <= 0) {
|
||||
/* Incident angle from the lower hemisphere is invalid. */
|
||||
return LABEL_NONE;
|
||||
}
|
||||
|
||||
const float m_eta = bsdf->ior;
|
||||
const float m_inv_eta = 1.0f / bsdf->ior;
|
||||
const bool m_refraction = CLOSURE_IS_REFRACTION(bsdf->type);
|
||||
const bool m_glass = CLOSURE_IS_GLASS(bsdf->type);
|
||||
const bool m_reflection = !(m_refraction || m_glass);
|
||||
const float alpha_x = bsdf->alpha_x;
|
||||
const float alpha_y = bsdf->alpha_y;
|
||||
bool m_singular = !bsdf_microfacet_eval_flag(bsdf);
|
||||
|
||||
const float3 N = bsdf->N;
|
||||
const float cos_NI = dot(N, wi);
|
||||
if (cos_NI <= 0) {
|
||||
*eval = zero_spectrum();
|
||||
*pdf = 0.0f;
|
||||
return (m_reflection ? LABEL_REFLECT : LABEL_TRANSMIT) |
|
||||
(m_singular ? LABEL_SINGULAR : LABEL_GLOSSY);
|
||||
}
|
||||
|
||||
float3 H;
|
||||
float cos_NH, cos_HI;
|
||||
float3 local_H, local_I, X, Y; /* Needed for anisotropic microfacets later. */
|
||||
/* Needed for anisotropic microfacets later. */
|
||||
float3 local_H, local_I;
|
||||
if (m_singular) {
|
||||
H = N;
|
||||
cos_NH = 1.0f;
|
||||
cos_HI = cos_NI;
|
||||
}
|
||||
else {
|
||||
float3 X, Y;
|
||||
if (alpha_x == alpha_y) {
|
||||
make_orthonormals(N, &X, &Y);
|
||||
}
|
||||
|
@ -628,83 +630,63 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc,
|
|||
}
|
||||
|
||||
H = X * local_H.x + Y * local_H.y + N * local_H.z;
|
||||
cos_NH = local_H.z;
|
||||
cos_HI = dot(H, wi);
|
||||
}
|
||||
const float cos_HI = dot(H, wi);
|
||||
|
||||
bool valid;
|
||||
/* The angle between the half vector and the refracted ray. Not used when sampling reflection. */
|
||||
float cos_HO;
|
||||
bool do_refract;
|
||||
float lobe_pdf;
|
||||
if (m_refraction || m_glass) {
|
||||
bool inside;
|
||||
float fresnel = fresnel_dielectric(m_eta, H, wi, wo, &inside);
|
||||
valid = !inside;
|
||||
float fresnel = fresnel_dielectric(cos_HI, m_eta, &cos_HO);
|
||||
|
||||
/* For glass closures, we decide between reflection and refraction here. */
|
||||
if (m_glass) {
|
||||
if (fresnel == 1.0f) {
|
||||
/* TIR, reflection is the only option. */
|
||||
do_refract = false;
|
||||
lobe_pdf = 1.0f;
|
||||
}
|
||||
else {
|
||||
/* Decide between reflection and refraction, using defensive sampling to avoid
|
||||
* excessive noise for reflection highlights. */
|
||||
float reflect_pdf = (path_flag & PATH_RAY_CAMERA) ? clamp(fresnel, 0.125f, 0.875f) :
|
||||
fresnel;
|
||||
do_refract = (rand.z >= reflect_pdf);
|
||||
lobe_pdf = do_refract ? (1.0f - reflect_pdf) : reflect_pdf;
|
||||
}
|
||||
do_refract = (rand.z >= fresnel);
|
||||
lobe_pdf = do_refract ? (1.0f - fresnel) : fresnel;
|
||||
}
|
||||
else {
|
||||
/* For pure refractive closures, refraction is the only option. */
|
||||
if (fresnel == 1.0f) {
|
||||
return LABEL_NONE;
|
||||
}
|
||||
do_refract = true;
|
||||
lobe_pdf = 1.0f;
|
||||
valid = valid && (fresnel != 1.0f);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Pure reflective closure, reflection is the only option. */
|
||||
valid = true;
|
||||
lobe_pdf = 1.0f;
|
||||
do_refract = false;
|
||||
}
|
||||
|
||||
int label;
|
||||
if (do_refract) {
|
||||
/* wo was already set to the refracted direction by fresnel_dielectric. */
|
||||
// valid = valid && (dot(Ng, *wo) < 0);
|
||||
label = LABEL_TRANSMIT;
|
||||
*wo = refract_angle(wi, H, cos_HO, m_inv_eta);
|
||||
/* If the IOR is close enough to 1.0, just treat the interaction as specular. */
|
||||
m_singular = m_singular || (fabsf(m_eta - 1.0f) < 1e-4f);
|
||||
}
|
||||
else {
|
||||
/* Eq. 39 - compute actual reflected direction */
|
||||
*wo = 2 * cos_HI * H - wi;
|
||||
valid = valid && (dot(Ng, *wo) > 0);
|
||||
label = LABEL_REFLECT;
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
*eval = zero_spectrum();
|
||||
*pdf = 0.0f;
|
||||
return label | (m_singular ? LABEL_SINGULAR : LABEL_GLOSSY);
|
||||
if ((dot(Ng, *wo) < 0) != do_refract) {
|
||||
return LABEL_NONE;
|
||||
}
|
||||
|
||||
if (m_singular) {
|
||||
label |= LABEL_SINGULAR;
|
||||
/* Some high number for MIS. */
|
||||
*pdf = lobe_pdf * 1e6f;
|
||||
*eval = make_spectrum(1e6f) * microfacet_fresnel(bsdf, wi, H, do_refract);
|
||||
}
|
||||
else {
|
||||
label |= LABEL_GLOSSY;
|
||||
float cos_NO = dot(N, *wo);
|
||||
float D, lambdaI, lambdaO;
|
||||
|
||||
/* TODO: add support for anisotropic transmission. */
|
||||
if (alpha_x == alpha_y || do_refract) { /* Isotropic. */
|
||||
float alpha2 = alpha_x * alpha_y;
|
||||
const float cos_NH = dot(N, H);
|
||||
const float cos_NO = dot(N, *wo);
|
||||
|
||||
if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
|
||||
D = bsdf_clearcoat_D(alpha2, cos_NH);
|
||||
|
@ -721,7 +703,7 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc,
|
|||
lambdaI = bsdf_lambda<m_type>(alpha2, cos_NI);
|
||||
}
|
||||
else { /* Anisotropic. */
|
||||
const float3 local_O = make_float3(dot(X, *wo), dot(Y, *wo), cos_NO);
|
||||
const float3 local_O = 2.0f * cos_HI * local_H - local_I;
|
||||
|
||||
D = bsdf_aniso_D<m_type>(alpha_x, alpha_y, local_H);
|
||||
|
||||
|
@ -729,9 +711,8 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc,
|
|||
lambdaI = bsdf_aniso_lambda<m_type>(alpha_x, alpha_y, local_I);
|
||||
}
|
||||
|
||||
const float cos_HO = dot(H, *wo);
|
||||
const float common = D / cos_NI *
|
||||
(do_refract ? fabsf(cos_HI * cos_HO) / sqr(cos_HO + cos_HI / m_eta) :
|
||||
(do_refract ? fabsf(cos_HI * cos_HO) / sqr(cos_HO + cos_HI * m_inv_eta) :
|
||||
0.25f);
|
||||
|
||||
*pdf = common * lobe_pdf / (1.0f + lambdaI);
|
||||
|
@ -741,9 +722,10 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc,
|
|||
}
|
||||
|
||||
*sampled_roughness = make_float2(alpha_x, alpha_y);
|
||||
*eta = do_refract ? 1.0f / m_eta : m_eta;
|
||||
*eta = do_refract ? m_inv_eta : m_eta;
|
||||
|
||||
return label;
|
||||
return (do_refract ? LABEL_TRANSMIT : LABEL_REFLECT) |
|
||||
(m_singular ? LABEL_SINGULAR : LABEL_GLOSSY);
|
||||
}
|
||||
|
||||
/* Fresnel term setup functions. These get called after the distribution-specific setup functions
|
||||
|
|
|
@ -17,15 +17,15 @@ ccl_device float fresnel_dielectric(float cos_theta_i, float eta, ccl_private fl
|
|||
|
||||
/* Using Snell's law, calculate the squared cosine of the angle between the surface normal and
|
||||
* the transmitted ray. */
|
||||
const float cos_theta_t_sq = 1.0f - (1.0f - sqr(cos_theta_i)) / sqr(eta);
|
||||
if (cos_theta_t_sq <= 0) {
|
||||
const float eta_cos_theta_t_sq = sqr(eta) - (1.0f - sqr(cos_theta_i));
|
||||
if (eta_cos_theta_t_sq <= 0) {
|
||||
/* Total internal reflection. */
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
cos_theta_i = fabsf(cos_theta_i);
|
||||
/* Relative to the surface normal. */
|
||||
const float cos_theta_t = -safe_sqrtf(cos_theta_t_sq);
|
||||
const float cos_theta_t = -safe_sqrtf(eta_cos_theta_t_sq) / eta;
|
||||
|
||||
if (r_cos_theta_t) {
|
||||
*r_cos_theta_t = cos_theta_t;
|
||||
|
@ -48,45 +48,6 @@ ccl_device_inline float3 refract_angle(const float3 incident,
|
|||
return (inv_eta * dot(normal, incident) + cos_theta_t) * normal - inv_eta * incident;
|
||||
}
|
||||
|
||||
ccl_device float fresnel_dielectric(
|
||||
float eta, const float3 N, const float3 I, ccl_private float3 *T, ccl_private bool *is_inside)
|
||||
{
|
||||
float cos = dot(N, I), neta;
|
||||
float3 Nn;
|
||||
|
||||
// check which side of the surface we are on
|
||||
if (cos > 0) {
|
||||
// we are on the outside of the surface, going in
|
||||
neta = 1 / eta;
|
||||
Nn = N;
|
||||
*is_inside = false;
|
||||
}
|
||||
else {
|
||||
// we are inside the surface
|
||||
cos = -cos;
|
||||
neta = eta;
|
||||
Nn = -N;
|
||||
*is_inside = true;
|
||||
}
|
||||
|
||||
float arg = 1 - (neta * neta * (1 - (cos * cos)));
|
||||
if (arg < 0) {
|
||||
*T = make_float3(0.0f, 0.0f, 0.0f);
|
||||
return 1; // total internal reflection
|
||||
}
|
||||
else {
|
||||
float dnp = max(sqrtf(arg), 1e-7f);
|
||||
float nK = (neta * cos) - dnp;
|
||||
*T = -(neta * I) + (nK * Nn);
|
||||
// compute Fresnel terms
|
||||
float cosTheta1 = cos; // N.R
|
||||
float cosTheta2 = -dot(Nn, *T);
|
||||
float pPara = (cosTheta1 - eta * cosTheta2) / (cosTheta1 + eta * cosTheta2);
|
||||
float pPerp = (eta * cosTheta1 - cosTheta2) / (eta * cosTheta1 + cosTheta2);
|
||||
return 0.5f * (pPara * pPara + pPerp * pPerp);
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device float fresnel_dielectric_cos(float cosi, float eta)
|
||||
{
|
||||
// compute fresnel reflectance without explicitly computing
|
||||
|
|
|
@ -202,7 +202,7 @@ bool metalrt_shadow_all_hit(constant KernelParamsMetal &launch_params_metal,
|
|||
type = segment.type;
|
||||
prim = segment.prim;
|
||||
|
||||
/* Filter out curve endcaps */
|
||||
/* Filter out curve end-caps. */
|
||||
if (u == 0.0f || u == 1.0f) {
|
||||
/* continue search */
|
||||
return true;
|
||||
|
@ -349,7 +349,7 @@ inline TReturnType metalrt_visibility_test(
|
|||
if (intersection_type == METALRT_HIT_BOUNDING_BOX &&
|
||||
(type == PRIMITIVE_CURVE_THICK || type == PRIMITIVE_CURVE_RIBBON))
|
||||
{
|
||||
/* Filter out curve endcaps. */
|
||||
/* Filter out curve end-caps. */
|
||||
if (u == 0.0f || u == 1.0f) {
|
||||
result.accept = false;
|
||||
result.continue_search = true;
|
||||
|
|
|
@ -20,7 +20,7 @@ enum DeviceKernel : int;
|
|||
# define CYCLES_KERNEL_ONEAPI_EXPORT extern __declspec(dllimport)
|
||||
# endif
|
||||
# else
|
||||
# define CYCLES_KERNEL_ONEAPI_EXPORT
|
||||
# define CYCLES_KERNEL_ONEAPI_EXPORT extern __attribute__((visibility("default")))
|
||||
# endif
|
||||
# endif
|
||||
|
||||
|
|
|
@ -633,6 +633,7 @@ ccl_device_forceinline Spectrum mnee_eval_bsdf_contribution(ccl_private ShaderCl
|
|||
* contribution = bsdf_do * |do/dh| * |n.wo / n.h| / pdf_dh
|
||||
* = (1 - F) * G * |h.wi / (n.wi * n.h^2)|
|
||||
*/
|
||||
/* TODO: energy compensation for multi-GGX. */
|
||||
return bsdf->weight * F * G * fabsf(cosHI / (cosNI * sqr(cosThetaM)));
|
||||
}
|
||||
|
||||
|
|
|
@ -176,32 +176,6 @@ ccl_device_inline void surface_shader_prepare_closures(KernelGlobals kg,
|
|||
}
|
||||
}
|
||||
|
||||
/* Defensive sampling.
|
||||
*
|
||||
* We can likely also do defensive sampling at deeper bounces, particularly
|
||||
* for cases like a perfect mirror but possibly also others. This will need
|
||||
* a good heuristic. */
|
||||
if (INTEGRATOR_STATE(state, path, bounce) + INTEGRATOR_STATE(state, path, transparent_bounce) ==
|
||||
0 &&
|
||||
sd->num_closure > 1)
|
||||
{
|
||||
float sum = 0.0f;
|
||||
|
||||
for (int i = 0; i < sd->num_closure; i++) {
|
||||
ccl_private ShaderClosure *sc = &sd->closure[i];
|
||||
if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
|
||||
sum += sc->sample_weight;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < sd->num_closure; i++) {
|
||||
ccl_private ShaderClosure *sc = &sd->closure[i];
|
||||
if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
|
||||
sc->sample_weight = max(sc->sample_weight, 0.125f * sum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Filter glossy.
|
||||
*
|
||||
* Blurring of bsdf after bounces, for rays that have a small likelihood
|
||||
|
@ -489,7 +463,7 @@ ccl_device int surface_shader_bsdf_guided_sample_closure_mis(KernelGlobals kg,
|
|||
ccl_private float3 *wo,
|
||||
ccl_private float *bsdf_pdf,
|
||||
ccl_private float *unguided_bsdf_pdf,
|
||||
ccl_private float2 *sampled_rougness,
|
||||
ccl_private float2 *sampled_roughness,
|
||||
ccl_private float *eta)
|
||||
{
|
||||
/* BSSRDF should already have been handled elsewhere. */
|
||||
|
@ -560,7 +534,7 @@ ccl_device int surface_shader_bsdf_guided_sample_closure_mis(KernelGlobals kg,
|
|||
|
||||
kernel_assert(reduce_min(bsdf_eval_sum(bsdf_eval)) >= 0.0f);
|
||||
|
||||
*sampled_rougness = make_float2(1.0f, 1.0f);
|
||||
*sampled_roughness = make_float2(1.0f, 1.0f);
|
||||
*eta = 1.0f;
|
||||
}
|
||||
else {
|
||||
|
@ -574,14 +548,14 @@ ccl_device int surface_shader_bsdf_guided_sample_closure_mis(KernelGlobals kg,
|
|||
&eval,
|
||||
wo,
|
||||
unguided_bsdf_pdf,
|
||||
sampled_rougness,
|
||||
sampled_roughness,
|
||||
eta);
|
||||
# if 0
|
||||
// Code path to validate the estimation of the label, sampled roughness and eta
|
||||
// This should be activated from time to time when the BSDFs change to check if everything
|
||||
// is still working correctly.
|
||||
if (*unguided_bsdf_pdf > 0.0f) {
|
||||
surface_shader_validate_bsdf_sample(kg, sc, *wo, label, sampled_roughness, eta);
|
||||
surface_shader_validate_bsdf_sample(kg, sc, *wo, label, *sampled_roughness, *eta);
|
||||
}
|
||||
# endif
|
||||
|
||||
|
@ -824,7 +798,7 @@ ccl_device int surface_shader_bsdf_guided_sample_closure_ris(KernelGlobals kg,
|
|||
// This should be activated from time to time when the BSDFs change to check if everything
|
||||
// is still working correctly.
|
||||
if (*unguided_bsdf_pdf > 0.0f) {
|
||||
surface_shader_validate_bsdf_sample(kg, sc, *wo, label, sampled_roughness, eta);
|
||||
surface_shader_validate_bsdf_sample(kg, sc, *wo, label, *sampled_roughness, *eta);
|
||||
}
|
||||
# endif
|
||||
|
||||
|
|
|
@ -406,6 +406,11 @@ LightTreeNode *LightTree::build(Scene *scene, DeviceScene *dscene)
|
|||
left, root_.get(), num_emissive_triangles, num_local_lights, emitters_.data(), 0, 1);
|
||||
task_pool.wait_work();
|
||||
|
||||
if (progress_.get_cancel()) {
|
||||
root_.reset();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* All distant lights are grouped to the right child as a leaf node. */
|
||||
root_->get_inner().children[right] = create_node(LightTreeMeasure::empty, 1);
|
||||
for (int i = 0; i < num_distant_lights; i++) {
|
||||
|
|
|
@ -473,7 +473,6 @@ class GHOST_ISystem {
|
|||
/**
|
||||
* Returns the selection buffer
|
||||
* \return "unsigned char" from X11 XA_CUT_BUFFER0 buffer
|
||||
*
|
||||
*/
|
||||
virtual char *getClipboard(bool selection) const = 0;
|
||||
|
||||
|
|
|
@ -327,7 +327,6 @@ class GHOST_System : public GHOST_ISystem {
|
|||
* Returns the selection buffer
|
||||
* \param selection: Only used on X11.
|
||||
* \return Returns the clipboard data
|
||||
*
|
||||
*/
|
||||
virtual char *getClipboard(bool selection) const = 0;
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
47:Slovak (Slovenčina):sk_SK
|
||||
#
|
||||
0:In Progress:
|
||||
11:Czech (Český):cs_CZ
|
||||
11:Czech (Čeština):cs_CZ
|
||||
5:German (Deutsch):de_DE
|
||||
4:Italian (Italiano):it_IT
|
||||
48:Georgian (ქართული):ka
|
||||
|
|
|
@ -44,7 +44,7 @@ LANGUAGES = (
|
|||
(8, "French (Français)", "fr_FR"),
|
||||
(9, "Spanish (Español)", "es"),
|
||||
(10, "Catalan (Català)", "ca_AD"),
|
||||
(11, "Czech (Český)", "cs_CZ"),
|
||||
(11, "Czech (Čeština)", "cs_CZ"),
|
||||
(12, "Portuguese (Português)", "pt_PT"),
|
||||
(13, "Simplified Chinese (简体中文)", "zh_CN"),
|
||||
(14, "Traditional Chinese (繁體中文)", "zh_TW"),
|
||||
|
|
|
@ -83,7 +83,7 @@ class _BPyOpsSubModOp:
|
|||
return _op_poll(self.idname_py(), C_exec)
|
||||
|
||||
def idname(self):
|
||||
# submod.foo -> SUBMOD_OT_foo
|
||||
# `submod.foo` -> `SUBMOD_OT_foo`.
|
||||
return self._module.upper() + "_OT_" + self._func
|
||||
|
||||
def idname_py(self):
|
||||
|
|
|
@ -199,8 +199,8 @@ def load_scripts(*, reload_scripts=False, refresh_scripts=False, extensions=True
|
|||
:arg refresh_scripts: only load scripts which are not already loaded
|
||||
as modules.
|
||||
:type refresh_scripts: bool
|
||||
:arg: extensions: Loads additional scripts (add-ons & app-templates).
|
||||
:type: extensions: bool
|
||||
:arg extensions: Loads additional scripts (add-ons & app-templates).
|
||||
:type extensions: bool
|
||||
"""
|
||||
use_time = use_class_register_check = _bpy.app.debug_python
|
||||
use_user = not _is_factory_startup
|
||||
|
|
|
@ -362,15 +362,15 @@ def _template_items_transform_actions(
|
|||
("transform.translate", {"type": params.select_mouse, "value": 'CLICK_DRAG'}, None),
|
||||
op_tool_optional(
|
||||
("transform.translate", {"type": 'G', "value": 'PRESS'},
|
||||
{"properties": [("alt_navigation", params.use_alt_navigation)]}),
|
||||
{"properties": [("alt_navigation", params.use_alt_navigation)]}),
|
||||
(op_tool_cycle, "builtin.move"), params),
|
||||
op_tool_optional(
|
||||
("transform.rotate", {"type": 'R', "value": 'PRESS'},
|
||||
{"properties": [("alt_navigation", params.use_alt_navigation)]}),
|
||||
{"properties": [("alt_navigation", params.use_alt_navigation)]}),
|
||||
(op_tool_cycle, "builtin.rotate"), params),
|
||||
op_tool_optional(
|
||||
("transform.resize", {"type": 'S', "value": 'PRESS'},
|
||||
{"properties": [("alt_navigation", params.use_alt_navigation)]}),
|
||||
{"properties": [("alt_navigation", params.use_alt_navigation)]}),
|
||||
(op_tool_cycle, "builtin.scale"), params),
|
||||
]
|
||||
|
||||
|
@ -568,7 +568,6 @@ def _template_items_tool_select(
|
|||
# Always use the cursor operator where possible,
|
||||
# needed for time-line views where we always want to be able to scrub time.
|
||||
cursor_prioritize=False,
|
||||
operator_props=(),
|
||||
fallback=False,
|
||||
):
|
||||
if not params.legacy and not fallback:
|
||||
|
@ -585,11 +584,11 @@ def _template_items_tool_select(
|
|||
if select_passthrough:
|
||||
return [
|
||||
(operator, {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("deselect_all", True), ("select_passthrough", True), *operator_props]}),
|
||||
{"properties": [("deselect_all", True), ("select_passthrough", True)]}),
|
||||
(operator, {"type": 'LEFTMOUSE', "value": 'CLICK'},
|
||||
{"properties": [("deselect_all", True), *operator_props]}),
|
||||
{"properties": [("deselect_all", True)]}),
|
||||
(operator, {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("deselect_all", False), ("toggle", True), *operator_props]}),
|
||||
{"properties": [("deselect_all", False), ("toggle", True)]}),
|
||||
("transform.translate", {"type": 'LEFTMOUSE', "value": 'CLICK_DRAG'},
|
||||
{"properties": [("release_confirm", True)]}),
|
||||
]
|
||||
|
@ -600,9 +599,9 @@ def _template_items_tool_select(
|
|||
# unless it is expected that the tool should operate on the selection (click-drag to rip for e.g.).
|
||||
return [
|
||||
(operator, {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("deselect_all", True), *operator_props]}),
|
||||
{"properties": [("deselect_all", True)]}),
|
||||
(operator, {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("toggle", True), *operator_props]}),
|
||||
{"properties": [("toggle", True)]}),
|
||||
|
||||
# Fallback key-map must transform as the primary tool is expected
|
||||
# to be accessed via gizmos in this case. See: #96885.
|
||||
|
@ -1895,7 +1894,7 @@ def km_graph_editor(params):
|
|||
("graph.easing_type", {"type": 'E', "value": 'PRESS', "ctrl": True}, None),
|
||||
("graph.smooth", {"type": 'O', "value": 'PRESS', "alt": True}, None),
|
||||
("graph.sample", {"type": 'O', "value": 'PRESS', "shift": True, "alt": True}, None),
|
||||
("graph.bake", {"type": 'C', "value": 'PRESS', "alt": True}, None),
|
||||
("graph.keys_to_samples", {"type": 'C', "value": 'PRESS', "alt": True}, None),
|
||||
op_menu("GRAPH_MT_delete", {"type": 'X', "value": 'PRESS'}),
|
||||
("graph.delete", {"type": 'DEL', "value": 'PRESS'}, {"properties": [("confirm", False)]}),
|
||||
("graph.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
|
||||
|
@ -2121,16 +2120,29 @@ def km_node_editor(params):
|
|||
)
|
||||
|
||||
if not params.legacy:
|
||||
items.extend(_template_node_select(type=params.select_mouse,
|
||||
value=params.select_mouse_value, select_passthrough=True))
|
||||
items.extend(_template_node_select(
|
||||
type=params.select_mouse,
|
||||
value=params.select_mouse_value,
|
||||
select_passthrough=True,
|
||||
))
|
||||
# Allow node selection with both for RMB select.
|
||||
if params.select_mouse == 'RIGHTMOUSE':
|
||||
items.extend(_template_node_select(type='LEFTMOUSE', value='PRESS', select_passthrough=True))
|
||||
else:
|
||||
items.extend([
|
||||
op_tool_cycle("builtin.select_box", {"type": 'W', "value": 'PRESS'}),
|
||||
])
|
||||
else:
|
||||
items.extend(_template_node_select(
|
||||
type='RIGHTMOUSE', value=params.select_mouse_value, select_passthrough=True))
|
||||
type='RIGHTMOUSE',
|
||||
value=params.select_mouse_value,
|
||||
select_passthrough=True,
|
||||
))
|
||||
items.extend(_template_node_select(
|
||||
type='LEFTMOUSE', value='PRESS', select_passthrough=True))
|
||||
type='LEFTMOUSE',
|
||||
value='PRESS',
|
||||
select_passthrough=True,
|
||||
))
|
||||
|
||||
items.extend([
|
||||
("node.select_box", {"type": params.select_mouse, "value": 'CLICK_DRAG'},
|
||||
|
@ -4043,8 +4055,10 @@ def km_grease_pencil_stroke_sculpt_mode(params):
|
|||
# Context menu
|
||||
*_template_items_context_panel("VIEW3D_PT_gpencil_sculpt_context_menu", params.context_menu_event),
|
||||
# Auto-masking Pie menu.
|
||||
op_menu_pie("VIEW3D_MT_sculpt_gpencil_automasking_pie", {
|
||||
"type": 'A', "shift": True, "alt": True, "value": 'PRESS'}),
|
||||
op_menu_pie(
|
||||
"VIEW3D_MT_sculpt_gpencil_automasking_pie",
|
||||
{"type": 'A', "shift": True, "alt": True, "value": 'PRESS'},
|
||||
),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
@ -4882,10 +4896,6 @@ def _template_view3d_select(*, type, value, legacy, select_passthrough, exclude_
|
|||
# NOTE: `exclude_mod` is needed since we don't want this tool to exclude Control-RMB actions when this is used
|
||||
# as a tool key-map with RMB-select and `use_fallback_tool` is enabled with RMB select. See #92467.
|
||||
|
||||
props_vert_without_handles = ()
|
||||
if select_passthrough:
|
||||
props_vert_without_handles = ("vert_without_handles",)
|
||||
|
||||
# See: `use_tweak_select_passthrough` doc-string.
|
||||
if select_passthrough and (value in {'CLICK', 'RELEASE'}):
|
||||
select_passthrough = False
|
||||
|
@ -4895,9 +4905,9 @@ def _template_view3d_select(*, type, value, legacy, select_passthrough, exclude_
|
|||
{"type": type, "value": value, **{m: True for m in mods}},
|
||||
{"properties": [(c, True) for c in props]},
|
||||
) for props, mods in (
|
||||
((("deselect_all", "select_passthrough", *props_vert_without_handles) if select_passthrough else
|
||||
("deselect_all", *props_vert_without_handles)) if not legacy else (), ()),
|
||||
(("toggle", *props_vert_without_handles), ("shift",)),
|
||||
((("deselect_all", "select_passthrough") if select_passthrough else
|
||||
("deselect_all",)) if not legacy else (), ()),
|
||||
(("toggle",), ("shift",)),
|
||||
(("center", "object"), ("ctrl",)),
|
||||
(("enumerate",), ("alt",)),
|
||||
(("toggle", "center"), ("shift", "ctrl")),
|
||||
|
@ -4914,7 +4924,7 @@ def _template_view3d_select(*, type, value, legacy, select_passthrough, exclude_
|
|||
{"type": type, "value": 'CLICK'},
|
||||
{"properties": [
|
||||
(c, True)
|
||||
for c in ("deselect_all", *props_vert_without_handles)
|
||||
for c in ("deselect_all",)
|
||||
]},
|
||||
))
|
||||
|
||||
|
@ -7070,17 +7080,12 @@ def km_3d_view_tool_text_select(_params):
|
|||
|
||||
|
||||
def km_3d_view_tool_select(params, *, fallback):
|
||||
if params.use_tweak_select_passthrough:
|
||||
operator_props = (("vert_without_handles", True),)
|
||||
else:
|
||||
operator_props = ()
|
||||
|
||||
return (
|
||||
_fallback_id("3D View Tool: Tweak", fallback),
|
||||
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
|
||||
{"items": [
|
||||
*([] if (fallback and (params.select_mouse == 'RIGHTMOUSE')) else _template_items_tool_select(
|
||||
params, "view3d.select", "view3d.cursor3d", operator_props=operator_props, fallback=fallback)),
|
||||
params, "view3d.select", "view3d.cursor3d", fallback=fallback)),
|
||||
*([] if params.use_fallback_tool_select_handled else
|
||||
_template_view3d_select(
|
||||
type=params.select_mouse,
|
||||
|
@ -7895,8 +7900,8 @@ def km_3d_view_tool_paint_gpencil_line(params):
|
|||
("gpencil.primitive_line", {"type": 'LEFTMOUSE', "value": 'PRESS', "alt": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
# Lasso select
|
||||
("gpencil.select_lasso", {"type": params.action_mouse,
|
||||
"value": 'CLICK_DRAG', "ctrl": True, "alt": True}, None),
|
||||
("gpencil.select_lasso",
|
||||
{"type": params.action_mouse, "value": 'CLICK_DRAG', "ctrl": True, "alt": True}, None),
|
||||
]},
|
||||
)
|
||||
|
||||
|
@ -7911,8 +7916,8 @@ def km_3d_view_tool_paint_gpencil_polyline(params):
|
|||
("gpencil.primitive_polyline", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
# Lasso select
|
||||
("gpencil.select_lasso", {"type": params.action_mouse,
|
||||
"value": 'CLICK_DRAG', "ctrl": True, "alt": True}, None),
|
||||
("gpencil.select_lasso",
|
||||
{"type": params.action_mouse, "value": 'CLICK_DRAG', "ctrl": True, "alt": True}, None),
|
||||
]},
|
||||
)
|
||||
|
||||
|
@ -7929,8 +7934,8 @@ def km_3d_view_tool_paint_gpencil_box(params):
|
|||
("gpencil.primitive_box", {"type": 'LEFTMOUSE', "value": 'PRESS', "alt": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
# Lasso select
|
||||
("gpencil.select_lasso", {"type": params.action_mouse,
|
||||
"value": 'CLICK_DRAG', "ctrl": True, "alt": True}, None),
|
||||
("gpencil.select_lasso",
|
||||
{"type": params.action_mouse, "value": 'CLICK_DRAG', "ctrl": True, "alt": True}, None),
|
||||
]},
|
||||
)
|
||||
|
||||
|
@ -7947,8 +7952,8 @@ def km_3d_view_tool_paint_gpencil_circle(params):
|
|||
("gpencil.primitive_circle", {"type": 'LEFTMOUSE', "value": 'PRESS', "alt": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
# Lasso select
|
||||
("gpencil.select_lasso", {"type": params.action_mouse,
|
||||
"value": 'CLICK_DRAG', "ctrl": True, "alt": True}, None),
|
||||
("gpencil.select_lasso",
|
||||
{"type": params.action_mouse, "value": 'CLICK_DRAG', "ctrl": True, "alt": True}, None),
|
||||
]},
|
||||
)
|
||||
|
||||
|
@ -7965,8 +7970,8 @@ def km_3d_view_tool_paint_gpencil_arc(params):
|
|||
("gpencil.primitive_curve", {"type": 'LEFTMOUSE', "value": 'PRESS', "alt": True},
|
||||
{"properties": [("type", 'ARC'), ("wait_for_input", False)]}),
|
||||
# Lasso select
|
||||
("gpencil.select_lasso", {"type": params.action_mouse,
|
||||
"value": 'CLICK_DRAG', "ctrl": True, "alt": True}, None),
|
||||
("gpencil.select_lasso",
|
||||
{"type": params.action_mouse, "value": 'CLICK_DRAG', "ctrl": True, "alt": True}, None),
|
||||
]},
|
||||
)
|
||||
|
||||
|
@ -7979,8 +7984,8 @@ def km_3d_view_tool_paint_gpencil_curve(params):
|
|||
("gpencil.primitive_curve", params.tool_maybe_tweak_event,
|
||||
{"properties": [("type", 'CURVE'), ("wait_for_input", False)]}),
|
||||
# Lasso select
|
||||
("gpencil.select_lasso", {"type": params.action_mouse,
|
||||
"value": 'CLICK_DRAG', "ctrl": True, "alt": True}, None),
|
||||
("gpencil.select_lasso",
|
||||
{"type": params.action_mouse, "value": 'CLICK_DRAG', "ctrl": True, "alt": True}, None),
|
||||
]},
|
||||
)
|
||||
|
||||
|
@ -7992,8 +7997,8 @@ def km_3d_view_tool_paint_gpencil_cutter(params):
|
|||
{"items": [
|
||||
("gpencil.stroke_cutter", {"type": params.tool_mouse, "value": 'PRESS'}, None),
|
||||
# Lasso select
|
||||
("gpencil.select_lasso", {"type": params.action_mouse,
|
||||
"value": 'CLICK_DRAG', "ctrl": True, "alt": True}, None),
|
||||
("gpencil.select_lasso",
|
||||
{"type": params.action_mouse, "value": 'CLICK_DRAG', "ctrl": True, "alt": True}, None),
|
||||
]},
|
||||
)
|
||||
|
||||
|
|
|
@ -35,6 +35,29 @@ def geometry_node_group_empty_new():
|
|||
return group
|
||||
|
||||
|
||||
def geometry_node_group_empty_tool_new(context):
|
||||
group = build_default_empty_geometry_node_group(data_("Tool"))
|
||||
group.links.new(group.nodes[data_("Group Input")].outputs[0], group.nodes[data_("Group Output")].inputs[0])
|
||||
group.asset_mark()
|
||||
group.is_tool = True
|
||||
|
||||
ob_type = context.object.type if context.object else 'MESH'
|
||||
if ob_type == 'CURVES':
|
||||
group.is_type_curve = True
|
||||
elif ob_type == 'POINTCLOUD':
|
||||
group.is_type_point_cloud = True
|
||||
else:
|
||||
group.is_type_mesh = True
|
||||
|
||||
mode = context.object.mode if context.object else 'EDIT'
|
||||
if mode in {'SCULPT', 'SCULPT_CURVES'}:
|
||||
group.is_mode_sculpt = True
|
||||
else:
|
||||
group.is_mode_edit = True
|
||||
|
||||
return group
|
||||
|
||||
|
||||
def geometry_modifier_poll(context):
|
||||
ob = context.object
|
||||
|
||||
|
@ -276,9 +299,7 @@ class NewGeometryNodeGroupTool(Operator):
|
|||
return space and space.type == 'NODE_EDITOR' and space.geometry_nodes_type == 'TOOL'
|
||||
|
||||
def execute(self, context):
|
||||
group = geometry_node_group_empty_new()
|
||||
group.asset_mark()
|
||||
group.is_tool = True
|
||||
group = geometry_node_group_empty_tool_new(context)
|
||||
context.space_data.node_tree = group
|
||||
return {'FINISHED'}
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ class DATA_PT_display(ArmatureButtonsPanel, Panel):
|
|||
col = layout.column(heading="Show")
|
||||
col.prop(arm, "show_names", text="Names")
|
||||
col.prop(arm, "show_bone_custom_shapes", text="Shapes")
|
||||
col.prop(arm, "show_group_colors", text="Group Colors")
|
||||
col.prop(arm, "show_bone_colors", text="Bone Colors")
|
||||
|
||||
if ob:
|
||||
col.prop(ob, "show_in_front", text="In Front")
|
||||
|
@ -96,16 +96,10 @@ class DATA_UL_bone_collections(UIList):
|
|||
class DATA_PT_bone_collections(ArmatureButtonsPanel, Panel):
|
||||
bl_label = "Bone Collections"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
ob = context.object
|
||||
return (ob and ob.type == 'ARMATURE' and ob.pose)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
ob = context.object
|
||||
arm = ob.data
|
||||
arm = context.armature
|
||||
active_bcoll = arm.collections.active
|
||||
|
||||
row = layout.row()
|
||||
|
@ -243,6 +237,17 @@ class DATA_PT_custom_props_arm(ArmatureButtonsPanel, PropertyPanel, Panel):
|
|||
_property_type = bpy.types.Armature
|
||||
|
||||
|
||||
class DATA_PT_custom_props_bcoll(ArmatureButtonsPanel, PropertyPanel, Panel):
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
|
||||
_context_path = "armature.collections.active"
|
||||
_property_type = bpy.types.BoneCollection
|
||||
bl_parent_id = "DATA_PT_bone_collections"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.armature and context.armature.collections.active
|
||||
|
||||
|
||||
classes = (
|
||||
DATA_PT_context_arm,
|
||||
DATA_PT_skeleton,
|
||||
|
@ -253,6 +258,7 @@ classes = (
|
|||
DATA_PT_display,
|
||||
DATA_PT_iksolver_itasc,
|
||||
DATA_PT_custom_props_arm,
|
||||
DATA_PT_custom_props_bcoll,
|
||||
)
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
|
|
|
@ -232,7 +232,6 @@ class BONE_PT_relations(BoneButtonsPanel, Panel):
|
|||
|
||||
if ob and pchan:
|
||||
col.prop(bone, "use_relative_parent")
|
||||
col.prop_search(pchan, "bone_group", ob.pose, "bone_groups", text="Bone Group")
|
||||
|
||||
sub = col.column()
|
||||
sub.active = (bone.parent is not None)
|
||||
|
|
|
@ -36,7 +36,7 @@ class OBJECT_MT_modifier_add(Menu):
|
|||
ob_type = context.object.type
|
||||
geometry_nodes_supported = ob_type in {'MESH', 'CURVE', 'CURVES', 'FONT', 'SURFACE', 'VOLUME', 'POINTCLOUD'}
|
||||
if geometry_nodes_supported:
|
||||
layout.operator("object.modifier_add", text="Empty Modifier").type = 'NODES'
|
||||
layout.operator("object.modifier_add", icon='GEOMETRY_NODES', text="Geometry Nodes").type = 'NODES'
|
||||
layout.separator()
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
|
||||
layout.menu("OBJECT_MT_modifier_add_edit")
|
||||
|
@ -227,6 +227,7 @@ class AddModifierMenu(Operator):
|
|||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
# NOTE: This operator only exists to add a poll to the add modifier shortcut in the property editor.
|
||||
space = context.space_data
|
||||
return space and space.type == 'PROPERTIES' and space.context == "MODIFIER"
|
||||
|
||||
|
|
|
@ -481,6 +481,7 @@ class RENDER_PT_eevee_next_volumetric_lighting(RenderButtonsPanel, Panel):
|
|||
layout.active = props.use_volumetric_lights
|
||||
layout.prop(props, "volumetric_light_clamp", text="Light Clamping")
|
||||
|
||||
|
||||
class RENDER_PT_eevee_next_volumetric_shadows(RenderButtonsPanel, Panel):
|
||||
bl_label = "Volumetric Shadows"
|
||||
bl_parent_id = "RENDER_PT_eevee_next_volumetric"
|
||||
|
|
|
@ -283,8 +283,8 @@ class GRAPH_MT_channel(Menu):
|
|||
layout.operator("anim.channels_fcurves_enable")
|
||||
|
||||
layout.separator()
|
||||
layout.operator("graph.bake")
|
||||
layout.operator("graph.unbake")
|
||||
layout.operator("graph.keys_to_samples")
|
||||
layout.operator("graph.samples_to_keys")
|
||||
layout.operator("graph.sound_bake")
|
||||
|
||||
layout.separator()
|
||||
|
@ -325,6 +325,7 @@ class GRAPH_MT_key_blending(Menu):
|
|||
layout.operator("graph.blend_to_ease", text="Blend to Ease")
|
||||
layout.operator("graph.match_slope", text="Match Slope")
|
||||
layout.operator("graph.shear", text="Shear Keys")
|
||||
layout.operator("graph.scale_average", text="Scale Average")
|
||||
|
||||
|
||||
class GRAPH_MT_key_smoothing(Menu):
|
||||
|
|
|
@ -929,7 +929,6 @@ class NODE_PT_node_tree_interface(Panel):
|
|||
active_item.draw(context, layout)
|
||||
|
||||
if active_item.item_type == 'PANEL':
|
||||
layout.prop(active_item, "name")
|
||||
layout.prop(active_item, "description")
|
||||
layout.prop(active_item, "default_closed", text="Closed by Default")
|
||||
|
||||
|
|
|
@ -344,7 +344,7 @@ class OUTLINER_MT_asset(Menu):
|
|||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
|
||||
layout.operator("asset.mark")
|
||||
layout.operator("asset.mark", icon="ASSET_MANAGER")
|
||||
layout.operator("asset.clear", text="Clear Asset").set_fake_user = False
|
||||
layout.operator("asset.clear", text="Clear Asset (Set Fake User)").set_fake_user = True
|
||||
|
||||
|
|
|
@ -966,15 +966,9 @@ class SEQUENCER_MT_strip(Menu):
|
|||
if has_sequencer:
|
||||
if strip:
|
||||
strip_type = strip.type
|
||||
|
||||
if strip_type != 'SOUND':
|
||||
layout.separator()
|
||||
layout.operator_menu_enum("sequencer.strip_video_modifier_add", "type", text="Add Modifier")
|
||||
layout.operator("sequencer.strip_modifier_copy", text="Copy Modifiers to Selection")
|
||||
else:
|
||||
layout.separator()
|
||||
layout.operator_menu_enum("sequencer.strip_sound_modifier_add", "type", text="Add Modifier")
|
||||
layout.operator("sequencer.strip_modifier_copy", text="Copy Modifiers to Selection")
|
||||
layout.separator()
|
||||
layout.operator_menu_enum("sequencer.strip_modifier_add", "type", text="Add Modifier")
|
||||
layout.operator("sequencer.strip_modifier_copy", text="Copy Modifiers to Selection")
|
||||
|
||||
if strip_type in {
|
||||
'CROSS', 'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER',
|
||||
|
@ -1112,18 +1106,16 @@ class SEQUENCER_MT_context_menu(Menu):
|
|||
strip_type = strip.type
|
||||
selected_sequences_count = selected_sequences_len(context)
|
||||
|
||||
layout.separator()
|
||||
layout.operator_menu_enum("sequencer.strip_modifier_add", "type", text="Add Modifier")
|
||||
layout.operator("sequencer.strip_modifier_copy", text="Copy Modifiers to Selection")
|
||||
|
||||
if strip_type != 'SOUND':
|
||||
layout.separator()
|
||||
layout.operator_menu_enum("sequencer.strip_video_modifier_add", "type", text="Add Modifier")
|
||||
layout.operator("sequencer.strip_modifier_copy", text="Copy Modifiers to Selection")
|
||||
if selected_sequences_count >= 2:
|
||||
layout.separator()
|
||||
col = layout.column()
|
||||
col.menu("SEQUENCER_MT_add_transitions", text="Add Transition")
|
||||
else:
|
||||
layout.separator()
|
||||
layout.operator_menu_enum("sequencer.strip_sound_modifier_add", "type", text="Add Modifier")
|
||||
layout.operator("sequencer.strip_modifier_copy", text="Copy Modifiers to Selection")
|
||||
if selected_sequences_count >= 2:
|
||||
layout.separator()
|
||||
layout.operator("sequencer.crossfade_sounds", text="Crossfade Sounds")
|
||||
|
|
|
@ -726,6 +726,7 @@ class TOPBAR_MT_file_context_menu(Menu):
|
|||
layout.operator_context = 'INVOKE_AREA'
|
||||
layout.menu("TOPBAR_MT_file_new", text="New", text_ctxt=i18n_contexts.id_windowmanager, icon='FILE_NEW')
|
||||
layout.operator("wm.open_mainfile", text="Open...", icon='FILE_FOLDER')
|
||||
layout.menu("TOPBAR_MT_file_open_recent")
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
|
|
@ -2601,7 +2601,7 @@ class VIEW3D_MT_object(Menu):
|
|||
|
||||
layout.separator()
|
||||
|
||||
layout.menu("VIEW3D_MT_object_asset")
|
||||
layout.menu("VIEW3D_MT_object_asset", icon="ASSET_MANAGER")
|
||||
layout.menu("VIEW3D_MT_object_parent")
|
||||
layout.menu("VIEW3D_MT_object_collection")
|
||||
layout.menu("VIEW3D_MT_object_relations")
|
||||
|
|
|
@ -867,7 +867,7 @@ class VIEW3D_PT_tools_weight_gradient(Panel, View3DPaintPanel):
|
|||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
# since we dont give context above, check mode here (to not show in other modes like sculpt)
|
||||
# since we don't give context above, check mode here (to not show in other modes like sculpt).
|
||||
if context.mode != 'PAINT_WEIGHT':
|
||||
return False
|
||||
settings = context.tool_settings.weight_paint
|
||||
|
|
|
@ -124,6 +124,7 @@ bool ANIM_armature_bonecoll_assign(struct BoneCollection *bcoll, struct Bone *bo
|
|||
bool ANIM_armature_bonecoll_assign_editbone(struct BoneCollection *bcoll, struct EditBone *ebone);
|
||||
bool ANIM_armature_bonecoll_assign_and_move(struct BoneCollection *bcoll, struct Bone *bone);
|
||||
bool ANIM_armature_bonecoll_unassign(struct BoneCollection *bcoll, struct Bone *bone);
|
||||
void ANIM_armature_bonecoll_unassign_all(struct Bone *bone);
|
||||
bool ANIM_armature_bonecoll_unassign_editbone(struct BoneCollection *bcoll,
|
||||
struct EditBone *ebone);
|
||||
|
||||
|
|
|
@ -265,11 +265,7 @@ bool ANIM_armature_bonecoll_assign_editbone(BoneCollection *bcoll, EditBone *ebo
|
|||
|
||||
bool ANIM_armature_bonecoll_assign_and_move(BoneCollection *bcoll, Bone *bone)
|
||||
{
|
||||
/* Remove the bone from all its current collections. */
|
||||
LISTBASE_FOREACH_MUTABLE (BoneCollectionReference *, ref, &bone->runtime.collections) {
|
||||
ANIM_armature_bonecoll_unassign(ref->bcoll, bone);
|
||||
}
|
||||
/* Assign the new collection. */
|
||||
ANIM_armature_bonecoll_unassign_all(bone);
|
||||
return ANIM_armature_bonecoll_assign(bcoll, bone);
|
||||
}
|
||||
|
||||
|
@ -299,6 +295,13 @@ bool ANIM_armature_bonecoll_unassign(BoneCollection *bcoll, Bone *bone)
|
|||
return was_found;
|
||||
}
|
||||
|
||||
void ANIM_armature_bonecoll_unassign_all(Bone *bone)
|
||||
{
|
||||
LISTBASE_FOREACH_MUTABLE (BoneCollectionReference *, ref, &bone->runtime.collections) {
|
||||
ANIM_armature_bonecoll_unassign(ref->bcoll, bone);
|
||||
}
|
||||
}
|
||||
|
||||
bool ANIM_armature_bonecoll_unassign_editbone(BoneCollection *bcoll, EditBone *ebone)
|
||||
{
|
||||
bool was_found = false;
|
||||
|
|
|
@ -49,10 +49,10 @@ bool BKE_blender_version_is_alpha(void);
|
|||
* Fill in given string buffer with user-readable formatted file version and subversion (if
|
||||
* provided).
|
||||
*
|
||||
* \param str_buff a char buffer where the formatted string is written, minimal recommended size is
|
||||
* 8, or 16 if subversion is provided.
|
||||
* \param str_buff: a char buffer where the formatted string is written,
|
||||
* minimal recommended size is 8, or 16 if subversion is provided.
|
||||
*
|
||||
* \param file_subversion the file subversion, if given value < 0, it is ignored, and only the
|
||||
* \param file_subversion: the file subversion, if given value < 0, it is ignored, and only the
|
||||
* `file_version` is used.
|
||||
*/
|
||||
void BKE_blender_version_blendfile_string_from_values(char *str_buff,
|
||||
|
|
|
@ -179,7 +179,7 @@ void BKE_constraints_copy_ex(struct ListBase *dst,
|
|||
/**
|
||||
* Run the given callback on all ID-blocks in list of constraints.
|
||||
*
|
||||
* \param flag the `IDWALK_` flags controlling the behavior of the foreach_id code, see
|
||||
* \param flag: the `IDWALK_` flags controlling the behavior of the foreach_id code, see
|
||||
* `BKE_lib_query.h`
|
||||
*/
|
||||
void BKE_constraints_id_loop(struct ListBase *list,
|
||||
|
|
|
@ -259,6 +259,15 @@ inline int2 face_find_adjecent_verts(const IndexRange face,
|
|||
corner_verts[face_corner_next(face, corner)]};
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of triangles needed to tessellate a face with \a face_size corners.
|
||||
*/
|
||||
inline int face_triangles_num(const int face_size)
|
||||
{
|
||||
BLI_assert(face_size > 2);
|
||||
return face_size - 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index of the edge's vertex that is not the \a vert.
|
||||
* If neither edge vertex is equal to \a v, returns -1.
|
||||
|
|
|
@ -275,7 +275,6 @@ bool BKE_pbvh_bmesh_node_raycast_detail(PBVHNode *node,
|
|||
* projecting the far clipping plane into the local object space. This works out to
|
||||
* dividing view3d->clip_end by the object scale, which for small object and large
|
||||
* clip_end's can easily lead to floating-point overflows.
|
||||
*
|
||||
*/
|
||||
void BKE_pbvh_clip_ray_ortho(
|
||||
PBVH *pbvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3]);
|
||||
|
|
|
@ -2879,7 +2879,7 @@ static void nlastrip_evaluate_meta(const int evaluation_mode,
|
|||
/* Assert currently supported modes. If new mode added, then assertion marks potentially missed
|
||||
* area.
|
||||
*
|
||||
* NOTE: In the future if support is ever added to metastrips to support nested tracks, then
|
||||
* NOTE: In the future if support is ever added to meta-strips to support nested tracks, then
|
||||
* STRIP_EVAL_BLEND and STRIP_EVAL_BLEND_GET_INVERTED_LOWER_SNAPSHOT cases are no longer
|
||||
* equivalent. The output of nlastrips_ctime_get_strip() may return a list of strips. The only
|
||||
* case difference should be the evaluation order.
|
||||
|
|
|
@ -485,8 +485,10 @@ static bool rule_follow_leader(BoidRule *rule,
|
|||
BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader *)rule;
|
||||
float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f};
|
||||
float mul, len;
|
||||
int n = (flbr->queue_size <= 1) ? bbd->sim->psys->totpart : flbr->queue_size;
|
||||
int i, p = pa - bbd->sim->psys->particles;
|
||||
const int n = (flbr->queue_size <= 1) ? bbd->sim->psys->totpart : flbr->queue_size;
|
||||
BLI_assert(ARRAY_HAS_ITEM(pa, bbd->sim->psys->particles, bbd->sim->psys->totpart));
|
||||
const int p = int(pa - bbd->sim->psys->particles);
|
||||
int i;
|
||||
bool ret = false;
|
||||
|
||||
if (flbr->ob) {
|
||||
|
|
|
@ -1104,7 +1104,7 @@ static BitVector<> looptri_no_hidden_map_get(const blender::OffsetIndices<int> f
|
|||
int looptri_no_hidden_len = 0;
|
||||
int looptri_index = 0;
|
||||
for (const int64_t i : faces.index_range()) {
|
||||
const int triangles_num = ME_FACE_TRI_TOT(faces[i].size());
|
||||
const int triangles_num = blender::bke::mesh::face_triangles_num(faces[i].size());
|
||||
if (hide_poly[i]) {
|
||||
looptri_index += triangles_num;
|
||||
}
|
||||
|
|
|
@ -4286,10 +4286,11 @@ void BKE_nurbList_handles_set(ListBase *editnurb,
|
|||
bezt = nu->bezt;
|
||||
a = nu->pntsu;
|
||||
while (a--) {
|
||||
if (bezt->f1 & SELECT) {
|
||||
const short flag = BKE_nurb_bezt_handle_test_calc_flag(bezt, SELECT, handle_mode);
|
||||
if (flag & (1 << 0)) {
|
||||
bezt->h1 = h_new;
|
||||
}
|
||||
if (bezt->f3 & SELECT) {
|
||||
if (flag & (1 << 2)) {
|
||||
bezt->h2 = h_new;
|
||||
}
|
||||
|
||||
|
|
|
@ -833,33 +833,34 @@ void BKE_defvert_add_index_notest(MDeformVert *dvert, const int defgroup, const
|
|||
|
||||
void BKE_defvert_remove_group(MDeformVert *dvert, MDeformWeight *dw)
|
||||
{
|
||||
if (dvert && dw) {
|
||||
int i = dw - dvert->dw;
|
||||
if (UNLIKELY(!dvert || !dw)) {
|
||||
return;
|
||||
}
|
||||
/* Ensure `dw` is part of `dvert` (security check). */
|
||||
if (UNLIKELY(uintptr_t(dw - dvert->dw) >= uintptr_t(dvert->totweight))) {
|
||||
/* Assert as an invalid `dw` (while supported) isn't likely to do what the caller expected. */
|
||||
BLI_assert_unreachable();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Security check! */
|
||||
if (i < 0 || i >= dvert->totweight) {
|
||||
return;
|
||||
const int i = dw - dvert->dw;
|
||||
dvert->totweight--;
|
||||
/* If there are still other deform weights attached to this vert then remove
|
||||
* this deform weight, and reshuffle the others. */
|
||||
if (dvert->totweight) {
|
||||
BLI_assert(dvert->dw != nullptr);
|
||||
|
||||
if (i != dvert->totweight) {
|
||||
dvert->dw[i] = dvert->dw[dvert->totweight];
|
||||
}
|
||||
|
||||
dvert->totweight--;
|
||||
/* If there are still other deform weights attached to this vert then remove
|
||||
* this deform weight, and reshuffle the others.
|
||||
*/
|
||||
if (dvert->totweight) {
|
||||
BLI_assert(dvert->dw != nullptr);
|
||||
|
||||
if (i != dvert->totweight) {
|
||||
dvert->dw[i] = dvert->dw[dvert->totweight];
|
||||
}
|
||||
|
||||
dvert->dw = static_cast<MDeformWeight *>(
|
||||
MEM_reallocN(dvert->dw, sizeof(MDeformWeight) * dvert->totweight));
|
||||
}
|
||||
else {
|
||||
/* If there are no other deform weights left then just remove this one. */
|
||||
MEM_freeN(dvert->dw);
|
||||
dvert->dw = nullptr;
|
||||
}
|
||||
dvert->dw = static_cast<MDeformWeight *>(
|
||||
MEM_reallocN(dvert->dw, sizeof(MDeformWeight) * dvert->totweight));
|
||||
}
|
||||
else {
|
||||
/* If there are no other deform weights left then just remove this one. */
|
||||
MEM_freeN(dvert->dw);
|
||||
dvert->dw = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1067,25 +1068,25 @@ void BKE_defvert_extract_vgroup_to_edgeweights(const MDeformVert *dvert,
|
|||
const bool invert_vgroup,
|
||||
float *r_weights)
|
||||
{
|
||||
if (dvert && defgroup != -1) {
|
||||
int i = edges_num;
|
||||
float *tmp_weights = static_cast<float *>(
|
||||
MEM_mallocN(sizeof(*tmp_weights) * size_t(verts_num), __func__));
|
||||
|
||||
BKE_defvert_extract_vgroup_to_vertweights(
|
||||
dvert, defgroup, verts_num, invert_vgroup, tmp_weights);
|
||||
|
||||
while (i--) {
|
||||
const blender::int2 &edge = edges[i];
|
||||
|
||||
r_weights[i] = (tmp_weights[edge[0]] + tmp_weights[edge[1]]) * 0.5f;
|
||||
}
|
||||
|
||||
MEM_freeN(tmp_weights);
|
||||
}
|
||||
else {
|
||||
if (UNLIKELY(!dvert || defgroup == -1)) {
|
||||
copy_vn_fl(r_weights, edges_num, 0.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
int i = edges_num;
|
||||
float *tmp_weights = static_cast<float *>(
|
||||
MEM_mallocN(sizeof(*tmp_weights) * size_t(verts_num), __func__));
|
||||
|
||||
BKE_defvert_extract_vgroup_to_vertweights(
|
||||
dvert, defgroup, verts_num, invert_vgroup, tmp_weights);
|
||||
|
||||
while (i--) {
|
||||
const blender::int2 &edge = edges[i];
|
||||
|
||||
r_weights[i] = (tmp_weights[edge[0]] + tmp_weights[edge[1]]) * 0.5f;
|
||||
}
|
||||
|
||||
MEM_freeN(tmp_weights);
|
||||
}
|
||||
|
||||
void BKE_defvert_extract_vgroup_to_loopweights(const MDeformVert *dvert,
|
||||
|
@ -1096,23 +1097,23 @@ void BKE_defvert_extract_vgroup_to_loopweights(const MDeformVert *dvert,
|
|||
const bool invert_vgroup,
|
||||
float *r_weights)
|
||||
{
|
||||
if (dvert && defgroup != -1) {
|
||||
int i = loops_num;
|
||||
float *tmp_weights = static_cast<float *>(
|
||||
MEM_mallocN(sizeof(*tmp_weights) * size_t(verts_num), __func__));
|
||||
|
||||
BKE_defvert_extract_vgroup_to_vertweights(
|
||||
dvert, defgroup, verts_num, invert_vgroup, tmp_weights);
|
||||
|
||||
while (i--) {
|
||||
r_weights[i] = tmp_weights[corner_verts[i]];
|
||||
}
|
||||
|
||||
MEM_freeN(tmp_weights);
|
||||
}
|
||||
else {
|
||||
if (UNLIKELY(!dvert || defgroup == -1)) {
|
||||
copy_vn_fl(r_weights, loops_num, 0.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
int i = loops_num;
|
||||
float *tmp_weights = static_cast<float *>(
|
||||
MEM_mallocN(sizeof(*tmp_weights) * size_t(verts_num), __func__));
|
||||
|
||||
BKE_defvert_extract_vgroup_to_vertweights(
|
||||
dvert, defgroup, verts_num, invert_vgroup, tmp_weights);
|
||||
|
||||
while (i--) {
|
||||
r_weights[i] = tmp_weights[corner_verts[i]];
|
||||
}
|
||||
|
||||
MEM_freeN(tmp_weights);
|
||||
}
|
||||
|
||||
void BKE_defvert_extract_vgroup_to_faceweights(const MDeformVert *dvert,
|
||||
|
@ -1124,31 +1125,31 @@ void BKE_defvert_extract_vgroup_to_faceweights(const MDeformVert *dvert,
|
|||
const bool invert_vgroup,
|
||||
float *r_weights)
|
||||
{
|
||||
if (dvert && defgroup != -1) {
|
||||
int i = faces.size();
|
||||
float *tmp_weights = static_cast<float *>(
|
||||
MEM_mallocN(sizeof(*tmp_weights) * size_t(verts_num), __func__));
|
||||
|
||||
BKE_defvert_extract_vgroup_to_vertweights(
|
||||
dvert, defgroup, verts_num, invert_vgroup, tmp_weights);
|
||||
|
||||
while (i--) {
|
||||
const blender::IndexRange face = faces[i];
|
||||
const int *corner_vert = &corner_verts[face.start()];
|
||||
int j = face.size();
|
||||
float w = 0.0f;
|
||||
|
||||
for (; j--; corner_vert++) {
|
||||
w += tmp_weights[*corner_vert];
|
||||
}
|
||||
r_weights[i] = w / float(face.size());
|
||||
}
|
||||
|
||||
MEM_freeN(tmp_weights);
|
||||
}
|
||||
else {
|
||||
if (UNLIKELY(!dvert || defgroup == -1)) {
|
||||
copy_vn_fl(r_weights, faces.size(), 0.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
int i = faces.size();
|
||||
float *tmp_weights = static_cast<float *>(
|
||||
MEM_mallocN(sizeof(*tmp_weights) * size_t(verts_num), __func__));
|
||||
|
||||
BKE_defvert_extract_vgroup_to_vertweights(
|
||||
dvert, defgroup, verts_num, invert_vgroup, tmp_weights);
|
||||
|
||||
while (i--) {
|
||||
const blender::IndexRange face = faces[i];
|
||||
const int *corner_vert = &corner_verts[face.start()];
|
||||
int j = face.size();
|
||||
float w = 0.0f;
|
||||
|
||||
for (; j--; corner_vert++) {
|
||||
w += tmp_weights[*corner_vert];
|
||||
}
|
||||
r_weights[i] = w / float(face.size());
|
||||
}
|
||||
|
||||
MEM_freeN(tmp_weights);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -286,7 +286,7 @@ void BKE_mesh_origindex_map_create_looptri(MeshElemMap **r_map,
|
|||
index_step = indices;
|
||||
for (const int64_t i : faces.index_range()) {
|
||||
map[i].indices = index_step;
|
||||
index_step += ME_FACE_TRI_TOT(faces[i].size());
|
||||
index_step += blender::bke::mesh::face_triangles_num(int(faces[i].size()));
|
||||
}
|
||||
|
||||
/* Assign face-tessellation users. */
|
||||
|
@ -328,12 +328,18 @@ static Array<int> reverse_indices_in_groups(const Span<int> group_indices,
|
|||
}
|
||||
BLI_assert(*std::max_element(group_indices.begin(), group_indices.end()) < offsets.size());
|
||||
BLI_assert(*std::min_element(group_indices.begin(), group_indices.end()) >= 0);
|
||||
Array<int> counts(offsets.size(), -1);
|
||||
|
||||
/* `counts` keeps track of how many elements have been added to each group, and is incremented
|
||||
* atomically by many threads in parallel. `calloc` can be measurably faster than a parallel fill
|
||||
* of zero. Alternatively the offsets could be copied and incremented directly, but the cost of
|
||||
* the copy is slightly higher than the cost of `calloc`. */
|
||||
int *counts = MEM_cnew_array<int>(size_t(offsets.size()), __func__);
|
||||
BLI_SCOPED_DEFER([&]() { MEM_freeN(counts); })
|
||||
Array<int> results(group_indices.size());
|
||||
threading::parallel_for(group_indices.index_range(), 1024, [&](const IndexRange range) {
|
||||
for (const int64_t i : range) {
|
||||
const int group_index = group_indices[i];
|
||||
const int index_in_group = atomic_add_and_fetch_int32(&counts[group_index], 1);
|
||||
const int index_in_group = atomic_fetch_and_add_int32(&counts[group_index], 1);
|
||||
results[offsets[group_index][index_in_group]] = int(i);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -306,7 +306,7 @@ void looptris_calc_face_indices(const OffsetIndices<int> faces, MutableSpan<int>
|
|||
for (const int64_t i : range) {
|
||||
const IndexRange face = faces[i];
|
||||
const int start = poly_to_tri_count(int(i), int(face.start()));
|
||||
const int num = ME_FACE_TRI_TOT(int(face.size()));
|
||||
const int num = face_triangles_num(int(face.size()));
|
||||
looptri_faces.slice(start, num).fill(int(i));
|
||||
}
|
||||
});
|
||||
|
|
|
@ -369,9 +369,43 @@ static void socket_data_foreach_id(LibraryForeachIDData *data, bNodeTreeInterfac
|
|||
|
||||
namespace item_types {
|
||||
|
||||
using UidGeneratorFn = blender::FunctionRef<int()>;
|
||||
|
||||
static void item_copy(bNodeTreeInterfaceItem &dst,
|
||||
const bNodeTreeInterfaceItem &src,
|
||||
const int flag)
|
||||
int flag,
|
||||
UidGeneratorFn generate_uid);
|
||||
|
||||
/**
|
||||
* Copy the source items and give each a new unique identifier.
|
||||
* \param generate_uid: Optional generator function for new item UIDs, copies existing identifiers
|
||||
* if null.
|
||||
*/
|
||||
static void panel_init(bNodeTreeInterfacePanel &panel,
|
||||
const Span<const bNodeTreeInterfaceItem *> items_src,
|
||||
const int flag,
|
||||
UidGeneratorFn generate_uid)
|
||||
{
|
||||
panel.items_num = items_src.size();
|
||||
panel.items_array = MEM_cnew_array<bNodeTreeInterfaceItem *>(panel.items_num, __func__);
|
||||
|
||||
/* Copy buffers. */
|
||||
for (const int i : items_src.index_range()) {
|
||||
const bNodeTreeInterfaceItem *item_src = items_src[i];
|
||||
panel.items_array[i] = static_cast<bNodeTreeInterfaceItem *>(MEM_dupallocN(item_src));
|
||||
item_types::item_copy(*panel.items_array[i], *item_src, flag, generate_uid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy data from a source item.
|
||||
* \param generate_uid: Optional generator function for new item UIDs, copies existing identifiers
|
||||
* if null.
|
||||
*/
|
||||
static void item_copy(bNodeTreeInterfaceItem &dst,
|
||||
const bNodeTreeInterfaceItem &src,
|
||||
const int flag,
|
||||
UidGeneratorFn generate_uid)
|
||||
{
|
||||
switch (dst.item_type) {
|
||||
case NODE_INTERFACE_SOCKET: {
|
||||
|
@ -385,7 +419,8 @@ static void item_copy(bNodeTreeInterfaceItem &dst,
|
|||
dst_socket.description = BLI_strdup_null(src_socket.description);
|
||||
dst_socket.socket_type = BLI_strdup(src_socket.socket_type);
|
||||
dst_socket.default_attribute_name = BLI_strdup_null(src_socket.default_attribute_name);
|
||||
dst_socket.identifier = BLI_strdup(src_socket.identifier);
|
||||
dst_socket.identifier = generate_uid ? BLI_sprintfN("Socket_%d", generate_uid()) :
|
||||
BLI_strdup(src_socket.identifier);
|
||||
if (src_socket.properties) {
|
||||
dst_socket.properties = IDP_CopyProperty_ex(src_socket.properties, flag);
|
||||
}
|
||||
|
@ -402,24 +437,9 @@ static void item_copy(bNodeTreeInterfaceItem &dst,
|
|||
|
||||
dst_panel.name = BLI_strdup(src_panel.name);
|
||||
dst_panel.description = BLI_strdup_null(src_panel.description);
|
||||
dst_panel.copy_from(src_panel.items(), flag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
dst_panel.identifier = generate_uid ? generate_uid() : src_panel.identifier;
|
||||
|
||||
static void item_set_unique_identifier(const int uid, bNodeTreeInterfaceItem &item)
|
||||
{
|
||||
switch (item.item_type) {
|
||||
case NODE_INTERFACE_SOCKET: {
|
||||
bNodeTreeInterfaceSocket &socket = reinterpret_cast<bNodeTreeInterfaceSocket &>(item);
|
||||
MEM_SAFE_FREE(socket.identifier);
|
||||
socket.identifier = BLI_sprintfN("Socket_%d", uid);
|
||||
break;
|
||||
}
|
||||
case NODE_INTERFACE_PANEL: {
|
||||
bNodeTreeInterfacePanel &panel = reinterpret_cast<bNodeTreeInterfacePanel &>(item);
|
||||
panel.identifier = uid;
|
||||
panel_init(dst_panel, src_panel.items(), flag, generate_uid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -999,20 +1019,6 @@ static bNodeTreeInterfacePanel *make_panel(const int uid,
|
|||
return new_panel;
|
||||
}
|
||||
|
||||
void bNodeTreeInterfacePanel::copy_from(
|
||||
const blender::Span<const bNodeTreeInterfaceItem *> items_src, int flag)
|
||||
{
|
||||
items_num = items_src.size();
|
||||
items_array = MEM_cnew_array<bNodeTreeInterfaceItem *>(items_num, __func__);
|
||||
|
||||
/* Copy buffers. */
|
||||
for (const int i : items_src.index_range()) {
|
||||
const bNodeTreeInterfaceItem *item_src = items_src[i];
|
||||
items_array[i] = static_cast<bNodeTreeInterfaceItem *>(MEM_dupallocN(item_src));
|
||||
item_types::item_copy(*items_array[i], *item_src, flag);
|
||||
}
|
||||
}
|
||||
|
||||
void bNodeTreeInterface::init_data()
|
||||
{
|
||||
/* Root panel is allowed to contain child panels. */
|
||||
|
@ -1021,7 +1027,7 @@ void bNodeTreeInterface::init_data()
|
|||
|
||||
void bNodeTreeInterface::copy_data(const bNodeTreeInterface &src, int flag)
|
||||
{
|
||||
this->root_panel.copy_from(src.root_panel.items(), flag);
|
||||
item_types::panel_init(this->root_panel, src.root_panel.items(), flag, nullptr);
|
||||
this->active_index = src.active_index;
|
||||
}
|
||||
|
||||
|
@ -1188,8 +1194,7 @@ bNodeTreeInterfaceItem *bNodeTreeInterface::add_item_copy(const bNodeTreeInterfa
|
|||
}
|
||||
|
||||
bNodeTreeInterfaceItem *citem = static_cast<bNodeTreeInterfaceItem *>(MEM_dupallocN(&item));
|
||||
item_types::item_copy(*citem, item, 0);
|
||||
item_types::item_set_unique_identifier(next_uid++, *citem);
|
||||
item_types::item_copy(*citem, item, 0, [&]() { return this->next_uid++; });
|
||||
parent->add_item(*citem);
|
||||
|
||||
return citem;
|
||||
|
@ -1213,8 +1218,7 @@ bNodeTreeInterfaceItem *bNodeTreeInterface::insert_item_copy(const bNodeTreeInte
|
|||
}
|
||||
|
||||
bNodeTreeInterfaceItem *citem = static_cast<bNodeTreeInterfaceItem *>(MEM_dupallocN(&item));
|
||||
item_types::item_copy(*citem, item, 0);
|
||||
item_types::item_set_unique_identifier(next_uid++, *citem);
|
||||
item_types::item_copy(*citem, item, 0, [&]() { return this->next_uid++; });
|
||||
parent->insert_item(*citem, position);
|
||||
|
||||
return citem;
|
||||
|
|
|
@ -61,6 +61,10 @@
|
|||
# include "BPY_extern.h"
|
||||
#endif
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name ID Type Implementation
|
||||
* \{ */
|
||||
|
||||
static void screen_free_data(ID *id)
|
||||
{
|
||||
bScreen *screen = (bScreen *)id;
|
||||
|
@ -189,7 +193,11 @@ IDTypeInfo IDType_ID_SCR = {
|
|||
/*lib_override_apply_post*/ nullptr,
|
||||
};
|
||||
|
||||
/* ************ Space-type/region-type handling ************** */
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Space-type/region-type handling
|
||||
* \{ */
|
||||
|
||||
/** Keep global; this has to be accessible outside of window-manager. */
|
||||
static ListBase spacetypes = {nullptr, nullptr};
|
||||
|
@ -277,7 +285,11 @@ bool BKE_spacetype_exists(int spaceid)
|
|||
return BKE_spacetype_from_id(spaceid) != nullptr;
|
||||
}
|
||||
|
||||
/* ***************** Space handling ********************** */
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Space handling
|
||||
* \{ */
|
||||
|
||||
void BKE_spacedata_freelist(ListBase *lb)
|
||||
{
|
||||
|
@ -570,7 +582,11 @@ void BKE_screen_free_data(bScreen *screen)
|
|||
screen_free_data(&screen->id);
|
||||
}
|
||||
|
||||
/* ***************** Screen edges & verts ***************** */
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Screen edges & verts
|
||||
* \{ */
|
||||
|
||||
ScrEdge *BKE_screen_find_edge(const bScreen *screen, ScrVert *v1, ScrVert *v2)
|
||||
{
|
||||
|
@ -725,7 +741,11 @@ void BKE_screen_remove_unused_scrverts(bScreen *screen)
|
|||
}
|
||||
}
|
||||
|
||||
/* ***************** Utilities ********************** */
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Utilities
|
||||
* \{ */
|
||||
|
||||
ARegion *BKE_region_find_in_listbase_by_type(const ListBase *regionbase, const int region_type)
|
||||
{
|
||||
|
@ -945,6 +965,12 @@ void BKE_screen_header_alignment_reset(bScreen *screen)
|
|||
screen->do_refresh = true;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Blend File IO (Screen & Related Data)
|
||||
* \{ */
|
||||
|
||||
void BKE_screen_view3d_shading_blend_write(BlendWriter *writer, View3DShading *shading)
|
||||
{
|
||||
if (shading->prop) {
|
||||
|
|
|
@ -21,7 +21,6 @@ extern "C" {
|
|||
* \return The number of indices in r_points.
|
||||
*
|
||||
* \note Performance is `O(n.log(n))`, same as `qsort`.
|
||||
*
|
||||
*/
|
||||
int BLI_convexhull_2d(const float (*points)[2], int n, int r_points[/* n */]);
|
||||
|
||||
|
|
|
@ -161,7 +161,6 @@ using IndexMaskSegment = OffsetSpan<int64_t, int16_t>;
|
|||
*
|
||||
* Extraction:
|
||||
* An #IndexMask can be converted into various other forms using the `to_*` methods.
|
||||
*
|
||||
*/
|
||||
class IndexMask : private IndexMaskData {
|
||||
public:
|
||||
|
|
|
@ -133,6 +133,8 @@ MINLINE void add_v4_v4v4(float r[4], const float a[4], const float b[4]);
|
|||
|
||||
MINLINE void add_v3fl_v3fl_v3i(float r[3], const float a[3], const int b[3]);
|
||||
|
||||
MINLINE void add_v3_uchar_clamped(uchar r[3], int i);
|
||||
|
||||
MINLINE void sub_v2_v2(float r[2], const float a[2]);
|
||||
MINLINE void sub_v2_v2_db(double r[2], const double a[2]);
|
||||
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2]);
|
||||
|
|
|
@ -89,9 +89,9 @@ template<typename T> class OffsetIndices {
|
|||
return OffsetIndices(offsets_.slice(range.start(), range.one_after_last()));
|
||||
}
|
||||
|
||||
const T *data() const
|
||||
Span<T> data() const
|
||||
{
|
||||
return offsets_.data();
|
||||
return offsets_;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -458,6 +458,13 @@ MINLINE void add_v4_v4v4(float r[4], const float a[4], const float b[4])
|
|||
r[3] = a[3] + b[3];
|
||||
}
|
||||
|
||||
MINLINE void add_v3_uchar_clamped(uchar r[3], int i)
|
||||
{
|
||||
r[0] = (uchar)clamp_i(r[0] + i, 0, 255);
|
||||
r[1] = (uchar)clamp_i(r[1] + i, 0, 255);
|
||||
r[2] = (uchar)clamp_i(r[2] + i, 0, 255);
|
||||
}
|
||||
|
||||
MINLINE void sub_v2_v2(float r[2], const float a[2])
|
||||
{
|
||||
r[0] -= a[0];
|
||||
|
|
|
@ -203,7 +203,8 @@ void BLO_blendfiledata_free(BlendFileData *bfd);
|
|||
*
|
||||
* Called at the end of #setup_add_data from BKE's `blendfile.cc`.
|
||||
*
|
||||
* \param new_bmain the newly read Main data-base. */
|
||||
* \param new_bmain: the newly read Main data-base.
|
||||
*/
|
||||
void BLO_read_do_version_after_setup(struct Main *new_bmain, struct BlendFileReadReport *reports);
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -3317,7 +3317,7 @@ static void lib_link_all(FileData *fd, Main *bmain)
|
|||
/* Some data that should be persistent, like the 3DCursor or the tool settings, are
|
||||
* stored in IDs affected by undo, like Scene. So this requires some specific handling. */
|
||||
/* NOTE: even though the ID may have been detected as unchanged, the 'undo_preserve' may have
|
||||
* to actually change some of its ID pointers, it's e.g. the case with Scene's toolsettings
|
||||
* to actually change some of its ID pointers, it's e.g. the case with Scene's tool-settings
|
||||
* Brush/Palette pointers. This is the case where both new and old ID may be the same. */
|
||||
if (id_type->blend_read_undo_preserve != nullptr) {
|
||||
BLI_assert(fd->flags & FD_FLAGS_IS_MEMFILE);
|
||||
|
|
|
@ -205,10 +205,9 @@ bool BLO_memfile_write_file(MemFile *memfile, const char *filepath)
|
|||
int file, oflags;
|
||||
|
||||
/* NOTE: This is currently used for auto-save and `quit.blend`,
|
||||
* where _not_ following symlinks is OK,
|
||||
* where _not_ following symbolic-links is OK,
|
||||
* however if this is ever executed explicitly by the user,
|
||||
* we may want to allow writing to symlinks.
|
||||
*/
|
||||
* we may want to allow writing to symbolic-links. */
|
||||
|
||||
oflags = O_BINARY | O_WRONLY | O_CREAT | O_TRUNC;
|
||||
#ifdef O_NOFOLLOW
|
||||
|
|
|
@ -1060,7 +1060,7 @@ static bNodeSocket *version_make_socket_stub(const char *idname,
|
|||
|
||||
/* Note: technically socket values can store ref-counted ID pointers, but at this stage the
|
||||
* refcount can be ignored. It gets recomputed after lib-linking for all ID pointers. Socket
|
||||
* values don't have allocated data, so a simple dupalloc works here. */
|
||||
* values don't have allocated data, so a simple duplication works here. */
|
||||
socket->default_value = default_value ? MEM_dupallocN(default_value) : nullptr;
|
||||
socket->prop = prop ? IDP_CopyProperty(prop) : nullptr;
|
||||
|
||||
|
|
|
@ -626,7 +626,7 @@ void do_versions_after_linking_290(FileData * /*fd*/, Main *bmain)
|
|||
}
|
||||
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 292, 8)) {
|
||||
/* Systematically rebuild posebones to ensure consistent ordering matching the one of bones in
|
||||
/* Systematically rebuild pose-bones to ensure consistent ordering matching the one of bones in
|
||||
* Armature obdata. */
|
||||
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
|
||||
if (ob->type == OB_ARMATURE) {
|
||||
|
|
|
@ -73,7 +73,7 @@ static void version_composite_nodetree_null_id(bNodeTree *ntree, Scene *scene)
|
|||
}
|
||||
}
|
||||
|
||||
/* Move bonegroup color to the individual bones. */
|
||||
/* Move bone-group color to the individual bones. */
|
||||
static void version_bonegroup_migrate_color(Main *bmain)
|
||||
{
|
||||
using PoseSet = blender::Set<bPose *>;
|
||||
|
@ -91,14 +91,14 @@ static void version_bonegroup_migrate_color(Main *bmain)
|
|||
|
||||
/* There is no guarantee that the current state of poses is in sync with the Armature data.
|
||||
*
|
||||
* NOTE: No need to handle user refcounting in readfile code. */
|
||||
* NOTE: No need to handle user reference-counting in readfile code. */
|
||||
BKE_pose_ensure(bmain, ob, arm, false);
|
||||
|
||||
PoseSet &pose_set = armature_poses.lookup_or_add_default(arm);
|
||||
pose_set.add(ob->pose);
|
||||
}
|
||||
|
||||
/* Move colors from the pose's bonegroup to either the armature bones or the
|
||||
/* Move colors from the pose's bone-group to either the armature bones or the
|
||||
* pose bones, depending on how many poses use the Armature. */
|
||||
for (const PoseSet &pose_set : armature_poses.values()) {
|
||||
/* If the Armature is shared, the bone group colors might be different, and thus they have to
|
||||
|
|
|
@ -50,6 +50,9 @@ BMUVOffsets BM_uv_map_get_offsets_from_layer(const BMesh *bm, const int layer)
|
|||
BMUVOffsets BM_uv_map_get_offsets(const BMesh *bm)
|
||||
{
|
||||
const int layer = CustomData_get_active_layer(&bm->ldata, CD_PROP_FLOAT2);
|
||||
if (layer == -1) {
|
||||
return {-1, -1, -1, -1};
|
||||
}
|
||||
return BM_uv_map_get_offsets_from_layer(bm, layer);
|
||||
}
|
||||
|
||||
|
|
|
@ -129,7 +129,8 @@ void Evaluator::map_node_operation_inputs_to_their_results(DNode node,
|
|||
* origin is the input socket itself or the input is connected to an unlinked input of a group
|
||||
* input node and the origin is the input of the group input node. So map the input to the
|
||||
* result of a newly created Input Single Value Operation. */
|
||||
auto *input_operation = new InputSingleValueOperation(context_, DInputSocket(dorigin));
|
||||
InputSingleValueOperation *input_operation = new InputSingleValueOperation(
|
||||
context_, DInputSocket(dorigin));
|
||||
operation->map_input_to_result(input->identifier, &input_operation->get_result());
|
||||
|
||||
operations_stream_.append(std::unique_ptr<InputSingleValueOperation>(input_operation));
|
||||
|
|
|
@ -58,7 +58,6 @@ int compute_number_of_diagonals(ivec2 size)
|
|||
* all share the same maximum value, that is, the longest length:
|
||||
*
|
||||
* Length => min(Longest Length, index + 1, Number Of Diagonals - index)
|
||||
*
|
||||
*/
|
||||
int compute_diagonal_length(ivec2 size, int diagonal_index)
|
||||
{
|
||||
|
@ -94,7 +93,6 @@ int compute_diagonal_length(ivec2 size, int diagonal_index)
|
|||
* while other indices are zero. Which can be described using the compact equation:
|
||||
*
|
||||
* Y => max(0, (height - 1) - index)
|
||||
*
|
||||
*/
|
||||
ivec2 compute_diagonal_start(ivec2 size, int index)
|
||||
{
|
||||
|
@ -158,7 +156,6 @@ int compute_anti_diagonal_length(ivec2 size, int diagonal_index)
|
|||
* from zero to (height - 1). Which can be described using the compact equation:
|
||||
*
|
||||
* Y => max(0, index - (width - 1))
|
||||
*
|
||||
*/
|
||||
ivec2 compute_anti_diagonal_start(ivec2 size, int index)
|
||||
{
|
||||
|
|
|
@ -42,8 +42,6 @@ void AmbientOcclusion::init()
|
|||
data_.quality = inst_.scene->eevee.gtao_quality;
|
||||
/* Size is multiplied by 2 because it is applied in NDC [-1..1] range. */
|
||||
data_.pixel_size = float2(2.0f) / float2(inst_.film.render_extent_get());
|
||||
|
||||
data_.push_update();
|
||||
}
|
||||
|
||||
void AmbientOcclusion::sync()
|
||||
|
@ -56,9 +54,9 @@ void AmbientOcclusion::sync()
|
|||
render_pass_ps_.shader_set(inst_.shaders.static_shader_get(AMBIENT_OCCLUSION_PASS));
|
||||
|
||||
render_pass_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, &inst_.pipelines.utility_tx);
|
||||
inst_.bind_uniform_data(&render_pass_ps_);
|
||||
inst_.sampling.bind_resources(&render_pass_ps_);
|
||||
inst_.hiz_buffer.bind_resources(&render_pass_ps_);
|
||||
bind_resources(&render_pass_ps_);
|
||||
|
||||
render_pass_ps_.bind_image("in_normal_img", &inst_.render_buffers.rp_color_tx);
|
||||
render_pass_ps_.push_constant("in_normal_img_layer_index", &inst_.render_buffers.data.normal_id);
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
* Based on Practical Realtime Strategies for Accurate Indirect Occlusion
|
||||
* http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pdf
|
||||
* http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pptx
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
@ -31,11 +30,11 @@ class AmbientOcclusion {
|
|||
|
||||
bool render_pass_enabled_;
|
||||
|
||||
AODataBuf data_;
|
||||
AOData &data_;
|
||||
PassSimple render_pass_ps_ = {"AO Render Pass"};
|
||||
|
||||
public:
|
||||
AmbientOcclusion(Instance &inst) : inst_(inst){};
|
||||
AmbientOcclusion(Instance &inst, AOData &data) : inst_(inst), data_(data){};
|
||||
~AmbientOcclusion(){};
|
||||
|
||||
void init();
|
||||
|
@ -44,11 +43,6 @@ class AmbientOcclusion {
|
|||
|
||||
void render(View &view);
|
||||
void render_pass(View &view);
|
||||
|
||||
template<typename T> void bind_resources(draw::detail::PassBase<T> *pass)
|
||||
{
|
||||
pass->bind_ubo(AO_BUF_SLOT, &data_);
|
||||
}
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -180,7 +180,6 @@ void Camera::sync()
|
|||
}
|
||||
|
||||
data_.initialized = true;
|
||||
data_.push_update();
|
||||
|
||||
update_bounds();
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ class Camera {
|
|||
private:
|
||||
Instance &inst_;
|
||||
|
||||
CameraDataBuf data_;
|
||||
CameraData &data_;
|
||||
|
||||
struct {
|
||||
float3 center;
|
||||
|
@ -104,7 +104,7 @@ class Camera {
|
|||
bool overscan_changed_;
|
||||
|
||||
public:
|
||||
Camera(Instance &inst) : inst_(inst){};
|
||||
Camera(Instance &inst, CameraData &data) : inst_(inst), data_(data){};
|
||||
~Camera(){};
|
||||
|
||||
void init();
|
||||
|
@ -118,10 +118,6 @@ class Camera {
|
|||
BLI_assert(data_.initialized);
|
||||
return data_;
|
||||
}
|
||||
GPUUniformBuf *ubo_get() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
bool is_panoramic() const
|
||||
{
|
||||
return eevee::is_panoramic(data_.type);
|
||||
|
|
|
@ -154,21 +154,14 @@
|
|||
|
||||
/* Uniform Buffers. */
|
||||
/* Slot 0 is GPU_NODE_TREE_UBO_SLOT. */
|
||||
#define CAMERA_BUF_SLOT 1
|
||||
#define RBUFS_BUF_SLOT 2
|
||||
#define UNIFORM_BUF_SLOT 1
|
||||
/* Only during surface shading (forward and deferred eval). */
|
||||
#define HIZ_BUF_SLOT 3
|
||||
#define IRRADIANCE_GRID_BUF_SLOT 4
|
||||
#define AO_BUF_SLOT 5
|
||||
#define VOLUMES_INFO_BUF_SLOT 6
|
||||
/* SLOT 6 is used by render shaders (Film, DoF and Motion Blur). Need to check if it should be
|
||||
* assigned a different slot. */
|
||||
/* TODO(fclem): This is above the limit of slot 6 for engines. Keep it lower by merging others. */
|
||||
#define REFLECTION_PROBE_BUF_SLOT 7
|
||||
#define IRRADIANCE_GRID_BUF_SLOT 2
|
||||
#define REFLECTION_PROBE_BUF_SLOT 3
|
||||
/* Only during pre-pass. */
|
||||
#define VELOCITY_CAMERA_PREV_BUF 3
|
||||
#define VELOCITY_CAMERA_CURR_BUF 4
|
||||
#define VELOCITY_CAMERA_NEXT_BUF 5
|
||||
#define VELOCITY_CAMERA_PREV_BUF 2
|
||||
#define VELOCITY_CAMERA_CURR_BUF 3
|
||||
#define VELOCITY_CAMERA_NEXT_BUF 4
|
||||
|
||||
/* Storage Buffers. */
|
||||
#define LIGHT_CULL_BUF_SLOT 0
|
||||
|
|
|
@ -434,7 +434,7 @@ void Film::sync()
|
|||
accumulate_ps_.init();
|
||||
accumulate_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
|
||||
accumulate_ps_.shader_set(inst_.shaders.static_shader_get(shader));
|
||||
accumulate_ps_.bind_ubo("film_buf", &data_);
|
||||
inst_.bind_uniform_data(&accumulate_ps_);
|
||||
accumulate_ps_.bind_ubo("camera_prev", &(*velocity.camera_steps[STEP_PREVIOUS]));
|
||||
accumulate_ps_.bind_ubo("camera_curr", &(*velocity.camera_steps[STEP_CURRENT]));
|
||||
accumulate_ps_.bind_ubo("camera_next", &(*velocity.camera_steps[step_next]));
|
||||
|
@ -455,7 +455,6 @@ void Film::sync()
|
|||
accumulate_ps_.bind_image("color_accum_img", &color_accum_tx_);
|
||||
accumulate_ps_.bind_image("value_accum_img", &value_accum_tx_);
|
||||
accumulate_ps_.bind_image("cryptomatte_img", &cryptomatte_tx_);
|
||||
accumulate_ps_.bind_ubo(RBUFS_BUF_SLOT, &inst_.render_buffers.data);
|
||||
/* Sync with rendering passes. */
|
||||
accumulate_ps_.barrier(GPU_BARRIER_TEXTURE_FETCH | GPU_BARRIER_SHADER_IMAGE_ACCESS);
|
||||
if (use_compute) {
|
||||
|
@ -646,7 +645,7 @@ void Film::accumulate(const DRWView *view, GPUTexture *combined_final_tx)
|
|||
combined_final_tx_ = combined_final_tx;
|
||||
|
||||
data_.display_only = false;
|
||||
data_.push_update();
|
||||
inst_.push_uniform_data();
|
||||
|
||||
draw::View drw_view("MainView", view);
|
||||
|
||||
|
@ -675,7 +674,7 @@ void Film::display()
|
|||
combined_final_tx_ = inst_.render_buffers.combined_tx;
|
||||
|
||||
data_.display_only = true;
|
||||
data_.push_update();
|
||||
inst_.push_uniform_data();
|
||||
|
||||
draw::View drw_view("MainView", DRW_view_default_get());
|
||||
|
||||
|
|
|
@ -75,13 +75,13 @@ class Film {
|
|||
PassSimple accumulate_ps_ = {"Film.Accumulate"};
|
||||
PassSimple cryptomatte_post_ps_ = {"Film.Cryptomatte.Post"};
|
||||
|
||||
FilmDataBuf data_;
|
||||
FilmData &data_;
|
||||
int2 display_extent;
|
||||
|
||||
eViewLayerEEVEEPassType enabled_passes_ = eViewLayerEEVEEPassType(0);
|
||||
|
||||
public:
|
||||
Film(Instance &inst) : inst_(inst){};
|
||||
Film(Instance &inst, FilmData &data) : inst_(inst), data_(data){};
|
||||
~Film(){};
|
||||
|
||||
void init(const int2 &full_extent, const rcti *output_rect);
|
||||
|
|
|
@ -31,7 +31,6 @@ void HiZBuffer::sync()
|
|||
GPU_texture_mipmap_mode(hiz_tx_, true, false);
|
||||
|
||||
data_.uv_scale = float2(render_extent) / float2(hiz_extent);
|
||||
data_.push_update();
|
||||
|
||||
{
|
||||
hiz_update_ps_.init();
|
||||
|
|
|
@ -42,10 +42,10 @@ class HiZBuffer {
|
|||
/** Dirty flag to check if the update is necessary. */
|
||||
bool is_dirty_ = true;
|
||||
|
||||
HiZDataBuf data_;
|
||||
HiZData &data_;
|
||||
|
||||
public:
|
||||
HiZBuffer(Instance &inst) : inst_(inst)
|
||||
HiZBuffer(Instance &inst, HiZData &data) : inst_(inst), data_(data)
|
||||
{
|
||||
atomic_tile_counter_.clear_to_zero();
|
||||
};
|
||||
|
@ -72,13 +72,11 @@ class HiZBuffer {
|
|||
void bind_resources(DRWShadingGroup *grp)
|
||||
{
|
||||
DRW_shgroup_uniform_texture_ref(grp, "hiz_tx", &hiz_tx_);
|
||||
DRW_shgroup_uniform_block_ref(grp, "hiz_buf", &data_);
|
||||
}
|
||||
|
||||
template<typename T> void bind_resources(draw::detail::PassBase<T> *pass)
|
||||
{
|
||||
pass->bind_texture(HIZ_TEX_SLOT, &hiz_tx_);
|
||||
pass->bind_ubo(HIZ_BUF_SLOT, &data_);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -280,6 +280,8 @@ void Instance::end_sync()
|
|||
light_probes.end_sync();
|
||||
reflection_probes.end_sync();
|
||||
volume.end_sync();
|
||||
|
||||
global_ubo_.push_update();
|
||||
}
|
||||
|
||||
void Instance::render_sync()
|
||||
|
|
|
@ -51,6 +51,8 @@ class Instance {
|
|||
friend VelocityModule;
|
||||
friend MotionBlurModule;
|
||||
|
||||
UniformDataBuf global_ubo_;
|
||||
|
||||
public:
|
||||
ShaderModule &shaders;
|
||||
SyncModule sync;
|
||||
|
@ -115,29 +117,29 @@ class Instance {
|
|||
: shaders(*ShaderModule::module_get()),
|
||||
sync(*this),
|
||||
materials(*this),
|
||||
subsurface(*this),
|
||||
subsurface(*this, global_ubo_.subsurface),
|
||||
pipelines(*this),
|
||||
shadows(*this),
|
||||
lights(*this),
|
||||
ambient_occlusion(*this),
|
||||
raytracing(*this),
|
||||
ambient_occlusion(*this, global_ubo_.ao),
|
||||
raytracing(*this, global_ubo_.raytrace),
|
||||
reflection_probes(*this),
|
||||
velocity(*this),
|
||||
motion_blur(*this),
|
||||
depth_of_field(*this),
|
||||
cryptomatte(*this),
|
||||
hiz_buffer(*this),
|
||||
hiz_buffer(*this, global_ubo_.hiz),
|
||||
sampling(*this),
|
||||
camera(*this),
|
||||
film(*this),
|
||||
render_buffers(*this),
|
||||
camera(*this, global_ubo_.camera),
|
||||
film(*this, global_ubo_.film),
|
||||
render_buffers(*this, global_ubo_.render_pass),
|
||||
main_view(*this),
|
||||
capture_view(*this),
|
||||
world(*this),
|
||||
lookdev(*this),
|
||||
light_probes(*this),
|
||||
irradiance_cache(*this),
|
||||
volume(*this){};
|
||||
volume(*this, global_ubo_.volumes){};
|
||||
~Instance(){};
|
||||
|
||||
/* Render & Viewport. */
|
||||
|
@ -216,6 +218,16 @@ class Instance {
|
|||
((v3d->shading.flag & V3D_SHADING_SCENE_WORLD_RENDER) == 0)));
|
||||
}
|
||||
|
||||
void push_uniform_data()
|
||||
{
|
||||
global_ubo_.push_update();
|
||||
}
|
||||
|
||||
template<typename T> void bind_uniform_data(draw::detail::PassBase<T> *pass)
|
||||
{
|
||||
pass->bind_ubo(UNIFORM_BUF_SLOT, &global_ubo_);
|
||||
}
|
||||
|
||||
private:
|
||||
static void object_sync_render(void *instance_,
|
||||
Object *ob,
|
||||
|
|
|
@ -417,6 +417,7 @@ void LightModule::debug_pass_sync()
|
|||
debug_draw_ps_.init();
|
||||
debug_draw_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM);
|
||||
debug_draw_ps_.shader_set(inst_.shaders.static_shader_get(LIGHT_CULLING_DEBUG));
|
||||
inst_.bind_uniform_data(&debug_draw_ps_);
|
||||
inst_.hiz_buffer.bind_resources(&debug_draw_ps_);
|
||||
debug_draw_ps_.bind_ssbo("light_buf", &culling_light_buf_);
|
||||
debug_draw_ps_.bind_ssbo("light_cull_buf", &culling_data_buf_);
|
||||
|
|
|
@ -125,7 +125,9 @@ void MotionBlurModule::sync()
|
|||
{
|
||||
/* Disable motion blur in viewport when changing camera projection type.
|
||||
* Avoids really high velocities. */
|
||||
if (inst_.velocity.camera_changed_projection() || inst_.camera.overscan_changed()) {
|
||||
if (inst_.velocity.camera_changed_projection() ||
|
||||
(inst_.is_viewport() && inst_.camera.overscan_changed()))
|
||||
{
|
||||
motion_blur_fx_enabled_ = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,8 +43,7 @@ void BackgroundPipeline::sync(GPUMaterial *gpumat, const float background_opacit
|
|||
/* Required by validation layers. */
|
||||
inst_.cryptomatte.bind_resources(&world_ps_);
|
||||
|
||||
world_ps_.bind_ubo(CAMERA_BUF_SLOT, inst_.camera.ubo_get());
|
||||
world_ps_.bind_ubo(RBUFS_BUF_SLOT, &inst_.render_buffers.data);
|
||||
inst_.bind_uniform_data(&world_ps_);
|
||||
|
||||
world_ps_.draw(DRW_cache_fullscreen_quad_get(), handle);
|
||||
/* To allow opaque pass rendering over it. */
|
||||
|
@ -82,8 +81,7 @@ void WorldPipeline::sync(GPUMaterial *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);
|
||||
inst_.bind_uniform_data(&pass);
|
||||
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_);
|
||||
|
@ -118,6 +116,7 @@ void WorldVolumePipeline::sync(GPUMaterial *gpumat)
|
|||
{
|
||||
world_ps_.init();
|
||||
world_ps_.state_set(DRW_STATE_WRITE_COLOR);
|
||||
inst_.bind_uniform_data(&world_ps_);
|
||||
inst_.volume.bind_properties_buffers(world_ps_);
|
||||
inst_.sampling.bind_resources(&world_ps_);
|
||||
|
||||
|
@ -152,10 +151,10 @@ void ShadowPipeline::sync()
|
|||
surface_ps_.state_set(DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
|
||||
surface_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
|
||||
surface_ps_.bind_image(SHADOW_ATLAS_IMG_SLOT, inst_.shadows.atlas_tx_);
|
||||
surface_ps_.bind_ubo(CAMERA_BUF_SLOT, inst_.camera.ubo_get());
|
||||
surface_ps_.bind_ssbo(SHADOW_RENDER_MAP_BUF_SLOT, &inst_.shadows.render_map_buf_);
|
||||
surface_ps_.bind_ssbo(SHADOW_VIEWPORT_INDEX_BUF_SLOT, &inst_.shadows.viewport_index_buf_);
|
||||
surface_ps_.bind_ssbo(SHADOW_PAGE_INFO_SLOT, &inst_.shadows.pages_infos_data_);
|
||||
inst_.bind_uniform_data(&surface_ps_);
|
||||
inst_.sampling.bind_resources(&surface_ps_);
|
||||
}
|
||||
|
||||
|
@ -192,9 +191,8 @@ void ForwardPipeline::sync()
|
|||
|
||||
/* Textures. */
|
||||
prepass_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
|
||||
/* Uniform Buffer. */
|
||||
prepass_ps_.bind_ubo(CAMERA_BUF_SLOT, inst_.camera.ubo_get());
|
||||
|
||||
inst_.bind_uniform_data(&prepass_ps_);
|
||||
inst_.velocity.bind_resources(&prepass_ps_);
|
||||
inst_.sampling.bind_resources(&prepass_ps_);
|
||||
}
|
||||
|
@ -224,16 +222,11 @@ void ForwardPipeline::sync()
|
|||
/* Textures. */
|
||||
opaque_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
|
||||
|
||||
/* Uniform Buffer. */
|
||||
opaque_ps_.bind_ubo(CAMERA_BUF_SLOT, inst_.camera.ubo_get());
|
||||
opaque_ps_.bind_ubo(RBUFS_BUF_SLOT, &inst_.render_buffers.data);
|
||||
|
||||
inst_.bind_uniform_data(&opaque_ps_);
|
||||
inst_.lights.bind_resources(&opaque_ps_);
|
||||
inst_.shadows.bind_resources(&opaque_ps_);
|
||||
inst_.sampling.bind_resources(&opaque_ps_);
|
||||
inst_.hiz_buffer.bind_resources(&opaque_ps_);
|
||||
inst_.ambient_occlusion.bind_resources(&opaque_ps_);
|
||||
inst_.cryptomatte.bind_resources(&opaque_ps_);
|
||||
}
|
||||
|
||||
opaque_single_sided_ps_ = &opaque_ps_.sub("SingleSided");
|
||||
|
@ -253,15 +246,13 @@ void ForwardPipeline::sync()
|
|||
|
||||
/* Textures. */
|
||||
sub.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
|
||||
/* Uniform Buffer. */
|
||||
sub.bind_ubo(CAMERA_BUF_SLOT, inst_.camera.ubo_get());
|
||||
|
||||
inst_.bind_uniform_data(&sub);
|
||||
inst_.lights.bind_resources(&sub);
|
||||
inst_.shadows.bind_resources(&sub);
|
||||
inst_.volume.bind_resources(sub);
|
||||
inst_.sampling.bind_resources(&sub);
|
||||
inst_.hiz_buffer.bind_resources(&sub);
|
||||
inst_.ambient_occlusion.bind_resources(&sub);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -368,9 +359,8 @@ void DeferredLayer::begin_sync()
|
|||
|
||||
/* Textures. */
|
||||
prepass_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
|
||||
/* Uniform Buffer. */
|
||||
prepass_ps_.bind_ubo(CAMERA_BUF_SLOT, inst_.camera.ubo_get());
|
||||
|
||||
inst_.bind_uniform_data(&prepass_ps_);
|
||||
inst_.velocity.bind_resources(&prepass_ps_);
|
||||
inst_.sampling.bind_resources(&prepass_ps_);
|
||||
}
|
||||
|
@ -410,13 +400,10 @@ void DeferredLayer::begin_sync()
|
|||
/* Storage Buffer. */
|
||||
/* Textures. */
|
||||
gbuffer_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
|
||||
/* Uniform Buffer. */
|
||||
gbuffer_ps_.bind_ubo(CAMERA_BUF_SLOT, inst_.camera.ubo_get());
|
||||
gbuffer_ps_.bind_ubo(RBUFS_BUF_SLOT, &inst_.render_buffers.data);
|
||||
|
||||
inst_.bind_uniform_data(&gbuffer_ps_);
|
||||
inst_.sampling.bind_resources(&gbuffer_ps_);
|
||||
inst_.hiz_buffer.bind_resources(&gbuffer_ps_);
|
||||
inst_.ambient_occlusion.bind_resources(&gbuffer_ps_);
|
||||
inst_.cryptomatte.bind_resources(&gbuffer_ps_);
|
||||
}
|
||||
|
||||
|
@ -455,13 +442,12 @@ void DeferredLayer::end_sync()
|
|||
eval_light_ps_.bind_image(RBUFS_COLOR_SLOT, &inst_.render_buffers.rp_color_tx);
|
||||
eval_light_ps_.bind_image(RBUFS_VALUE_SLOT, &inst_.render_buffers.rp_value_tx);
|
||||
eval_light_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
|
||||
eval_light_ps_.bind_ubo(RBUFS_BUF_SLOT, &inst_.render_buffers.data);
|
||||
|
||||
inst_.bind_uniform_data(&eval_light_ps_);
|
||||
inst_.lights.bind_resources(&eval_light_ps_);
|
||||
inst_.shadows.bind_resources(&eval_light_ps_);
|
||||
inst_.sampling.bind_resources(&eval_light_ps_);
|
||||
inst_.hiz_buffer.bind_resources(&eval_light_ps_);
|
||||
inst_.ambient_occlusion.bind_resources(&eval_light_ps_);
|
||||
inst_.reflection_probes.bind_resources(&eval_light_ps_);
|
||||
inst_.irradiance_cache.bind_resources(&eval_light_ps_);
|
||||
|
||||
|
@ -617,6 +603,7 @@ void VolumePipeline::sync()
|
|||
{
|
||||
volume_ps_.init();
|
||||
volume_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
|
||||
inst_.bind_uniform_data(&volume_ps_);
|
||||
inst_.volume.bind_properties_buffers(volume_ps_);
|
||||
inst_.sampling.bind_resources(&volume_ps_);
|
||||
}
|
||||
|
@ -646,9 +633,8 @@ void DeferredProbeLayer::begin_sync()
|
|||
|
||||
/* Textures. */
|
||||
prepass_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
|
||||
/* Uniform Buffer. */
|
||||
prepass_ps_.bind_ubo(CAMERA_BUF_SLOT, inst_.camera.ubo_get());
|
||||
|
||||
inst_.bind_uniform_data(&prepass_ps_);
|
||||
inst_.velocity.bind_resources(&prepass_ps_);
|
||||
inst_.sampling.bind_resources(&prepass_ps_);
|
||||
}
|
||||
|
@ -680,13 +666,10 @@ void DeferredProbeLayer::begin_sync()
|
|||
/* Storage Buffer. */
|
||||
/* Textures. */
|
||||
gbuffer_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
|
||||
/* Uniform Buffer. */
|
||||
gbuffer_ps_.bind_ubo(CAMERA_BUF_SLOT, inst_.camera.ubo_get());
|
||||
gbuffer_ps_.bind_ubo(RBUFS_BUF_SLOT, &inst_.render_buffers.data);
|
||||
|
||||
inst_.bind_uniform_data(&gbuffer_ps_);
|
||||
inst_.sampling.bind_resources(&gbuffer_ps_);
|
||||
inst_.hiz_buffer.bind_resources(&gbuffer_ps_);
|
||||
inst_.ambient_occlusion.bind_resources(&gbuffer_ps_);
|
||||
inst_.cryptomatte.bind_resources(&gbuffer_ps_);
|
||||
}
|
||||
|
||||
|
@ -728,13 +711,12 @@ void DeferredProbeLayer::end_sync()
|
|||
eval_light_ps_.bind_image(RBUFS_COLOR_SLOT, &inst_.render_buffers.rp_color_tx);
|
||||
eval_light_ps_.bind_image(RBUFS_VALUE_SLOT, &inst_.render_buffers.rp_value_tx);
|
||||
eval_light_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
|
||||
eval_light_ps_.bind_ubo(RBUFS_BUF_SLOT, &inst_.render_buffers.data);
|
||||
|
||||
inst_.bind_uniform_data(&eval_light_ps_);
|
||||
inst_.lights.bind_resources(&eval_light_ps_);
|
||||
inst_.shadows.bind_resources(&eval_light_ps_);
|
||||
inst_.sampling.bind_resources(&eval_light_ps_);
|
||||
inst_.hiz_buffer.bind_resources(&eval_light_ps_);
|
||||
inst_.ambient_occlusion.bind_resources(&eval_light_ps_);
|
||||
inst_.reflection_probes.bind_resources(&eval_light_ps_);
|
||||
inst_.irradiance_cache.bind_resources(&eval_light_ps_);
|
||||
|
||||
|
@ -845,8 +827,9 @@ void CapturePipeline::sync()
|
|||
surface_ps_.bind_ssbo(CAPTURE_BUF_SLOT, &inst_.irradiance_cache.bake.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());
|
||||
/* TODO(fclem): Remove. Binded to get the camera data,
|
||||
* but there should be no view dependent behavior during capture. */
|
||||
inst_.bind_uniform_data(&surface_ps_);
|
||||
}
|
||||
|
||||
PassMain::Sub *CapturePipeline::surface_material_add(GPUMaterial *gpumat)
|
||||
|
|
|
@ -48,7 +48,7 @@ void RayTraceModule::sync()
|
|||
pass.bind_image("tile_mask_img", &tile_mask_tx_);
|
||||
pass.bind_ssbo("ray_dispatch_buf", &ray_dispatch_buf_);
|
||||
pass.bind_ssbo("denoise_dispatch_buf", &denoise_dispatch_buf_);
|
||||
pass.bind_ubo("raytrace_buf", &data_);
|
||||
inst_.bind_uniform_data(&pass);
|
||||
pass.dispatch(&tile_classify_dispatch_size_);
|
||||
pass.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS | GPU_BARRIER_SHADER_STORAGE);
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ void RayTraceModule::sync()
|
|||
pass.bind_ssbo("denoise_dispatch_buf", &denoise_dispatch_buf_);
|
||||
pass.bind_ssbo("ray_tiles_buf", &ray_tiles_buf_);
|
||||
pass.bind_ssbo("denoise_tiles_buf", &denoise_tiles_buf_);
|
||||
pass.bind_ubo("raytrace_buf", &data_);
|
||||
inst_.bind_uniform_data(&pass);
|
||||
pass.dispatch(&tile_compact_dispatch_size_);
|
||||
pass.barrier(GPU_BARRIER_SHADER_STORAGE);
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ void RayTraceModule::sync()
|
|||
pass.bind_image("ray_data_img", &ray_data_tx_);
|
||||
pass.bind_image("ray_time_img", &ray_time_tx_);
|
||||
pass.bind_image("ray_radiance_img", &ray_radiance_tx_);
|
||||
pass.bind_ubo("raytrace_buf", &data_);
|
||||
inst_.bind_uniform_data(&pass);
|
||||
inst_.hiz_buffer.bind_resources(&pass);
|
||||
inst_.sampling.bind_resources(&pass);
|
||||
inst_.reflection_probes.bind_resources(&pass);
|
||||
|
@ -115,7 +115,7 @@ void RayTraceModule::sync()
|
|||
pass.bind_image("out_variance_img", &hit_variance_tx_);
|
||||
pass.bind_image("out_hit_depth_img", &hit_depth_tx_);
|
||||
pass.bind_image("tile_mask_img", &tile_mask_tx_);
|
||||
pass.bind_ubo("raytrace_buf", &data_);
|
||||
inst_.bind_uniform_data(&pass);
|
||||
inst_.sampling.bind_resources(&pass);
|
||||
inst_.hiz_buffer.bind_resources(&pass);
|
||||
pass.dispatch(denoise_dispatch_buf_);
|
||||
|
@ -125,7 +125,7 @@ void RayTraceModule::sync()
|
|||
PassSimple &pass = denoise_temporal_ps_;
|
||||
pass.init();
|
||||
pass.shader_set(inst_.shaders.static_shader_get(RAY_DENOISE_TEMPORAL));
|
||||
pass.bind_ubo("raytrace_buf", &data_);
|
||||
inst_.bind_uniform_data(&pass);
|
||||
pass.bind_texture("radiance_history_tx", &radiance_history_tx_);
|
||||
pass.bind_texture("variance_history_tx", &variance_history_tx_);
|
||||
pass.bind_texture("tilemask_history_tx", &tilemask_history_tx_);
|
||||
|
@ -151,7 +151,7 @@ void RayTraceModule::sync()
|
|||
pass.bind_image("in_variance_img", &denoise_variance_tx_);
|
||||
pass.bind_image("tile_mask_img", &tile_mask_tx_);
|
||||
pass.bind_ssbo("tiles_coord_buf", &denoise_tiles_buf_);
|
||||
pass.bind_ubo("raytrace_buf", &data_);
|
||||
inst_.bind_uniform_data(&pass);
|
||||
inst_.sampling.bind_resources(&pass);
|
||||
inst_.hiz_buffer.bind_resources(&pass);
|
||||
pass.dispatch(denoise_dispatch_buf_);
|
||||
|
@ -248,7 +248,7 @@ RayTraceResult RayTraceModule::trace(RayTraceBuffer &rt_buffer,
|
|||
data_.full_resolution = extent;
|
||||
data_.full_resolution_inv = 1.0f / float2(extent);
|
||||
data_.skip_denoise = !use_spatial_denoise;
|
||||
data_.push_update();
|
||||
inst_.push_uniform_data();
|
||||
|
||||
tile_mask_tx_.acquire(tile_mask_extent, RAYTRACE_TILEMASK_FORMAT);
|
||||
denoise_tiles_buf_.resize(ceil_to_multiple_u(denoise_tile_count, 512));
|
||||
|
|
|
@ -159,10 +159,10 @@ class RayTraceModule {
|
|||
RaytraceEEVEE reflection_options_;
|
||||
RaytraceEEVEE refraction_options_;
|
||||
|
||||
RayTraceDataBuf data_;
|
||||
RayTraceData &data_;
|
||||
|
||||
public:
|
||||
RayTraceModule(Instance &inst) : inst_(inst){};
|
||||
RayTraceModule(Instance &inst, RayTraceData &data) : inst_(inst), data_(data){};
|
||||
|
||||
void init();
|
||||
|
||||
|
|
|
@ -51,7 +51,6 @@ void RenderBuffers::sync()
|
|||
data.ambient_occlusion_id = pass_index_get(EEVEE_RENDER_PASS_AO);
|
||||
|
||||
data.aovs = inst_.film.aovs_info;
|
||||
data.push_update();
|
||||
}
|
||||
|
||||
void RenderBuffers::acquire(int2 extent)
|
||||
|
|
|
@ -22,7 +22,7 @@ class Instance;
|
|||
|
||||
class RenderBuffers {
|
||||
public:
|
||||
UniformBuffer<RenderBuffersInfoData> data;
|
||||
RenderBuffersInfoData &data;
|
||||
|
||||
Texture depth_tx;
|
||||
TextureFromPool combined_tx;
|
||||
|
@ -38,7 +38,7 @@ class RenderBuffers {
|
|||
Instance &inst_;
|
||||
|
||||
public:
|
||||
RenderBuffers(Instance &inst) : inst_(inst){};
|
||||
RenderBuffers(Instance &inst, RenderBuffersInfoData &data) : data(data), inst_(inst){};
|
||||
|
||||
/** WARNING: RenderBuffers and Film use different storage types for AO and Shadow. */
|
||||
static ePassStorageType pass_storage_type(eViewLayerEEVEEPassType pass_type)
|
||||
|
|
|
@ -405,11 +405,14 @@ struct VelocityObjectIndex {
|
|||
BLI_STATIC_ASSERT_ALIGN(VelocityObjectIndex, 16)
|
||||
|
||||
struct VelocityGeometryIndex {
|
||||
/** Offset inside #VelocityGeometryBuf for each timestep. Indexed using eVelocityStep. */
|
||||
/** Offset inside #VelocityGeometryBuf for each time-step. Indexed using eVelocityStep. */
|
||||
packed_int3 ofs;
|
||||
/** If true, compute deformation motion blur. */
|
||||
bool1 do_deform;
|
||||
/** Length of data inside #VelocityGeometryBuf for each timestep. Indexed using eVelocityStep. */
|
||||
/**
|
||||
* Length of data inside #VelocityGeometryBuf for each time-step.
|
||||
* Indexed using eVelocityStep.
|
||||
*/
|
||||
packed_int3 len;
|
||||
|
||||
int _pad0;
|
||||
|
@ -861,9 +864,9 @@ struct ShadowPagesInfoData {
|
|||
int page_alloc_count;
|
||||
/** Index of the next cache page in the cached page buffer. */
|
||||
uint page_cached_next;
|
||||
/** Index of the first page in the buffer since the last defrag. */
|
||||
/** Index of the first page in the buffer since the last defragment. */
|
||||
uint page_cached_start;
|
||||
/** Index of the last page in the buffer since the last defrag. */
|
||||
/** Index of the last page in the buffer since the last defragment. */
|
||||
uint page_cached_end;
|
||||
|
||||
int _pad0;
|
||||
|
@ -1161,6 +1164,9 @@ struct RayTraceData {
|
|||
bool1 skip_denoise;
|
||||
/** Closure being ray-traced. */
|
||||
eClosureBits closure_active;
|
||||
int _pad0;
|
||||
int _pad1;
|
||||
int _pad2;
|
||||
};
|
||||
BLI_STATIC_ASSERT_ALIGN(RayTraceData, 16)
|
||||
|
||||
|
@ -1246,6 +1252,25 @@ BLI_STATIC_ASSERT_ALIGN(ReflectionProbeData, 16)
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Uniform Data
|
||||
* \{ */
|
||||
|
||||
/* Combines data from several modules to avoid wasting binding slots. */
|
||||
struct UniformData {
|
||||
AOData ao;
|
||||
CameraData camera;
|
||||
FilmData film;
|
||||
HiZData hiz;
|
||||
RayTraceData raytrace;
|
||||
RenderBuffersInfoData render_pass;
|
||||
SubsurfaceData subsurface;
|
||||
VolumesInfoData volumes;
|
||||
};
|
||||
BLI_STATIC_ASSERT_ALIGN(UniformData, 16)
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Utility Texture
|
||||
* \{ */
|
||||
|
@ -1310,8 +1335,7 @@ using DepthOfFieldDataBuf = draw::UniformBuffer<DepthOfFieldData>;
|
|||
using DepthOfFieldScatterListBuf = draw::StorageArrayBuffer<ScatterRect, 16, true>;
|
||||
using DrawIndirectBuf = draw::StorageBuffer<DrawCommand, true>;
|
||||
using DispatchIndirectBuf = draw::StorageBuffer<DispatchCommand>;
|
||||
using FilmDataBuf = draw::UniformBuffer<FilmData>;
|
||||
using HiZDataBuf = draw::UniformBuffer<HiZData>;
|
||||
using UniformDataBuf = draw::UniformBuffer<UniformData>;
|
||||
using IrradianceGridDataBuf = draw::UniformArrayBuffer<IrradianceGridData, IRRADIANCE_GRID_MAX>;
|
||||
using IrradianceBrickBuf = draw::StorageVectorBuffer<IrradianceBrickPacked, 16>;
|
||||
using LightCullingDataBuf = draw::StorageBuffer<LightCullingData>;
|
||||
|
@ -1323,7 +1347,6 @@ using LightDataBuf = draw::StorageArrayBuffer<LightData, LIGHT_CHUNK>;
|
|||
using MotionBlurDataBuf = draw::UniformBuffer<MotionBlurData>;
|
||||
using MotionBlurTileIndirectionBuf = draw::StorageBuffer<MotionBlurTileIndirection, true>;
|
||||
using RayTraceTileBuf = draw::StorageArrayBuffer<uint, 1024, true>;
|
||||
using RayTraceDataBuf = draw::UniformBuffer<RayTraceData>;
|
||||
using ReflectionProbeDataBuf =
|
||||
draw::UniformArrayBuffer<ReflectionProbeData, REFLECTION_PROBES_MAX>;
|
||||
using SamplingDataBuf = draw::StorageBuffer<SamplingData>;
|
||||
|
@ -1334,7 +1357,6 @@ 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 SubsurfaceDataBuf = draw::UniformBuffer<SubsurfaceData>;
|
||||
using SurfelBuf = draw::StorageArrayBuffer<Surfel, 64>;
|
||||
using SurfelRadianceBuf = draw::StorageArrayBuffer<SurfelRadiance, 64>;
|
||||
using CaptureInfoBuf = draw::StorageBuffer<CaptureInfoData>;
|
||||
|
@ -1342,9 +1364,7 @@ using SurfelListInfoBuf = draw::StorageBuffer<SurfelListInfoData>;
|
|||
using VelocityGeometryBuf = draw::StorageArrayBuffer<float4, 16, true>;
|
||||
using VelocityIndexBuf = draw::StorageArrayBuffer<VelocityIndex, 16>;
|
||||
using VelocityObjectBuf = draw::StorageArrayBuffer<float4x4, 16>;
|
||||
using VolumesInfoDataBuf = draw::UniformBuffer<VolumesInfoData>;
|
||||
using CryptomatteObjectBuf = draw::StorageArrayBuffer<float2, 16>;
|
||||
using AODataBuf = draw::UniformBuffer<AOData>;
|
||||
|
||||
} // namespace blender::eevee
|
||||
#endif
|
||||
|
|
|
@ -780,6 +780,7 @@ void ShadowModule::begin_sync()
|
|||
sub.push_constant("pixel_world_radius", &pixel_world_radius_);
|
||||
sub.push_constant("fb_resolution", &usage_tag_fb_resolution_);
|
||||
sub.push_constant("fb_lod", &usage_tag_fb_lod_);
|
||||
inst_.bind_uniform_data(&sub);
|
||||
inst_.hiz_buffer.bind_resources(&sub);
|
||||
inst_.lights.bind_resources(&sub);
|
||||
|
||||
|
@ -981,6 +982,7 @@ void ShadowModule::end_sync()
|
|||
sub.bind_ssbo("tilemaps_buf", &tilemap_pool.tilemaps_data);
|
||||
sub.bind_ssbo("tiles_buf", &tilemap_pool.tiles_data);
|
||||
sub.push_constant("tilemap_projection_ratio", &tilemap_projection_ratio_);
|
||||
inst_.bind_uniform_data(&sub);
|
||||
inst_.hiz_buffer.bind_resources(&sub);
|
||||
inst_.sampling.bind_resources(&sub);
|
||||
inst_.lights.bind_resources(&sub);
|
||||
|
@ -1121,6 +1123,7 @@ void ShadowModule::debug_end_sync()
|
|||
debug_draw_ps_.push_constant("debug_tilemap_index", light.tilemap_index);
|
||||
debug_draw_ps_.bind_ssbo("tilemaps_buf", &tilemap_pool.tilemaps_data);
|
||||
debug_draw_ps_.bind_ssbo("tiles_buf", &tilemap_pool.tiles_data);
|
||||
inst_.bind_uniform_data(&debug_draw_ps_);
|
||||
inst_.hiz_buffer.bind_resources(&debug_draw_ps_);
|
||||
inst_.lights.bind_resources(&debug_draw_ps_);
|
||||
inst_.shadows.bind_resources(&debug_draw_ps_);
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
/** \file
|
||||
* \ingroup eevee
|
||||
*
|
||||
*/
|
||||
|
||||
#include "BLI_vector.hh"
|
||||
|
@ -18,7 +17,6 @@ namespace blender::eevee {
|
|||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Subsurface
|
||||
*
|
||||
* \{ */
|
||||
|
||||
void SubsurfaceModule::end_sync()
|
||||
|
@ -33,19 +31,16 @@ void SubsurfaceModule::end_sync()
|
|||
|
||||
precompute_samples_location();
|
||||
|
||||
data_.push_update();
|
||||
|
||||
subsurface_ps_.init();
|
||||
subsurface_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL |
|
||||
DRW_STATE_BLEND_ADD_FULL);
|
||||
subsurface_ps_.state_stencil(0x00u, 0xFFu, CLOSURE_SSS);
|
||||
subsurface_ps_.shader_set(inst_.shaders.static_shader_get(SUBSURFACE_EVAL));
|
||||
inst_.subsurface.bind_resources(&subsurface_ps_);
|
||||
inst_.bind_uniform_data(&subsurface_ps_);
|
||||
inst_.hiz_buffer.bind_resources(&subsurface_ps_);
|
||||
subsurface_ps_.bind_texture("radiance_tx", &diffuse_light_tx_);
|
||||
subsurface_ps_.bind_texture("gbuffer_closure_tx", &inst_.gbuffer.closure_tx);
|
||||
subsurface_ps_.bind_texture("gbuffer_color_tx", &inst_.gbuffer.color_tx);
|
||||
subsurface_ps_.bind_ubo(RBUFS_BUF_SLOT, &inst_.render_buffers.data);
|
||||
subsurface_ps_.bind_image(RBUFS_COLOR_SLOT, &inst_.render_buffers.rp_color_tx);
|
||||
/** NOTE: Not used in the shader, but we bind it to avoid debug warnings. */
|
||||
subsurface_ps_.bind_image(RBUFS_VALUE_SLOT, &inst_.render_buffers.rp_value_tx);
|
||||
|
|
|
@ -34,14 +34,14 @@ struct SubsurfaceModule {
|
|||
private:
|
||||
Instance &inst_;
|
||||
/** Contains samples locations. */
|
||||
SubsurfaceDataBuf data_;
|
||||
SubsurfaceData &data_;
|
||||
/** Scene diffuse irradiance. Pointer binded at sync time, set at render time. */
|
||||
GPUTexture *diffuse_light_tx_;
|
||||
/** Subsurface eval pass. Runs after the deferred pass. */
|
||||
PassSimple subsurface_ps_ = {"Subsurface"};
|
||||
|
||||
public:
|
||||
SubsurfaceModule(Instance &inst) : inst_(inst)
|
||||
SubsurfaceModule(Instance &inst, SubsurfaceData &data) : inst_(inst), data_(data)
|
||||
{
|
||||
/* Force first update. */
|
||||
data_.sample_len = -1;
|
||||
|
@ -56,11 +56,6 @@ struct SubsurfaceModule {
|
|||
|
||||
void render(View &view, Framebuffer &fb, Texture &diffuse_light_tx);
|
||||
|
||||
template<typename T> void bind_resources(draw::detail::PassBase<T> *pass)
|
||||
{
|
||||
pass->bind_ubo("sss_buf", data_);
|
||||
}
|
||||
|
||||
private:
|
||||
void precompute_samples_location();
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
* Volumetric effects rendering using Frostbite's Physically-based & Unified Volumetric Rendering
|
||||
* approach.
|
||||
* https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite
|
||||
*
|
||||
*/
|
||||
|
||||
#include "DNA_volume_types.h"
|
||||
|
@ -23,7 +22,7 @@
|
|||
|
||||
namespace blender::eevee {
|
||||
|
||||
bool VolumeModule::GridAABB::init(Object *ob, const Camera &camera, const VolumesInfoDataBuf &data)
|
||||
bool VolumeModule::GridAABB::init(Object *ob, const Camera &camera, const VolumesInfoData &data)
|
||||
{
|
||||
/* Returns the unified volume grid cell index of a world space coordinate. */
|
||||
auto to_global_grid_coords = [&](float3 wP) -> int3 {
|
||||
|
@ -150,8 +149,6 @@ void VolumeModule::begin_sync()
|
|||
data_.depth_distribution = 1.0f / (integration_end - integration_start);
|
||||
}
|
||||
|
||||
data_.push_update();
|
||||
|
||||
enabled_ = inst_.world.has_volume();
|
||||
}
|
||||
|
||||
|
@ -273,7 +270,7 @@ void VolumeModule::end_sync()
|
|||
|
||||
integration_ps_.init();
|
||||
integration_ps_.shader_set(inst_.shaders.static_shader_get(VOLUME_INTEGRATION));
|
||||
integration_ps_.bind_ubo(VOLUMES_INFO_BUF_SLOT, data_);
|
||||
inst_.bind_uniform_data(&integration_ps_);
|
||||
integration_ps_.bind_texture("in_scattering_tx", &scatter_tx_);
|
||||
integration_ps_.bind_texture("in_extinction_tx", &extinction_tx_);
|
||||
integration_ps_.bind_image("out_scattering_img", &integrated_scatter_tx_);
|
||||
|
@ -286,9 +283,9 @@ void VolumeModule::end_sync()
|
|||
resolve_ps_.init();
|
||||
resolve_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM);
|
||||
resolve_ps_.shader_set(inst_.shaders.static_shader_get(VOLUME_RESOLVE));
|
||||
inst_.bind_uniform_data(&resolve_ps_);
|
||||
bind_resources(resolve_ps_);
|
||||
resolve_ps_.bind_texture("depth_tx", &inst_.render_buffers.depth_tx);
|
||||
resolve_ps_.bind_ubo(RBUFS_BUF_SLOT, &inst_.render_buffers.data);
|
||||
resolve_ps_.bind_image(RBUFS_COLOR_SLOT, &inst_.render_buffers.rp_color_tx);
|
||||
/* Sync with the integration pass. */
|
||||
resolve_ps_.barrier(GPU_BARRIER_TEXTURE_FETCH);
|
||||
|
|
|
@ -47,7 +47,7 @@ class VolumeModule {
|
|||
|
||||
bool enabled_;
|
||||
|
||||
VolumesInfoDataBuf data_;
|
||||
VolumesInfoData &data_;
|
||||
|
||||
/* Material Parameters */
|
||||
Texture prop_scattering_tx_;
|
||||
|
@ -82,7 +82,7 @@ class VolumeModule {
|
|||
int3 min, max;
|
||||
|
||||
/* Returns true if visible. */
|
||||
bool init(Object *ob, const Camera &camera, const VolumesInfoDataBuf &data);
|
||||
bool init(Object *ob, const Camera &camera, const VolumesInfoData &data);
|
||||
|
||||
bool overlaps(const GridAABB &aabb);
|
||||
};
|
||||
|
@ -92,7 +92,7 @@ class VolumeModule {
|
|||
Map<GPUShader *, Vector<GridAABB>> subpass_aabbs_;
|
||||
|
||||
public:
|
||||
VolumeModule(Instance &inst) : inst_(inst)
|
||||
VolumeModule(Instance &inst, VolumesInfoData &data) : inst_(inst), data_(data)
|
||||
{
|
||||
dummy_scatter_tx_.ensure_3d(GPU_RGBA8, int3(1), GPU_TEXTURE_USAGE_SHADER_READ, float4(0.0f));
|
||||
dummy_transmit_tx_.ensure_3d(GPU_RGBA8, int3(1), GPU_TEXTURE_USAGE_SHADER_READ, float4(1.0f));
|
||||
|
@ -103,7 +103,6 @@ class VolumeModule {
|
|||
/* Bind resources needed by external passes to perform their own resolve. */
|
||||
template<typename PassType> void bind_resources(PassType &ps)
|
||||
{
|
||||
ps.bind_ubo(VOLUMES_INFO_BUF_SLOT, data_);
|
||||
ps.bind_texture(VOLUME_SCATTERING_TEX_SLOT, &transparent_pass_scatter_tx_);
|
||||
ps.bind_texture(VOLUME_TRANSMITTANCE_TEX_SLOT, &transparent_pass_transmit_tx_);
|
||||
}
|
||||
|
@ -111,7 +110,6 @@ class VolumeModule {
|
|||
/* Bind the common resources needed by all volumetric passes. */
|
||||
template<typename PassType> void bind_properties_buffers(PassType &ps)
|
||||
{
|
||||
ps.bind_ubo(VOLUMES_INFO_BUF_SLOT, &data_);
|
||||
ps.bind_image(VOLUME_PROP_SCATTERING_IMG_SLOT, &prop_scattering_tx_);
|
||||
ps.bind_image(VOLUME_PROP_EXTINCTION_IMG_SLOT, &prop_extinction_tx_);
|
||||
ps.bind_image(VOLUME_PROP_EMISSION_IMG_SLOT, &prop_emission_tx_);
|
||||
|
|
|
@ -102,10 +102,10 @@ float ambient_ambient_occlusion_search_horizon(vec3 vI,
|
|||
/* Gives us good precision at center and ensure we cross at least one pixel per iteration. */
|
||||
time = 1.0 + iter + sqr((iter + noise) / sample_count) * ssray.max_time;
|
||||
float stride = time - prev_time;
|
||||
float lod = (log2(stride) - noise) / (1.0 + ao_buf.quality);
|
||||
float lod = (log2(stride) - noise) / (1.0 + uniform_buf.ao.quality);
|
||||
|
||||
vec2 uv = ssray.origin.xy + ssray.direction.xy * time;
|
||||
float depth = textureLod(depth_tx, uv * hiz_buf.uv_scale, floor(lod)).r;
|
||||
float depth = textureLod(depth_tx, uv * uniform_buf.hiz.uv_scale, floor(lod)).r;
|
||||
|
||||
if (depth == 1.0 && inverted == 0.0) {
|
||||
/* Skip background. Avoids making shadow on the geometry near the far plane. */
|
||||
|
@ -163,13 +163,13 @@ OcclusionData ambient_occlusion_search(vec3 vP,
|
|||
|
||||
ScreenSpaceRay ssray;
|
||||
|
||||
ssray = raytrace_screenspace_ray_create(ray, ao_buf.pixel_size);
|
||||
ssray = raytrace_screenspace_ray_create(ray, uniform_buf.ao.pixel_size);
|
||||
data.horizons[0 + i * 2] = ambient_ambient_occlusion_search_horizon(
|
||||
vI, vP, noise.y, ssray, depth_tx, inverted, radius, dir_sample_count);
|
||||
|
||||
ray.direction = -ray.direction;
|
||||
|
||||
ssray = raytrace_screenspace_ray_create(ray, ao_buf.pixel_size);
|
||||
ssray = raytrace_screenspace_ray_create(ray, uniform_buf.ao.pixel_size);
|
||||
data.horizons[1 + i * 2] = -ambient_ambient_occlusion_search_horizon(
|
||||
vI, vP, noise.y, ssray, depth_tx, inverted, radius, dir_sample_count);
|
||||
|
||||
|
|
|
@ -81,7 +81,8 @@ void main()
|
|||
vec3 Ng = transform_direction(ViewMatrixInverse, vNg);
|
||||
vec3 N = imageLoad(in_normal_img, ivec3(texel, in_normal_img_layer_index)).xyz;
|
||||
|
||||
OcclusionData data = ambient_occlusion_search(vP, hiz_tx, texel, ao_buf.distance, 0.0, 8.0);
|
||||
OcclusionData data = ambient_occlusion_search(
|
||||
vP, hiz_tx, texel, uniform_buf.ao.distance, 0.0, 8.0);
|
||||
|
||||
float visibility;
|
||||
float visibility_error_out;
|
||||
|
|
|
@ -45,7 +45,7 @@ void cryptomatte_store_film_sample(FilmSample dst,
|
|||
if (crypto_sample.y == 0.0) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < film_buf.cryptomatte_samples_len / 2; i++) {
|
||||
for (int i = 0; i < uniform_buf.film.cryptomatte_samples_len / 2; i++) {
|
||||
ivec3 img_co = ivec3(dst.texel, cryptomatte_layer_id + i);
|
||||
vec4 sample_pair = imageLoad(cryptomatte_img, img_co);
|
||||
if (cryptomatte_can_merge_sample(sample_pair.xy, crypto_sample)) {
|
||||
|
@ -60,7 +60,7 @@ void cryptomatte_store_film_sample(FilmSample dst,
|
|||
else if (cryptomatte_can_merge_sample(sample_pair.zw, crypto_sample)) {
|
||||
sample_pair.zw = cryptomatte_merge_sample(sample_pair.zw, crypto_sample);
|
||||
}
|
||||
else if (i == film_buf.cryptomatte_samples_len / 2 - 1) {
|
||||
else if (i == uniform_buf.film.cryptomatte_samples_len / 2 - 1) {
|
||||
/* TODO(jbakker): New hash detected, but there is no space left to store it. Currently we
|
||||
* will ignore this sample, but ideally we could replace a sample with a lowest weight. */
|
||||
continue;
|
||||
|
|
|
@ -91,15 +91,19 @@ void main()
|
|||
diffuse_data.color = is_refraction ? vec3(0.0) : gbuffer_color_unpack(color_1_packed);
|
||||
|
||||
/* Light passes. */
|
||||
if (rp_buf.diffuse_light_id >= 0) {
|
||||
imageStore(rp_color_img, ivec3(texel, rp_buf.diffuse_light_id), vec4(diffuse_light, 1.0));
|
||||
if (uniform_buf.render_pass.diffuse_light_id >= 0) {
|
||||
imageStore(rp_color_img,
|
||||
ivec3(texel, uniform_buf.render_pass.diffuse_light_id),
|
||||
vec4(diffuse_light, 1.0));
|
||||
}
|
||||
if (rp_buf.specular_light_id >= 0) {
|
||||
if (uniform_buf.render_pass.specular_light_id >= 0) {
|
||||
vec3 specular_light = reflection_light + refraction_light;
|
||||
imageStore(rp_color_img, ivec3(texel, rp_buf.specular_light_id), vec4(specular_light, 1.0));
|
||||
imageStore(rp_color_img,
|
||||
ivec3(texel, uniform_buf.render_pass.specular_light_id),
|
||||
vec4(specular_light, 1.0));
|
||||
}
|
||||
if (rp_buf.shadow_id >= 0) {
|
||||
imageStore(rp_value_img, ivec3(texel, rp_buf.shadow_id), vec4(shadow));
|
||||
if (uniform_buf.render_pass.shadow_id >= 0) {
|
||||
imageStore(rp_value_img, ivec3(texel, uniform_buf.render_pass.shadow_id), vec4(shadow));
|
||||
}
|
||||
|
||||
if (!is_last_eval_pass) {
|
||||
|
|
|
@ -249,9 +249,9 @@ DofSample dof_sample_history(vec2 input_texel)
|
|||
|
||||
/* Slide 92. */
|
||||
vec2 weight_12 = weights[1] + weights[2];
|
||||
vec2 uv_12 = (center_texel + weights[2] / weight_12) * film_buf.extent_inv;
|
||||
vec2 uv_0 = (center_texel - 1.0) * film_buf.extent_inv;
|
||||
vec2 uv_3 = (center_texel + 2.0) * film_buf.extent_inv;
|
||||
vec2 uv_12 = (center_texel + weights[2] / weight_12) * uniform_buf.film.extent_inv;
|
||||
vec2 uv_0 = (center_texel - 1.0) * uniform_buf.film.extent_inv;
|
||||
vec2 uv_3 = (center_texel + 2.0) * uniform_buf.film.extent_inv;
|
||||
|
||||
vec4 color;
|
||||
vec4 weight_cross = weight_12.xyyx * vec4(weights[0].yx, weights[3].xy);
|
||||
|
|
|
@ -7,25 +7,26 @@
|
|||
|
||||
void main()
|
||||
{
|
||||
ivec2 texel_film = ivec2(gl_FragCoord.xy) - film_buf.offset;
|
||||
ivec2 texel_film = ivec2(gl_FragCoord.xy) - uniform_buf.film.offset;
|
||||
float out_depth;
|
||||
|
||||
if (film_buf.display_only) {
|
||||
if (uniform_buf.film.display_only) {
|
||||
out_depth = imageLoad(depth_img, texel_film).r;
|
||||
|
||||
if (film_buf.display_id == -1) {
|
||||
if (uniform_buf.film.display_id == -1) {
|
||||
out_color = texelFetch(in_combined_tx, texel_film, 0);
|
||||
}
|
||||
else if (film_buf.display_storage_type == PASS_STORAGE_VALUE) {
|
||||
out_color.rgb = imageLoad(value_accum_img, ivec3(texel_film, film_buf.display_id)).rrr;
|
||||
else if (uniform_buf.film.display_storage_type == PASS_STORAGE_VALUE) {
|
||||
out_color.rgb =
|
||||
imageLoad(value_accum_img, ivec3(texel_film, uniform_buf.film.display_id)).rrr;
|
||||
out_color.a = 1.0;
|
||||
}
|
||||
else if (film_buf.display_storage_type == PASS_STORAGE_COLOR) {
|
||||
out_color = imageLoad(color_accum_img, ivec3(texel_film, film_buf.display_id));
|
||||
else if (uniform_buf.film.display_storage_type == PASS_STORAGE_COLOR) {
|
||||
out_color = imageLoad(color_accum_img, ivec3(texel_film, uniform_buf.film.display_id));
|
||||
}
|
||||
else /* PASS_STORAGE_CRYPTOMATTE */ {
|
||||
out_color = cryptomatte_false_color(
|
||||
imageLoad(cryptomatte_img, ivec3(texel_film, film_buf.display_id)).r);
|
||||
imageLoad(cryptomatte_img, ivec3(texel_film, uniform_buf.film.display_id)).r);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -39,7 +39,7 @@ float film_luma_weight(float luma)
|
|||
{
|
||||
/* Slide 20 of "High Quality Temporal Supersampling" by Brian Karis at Siggraph 2014. */
|
||||
/* To preserve more details in dark areas, we use a bigger bias. */
|
||||
return 1.0 / (4.0 + luma * film_buf.exposure_scale);
|
||||
return 1.0 / (4.0 + luma * uniform_buf.film.exposure_scale);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -55,21 +55,22 @@ FilmSample film_sample_get(int sample_n, ivec2 texel_film)
|
|||
#else
|
||||
|
||||
# ifdef SCALED_RENDERING
|
||||
texel_film /= film_buf.scaling_factor;
|
||||
texel_film /= uniform_buf.film.scaling_factor;
|
||||
# endif
|
||||
|
||||
FilmSample film_sample = film_buf.samples[sample_n];
|
||||
film_sample.texel += texel_film + film_buf.render_offset;
|
||||
FilmSample film_sample = uniform_buf.film.samples[sample_n];
|
||||
film_sample.texel += texel_film + uniform_buf.film.render_offset;
|
||||
/* Use extend on borders. */
|
||||
film_sample.texel = clamp(film_sample.texel, ivec2(0, 0), film_buf.render_extent - 1);
|
||||
film_sample.texel = clamp(film_sample.texel, ivec2(0, 0), uniform_buf.film.render_extent - 1);
|
||||
|
||||
/* TODO(fclem): Panoramic projection will need to compute the sample weight in the shader
|
||||
* instead of precomputing it on CPU. */
|
||||
# ifdef SCALED_RENDERING
|
||||
/* We need to compute the real distance and weight since a sample
|
||||
* can be used by many final pixel. */
|
||||
vec2 offset = film_buf.subpixel_offset - vec2(texel_film % film_buf.scaling_factor);
|
||||
film_sample.weight = film_filter_weight(film_buf.filter_size, len_squared(offset));
|
||||
vec2 offset = uniform_buf.film.subpixel_offset -
|
||||
vec2(texel_film % uniform_buf.film.scaling_factor);
|
||||
film_sample.weight = film_filter_weight(uniform_buf.film.filter_size, len_squared(offset));
|
||||
# endif
|
||||
|
||||
#endif /* PANORAMIC */
|
||||
|
@ -85,12 +86,12 @@ float film_weight_accumulation(ivec2 texel_film)
|
|||
{
|
||||
#if 0 /* TODO(fclem): Reference implementation, also needed for panoramic cameras. */
|
||||
float weight = 0.0;
|
||||
for (int i = 0; i < film_buf.samples_len; i++) {
|
||||
for (int i = 0; i < uniform_buf.film.samples_len; i++) {
|
||||
weight += film_sample_get(i, texel_film).weight;
|
||||
}
|
||||
return weight;
|
||||
#endif
|
||||
return film_buf.samples_weight_total;
|
||||
return uniform_buf.film.samples_weight_total;
|
||||
}
|
||||
|
||||
void film_sample_accum(
|
||||
|
@ -113,7 +114,7 @@ void film_sample_accum(
|
|||
|
||||
void film_sample_accum_mist(FilmSample samp, inout float accum)
|
||||
{
|
||||
if (film_buf.mist_id == -1) {
|
||||
if (uniform_buf.film.mist_id == -1) {
|
||||
return;
|
||||
}
|
||||
float depth = texelFetch(depth_tx, samp.texel, 0).x;
|
||||
|
@ -122,15 +123,15 @@ void film_sample_accum_mist(FilmSample samp, inout float accum)
|
|||
bool is_persp = ProjectionMatrix[3][3] == 0.0;
|
||||
float mist = (is_persp) ? length(vP) : abs(vP.z);
|
||||
/* Remap to 0..1 range. */
|
||||
mist = saturate(mist * film_buf.mist_scale + film_buf.mist_bias);
|
||||
mist = saturate(mist * uniform_buf.film.mist_scale + uniform_buf.film.mist_bias);
|
||||
/* Falloff. */
|
||||
mist = pow(mist, film_buf.mist_exponent);
|
||||
mist = pow(mist, uniform_buf.film.mist_exponent);
|
||||
accum += mist * samp.weight;
|
||||
}
|
||||
|
||||
void film_sample_accum_combined(FilmSample samp, inout vec4 accum, inout float weight_accum)
|
||||
{
|
||||
if (film_buf.combined_id == -1) {
|
||||
if (uniform_buf.film.combined_id == -1) {
|
||||
return;
|
||||
}
|
||||
vec4 color = film_texelfetch_as_YCoCg_opacity(combined_tx, samp.texel);
|
||||
|
@ -179,7 +180,7 @@ void film_cryptomatte_layer_accum_and_store(
|
|||
}
|
||||
/* x = hash, y = accumulated weight. Only keep track of 4 highest weighted samples. */
|
||||
vec2 crypto_samples[4] = vec2[4](vec2(0.0), vec2(0.0), vec2(0.0), vec2(0.0));
|
||||
for (int i = 0; i < film_buf.samples_len; i++) {
|
||||
for (int i = 0; i < uniform_buf.film.samples_len; i++) {
|
||||
FilmSample src = film_sample_get(i, texel_film);
|
||||
film_sample_cryptomatte_accum(src, layer_component, cryptomatte_tx, crypto_samples);
|
||||
}
|
||||
|
@ -200,7 +201,7 @@ float film_distance_load(ivec2 texel)
|
|||
/* Repeat texture coordinates as the weight can be optimized to a small portion of the film. */
|
||||
texel = texel % imageSize(in_weight_img).xy;
|
||||
|
||||
if (!film_buf.use_history || film_buf.use_reprojection) {
|
||||
if (!uniform_buf.film.use_history || uniform_buf.film.use_reprojection) {
|
||||
return 1.0e16;
|
||||
}
|
||||
return imageLoad(in_weight_img, ivec3(texel, FILM_WEIGHT_LAYER_DISTANCE)).x;
|
||||
|
@ -211,7 +212,7 @@ float film_weight_load(ivec2 texel)
|
|||
/* Repeat texture coordinates as the weight can be optimized to a small portion of the film. */
|
||||
texel = texel % imageSize(in_weight_img).xy;
|
||||
|
||||
if (!film_buf.use_history || film_buf.use_reprojection) {
|
||||
if (!uniform_buf.film.use_history || uniform_buf.film.use_reprojection) {
|
||||
return 0.0;
|
||||
}
|
||||
return imageLoad(in_weight_img, ivec3(texel, FILM_WEIGHT_LAYER_ACCUMULATION)).x;
|
||||
|
@ -239,7 +240,7 @@ vec2 film_pixel_history_motion_vector(ivec2 texel_sample)
|
|||
vec4 vector = velocity_resolve(vector_tx, nearest_texel, min_depth);
|
||||
|
||||
/* Transform to pixel space. */
|
||||
vector.xy *= vec2(film_buf.extent);
|
||||
vector.xy *= vec2(uniform_buf.film.extent);
|
||||
|
||||
return vector.xy;
|
||||
}
|
||||
|
@ -297,9 +298,9 @@ vec4 film_sample_catmull_rom(sampler2D color_tx, vec2 input_texel)
|
|||
|
||||
/* Slide 92. */
|
||||
vec2 weight_12 = weights[1] + weights[2];
|
||||
vec2 uv_12 = (center_texel + weights[2] / weight_12) * film_buf.extent_inv;
|
||||
vec2 uv_0 = (center_texel - 1.0) * film_buf.extent_inv;
|
||||
vec2 uv_3 = (center_texel + 2.0) * film_buf.extent_inv;
|
||||
vec2 uv_12 = (center_texel + weights[2] / weight_12) * uniform_buf.film.extent_inv;
|
||||
vec2 uv_0 = (center_texel - 1.0) * uniform_buf.film.extent_inv;
|
||||
vec2 uv_3 = (center_texel + 2.0) * uniform_buf.film.extent_inv;
|
||||
|
||||
vec4 color;
|
||||
vec4 weight_cross = weight_12.xyyx * vec4(weights[0].yx, weights[3].xy);
|
||||
|
@ -430,11 +431,12 @@ float film_history_blend_factor(float velocity,
|
|||
/* Linearly blend when history gets below to 25% of the bbox size. */
|
||||
blend *= saturate(distance_to_luma_clip * 4.0 + 0.1);
|
||||
/* Discard out of view history. */
|
||||
if (any(lessThan(texel, vec2(0))) || any(greaterThanEqual(texel, vec2(film_buf.extent)))) {
|
||||
if (any(lessThan(texel, vec2(0))) || any(greaterThanEqual(texel, vec2(uniform_buf.film.extent))))
|
||||
{
|
||||
blend = 1.0;
|
||||
}
|
||||
/* Discard history if invalid. */
|
||||
if (film_buf.use_history == false) {
|
||||
if (uniform_buf.film.use_history == false) {
|
||||
blend = 1.0;
|
||||
}
|
||||
return blend;
|
||||
|
@ -444,7 +446,7 @@ float film_history_blend_factor(float velocity,
|
|||
void film_store_combined(
|
||||
FilmSample dst, ivec2 src_texel, vec4 color, float color_weight, inout vec4 display)
|
||||
{
|
||||
if (film_buf.combined_id == -1) {
|
||||
if (uniform_buf.film.combined_id == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -454,7 +456,7 @@ void film_store_combined(
|
|||
/* Undo the weighting to get final spatially-filtered color. */
|
||||
color_src = color / color_weight;
|
||||
|
||||
if (film_buf.use_reprojection) {
|
||||
if (uniform_buf.film.use_reprojection) {
|
||||
/* Interactive accumulation. Do reprojection and Temporal Anti-Aliasing. */
|
||||
|
||||
/* Reproject by finding where this pixel was in the previous frame. */
|
||||
|
@ -507,7 +509,7 @@ void film_store_combined(
|
|||
color = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
if (film_buf.display_id == -1) {
|
||||
if (uniform_buf.film.display_id == -1) {
|
||||
display = color;
|
||||
}
|
||||
imageStore(out_combined_img, dst.texel, color);
|
||||
|
@ -528,7 +530,7 @@ void film_store_color(FilmSample dst, int pass_id, vec4 color, inout vec4 displa
|
|||
color = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
if (film_buf.display_id == pass_id) {
|
||||
if (uniform_buf.film.display_id == pass_id) {
|
||||
display = color;
|
||||
}
|
||||
imageStore(color_accum_img, ivec3(dst.texel, pass_id), color);
|
||||
|
@ -549,7 +551,7 @@ void film_store_value(FilmSample dst, int pass_id, float value, inout vec4 displ
|
|||
value = 0.0;
|
||||
}
|
||||
|
||||
if (film_buf.display_id == pass_id) {
|
||||
if (uniform_buf.film.display_id == pass_id) {
|
||||
display = vec4(value, value, value, 1.0);
|
||||
}
|
||||
imageStore(value_accum_img, ivec3(dst.texel, pass_id), vec4(value));
|
||||
|
@ -562,7 +564,7 @@ void film_store_data(ivec2 texel_film, int pass_id, vec4 data_sample, inout vec4
|
|||
return;
|
||||
}
|
||||
|
||||
if (film_buf.display_id == pass_id) {
|
||||
if (uniform_buf.film.display_id == pass_id) {
|
||||
display = data_sample;
|
||||
}
|
||||
imageStore(color_accum_img, ivec3(texel_film, pass_id), data_sample);
|
||||
|
@ -570,7 +572,7 @@ void film_store_data(ivec2 texel_film, int pass_id, vec4 data_sample, inout vec4
|
|||
|
||||
void film_store_depth(ivec2 texel_film, float value, out float out_depth)
|
||||
{
|
||||
if (film_buf.depth_id == -1) {
|
||||
if (uniform_buf.film.depth_id == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -624,13 +626,13 @@ void film_process_data(ivec2 texel_film, out vec4 out_color, out float out_depth
|
|||
/* NOTE: We split the accumulations into separate loops to avoid using too much registers and
|
||||
* maximize occupancy. */
|
||||
|
||||
if (film_buf.combined_id != -1) {
|
||||
if (uniform_buf.film.combined_id != -1) {
|
||||
/* NOTE: Do weight accumulation again since we use custom weights. */
|
||||
float weight_accum = 0.0;
|
||||
vec4 combined_accum = vec4(0.0);
|
||||
|
||||
FilmSample src;
|
||||
for (int i = film_buf.samples_len - 1; i >= 0; i--) {
|
||||
for (int i = uniform_buf.film.samples_len - 1; i >= 0; i--) {
|
||||
src = film_sample_get(i, texel_film);
|
||||
film_sample_accum_combined(src, combined_accum, weight_accum);
|
||||
}
|
||||
|
@ -638,62 +640,70 @@ void film_process_data(ivec2 texel_film, out vec4 out_color, out float out_depth
|
|||
film_store_combined(dst, src.texel, combined_accum, weight_accum, out_color);
|
||||
}
|
||||
|
||||
if (film_buf.has_data) {
|
||||
if (uniform_buf.film.has_data) {
|
||||
float film_distance = film_distance_load(texel_film);
|
||||
|
||||
/* Get sample closest to target texel. It is always sample 0. */
|
||||
FilmSample film_sample = film_sample_get(0, texel_film);
|
||||
|
||||
if (film_buf.use_reprojection || film_sample.weight < film_distance) {
|
||||
vec4 normal = texelFetch(rp_color_tx, ivec3(film_sample.texel, rp_buf.normal_id), 0);
|
||||
if (uniform_buf.film.use_reprojection || film_sample.weight < film_distance) {
|
||||
vec4 normal = texelFetch(
|
||||
rp_color_tx, ivec3(film_sample.texel, uniform_buf.render_pass.normal_id), 0);
|
||||
float depth = texelFetch(depth_tx, film_sample.texel, 0).x;
|
||||
vec4 vector = velocity_resolve(vector_tx, film_sample.texel, depth);
|
||||
/* Transform to pixel space. */
|
||||
vector *= vec4(vec2(film_buf.render_extent), -vec2(film_buf.render_extent));
|
||||
vector *= vec4(vec2(uniform_buf.film.render_extent), -vec2(uniform_buf.film.render_extent));
|
||||
|
||||
film_store_depth(texel_film, depth, out_depth);
|
||||
film_store_data(texel_film, film_buf.normal_id, normal, out_color);
|
||||
film_store_data(texel_film, film_buf.vector_id, vector, out_color);
|
||||
film_store_data(texel_film, uniform_buf.film.normal_id, normal, out_color);
|
||||
film_store_data(texel_film, uniform_buf.film.vector_id, vector, out_color);
|
||||
film_store_distance(texel_film, film_sample.weight);
|
||||
}
|
||||
else {
|
||||
out_depth = imageLoad(depth_img, texel_film).r;
|
||||
if (film_buf.display_id != -1 && film_buf.display_id == film_buf.normal_id) {
|
||||
out_color = imageLoad(color_accum_img, ivec3(texel_film, film_buf.display_id));
|
||||
if (uniform_buf.film.display_id != -1 &&
|
||||
uniform_buf.film.display_id == uniform_buf.film.normal_id) {
|
||||
out_color = imageLoad(color_accum_img, ivec3(texel_film, uniform_buf.film.display_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (film_buf.any_render_pass_1) {
|
||||
if (uniform_buf.film.any_render_pass_1) {
|
||||
vec4 diffuse_light_accum = vec4(0.0);
|
||||
vec4 specular_light_accum = vec4(0.0);
|
||||
vec4 volume_light_accum = vec4(0.0);
|
||||
vec4 emission_accum = vec4(0.0);
|
||||
|
||||
for (int i = 0; i < film_buf.samples_len; i++) {
|
||||
for (int i = 0; i < uniform_buf.film.samples_len; i++) {
|
||||
FilmSample src = film_sample_get(i, texel_film);
|
||||
film_sample_accum(src,
|
||||
film_buf.diffuse_light_id,
|
||||
rp_buf.diffuse_light_id,
|
||||
uniform_buf.film.diffuse_light_id,
|
||||
uniform_buf.render_pass.diffuse_light_id,
|
||||
rp_color_tx,
|
||||
diffuse_light_accum);
|
||||
film_sample_accum(src,
|
||||
film_buf.specular_light_id,
|
||||
rp_buf.specular_light_id,
|
||||
uniform_buf.film.specular_light_id,
|
||||
uniform_buf.render_pass.specular_light_id,
|
||||
rp_color_tx,
|
||||
specular_light_accum);
|
||||
film_sample_accum(
|
||||
src, film_buf.volume_light_id, rp_buf.volume_light_id, rp_color_tx, volume_light_accum);
|
||||
film_sample_accum(
|
||||
src, film_buf.emission_id, rp_buf.emission_id, rp_color_tx, emission_accum);
|
||||
film_sample_accum(src,
|
||||
uniform_buf.film.volume_light_id,
|
||||
uniform_buf.render_pass.volume_light_id,
|
||||
rp_color_tx,
|
||||
volume_light_accum);
|
||||
film_sample_accum(src,
|
||||
uniform_buf.film.emission_id,
|
||||
uniform_buf.render_pass.emission_id,
|
||||
rp_color_tx,
|
||||
emission_accum);
|
||||
}
|
||||
film_store_color(dst, film_buf.diffuse_light_id, diffuse_light_accum, out_color);
|
||||
film_store_color(dst, film_buf.specular_light_id, specular_light_accum, out_color);
|
||||
film_store_color(dst, film_buf.volume_light_id, volume_light_accum, out_color);
|
||||
film_store_color(dst, film_buf.emission_id, emission_accum, out_color);
|
||||
film_store_color(dst, uniform_buf.film.diffuse_light_id, diffuse_light_accum, out_color);
|
||||
film_store_color(dst, uniform_buf.film.specular_light_id, specular_light_accum, out_color);
|
||||
film_store_color(dst, uniform_buf.film.volume_light_id, volume_light_accum, out_color);
|
||||
film_store_color(dst, uniform_buf.film.emission_id, emission_accum, out_color);
|
||||
}
|
||||
|
||||
if (film_buf.any_render_pass_2) {
|
||||
if (uniform_buf.film.any_render_pass_2) {
|
||||
vec4 diffuse_color_accum = vec4(0.0);
|
||||
vec4 specular_color_accum = vec4(0.0);
|
||||
vec4 environment_accum = vec4(0.0);
|
||||
|
@ -701,64 +711,75 @@ void film_process_data(ivec2 texel_film, out vec4 out_color, out float out_depth
|
|||
float shadow_accum = 0.0;
|
||||
float ao_accum = 0.0;
|
||||
|
||||
for (int i = 0; i < film_buf.samples_len; i++) {
|
||||
for (int i = 0; i < uniform_buf.film.samples_len; i++) {
|
||||
FilmSample src = film_sample_get(i, texel_film);
|
||||
film_sample_accum(src,
|
||||
film_buf.diffuse_color_id,
|
||||
rp_buf.diffuse_color_id,
|
||||
uniform_buf.film.diffuse_color_id,
|
||||
uniform_buf.render_pass.diffuse_color_id,
|
||||
rp_color_tx,
|
||||
diffuse_color_accum);
|
||||
film_sample_accum(src,
|
||||
film_buf.specular_color_id,
|
||||
rp_buf.specular_color_id,
|
||||
uniform_buf.film.specular_color_id,
|
||||
uniform_buf.render_pass.specular_color_id,
|
||||
rp_color_tx,
|
||||
specular_color_accum);
|
||||
film_sample_accum(
|
||||
src, film_buf.environment_id, rp_buf.environment_id, rp_color_tx, environment_accum);
|
||||
film_sample_accum(src, film_buf.shadow_id, rp_buf.shadow_id, rp_value_tx, shadow_accum);
|
||||
film_sample_accum(
|
||||
src, film_buf.ambient_occlusion_id, rp_buf.ambient_occlusion_id, rp_value_tx, ao_accum);
|
||||
film_sample_accum(src,
|
||||
uniform_buf.film.environment_id,
|
||||
uniform_buf.render_pass.environment_id,
|
||||
rp_color_tx,
|
||||
environment_accum);
|
||||
film_sample_accum(src,
|
||||
uniform_buf.film.shadow_id,
|
||||
uniform_buf.render_pass.shadow_id,
|
||||
rp_value_tx,
|
||||
shadow_accum);
|
||||
film_sample_accum(src,
|
||||
uniform_buf.film.ambient_occlusion_id,
|
||||
uniform_buf.render_pass.ambient_occlusion_id,
|
||||
rp_value_tx,
|
||||
ao_accum);
|
||||
film_sample_accum_mist(src, mist_accum);
|
||||
}
|
||||
film_store_color(dst, film_buf.diffuse_color_id, diffuse_color_accum, out_color);
|
||||
film_store_color(dst, film_buf.specular_color_id, specular_color_accum, out_color);
|
||||
film_store_color(dst, film_buf.environment_id, environment_accum, out_color);
|
||||
film_store_color(dst, film_buf.shadow_id, vec4(vec3(shadow_accum), 1.0), out_color);
|
||||
film_store_color(dst, film_buf.ambient_occlusion_id, vec4(vec3(ao_accum), 1.0), out_color);
|
||||
film_store_value(dst, film_buf.mist_id, mist_accum, out_color);
|
||||
film_store_color(dst, uniform_buf.film.diffuse_color_id, diffuse_color_accum, out_color);
|
||||
film_store_color(dst, uniform_buf.film.specular_color_id, specular_color_accum, out_color);
|
||||
film_store_color(dst, uniform_buf.film.environment_id, environment_accum, out_color);
|
||||
film_store_color(dst, uniform_buf.film.shadow_id, vec4(vec3(shadow_accum), 1.0), out_color);
|
||||
film_store_color(
|
||||
dst, uniform_buf.film.ambient_occlusion_id, vec4(vec3(ao_accum), 1.0), out_color);
|
||||
film_store_value(dst, uniform_buf.film.mist_id, mist_accum, out_color);
|
||||
}
|
||||
|
||||
for (int aov = 0; aov < film_buf.aov_color_len; aov++) {
|
||||
for (int aov = 0; aov < uniform_buf.film.aov_color_len; aov++) {
|
||||
vec4 aov_accum = vec4(0.0);
|
||||
|
||||
for (int i = 0; i < film_buf.samples_len; i++) {
|
||||
for (int i = 0; i < uniform_buf.film.samples_len; i++) {
|
||||
FilmSample src = film_sample_get(i, texel_film);
|
||||
film_sample_accum(src, 0, rp_buf.color_len + aov, rp_color_tx, aov_accum);
|
||||
film_sample_accum(src, 0, uniform_buf.render_pass.color_len + aov, rp_color_tx, aov_accum);
|
||||
}
|
||||
film_store_color(dst, film_buf.aov_color_id + aov, aov_accum, out_color);
|
||||
film_store_color(dst, uniform_buf.film.aov_color_id + aov, aov_accum, out_color);
|
||||
}
|
||||
|
||||
for (int aov = 0; aov < film_buf.aov_value_len; aov++) {
|
||||
for (int aov = 0; aov < uniform_buf.film.aov_value_len; aov++) {
|
||||
float aov_accum = 0.0;
|
||||
|
||||
for (int i = 0; i < film_buf.samples_len; i++) {
|
||||
for (int i = 0; i < uniform_buf.film.samples_len; i++) {
|
||||
FilmSample src = film_sample_get(i, texel_film);
|
||||
film_sample_accum(src, 0, rp_buf.value_len + aov, rp_value_tx, aov_accum);
|
||||
film_sample_accum(src, 0, uniform_buf.render_pass.value_len + aov, rp_value_tx, aov_accum);
|
||||
}
|
||||
film_store_value(dst, film_buf.aov_value_id + aov, aov_accum, out_color);
|
||||
film_store_value(dst, uniform_buf.film.aov_value_id + aov, aov_accum, out_color);
|
||||
}
|
||||
|
||||
if (film_buf.cryptomatte_samples_len != 0) {
|
||||
if (uniform_buf.film.cryptomatte_samples_len != 0) {
|
||||
/* Cryptomatte passes cannot be cleared by a weighted store like other passes. */
|
||||
if (!film_buf.use_history || film_buf.use_reprojection) {
|
||||
if (!uniform_buf.film.use_history || uniform_buf.film.use_reprojection) {
|
||||
cryptomatte_clear_samples(dst);
|
||||
}
|
||||
|
||||
film_cryptomatte_layer_accum_and_store(
|
||||
dst, texel_film, film_buf.cryptomatte_object_id, 0, out_color);
|
||||
dst, texel_film, uniform_buf.film.cryptomatte_object_id, 0, out_color);
|
||||
film_cryptomatte_layer_accum_and_store(
|
||||
dst, texel_film, film_buf.cryptomatte_asset_id, 1, out_color);
|
||||
dst, texel_film, uniform_buf.film.cryptomatte_asset_id, 1, out_color);
|
||||
film_cryptomatte_layer_accum_and_store(
|
||||
dst, texel_film, film_buf.cryptomatte_material_id, 2, out_color);
|
||||
dst, texel_film, uniform_buf.film.cryptomatte_material_id, 2, out_color);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -378,11 +378,11 @@ void output_renderpass_value(int id, float value)
|
|||
void clear_aovs()
|
||||
{
|
||||
#if defined(MAT_RENDER_PASS_SUPPORT) && defined(GPU_FRAGMENT_SHADER)
|
||||
for (int i = 0; i < AOV_MAX && i < rp_buf.aovs.color_len; i++) {
|
||||
output_renderpass_color(rp_buf.color_len + i, vec4(0));
|
||||
for (int i = 0; i < AOV_MAX && i < uniform_buf.render_pass.aovs.color_len; i++) {
|
||||
output_renderpass_color(uniform_buf.render_pass.color_len + i, vec4(0));
|
||||
}
|
||||
for (int i = 0; i < AOV_MAX && i < rp_buf.aovs.value_len; i++) {
|
||||
output_renderpass_value(rp_buf.value_len + i, 0.0);
|
||||
for (int i = 0; i < AOV_MAX && i < uniform_buf.render_pass.aovs.value_len; i++) {
|
||||
output_renderpass_value(uniform_buf.render_pass.value_len + i, 0.0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -390,15 +390,19 @@ void clear_aovs()
|
|||
void output_aov(vec4 color, float value, uint hash)
|
||||
{
|
||||
#if defined(MAT_RENDER_PASS_SUPPORT) && defined(GPU_FRAGMENT_SHADER)
|
||||
for (int i = 0; i < AOV_MAX && i < rp_buf.aovs.color_len; i++) {
|
||||
if (rp_buf.aovs.hash_color[i].x == hash) {
|
||||
imageStore(rp_color_img, ivec3(ivec2(gl_FragCoord.xy), rp_buf.color_len + i), color);
|
||||
for (int i = 0; i < AOV_MAX && i < uniform_buf.render_pass.aovs.color_len; i++) {
|
||||
if (uniform_buf.render_pass.aovs.hash_color[i].x == hash) {
|
||||
imageStore(rp_color_img,
|
||||
ivec3(ivec2(gl_FragCoord.xy), uniform_buf.render_pass.color_len + i),
|
||||
color);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < AOV_MAX && i < rp_buf.aovs.value_len; i++) {
|
||||
if (rp_buf.aovs.hash_value[i].x == hash) {
|
||||
imageStore(rp_value_img, ivec3(ivec2(gl_FragCoord.xy), rp_buf.value_len + i), vec4(value));
|
||||
for (int i = 0; i < AOV_MAX && i < uniform_buf.render_pass.aovs.value_len; i++) {
|
||||
if (uniform_buf.render_pass.aovs.hash_value[i].x == hash) {
|
||||
imageStore(rp_value_img,
|
||||
ivec3(ivec2(gl_FragCoord.xy), uniform_buf.render_pass.value_len + i),
|
||||
vec4(value));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -497,7 +501,7 @@ vec3 coordinate_screen(vec3 P)
|
|||
else {
|
||||
/* TODO(fclem): Actual camera transform. */
|
||||
window.xy = project_point(ProjectionMatrix, transform_point(ViewMatrix, P)).xy * 0.5 + 0.5;
|
||||
window.xy = window.xy * camera_buf.uv_scale + camera_buf.uv_bias;
|
||||
window.xy = window.xy * uniform_buf.camera.uv_scale + uniform_buf.camera.uv_bias;
|
||||
}
|
||||
return window;
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ void main()
|
|||
const uint tile_size = RAYTRACE_GROUP_SIZE;
|
||||
uvec2 tile_coord = unpackUvec2x16(tiles_coord_buf[gl_WorkGroupID.x]);
|
||||
ivec2 texel_fullres = ivec2(gl_LocalInvocationID.xy + tile_coord * tile_size);
|
||||
vec2 center_uv = vec2(texel_fullres) * raytrace_buf.full_resolution_inv;
|
||||
vec2 center_uv = vec2(texel_fullres) * uniform_buf.raytrace.full_resolution_inv;
|
||||
|
||||
float center_depth = texelFetch(hiz_tx, texel_fullres, 0).r;
|
||||
vec3 center_P = get_world_space_from_depth(center_uv, center_depth);
|
||||
|
@ -160,7 +160,7 @@ void main()
|
|||
}
|
||||
|
||||
float sample_depth = texelFetch(hiz_tx, sample_texel, 0).r;
|
||||
vec2 sample_uv = vec2(sample_texel) * raytrace_buf.full_resolution_inv;
|
||||
vec2 sample_uv = vec2(sample_texel) * uniform_buf.raytrace.full_resolution_inv;
|
||||
vec3 sample_P = get_world_space_from_depth(sample_uv, sample_depth);
|
||||
|
||||
/* Background case. */
|
||||
|
|
|
@ -107,9 +107,9 @@ void main()
|
|||
uvec2 tile_coord = unpackUvec2x16(tiles_coord_buf[gl_WorkGroupID.x]);
|
||||
|
||||
ivec2 texel_fullres = ivec2(gl_LocalInvocationID.xy + tile_coord * tile_size);
|
||||
ivec2 texel = (texel_fullres) / raytrace_buf.resolution_scale;
|
||||
ivec2 texel = (texel_fullres) / uniform_buf.raytrace.resolution_scale;
|
||||
|
||||
if (raytrace_buf.skip_denoise) {
|
||||
if (uniform_buf.raytrace.skip_denoise) {
|
||||
imageStore(out_radiance_img, texel_fullres, imageLoad(ray_radiance_img, texel));
|
||||
return;
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ void main()
|
|||
return;
|
||||
}
|
||||
|
||||
vec2 uv = (vec2(texel_fullres) + 0.5) * raytrace_buf.full_resolution_inv;
|
||||
vec2 uv = (vec2(texel_fullres) + 0.5) * uniform_buf.raytrace.full_resolution_inv;
|
||||
vec3 V = transform_direction(ViewMatrixInverse, get_view_vector_from_screen_uv(uv));
|
||||
|
||||
ClosureT closure;
|
||||
|
@ -166,7 +166,7 @@ void main()
|
|||
/* NOTE: filter_size should never be greater than twice RAYTRACE_GROUP_SIZE. Otherwise, the
|
||||
* reconstruction can becomes ill defined since we don't know if further tiles are valid. */
|
||||
filter_size = 12.0 * sqrt(filter_size_factor);
|
||||
if (raytrace_buf.resolution_scale > 1) {
|
||||
if (uniform_buf.raytrace.resolution_scale > 1) {
|
||||
/* Filter at least 1 trace pixel to fight the undersampling. */
|
||||
filter_size = max(filter_size, 3.0);
|
||||
sample_count = max(sample_count, 5u);
|
||||
|
@ -189,7 +189,8 @@ void main()
|
|||
ivec2 sample_texel = texel + offset;
|
||||
|
||||
/* Reject samples outside of valid neighbor tiles. */
|
||||
ivec2 sample_tile = ivec2(sample_texel * raytrace_buf.resolution_scale) / int(tile_size);
|
||||
ivec2 sample_tile = ivec2(sample_texel * uniform_buf.raytrace.resolution_scale) /
|
||||
int(tile_size);
|
||||
ivec2 sample_tile_relative = sample_tile - ivec2(tile_coord);
|
||||
if (neighbor_tile_mask_bit_get(invalid_neighbor_tile_mask, sample_tile_relative)) {
|
||||
continue;
|
||||
|
|
|
@ -111,7 +111,7 @@ vec4 radiance_history_fetch(ivec2 texel, float bilinear_weight)
|
|||
|
||||
vec4 radiance_history_sample(vec3 P, LocalStatistics local)
|
||||
{
|
||||
vec2 uv = project_point(raytrace_buf.history_persmat, P).xy * 0.5 + 0.5;
|
||||
vec2 uv = project_point(uniform_buf.raytrace.history_persmat, P).xy * 0.5 + 0.5;
|
||||
|
||||
/* FIXME(fclem): Find why we need this half pixel offset. */
|
||||
vec2 texel_co = uv * vec2(textureSize(radiance_history_tx, 0).xy) - 0.5;
|
||||
|
@ -139,7 +139,7 @@ vec4 radiance_history_sample(vec3 P, LocalStatistics local)
|
|||
|
||||
vec2 variance_history_sample(vec3 P)
|
||||
{
|
||||
vec2 uv = project_point(raytrace_buf.history_persmat, P).xy * 0.5 + 0.5;
|
||||
vec2 uv = project_point(uniform_buf.raytrace.history_persmat, P).xy * 0.5 + 0.5;
|
||||
|
||||
if (!in_range_exclusive(uv, vec2(0.0), vec2(1.0))) {
|
||||
/* Out of history view. Return sample without weight. */
|
||||
|
@ -164,7 +164,7 @@ void main()
|
|||
const uint tile_size = RAYTRACE_GROUP_SIZE;
|
||||
uvec2 tile_coord = unpackUvec2x16(tiles_coord_buf[gl_WorkGroupID.x]);
|
||||
ivec2 texel_fullres = ivec2(gl_LocalInvocationID.xy + tile_coord * tile_size);
|
||||
vec2 uv = (vec2(texel_fullres) + 0.5) * raytrace_buf.full_resolution_inv;
|
||||
vec2 uv = (vec2(texel_fullres) + 0.5) * uniform_buf.raytrace.full_resolution_inv;
|
||||
|
||||
float in_variance = imageLoad(in_variance_img, texel_fullres).r;
|
||||
vec3 in_radiance = imageLoad(in_radiance_img, texel_fullres).rgb;
|
||||
|
|
|
@ -19,7 +19,8 @@ void main()
|
|||
uvec2 tile_coord = unpackUvec2x16(tiles_coord_buf[gl_WorkGroupID.x]);
|
||||
ivec2 texel = ivec2(gl_LocalInvocationID.xy + tile_coord * tile_size);
|
||||
|
||||
ivec2 texel_fullres = texel * raytrace_buf.resolution_scale + raytrace_buf.resolution_bias;
|
||||
ivec2 texel_fullres = texel * uniform_buf.raytrace.resolution_scale +
|
||||
uniform_buf.raytrace.resolution_bias;
|
||||
|
||||
bool valid_texel = in_texture_range(texel_fullres, stencil_tx);
|
||||
uint closure_bits = (!valid_texel) ? 0u : texelFetch(stencil_tx, texel_fullres, 0).r;
|
||||
|
|
|
@ -44,8 +44,8 @@ void main()
|
|||
|
||||
eClosureBits closure_bits = eClosureBits(texelFetch(stencil_tx, texel, 0).r);
|
||||
|
||||
if (flag_test(closure_bits, raytrace_buf.closure_active)) {
|
||||
int gbuffer_layer = raytrace_buf.closure_active == CLOSURE_REFRACTION ? 1 : 0;
|
||||
if (flag_test(closure_bits, uniform_buf.raytrace.closure_active)) {
|
||||
int gbuffer_layer = uniform_buf.raytrace.closure_active == CLOSURE_REFRACTION ? 1 : 0;
|
||||
|
||||
vec4 gbuffer_packed = texelFetch(gbuffer_closure_tx, ivec3(texel, gbuffer_layer), 0);
|
||||
float roughness = gbuffer_packed.z;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue