blender/intern/cycles/util/math_spherical_harmonics.h
Sergey Sharybin a4cdca016e Cleanup: Cycles: Consistently call packed spherical harmonics rest
The pack only contains bands 1 to 3. The evaluation function has
been renamed as part of the original review. It makes sense to be
consistent, although a bit more verbose.

Pull Request: https://projects.blender.org/blender/blender/pulls/163446
2026-09-03 11:27:09 +02:00

177 lines
6.5 KiB
C++

/* SPDX-FileCopyrightText: 2026 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
/* Evaluation of spherical harmonics.
*
* References:
*
* [sloan2010] Peter-Pike Sloan
* Stupid Spherical Harmonics (SH) Trick
* Game Developers Conference 2008, February 2008 (updated 2/10/2010)
*/
#pragma once
#include "util/math_base.h"
#include "util/types_float3.h"
#include "util/types_spherical_harmonics.h"
CCL_NAMESPACE_BEGIN
/* The polynomial forms of the spherical basis functions.
* [sloan2010] Appendix A2. */
template<int L, int M> ccl_device_inline float spherical_harmonics_polynomial_form(float3 v);
/* Band L=0. */
ccl_device_template_spec float spherical_harmonics_polynomial_form<0, 0>(const float3 /*v*/)
{
return 0.282094792f;
}
/* Band L=1. */
ccl_device_template_spec float spherical_harmonics_polynomial_form<1, -1>(const float3 v)
{
return -0.488602512f * v.y;
}
ccl_device_template_spec float spherical_harmonics_polynomial_form<1, 0>(const float3 v)
{
return 0.488602512f * v.z;
}
ccl_device_template_spec float spherical_harmonics_polynomial_form<1, 1>(const float3 v)
{
return -0.488602512f * v.x;
}
/* Band L=2. */
ccl_device_template_spec float spherical_harmonics_polynomial_form<2, -2>(const float3 v)
{
return 1.092548431f * (v.x * v.y);
}
ccl_device_template_spec float spherical_harmonics_polynomial_form<2, -1>(const float3 v)
{
return -1.092548431f * (v.y * v.z);
}
ccl_device_template_spec float spherical_harmonics_polynomial_form<2, 0>(const float3 v)
{
return 0.315391565f * (3.0f * v.z * v.z - 1.0f);
}
ccl_device_template_spec float spherical_harmonics_polynomial_form<2, 1>(const float3 v)
{
return -1.092548431f * (v.x * v.z);
}
ccl_device_template_spec float spherical_harmonics_polynomial_form<2, 2>(const float3 v)
{
return 0.546274215f * (v.x * v.x - v.y * v.y);
}
/* Band L=3. */
ccl_device_template_spec float spherical_harmonics_polynomial_form<3, -3>(const float3 v)
{
return -0.590043589f * v.y * (3.0f * v.x * v.x - v.y * v.y);
}
ccl_device_template_spec float spherical_harmonics_polynomial_form<3, -2>(const float3 v)
{
return 2.890611442f * (v.y * v.x * v.z);
}
ccl_device_template_spec float spherical_harmonics_polynomial_form<3, -1>(const float3 v)
{
return -0.457045799f * v.y * (-1.0f + 5.0f * v.z * v.z);
}
ccl_device_template_spec float spherical_harmonics_polynomial_form<3, 0>(const float3 v)
{
return 0.373176332f * v.z * (5.0f * v.z * v.z - 3.0f);
}
ccl_device_template_spec float spherical_harmonics_polynomial_form<3, 1>(const float3 v)
{
return -0.457045799f * v.x * (-1.0f + 5.0f * v.z * v.z);
}
ccl_device_template_spec float spherical_harmonics_polynomial_form<3, 2>(const float3 v)
{
return 1.445305721f * v.z * (v.x * v.x - v.y * v.y);
}
ccl_device_template_spec float spherical_harmonics_polynomial_form<3, 3>(const float3 v)
{
return -0.5900435899f * v.x * (v.x * v.x - 3.0f * v.y * v.y);
}
template<class T>
ccl_device_forceinline T spherical_harmonics_evaluate_band_L0(const float3 direction, const T M0)
{
return spherical_harmonics_polynomial_form<0, 0>(direction) * M0;
}
template<class T>
ccl_device_forceinline T
spherical_harmonics_evaluate_band_L1(const float3 direction, const T Mn1, const T M0, const T Mp1)
{
return spherical_harmonics_polynomial_form<1, -1>(direction) * Mn1 +
spherical_harmonics_polynomial_form<1, 0>(direction) * M0 +
spherical_harmonics_polynomial_form<1, 1>(direction) * Mp1;
}
template<class T>
ccl_device_forceinline T spherical_harmonics_evaluate_band_L2(
const float3 direction, const T Mn2, const T Mn1, const T M0, const T Mp1, const T Mp2)
{
return spherical_harmonics_polynomial_form<2, -2>(direction) * Mn2 +
spherical_harmonics_polynomial_form<2, -1>(direction) * Mn1 +
spherical_harmonics_polynomial_form<2, 0>(direction) * M0 +
spherical_harmonics_polynomial_form<2, 1>(direction) * Mp1 +
spherical_harmonics_polynomial_form<2, 2>(direction) * Mp2;
}
template<class T>
ccl_device_forceinline T spherical_harmonics_evaluate_band_L3(const float3 direction,
const T Mn3,
const T Mn2,
const T Mn1,
const T M0,
const T Mp1,
const T Mp2,
const T Mp3)
{
return spherical_harmonics_polynomial_form<3, -3>(direction) * Mn3 +
spherical_harmonics_polynomial_form<3, -2>(direction) * Mn2 +
spherical_harmonics_polynomial_form<3, -1>(direction) * Mn1 +
spherical_harmonics_polynomial_form<3, 0>(direction) * M0 +
spherical_harmonics_polynomial_form<3, 1>(direction) * Mp1 +
spherical_harmonics_polynomial_form<3, 2>(direction) * Mp2 +
spherical_harmonics_polynomial_form<3, 3>(direction) * Mp3;
}
/* Evaluate bands L1, L2, and L3. */
ccl_device_inline float3 spherical_harmonics_evaluate_rest(
const ccl_global PackedSphericalHarmonicsRest &packed_spherical_harmonics_rest,
const float3 direction)
{
float3 result;
result = spherical_harmonics_evaluate_band_L1(
direction,
spherical_harmonics_get<1, -1>(packed_spherical_harmonics_rest),
spherical_harmonics_get<1, 0>(packed_spherical_harmonics_rest),
spherical_harmonics_get<1, 1>(packed_spherical_harmonics_rest));
result += spherical_harmonics_evaluate_band_L2(
direction,
spherical_harmonics_get<2, -2>(packed_spherical_harmonics_rest),
spherical_harmonics_get<2, -1>(packed_spherical_harmonics_rest),
spherical_harmonics_get<2, 0>(packed_spherical_harmonics_rest),
spherical_harmonics_get<2, 1>(packed_spherical_harmonics_rest),
spherical_harmonics_get<2, 2>(packed_spherical_harmonics_rest));
result += spherical_harmonics_evaluate_band_L3(
direction,
spherical_harmonics_get<3, -3>(packed_spherical_harmonics_rest),
spherical_harmonics_get<3, -2>(packed_spherical_harmonics_rest),
spherical_harmonics_get<3, -1>(packed_spherical_harmonics_rest),
spherical_harmonics_get<3, 0>(packed_spherical_harmonics_rest),
spherical_harmonics_get<3, 1>(packed_spherical_harmonics_rest),
spherical_harmonics_get<3, 2>(packed_spherical_harmonics_rest),
spherical_harmonics_get<3, 3>(packed_spherical_harmonics_rest));
return result;
}
CCL_NAMESPACE_END