{"id":1343,"date":"2023-11-19T22:52:29","date_gmt":"2023-11-19T13:52:29","guid":{"rendered":"https:\/\/xn--k10aa.com\/?p=1343"},"modified":"2024-10-29T18:15:22","modified_gmt":"2024-10-29T09:15:22","slug":"202hw2","status":"publish","type":"post","link":"https:\/\/remoooo.com\/en\/202hw2\/","title":{"rendered":"Games202 Assignment 2 PRT Implementation"},"content":{"rendered":"<div class=\"wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-6c531013 wp-block-group-is-layout-flex\">\n<figure class=\"wp-block-embed aligncenter is-type-wp-embed is-provider-remo wp-block-embed-remo\"><div class=\"wp-block-embed__wrapper\">\nhttps:\/\/remoooo.com\/202hw1\n<\/div><figcaption class=\"wp-element-caption\">Previous<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-embed is-type-wp-embed is-provider-remo wp-block-embed-remo\"><div class=\"wp-block-embed__wrapper\">\n<blockquote class=\"wp-embedded-content\" data-secret=\"SoZzEXNtpB\"><a href=\"https:\/\/remoooo.com\/en\/202hw3\/\">Games202 Assignment 3 SSR Implementation<\/a><\/blockquote><iframe class=\"wp-embedded-content lazyload\" sandbox=\"allow-scripts\" security=\"restricted\" style=\"position: absolute; visibility: hidden;\" title=\"&quot;Games202 Assignment 3 SSR Implementation&quot; - Remo\" data-src=\"https:\/\/remoooo.com\/202hw3\/embed\/#?secret=xOT1Bl9aWK#?secret=SoZzEXNtpB\" data-secret=\"SoZzEXNtpB\" width=\"500\" height=\"282\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe>\n<\/div><figcaption class=\"wp-element-caption\">Next<\/figcaption><\/figure>\n<\/div>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-218.png\" alt=\"img\" class=\"wp-image-1344 lazyload\"\/><noscript><img decoding=\"async\" width=\"1440\" height=\"496\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-218.png\" alt=\"img\" class=\"wp-image-1344 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-218.png 1440w, https:\/\/remoooo.com\/wp-content\/uploads\/image-218-300x103.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-218-1024x353.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-218-768x265.png 768w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/noscript><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-3.gif\" alt=\"img\" class=\"wp-image-1346 lazyload\"\/><noscript><img decoding=\"async\" width=\"300\" height=\"200\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-3.gif\" alt=\"img\" class=\"wp-image-1346 lazyload\"\/><\/noscript><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-219.png\" alt=\"img\" class=\"wp-image-1345 lazyload\"\/><noscript><img decoding=\"async\" width=\"1074\" height=\"718\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-219.png\" alt=\"img\" class=\"wp-image-1345 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-219.png 1074w, https:\/\/remoooo.com\/wp-content\/uploads\/image-219-300x201.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-219-1024x685.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-219-768x513.png 768w\" sizes=\"(max-width: 1074px) 100vw, 1074px\" \/><\/noscript><\/figure>\n\n\n\n<p>Because I am also a newbie, I can&#039;t ensure that everything is correct. I hope the experts can correct me.<\/p>\n\n\n\n<p>Zhihu&#039;s formula is a bit ugly, you can go to:<a href=\"https:\/\/github.com\/Remyuu\/GAMES202-Notes\/blob\/main\/HW2\uff1a\u7403\u8c10\u51fd\u6570\u5b9e\u73b0.md\" data-type=\"link\" data-id=\"https:\/\/github.com\/Remyuu\/GAMES202-Notes\/blob\/main\/HW2\uff1a\u7403\u8c10\u51fd\u6570\u5b9e\u73b0.md\">GitHub<\/a><\/p>\n\n\n\n<p>Project source code:<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/Remyuu\/GAMES202-Homeworkgithub.com\/Remyuu\/GAMES202-Homework\">https:\/\/github.com\/Remyuu\/GAMES202-Homeworkgithub.com\/Remyuu\/GAMES202-Homework<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Precomputed spherical harmonic coefficients<\/h3>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>The spherical harmonics coefficients are pre-computed using the framework nori.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">Ambient lighting: Calculate the spherical harmonic coefficients for each pixel of the cubemap<\/h2>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>ProjEnv::PrecomputeCubemapSH(images, width, height, channel); Use the Riemann integral method to calculate the coefficients of the ambient light spherical harmonics.<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">Complete code<\/h3>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ TODO: here you need to compute light sh of each face of cubemap of each pixel\/\/ TODO: \u6b64\u5904\u4f60\u9700\u8981\u8ba1\u7b97\u6bcf\u4e2a\u50cf\u7d20\u4e0bcubemap\u67d0\u4e2a\u9762\u7684\u7403\u8c10\u7cfb\u6570Eigen::Vector3f dir = cubemapDirs[i * width * height + y * width + x];int index = (y * width + x) * channel;Eigen::Array3f Le(images[i][index + 0], images[i][index + 1],                  images[i][index + 2]);\/\/ \u63cf\u8ff0\u5728\u7403\u9762\u5750\u6807\u4e0a\u5f53\u524d\u7684\u89d2\u5ea6double theta = acos(dir.z());double phi = atan2(dir.y(), dir.x());\/\/ \u904d\u5386\u7403\u8c10\u51fd\u6570\u7684\u5404\u4e2a\u57fa\u51fd\u6570for (int l = 0; l <= SHOrder; l++){    for (int m = -l; m <= l; m++){        float sh = sh::EvalSH(l, m, phi, theta);        float delta = CalcArea((float)x, (float)y, width, height);        SHCoeffiecents[l*(l+1)+m] += Le * sh * delta;    }}\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/\/ TODO: here you need to compute light sh of each face of cubemap of each pixel<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ TODO: Here you need to calculate the spherical harmonic coefficients of a certain face of the cubemap for each pixel<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C8C8C8\">Eigen<\/span><span style=\"color: #D4D4D4\">::<\/span><span style=\"color: #4EC9B0\">Vector3f<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">dir<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">cubemapDirs<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">width<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">height<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #9CDCFE\">y<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">width<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\">];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">index<\/span><span style=\"color: #D4D4D4\"> = (<\/span><span style=\"color: #9CDCFE\">y<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">width<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\">) * <\/span><span style=\"color: #9CDCFE\">channel<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C8C8C8\">Eigen<\/span><span style=\"color: #D4D4D4\">::<\/span><span style=\"color: #4EC9B0\">Array3f<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">Le<\/span><span style=\"color: #D4D4D4\">(images[<\/span><span style=\"color: #4EC9B0\">i<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #4EC9B0\">index<\/span><span style=\"color: #D4D4D4\"> + 0], images[<\/span><span style=\"color: #4EC9B0\">i<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #4EC9B0\">index<\/span><span style=\"color: #D4D4D4\"> + 1],<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                  images[<\/span><span style=\"color: #4EC9B0\">i<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #4EC9B0\">index<\/span><span style=\"color: #D4D4D4\"> + 2]);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Describe the current angle in spherical coordinates<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">double<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">theta<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">acos<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">dir<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">z<\/span><span style=\"color: #D4D4D4\">());<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">double<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">phi<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">atan2<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">dir<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">y<\/span><span style=\"color: #D4D4D4\">(), <\/span><span style=\"color: #9CDCFE\">dir<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">x<\/span><span style=\"color: #D4D4D4\">());<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Traverse each basis function of spherical harmonics<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">l<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">l<\/span><span style=\"color: #D4D4D4\"> &lt;= <\/span><span style=\"color: #9CDCFE\">SHOrder<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">l<\/span><span style=\"color: #D4D4D4\">++){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">m<\/span><span style=\"color: #D4D4D4\"> = -<\/span><span style=\"color: #9CDCFE\">l<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">m<\/span><span style=\"color: #D4D4D4\"> &lt;= <\/span><span style=\"color: #9CDCFE\">l<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">m<\/span><span style=\"color: #D4D4D4\">++){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">sh<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">sh<\/span><span style=\"color: #D4D4D4\">::<\/span><span style=\"color: #DCDCAA\">EvalSH<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">l<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">m<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">phi<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">theta<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">delta<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">CalcArea<\/span><span style=\"color: #D4D4D4\">((<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\">)<\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\">, (<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\">)<\/span><span style=\"color: #9CDCFE\">y<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">width<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">height<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">SHCoeffiecents<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">l<\/span><span style=\"color: #D4D4D4\">*(<\/span><span style=\"color: #9CDCFE\">l<\/span><span style=\"color: #D4D4D4\">+<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">)+<\/span><span style=\"color: #9CDCFE\">m<\/span><span style=\"color: #D4D4D4\">] += <\/span><span style=\"color: #9CDCFE\">Le<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">sh<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">delta<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">analyze<\/h3>\n\n\n\n<p><strong>Spherical harmonic coefficients<\/strong>It is the projection of the spherical harmonic function on a sphere, which can be used to represent the distribution of the function on the sphere. Since we have three channels of RGB values, the spherical harmonic coefficients we will store as a three-dimensional vector. Parts that need to be improved:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/\/ prt.cpp - PrecomputeCubemapSH()\/\/ TODO: here you need to compute light sh of each face of cubemap of each pixel\/\/ TODO: \u6b64\u5904\u4f60\u9700\u8981\u8ba1\u7b97\u6bcf\u4e2a\u50cf\u7d20\u4e0bcubemap\u67d0\u4e2a\u9762\u7684\u7403\u8c10\u7cfb\u6570Eigen::Vector3f dir = cubemapDirs[i * width * height + y * width + x];int index = (y * width + x) * channel;Eigen::Array3f Le(images[i][index + 0], images[i][index + 1],                  images[i][index + 2]);\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/\/\/ prt.cpp - PrecomputeCubemapSH()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ TODO: here you need to compute light sh of each face of cubemap of each pixel<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ TODO: Here you need to calculate the spherical harmonic coefficients of a certain face of the cubemap for each pixel<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C8C8C8\">Eigen<\/span><span style=\"color: #D4D4D4\">::<\/span><span style=\"color: #4EC9B0\">Vector3f<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">dir<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">cubemapDirs<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">width<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">height<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #9CDCFE\">y<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">width<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\">];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">index<\/span><span style=\"color: #D4D4D4\"> = (<\/span><span style=\"color: #9CDCFE\">y<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">width<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\">) * <\/span><span style=\"color: #9CDCFE\">channel<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C8C8C8\">Eigen<\/span><span style=\"color: #D4D4D4\">::<\/span><span style=\"color: #4EC9B0\">Array3f<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">Le<\/span><span style=\"color: #D4D4D4\">(images[<\/span><span style=\"color: #4EC9B0\">i<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #4EC9B0\">index<\/span><span style=\"color: #D4D4D4\"> + 0], images[<\/span><span style=\"color: #4EC9B0\">i<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #4EC9B0\">index<\/span><span style=\"color: #D4D4D4\"> + 1],<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                  images[<\/span><span style=\"color: #4EC9B0\">i<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #4EC9B0\">index<\/span><span style=\"color: #D4D4D4\"> + 2]);<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<p>First, we sample a direction (a 3D vector representing the direction from the center to the pixel) from each pixel of the six cubemaps (the images array) and convert the direction to spherical coordinates (theta and phi).<\/p>\n\n\n\n<p>Then, each spherical coordinate is passed into sh::EvalSH() to calculate the real value sh of each spherical harmonic function (basis function) and the proportion delta of the spherical area occupied by each pixel in each cubemap is calculated.<\/p>\n\n\n\n<p>Finally, we accumulate the spherical harmonic coefficients. In the code, we can accumulate all the pixels of the cubemap, which is similar to the original operation of calculating the integral of the spherical harmonic function.<\/p>\n\n\n\n<p>$$<br>Ylm=\u222b\u03d5=02\u03c0\u222b\u03b8=0\u03c0f(\u03b8,\u03d5)Ylm(\u03b8,\u03d5)sin\u2061(\u03b8)d\u03b8d\u03d5<br>$$<\/p>\n\n\n\n<p>in:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u03b8 is the zenith angle, ranging from 0 to \u03c0; \u03d5 is the azimuth angle, ranging from 0 to 2pi.<\/li>\n\n\n\n<li>f(\u03b8,\u03d5) is the value of the function at a point on the sphere.<\/li>\n\n\n\n<li>Ylm is a spherical harmonic function, which consists of the corresponding Legendre polynomials Plm and some trigonometric functions.<\/li>\n\n\n\n<li>l is the order of the spherical harmonics; m is the ordinal number of the spherical harmonics, ranging from \u2212l to l.<\/li>\n<\/ul>\n\n\n\n<p>In order to make the readers understand more specifically, here is the estimate of the discrete form of the spherical harmonics in the code, that is, the Riemann integral method for calculation.<\/p>\n\n\n\n<p>$$<br>Ylm=\u2211i=1Nf(\u03b8i,\u03d5i)Ylm(\u03b8i,\u03d5i)\u0394\u03c9i<br>$$<\/p>\n\n\n\n<p>in:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>f(\u03b8i,\u03d5i) is the value of the function at a point on the sphere.<\/li>\n\n\n\n<li>Ylm(\u03b8i,\u03d5i) is the value of the spherical harmonics at that point.<\/li>\n\n\n\n<li>\u0394\u03c9i is the tiny area or weight of the point on the sphere.<\/li>\n\n\n\n<li>N is the total number of discrete points.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Code Details<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Get RGB lighting information from cubemap<\/strong><\/li>\n<\/ul>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"Eigen::Array3f Le(images[i][index + 0], images[i][index + 1],                  images[i][index + 2]);\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #C8C8C8\">Eigen<\/span><span style=\"color: #D4D4D4\">::<\/span><span style=\"color: #4EC9B0\">Array3f<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">Le<\/span><span style=\"color: #D4D4D4\">(images[<\/span><span style=\"color: #4EC9B0\">i<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #4EC9B0\">index<\/span><span style=\"color: #D4D4D4\"> + 0], images[<\/span><span style=\"color: #4EC9B0\">i<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #4EC9B0\">index<\/span><span style=\"color: #D4D4D4\"> + 1],<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                  images[<\/span><span style=\"color: #4EC9B0\">i<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #4EC9B0\">index<\/span><span style=\"color: #D4D4D4\"> + 2]);<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<p>The value of channel is 3, corresponding to the three channels of RGB. Therefore, index points to the position of the red channel of a pixel, index + 1 points to the position of the green channel, and index + 2 points to the position of the blue channel.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Convert direction vector to spherical coordinates<\/strong><\/li>\n<\/ul>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"double theta = acos(dir.z());double phi = atan2(dir.y(), dir.x());\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #569CD6\">double<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">theta<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">acos<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">dir<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">z<\/span><span style=\"color: #D4D4D4\">());<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">double<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">phi<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">atan2<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">dir<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">y<\/span><span style=\"color: #D4D4D4\">(), <\/span><span style=\"color: #9CDCFE\">dir<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">x<\/span><span style=\"color: #D4D4D4\">());<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<p>theta is the angle from the positive z-axis to the direction of dir, and phi is the angle from the positive x-axis to the projection of dir on the xz plane.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Traversing the basis functions of spherical harmonics<\/strong><\/li>\n<\/ul>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"for (int l = 0; l <= SHOrder; l++){    for (int m = -l; m <= l; m++){        float sh = sh::EvalSH(l, m, phi, theta);        float delta = CalcArea((float)x, (float)y, width, height);        SHCoeffiecents[l*(l+1)+m] += Le * sh * delta;    }}\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">l<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">l<\/span><span style=\"color: #D4D4D4\"> &lt;= <\/span><span style=\"color: #9CDCFE\">SHOrder<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">l<\/span><span style=\"color: #D4D4D4\">++){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">m<\/span><span style=\"color: #D4D4D4\"> = -<\/span><span style=\"color: #9CDCFE\">l<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">m<\/span><span style=\"color: #D4D4D4\"> &lt;= <\/span><span style=\"color: #9CDCFE\">l<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">m<\/span><span style=\"color: #D4D4D4\">++){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">sh<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">sh<\/span><span style=\"color: #D4D4D4\">::<\/span><span style=\"color: #DCDCAA\">EvalSH<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">l<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">m<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">phi<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">theta<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">delta<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">CalcArea<\/span><span style=\"color: #D4D4D4\">((<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\">)<\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\">, (<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\">)<\/span><span style=\"color: #9CDCFE\">y<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">width<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">height<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">SHCoeffiecents<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">l<\/span><span style=\"color: #D4D4D4\">*(<\/span><span style=\"color: #9CDCFE\">l<\/span><span style=\"color: #D4D4D4\">+<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">)+<\/span><span style=\"color: #9CDCFE\">m<\/span><span style=\"color: #D4D4D4\">] += <\/span><span style=\"color: #9CDCFE\">Le<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">sh<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">delta<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Unshadowed diffuse term<\/h2>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>scene-&gt;getIntegrator()-&gt;preprocess(scene); calculation <strong>Diffuse Unshadowed<\/strong> Simplify the rendering equation and substitute the spherical harmonic function in the previous section to further calculate the coefficients of the spherical harmonic projection of the BRDF. The key function is ProjectFunction. We need to write a lambda expression for this function to calculate the transfer function term.<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">analyze<\/h3>\n\n\n\n<p>For the diffuse transmission term, we can<strong>There are three situations<\/strong>consider:<strong>Shadowed<\/strong>,<strong>No shadow<\/strong>and<strong>Mutually Reflective<\/strong>.<\/p>\n\n\n\n<p>Let&#039;s first consider the simplest case without shadows. We have the rendering equation<\/p>\n\n\n\n<p>in,<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>is the incident radiance.<\/li>\n\n\n\n<li>It is a geometric function, and the microscopic properties of the surface are related to the direction of the incident light.<\/li>\n\n\n\n<li>is the incident light direction.<\/li>\n<\/ul>\n\n\n\n<p>For a diffuse surface with equal reflection everywhere, we can simplify to <strong>Unshadowed<\/strong> Lighting equation<\/p>\n\n\n\n<p>in:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>is the diffuse outgoing radiance of the point.<\/li>\n\n\n\n<li>is the surface normal.<\/li>\n<\/ul>\n\n\n\n<p>The incident radiance and transfer function terms are independent of each other, as the former represents the contribution of the light sources in the scene, and the latter represents how the surface responds to the incident light. Therefore, these two components are treated independently.<\/p>\n\n\n\n<p>Specifically, when using spherical harmonics approximation, we expand these two items separately. The input of the former is the incident direction of light, and the input of the latter is the reflection (or outgoing direction), and the expansion is two series of arrays, so we use a data structure called Look-Up Table (LUT).<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"auto shCoeff = sh::ProjectFunction(SHOrder, shFunc, m_SampleCount);\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #4EC9B0\">auto<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">shCoeff<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">sh<\/span><span style=\"color: #D4D4D4\">::<\/span><span style=\"color: #DCDCAA\">ProjectFunction<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">SHOrder<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">shFunc<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">m_SampleCount<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<p>Among them, the most important one is the function ProjectFunction above. We need to write a Lambda expression (shFunc) as a parameter for this function, which is used to calculate the transfer function term.<\/p>\n\n\n\n<p>ProjectFunction function parameter passing:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Spherical harmonic order<\/li>\n\n\n\n<li>Functions that need to be projected onto basis functions (that we need to write)<\/li>\n\n\n\n<li>Number of samples<\/li>\n<\/ul>\n\n\n\n<p>This function will take the result returned by the Lambda function and project it onto the basis function to get the coefficient. Finally, it will add up the coefficients of each sample and multiply them by the weight to get the final coefficient of the vertex.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Complete code<\/h3>\n\n\n\n<p>Compute the geometric terms, i.e. the transfer function terms.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ prt.cpp...double H = wi.normalized().dot(n.normalized()) \/ M_PI;if (m_Type == Type::Unshadowed){    \/\/ TODO: here you need to calculate unshadowed transport term of a given direction    \/\/ TODO: \u6b64\u5904\u4f60\u9700\u8981\u8ba1\u7b97\u7ed9\u5b9a\u65b9\u5411\u4e0b\u7684unshadowed\u4f20\u8f93\u9879\u7403\u8c10\u51fd\u6570\u503c    return (H &gt; 0.0) ? H : 0.0;}\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/\/prt.cpp<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">double<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">H<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">wi<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">normalized<\/span><span style=\"color: #D4D4D4\">().<\/span><span style=\"color: #DCDCAA\">dot<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">n<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">normalized<\/span><span style=\"color: #D4D4D4\">()) \/ <\/span><span style=\"color: #9CDCFE\">M_PI<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">m_Type<\/span><span style=\"color: #D4D4D4\"> == <\/span><span style=\"color: #9CDCFE\">Type<\/span><span style=\"color: #D4D4D4\">::<\/span><span style=\"color: #9CDCFE\">Unshadowed<\/span><span style=\"color: #D4D4D4\">){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ TODO: here you need to calculate unshadowed transport term of a given direction<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ TODO: Here you need to calculate the unshadowed transmission term spherical harmonics value in a given direction<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">H<\/span><span style=\"color: #D4D4D4\"> &gt; <\/span><span style=\"color: #B5CEA8\">0.0<\/span><span style=\"color: #D4D4D4\">) ? <\/span><span style=\"color: #9CDCFE\">H<\/span><span style=\"color: #D4D4D4\"> : <\/span><span style=\"color: #B5CEA8\">0.0<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>In short, remember to divide the final integral result by , and then pass it to m_TransportSHCoeffs.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">Shadowed Diffuse Term<\/h2>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>scene-&gt;getIntegrator()-&gt;preprocess(scene); calculation <strong>Diffuse Shadowed<\/strong> This item has an additional visible item.<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">analyze<\/h3>\n\n\n\n<p>The Visibility item () is a value that is either 1 or 0. The bool rayIntersect(const Ray3f &amp;ray) function is used to reflect a ray from the vertex position to the sampling direction. If it hits the object, it is considered to be blocked and has a shadow, and 0 is returned; if the ray does not hit the object, it is still returned.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Complete code<\/h3>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ prt.cpp...double H = wi.normalized().dot(n.normalized()) \/ M_PI;...else{    \/\/ TODO: here you need to calculate shadowed transport term of a given direction    \/\/ TODO: \u6b64\u5904\u4f60\u9700\u8981\u8ba1\u7b97\u7ed9\u5b9a\u65b9\u5411\u4e0b\u7684shadowed\u4f20\u8f93\u9879\u7403\u8c10\u51fd\u6570\u503c    if (H &gt; 0.0 &amp;&amp; !scene-&gt;rayIntersect(Ray3f(v, wi.normalized())))        return H;    return 0.0;}\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/\/prt.cpp<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">double<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">H<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">wi<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">normalized<\/span><span style=\"color: #D4D4D4\">().<\/span><span style=\"color: #DCDCAA\">dot<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">n<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">normalized<\/span><span style=\"color: #D4D4D4\">()) \/ <\/span><span style=\"color: #9CDCFE\">M_PI<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">else<\/span><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ TODO: here you need to calculate shadowed transport term of a given direction<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ TODO: Here you need to calculate the spherical harmonic value of the shadowed transmission term in a given direction<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">H<\/span><span style=\"color: #D4D4D4\"> &gt; <\/span><span style=\"color: #B5CEA8\">0.0<\/span><span style=\"color: #D4D4D4\"> &amp;&amp; !<\/span><span style=\"color: #9CDCFE\">scene<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #DCDCAA\">rayIntersect<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #DCDCAA\">Ray3f<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">v<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">wi<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">normalized<\/span><span style=\"color: #D4D4D4\">())))<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">H<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #B5CEA8\">0.0<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>In short, remember to divide the final integral result by , and then pass it to m_TransportSHCoeffs.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">Export calculation results<\/h2>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>The nori framework will generate two pre-calculated result files.<\/p>\n<\/blockquote>\n\n\n\n<p>Add run parameters:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\/scenes\/prt.xml<\/code><\/pre>\n\n\n\n<p>In prt.xml, you need to do the following<strong>Revise<\/strong>, you can choose to render the ambient light cubemap. In addition, the model, camera parameters, etc. can also be modified by yourself.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ prt.xml<!-- Render the visible surface normals --&gt;<integrator type=&quot;prt&quot;&gt;    <string name=&quot;type&quot; value=&quot;unshadowed&quot; \/&gt;    <integer name=&quot;bounce&quot; value=&quot;1&quot; \/&gt;    <integer name=&quot;PRTSampleCount&quot; value=&quot;100&quot; \/&gt;<!--        <string name=&quot;cubemap&quot; value=&quot;cubemap\/GraceCathedral&quot; \/&gt;--&gt;<!--        <string name=&quot;cubemap&quot; value=&quot;cubemap\/Indoor&quot; \/&gt;--&gt;<!--        <string name=&quot;cubemap&quot; value=&quot;cubemap\/Skybox&quot; \/&gt;--&gt;    <string name=&quot;cubemap&quot; value=&quot;cubemap\/CornellBox&quot; \/&gt;<\/integrator&gt;\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/\/prt.xml<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">&lt;!-- <\/span><span style=\"color: #9CDCFE\">Render<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">the<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">visible<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">surface<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">normals<\/span><span style=\"color: #D4D4D4\"> --&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #4EC9B0\">integrator<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">type<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #CE9178\">&quot;prt&quot;<\/span><span style=\"color: #D4D4D4\">&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    &lt;<\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">name<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #CE9178\">&quot;type&quot;<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">value<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #CE9178\">&quot;unshadowed&quot;<\/span><span style=\"color: #D4D4D4\"> \/&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    &lt;<\/span><span style=\"color: #9CDCFE\">integer<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">name<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #CE9178\">&quot;bounce&quot;<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">value<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #CE9178\">&quot;1&quot;<\/span><span style=\"color: #D4D4D4\"> \/&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    &lt;<\/span><span style=\"color: #9CDCFE\">integer<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">name<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #CE9178\">&quot;PRTSampleCount&quot;<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">value<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #CE9178\">&quot;100&quot;<\/span><span style=\"color: #D4D4D4\"> \/&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">&lt;!--        &lt;<\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">name<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #CE9178\">&quot;cubemap&quot;<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">value<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #CE9178\">&quot;cubemap\/GraceCathedral&quot;<\/span><span style=\"color: #D4D4D4\"> \/&gt;--&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">&lt;!--        &lt;<\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">name<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #CE9178\">&quot;cubemap&quot;<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">value<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #CE9178\">&quot;cubemap\/Indoor&quot;<\/span><span style=\"color: #D4D4D4\"> \/&gt;--&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">&lt;!--        &lt;<\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">name<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #CE9178\">&quot;cubemap&quot;<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">value<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #CE9178\">&quot;cubemap\/Skybox&quot;<\/span><span style=\"color: #D4D4D4\"> \/&gt;--&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    &lt;<\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">name<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #CE9178\">&quot;cubemap&quot;<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">value<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #CE9178\">&quot;cubemap\/CornellBox&quot;<\/span><span style=\"color: #D4D4D4\"> \/&gt;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">&lt;\/<\/span><span style=\"color: #9CDCFE\">integrator<\/span><span style=\"color: #D4D4D4\">&gt;<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<p>Among them, the label optional value:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>type: unshadowed, shadowed, interreflection<\/li>\n\n\n\n<li>bounce: The number of light bounces under the interreflection type (not yet implemented)<\/li>\n\n\n\n<li>PRTSampleCount: The number of samples per vertex of the transmission item<\/li>\n\n\n\n<li>cubemap: cubemap\/GraceCathedral, cubemap\/Indoor, cubemap\/Skybox, cubemap\/CornellBox<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-222.png\" alt=\"img\" class=\"wp-image-1349 lazyload\"\/><noscript><img decoding=\"async\" width=\"1440\" height=\"496\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-222.png\" alt=\"img\" class=\"wp-image-1349 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-222.png 1440w, https:\/\/remoooo.com\/wp-content\/uploads\/image-222-300x103.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-222-1024x353.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-222-768x265.png 768w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/noscript><\/figure>\n\n\n\n<p>The above pictures are the unshadowed rendering results of GraceCathedral, Indoor, Skybox and CornellBox, with a sampling number of 1.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Coloring using spherical harmonics<\/h2>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Manually drag the files generated by nori into the real-time rendering framework and make some changes to the real-time framework.<\/p>\n<\/blockquote>\n\n\n\n<p>After the calculation in the previous chapter is completed, copy the light.txt and transport.txt in the corresponding cubemap path to the cubemap folder of the real-time rendering framework.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Precomputed data analysis<\/h2>\n\n\n\n<p><strong>Cancel<\/strong> The comments on lines 88-114 in engine.js are used to parse the txt file just added.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ engine.js\/\/ file parsing... \/\/ \u628a\u8fd9\u5757\u4ee3\u7801\u53d6\u6d88\u6ce8\u91ca\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/\/ engine.js<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ file parsing<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">... <\/span><span style=\"color: #6A9955\">\/\/ Uncomment this code<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Import model\/create and use PRT material shader<\/h3>\n\n\n\n<p>In the materials folder<strong>Establish<\/strong>File PRTMaterial.js.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/PRTMaterial.jsclass PRTMaterial extends Material {    constructor(vertexShader, fragmentShader) {        super({            'uPrecomputeL[0]': { type: 'precomputeL', value: null},            'uPrecomputeL[1]': { type: 'precomputeL', value: null},            'uPrecomputeL[2]': { type: 'precomputeL', value: null},        },         ['aPrecomputeLT'],         vertexShader, fragmentShader, null);    }}async function buildPRTMaterial(vertexPath, fragmentPath) {    let vertexShader = await getShaderString(vertexPath);    let fragmentShader = await getShaderString(fragmentPath);    return new PRTMaterial(vertexShader, fragmentShader);}\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/\/PRTMaterial.js<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">class<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">PRTMaterial<\/span><span style=\"color: #D4D4D4\"> extends Material {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">constructor<\/span><span style=\"color: #D4D4D4\">(vertexShader, fragmentShader) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">super<\/span><span style=\"color: #D4D4D4\">({<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #CE9178\">&#039;uPrecomputeL[0]&#039;<\/span><span style=\"color: #D4D4D4\">: { <\/span><span style=\"color: #9CDCFE\">type<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #CE9178\">&#039;precomputeL&#039;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">value<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #569CD6\">null<\/span><span style=\"color: #D4D4D4\">},<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #CE9178\">&#039;uPrecomputeL[1]&#039;<\/span><span style=\"color: #D4D4D4\">: { <\/span><span style=\"color: #9CDCFE\">type<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #CE9178\">&#039;precomputeL&#039;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">value<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #569CD6\">null<\/span><span style=\"color: #D4D4D4\">},<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #CE9178\">&#039;uPrecomputeL[2]&#039;<\/span><span style=\"color: #D4D4D4\">: { <\/span><span style=\"color: #9CDCFE\">type<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #CE9178\">&#039;precomputeL&#039;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">value<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #569CD6\">null<\/span><span style=\"color: #D4D4D4\">},<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }, <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        [<\/span><span style=\"color: #CE9178\">&#039;aPrecomputeLT&#039;<\/span><span style=\"color: #D4D4D4\">], <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">vertexShader<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">fragmentShader<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #569CD6\">null<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">async<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">buildPRTMaterial<\/span><span style=\"color: #D4D4D4\">(vertexPath, fragmentPath) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">vertexShader<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">await<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">getShaderString<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">vertexPath<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">fragmentShader<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">await<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">getShaderString<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">fragmentPath<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">PRTMaterial<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">vertexShader<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">fragmentShader<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<p>Then import it in index.html.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ index.html<script src=&quot;src\/materials\/Material.js&quot; defer&gt;<\/script&gt;\n<script src=&quot;src\/materials\/ShadowMaterial.js&quot; defer&gt;<\/script&gt;\n<script src=&quot;src\/materials\/PhongMaterial.js&quot; defer&gt;<\/script&gt;\n<!-- Edit Start --&gt;<script src=&quot;src\/materials\/PRTMaterial.js&quot; defer&gt;<\/script&gt;<!-- Edit End --&gt;\n<script src=&quot;src\/materials\/SkyBoxMaterial.js&quot; defer&gt;<\/script&gt;\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/\/ index.html<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #4EC9B0\">script<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">src<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #CE9178\">&quot;src\/materials\/Material.js&quot;<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">defer<\/span><span style=\"color: #D4D4D4\">&gt;&lt;\/<\/span><span style=\"color: #9CDCFE\">script<\/span><span style=\"color: #D4D4D4\">&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #9CDCFE\">script<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">src<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #CE9178\">&quot;src\/materials\/ShadowMaterial.js&quot;<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">defer<\/span><span style=\"color: #D4D4D4\">&gt;&lt;\/<\/span><span style=\"color: #9CDCFE\">script<\/span><span style=\"color: #D4D4D4\">&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #9CDCFE\">script<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">src<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #CE9178\">&quot;src\/materials\/PhongMaterial.js&quot;<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">defer<\/span><span style=\"color: #D4D4D4\">&gt;&lt;\/<\/span><span style=\"color: #9CDCFE\">script<\/span><span style=\"color: #D4D4D4\">&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">&lt;!-- <\/span><span style=\"color: #9CDCFE\">Edit<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">Start<\/span><span style=\"color: #D4D4D4\"> --&gt;<\/span><span style=\"color: #9CDCFE\">script<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">src<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #CE9178\">&quot;src\/materials\/PRTMaterial.js&quot;<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">defer<\/span><span style=\"color: #D4D4D4\">&gt;&lt;\/<\/span><span style=\"color: #9CDCFE\">script<\/span><span style=\"color: #D4D4D4\">&gt; <\/span><span style=\"color: #9CDCFE\">Edit<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">End<\/span><span style=\"color: #D4D4D4\"> --&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #9CDCFE\">script<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">src<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #CE9178\">&quot;src\/materials\/SkyBoxMaterial.js&quot;<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">defer<\/span><span style=\"color: #D4D4D4\">&gt;&lt;\/<\/span><span style=\"color: #9CDCFE\">script<\/span><span style=\"color: #D4D4D4\">&gt;<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<p>Load the new material in loadOBJ.js.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ loadOBJ.jsswitch (objMaterial) {    case 'PhongMaterial':        material = buildPhongMaterial(colorMap, mat.specular.toArray(), light, Translation, Scale, &quot;.\/src\/shaders\/phongShader\/phongVertex.glsl&quot;, &quot;.\/src\/shaders\/phongShader\/phongFragment.glsl&quot;);        shadowMaterial = buildShadowMaterial(light, Translation, Scale, &quot;.\/src\/shaders\/shadowShader\/shadowVertex.glsl&quot;, &quot;.\/src\/shaders\/shadowShader\/shadowFragment.glsl&quot;);        break;    \/\/ TODO: Add your PRTmaterial here    \/\/Edit Start    case 'PRTMaterial':        material = buildPRTMaterial(&quot;.\/src\/shaders\/prtShader\/prtVertex.glsl&quot;, &quot;.\/src\/shaders\/prtShader\/prtFragment.glsl&quot;);        break;    \/\/Edit End    \/\/ ...}\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/\/ loadOBJ.js<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">switch<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">objMaterial<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">case<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&#39;PhongMaterial&#39;<\/span><span style=\"color: #D4D4D4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">Material<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">buildPhongMaterial<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">colorMap<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">mat<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">specular<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">toArray<\/span><span style=\"color: #D4D4D4\">(), <\/span><span style=\"color: #9CDCFE\">light<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">Translation<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">Scale<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&quot;.\/src\/shaders\/phongShader\/phongVertex.glsl&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&quot;.\/src\/shaders\/phongShader\/phongFragment.glsl&quot;<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">shadowMaterial<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">buildShadowMaterial<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">light<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">Translation<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">Scale<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&quot;.\/src\/shaders\/shadowShader\/shadowVertex.glsl&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&quot;.\/src\/shaders\/shadowShader\/shadowFragment.glsl&quot;<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">break<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ TODO: Add your PRTmaterial here<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/Edit Start<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">case<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&#39;PRTMaterial&#39;<\/span><span style=\"color: #D4D4D4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">Material<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">buildPRTMaterial<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;.\/src\/shaders\/prtShader\/prtVertex.glsl&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&quot;.\/src\/shaders\/prtShader\/prtFragment.glsl&quot;<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">break<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/Edit End<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ ...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<p>Add the Mary model to the scene, set its position and size, and use the material just created.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/engine.js\/\/ Add shapes...\/\/ Edit Startlet maryTransform = setTransform(0, -35, 0, 20, 20, 20);\/\/ Edit End...\/\/ TODO: load model - Add your Material here...\/\/ Edit StartloadOBJ(renderer, 'assets\/mary\/', 'mary', 'PRTMaterial', maryTransform);\/\/ Edit End\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/\/engine.js<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Add shapes<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Edit Start<\/span><\/span>\n<span class=\"line\"><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">maryTransform<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">setTransform<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, -<\/span><span style=\"color: #B5CEA8\">35<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">20<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">20<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">20<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Edit End<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ TODO: load model - Add your Material here<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Edit Start<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">loadOBJ<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">Renderer<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;assets\/mary\/&#39;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;mary&#39;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;PRTMaterial&#39;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">maryTransform<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Edit End<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Compute Shading<\/h3>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Load precomputed data into the GPU.<\/p>\n<\/blockquote>\n\n\n\n<p>\u5728\u6e32\u67d3\u5faa\u73af\u7684camera pass\u4e2d\u7ed9\u6750\u8d28\u8bbe\u7f6eprecomputeL\u5b9e\u65f6\u7684\u503c\uff0c\u4e5f\u5c31\u662f\u4f20\u9012\u9884\u5148\u8ba1\u7b97\u7684\u6570\u636e\u7ed9shader\u3002\u4e0b\u9762\u4ee3\u7801\u662f\u6bcf\u4e00\u5e27\u4e2d\u6bcf\u4e00\u8d9fcamera pass\u4e2d\u6bcf\u4e00\u4e2a\u7f51\u683cmesh\u7684\u6bcf\u4e00\u4e2auniforms\u7684\u904d\u5386\u3002\u5b9e\u65f6\u6e32\u67d3\u6846\u67b6\u5df2\u7ecf\u89e3\u6790\u4e86\u9884\u8ba1\u7b97\u7684\u6570\u636e\u5e76\u4e14\u5b58\u50a8\u5230\u4e86uniforms\u4e2d\u3002precomputeL\u662f\u4e00\u4e2a 9&#215;3 \u7684\u77e9\u9635\uff0c\u4ee3\u8868\u8fd9\u91cc\u5206\u522b\u6709RGB\u4e09\u4e2a\u901a\u9053\u7684\u524d\u4e09\u9636\uff089\u4e2a\uff09\u7403\u8c10\u51fd\u6570\uff08\u5b9e\u9645\u4e0a\u6211\u4eec\u4f1a\u8bf4\u8fd9\u662f\u4e00\u4e2a 3&#215;3 \u7684\u77e9\u9635\uff0c\u4f46\u662f\u6211\u4eec\u5199\u4ee3\u7801\u76f4\u63a5\u5199\u6210\u4e00\u4e2a\u957f\u5ea6\u4e3a9\u7684\u6570\u7ec4\uff09\u3002\u4e3a\u4e86\u65b9\u4fbf\u4f7f\u7528\uff0c\u901a\u8fc7 tool.js \u7684\u51fd\u6570\u5c06 precomputeL \u8f6c\u6362\u4e3a 3&#215;9 \u7684\u77e9\u9635\u3002<\/p>\n\n\n\n<p>Through the uniformMatrix3fv function, we can upload the information stored in the material to the GPU. This function accepts three parameters, please refer to <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/WebGLRenderingContext\/uniformMatrix\">WebGL\u6587\u6863 &#8211; uniformMatrix<\/a> . The first parameter is used in the PRTMaterial we created ourselves. Uniforms include uPrecomputeL[0], uPrecomputeL[1] and uPrecomputeL[2]. We don&#039;t need to pay attention to the work in the GPU. We only need to have the uniform on the CPU to automatically access the corresponding content on the GPU through the API. In other words, when getting the location of a uniform or attribute, what you actually get is a reference on the CPU side, but at the bottom level, this reference will be mapped to a specific location on the GPU. The step of linking uniforms is completed in this.program = this.addShaderLocations() in Shader.js (you can understand it by looking at the code, but it is a bit complicated. I have also analyzed it in my HW1 article). shader.program has three attributes: glShaderProgram, uniforms, and attribs. The specific declaration location is in XXXshader.glsl, which we will complete in the next step.<\/p>\n\n\n\n<p>To summarize, the following code mainly provides pre-processed data to the fragment shader.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ WebGLRenderer.jsif (k == 'uMoveWithCamera') { \/\/ The rotation of the skybox    gl.uniformMatrix4fv(        this.meshes[i].shader.program.uniforms[k],        false,        cameraModelMatrix);}\/\/ Bonus - Fast Spherical Harmonic Rotation\/\/let precomputeL_RGBMat3 = getRotationPrecomputeL(precomputeL[guiParams.envmapId], cameraModelMatrix);\/\/ Edit Startlet Mat3Value = getMat3ValueFromRGB(precomputeL[guiParams.envmapId]);if (\/^uPrecomputeL\\[\\d\\]$$\/.test(k)) {    let index = parseInt(k.split('[')[1].split(']')[0]);    if (index &gt;= 0 &amp;&amp; index < 3) {        gl.uniformMatrix3fv(            this.meshes[i].shader.program.uniforms[k],            false,            Mat3Value[index]        );    }}\/\/ Edit End\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/\/ WebGLRenderer.js<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">k<\/span><span style=\"color: #D4D4D4\"> == <\/span><span style=\"color: #CE9178\">&#39;uMoveWithCamera&#39;<\/span><span style=\"color: #D4D4D4\">) { <\/span><span style=\"color: #6A9955\">\/\/ The rotation of the skybox<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">gl<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">uniformMatrix4fv<\/span><span style=\"color: #D4D4D4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">this<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">meshes<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">].<\/span><span style=\"color: #9CDCFE\">shader<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">program<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">uniforms<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">k<\/span><span style=\"color: #D4D4D4\">],<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">false<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">cameraModelMatrix<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Bonus - Fast Spherical Harmonic Rotation<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/let precomputeL_RGBMat3 = getRotationPrecomputeL(precomputeL[guiParams.envmapId], cameraModelMatrix);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Edit Start<\/span><\/span>\n<span class=\"line\"><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">Mat3Value<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">getMat3ValueFromRGB<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">precomputeL<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">guiParams<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">envmapId<\/span><span style=\"color: #D4D4D4\">]);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (\/^<\/span><span style=\"color: #9CDCFE\">uPrecomputeL<\/span><span style=\"color: #D4D4D4\">\\[\\<\/span><span style=\"color: #9CDCFE\">d<\/span><span style=\"color: #D4D4D4\">\\]$$\/.<\/span><span style=\"color: #DCDCAA\">test<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">k<\/span><span style=\"color: #D4D4D4\">)) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">index<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">parseInt<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">k<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">split<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&#39;[&#39;<\/span><span style=\"color: #D4D4D4\">)[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">].<\/span><span style=\"color: #DCDCAA\">split<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&#39;]&#39;<\/span><span style=\"color: #D4D4D4\">)[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">]);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">index<\/span><span style=\"color: #D4D4D4\"> &gt;= <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\"> &amp;&amp; <\/span><span style=\"color: #9CDCFE\">index<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">gl<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">uniformMatrix3fv<\/span><span style=\"color: #D4D4D4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #569CD6\">this<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">meshes<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">].<\/span><span style=\"color: #9CDCFE\">shader<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">program<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">uniforms<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">k<\/span><span style=\"color: #D4D4D4\">],<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #569CD6\">false<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">Mat3Value<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">index<\/span><span style=\"color: #D4D4D4\">]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        );<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Edit End<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>You can also put the calculation of Mat3Value outside the i loop to reduce the number of calculations.<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">Writing the vertex shader<\/h3>\n\n\n\n<p>After understanding the purpose of the above code, the next task is very clear. In the previous step, we passed each spherical harmonic coefficient to the uPrecomputeL[] of the GPU. Next, we program the GPU to calculate the dot product of the spherical harmonic coefficient and the transport matrix, which is light_coefficient * transport_matrix in the figure below.<\/p>\n\n\n\n<p>The real-time rendering framework has already simplified the matrix from Light_Transport to the corresponding direction. We only need to do dot multiplication on the vectors of length 9 of the three color channels. It is worth mentioning that PrecomputeL and PrecomputeLT can be passed to both the vertex shader and the fragment shader. If passed to the vertex shader, only the color difference in the fragment shader is needed, which is faster but less realistic. How to calculate depends on different needs.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-227.png\" alt=\"img\" class=\"wp-image-1355 lazyload\"\/><noscript><img decoding=\"async\" width=\"930\" height=\"762\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-227.png\" alt=\"img\" class=\"wp-image-1355 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-227.png 930w, https:\/\/remoooo.com\/wp-content\/uploads\/image-227-300x246.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-227-768x629.png 768w\" sizes=\"(max-width: 930px) 100vw, 930px\" \/><\/noscript><\/figure>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/prtVertex.glslattribute vec3 aVertexPosition;attribute vec3 aNormalPosition;attribute mat3 aPrecomputeLT;  \/\/ Precomputed Light Transfer matrix for the vertexuniform mat4 uModelMatrix;uniform mat4 uViewMatrix;uniform mat4 uProjectionMatrix;uniform mat3 uPrecomputeL[3];  \/\/ Precomputed Lighting matricesvarying highp vec3 vNormal;varying highp vec3 vColor;     \/\/ Outgoing color after the dot product calculationsfloat L_dot_LT(const mat3 PrecomputeL, const mat3 PrecomputeLT) {  return dot(PrecomputeL[0], PrecomputeLT[0])         + dot(PrecomputeL[1], PrecomputeLT[1])         + dot(PrecomputeL[2], PrecomputeLT[2]);}void main(void) {  \/\/ \u9632\u6b62\u56e0\u4e3a\u6d4f\u89c8\u5668\u4f18\u5316\u62a5\u9519\uff0c\u65e0\u5b9e\u9645\u4f5c\u7528  aNormalPosition;  for(int i = 0; i < 3; i++) {      vColor[i] = L_dot_LT(aPrecomputeLT, uPrecomputeL[i]);  }  gl_Position = uProjectionMatrix * uViewMatrix * uModelMatrix * vec4(aVertexPosition, 1.0);}\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/\/prtVertex.glsl<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">attribute<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">vec3<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">aVertexPosition<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">attribute<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">vec3<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">aNormalPosition<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">attribute<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">mat3<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">aPrecomputeLT<\/span><span style=\"color: #D4D4D4\">;  <\/span><span style=\"color: #6A9955\">\/\/ Precomputed Light Transfer matrix for the vertex<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">uniform<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">mat4<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">uModelMatrix<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">uniform<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">mat4<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">uViewMatrix<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">uniform<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">mat4<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">uProjectionMatrix<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">uniform<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">mat3<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">uPrecomputeL<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">];  <\/span><span style=\"color: #6A9955\">\/\/ Precomputed Lighting matrices<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">varying<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">highp<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">vec3<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">vNormal<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">varying<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">highp<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">vec3<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">vColor<\/span><span style=\"color: #D4D4D4\">;     <\/span><span style=\"color: #6A9955\">\/\/ Outgoing color after the dot product calculations<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">L_dot_LT<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4EC9B0\">const<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">mat3<\/span><span style=\"color: #D4D4D4\"> PrecomputeL, <\/span><span style=\"color: #4EC9B0\">const<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">mat3<\/span><span style=\"color: #D4D4D4\"> PrecomputeLT) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">dot<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">PrecomputeL<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">PrecomputeLT<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">]) <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        + <\/span><span style=\"color: #DCDCAA\">dot<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">PrecomputeL<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">PrecomputeLT<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">]) <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        + <\/span><span style=\"color: #DCDCAA\">dot<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">PrecomputeL<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">PrecomputeLT<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">]);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">main<\/span><span style=\"color: #D4D4D4\">(void) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">  \/\/ Prevent errors due to browser optimization, no practical effect<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  <\/span><span style=\"color: #9CDCFE\">aNormalPosition<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #9CDCFE\">vColor<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">] = <\/span><span style=\"color: #DCDCAA\">L_dot_LT<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">aPrecomputeLT<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">uPrecomputeL<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">]);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  <\/span><span style=\"color: #9CDCFE\">gl_Position<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">uProjectionMatrix<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">uViewMatrix<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">uModelMatrix<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #DCDCAA\">vec4<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">aVertexPosition<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">1.0<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<p>It is also worth mentioning that in the rendering framework, a value is set for an attribute called aNormalPosition. If it is not used in the Shader, it will be optimized by WebGL, causing the browser to keep reporting errors.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Writing fragment shaders<\/h3>\n\n\n\n<p>After the vertex shader completes the color calculation for the current vertex, the fragment shader interpolates the color. Since the vColor value calculated for each vertex in the vertex shader will be automatically interpolated in the fragment shader, it can be used directly.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ prtFragment.glsl#ifdef GL_ESprecision mediump float;#endifvarying highp vec3 vColor;void main(){  gl_FragColor = vec4(vColor, 1.0);}\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/\/prtFragment.glsl<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">#ifdef GL_ES<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">precision<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">mediump<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">float<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">#endif<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">varying<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">highp<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">vec3<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">vColor<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">main<\/span><span style=\"color: #D4D4D4\">(){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  <\/span><span style=\"color: #9CDCFE\">gl_FragColor<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">vec4<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">vColor<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">1.0<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Exposure and color correction<\/h2>\n\n\n\n<p>Although the framework author mentioned that the results saved by PRT pre-calculation are in linear space and no gamma correction is required, the final result is obviously problematic. If you do not divide beforehand when calculating the coefficient, then taking the Skybox scene as an example, there will be an overexposure problem. If you divide beforehand but do not do color correction, it will be too dark in the real-time rendering framework.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-221.png\" alt=\"img\" class=\"wp-image-1348 lazyload\"\/><noscript><img decoding=\"async\" width=\"1062\" height=\"706\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-221.png\" alt=\"img\" class=\"wp-image-1348 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-221.png 1062w, https:\/\/remoooo.com\/wp-content\/uploads\/image-221-300x199.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-221-1024x681.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-221-768x511.png 768w\" sizes=\"(max-width: 1062px) 100vw, 1062px\" \/><\/noscript><\/figure>\n\n\n\n<p>First, divide by when calculating the coefficient, and then do a color correction. How to do it? We can refer to the toSRGB() function in the export process of the nori framework:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ common.cppColor3f Color3f::toSRGB() const {    Color3f result;    for (int i=0; i<3; ++i) {        float value = coeff(i);        if (value <= 0.0031308f)            result[i] = 12.92f * value;        else            result[i] = (1.0f + 0.055f)                * std::pow(value, 1.0f\/2.4f) -  0.055f;    }    return result;}\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/\/ common.cpp<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">Color3f<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #C8C8C8\">Color3f<\/span><span style=\"color: #D4D4D4\">::<\/span><span style=\"color: #DCDCAA\">toSRGB<\/span><span style=\"color: #D4D4D4\">() <\/span><span style=\"color: #569CD6\">const<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">Color3f<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">Result<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">; ++<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">value<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">coeff<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">value<\/span><span style=\"color: #D4D4D4\"> &lt;= <\/span><span style=\"color: #B5CEA8\">0.0031308f<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">Result<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">] = <\/span><span style=\"color: #B5CEA8\">12.92f<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">value<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">else<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">Result<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">] = (<\/span><span style=\"color: #B5CEA8\">1.0f<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">0.055f<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                * <\/span><span style=\"color: #9CDCFE\">std<\/span><span style=\"color: #D4D4D4\">::<\/span><span style=\"color: #DCDCAA\">pow<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">value<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">1.0f<\/span><span style=\"color: #D4D4D4\">\/<\/span><span style=\"color: #B5CEA8\">2.4f<\/span><span style=\"color: #D4D4D4\">) -  <\/span><span style=\"color: #B5CEA8\">0.055f<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">Result<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<p>We can imitate this and do color correction in fragment shading.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/prtFragment.glsl#ifdef GL_ESprecision mediump float;#endifvarying highp vec3 vColor;vec3 toneMapping(vec3 color){    vec3 result;    for (int i=0; i<3; ++i) {        if (color[i] <= 0.0031308)            result[i] = 12.92 * color[i];        else            result[i] = (1.0 + 0.055) * pow(color[i], 1.0\/2.4) - 0.055;    }    return result;}void main(){  vec3 color = toneMapping(vColor);   gl_FragColor = vec4(color, 1.0);}\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/\/prtFragment.glsl<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">#ifdef GL_ES<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">precision<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">mediump<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">float<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">#endif<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">varying<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">highp<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">vec3<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">vColor<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #4EC9B0\">vec3<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">toneMapping<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4EC9B0\">vec3<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">color<\/span><span style=\"color: #D4D4D4\">){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">vec3<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">Result<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">; ++<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">color<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">] &lt;= <\/span><span style=\"color: #B5CEA8\">0.0031308<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">Result<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">] = <\/span><span style=\"color: #B5CEA8\">12.92<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">color<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">else<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">Result<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">] = (<\/span><span style=\"color: #B5CEA8\">1.0<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">0.055<\/span><span style=\"color: #D4D4D4\">) * <\/span><span style=\"color: #DCDCAA\">pow<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">color<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #B5CEA8\">1.0<\/span><span style=\"color: #D4D4D4\">\/<\/span><span style=\"color: #B5CEA8\">2.4<\/span><span style=\"color: #D4D4D4\">) - <\/span><span style=\"color: #B5CEA8\">0.055<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">Result<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">main<\/span><span style=\"color: #D4D4D4\">(){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  <\/span><span style=\"color: #4EC9B0\">vec3<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">color<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">toneMapping<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">vColor<\/span><span style=\"color: #D4D4D4\">); <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  <\/span><span style=\"color: #9CDCFE\">gl_FragColor<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">vec4<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">color<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">1.0<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<p>This ensures that the rendering results of the real-time rendering framework are consistent with the screenshot results of the nori framework.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-220.png\" alt=\"img\" class=\"wp-image-1347 lazyload\"\/><noscript><img decoding=\"async\" width=\"1062\" height=\"832\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-220.png\" alt=\"img\" class=\"wp-image-1347 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-220.png 1062w, https:\/\/remoooo.com\/wp-content\/uploads\/image-220-300x235.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-220-1024x802.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-220-768x602.png 768w\" sizes=\"(max-width: 1062px) 100vw, 1062px\" \/><\/noscript><\/figure>\n\n\n\n<p>We can also do other color corrections. Here are several common Tone Mapping methods for converting the HDR range to the LDR range.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"vec3 linearToneMapping(vec3 color) {    return color \/ (color + vec3(1.0));}vec3 reinhardToneMapping(vec3 color) {    return color \/ (vec3(1.0) + color);}vec3 exposureToneMapping(vec3 color, float exposure) {    return vec3(1.0) - exp(-color * exposure);}vec3 filmicToneMapping(vec3 color) {    color = max(vec3(0.0), color - vec3(0.004));    color = (color * (6.2 * color + 0.5)) \/ (color * (6.2 * color + 1.7) + 0.06);    return color;}\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #4EC9B0\">vec3<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">linearToneMapping<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4EC9B0\">vec3<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">color<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">color<\/span><span style=\"color: #D4D4D4\"> \/ (<\/span><span style=\"color: #9CDCFE\">color<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #DCDCAA\">vec3<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #B5CEA8\">1.0<\/span><span style=\"color: #D4D4D4\">));<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #4EC9B0\">vec3<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">reinhardToneMapping<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4EC9B0\">vec3<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">color<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">color<\/span><span style=\"color: #D4D4D4\"> \/ (<\/span><span style=\"color: #DCDCAA\">vec3<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #B5CEA8\">1.0<\/span><span style=\"color: #D4D4D4\">) + <\/span><span style=\"color: #9CDCFE\">color<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #4EC9B0\">vec3<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">exposureToneMapping<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4EC9B0\">vec3<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">color<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">exposure<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">vec3<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #B5CEA8\">1.0<\/span><span style=\"color: #D4D4D4\">) - <\/span><span style=\"color: #DCDCAA\">exp<\/span><span style=\"color: #D4D4D4\">(-<\/span><span style=\"color: #9CDCFE\">color<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">exposure<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #4EC9B0\">vec3<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">filmicToneMapping<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4EC9B0\">vec3<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">color<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">color<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">max<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #DCDCAA\">vec3<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #B5CEA8\">0.0<\/span><span style=\"color: #D4D4D4\">), <\/span><span style=\"color: #9CDCFE\">color<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #DCDCAA\">vec3<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #B5CEA8\">0.004<\/span><span style=\"color: #D4D4D4\">));<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">color<\/span><span style=\"color: #D4D4D4\"> = (<\/span><span style=\"color: #9CDCFE\">color<\/span><span style=\"color: #D4D4D4\"> * (<\/span><span style=\"color: #B5CEA8\">6.2<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">color<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">0.5<\/span><span style=\"color: #D4D4D4\">)) \/ (<\/span><span style=\"color: #9CDCFE\">color<\/span><span style=\"color: #D4D4D4\"> * (<\/span><span style=\"color: #B5CEA8\">6.2<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">color<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1.7<\/span><span style=\"color: #D4D4D4\">) + <\/span><span style=\"color: #B5CEA8\">0.06<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">color<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<p>So far, the basic part of the assignment has been completed.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Add CornellBox scene<\/h2>\n\n\n\n<p>There is no CornellBox in the default framework code, but there is one in the resource file, so we need to add it ourselves:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ engine.jsvar envmap = [    'assets\/cubemap\/GraceCathedral',    'assets\/cubemap\/Indoor',    'assets\/cubemap\/Skybox',    \/\/ Edit Start    'assets\/cubemap\/CornellBox',    \/\/ Edit End];\/\/ engine.jsfunction createGUI() {    const gui = new dat.gui.GUI();    const panelModel = gui.addFolder('Switch Environemtn Map');    \/\/ Edit Start    panelModel.add(guiParams, 'envmapId', { 'GraceGathedral': 0, 'Indoor': 1, 'Skybox': 2, 'CornellBox': 3}).name('Envmap Name');    \/\/ Edit End    panelModel.open();}\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/\/ engine.js<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">envmap<\/span><span style=\"color: #D4D4D4\"> = [<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #CE9178\">&#39;assets\/cubemap\/GraceCathedral&#39;<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #CE9178\">&#39;assets\/cubemap\/Indoor&#39;<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #CE9178\">&#39;assets\/cubemap\/Skybox&#39;<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ Edit Start<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #CE9178\">&#39;assets\/cubemap\/CornellBox&#39;<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ Edit End<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ engine.js<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #4EC9B0\">Function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">createGUI<\/span><span style=\"color: #D4D4D4\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">const<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">gui<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">dat<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #4EC9B0\">gui<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #4EC9B0\">GUI<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">const<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">panelModel<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">gui<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">addFolder<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&#39;Switch Environemtn Map&#39;<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ Edit Start<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">panelModel<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">add<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">guiParams<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;envmapId&#39;<\/span><span style=\"color: #D4D4D4\">, { <\/span><span style=\"color: #CE9178\">&#39;GraceGathedral&#39;<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;Indoor&#39;<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;Skybox&#39;<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;CornellBox&#39;<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">}).<\/span><span style=\"color: #DCDCAA\">name<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&#39;Envmap Name&#39;<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ Edit End<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">panelModel<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">open<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-226.png\" alt=\"img\" class=\"wp-image-1354 lazyload\"\/><noscript><img decoding=\"async\" width=\"970\" height=\"662\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-226.png\" alt=\"img\" class=\"wp-image-1354 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-226.png 970w, https:\/\/remoooo.com\/wp-content\/uploads\/image-226-300x205.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-226-768x524.png 768w\" sizes=\"(max-width: 970px) 100vw, 970px\" \/><\/noscript><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Results of the basic part<\/h3>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Four shadowed and unshadowed scenes are shown respectively.<\/p>\n<\/blockquote>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-224.png\" alt=\"img\" class=\"wp-image-1352 lazyload\"\/><noscript><img decoding=\"async\" width=\"1074\" height=\"718\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-224.png\" alt=\"img\" class=\"wp-image-1352 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-224.png 1074w, https:\/\/remoooo.com\/wp-content\/uploads\/image-224-300x201.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-224-1024x685.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-224-768x513.png 768w\" sizes=\"(max-width: 1074px) 100vw, 1074px\" \/><\/noscript><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Consider multiple bounces of the transport ray (bonus 1)<\/h2>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>This is the first part of the improvement. Calculating the transport of light for multiple bounces has similarities to ray tracing, and you can combine ray tracing with the lighting approximation using spherical harmonics (SH) to calculate the effect of these multiple bounces.<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">Complete code<\/h3>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ TODO: leave for bonusEigen::MatrixXf m_IndirectCoeffs = Eigen::MatrixXf::Zero(SHCoeffLength, mesh-&gt;getVertexCount());int sample_side = static_cast<int&gt;(floor(sqrt(m_SampleCount)));std::random_device rd;std::mt19937 gen(rd());std::uniform_real_distribution<&gt; rng(0.0, 1.0);const double twoPi = 2.0 * M_PI;for(int bo = 0; bo < m_Bounce; bo++){    for (int i = 0; i < mesh-&gt;getVertexCount(); i++)    {        const Point3f &amp;v = mesh-&gt;getVertexPositions().col(i);        const Normal3f &amp;n = mesh-&gt;getVertexNormals().col(i);        std::vector<float&gt; coeff(SHCoeffLength, 0.0f);        for (int t = 0; t < sample_side; t++) {            for (int p = 0; p < sample_side; p++) {                double alpha = (t + rng(gen)) \/ sample_side;                double beta = (p + rng(gen)) \/ sample_side;                double phi = twoPi * beta;                double theta = acos(2.0 * alpha - 1.0);                Eigen::Array3d d = sh::ToVector(phi, theta);                const Vector3f wi(d[0], d[1], d[2]);                double H = wi.dot(n);                if(H &gt; 0.0) {                    const auto ray = Ray3f(v, wi);                    Intersection intersect;                    bool is_inter = scene-&gt;rayIntersect(ray, intersect);                    if(is_inter) {                        for(int j = 0; j < SHCoeffLength; j++) {                            const Vector3f coef3(                                m_TransportSHCoeffs.col((int)intersect.tri_index[0]).coeffRef(j),                                m_TransportSHCoeffs.col((int)intersect.tri_index[1]).coeffRef(j),                                m_TransportSHCoeffs.col((int)intersect.tri_index[2]).coeffRef(j)                            );                            coeff[j] += intersect.bary.dot(coef3) \/ m_SampleCount;                        }                    }                }            }        }        for (int j = 0; j < SHCoeffLength; j++)        {            m_IndirectCoeffs.col(i).coeffRef(j) = coeff[j] - m_IndirectCoeffs.col(i).coeffRef(j);        }    }    m_TransportSHCoeffs += m_IndirectCoeffs;}\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/\/ TODO: leave for bonus<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C8C8C8\">Eigen<\/span><span style=\"color: #D4D4D4\">::<\/span><span style=\"color: #4EC9B0\">MatrixXf<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">m_IndirectCoeffs<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">Eigen<\/span><span style=\"color: #D4D4D4\">::<\/span><span style=\"color: #9CDCFE\">MatrixXf<\/span><span style=\"color: #D4D4D4\">::<\/span><span style=\"color: #DCDCAA\">Zero<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">SHCoeffLength<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #DCDCAA\">getVertexCount<\/span><span style=\"color: #D4D4D4\">());<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">sample_side<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">static_cast<\/span><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\">&gt;(<\/span><span style=\"color: #DCDCAA\">floor<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #DCDCAA\">sqrt<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">m_SampleCount<\/span><span style=\"color: #D4D4D4\">)));<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #C8C8C8\">std<\/span><span style=\"color: #D4D4D4\">::<\/span><span style=\"color: #4EC9B0\">random_device<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">rd<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C8C8C8\">std<\/span><span style=\"color: #D4D4D4\">::<\/span><span style=\"color: #4EC9B0\">mt19937<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">gen<\/span><span style=\"color: #D4D4D4\">(rd());<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C8C8C8\">std<\/span><span style=\"color: #D4D4D4\">::<\/span><span style=\"color: #9CDCFE\">uniform_real_distribution<\/span><span style=\"color: #D4D4D4\">&lt;&gt; <\/span><span style=\"color: #DCDCAA\">rng<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #B5CEA8\">0.0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">1.0<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">const<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">double<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">twoPi<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">2.0<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">M_PI<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">bo<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">bo<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">m_Bounce<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">bo<\/span><span style=\"color: #D4D4D4\">++)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #DCDCAA\">getVertexCount<\/span><span style=\"color: #D4D4D4\">(); <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">const<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">Point3f<\/span><span style=\"color: #D4D4D4\"> &amp;<\/span><span style=\"color: #9CDCFE\">v<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #DCDCAA\">getVertexPositions<\/span><span style=\"color: #D4D4D4\">().<\/span><span style=\"color: #DCDCAA\">col<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">const<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">Normal3f<\/span><span style=\"color: #D4D4D4\"> &amp;<\/span><span style=\"color: #9CDCFE\">n<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #DCDCAA\">getVertexNormals<\/span><span style=\"color: #D4D4D4\">().<\/span><span style=\"color: #DCDCAA\">col<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C8C8C8\">std<\/span><span style=\"color: #D4D4D4\">::<\/span><span style=\"color: #4EC9B0\">vector<\/span><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\">&gt; <\/span><span style=\"color: #DCDCAA\">coeff<\/span><span style=\"color: #D4D4D4\">(SHCoeffLength, 0.0f);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">t<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">t<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">sample_side<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">t<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">p<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">p<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">sample_side<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">p<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #569CD6\">double<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">alpha<\/span><span style=\"color: #D4D4D4\"> = (<\/span><span style=\"color: #9CDCFE\">t<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #DCDCAA\">rng<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">gen<\/span><span style=\"color: #D4D4D4\">)) \/ <\/span><span style=\"color: #9CDCFE\">sample_side<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #569CD6\">double<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">beta<\/span><span style=\"color: #D4D4D4\"> = (<\/span><span style=\"color: #9CDCFE\">p<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #DCDCAA\">rng<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">gen<\/span><span style=\"color: #D4D4D4\">)) \/ <\/span><span style=\"color: #9CDCFE\">sample_side<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #569CD6\">double<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">phi<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">twoPi<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">beta<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #569CD6\">double<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">theta<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">acos<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #B5CEA8\">2.0<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">alpha<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1.0<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #C8C8C8\">Eigen<\/span><span style=\"color: #D4D4D4\">::<\/span><span style=\"color: #4EC9B0\">Array3d<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">d<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">sh<\/span><span style=\"color: #D4D4D4\">::<\/span><span style=\"color: #DCDCAA\">ToVector<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">phi<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">theta<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #9CDCFE\">const<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Vector3f<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">wi<\/span><span style=\"color: #D4D4D4\">(d[0], d[1], d[2]);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #569CD6\">double<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">H<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">wi<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">dot<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">n<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">H<\/span><span style=\"color: #D4D4D4\"> &gt; <\/span><span style=\"color: #B5CEA8\">0.0<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                    <\/span><span style=\"color: #569CD6\">const<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">auto<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">ray<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Ray3f<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">v<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">wi<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                    <\/span><span style=\"color: #4EC9B0\">Intersection<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">intersect<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                    <\/span><span style=\"color: #569CD6\">bool<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">is_inter<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">scene<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #DCDCAA\">rayIntersect<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">ray<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">intersect<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">is_inter<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                        <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">SHCoeffLength<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                            <\/span><span style=\"color: #9CDCFE\">const<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Vector3f<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">coef3<\/span><span style=\"color: #D4D4D4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                                m_TransportSHCoeffs.col((int)intersect.tri_index[0]).coeffRef(j),<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                                m_TransportSHCoeffs.col((int)intersect.tri_index[1]).coeffRef(j),<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                                m_TransportSHCoeffs.col((int)intersect.tri_index[2]).coeffRef(j)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                            );<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                            <\/span><span style=\"color: #9CDCFE\">coeff<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\">] += <\/span><span style=\"color: #9CDCFE\">intersect<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">bary<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">dot<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">coef3<\/span><span style=\"color: #D4D4D4\">) \/ <\/span><span style=\"color: #9CDCFE\">m_SampleCount<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">SHCoeffLength<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\">++)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">m_IndirectCoeffs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">col<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">).<\/span><span style=\"color: #DCDCAA\">coeffRef<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\">) = <\/span><span style=\"color: #9CDCFE\">coeff<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\">] - <\/span><span style=\"color: #9CDCFE\">m_IndirectCoeffs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">col<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">).<\/span><span style=\"color: #DCDCAA\">coeffRef<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">m_TransportSHCoeffs<\/span><span style=\"color: #D4D4D4\"> += <\/span><span style=\"color: #9CDCFE\">m_IndirectCoeffs<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">analyze<\/h3>\n\n\n\n<p>Based on the calculation of occluded shadows (<strong>Direct Lighting<\/strong>), plus the secondary reflected light (<strong>Indirect lighting<\/strong>). The same steps can be followed for the secondary reflected light. For the calculation of indirect lighting, spherical harmonics are used to approximate the illumination of these reflected rays. If multiple bounces are considered, recursive calculations are performed, and the termination condition can be the recursive depth or the light intensity is lower than a certain threshold. The following is a textual formula description.<\/p>\n\n\n\n<p>The brief code and comments are as follows:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ TODO: leave for bonus\/\/ \u9996\u5148\u521d\u59cb\u5316\u7403\u8c10\u7cfb\u6570Eigen::MatrixXf m_IndirectCoeffs = Eigen::MatrixXf::Zero(SHCoeffLength, mesh-&gt;getVertexCount());\/\/ \u91c7\u6837\u4fa7\u8fb9\u7684\u5927\u5c0f = \u6837\u672c\u6570\u91cf\u7684\u5e73\u65b9\u6839 \/\/ \u8fd9\u6837\u6211\u4eec\u5728\u540e\u9762\u53ef\u4ee5\u8fdb\u884c\u4e8c\u7ef4\u7684\u91c7\u6837int sample_side = static_cast<int&gt;(floor(sqrt(m_SampleCount)));\/\/ \u751f\u6210\u968f\u673a\u6570\uff0c\u8303\u56f4\u662f [0,1]...std::uniform_real_distribution<&gt; rng(0.0, 1.0);\/\/ \u5b9a\u4e49\u5e38\u91cf 2 \\pi...\/\/ \u5faa\u73af\u8ba1\u7b97\u591a\u6b21\u53cd\u5c04 \uff08m_Bounce \u6b21\uff09for (int bo = 0; bo < m_Bounce; bo++) {  \/\/ \u5bf9\u6bcf\u4e2a\u9876\u70b9\u505a\u5904\u7406  \/\/ \u5bf9\u4e8e\u6bcf\u4e2a\u9876\u70b9\uff0c\u4f1a\u505a\u5982\u4e0b\u64cd\u4f5c  \/\/ - \u83b7\u53d6\u8be5\u9876\u70b9\u7684\u4f4d\u7f6e\u548c\u6cd5\u7ebf v n  \/\/ - rng()\u83b7\u5f97\u968f\u673a\u7684\u4e8c\u7ef4\u65b9\u5411 alpha beta  \/\/ - \u5982\u679cwi\u5728\u9876\u70b9\u6cd5\u7ebf\u7684\u540c\u4e00\u4fa7\uff0c\u5219\u7ee7\u7eed\u8fdb\u884c\uff1a  \/\/ - \u751f\u6210\u4e00\u6761\u4ece\u9876\u70b9\u51fa\u53d1\u7684\u5c04\u7ebf\uff0c\u5e76\u68c0\u67e5\u8fd9\u6761\u5c04\u7ebf\u662f\u5426\u4e0e\u573a\u666f\u4e2d\u7684\u5176\u4ed6\u7269\u4f53\u76f8\u4ea4  \/\/ - \u5982\u679c\u6709\u76f8\u4ea4\u7684\u7269\u4f53\uff0c\u4ee3\u7801\u4f1a\u4f7f\u7528\u76f8\u4ea4\u5904\u7684\u4fe1\u606f\u548c\u73b0\u6709\u7684\u7403\u8c10\u7cfb\u6570\u6765\u66f4\u65b0\u8be5\u9876\u70b9\u7684\u5149\u7ebf\u95f4\u63a5\u53cd\u5c04\u4fe1\u606f\u3002  for (int i = 0; i < mesh-&gt;getVertexCount(); i++) {    const Point3f &amp;v = mesh-&gt;getVertexPositions().col(i);    const Normal3f &amp;n = mesh-&gt;getVertexNormals().col(i);    ...    for (int t = 0; t < sample_side; t++) {      for (int p = 0; p < sample_side; p++) {        ...        double H = wi.dot(n);        if (H &gt; 0.0) {          \/\/ \u8fd9\u91cc\u5c31\u662f\u516c\u5f0f\u4e2d\u7684 $$(1-V(w_i))$$ \u5982\u679c\u4e0d\u6ee1\u8db3\uff0c\u8fd9\u4e00\u8f6e\u5faa\u73af\u5c31\u4e0d\u7d2f\u52a0          bool is_inter = scene-&gt;rayIntersect(ray, intersect);          if (is_inter) {            for (int j = 0; j < SHCoeffLength; j++) {              ...              coeff[j] += intersect.bary.dot(coef3) \/ m_SampleCount;            }          }        }      }    }    \/\/ \u5bf9\u4e8e\u6bcf\u4e2a\u9876\u70b9\uff0c\u4f1a\u6839\u636e\u8ba1\u7b97\u7684\u53cd\u5c04\u4fe1\u606f\u66f4\u65b0\u5176\u7403\u8c10\u7cfb\u6570\u3002    for (int j = 0; j < SHCoeffLength; j++) {      m_IndirectCoeffs.col(i).coeffRef(j) = coeff[j] - m_IndirectCoeffs.col(i).coeffRef(j);    }  }  m_TransportSHCoeffs += m_IndirectCoeffs;}\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/\/ TODO: leave for bonus<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/First initialize the spherical harmonic coefficients<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C8C8C8\">Eigen<\/span><span style=\"color: #D4D4D4\">::<\/span><span style=\"color: #4EC9B0\">MatrixXf<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">m_IndirectCoeffs<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">Eigen<\/span><span style=\"color: #D4D4D4\">::<\/span><span style=\"color: #9CDCFE\">MatrixXf<\/span><span style=\"color: #D4D4D4\">::<\/span><span style=\"color: #DCDCAA\">Zero<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">SHCoeffLength<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #DCDCAA\">getVertexCount<\/span><span style=\"color: #D4D4D4\">());<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ The size of the sampling side = the square root of the number of samples \/\/ This way we can perform two-dimensional sampling later<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">sample_side<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">static_cast<\/span><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\">&gt;(<\/span><span style=\"color: #DCDCAA\">floor<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #DCDCAA\">sqrt<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">m_SampleCount<\/span><span style=\"color: #D4D4D4\">)));<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Generate a random number in the range [0,1]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C8C8C8\">std<\/span><span style=\"color: #D4D4D4\">::<\/span><span style=\"color: #9CDCFE\">uniform_real_distribution<\/span><span style=\"color: #D4D4D4\">&lt;&gt; <\/span><span style=\"color: #DCDCAA\">rng<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #B5CEA8\">0.0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">1.0<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Define constant 2 \\pi<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">...<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Loop to calculate multiple reflections (m_Bounce times)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">bo<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">bo<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">m_Bounce<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">bo<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">  \/\/ Process each vertex<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">  \/\/ For each vertex, the following operations are performed<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">  \/\/ - Get the position and normal vn of the vertex<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">  \/\/ - rng() gets random two-dimensional direction alpha beta<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">  \/\/ - If wi is on the same side of the vertex normal, then proceed:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">  \/\/ - Generate a ray from the vertex and check if the ray intersects with other objects in the scene<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">  \/\/ - If there is an intersecting object, the code uses the information of the intersection and the existing spherical harmonic coefficients to update the indirect reflection information of the light at that vertex.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #DCDCAA\">getVertexCount<\/span><span style=\"color: #D4D4D4\">(); <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">const<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">Point3f<\/span><span style=\"color: #D4D4D4\"> &amp;<\/span><span style=\"color: #9CDCFE\">v<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #DCDCAA\">getVertexPositions<\/span><span style=\"color: #D4D4D4\">().<\/span><span style=\"color: #DCDCAA\">col<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">const<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">Normal3f<\/span><span style=\"color: #D4D4D4\"> &amp;<\/span><span style=\"color: #9CDCFE\">n<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #DCDCAA\">getVertexNormals<\/span><span style=\"color: #D4D4D4\">().<\/span><span style=\"color: #DCDCAA\">col<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    ...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">t<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">t<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">sample_side<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">t<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">p<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">p<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">sample_side<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">p<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        ...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">double<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">H<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">wi<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">dot<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">n<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">H<\/span><span style=\"color: #D4D4D4\"> &gt; <\/span><span style=\"color: #B5CEA8\">0.0<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">          \/\/ Here is the formula $$(1-V(w_i))$$. If it is not satisfied, this round of loop will not accumulate.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #569CD6\">bool<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">is_inter<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">scene<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #DCDCAA\">rayIntersect<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">ray<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">intersect<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">is_inter<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">SHCoeffLength<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">              ...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">              <\/span><span style=\"color: #9CDCFE\">coeff<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\">] += <\/span><span style=\"color: #9CDCFE\">intersect<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">bary<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">dot<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">coef3<\/span><span style=\"color: #D4D4D4\">) \/ <\/span><span style=\"color: #9CDCFE\">m_SampleCount<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ For each vertex, its spherical harmonic coefficients are updated based on the calculated reflection information.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">SHCoeffLength<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #9CDCFE\">m_IndirectCoeffs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">col<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">).<\/span><span style=\"color: #DCDCAA\">coeffRef<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\">) = <\/span><span style=\"color: #9CDCFE\">coeff<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\">] - <\/span><span style=\"color: #9CDCFE\">m_IndirectCoeffs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">col<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">).<\/span><span style=\"color: #DCDCAA\">coeffRef<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  <\/span><span style=\"color: #9CDCFE\">m_TransportSHCoeffs<\/span><span style=\"color: #D4D4D4\"> += <\/span><span style=\"color: #9CDCFE\">m_IndirectCoeffs<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<p>In the previous steps, we only calculated the spherical harmonics of each vertex, and did not involve the interpolation calculation of the triangle center. However, in the implementation of multiple ray bounces, the light emitted from the vertex to the positive hemisphere will intersect with the position outside the vertex, so we need to obtain the information of the intersection of the emitted light and the inside of the triangle through barycentric coordinate interpolation calculation, which is the role of intersect.bary.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">result<\/h3>\n\n\n\n<p>If you observe, there is not much difference overall, except that the shadow areas are brighter.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-223.png\" alt=\"img\" class=\"wp-image-1350 lazyload\"\/><noscript><img decoding=\"async\" width=\"874\" height=\"600\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-223.png\" alt=\"img\" class=\"wp-image-1350 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-223.png 874w, https:\/\/remoooo.com\/wp-content\/uploads\/image-223-300x206.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-223-768x527.png 768w\" sizes=\"(max-width: 874px) 100vw, 874px\" \/><\/noscript><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Ambient lighting spherical harmonics rotation (bonus 2)<\/h2>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Improved by 2. The rotation of low-level sneaker lighting can use the &quot;low-level SH fast rotation method&quot;.<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">Code<\/h3>\n\n\n\n<p>First, let Skybox rotate. [0, 1, 0] means rotation around the y axis. Then calculate the spherical harmonics after rotation through the getRotationPrecomputeL function. Finally, apply it to Mat3Value.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ WebGLRenderer.jslet cameraModelMatrix = mat4.create();\/\/ Edit Startmat4.fromRotation(cameraModelMatrix, timer, [0, 1, 0]);\/\/ Edit Endif (k == 'uMoveWithCamera') { \/\/ The rotation of the skybox    gl.uniformMatrix4fv(        this.meshes[i].shader.program.uniforms[k],        false,        cameraModelMatrix);}\/\/ Bonus - Fast Spherical Harmonic Rotation\/\/ Edit Startlet precomputeL_RGBMat3 = getRotationPrecomputeL(precomputeL[guiParams.envmapId], cameraModelMatrix);Mat3Value = getMat3ValueFromRGB(precomputeL_RGBMat3);\/\/ Edit End\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/\/ WebGLRenderer.js<\/span><\/span>\n<span class=\"line\"><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">cameraModelMatrix<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">mat4<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">create<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Edit Start<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">mat4<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">fromRotation<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">cameraModelMatrix<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">timer<\/span><span style=\"color: #D4D4D4\">, [<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">]);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Edit End<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">k<\/span><span style=\"color: #D4D4D4\"> == <\/span><span style=\"color: #CE9178\">&#39;uMoveWithCamera&#39;<\/span><span style=\"color: #D4D4D4\">) { <\/span><span style=\"color: #6A9955\">\/\/ The rotation of the skybox<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">gl<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">uniformMatrix4fv<\/span><span style=\"color: #D4D4D4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">this<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">meshes<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">].<\/span><span style=\"color: #9CDCFE\">shader<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">program<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">uniforms<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">k<\/span><span style=\"color: #D4D4D4\">],<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">false<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">cameraModelMatrix<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Bonus - Fast Spherical Harmonic Rotation<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Edit Start<\/span><\/span>\n<span class=\"line\"><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">precomputeL_RGBMat3<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">getRotationPrecomputeL<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">precomputeL<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">guiParams<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">envmapId<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">cameraModelMatrix<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">Mat3Value<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">getMat3ValueFromRGB<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">precomputeL_RGBMat3<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Edit End<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<p>Next, jump to tool.js and write the getRotationPrecomputeL function.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:1rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(3 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ tools.jsfunction getRotationPrecomputeL(precompute_L, rotationMatrix){    let rotationMatrix_inverse = mat4.create()    mat4.invert(rotationMatrix_inverse, rotationMatrix)    let r = mat4Matrix2mathMatrix(rotationMatrix_inverse)    let shRotateMatrix3x3 = computeSquareMatrix_3by3(r);    let shRotateMatrix5x5 = computeSquareMatrix_5by5(r);    let result = [];    for(let i = 0; i < 9; i++){        result[i] = [];    }    for(let i = 0; i < 3; i++){        let L_SH_R_3 = math.multiply([precompute_L[1][i], precompute_L[2][i], precompute_L[3][i]], shRotateMatrix3x3);        let L_SH_R_5 = math.multiply([precompute_L[4][i], precompute_L[5][i], precompute_L[6][i], precompute_L[7][i], precompute_L[8][i]], shRotateMatrix5x5);        result[0][i] = precompute_L[0][i];        result[1][i] = L_SH_R_3._data[0];        result[2][i] = L_SH_R_3._data[1];        result[3][i] = L_SH_R_3._data[2];        result[4][i] = L_SH_R_5._data[0];        result[5][i] = L_SH_R_5._data[1];        result[6][i] = L_SH_R_5._data[2];        result[7][i] = L_SH_R_5._data[3];        result[8][i] = L_SH_R_5._data[4];    }    return result;}function computeSquareMatrix_3by3(rotationMatrix){ \/\/ \u8ba1\u7b97\u65b9\u9635SA(-1) 3*3     \/\/ 1\u3001pick ni - {ni}    let n1 = [1, 0, 0, 0]; let n2 = [0, 0, 1, 0]; let n3 = [0, 1, 0, 0];    \/\/ 2\u3001{P(ni)} - A  A_inverse    let n1_sh = SHEval(n1[0], n1[1], n1[2], 3)    let n2_sh = SHEval(n2[0], n2[1], n2[2], 3)    let n3_sh = SHEval(n3[0], n3[1], n3[2], 3)    let A = math.matrix(    [        [n1_sh[1], n2_sh[1], n3_sh[1]],         [n1_sh[2], n2_sh[2], n3_sh[2]],         [n1_sh[3], n2_sh[3], n3_sh[3]],     ]);    let A_inverse = math.inv(A);    \/\/ 3\u3001\u7528 R \u65cb\u8f6c ni - {R(ni)}    let n1_r = math.multiply(rotationMatrix, n1);    let n2_r = math.multiply(rotationMatrix, n2);    let n3_r = math.multiply(rotationMatrix, n3);    \/\/ 4\u3001R(ni) SH\u6295\u5f71 - S    let n1_r_sh = SHEval(n1_r[0], n1_r[1], n1_r[2], 3)    let n2_r_sh = SHEval(n2_r[0], n2_r[1], n2_r[2], 3)    let n3_r_sh = SHEval(n3_r[0], n3_r[1], n3_r[2], 3)    let S = math.matrix(    [        [n1_r_sh[1], n2_r_sh[1], n3_r_sh[1]],         [n1_r_sh[2], n2_r_sh[2], n3_r_sh[2]],         [n1_r_sh[3], n2_r_sh[3], n3_r_sh[3]],     ]);    \/\/ 5\u3001S*A_inverse    return math.multiply(S, A_inverse)   }function computeSquareMatrix_5by5(rotationMatrix){ \/\/ \u8ba1\u7b97\u65b9\u9635SA(-1) 5*5    \/\/ 1\u3001pick ni - {ni}    let k = 1 \/ math.sqrt(2);    let n1 = [1, 0, 0, 0]; let n2 = [0, 0, 1, 0]; let n3 = [k, k, 0, 0];     let n4 = [k, 0, k, 0]; let n5 = [0, k, k, 0];    \/\/ 2\u3001{P(ni)} - A  A_inverse    let n1_sh = SHEval(n1[0], n1[1], n1[2], 3)    let n2_sh = SHEval(n2[0], n2[1], n2[2], 3)    let n3_sh = SHEval(n3[0], n3[1], n3[2], 3)    let n4_sh = SHEval(n4[0], n4[1], n4[2], 3)    let n5_sh = SHEval(n5[0], n5[1], n5[2], 3)    let A = math.matrix(    [        [n1_sh[4], n2_sh[4], n3_sh[4], n4_sh[4], n5_sh[4]],         [n1_sh[5], n2_sh[5], n3_sh[5], n4_sh[5], n5_sh[5]],         [n1_sh[6], n2_sh[6], n3_sh[6], n4_sh[6], n5_sh[6]],         [n1_sh[7], n2_sh[7], n3_sh[7], n4_sh[7], n5_sh[7]],         [n1_sh[8], n2_sh[8], n3_sh[8], n4_sh[8], n5_sh[8]],     ]);    let A_inverse = math.inv(A);    \/\/ 3\u3001\u7528 R \u65cb\u8f6c ni - {R(ni)}    let n1_r = math.multiply(rotationMatrix, n1);    let n2_r = math.multiply(rotationMatrix, n2);    let n3_r = math.multiply(rotationMatrix, n3);    let n4_r = math.multiply(rotationMatrix, n4);    let n5_r = math.multiply(rotationMatrix, n5);    \/\/ 4\u3001R(ni) SH\u6295\u5f71 - S    let n1_r_sh = SHEval(n1_r[0], n1_r[1], n1_r[2], 3)    let n2_r_sh = SHEval(n2_r[0], n2_r[1], n2_r[2], 3)    let n3_r_sh = SHEval(n3_r[0], n3_r[1], n3_r[2], 3)    let n4_r_sh = SHEval(n4_r[0], n4_r[1], n4_r[2], 3)    let n5_r_sh = SHEval(n5_r[0], n5_r[1], n5_r[2], 3)    let S = math.matrix(    [            [n1_r_sh[4], n2_r_sh[4], n3_r_sh[4], n4_r_sh[4], n5_r_sh[4]],         [n1_r_sh[5], n2_r_sh[5], n3_r_sh[5], n4_r_sh[5], n5_r_sh[5]],         [n1_r_sh[6], n2_r_sh[6], n3_r_sh[6], n4_r_sh[6], n5_r_sh[6]],         [n1_r_sh[7], n2_r_sh[7], n3_r_sh[7], n4_r_sh[7], n5_r_sh[7]],         [n1_r_sh[8], n2_r_sh[8], n3_r_sh[8], n4_r_sh[8], n5_r_sh[8]],     ]);    \/\/ 5\u3001S*A_inverse    return math.multiply(S, A_inverse)  }function mat4Matrix2mathMatrix(rotationMatrix){    let mathMatrix = [];    for(let i = 0; i < 4; i++){        let r = [];        for(let j = 0; j < 4; j++){            r.push(rotationMatrix[i*4+j]);        }        mathMatrix.push(r);    }    \/\/ Edit Start    \/\/return math.matrix(mathMatrix)    return math.transpose(mathMatrix)    \/\/ Edit End}function getMat3ValueFromRGB(precomputeL){    let colorMat3 = [];    for(var i = 0; i<3; i++){        colorMat3[i] = mat3.fromValues( precomputeL[0][i], precomputeL[1][i], precomputeL[2][i],                                        precomputeL[3][i], precomputeL[4][i], precomputeL[5][i],                                        precomputeL[6][i], precomputeL[7][i], precomputeL[8][i] );     }    return colorMat3;}\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/\/ tools.js<\/span><\/span>\n<span class=\"line\"><span style=\"color: #4EC9B0\">Function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">getRotationPrecomputeL<\/span><span style=\"color: #D4D4D4\">(precompute_L, rotationMatrix){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">rotationMatrix_inverse<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">mat4<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">create<\/span><span style=\"color: #D4D4D4\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">mat4<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">invert<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">rotationMatrix_inverse<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">rotationMatrix<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">r<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">mat4Matrix2mathMatrix<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">rotationMatrix_inverse<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">shRotateMatrix3x3<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">computeSquareMatrix_3by3<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">r<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">shRotateMatrix5x5<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">computeSquareMatrix_5by5<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">r<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">Result<\/span><span style=\"color: #D4D4D4\"> = [];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #B5CEA8\">9<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">Result<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">] = [];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">L_SH_R_3<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">math<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">multiply<\/span><span style=\"color: #D4D4D4\">([<\/span><span style=\"color: #9CDCFE\">precompute_L<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">precompute_L<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">precompute_L<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">]], <\/span><span style=\"color: #9CDCFE\">shRotateMatrix3x3<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">L_SH_R_5<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">math<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">multiply<\/span><span style=\"color: #D4D4D4\">([<\/span><span style=\"color: #9CDCFE\">precompute_L<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">4<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">precompute_L<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">5<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">precompute_L<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">6<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">precompute_L<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">7<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">precompute_L<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">8<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">]], <\/span><span style=\"color: #9CDCFE\">shRotateMatrix5x5<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">Result<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">] = <\/span><span style=\"color: #9CDCFE\">precompute_L<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">Result<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">] = <\/span><span style=\"color: #9CDCFE\">L_SH_R_3<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">_data<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">Result<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">] = <\/span><span style=\"color: #9CDCFE\">L_SH_R_3<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">_data<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">Result<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">] = <\/span><span style=\"color: #9CDCFE\">L_SH_R_3<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">_data<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">Result<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">4<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">] = <\/span><span style=\"color: #9CDCFE\">L_SH_R_5<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">_data<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">Result<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">5<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">] = <\/span><span style=\"color: #9CDCFE\">L_SH_R_5<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">_data<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">Result<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">6<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">] = <\/span><span style=\"color: #9CDCFE\">L_SH_R_5<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">_data<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">Result<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">7<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">] = <\/span><span style=\"color: #9CDCFE\">L_SH_R_5<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">_data<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">Result<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">8<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">] = <\/span><span style=\"color: #9CDCFE\">L_SH_R_5<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">_data<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">4<\/span><span style=\"color: #D4D4D4\">];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">Result<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #4EC9B0\">Function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">computeSquareMatrix_3by3<\/span><span style=\"color: #D4D4D4\">(rotationMatrix){ <\/span><span style=\"color: #6A9955\">\/\/ Calculate the square matrix SA(-1) 3*3 <\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ 1. pick ni - {ni}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n1<\/span><span style=\"color: #D4D4D4\"> = [<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">]; <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n2<\/span><span style=\"color: #D4D4D4\"> = [<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">]; <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n3<\/span><span style=\"color: #D4D4D4\"> = [<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">];<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ 2. {P(ni)} - A A_inverse<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n1_sh<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">SHEval<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">n1<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n1<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n1<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n2_sh<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">SHEval<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">n2<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n2<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n2<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n3_sh<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">SHEval<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">n3<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n3<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n3<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">A<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">math<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">matrix<\/span><span style=\"color: #D4D4D4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    [<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        [<\/span><span style=\"color: #9CDCFE\">n1_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n2_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n3_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">]], <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        [<\/span><span style=\"color: #9CDCFE\">n1_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n2_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n3_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">]], <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        [<\/span><span style=\"color: #9CDCFE\">n1_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n2_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n3_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">]], <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    ]);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">A_inverse<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">math<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">inv<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">A<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ 3. Use R to rotate ni - {R(ni)}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n1_r<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">math<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">multiply<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">rotationMatrix<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">n1<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n2_r<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">math<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">multiply<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">rotationMatrix<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">n2<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n3_r<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">math<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">multiply<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">rotationMatrix<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">n3<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ 4. R(ni) SH projection - S<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n1_r_sh<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">SHEval<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">n1_r<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n1_r<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n1_r<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n2_r_sh<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">SHEval<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">n2_r<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n2_r<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n2_r<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n3_r_sh<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">SHEval<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">n3_r<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n3_r<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n3_r<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">S<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">math<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">matrix<\/span><span style=\"color: #D4D4D4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    [<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        [<\/span><span style=\"color: #9CDCFE\">n1_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n2_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n3_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">]], <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        [<\/span><span style=\"color: #9CDCFE\">n1_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n2_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n3_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">]], <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        [<\/span><span style=\"color: #9CDCFE\">n1_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n2_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n3_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">]], <\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    ]);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ 5. S*A_inverse<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">math<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">multiply<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">S<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">A_inverse<\/span><span style=\"color: #D4D4D4\">)   <\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #4EC9B0\">Function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">computeSquareMatrix_5by5<\/span><span style=\"color: #D4D4D4\">(rotationMatrix){ <\/span><span style=\"color: #6A9955\">\/\/ Calculate the square matrix SA(-1) 5*5<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ 1. pick ni - {ni}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">k<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\"> \/ <\/span><span style=\"color: #9CDCFE\">math<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">sqrt<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n1<\/span><span style=\"color: #D4D4D4\"> = [<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">]; <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n2<\/span><span style=\"color: #D4D4D4\"> = [<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">]; <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n3<\/span><span style=\"color: #D4D4D4\"> = [<\/span><span style=\"color: #9CDCFE\">k<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">k<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">]; <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n4<\/span><span style=\"color: #D4D4D4\"> = [<\/span><span style=\"color: #9CDCFE\">k<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">k<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">]; <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n5<\/span><span style=\"color: #D4D4D4\"> = [<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">k<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">k<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">];<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ 2. {P(ni)} - A A_inverse<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n1_sh<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">SHEval<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">n1<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n1<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n1<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n2_sh<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">SHEval<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">n2<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n2<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n2<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n3_sh<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">SHEval<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">n3<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n3<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n3<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n4_sh<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">SHEval<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">n4<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n4<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n4<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n5_sh<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">SHEval<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">n5<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n5<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n5<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">A<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">math<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">matrix<\/span><span style=\"color: #D4D4D4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    [<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        [<\/span><span style=\"color: #9CDCFE\">n1_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">4<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n2_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">4<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n3_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">4<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n4_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">4<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n5_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">4<\/span><span style=\"color: #D4D4D4\">]], <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        [<\/span><span style=\"color: #9CDCFE\">n1_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">5<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n2_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">5<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n3_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">5<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n4_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">5<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n5_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">5<\/span><span style=\"color: #D4D4D4\">]], <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        [<\/span><span style=\"color: #9CDCFE\">n1_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">6<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n2_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">6<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n3_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">6<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n4_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">6<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n5_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">6<\/span><span style=\"color: #D4D4D4\">]], <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        [<\/span><span style=\"color: #9CDCFE\">n1_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">7<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n2_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">7<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n3_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">7<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n4_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">7<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n5_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">7<\/span><span style=\"color: #D4D4D4\">]], <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        [<\/span><span style=\"color: #9CDCFE\">n1_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">8<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n2_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">8<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n3_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">8<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n4_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">8<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n5_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">8<\/span><span style=\"color: #D4D4D4\">]], <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    ]);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">A_inverse<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">math<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">inv<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">A<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ 3. Use R to rotate ni - {R(ni)}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n1_r<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">math<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">multiply<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">rotationMatrix<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">n1<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n2_r<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">math<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">multiply<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">rotationMatrix<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">n2<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n3_r<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">math<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">multiply<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">rotationMatrix<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">n3<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n4_r<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">math<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">multiply<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">rotationMatrix<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">n4<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n5_r<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">math<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">multiply<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">rotationMatrix<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">n5<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ 4. R(ni) SH projection - S<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n1_r_sh<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">SHEval<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">n1_r<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n1_r<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n1_r<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n2_r_sh<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">SHEval<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">n2_r<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n2_r<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n2_r<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n3_r_sh<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">SHEval<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">n3_r<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n3_r<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n3_r<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n4_r_sh<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">SHEval<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">n4_r<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n4_r<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n4_r<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n5_r_sh<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">SHEval<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">n5_r<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n5_r<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n5_r<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">S<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">math<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">matrix<\/span><span style=\"color: #D4D4D4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    [    <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        [<\/span><span style=\"color: #9CDCFE\">n1_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">4<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n2_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">4<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n3_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">4<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n4_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">4<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n5_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">4<\/span><span style=\"color: #D4D4D4\">]], <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        [<\/span><span style=\"color: #9CDCFE\">n1_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">5<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n2_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">5<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n3_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">5<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n4_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">5<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n5_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">5<\/span><span style=\"color: #D4D4D4\">]], <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        [<\/span><span style=\"color: #9CDCFE\">n1_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">6<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n2_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">6<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n3_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">6<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n4_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">6<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n5_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">6<\/span><span style=\"color: #D4D4D4\">]], <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        [<\/span><span style=\"color: #9CDCFE\">n1_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">7<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n2_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">7<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n3_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">7<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n4_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">7<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n5_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">7<\/span><span style=\"color: #D4D4D4\">]], <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        [<\/span><span style=\"color: #9CDCFE\">n1_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">8<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n2_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">8<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n3_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">8<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n4_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">8<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">n5_r_sh<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">8<\/span><span style=\"color: #D4D4D4\">]], <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    ]);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ 5. S*A_inverse<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">math<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">multiply<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">S<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">A_inverse<\/span><span style=\"color: #D4D4D4\">)  <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #4EC9B0\">Function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">mat4Matrix2mathMatrix<\/span><span style=\"color: #D4D4D4\">(rotationMatrix){<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">mathMatrix<\/span><span style=\"color: #D4D4D4\"> = [];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #B5CEA8\">4<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">r<\/span><span style=\"color: #D4D4D4\"> = [];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #B5CEA8\">4<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\">++){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">r<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">push<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">rotationMatrix<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">*<\/span><span style=\"color: #B5CEA8\">4<\/span><span style=\"color: #D4D4D4\">+<\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\">]);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">mathMatrix<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">push<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">r<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ Edit Start<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/return math.matrix(mathMatrix)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">math<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">transpose<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">mathMatrix<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ Edit End<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #4EC9B0\">Function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">getMat3ValueFromRGB<\/span><span style=\"color: #D4D4D4\">(precomputeL){<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">let<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">colorMat3<\/span><span style=\"color: #D4D4D4\"> = [];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">colorMat3<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">] = <\/span><span style=\"color: #9CDCFE\">mat3<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">fromValues<\/span><span style=\"color: #D4D4D4\">( <\/span><span style=\"color: #9CDCFE\">precomputeL<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">precomputeL<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">precomputeL<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">],<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                                        <\/span><span style=\"color: #9CDCFE\">precomputeL<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">precomputeL<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">4<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">precomputeL<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">5<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">],<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                                        <\/span><span style=\"color: #9CDCFE\">precomputeL<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">6<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">precomputeL<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">7<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">precomputeL<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">8<\/span><span style=\"color: #D4D4D4\">][<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">] ); <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">colorMat3<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative\">C#<\/span><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">result<\/h3>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-4.gif\" alt=\"img\" class=\"wp-image-1351 lazyload\"\/><noscript><img decoding=\"async\" width=\"300\" height=\"200\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-4.gif\" alt=\"img\" class=\"wp-image-1351 lazyload\"\/><\/noscript><\/figure>\n\n\n\n<p>Animated GIFs can be found on<a href=\"https:\/\/regz-1258735137.cos.ap-guangzhou.myqcloud.com\/PicGo_dir\/converted_to_gif-2.gif\">Here <\/a>Get.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">principle<\/h3>\n\n\n\n<h3 class=\"wp-block-heading\">Two key properties<\/h3>\n\n\n\n<p>First, let me briefly explain the principle. Two properties of spherical harmonics are used here.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Rotational invariance<\/strong><\/li>\n<\/ol>\n\n\n\n<p>If you rotate the coordinates of a function in 3D space and substitute the rotated coordinates into the spherical harmonics, you will get the same result as the original function.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Linearity of rotation<\/strong><\/li>\n<\/ol>\n\n\n\n<p>For each &quot;layer&quot; or &quot;band&quot; of spherical harmonics (that is, all spherical harmonics of a given order l), its SH coefficients can be rotated, and this rotation is linear. That is, the coefficients of a spherical harmonic expansion can be rotated by a matrix multiplication.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Overview of Wigner D Matrix Rotation Method<\/h3>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>The rotation of spherical harmonics is an in-depth topic, so we will give a brief overview here without involving complicated mathematical proofs. The method given in the homework framework is based on projection. This article will first introduce a more precise method, the Wigner D matrix. For more details, please see:<a href=\"https:\/\/zhuanlan.zhihu.com\/p\/140421707\">\u7403\u8c10\u5149\u7167\u7b14\u8bb0\uff08\u65cb\u8f6c\u7bc7\uff09 &#8211; \u7f51\u6613\u6e38\u620f\u96f7\u706b\u4e8b\u4e1a\u7fa4\u7684\u6587\u7ae0 &#8211; \u77e5\u4e4e<\/a> Anyway, I didn\u2019t understand it QAQ.<\/p>\n<\/blockquote>\n\n\n\n<p>Since the first three order spherical harmonics are currently used and band0 has only one projection coefficient, we only need to process the rotation matrices of band1 and band2.<\/p>\n\n\n\n<p>The rotation of spherical harmonics can be expressed as:<\/p>\n\n\n\n<p>where is the rotation matrix element that gives how to rotate the spherical harmonic coefficients from their original orientations to their new orientations.<\/p>\n\n\n\n<p>Suppose there is a function that can<strong>Expanded into a linear combination of spherical harmonics<\/strong> :<\/p>\n\n\n\n<p>If we want to rotate this function, we do not rotate each spherical harmonic directly, but<strong>Rotate their coefficients<\/strong>The new expansion coefficients can be obtained from the original coefficients through the rotation matrix:<\/p>\n\n\n\n<p>Now comes the crucial step: how to<strong>Calculate the rotation matrix<\/strong>?<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-225.png\" alt=\"img\" class=\"wp-image-1353 lazyload\"\/><noscript><img decoding=\"async\" width=\"1108\" height=\"492\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-225.png\" alt=\"img\" class=\"wp-image-1353 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-225.png 1108w, https:\/\/remoooo.com\/wp-content\/uploads\/image-225-300x133.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-225-1024x455.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-225-768x341.png 768w\" sizes=\"(max-width: 1108px) 100vw, 1108px\" \/><\/noscript><\/figure>\n\n\n\n<p>In the homework framework, we learned that band 1 needs to construct a matrix, and band 2 needs to construct a matrix. In other words, for each band of order, it has a legal solution, and each solution corresponds to a basis function on the current band, which is a feature of the Legendre equation.<\/p>\n\n\n\n<p>Now, let&#039;s consider the effect of rotation.<\/p>\n\n\n\n<p>When we rotate an environment light, we don&#039;t rotate the basis functions, but rather &quot;rotate&quot; all the coefficients. The process of rotating a specific coefficient involves using the Wigner D matrix. First, when we talk about rotations, we usually mean rotations around some axis, defined by Euler angles. For each order, we calculate a square matrix with side length .<\/p>\n\n\n\n<p>Once we get the rotation matrix corresponding to each order, we can easily calculate the new coefficients after &quot;rotation&quot;:<\/p>\n\n\n\n<p>However, computing the elements of the Wigner D matrix can be a bit complicated, especially for higher orders. Therefore, the assignment prompt gives a projection-based method. Next, let&#039;s see how the above two code snippets are implemented.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Projection approximation<\/h3>\n\n\n\n<p>First, select a normal vector. The selection of this quantity needs to ensure linear independence, that is, to cover the sphere as evenly as possible (Fibonacci spherical sampling may be a good choice), otherwise there will be errors in calculating singular matrices later.<strong>Make sure the resulting matrix is full rank<\/strong>.<\/p>\n\n\n\n<p>For each normal vector, project it onto the spherical harmonics (SHEval function), which actually calculates the dot product of the spherical harmonics with that direction. From this projection, you can get a dimensional vector, each of whose components is a coefficient of the spherical harmonics.<\/p>\n\n\n\n<p>Using the vectors obtained above, we can construct the matrix and the inverse matrix. If we denote the normal vector as the coefficient of the spherical harmonic function, then the matrix can be written as:<\/p>\n\n\n\n<p>For each normal vector, apply the rotation, and we get (pre-multiplication):<\/p>\n\n\n\n<p>Then, for these rotated normal vectors, spherical harmonic projection is performed again to obtain.<\/p>\n\n\n\n<p>Using the vectors obtained from the rotated normal vectors, we can construct the matrix S. Calculating the rotation matrix: The rotation matrix tells us how to rotate the spherical harmonic coefficients by simple matrix multiplication.<\/p>\n\n\n\n<p>By multiplying the original spherical harmonic coefficient vector by the matrix, we can get the rotated spherical harmonic coefficients. Repeat for each layer: To get the complete rotated spherical harmonic coefficients, we need to repeat the above process for each layer.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Reference<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Games 202<\/li>\n\n\n\n<li>https:\/\/github.com\/DrFlower\/GAMES_101_202_Homework\/tree\/main\/Homework_202\/Assignment2<\/li>\n<\/ol>","protected":false},"excerpt":{"rendered":"<p>\u56e0\u4e3a\u6211\u4e5f\u662f\u83dc\u9e21\uff0c\u6240\u4ee5\u4e0d\u80fd\u786e\u4fdd\u6240\u6709\u90fd\u662f\u6b63\u786e\u7684\uff0c\u5e0c\u671b\u5927\u4f6c\u6307\u6b63\u3002 \u77e5\u4e4e\u7684\u516c\u5f0f\u6709\u70b9\u4e11\u964b\uff0c\u53ef\u4ee5\u53bb\uff1aGitHub \u9879\u76ee\u6e90\u4ee3 [&hellip;]<\/p>","protected":false},"author":1,"featured_media":1351,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[53],"tags":[56,72],"class_list":["post-1343","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tech","tag-cg","tag-prt"],"_links":{"self":[{"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/posts\/1343","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/comments?post=1343"}],"version-history":[{"count":3,"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/posts\/1343\/revisions"}],"predecessor-version":[{"id":1913,"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/posts\/1343\/revisions\/1913"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/media\/1351"}],"wp:attachment":[{"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/media?parent=1343"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/categories?post=1343"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/tags?post=1343"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}