diff options
| author | chai <chaifix@163.com> | 2019-08-14 22:50:43 +0800 | 
|---|---|---|
| committer | chai <chaifix@163.com> | 2019-08-14 22:50:43 +0800 | 
| commit | 15740faf9fe9fe4be08965098bbf2947e096aeeb (patch) | |
| tree | a730ec236656cc8cab5b13f088adfaed6bb218fb /Runtime/Math/SphericalHarmonics.h | |
Diffstat (limited to 'Runtime/Math/SphericalHarmonics.h')
| -rw-r--r-- | Runtime/Math/SphericalHarmonics.h | 83 | 
1 files changed, 83 insertions, 0 deletions
| diff --git a/Runtime/Math/SphericalHarmonics.h b/Runtime/Math/SphericalHarmonics.h new file mode 100644 index 0000000..539d316 --- /dev/null +++ b/Runtime/Math/SphericalHarmonics.h @@ -0,0 +1,83 @@ +#pragma once + + +static inline void SHEvalDirection9 (float x, float y, float z, float outsh[9]) +{ +	// Core i7 920, VS2008 Release, FPU code: + +	// 114 clocks +	//D3DXSHEvalDirection (outsh, 3, &D3DXVECTOR3(x,y,z)); + +	/* +	// 314 clocks +	// Reference implementation from Stupid Spherical Harmonics Tricks +	// http://www.ppsloan.org/publications/StupidSH36.pdf +	const float kSqrtPI = sqrtf(kPI); +	const float kSqrt3 = sqrtf(3.0f); +	const float kSqrt15 = sqrtf(15.0f); +	outsh[0] = 1.0f / (2.0f * kSqrtPI); +	outsh[1] = -(kSqrt3 * y) / (2.0f * kSqrtPI); +	outsh[2] = (kSqrt3 * z) / (2.0f * kSqrtPI); +	outsh[3] = -(kSqrt3 * x) / (2.0f * kSqrtPI); +	outsh[4] = (kSqrt15 * x * y) / (2.0f * kSqrtPI); +	outsh[5] = -(kSqrt15 * y * z) / (2.0f * kSqrtPI); +	outsh[6] = (sqrtf(5.0f) * (3.0f*z*z-1.0f)) / (4.0f * kSqrtPI); +	outsh[7] = -(kSqrt15 * x * z) / (2.0f * kSqrtPI); +	outsh[8] = (kSqrt15 * (x*x - y*y)) / (4.0f * kSqrtPI); +	*/ + +	// 86 clocks +	// Make sure all constants are never computed at runtime +	const float kInv2SqrtPI = 0.28209479177387814347403972578039f; // 1 / (2*sqrt(kPI)) +	const float kSqrt3Div2SqrtPI = 0.48860251190291992158638462283835f; // sqrt(3) / (2*sqrt(kPI)) +	const float kSqrt15Div2SqrtPI = 1.0925484305920790705433857058027f; // sqrt(15) / (2*sqrt(kPI)) +	const float k3Sqrt5Div4SqrtPI = 0.94617469575756001809268107088713f; // 3 * sqrtf(5) / (4*sqrt(kPI)) +	const float kSqrt15Div4SqrtPI = 0.54627421529603953527169285290135f; // sqrt(15) / (4*sqrt(kPI)) +	const float kOneThird = 0.3333333333333333333333f; // 1.0/3.0 +	outsh[0] = kInv2SqrtPI; +	outsh[1] = - y * kSqrt3Div2SqrtPI; +	outsh[2] =   z * kSqrt3Div2SqrtPI; +	outsh[3] = - x * kSqrt3Div2SqrtPI; +	outsh[4] =   x * y * kSqrt15Div2SqrtPI; +	outsh[5] = - y * z * kSqrt15Div2SqrtPI; +	outsh[6] =  (z*z-kOneThird) * k3Sqrt5Div4SqrtPI; +	outsh[7] = - x * z * kSqrt15Div2SqrtPI; +	outsh[8] =  (x*x-y*y) * kSqrt15Div4SqrtPI; +} + + +static inline void SHEvalDirectionalLight9 ( +	float x, float y, float z, +	float colorR, float colorG, float colorB, +	float outR[9], float outG[9], float outB[9]) +{ +	// Core i7 920, VS2008 Release, FPU code: + +	// 397 clocks +	//D3DXSHEvalDirectionalLight (3, &D3DXVECTOR3(x,y,z), colorR, colorG, colorB, outR, outG, outB); + +	// 300 clocks +	float sh[9]; +	SHEvalDirection9 (x, y, z, sh); +	// Normalization factor from http://www.ppsloan.org/publications/StupidSH36.pdf +	const float kNormalization = 2.9567930857315701067858823529412f; // 16*kPI/17 +	float rscale = colorR * kNormalization; +	float gscale = colorG * kNormalization; +	float bscale = colorB * kNormalization; +	for (int i = 0; i < 9; ++i) +	{ +		float c = sh[i]; +		outR[i] = c * rscale; +		outG[i] = c * gscale; +		outB[i] = c * bscale; +	} +} + +// Add 'out' to the 0th SH coefficients +static inline void SHEvalAmbientLight(const ColorRGBAf& ambient, float out[3]) +{ +	const float k2SqrtPI = 3.54490770181103205459633496668229f; // 2*sqrt(kPI) +	out[0] = ambient.r * k2SqrtPI; +	out[1] = ambient.g * k2SqrtPI; +	out[2] = ambient.b * k2SqrtPI; +} | 
