Repository: sebh/HLSL-Spherical-Harmonics Branch: master Commit: b6565a385e40 Files: 4 Total size: 36.0 KB Directory structure: gitextract_3d9p7imu/ ├── LICENSE ├── README.md ├── SphericalHarmonics.hlsl └── sh2.nb ================================================ FILE CONTENTS ================================================ ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2018 SebH Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # HLSL-Spherical-Harmonics ## Description A collection of HLSL functions one can include to use spherical harmonics in shaders. This is practical when generating and consuming SH on the GPU. Using Git, this repository can be integrated in your project as a _submodule_. Files description: * SphericalHarmonics.hlsl: the HLSL file containing all the SH functions. * sh2.nb : A Mathematica notebook to verify and visualize SH functions correctness. * sh2.pdf: A compiled pdf to simply read sh2.nb. ## Examples Precomputed occlusion as SH for cloud ambient lighting. Result as video and as images (1st image: directional occlusion as SH, 2nd image: final cloud render): cloud cloud ## Future * As of today, only 2nd order SH functions are provided. 3rd order SH could be added. * Do not hesitate to send suggestions or improvements. ================================================ FILE: SphericalHarmonics.hlsl ================================================ // SphericalHarmonics.hlsl from https://github.com/sebh/HLSL-Spherical-Harmonics // Great documents about spherical harmonics: // [1] http://www.cse.chalmers.se/~uffe/xjobb/Readings/GlobalIllumination/Spherical%20Harmonic%20Lighting%20-%20the%20gritty%20details.pdf // [2] https://www.ppsloan.org/publications/StupidSH36.pdf // [3] https://cseweb.ucsd.edu/~ravir/papers/envmap/envmap.pdf // [4] https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2011/06/10-14.pdf // [5] https://github.com/kayru/Probulator // [6] https://www.ppsloan.org/publications/SHJCGT.pdf // [7] http://www.patapom.com/blog/SHPortal/ // [8] https://grahamhazel.com/blog/2017/12/22/converting-sh-radiance-to-irradiance/ // [9] http://www.ppsloan.org/publications/shdering.pdf // [10] http://limbicsoft.com/volker/prosem_paper.pdf // [11] https://bartwronski.files.wordpress.com/2014/08/bwronski_volumetric_fog_siggraph2014.pdf // // // Provided functions are commented. A "SH function" means a "spherical function represented as spherical harmonics". // You can also find a FAQ below. // //**** HOW TO PROJECT RADIANCE FROM A SPHERE INTO SH? // // // Initialise sh to 0 // sh2 shR = shZero(); // sh2 shG = shZero(); // sh2 shB = shZero(); // // // Accumulate coefficients according to surounding direction/color tuples. // for (float az = 0.5f; az < axisSampleCount; az += 1.0f) // for (float ze = 0.5f; ze < axisSampleCount; ze += 1.0f) // { // float3 rayDir = shGetUniformSphereSample(az / axisSampleCount, ze / axisSampleCount); // float3 color = [...]; // // sh2 sh = shEvaluate(rayDir); // shR = shAdd(shR, shScale(sh, color.r)); // shG = shAdd(shG, shScale(sh, color.g)); // shB = shAdd(shB, shScale(sh, color.b)); // } // // // integrating over a sphere so each sample has a weight of 4*PI/samplecount (uniform solid angle, for each sample) // float shFactor = 4.0 * shPI / (axisSampleCount * axisSampleCount); // shR = shScale(shR, shFactor ); // shG = shScale(shG, shFactor ); // shB = shScale(shB, shFactor ); // // //**** HOW TO VIZUALISE A SPHERICAL FUNCTION REPRESENTED AS SH? // // sh2 shR = fromSomewhere.Load(...); // sh2 shG = fromSomewhere.Load(...); // sh2 shB = fromSomewhere.Load(...); // float3 rayDir = compute(...); // the direction for which you want to know the color // float3 rgbColor = max(0.0f, shUnproject(shR, shG, shB, rayDir)); // A "max" is usually recomended to avoid negative values (can happen with SH) // #ifndef SPHERICAL_HARMONICS_HLSL #define SPHERICAL_HARMONICS_HLSL #define shPI 3.1415926536f // Generates a uniform distribution of directions over a unit sphere. // Adapted from http://www.pbr-book.org/3ed-2018/Monte_Carlo_Integration/2D_Sampling_with_Multidimensional_Transformations.html#fragment-SamplingFunctionDefinitions-6 // azimuthX and zenithY are both in [0, 1]. You can use random value, stratified, etc. // Top and bottom sphere pole (+-zenith) are along the Y axis. float3 shGetUniformSphereSample(float azimuthX, float zenithY) { float phi = 2.0f * shPI * azimuthX; float z = 1.0f - 2.0f * zenithY; float r = sqrt(max(0.0f, 1.0f - z * z)); return float3(r * cos(phi), z, r * sin(phi)); } #define sh2 float4 // TODO sh3 sh2 shZero() { return float4(0.0f, 0.0f, 0.0f, 0.0f); } // Evaluates spherical harmonics basis for a direction dir. // This follows [2] Appendix A2 order when storing in x, y, z and w. // (evaluating the associated Legendre polynomials using the polynomial forms) sh2 shEvaluate(float3 dir) { sh2 result; result.x = 0.28209479177387814347403972578039f; // L=0 , M= 0 result.y =-0.48860251190291992158638462283836f * dir.y; // L=1 , M=-1 result.z = 0.48860251190291992158638462283836f * dir.z; // L=1 , M= 0 result.w =-0.48860251190291992158638462283836f * dir.x; // L=1 , M= 1 return result; } // Recovers the value of a SH function in the direction dir. float shUnproject(sh2 functionSh, float3 dir) { sh2 sh = shEvaluate(dir); return dot(functionSh, sh); } float3 shUnproject(sh2 functionShX, sh2 functionShY, sh2 functionShZ, float3 dir) { sh2 sh = shEvaluate(dir); return float3(dot(functionShX, sh), dot(functionShY, sh), dot(functionShZ, sh)); } // Projects a cosine lobe function, with peak value in direction dir, into SH. (from [4]) // The integral over the unit sphere of the SH representation is PI. sh2 shEvaluateCosineLobe(float3 dir) { sh2 result; result.x = 0.8862269254527580137f; // L=0 , M= 0 result.y =-1.0233267079464884885f * dir.y; // L=1 , M=-1 result.z = 1.0233267079464884885f * dir.z; // L=1 , M= 0 result.w =-1.0233267079464884885f * dir.x; // L=1 , M= 1 return result; } // Projects a Henyey-Greenstein phase function, with peak value in direction dir, into SH. (from [11]) // The integral over the unit sphere of the SH representation is 1. sh2 shEvaluatePhaseHG(float3 dir, float g) { sh2 result; const float factor = 0.48860251190291992158638462283836 * g; result.x = 0.28209479177387814347403972578039; // L=0 , M= 0 result.y =-factor * dir.y; // L=1 , M=-1 result.z = factor * dir.z; // L=1 , M= 0 result.w =-factor * dir.x; // L=1 , M= 1 return result; } // Adds two SH functions together. sh2 shAdd(sh2 shL, sh2 shR) { return shL + shR; } // Scales a SH function uniformly by v. sh2 shScale(sh2 sh, float v) { return sh * v; } // Operates a rotation of a SH function. sh2 shRotate(sh2 sh, float3x3 rotation) { // TODO verify and optimize sh2 result; result.x = sh.x; float3 tmp = float3(sh.w, sh.y, sh.z); // undo direction component shuffle to match source/function space result.yzw = mul(tmp, rotation).yzx; // apply rotation and re-shuffle return result; } // Integrates the product of two SH functions over the unit sphere. float shFuncProductIntegral(sh2 shL, sh2 shR) { return dot(shL, shR); } // Computes the SH coefficients of a SH function representing the result of the multiplication of two SH functions. (from [4]) // If sources have N bands, this product will result in 2N*1 bands as signal multiplication can add frequencies (think about two lobes intersecting). // To avoid that, the result can be truncated to N bands. It will just have a lower frequency, i.e. less details. (from [2], SH Products p.7) // Note: - the code from [4] has been adapted to match the mapping from [2] we use. // - !!! Be aware that this code has note yet be tested !!! sh2 shProduct(sh2 shL, sh2 shR) { const float factor = 1.0f / (2.0f * sqrt(shPI)); return factor * sh2( dot(shL, shR), shL.y*shR.w + shL.w*shR.y, shL.z*shR.w + shL.w*shR.z, shL.w*shR.w + shL.w*shR.w ); } // Convolves a SH function using a Hanning filtering. This helps reducing ringing and negative values. (from [2], Windowing p.16) // A lower value of w will reduce ringing (like the frequency of a filter) sh2 shHanningConvolution( sh2 sh, float w ) { sh2 result = sh; float invW = 1.0 / w; float factorBand1 =(1.0 + cos( shPI * invW )) / 2.0f; result.y *= factorBand1; result.z *= factorBand1; result.w *= factorBand1; return result; } // Convolves a SH function using a cosine lob. This is tipically used to transform radiance to irradiance. (from [3], eq.7 & eq.8) sh2 shDiffuseConvolution(sh2 sh) { sh2 result = sh; // L0 result.x *= shPI; // L1 result.yzw *= 2.0943951023931954923f; return result; } #endif // SPHERICAL_HARMONICS_HLSL ================================================ FILE: sh2.nb ================================================ (* Content-type: application/vnd.wolfram.mathematica *) (*** Wolfram Notebook File ***) (* http://www.wolfram.com/nb *) (* CreatedBy='Mathematica 9.0' *) (*CacheID: 234*) (* Internal cache information: NotebookFileLineBreakTest NotebookFileLineBreakTest NotebookDataPosition[ 157, 7] NotebookDataLength[ 27072, 697] NotebookOptionsPosition[ 26205, 667] NotebookOutlinePosition[ 26839, 690] CellTagsIndexPosition[ 26796, 687] WindowFrame->Normal*) (* Beginning of Notebook Content *) Notebook[{ Cell[BoxData[ RowBox[{"(*", "\[IndentingNewLine]", " ", RowBox[{ RowBox[{"This", " ", "files", " ", "presents", " ", "2", " ", "bands", " ", RowBox[{"(", RowBox[{ RowBox[{"a", ".", "k", ".", "a", ".", " ", "order"}], " ", "2"}], ")"}], " ", "spherical", " ", "harmonics", " ", RowBox[{"results", ".", "\[IndentingNewLine]", "It"}], " ", "comes", " ", "from", " ", RowBox[{"https", ":"}]}], "//", RowBox[{ RowBox[{ RowBox[{ RowBox[{"github", ".", "com"}], "/", "sebh"}], "/", "HLSL"}], "-", "Spherical", "-", "Harmonics"}]}], "\[IndentingNewLine]", "*)"}]], "Input"], Cell[BoxData[ RowBox[{"(*", RowBox[{"Restart", " ", "the", " ", "kernel", " ", RowBox[{"(", RowBox[{ "helps", " ", "removes", " ", "all", " ", "definitions", " ", "for", " ", "instance"}], ")"}], "\[IndentingNewLine]", "Quit"}], "*)"}]], "Input"], Cell[BoxData[ RowBox[{ RowBox[{"(*", "\[IndentingNewLine]", " ", RowBox[{ RowBox[{"aToD", ":", " ", RowBox[{ "transformation", " ", "from", " ", "azimuth", " ", "and", " ", "zenith", " ", "angle", " ", "to", " ", RowBox[{ RowBox[{"(", RowBox[{"x", ",", "y", ",", "z"}], ")"}], ".", " ", "\[IndentingNewLine]", " ", "evalSh2"}]}], ":", " ", RowBox[{ "evaluate", " ", "SH2", " ", "for", " ", "a", " ", "direction", "\[IndentingNewLine]", " ", RowBox[{"unprojSh2", ":", " ", RowBox[{ "unproject", " ", "a", " ", "SH2", " ", "encoded", " ", "function"}]}]}]}], ",", " ", RowBox[{"giving", " ", "its", " ", "value", " ", "along", " ", RowBox[{"(", RowBox[{"\[Theta]", ",", "\[Phi]"}], ")"}]}]}], "\[IndentingNewLine]", "*)"}], "\[IndentingNewLine]", "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"aToD", "[", RowBox[{"\[Theta]_", ",", "\[Phi]_"}], "]"}], " ", ":=", "\[IndentingNewLine]", RowBox[{"{", "\[IndentingNewLine]", " ", RowBox[{ RowBox[{ RowBox[{"Cos", "[", "\[Phi]", "]"}], RowBox[{"Sin", "[", "\[Theta]", "]"}]}], ",", RowBox[{ RowBox[{"Sin", "[", "\[Phi]", "]"}], RowBox[{"Sin", "[", "\[Theta]", "]"}]}], ",", RowBox[{"Cos", "[", "\[Theta]", "]"}]}], "\[IndentingNewLine]", "}"}]}], "\[IndentingNewLine]", "\[IndentingNewLine]", RowBox[{ RowBox[{"evalSh2", "[", RowBox[{"\[Theta]_", ",", "\[Phi]_"}], "]"}], ":=", RowBox[{"{", "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"d", " ", "=", " ", RowBox[{"aToD", "[", RowBox[{"\[Theta]", ",", "\[Phi]"}], "]"}]}], " ", ";", "\[IndentingNewLine]", "0.28209479177387814347403972578039"}], ",", "\[IndentingNewLine]", RowBox[{ RowBox[{"-", "0.48860251190291992158638462283836"}], "*", RowBox[{"d", "[", RowBox[{"[", "2", "]"}], "]"}]}], ",", "\[IndentingNewLine]", RowBox[{"0.48860251190291992158638462283836", "*", RowBox[{"d", "[", RowBox[{"[", "3", "]"}], "]"}]}], ",", "\[IndentingNewLine]", RowBox[{ RowBox[{"-", "0.48860251190291992158638462283836"}], "*", RowBox[{"d", "[", RowBox[{"[", "1", "]"}], "]"}]}]}], "\[IndentingNewLine]", "}"}]}], "\[IndentingNewLine]", "\[IndentingNewLine]", RowBox[{ RowBox[{"unprojSh2", "[", RowBox[{"shIn_", ",", "\[Theta]_", ",", "\[Phi]_"}], "]"}], ":=", RowBox[{ RowBox[{"{", "\[IndentingNewLine]", RowBox[{ RowBox[{"sh", " ", "=", " ", RowBox[{"evalSh2", "[", RowBox[{"\[Theta]", ",", "\[Phi]"}], "]"}]}], ";", "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"sh", "[", RowBox[{"[", "1", "]"}], "]"}], "*", RowBox[{"shIn", "[", RowBox[{"[", "1", "]"}], "]"}]}], " ", "+", " ", RowBox[{ RowBox[{"sh", "[", RowBox[{"[", "2", "]"}], "]"}], "*", RowBox[{"shIn", "[", RowBox[{"[", "2", "]"}], "]"}]}], " ", "+", " ", RowBox[{ RowBox[{"sh", "[", RowBox[{"[", "3", "]"}], "]"}], "*", RowBox[{"shIn", "[", RowBox[{"[", "3", "]"}], "]"}]}], " ", "+", " ", RowBox[{ RowBox[{"sh", "[", RowBox[{"[", "4", "]"}], "]"}], "*", RowBox[{"shIn", "[", RowBox[{"[", "4", "]"}], "]"}]}]}]}], " ", "\[IndentingNewLine]", "}"}], "[", RowBox[{"[", "1", "]"}], "]"}]}], "\[IndentingNewLine]", "\[IndentingNewLine]", "\[IndentingNewLine]", RowBox[{"Print", "[", "\"\\"", "]"}], "\[IndentingNewLine]", RowBox[{"aToD", "[", RowBox[{"0", ",", "0"}], "]"}], "\[IndentingNewLine]", RowBox[{"test", " ", "=", " ", RowBox[{"evalSh2", "[", RowBox[{"0", ",", "0"}], "]"}]}], "\[IndentingNewLine]", RowBox[{"unprojSh2", "[", RowBox[{"test", ",", "1", ",", "2"}], "]"}], "\[IndentingNewLine]"}]}]], "Input"], Cell[BoxData[ RowBox[{ RowBox[{"(*", " ", "\[IndentingNewLine]", " ", RowBox[{ RowBox[{ RowBox[{"From", " ", RowBox[{"https", ":"}]}], "//", RowBox[{ RowBox[{ RowBox[{"d3cw3dd2w32x2b", ".", "cloudfront", ".", "net"}], "/", "wp"}], "-", RowBox[{ RowBox[{ RowBox[{ RowBox[{"content", "/", "uploads"}], "/", "2011"}], "/", "06"}], "/", "10"}], "-", RowBox[{"14.", RowBox[{"pdf", ".", "\[IndentingNewLine]", "A"}], " ", "cosine", " ", "lob", " ", "with", " ", "peak", " ", "in", " ", "a", " ", "specified", " ", RowBox[{"(", RowBox[{"\[Theta]", ",", "\[Phi]"}], ")"}], " ", RowBox[{"direction", ".", "\[IndentingNewLine]", "The"}], " ", "integration", " ", "over", " ", "the", " ", "unit", " ", "sphere", " ", "is", " ", "\[Pi]"}]}]}], ",", " ", RowBox[{"and", " ", "this", " ", "is", " ", RowBox[{"correct", ".", "\[IndentingNewLine]", " ", RowBox[{"(", RowBox[{ "even", " ", "though", " ", "it", " ", "does", " ", "have", " ", "a", " ", "negative", " ", "values", " ", "in", " ", "the", " ", "opposite", " ", "directin", " ", "from", " ", "the", " ", "lobe"}], ")"}], "."}]}]}], "\[IndentingNewLine]", "*)"}], "\[IndentingNewLine]", "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"cosLobeDir", " ", "=", " ", RowBox[{"{", RowBox[{"1", ",", "0", ",", "0"}], "}"}]}], ";"}], "\[IndentingNewLine]", RowBox[{ RowBox[{"shCosLobe", " ", "=", " ", RowBox[{"{", RowBox[{ RowBox[{ RowBox[{"Sqrt", "[", "\[Pi]", "]"}], "/", "2"}], ",", "\[IndentingNewLine]", RowBox[{ RowBox[{"-", RowBox[{"Sqrt", "[", RowBox[{"\[Pi]", "/", "3"}], "]"}]}], "*", RowBox[{"cosLobeDir", "[", RowBox[{"[", "2", "]"}], "]"}]}], ",", "\[IndentingNewLine]", RowBox[{ RowBox[{"Sqrt", "[", RowBox[{"\[Pi]", "/", "3"}], "]"}], "*", RowBox[{"cosLobeDir", "[", RowBox[{"[", "3", "]"}], "]"}]}], ",", "\[IndentingNewLine]", RowBox[{ RowBox[{"-", RowBox[{"Sqrt", "[", RowBox[{"\[Pi]", "/", "3"}], "]"}]}], "*", RowBox[{"cosLobeDir", "[", RowBox[{"[", "1", "]"}], "]"}]}]}], "}"}]}], ";"}], "\[IndentingNewLine]", "\[IndentingNewLine]", RowBox[{"SphericalPlot3D", "[", "\[IndentingNewLine]", RowBox[{ RowBox[{"unprojSh2", "[", RowBox[{"shCosLobe", ",", "\[Theta]", ",", "\[Phi]"}], "]"}], ",", "\[IndentingNewLine]", RowBox[{"{", RowBox[{"\[Theta]", ",", "0", ",", "\[Pi]"}], "}"}], ",", RowBox[{"{", RowBox[{"\[Phi]", ",", "0", ",", RowBox[{"2", " ", "\[Pi]"}]}], "}"}], ",", RowBox[{"PlotRange", "\[Rule]", RowBox[{"{", RowBox[{ RowBox[{"-", "1"}], ",", "1"}], "}"}]}], ",", "\[IndentingNewLine]", RowBox[{"ColorFunction", "\[Rule]", RowBox[{"(", RowBox[{ RowBox[{ RowBox[{"ColorData", "[", "\"\\"", "]"}], "[", "#6", "]"}], "&"}], ")"}]}], ",", "\[IndentingNewLine]", RowBox[{"PlotStyle", "\[Rule]", RowBox[{"Directive", "[", RowBox[{"Opacity", "[", "0.5", "]"}], "]"}]}], ",", "\[IndentingNewLine]", RowBox[{"Axes", "\[Rule]", "True"}], " ", ",", " ", RowBox[{"AxesStyle", "\[Rule]", RowBox[{"{", RowBox[{"Red", ",", "Green", ",", "Blue"}], "}"}]}]}], "\[IndentingNewLine]", "]"}], "\[IndentingNewLine]", "\[IndentingNewLine]", "\[IndentingNewLine]", RowBox[{"Print", "[", "\"\\"", "]"}], "\[IndentingNewLine]", RowBox[{"Integrate", "[", "\[IndentingNewLine]", RowBox[{ RowBox[{"1", "*", RowBox[{"Abs", "[", RowBox[{"Sin", "[", "\[Theta]", "]"}], "]"}]}], "\[IndentingNewLine]", ",", RowBox[{"{", RowBox[{"\[Theta]", ",", "0", ",", "\[Pi]"}], "}"}], ",", RowBox[{"{", RowBox[{"\[Phi]", ",", "0", ",", RowBox[{"2", "\[Pi]"}]}], "}"}]}], "]"}], "\[IndentingNewLine]", RowBox[{ "Print", "[", "\"\\"", "]"}], "\[IndentingNewLine]", RowBox[{"Integrate", "[", "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"unprojSh2", "[", RowBox[{"shCosLobe", ",", "\[Theta]", ",", "\[Phi]"}], "]"}], "*", RowBox[{"Sin", "[", "\[Theta]", "]"}]}], "\[IndentingNewLine]", ",", RowBox[{"{", RowBox[{"\[Theta]", ",", "0", ",", "\[Pi]"}], "}"}], ",", RowBox[{"{", RowBox[{"\[Phi]", ",", "0", ",", RowBox[{"2", "\[Pi]"}]}], "}"}]}], "]"}]}]}]], "Input"], Cell["", "PageBreak", PageBreakBelow->True], Cell["", "PageBreak", PageBreakBelow->True], Cell[BoxData[ RowBox[{ RowBox[{"(*", " ", "\[IndentingNewLine]", " ", RowBox[{ RowBox[{"Definition", " ", "of", " ", "a", " ", "few", " ", "phase", " ", RowBox[{"functions", ":", " ", RowBox[{ RowBox[{"(", "1", ")"}], " ", "schlick", " ", "approximation"}]}]}], ",", " ", RowBox[{ RowBox[{ RowBox[{"(", "2", ")"}], " ", "Henyey"}], "-", RowBox[{"Greenstein", " ", "and"}]}], ",", " ", RowBox[{ RowBox[{ RowBox[{"(", "3", ")"}], " ", "Cornette"}], "-", RowBox[{ "Shanks", "\[IndentingNewLine]", " ", "Integrale", " ", "of", " ", "phase", " ", "function", " ", "over", " ", "the", " ", "unit", " ", "sphere", " ", "should", " ", "be", " ", "1", " ", RowBox[{ RowBox[{"(", RowBox[{"it", " ", "is", " ", "a", " ", "unitless", " ", "function"}], ")"}], "."}]}]}]}], "\[IndentingNewLine]", "*)"}], "\[IndentingNewLine]", "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"phaseFuncSchlick", "[", RowBox[{"G_", ",", " ", "A_"}], "]"}], " ", ":=", "\[IndentingNewLine]", RowBox[{ RowBox[{"{", "\[IndentingNewLine]", RowBox[{ RowBox[{"k", " ", "=", " ", RowBox[{ RowBox[{"1.55", "*", "G"}], " ", "-", " ", RowBox[{"0.55", "*", "G", "*", "G", "*", "G"}]}]}], ";", "\[IndentingNewLine]", RowBox[{"tmp", " ", "=", " ", RowBox[{"1.0", " ", "+", " ", RowBox[{"k", "*", RowBox[{"Cos", "[", "A", "]"}]}]}]}], ";", "\[IndentingNewLine]", RowBox[{ RowBox[{"(", RowBox[{"1", "-", RowBox[{"k", "*", "k"}]}], ")"}], "/", RowBox[{"(", RowBox[{"(", RowBox[{"4.0", "*", "\[Pi]", "*", "tmp", "*", "tmp"}], ")"}], ")"}]}]}], "\[IndentingNewLine]", "}"}], "[", RowBox[{"[", "1", "]"}], "]"}]}], "\[IndentingNewLine]", RowBox[{ RowBox[{"phaseHG", "[", RowBox[{"G_", ",", " ", "A_"}], "]"}], " ", ":=", "\[IndentingNewLine]", RowBox[{ RowBox[{"{", "\[IndentingNewLine]", RowBox[{ RowBox[{"(", RowBox[{"1", "-", RowBox[{"G", "*", "G"}]}], ")"}], "/", RowBox[{"(", RowBox[{"4.0", "*", "Pi", "*", RowBox[{ RowBox[{"(", RowBox[{"1", "+", RowBox[{"G", "*", "G"}], "-", RowBox[{"2", "*", "G", "*", RowBox[{"Cos", "[", "A", "]"}]}]}], ")"}], "^", "1.5"}]}], ")"}]}], "\[IndentingNewLine]", "}"}], "[", RowBox[{"[", "1", "]"}], "]"}]}], "\[IndentingNewLine]", RowBox[{"(*", RowBox[{ RowBox[{"Cornette", "-", RowBox[{"Shanks", " ", "phase", " ", "function", " ", RowBox[{"http", ":"}]}]}], "//", RowBox[{ RowBox[{ RowBox[{ RowBox[{"www", ".", "csroc", ".", "org", ".", "tw"}], "/", "journal"}], "/", "JOC25"}], "-", RowBox[{"3", "/", "JOC25"}], "-", "3", "-", RowBox[{"2.", "pdf"}]}]}], "*)"}], "\[IndentingNewLine]", RowBox[{ RowBox[{"phaseCS", "[", RowBox[{"G_", ",", " ", "A_"}], "]"}], " ", ":=", "\[IndentingNewLine]", RowBox[{ RowBox[{"{", "\[IndentingNewLine]", RowBox[{ RowBox[{"(", RowBox[{"3", "*", RowBox[{"(", RowBox[{"1", "-", RowBox[{"G", "*", "G"}]}], ")"}], "*", RowBox[{"(", RowBox[{"1", "+", RowBox[{ RowBox[{"Cos", "[", "A", "]"}], "*", RowBox[{"Cos", "[", "A", "]"}]}]}], ")"}]}], ")"}], "/", RowBox[{"(", RowBox[{"4.0", "*", "\[Pi]", "*", "2", "*", RowBox[{"(", RowBox[{"2", "+", RowBox[{"G", "*", "G"}]}], ")"}], "*", RowBox[{"(", RowBox[{ RowBox[{"(", RowBox[{"1", "+", RowBox[{"G", "*", "G"}], "-", RowBox[{"2", "*", "G", "*", RowBox[{"Cos", "[", "A", "]"}]}]}], ")"}], "^", "1.5"}], ")"}]}], ")"}]}], "\[IndentingNewLine]", "}"}], "[", RowBox[{"[", "1", "]"}], "]"}]}], "\[IndentingNewLine]", "\[IndentingNewLine]", "\[IndentingNewLine]", RowBox[{ "Print", "[", "\"\\"", "]"}], "\[IndentingNewLine]", RowBox[{"Integrate", "[", "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"phaseHG", "[", RowBox[{"0.0", ",", " ", "\[Theta]"}], "]"}], " ", "*", RowBox[{"Sin", "[", "\[Theta]", "]"}]}], "\[IndentingNewLine]", ",", RowBox[{"{", RowBox[{"\[Theta]", ",", "0", ",", "\[Pi]"}], "}"}], ",", RowBox[{"{", RowBox[{"\[Phi]", ",", "0", ",", RowBox[{"2", " ", "Pi"}]}], "}"}]}], "]"}], "\[IndentingNewLine]", RowBox[{"Integrate", "[", "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"phaseHG", "[", RowBox[{"0.9", ",", " ", "\[Theta]"}], "]"}], " ", "*", RowBox[{"Sin", "[", "\[Theta]", "]"}]}], "\[IndentingNewLine]", ",", RowBox[{"{", RowBox[{"\[Theta]", ",", "0", ",", "\[Pi]"}], "}"}], ",", RowBox[{"{", RowBox[{"\[Phi]", ",", "0", ",", RowBox[{"2", " ", "Pi"}]}], "}"}]}], "]"}], "\[IndentingNewLine]", RowBox[{"Integrate", "[", "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"phaseFuncSchlick", "[", RowBox[{"0.0", ",", " ", "\[Theta]"}], "]"}], " ", "*", RowBox[{"Sin", "[", "\[Theta]", "]"}]}], "\[IndentingNewLine]", ",", RowBox[{"{", RowBox[{"\[Theta]", ",", "0", ",", "\[Pi]"}], "}"}], ",", RowBox[{"{", RowBox[{"\[Phi]", ",", "0", ",", RowBox[{"2", " ", "Pi"}]}], "}"}]}], "]"}], "\[IndentingNewLine]", RowBox[{"Integrate", "[", "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"phaseFuncSchlick", "[", RowBox[{"0.9", ",", " ", "\[Theta]"}], "]"}], " ", "*", RowBox[{"Sin", "[", "\[Theta]", "]"}]}], "\[IndentingNewLine]", ",", RowBox[{"{", RowBox[{"\[Theta]", ",", "0", ",", "\[Pi]"}], "}"}], ",", RowBox[{"{", RowBox[{"\[Phi]", ",", "0", ",", RowBox[{"2", " ", "Pi"}]}], "}"}]}], "]"}], "\[IndentingNewLine]", RowBox[{"Integrate", "[", "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"phaseCS", "[", RowBox[{"0.0", ",", " ", "\[Theta]"}], "]"}], " ", "*", RowBox[{"Sin", "[", "\[Theta]", "]"}]}], "\[IndentingNewLine]", ",", RowBox[{"{", RowBox[{"\[Theta]", ",", "0", ",", "\[Pi]"}], "}"}], ",", RowBox[{"{", RowBox[{"\[Phi]", ",", "0", ",", RowBox[{"2", " ", "Pi"}]}], "}"}]}], "]"}], "\[IndentingNewLine]", RowBox[{"Integrate", "[", "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"phaseCS", "[", RowBox[{"0.9", ",", " ", "\[Theta]"}], "]"}], " ", "*", RowBox[{"Sin", "[", "\[Theta]", "]"}]}], "\[IndentingNewLine]", ",", RowBox[{"{", RowBox[{"\[Theta]", ",", "0", ",", "\[Pi]"}], "}"}], ",", RowBox[{"{", RowBox[{"\[Phi]", ",", "0", ",", RowBox[{"2", " ", "Pi"}]}], "}"}]}], "]"}]}]}]], "Input"], Cell[BoxData[ RowBox[{ RowBox[{"(*", " ", "\[IndentingNewLine]", " ", RowBox[{ RowBox[{ RowBox[{ "Plot", " ", "of", " ", "the", " ", "different", " ", "phase", " ", "functions", " ", "as", " ", "well", " ", "as", " ", "the", " ", "SH2", " ", "approximation", " ", "presented", " ", "in", " ", RowBox[{"https", ":"}]}], "//", RowBox[{ RowBox[{ RowBox[{ RowBox[{ RowBox[{"bartwronski", ".", "files", ".", "wordpress", ".", "com"}], "/", "2014"}], "/", "08"}], "/", "bwronski_volumetric"}], "_fog", RowBox[{ "_siggraph2014", ".", "pdf", ".", "\[IndentingNewLine]", " ", "The"}], " ", "integral", " ", "of", " ", "all", " ", "the", " ", "phase", " ", "functions"}]}], ",", " ", RowBox[{ "as", " ", "well", " ", "as", " ", "the", " ", "SH", " ", "approximation"}], ",", " ", RowBox[{"is", " ", "1", " ", "as", " ", "expected", " ", RowBox[{ RowBox[{"(", RowBox[{"unitless", " ", "function"}], ")"}], "."}]}]}], "\[IndentingNewLine]", "*)"}], "\[IndentingNewLine]", "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"g", " ", "=", " ", "0.3"}], ";"}], "\[IndentingNewLine]", RowBox[{ RowBox[{"phaseDir", " ", "=", " ", RowBox[{"{", RowBox[{"1", ",", "0", ",", "0"}], "}"}]}], ";"}], "\[IndentingNewLine]", "\[IndentingNewLine]", RowBox[{ RowBox[{"shPhaseLobe", "[", RowBox[{"g_", ",", "d_"}], "]"}], ":=", RowBox[{"{", "\[IndentingNewLine]", RowBox[{"0.28209479177387814347403972578039", ",", "\[IndentingNewLine]", RowBox[{ RowBox[{"-", "0.48860251190291992158638462283836"}], "*", "g", "*", RowBox[{"d", "[", RowBox[{"[", "2", "]"}], "]"}]}], ",", "\[IndentingNewLine]", RowBox[{"0.48860251190291992158638462283836", "*", "g", "*", RowBox[{"d", "[", RowBox[{"[", "3", "]"}], "]"}]}], ",", "\[IndentingNewLine]", RowBox[{ RowBox[{"-", "0.48860251190291992158638462283836"}], "*", "g", "*", RowBox[{"d", "[", RowBox[{"[", "1", "]"}], "]"}]}]}], "\[IndentingNewLine]", "}"}]}], "\[IndentingNewLine]", RowBox[{ RowBox[{"shPhase", " ", "=", " ", RowBox[{"shPhaseLobe", "[", RowBox[{"g", ",", " ", "phaseDir"}], "]"}]}], ";"}], "\[IndentingNewLine]", "\[IndentingNewLine]", RowBox[{ "Print", "[", "\"\\"", "]"}], "\[IndentingNewLine]", RowBox[{"Table", "[", "\[IndentingNewLine]", RowBox[{ RowBox[{"{", "\[IndentingNewLine]", RowBox[{ RowBox[{"SphericalPlot3D", "[", "\[IndentingNewLine]", RowBox[{ RowBox[{"phaseHG", "[", RowBox[{"g", " ", ",", " ", RowBox[{"ArcCos", "[", RowBox[{"Dot", "[", RowBox[{ RowBox[{"aToD", "[", RowBox[{"\[Theta]", ",", "\[Phi]"}], "]"}], ",", "phaseDir"}], "]"}], "]"}]}], "]"}], ",", "\[IndentingNewLine]", RowBox[{"{", RowBox[{"\[Theta]", ",", "0", ",", "\[Pi]"}], "}"}], ",", RowBox[{"{", RowBox[{"\[Phi]", ",", "0", ",", RowBox[{"2", " ", "\[Pi]"}]}], "}"}], ",", RowBox[{"PlotRange", "\[Rule]", RowBox[{"{", RowBox[{ RowBox[{"-", "0.35"}], ",", "0.35"}], "}"}]}], ",", "\[IndentingNewLine]", RowBox[{"ColorFunction", "\[Rule]", RowBox[{"(", RowBox[{ RowBox[{ RowBox[{"ColorData", "[", "\"\\"", "]"}], "[", "#6", "]"}], "&"}], ")"}]}], ",", "\[IndentingNewLine]", RowBox[{"PlotStyle", "\[Rule]", RowBox[{"Directive", "[", RowBox[{"Opacity", "[", "0.5", "]"}], "]"}]}], ",", "\[IndentingNewLine]", RowBox[{"Axes", "\[Rule]", "True"}], " ", ",", " ", RowBox[{"AxesStyle", "\[Rule]", RowBox[{"{", RowBox[{"Red", ",", "Green", ",", "Blue"}], "}"}]}], ",", " ", RowBox[{"ImageSize", "\[Rule]", "170"}]}], "\[IndentingNewLine]", "]"}], ",", "\[IndentingNewLine]", RowBox[{"SphericalPlot3D", "[", "\[IndentingNewLine]", RowBox[{ RowBox[{"phaseCS", "[", RowBox[{"g", " ", ",", " ", RowBox[{"ArcCos", "[", RowBox[{"Dot", "[", RowBox[{ RowBox[{"aToD", "[", RowBox[{"\[Theta]", ",", "\[Phi]"}], "]"}], ",", "phaseDir"}], "]"}], "]"}]}], "]"}], ",", "\[IndentingNewLine]", RowBox[{"{", RowBox[{"\[Theta]", ",", "0", ",", "\[Pi]"}], "}"}], ",", RowBox[{"{", RowBox[{"\[Phi]", ",", "0", ",", RowBox[{"2", " ", "\[Pi]"}]}], "}"}], ",", RowBox[{"PlotRange", "\[Rule]", RowBox[{"{", RowBox[{ RowBox[{"-", "0.35"}], ",", "0.35"}], "}"}]}], ",", "\[IndentingNewLine]", RowBox[{"ColorFunction", "\[Rule]", RowBox[{"(", RowBox[{ RowBox[{ RowBox[{"ColorData", "[", "\"\\"", "]"}], "[", "#6", "]"}], "&"}], ")"}]}], ",", "\[IndentingNewLine]", RowBox[{"PlotStyle", "\[Rule]", RowBox[{"Directive", "[", RowBox[{"Opacity", "[", "0.5", "]"}], "]"}]}], ",", "\[IndentingNewLine]", RowBox[{"Axes", "\[Rule]", "True"}], " ", ",", " ", RowBox[{"AxesStyle", "\[Rule]", RowBox[{"{", RowBox[{"Red", ",", "Green", ",", "Blue"}], "}"}]}], ",", " ", RowBox[{"ImageSize", "\[Rule]", "170"}]}], "\[IndentingNewLine]", "]"}], ",", "\[IndentingNewLine]", RowBox[{"SphericalPlot3D", "[", "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"shPhase", " ", "=", " ", RowBox[{"shPhaseLobe", "[", RowBox[{"g", ",", " ", "phaseDir"}], "]"}]}], ";", "\[IndentingNewLine]", RowBox[{"unprojSh2", "[", RowBox[{"shPhase", ",", "\[Theta]", ",", "\[Phi]"}], "]"}]}], ",", "\[IndentingNewLine]", RowBox[{"{", RowBox[{"\[Theta]", ",", "0", ",", "\[Pi]"}], "}"}], ",", RowBox[{"{", RowBox[{"\[Phi]", ",", "0", ",", RowBox[{"2", " ", "\[Pi]"}]}], "}"}], ",", RowBox[{"PlotRange", "\[Rule]", RowBox[{"{", RowBox[{ RowBox[{"-", "0.35"}], ",", "0.35"}], "}"}]}], ",", "\[IndentingNewLine]", RowBox[{"ColorFunction", "\[Rule]", RowBox[{"(", RowBox[{ RowBox[{ RowBox[{"ColorData", "[", "\"\\"", "]"}], "[", "#6", "]"}], "&"}], ")"}]}], ",", "\[IndentingNewLine]", RowBox[{"PlotStyle", "\[Rule]", RowBox[{"Directive", "[", RowBox[{"Opacity", "[", "0.5", "]"}], "]"}]}], ",", "\[IndentingNewLine]", RowBox[{"Axes", "\[Rule]", "True"}], " ", ",", " ", RowBox[{"AxesStyle", "\[Rule]", RowBox[{"{", RowBox[{"Red", ",", "Green", ",", "Blue"}], "}"}]}], ",", " ", RowBox[{"ImageSize", "\[Rule]", "170"}]}], "\[IndentingNewLine]", "]"}]}], "\[IndentingNewLine]", "}"}], "\[IndentingNewLine]", RowBox[{"(*", RowBox[{ "phaseCS", " ", "could", " ", "be", " ", "approximated", " ", "nicely", " ", "with", " ", "two", " ", "sh2", " ", RowBox[{"lob", "?"}]}], "*)"}], "\[IndentingNewLine]", ",", "\[IndentingNewLine]", RowBox[{"{", RowBox[{"g", ",", RowBox[{"{", RowBox[{"0.0", ",", "0.1", ",", "0.5", ",", "0.9"}], "}"}]}], "}"}]}], "\[IndentingNewLine]", "]"}], "\[IndentingNewLine]", "\[IndentingNewLine]", "\[IndentingNewLine]", RowBox[{"Print", "[", RowBox[{"\"\\"", ",", "g"}], "]"}], "\[IndentingNewLine]", RowBox[{"Integrate", "[", "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"unprojSh2", "[", RowBox[{"shPhase", ",", "\[Theta]", ",", "\[Phi]"}], "]"}], "*", RowBox[{"Sin", "[", "\[Theta]", "]"}]}], "\[IndentingNewLine]", ",", RowBox[{"{", RowBox[{"\[Theta]", ",", "0", ",", "\[Pi]"}], "}"}], ",", RowBox[{"{", RowBox[{"\[Phi]", ",", "0", ",", RowBox[{"2", "\[Pi]"}]}], "}"}]}], "]"}], "\[IndentingNewLine]"}]}]], "Input"] }, WindowSize->{858, 943}, WindowMargins->{{0, Automatic}, {Automatic, 0}}, PrintingCopies->1, PrintingPageRange->{32000, 32000}, PrintingOptions->{"Magnification"->1., "PaperOrientation"->"Portrait", "PaperSize"->{612, 792}}, TrackCellChangeTimes->False, Magnification->1.100000023841858, FrontEndVersion->"9.0 for Microsoft Windows (64-bit) (November 20, 2012)", StyleDefinitions->FrontEnd`FileName[{"Report"}, "StandardReport.nb", CharacterEncoding -> "WindowsANSI"] ] (* End of Notebook Content *) (* Internal cache information *) (*CellTagsOutline CellTagsIndex->{} *) (*CellTagsIndex CellTagsIndex->{} *) (*NotebookFileOutline Notebook[{ Cell[557, 20, 635, 15, 103, "Input"], Cell[1195, 37, 269, 6, 63, "Input"], Cell[1467, 45, 4110, 104, 623, "Input"], Cell[5580, 151, 4810, 122, 623, "Input"], Cell[10393, 275, 44, 1, 1, "PageBreak", PageBreakBelow->True], Cell[10440, 278, 44, 1, 4, "PageBreak", PageBreakBelow->True], Cell[10487, 281, 7158, 181, 883, "Input"], Cell[17648, 464, 8553, 201, 1146, "Input"] } ] *) (* End of internal cache information *)