ăăăŤăĄăŻă 2017ĺš´ăŻĺşăŤăăăžăă ĺç´ăŞă˘ăă¤ăŤăăăłăăŠăŚăśă˘ăăŞăąăźăˇă§ăłă§ăăăçŠççăŤćŁăăç
§ćăăăŁăăă¨ćăĺ§ăăŚăăžăă ă¤ăłăżăźăăăăŤăŻăăăăăăŽč¨äşă¨ć˘čŁ˝ăŽăˇă§ăźăăźăăăăăăăăžăă ăăăŚăPBRăĺĄăäťăăăŽăç°ĄĺăŞăŻăă§ă...ăžăăŻăăă§ăŞăăŽă§ăăďź
ĺŽéăćŁç´ăŞPBRăŻăĺć§ăŽçľćăéćăăăŽăŻç°Ąĺă§ăăăćŁăăçľćăĺžăăŽăŻéŁăăăăăĺŽčĄăăăŽăŻĺ°éŁă§ăă ăžăăă¤ăłăżăźăăăăŤăŻăćŁăăçľćă§ăŻăŞăăăžăŁăăĺăçľćăăăăăč¨äşăăăăăăăăžăă ăăŽăŤăŞăšă§ăŤăăŹăăăăă¨ăĺé˘ăăăă¨ăŻéŁăăăŞăăžăă
ăăăăŁăŚăăăŽč¨äşăŽçŽçăŻăPBRăŽćŚčŚă¨ăăŽćŠč˝ăç解ăăăă¨ă ăă§ăŞăăPBRăŽä˝ććšćłăĺŚăśăă¨ă§ăăăăžăă é常ăăăăă°ćšćłăĺç
§ĺ
ăăăăłééăăŽĺĺ ă
ăăŽč¨äşăŻăăă§ăŤhlslăĺĺăŤçĽăŁăŚăăăçˇĺ˝˘äťŁć°ăŤç˛žéăăŚăăäşşă寞蹥ă¨ăăŚăăžăăćăĺç´ăŞéPBR PhongăŠă¤ăăć¸ăăă¨ăă§ăăžăă ä¸čŹçăŤăŻăă§ăăă ăç°ĄĺăŤčŞŹćăăăă¨ăăžăăăăˇă§ăźăăźăŽä˝żç¨çľé¨ăăăăă¨ăéĄăŁăŚăăžăă
ăľăłăăŤăŻDelphiă§č¨čż°ăăăžăďźFreePascală§ăăŤăăăăžăďźăăăĄă¤ăłăłăźăăŻhlslăŽăžăžă§ăă ăăăăŁăŚăDelphiăçĽăăŞăăŚăćăăăŞăă§ăă ăăă
ăŠăă§čŚăăćăăăă§ăăžăăďźăľăłăăŤăăăŤăăăăŤăŻă
AvalancheProjectăłăźăăĺż
čŚă§ăă ăăăŻDX11 / OpenGLăä¸ĺżă¨ăăç§ăŽăăŹăźă ăŻăźăŻă§ăă ăžă
Vampyre Imaging Libraryăĺż
čŚă§ăă ăăăŻĺçăćä˝ăăăăăŽăŠă¤ăăŠăŞă§ăăăăŻăšăăŁăăăźăăăăăăŤä˝żç¨ăăžăă äžăŽă˝ăźăšăłăźăăŻ
ăăĄăă§ăă ăă¤ăăŞăĺéăăăăŞă/ĺéă§ăăŞăăăć˘ăŤĺéăăăăŽă使ç¨ăăăĺ ´ĺăŻă
ăăĄăăŤăă
ăžă ă
ăˇăźăăăŤăăçˇ ăăăŽă§ăčĄăăă
1 sRGBăľăăźăăŽéčŚć§
é常ăă˘ăăżăźăŻsRGBçťĺă襨示ăăžăă ăăăŻăăšăŻăăăăŤă¤ăăŚăŻ95ďź
çĺŽă§ăăăăŠăăăăăăŤă¤ăăŚăŻăăç¨ĺşŚçĺŽă§ăďźăăăŚăéťčŠąă§ăŻĺ
¨ăăŽćć§ăăăăžăďźă
ăăăŻăçĽčŚăçˇĺ˝˘ă§ăŻăŞăă¨ăăäşĺŽăŤăăăăŽă§ăăăćăăé ĺă§ăŽĺă羜寞çăŞĺ¤ĺăăăćăé ĺă§ăŽĺ
ăŽćšăăăĺ°ăăŞĺ¤ĺăŤć°ăĽăăžăă ç˛ăĺ ´ĺăŻă4ĺăŽćăăăŽĺ˘ĺ ă§ă2ĺăŽćăăăŽĺ˘ĺ ă¨ăăŚčŞčăăžăă ç§ăŻăăŞăăŽăăăŤĺçăç¨ćăăžăăďź
çťĺăç解ăăĺăŤăăăŠăŚăśăžăăŻăŞăăŹăźăăŁăłă°ăˇăšăă ăçťĺăŽăľă¤ăşăĺ¤ć´ăăŚăăŞăăă¨ă確čŞăăŚăă ăăă
ä¸ĺ¤ŽăŤăŻăć°´ĺšłćšĺăŽĺä¸ăăŻăťăŤăŽéťă¨ç˝ăŽăšăăŠă¤ăă§ć§ćăăăćŁćšĺ˝˘ăăăăžăă ăăŽćŁćšĺ˝˘ăăăŽĺ
ăŽéăŻăçăŁç˝ăăăŽĺ
ăŽéăŽăĄăăăŠ2ĺă§ăă ăăă§ăăšăăŠă¤ăăĺăč˛ăŽćŁćšĺ˝˘ăŤăăźă¸ăăăăăŤçťé˘ăăé˘ăăă¨ăăăŁăŞăăŹăźăˇă§ăłăăăă˘ăăżăźă§ăŻăä¸ĺ¤ŽăŽćŁćšĺ˝˘ăĺłăŽćŁćšĺ˝˘ă¨ăăźă¸ăă塌ăŽćŁćšĺ˝˘ăăŻăăăŤćăăŞăăžăă 塌ĺ´ăŽćŁćšĺ˝˘ăŽč˛ăăăăăă§čŚăă¨ă128ă§ăăăĺłĺ´ăŽč˛ă187ă§ăăăă¨ăăăăăžăă 187ă
ăăăăŁăŚăçŠççăŤćŁăăăŹăłăăŞăłă°ăčĄăăŤăŻăçťé˘ä¸ăŽç˝ă0.5ĺăăĺ¤ă187 187 187ăŤăŞăăă¨ăéčŚă§ăăăăŽăăăă°ăŠăăŁăăŻAPIďźDirectXăăăłOpenGLďźăŻsRGBăŽăăźăăŚă§ă˘ăľăăźăăĺăăŚăăžăă ăˇă§ăźăăźă§ăăŻăšăăŁăćä˝ăăçŹéăŤăăăŻăšăăŁăŻçˇĺ˝˘çŠşéăŤčť˘éăăăçťé˘ăŤčĄ¨ç¤şăăăă¨ăsRGBăŤčť˘éăăăžăă
DirectX / OpenGLă§ăăăĺŽçžăăćšćłăŤă¤ăăŚăŻčŠłăă誏ćăăžăăă ă°ăźă°ăŤăŻç°Ąĺă§ăă ăăăŚăăăŞăăŽsRGBăé常ăŤĺç´ăŤç˛ĺžăăăă¨ă確čŞăăŚăă ăăă éťăăç˝ă¸ăŽçˇĺ˝˘ă°ăŠăăźăˇă§ăłăŻćŹĄăŽăăăŤĺ¤ć´ăăĺż
čŚăăăăžăă
ăă
㯠ăPBRăŤé˘ăăč¨äşă§ă¤ăłăżăźăăăä¸ă§çşçăă
ćĺăŽééăăŽ1ă¤ă§ăăăăăçˇĺ˝˘çŠşéă§ä˝ćĽăăăă¨ăŽéčŚć§ă示ăĺż
čŚăăăăžăăă
2ăŻăăŻăăźăŠăłăš
çŠççăŤćŁăăăŹăłăăŞăłă°ă§ăŻăé常揥ăŽăăăŞăă¨ăčć
Žăăăžăă
- ăăŹăăŤĺĺ°äżć°
- çă¨ăćł
- ĺĺ°ĺ
ă¨ĺćžĺ°ăŽăă¤ăŻăăăĄăťăăçčŤ
ăăŽăŞăšăăŻă襨é˘ä¸ćŁäšąăçŠççăŤćŁăăĺąćăŞăŠăŽăă¤ăŻăăăĄăťăăçčŤă§ćĄĺźľă§ăăžăăăăăŽč¨äşă§ăŻćĺăŽ3ă¤ăŽăă¤ăłăăŤă¤ăăŚčŞŹćăăžăă
2.1ăă¤ăŻăăăĄăťăăçčŤ
çžĺŽä¸çăŽăăžăăžăŞććăŽčĄ¨é˘ăŻăĺŽĺ
¨ăŤćťăăă§ăŻăŞăăé常ăŤç˛ăă§ăă ăăăăŽä¸čŚĺć§ăŻĺ
ăŽćł˘éˇăăăăŻăăăŤéˇăăç
§ćăŤĺ¤§ăă貢çŽăăžăă ĺä¸ăŽćłçˇăăŻăăŤă§ĺ¤§ăžăăŞĺšłé˘ăč¨čż°ăăăă¨ăŻä¸ĺŻč˝ă§ăăăćłçˇăŻé常ăăăŻă襨é˘ăŽĺšłĺĺ¤ăč¨čż°ăăžăă
çžĺŽăŤăŻăĺĺ°ĺ
ăŤä¸ťăŤč˛˘çŽăăăŽăŻăăŻăăŽéĄă§ăďź
ĺ
Ľĺ°č§ăŻĺĺ°č§ăŤçăăăăăŽĺłăŽăăŻăăŤhăŻăă¤ăŻăăă§ă¤ăšăŽćłçˇăćŁç˘şăŤčĄ¨ăăç
§ćăŤĺŻä¸ăăăă¨ăçăčŚăăŚăăžăă 襨é˘ä¸ăŽăăŽăă¤ăłăăăăŽĺ
ă襨示ăăăžăă
ăăăŤăä¸çăŽä¸é¨ăŻăăăăĺć ăăĺŻč˝ć§ăŽăăăă¤ăŻăăă§ă¤ăšăŤçŠççăŤĺ°éăăŚăăžăăă
ăăăŻăăťăŤăăˇăŁăăŚă¤ăłă°ăžăăŻ
ăťăŤăăˇăŁăăŚă¤ăłă°ă¨ĺźă°ăăžăă
ăăăŚă襨é˘ăŤéŁăă§ĺĺ°ăăĺ
ăŻă常ăŤéŁăłĺşăăă¨ăă§ăăă¨ăŻéăăžăăă
ăăăŻăčŞĺˇąéč¤ăžăăŻ
ăăšăăłă°ă¨ĺźă°ăăžăă ăăăŚăćăunningăŞĺ
ăŻ2ĺ䝼ä¸ĺĺ°ăăăă¨ăă§ăăžăďź
ăăăŚăăăŽĺšćăŻ-
ĺ帰ĺĺ°ă¨ĺźă°ăăžăă ăăăăŽăăšăŚăŽăă¤ăŻăăă§ăźăšăŻăé常ďźĺ¸¸ăŤă§ăŻăŞăăďźçŻĺ˛ďź0; 1ďźăŤăăç˛ăäżć°ă§čĄ¨ăăăžăă0ă§ăŻă襨é˘ăŻĺŽĺ
¨ăŤćťăăă§ăăă¤ăŻăăă§ăźăšăŻăăăžăăăç˛ăäżć°ăŻă1ç˛ăăŤçăăĺšłćťĺşŚäżć°ăŤç˝Žăćăăăăĺ ´ĺăăăăžăă
ăăăŻĺşćŹçăŤăĺĺ°ĺ
ăŤĺŻžăăăľăźăă§ăšăŽĺä˝ăŤé˘ăăăăšăŚă§ăă
2.2ĺćšĺĺĺ°çĺĺ¸é˘ć°
ăăŽăăă襨é˘ăŤĺ
Ľăĺ
ăŻé¨ĺçăŤĺĺ°ăăăé¨ĺçăŤććăŤćľ¸éăăžăă ăăăăŁăŚăĺĺ°ĺ
ăŽéăŻćĺăŤĺ
¨ĺ
ćăăĺé˘ăăăžăă ăăăŤăĺĺ°ĺ
ăŽéă ăă§ăŞăăçŽăŤĺ
Ľăĺ
ăŽéăŤăé˘ĺżăăăăžăă ăăăŚăăăăŻăăžăăžăŞ
ĺćšĺĺĺ°çĺĺ¸é˘ć°ďźBRDFďźăŤăăŁăŚč¨čż°ăăăžăă
ćăäşşć°ăŽăăă˘ăăŤăŽ1ă¤ă
ăŻăăŻăăźăŠăłăšă˘ăăŤăć¤č¨ăăžăă
ăăŽé˘ć°ă§ăŻďź
VăŻă茳渏č
ăŽčĄ¨é˘ăăçŽăžă§ăŽăăŻăăŤă§ăă
N-襨é˘ăŽăăŻăćłçˇ
L-襨é˘ăăĺ
ćşă¸ăŽćšĺ
DăŻă垎ĺ°é˘ăčć
Žăăĺĺ°ĺ
ăŽĺĺ¸é˘ć°ă§ăă ç§ăăĄăŽçŽăŤĺ
ăĺĺ°ăăăăăŤç§ăăĄăŤĺăăăăăă¤ăŻăăă§ăźăšăŽć°ă誏ćăăžăă
GăŻăčŞĺˇąăˇăŁăăŚă¤ăłă°ă¨čŞĺˇąéč¤ăŽĺĺ¸é˘ć°ă§ăă ćŽĺżľăŞăăăăăŽé˘ć°ă§ć°ĺĺĺ°ăăĺ
ăŻčć
Žăăăă夹ăăăžăă ăăŽçšăŤă¤ăăŚăŻăč¨äşăŽĺžĺă§čŞŹćăăžăă
F-ăăŹăăŤĺĺ°äżć°ă ăăšăŚăŽĺ
ăĺĺ°ăăăăăă§ăŻăăăžăăă ĺ
ăŽä¸é¨ăŻĺąćăăăăăŞă˘ăŤăŤĺ
Ľăăžăă ăăŽé˘ć°ă§ăŻăFăŻĺĺ°ĺ
ăŽéă襨ăăžăă
ĺźă§ăă
HăăŻăăŤăŞăŠăŽăăŠăĄăźăżăźăŻčĄ¨ç¤şăăăžăăăăDăăăłGĺĺ¸é˘ć°ă§çŠćĽľçăŤä˝żç¨ăăăžăă
HăăŻăăŤăŽćĺłăŻăĺĺ°ĺ
ăŤĺŻä¸ăăăă¤ăŻăăă§ăźăšăŽćłçˇăč¨čż°ăăăă¨ă§ăă ă¤ăžă é常ăŽ
Hăćă¤ăă¤ăŻăăăĄăťăăăŤĺ
Ľĺ°ăăĺ
çˇăŻă常ăŤç§ăăĄăŽçŽăŤĺĺ°ăăăžăă ĺ
Ľĺ°č§ăŻĺĺ°č§ăŤçăăăăă
Hă
ćŁčŚĺďźV + Lďźă¨ăăŚĺ¸¸ăŤč¨çŽă§ăăžăă ăăŽăăăŞăăŽďź
ĺĺ¸é˘ć°
Dă¨
GăŻčżäźźč§Łă§ăăăĺ¤ăăŽç°ăŞăé˘ć°ăăăăžăă č¨äşăŽćĺžăŤăăăŽăăăŞăăŁăšăăŞăăĽăźăˇă§ăłăŽăŞăšăă¸ăŽĺç
§ăćŽăăžăă Bruce Walterăéçşăă
GGXĺĺ¸é˘ć°ă使ç¨ăăžăă
2.3 G.ăŞăźăăźăŠăăă¸ăŞăĄăăŞ
ăťăŤăăˇăŁăăźă¤ăłă°ă¨ăŞăźăăźăŠăăăăĺ§ăăžăăăă ăăăŻé˘ć°
Gă§ăă ăăŽé˘ć°
ăŽGGXĺĺ¸ăŻăăšăăšćłă使ç¨ăăŚăăžăďźSmith 1967ăăăŠăłăă ăŞç˛ă襨é˘ăŽĺšžä˝ĺŚçăŞĺ˝ąăďźă ăăŽćšćłăŽä¸ťăŞçšăŻăĺ
ăă襨é˘ă¸ăăăăłčĄ¨é˘ăă茳ĺŻč
ă¸ă¨ĺ¤ąăăăĺ
ăŽéăăćĺˇăŽăăŻăăăźăăŤăŤĺŻžăăŚĺŻžç§°ăŤăŞăăă¨ă§ăă ăăăăŁăŚăé˘ć°
Gă2ă¤ăŽé¨ĺăŤĺĺ˛ăă
Nă¨
LăŽéăŽč§ĺşŚăăć夹ĺ
ăŽĺĺăč¨çŽăă揥ăŤĺăé˘ć°ă使ç¨ăăŚă
Vă¨
NăŽéăŽč§ĺşŚăăć夹ĺ
ăč¨çŽă§ăăžă
ă ăăŽăăăŞé˘ć°
GăŽĺĺă揥ăŤç¤şăă
GGXăŽĺĺ¸ă誏ćăăžăă
ăăŽćŠč˝ă§ăŻ
Îąg-ćŁćšĺ˝˘ăŽčĄ¨é˘ç˛ăďźç˛ă*ç˛ăďźă
θvăŻăăăŻăćłçˇ
Nă¨ăăăĺ ´ĺăŤăŻĺ
Lă¨ăäťăŽĺ ´ĺăŤăŻčŚłć¸Źč
Vä¸ăŽăăŻăăŤă¨ăŽéăŽč§ĺşŚă§ă
ăΧ-ăăšă寞蹥ăŽăăźă ăćłçˇăŽĺ寞ĺ´ăăćĽăĺ ´ĺăŤăźăăčżăé˘ć°ăăă䝼ĺ¤ăŽĺ ´ĺăŻ1ăčżăăžăă HLSLăˇă§ăźăăźă§ăŻăăăăć°ĺźăăĺé¤ăăžăă ćŠă掾éă§ç˘şčŞăăăăŽăăăŞăăŻăťăŤăăžăŁăăçšçŻăăăžăăă ĺ
ăŽĺźă§ăŻćĽçˇăăăăžăăăăŹăłăăŞăłă°ăŤăŻč§ĺşŚăŽä˝ĺźŚă使ç¨ăăă¨äžżĺŠă§ăă ăšăŤăŠăźçŠăäťăăŚĺĺžăăžăă ăăăăŁăŚăĺźăĺ°ăĺ¤ćăăHLSLăłăźăă§č¨čż°ăăžăăă
float GGX_PartialGeometry(float cosThetaN, float alpha) { float cosTheta_sqr = saturate(cosThetaN*cosThetaN); float tan2 = ( 1 - cosTheta_sqr ) / cosTheta_sqr; float GP = 2 / ( 1 + sqrt( 1 + alpha * alpha * tan2 ) ); return GP; }
ăăăŚăĺ
ăăŻăăŤă¨čŚłć¸ŹăăŻăăŤăăăŽĺč¨
Gă揥ăŽăăăŤčć
Žăăžăă
float roug_sqr = roughness*roughness; float G = GGX_PartialGeometry(dot(N,V), roug_sqr) * GGX_PartialGeometry(dot(N,L), roug_sqr);
ăăźăŤăăŹăłăăŞăłă°ăăŚăăŽ
Găĺ°ĺşăăă¨ă揥ăŽĺłăĺžăăăžăă
ĺ
ćşăŻĺˇŚĺ´ăŤăăăžăă 塌ăăĺłă¸ăŽăăźăŤăŽç˛ăăŻ0.05ăă1.0ă§ăă
ăă§ă㯠ďźăăŻăťăŤăŻč¤ć°ă§ăăŁăŚăŻăŞăăžăăă ăăŽćĄäťśăĺ
ĽăăŚăă ăăďź
Out.Color = G; if (Out.Color.r > 1.000001) Out.Color.gb = 0.0;
ĺ°ăŞăă¨ă1ă¤ăŽĺşĺăăŻăťăŤăč¤ć°ăăĺ ´ĺă辤ăŤĺ¤ăăăžăă ăăšăŚăćŁăăčĄăăăă¨ăăăšăŚăŽăăŻăťăŤăç˝ăŽăžăžăŤăŞăăžăă
2.4 D.ĺĺ°ăă¤ăŻăăăĄăťăăăŽĺĺ¸
ăăŽ
ăă ă
ăăŻăăăźă㍠ă
ăŠăăăš ă
HăăŻăăŤăŞăŠăŽăăŠăĄăźăżăźăăăăžăă ăăăăŽăăŠăĄăźăżăźăăăćĺŽăăăăăŻăťăŤăŽăă¤ăŻăăă§ă¤ăšăŽăŠăŽďź
ă
HăŤä¸č´ăăćłçˇăćăŁăŚăăăă確çŤăăăă¨ăă§ăăžă
ă GGXă§ăŻăăăŽé˘ć°ăăăăć
ĺ˝ăăžăă
ăŻ
GăŽĺ ´ĺă¨ĺăé˘ć°ă§ă
ă ĺăççąă§ç ´ćŁăăžăă
Îąg-ćŁćšĺ˝˘ăŽčĄ¨é˘ç˛ă
θmăŻăăăŻăćłçˇ
Nă¨
HăăŻăăŤăŽéăŽč§ĺşŚă§ăă
ĺăłăç§ăŻăăă¤ăăŽĺ°ăăŞĺ¤ćăčĄăăćĽçˇăč§ĺşŚăŽăłăľă¤ăłăŤç˝Žăćăăžăăă çľćă¨ăăŚăăžăăŤăăŽăăăŞHLSLé˘ć°ăăăăžăă
float GGX_Distribution(float cosThetaNH, float alpha) { float alpha2 = alpha * alpha; float NH_sqr = saturate(cosThetaNH * cosThetaNH); float den = NH_sqr * alpha2 + (1.0 - NH_sqr); return alpha2 / ( PI * den * den ); }
ăăăŚă揥ăŽăăăŤĺźăłĺşăăžăďź
float D = GGX_Distribution(dot(N,H), roughness*roughness);
DăŽĺ¤ăçťé˘ăŤčĄ¨ç¤şăăă¨ă揥ăŽăăăŤăŞăăžăă
ç˛ăăŻă塌ăŽ0.05ăăĺłăŽ1.0ăžă§ĺ¤ĺăăžăă
ăă§ă㯠ďź1.0ăŽç˛ăă§ăŻăăăšăŚăŽĺ
ăĺçĺ
¨ä˝ăŤĺçăŤĺé
ăăăăă¨ăŤćł¨ćăăŚăă ăăă ăăăŻăćĺžăŽăăźăŤăĺşä˝ă§ăŞăăă°ăŞăăŞăăă¨ăćĺłăăžăă ăăŽč˛ăŻ153 153 153ďźä¸¸ăăŤăă+ -1ďźă§ăă
ĺż
čŚăăăăžăăsRGB
ăăçˇĺ˝˘çŠşéăŤĺ¤ćăăă¨ă0.318546778125092ăŤăŞăăžăă ăăŽć°ĺ¤ăŤPIăćăăă¨ăç´1ăŤăŞăăžăăăăăŻăĺçă§ăŽĺĺ°ăŤç¸ĺ˝ăăžăă PIăé¸ăśççą
ĺççŠĺcosďźxďźsinďźxďźăŻPIăä¸ăăăăă§ăă
2.5 F.ăăŹăăŤĺĺ°äżć°
2ă¤ăŽç°ăŞăăĄăăŁă˘ăŽĺ˘çăŤĺ˝ăăĺ
çˇăŻăĺĺ°ăăăłĺąćăăžăă
ăăŹăăŤĺźăŻăăăă辡ăăćłĺăćŁç˘şăŤčŞŹćăăŚăăžă
ăăăŚăŁăăŤčĄăŁăŚăăăăŽč¤ć°éăŽĺźăčŚăă¨ăăăăăéăăă¨ăăăăăžăă 嚸ăăŞăă¨ăŤăPBRăŹăłăăŞăłă°ă§ăťă¨ăăŠăŽĺ ´ĺăŤä˝żç¨ăăăéŠĺăŞčżäźźăăăăžăăăăăŻ
ăˇăĽăŞăăŻčżäźźă§ăă
ăăă§ă
R0ăŻĺąćçăŽćŻă¨ăăŚč¨çŽăăăžăă
ĺźăŽ
cosθăŻăĺ
ăŽĺ
Ľĺ°ă¨ćłçˇăŽéăŽč§ĺşŚăŽä˝ĺźŚă§ăă
cosθ= 1ăŽĺ ´ĺăĺźăŻ
R0ăŤç¸Žéăăăă¨ă
ăăăăžă ăăăăŻă
R0ăŽçŠççćĺłăŻăăăźă ă襨é˘ăŤĺç´ăŤč˝ăĄăĺ ´ĺăŽĺĺ°ĺ
ăŽéă§ăăăă¨ăćĺłăăžă ăăăhlslăłăźăăŤç´ćĽĺ
Ľăăžăăăďź
float3 FresnelSchlick(float3 F0, float cosTheta) { return F0 + (1.0 - F0) * pow(1.0 - saturate(cosTheta), 5.0); }
F0ăŻ
float3ĺ
ă§ă ă ăăăŻăĺĺ°äżć°ăăăŁăăŤăă¨ăŤç°ăŞăĺ ´ĺăăăăăă§ăă ç°ăŞăććăŻă波éˇăŤĺżăăŚç°ăŞăéăŽĺ
ăĺĺ°ăăžăă
ăžăăçŽăŤăŻRGBăłăźăłăăăăăăfloat3ă§ĺĺă§ăă
2.6ä¸çˇăŤćăăžă
ăăă ĺĺ°č˛ĺ
¨ä˝ăčżăé˘ć°ăçľăżçŤăŚăžăăăďź
float3 CookTorrance_GGX(float3 n, float3 l, float3 v, Material_pbr m) { n = normalize(n); v = normalize(v); l = normalize(l); float3 h = normalize(v+l);
ćĺăŤă襨é˘ăŤĺ°éăăŞăĺ
ăăăŁăŤăżăŞăłă°ăăžăă
if (NL <= 0.0) return 0.0;
襨示ăăăŚăăŞăé ĺă¨ĺć§ăŤďź
if (NV <= 0.0) return 0.0;
ăăžăăžăŞăšăŤăŠăźčŁ˝ĺăćşĺăăăăăăŽé˘ć°ăŤ
GGX_PartialGeometryďźďź ă
GGX_Distributionďźďź ă
FresnelSchlickďźďźăćäžăăžăă 揥ăŤăĺčż°ăŽĺźăŤĺžăŁăŚăăšăŚăäšçŽăăžăă
NLăŤĺĺ˛ăăŞăăŁăăă¨ăŤćł¨ćăăŚăă ăăă
float3 specK = G*D*F*0.25/NV;
ă¨ăŤăă
NLăćăăă¨
NLăć¸ăăăă§ăă ĺşĺă§ăç§ăŻăăŽĺçăĺžăžăăďź
塌ăăĺłăŤăç˛ăăŻ0.05ăă1.0ăŤĺ˘ĺ ăăžă
ä¸ăăä¸ă¸ăç°ăŞăăăŹăăŤäżć°
F0 ďź
1.ďź0.04ă0.04ă0.04ďź
2.ďź0.24ă0.24ă0.24ďź
3.ďź1.0ă0.86ă0.56ďź
2.7ăŠăłăăźăăŽă˘ăłăă¨ăłăăŠă¤ăă˘ăăŤ
ăăăăŁăŚă
FresnelSchlické˘ć°ăŻĺĺ°ĺ
ăŽéăčżăăžăă ćŽăăŽăŠă¤ăăŻ
1.0-FresnelSchlickďźďźăŤçăăăŞăăžăă
ăăă§ä˝čŤăăăăŚăă ăăăĺ¤ăăŽäşşă
ăŻăăăŽăŚăăăăăăăŹăăŤăĺźăăăăŽăç°ăŞăŁăŚčăăŚăăžăă ăă¨ăă°ăUE4ă§ăŻăFresnelSchlickăŻăăăďźVăHďźăăăŤăŚăłăăăăžăă ăŠăăă§2ă¤ăŽäżć°ďźăăăďźLăNďźă¨ăăăďźVăNďźăăďźăĺăăžăă ç§ăŤé˘ăăŚăŻăăăăďźLăNďźăăĺĺžăăćšăčŤççă§ăă äťăç§ăŻăăăăăćŁç˘şă§ăăŠăŽăăăŤçžĺŽăŤčżăĽăăăćŁç˘şăŤçĽăăŞăă¨č¨ăăă¨ăă§ăăžăă ăăŽĺéĄăç 犜ăăă¨ăăăăŽč¨äşăŽăăŽăŽăŁăăăčŁăăžăăăäťăŽă¨ăăăŻUE4ăŽăăăŤăă¤ăžăăăăďźVăHďźă使ç¨ăăžăă
ăăŽĺ
ăŻčĄ¨é˘ăééăăĺ¸ĺ/ĺćžĺ°/ĺĽăŽçšă§čĄ¨é˘ăé˘ăăăžă§ăăăŽĺ
é¨ăăŠăłăă ăŤăăžăăăžăă 襨é˘ä¸ăŽćŁäšąăŤăžă 役éżăä¸ăăŚăăŞăăăăăăŽĺ
ăŻĺçă§ĺ¸ĺăžăăŻĺćžĺ°ăăăă¨ăăăă䝎ĺŽăăžăă
ćĺăŽčżäźźă§ăŻăăăăŻç§ăăĄăŤéŠăăŚăăžăă ăăŽĺćŁăŻă
LambertăŠă¤ăăŁăłă°ă˘ăăŤăŤăăŁăŚč¨čż°ăăăžăă ăăăŻăćăĺç´ăŞĺź
LightColor * dotďźNăLďź/ PIă§č¨čż°ăăăžăă ă¤ăžăă誰ăăçĽăŁăŚăăăŽăŻă襨é˘ăŤĺ
Ľĺ°ăăĺ
ćăŽĺŻĺşŚă襨ă
ăăăďźNăLďźă¨ă
çŠĺĺçăŽĺ˝˘ă§äťĽĺăŤĺşäźăŁă
PIăŤăăé¤çŽă§ăă ĺ¸ĺ/ĺćžĺ°ăăăĺ
ăŽéăŻă
albedoă¨ĺźă°ăă
float3ăăŠăĄăźăżăźăŤăăŁăŚč¨čż°ăăăžăă ăăăŽăăšăŚăŻă
F0ăăŠăĄăźăżăźă¨é常ăŤäźźăŚăăžăă 袍é¨č
ăŻçšĺŽăŽćł˘éˇăŽăżăĺćžĺ°ăăžăă
LambertăŻç
§ćă˘ăăŤăŤă¤ăăŚä˝ăč¨ăăă¨ăăŞăăŽă§ă
CookTorrance_GGXăŤčż˝ĺ ăăŚăăžăďźăă ăăĺĽăŽé˘ć°ăŤĺ
ĽăăćšăćŁăăăăăăăžăăăăç§ăŻăăăžă§FăăŠăĄăźăżăźăĺźăĺşăăŽă
é˘ĺă§ăďźă
float3 specK = G*D*F*0.25/(NV+0.001); float3 diffK = saturate(1.0-F); return max(0.0, m.albedo*diffK*NL/PI + specK);
ăăăăä¸čŹçăŤăé˘ć°ăŻćŹĄăŽăăăŤăŞăăžăă float3 CookTorrance_GGX(float3 n, float3 l, float3 v, Material_pbr m) { n = normalize(n); v = normalize(v); l = normalize(l); float3 h = normalize(v+l);
䝼ä¸ăŻăćĄćŁăłăłăăźăăłăăčż˝ĺ ăăĺžăŤĺžăăăăăŽă§ăă
ä¸ăăä¸ăŤďźçˇĺ˝˘çŠşéă§ďź3ă¤ăŽććăŽă˘ăŤăăďź
1.ďź0.47ă0.78ă0.73ďź
2.ďź0.86ă0.176ă0ďź
3.ďź0.01ă0.01ă0.01ďź
ăăŚăăăă§2çŞçŽăŽĺ
ćşăĺłĺ´ăŤé
罎ăăĺ
ćşăŽĺźˇĺşŚă3ĺăŤĺ˘ăăăžăăă
çžĺ¨ăŽäžăŻăăŞăă¸ăăŞăŽ
ăăĄăăăăăŚăłăăźăă§ăăžăă ăžăăäžăŽĺéăăăăăźă¸ă§ăł
ăăăăŤăăăă¨ăćăĺşăăăžăă
3.0çťĺăăźăšăŽç
§ć
ăăă§ăçšĺ
ćşăçťĺăŽĺăăŻăťăŤăŽç
§ćăŤăŠăŽăăăŤĺŻä¸ăăăă調ăšăžăăă ăăĄăăăĺ
ćşăčˇé˘ăŽ2äšăăć¸čĄ°ăăŞăăă°ăŞăăŞăă¨ăăäşĺŽăăăăłĺ
ćşăçšăŽăăăŤăŞăĺžăŞăă¨ăăäşĺŽăçĄčŚăăžăăăăăăŻăăšăŚčć
Žăăăă¨ăă§ăăžăăăç
§ćă¸ăŽĺĽăŽă˘ăăăźăăčŚăŚăżăžăăăă äşĺŽăŻăĺ¨ĺ˛ăŽăăšăŚăŽăŞăă¸ă§ăŻăăĺ
ăĺĺ°/ĺćžĺ°ăăăăăŤăăŁăŚç°ĺ˘ăç
§ăăă¨ăăăă¨ă§ăă ăăŞăăŻéĄăŤčĄăăčŞĺăčŚăžăă éĄă§ĺĺ°ăăăĺ
ăŻăćčżăăŞăăŽä˝ăŤăăŁăŚĺćžĺ°/ĺĺ°ăăăăŽă§ăăăŞăăŻăăŽä¸ăŤčŞĺčŞčşŤăčŚăžăă ćťăăăŞăŞăă¸ă§ăŻăă§çžăăĺĺ°ăĺĺžăăĺ ´ĺăŻăăăŻăťăŤăă¨ăŤăăăŽăăŻăťăŤăĺ˛ăĺçăăăŽĺ
ăč¨çŽăăĺż
čŚăăăăžăă ă˛ăźă ă§ăŻăăăŽĺ˝çŠăăăŽĺ ´ĺăŤä˝żç¨ăăăžăă ç°ĺ˘ăŤĺăăăŚĺ¤§ăăŞăăŻăšăăŁăćşĺăăžăďźĺŽéăŤăŻ360庌ăŽĺçăžăăŻçŤä˝ĺ°ĺłďźă ăăŽăăăŞĺçăŽĺăăŻăťăŤăŻĺ°ăăŞă¨ăăăżă§ăă 揥ăŤăăä˝ăăăŽéćłăă使ç¨ăăŚăăăŽăăăŞăăŻăšăăŁăăăăŻăťăŤăé¸ćăăăă¤ăłăă˝ăźăšç¨ăŤä¸č¨ă§č¨čż°ăăăłăźăă使ç¨ăăŚćçťăăăŚăăăăŻăťăŤăç
§ăăăžăă ăăŽăăăăăŽććłăŻçťĺăăźăšăŽç
§ćă¨ĺźă°ăăžăďźă¤ăžăăç°ĺ˘ăŽăăŻăšăăŁăĺ
ćşă¨ăăŚä˝żç¨ăăăžăďźă
3.1ă˘ăłăăŤăŤă
ç°ĄĺăŞăăŽăăĺ§ăăžăăăă ă˘ăłăăŤăŤăćłă使ç¨ăăŚăŤăăŹăă¸ăč¨çŽăăžăă ćăăŚăă˘ăłăăŤăŤăćłăă¨ăăćăč¨čăăăăăŞăäşşăŽăăăŤăćă§čŞŹćăăăă¨ćăăžăă ĺăă¤ăłăăŽç
§ćăŻăăăăăŽăăšăŚăŽăă¤ăłăăŽĺ˝ąéżăĺăăžăă ăăăăŽĺĺăĺăé¤ăăă¨ăă§ăăžăă ăăăăŻăăŠă¤ăăŁăłă°ăŤăžăŁăăĺŻä¸ăăŞăăăăăľăźăă§ăšăŽĺ寞ĺ´ăŤăăăăŽă§ăă ăžă ĺçăăăăžăă ăăă§ăăăŽĺçăŤăŠăłăă ăŤĺçăŤĺĺ¸ăăĺ
çˇăĺşăăç
§ćăăăźăăŤçŠăżéăăŚăăăćžĺ°ăăăĺ
çˇăŽć°ă§é¤çŽăă2Ďăćăăăă¨ăă§ăăžăă 2Ďă§ăŻăăăăŻĺĺž1ăŽĺçăŽé ĺă§ăăć°ĺŚč
ăŻăă˘ăłăăŤăŤăćłă使ç¨ăăŚĺçĺ
¨ä˝ăŤç
§ćăçľąĺăăă¨č¨ăăžăă
ăăăŻĺŽéăŤăŠăŽăăăŤćŠč˝ăăžăăďź ĺ çŽăăŹăłăăŤăăă澎ĺĺ°ć°çšăăŻăšăăŁăŽăŹăłăăŞăłă°ă使ç¨ăăŚăăźăăŤčż˝ĺ ăăžăă ăăŽăăŻăšăăŁăŽă˘ăŤăăĄăăŁăłăăŤă§ăŻăăŹă¤ăŽć°ăč¨é˛ăărgbă§ăŻĺŽéăŽç
§ćăč¨é˛ăăžăă ăăăŤăăăcolor.rgbăcolor.aăŤĺĺ˛ăăćçľçăŞçťĺăĺĺžă§ăăžăă
ăă ăăĺ ćłăăŹăłăăŻăäťăŽăŞăă¸ă§ăŻăă§čŚăăăăŞăă¸ă§ăŻăăăćçťăăăăŤă¤ăăŚäťăŽăŞăă¸ă§ăŻăăéăăŚčźăĺ§ăăăă¨ăćĺłăăžăă ăăŽĺéĄăĺéżăăăăăŤă
桹庌ăăŞăăšććłă使ç¨ăăžăă ăăŽăăŻăăăŻăŽćŹčłŞăŻăćĺăŤăŞăă¸ă§ăŻăă
桹庌ăăăăĄăŤăŽăżćçťăă揥ăŤ
桹庌ăăšăăĺçăŤĺăćżă㌠ăăŞăă¸ă§ăŻăă
ăŤăŠăźăăăăĄăŤćçťăăăă¨ă§ăă
ăăăăŁăŚăçĺ
¨ä˝ăŤĺçăŤĺćŁăăĺ
çˇăŽćăçćăăžăă
function RandomRay(): TVec3; var theta, cosphi, sinphi: Single; begin theta := 2 * Pi * Random; cosphi := 1 - 2 * Random; sinphi := sqrt(1 - min(1.0, sqr(cosphi))); Result.x := sinphi * cos(theta); Result.y := sinphi * sin(theta); Result.z := cosphi; end; SetLength(Result, ACount); for i := 0 to ACount - 1 do Result[i] := Vec(RandomRay(), 1.0);
ăăŽăăŽăĺŽć°ă¨ăăŚăăŽăˇă§ăźăăźăŤé俥ăăžăă
float3 m_albedo; float3 m_f0; float m_roughness; static const float LightInt = 1.0; #define SamplesCount 1024 #define MaxSamplesCount 1024 float4 uLightDirections[MaxSamplesCount]; TextureCube uEnviroment; SamplerState uEnviromentSampler; PS_Output PS(VS_Output In) { PS_Output Out; Material_pbr m; m.albedo = m_albedo; m.f0 = m_f0; m.roughness = m_roughness; float3 MacroNormal = normalize(In.vNorm); float3 ViewDir = normalize(-In.vCoord); Out.Color.rgb = 0.0; [fastopt] for (uint i=0; i<SamplesCount; i++){
éĺ§ăăĺăăăźăŤăŽçťĺăĺžă
ăŤĺćăăăŽă確čŞăăžăă ăŹăłăăŞăłă°ăŤăŻ2ă¤ăŽçŤćšä˝ăăăă使ç¨ăăžăăă ăăŽăăăŤăăăŤďź
RenderMonkeyăŤäťĺąăăŚăăçŤćšä˝ăŽĺ°ĺłăĺăăžăăă Snow.ddsă¨ĺźă°ăăžăă ăăăŻ
LDRăăŻăšăăŁă§ăăăéĺąă§ăă ăăźăŤăŻçžăăç
§ăăăăăăăćąăăŚăăăăăŤčŚăăžăă
ăăăŚăăăŽăăăŤďź
ç§ăŻăăăă
HDRăăăźăăĺăăžăăďź
www.pauldebevec.com/Probesă¨ĺźă°ăăăľăłăăŠăłăˇăšăłăŽă°ăŹăźăšĺ¤§čĺ ă 彟弳ăŽăă¤ăăăăŻăŹăłă¸ăŻć大200,000ă§ă.1ă éăăŻä˝ă§ăăďź ăăăăŁăŚăăăŽăăăŞç
§ćăčŞĺă§ä˝ćăăĺ ´ĺăŻăăăăŤ
HDRăăŻăšăăŁă使ç¨ăăŚăă ăăă
ă¨ăăă§ăă¨ăăŤăŽăźäżĺăŽćłĺăćşăăăăŚăăăă¨ăčŚăŚăżăžăăăă ăăăčĄăăŤăŻăăˇă§ăźăăźăŽă˘ăŤăăă埡ĺśçăŤ1.0ăŤč¨ĺŽăăžăă
m.albedo = 1.0;
1.0ă§ăŠă¤ăăč¨ĺŽăăžăă
LightColor = 1.0;
çćłçăŤăŻăăăźăŤăŽĺăăŻăťăŤăŻ1ăŤçăăăŻăă§ăă ăăăăŁăŚăăŚăăăăčś
ăăăăŽăŻăăšăŚčľ¤ă§ăăźăŻăăăžăă 揥ăŽăăăŤăŞăăžăăă
ĺŽéăçžĺ¨ĺĺ¨ăă辤ăŻă¨ăŠăźă§ăă ĺćăĺ§ăăžăăăăăćçšă§ăăăźăăŽç˛žĺşŚăĺĺă§ăŻăŞăăĺćăćśăăžăă ĺłä¸ăŽăăźăŤăéăŤĺ¤ăăŁăŚăăăă¨ăŤćł¨ćăăŚăă ăăă ăăăŻăLambertă˘ăăŤă§ăŻčĄ¨é˘ç˛ăăčć
ŽăăăŚăăăăCook-Torensă˘ăăŤă§ăŻčĄ¨é˘ç˛ăăĺŽĺ
¨ăŤčć
ŽăăăŚăăŞăăăă§ăă ĺŽéă
F0ăŤčĄăéťč˛ăŻĺ¤ąăăăžăăă
F0ă芌ăăŚăăăšăŚăŽăăźăŤă1.0ăŤč¨ĺŽăăŚăżăžăăăă
ç˛ăă大ăăăăăĺłĺ´ăŽăăźăŤăŻăăŁă¨ćăăŞăăžăăă ăăăŻĺŽéăç§ăăĄă夹ăŁăĺ帰ĺĺ°ă§ăă ăŻăăŻăăŹăłăşăŻăăŽă¨ăăŤăŽăźă夹ăăžăă Oren-Nayară˘ăăŤăŻăăăŽă¨ăăŤăŽăźăé¨ĺçăŤĺžŠĺ
ă§ăăžăă ăăăăç§ăăĄăŻäťăŽă¨ăăĺťśćăăžăă é常ăŤăŠăăŞă˘ăăŤă§ăŻăĺ帰ĺĺ°ăŽă¨ăăŤăŽăźăŽć大70ďź
ă夹ăăăă¨ăăäşĺŽăŤćć
˘ăăĺż
čŚăăăăžăă
ă˝ăźăšăłăźăăŻ
ăăĄăă§ăă ĺéăăăă¤ăăŞăŤă¤ăăŚăŻć˘ăŤč¨ĺăăžăă
ăăăăăŤ
ăăăžă ă
3.2éčŚĺşŚăľăłăăŞăłă°
ăăĄăăăă˛ăźăăźăŻçťĺăŽĺ
ăĺćăăăŽăĺž
ăĄăžăăă ĺăăŻăťăŤăŽć°ĺăăăłć°ĺăŽĺ
çˇăăŤăŚăłăăăŞăăăăŤăä˝ăăčĄăĺż
čŚăăăăžăă ăăăŚăăăŞăăŻăŻăăă§ăă ă˘ăłăăŤăŤăăŤă¤ăăŚăŻăĺçĺ
ăŽĺä¸ăŞĺĺ¸ăčć
Žăăžăăă ăăăăľăłăăŞăłă°ćšćłă§ăă
ăăăăĺŽéăŽé¨ĺăŻăăłăŻč˛ă§ĺ˛ăžăăé¨ĺăŤăăŁăŚä¸ăăăăžăă 丝ăŤăŹăăăžăźăłăăăŽĺ
çˇăé¸ćă§ăăă°ăăŻăăăŤćŠă掾éă§č¨ąĺŽšĺŻč˝ăŞçťĺăĺžăăăžăă ă ăăăăă揲ăăďź
嚸ăăŞăă¨ăŤăăăŽăăăŽéčŚăŞăľăłăăŞăłă°ďźăžăăŻéčŚĺşŚăŤăăăľăłăăŞăłă°ďźă¨ĺźă°ăăć°ĺŚçăŞćšćłăăăăžăă ĺźăŽéčŚć§ăŻăăăŠăĄăźăżăź
DăŤăăŁăŚĺ°ĺ
Ľăăăžă
ă ăăă使ç¨ăăŚăăăă¤ăăŽ
PDFé˘ć°ďźç˘şçĺŻĺşŚé˘ć°ďźăă
CDF ďźĺĺ¸é˘ć°ďźăć§çŻă§ăăžăă
PDFăŽĺ ´ĺăćŁčŚĺĺ¸ăŤĺŻžăăăă¤ăŻăćŁčŚĺĺ¸ă使ç¨ăăžăăĺçăŽĺč¨ăŻĺä¸ć§ăä¸ăăăăăăăŽăăăŞçŠĺăć¸ăăă¨ăă§ăăžăă
袍çŠĺé˘ć°ăŻăăĄă-PDF
çé˘č§ĺ
¨ä˝ăŽçŠĺăĺăă¨ă揥ăŽ
CDFăĺžăăăžăă
ăăŽăšăăăăăšăăăăă¨ăŤĺŽčĄăăăĺ ´ĺăŻă
ăăĄăăă茧ăă ăă ă
ćăă§ăăŞă/桹ăčĄăăă¨ăă§ăăŞăäşşăŽăăăŤç§ăŻč¨ăăžăă ĺçăŤĺćŁăăă
Ξă䝣ĺ
Ľăă
CDFăăăăĺşĺă§ăŻ
PDFăĺć ăăĺĺ¸ăĺžăăăžăă ăăăŻç§ăăĄăŤă¨ăŁăŚä˝ăćĺłăăăŽă§ăăăăďź
1.ăăăŤăăă
Cook-Torrensé˘ć°ăĺ¤ć´ăăăăă¨ă
PDFé˘ć°ăŤĺĺ˛ăăĺż
čŚăăăăžăă
2.
PDFé˘ć°ăŻăăăŻăćŁčŚăŤĺŻžăăăă¤ăŻăćŁčŚăŽĺĺ¸ăĺć ăăŚăăžăă 䝼ĺăŻăă˘ăłăăŤăŤăăŽĺ ´ĺăăŠăłăă ăŞăăŻăăŤăĺĺžăăĺ
ćşă¸ăŽăăŻăăŤă¨ăăŚä˝żç¨ăăŚăăžăăă ăăă§ă
CDFă使ç¨ăăŚăăŠăłăă ăŞăăŻăăŤ
Hăé¸ćăăžă
ă 揥ăŤăăăŽăŠăłăă
HăŤé˘ăăŚčŚçˇăăŻăăŤăĺć ăăĺ
ăăŻăăŤăĺĺžăăžăă
3.
PDFăŻăăŠăźă ăŽăšăăźăšăŤčť˘éăăĺż
čŚăăăăžăďźăăŻăăŤ
NăŤć˛żăŁăĺĺ¸ăĺć ăăŚăăăăďźă 翝訳ăăăŤăŻă
PDFă
4 *ăăăďźHăVďźăŤĺĺ˛ăăĺż
čŚăăă
ăžăăăăăŤćˇąăćăä¸ăăăĺ ´ĺăŻă
ăăăŤă˘ăŻăťăšăăŚ
ăă ăă ă
ä˝ăć確ă§ăŻăŞăăăă§ăă ăăăăăšăŚăăłăźăă§ăă¤ă¸ă§ăšăăăŚăżăžăăăă
ăžăă
CDFăăăăŻăăŤ
Hăçćăăé˘ć°ăä˝ćăăžăă HLSLă§ăŻă揥ăŽăăăŤăŞăăžăă
float3 GGX_Sample(float2 E, float alpha) { float Phi = 2.0*PI*Ex; float cosThetha = saturate(sqrt( (1.0 - Ey) / (1.0 + alpha*alpha * Ey - Ey) )); float sinThetha = sqrt( 1.0 - cosThetha*cosThetha); return float3(sinThetha*cos(Phi), sinThetha*sin(Phi), cosThetha); }
ăăă§
Eă§ăŻă严ćšăŽçé˘č§ăŤĺŻžăăŚĺä¸ăŞĺĺ¸[0; 1ďźăä¸ăăžăă
ă˘ăŤă㥠ă§ăŻăććăŽ
ç˛ă㎠2äšăćăĄăžăă
ĺşĺă§ăŻăĺçă§
HăăŻăăŤăĺĺžăăžăă ăăăăăăŽĺçăŻčĄ¨é˘ăŤć˛żăŁăŚćšĺäťăăăăĺż
čŚăăăăžăă ăăăčĄăăăăŤăăľăźăă§ăšä¸ăŽćšĺăăăŞăăŻăšăčżăĺĽăŽé˘ć°ăä˝ćăăžăă
float3x3 GetSampleTransform(float3 Normal) { float3x3 w; float3 up = abs(Normal.y) < 0.999 ? float3(0,1,0) : float3(1,0,0); w[0] = normalize ( cross( up, Normal ) ); w[1] = cross( Normal, w[0] ); w[2] = Normal; return w; }
ăăŽčĄĺăŤăăăçćăăăăăšăŚăŽăăŻăăŤ
HăäšçŽăăăăăăŽćĽçˇçŠşéăăăŠăźă ăŽçŠşéăŤĺ¤ćăăžăă ăăŽĺçăŻăTBNăŽĺşç¤ăŤé常ăŤäźźăŚăăžăă
äťăăŻăăŻăťăăŹăłăĺĺ˛ăăăă¨ăŻćŽăŁăŚăăžăďź
G * D * F * 0.25 /ďźNVďźă
PDF㍠ă
PDF = D * NH /ďź4 * HVďź ă ăăăăŁăŚă俎ćŁăăăăŻăăŻăťăăŹăłăŻćŹĄăŽăăăŤăŞăăžă
G * F * HV /ďźNV * NHďźHLSLă§ăŻă揥ăŽăăăŤăŞăăžăă
float3 CookTorrance_GGX_sample(float3 n, float3 l, float3 v, Material_pbr m, out float3 FK) { pdf = 0.0; FK = 0.0; n = normalize(n); v = normalize(v); l = normalize(l); float3 h = normalize(v+l);
ăăŽé˘ć°ăăăŽLambertç
§ćăăćĄćŁé¨ĺăć¨ăŚă
FKăăŠăĄăźăżăźăčżăăă¨ăŤćł¨ćăăŚăă ăăă äşĺŽăŻă
Importance SamplingăäťăăŚćĄćŁăłăłăăźăăłăăăŤăŚăłăă§ăăŞăăă¨ă§ăă
PDFăŻăçŽăŽä¸ă§ĺ
ăĺĺ°ăăéĄç¨ă§ăă ăăăŚăăŠăłăăźăăŽĺĺ¸ăŻăăăŤäžĺăăŚăăžăăă ăŠăăăďź ăăźă...äťăŻćĄćŁé¨ĺăéťăŽăžăžăŤăăŚăéĄé˘ĺĺ°ăŤçŚçšăĺ˝ăŚăžăăăă
PS_Output PS(VS_Output In) { PS_Output Out; Material_pbr m; m.albedo = m_albedo; m.f0 = m_f0; m.roughness = m_roughness; float3 MacroNormal = normalize(In.vNorm); float3 ViewDir = normalize(-In.vCoord); float3x3 HTransform = GetSampleTransform(MacroNormal); Out.Color.rgb = 0.0; float3 specColor = 0.0; float3 FK_summ = 0.0; for (uint i=0; i<(uint)uSamplesCount; i++){ float3 H = GGX_Sample(uHammersleyPts[i].xy, m.roughness*m.roughness);
1024ĺăŽăľăłăăŤăč¨ĺŽăăŚďźă˘ăłăăŤăŤăăŽăăăŤčçŠăăăŤďźăçľćăčŚăŚăżăžăăăďź
ĺ¤ăăŽăľăłăăŤăăăăžăăăăă¤ăşăĺ¤ăăă¨ăĺ¤ćăăžăăă çšăŤĺ¤§ăăŞç˛ăă§ă
3.3 LODăŽé¸ć
ăăăŻă
LODăăźăăŽé常ăŤčŠłç´°ăŞăăăăăăľăłăăŤăĺĺžăăăăă§ăă ăăăŚăĺ塎ăŽĺ¤§ăăĺ
çˇăăăĺ°ăăŞăăăăĺăăŽăčŻăă§ăăăă ăăŽĺçăŻăăŽĺçă§ăă示ăăăŚăăžăă
NVidiaăŽ
ăăŽč¨äşăăă éăé ĺăŻĺšłĺĺ¤ă示ăăŚăă
ăăăŻăšăăŁăŽ
LODăăĺĺžăăă¨čŻăă§ăăăă ăăéčŚăŞĺ ´ĺăŻ
LODăĺ°ăăăăéčŚă§ăŞăĺ ´ĺăŻ
LODă大ăăăăăă¨ăăăăăžăă ĺ°ĺĺ
¨ä˝ăŽĺšłĺĺ¤ăĺĺžăăžăă ĺçĺ
¨ä˝ălodaă§čŚăă¨çćłçă§ăă 嚸ăăŞăă¨ăŤăNVidiaăŻć˘čŁ˝ăŽďźăăăŚç°ĄĺăŤč¨ăă¨ďźĺ
Źĺźăăă§ăŤćäžăăŚăăăžăăă
ăăŽĺźăŻéăăăćăăžăďź
塌ĺ´ăŽé¨ĺăŻăăăŻăšăăŁăŽăľă¤ăşă¨ăľăłăăŤăŽć°ăŤäžĺăăžăă ăăăŚăăăŻăăăšăŚăŽăľăłăăŤăŤă¤ăăŚăä¸ĺşŚăŤăŚăłăă§ăăăă¨ăćĺłăăžăă
ĺłĺ´ăŤăŻăç§ăăĄăŻćŠč˝ăăŚăăpĺ˝ç¤žäťĽĺ¤ăŽä˝ăăŽă§ăăăăžăăăPDFăăĄă¤ăŤăăăăłé˘ć°D彟ăăĺźăśăćŞăżăŽăăĺŽéăŤčŚłĺŻč
ăŤăľăłăăŤăŽč§äžĺć§ăăăăžăă䝼ä¸ăŽăăăŤD彟ăăŻăăăŤćăŁăŚăăĺźăŻćŹĄăŽă¨ăăă§ăăăăżăăŹčŚĺşă(, Dual-Paraboloid . , , b , . b=1.2 )
ăžăăNVidia ăŻlodsăŤăă¤ă˘ăšăăăăŚăčż˝ĺ ăăăă¨ăć¨ĺĽ¨ăăŚăăžăăhlslăłăźăă§ăŠăŽăăăŤčŚăăăčŚăŚăżăžăăăăćšç¨ĺźăŽĺˇŚĺ´ăŻćŹĄăŽă¨ăăă§ăă float ComputeLOD_AParam(){ float w, h; uRadiance.GetDimensions(w, h); return 0.5*log2(w*h/uSamplesCount); }
ăăă§ăŻĺłĺ´ăčć
ŽăăăăăŤĺˇŚĺ´ăăć¸çŽăăžăă float ComputeLOD(float AParam, float pdf, float3 l) { float du = 2.0*1.2*(abs(lz)+1.0); return max(0.0, AParam-0.5*log2(pdf*du*du)+1.0); }
ComputeLODă§pdfă¨lăŽĺ¤ă渥ăĺż
čŚăăăăă¨ăăăăăžăăălăŻĺ
ăľăłăăŤăŽăăŻăăŤăpdfăŻä¸ăčŚăă¨pdf = D * dotďźNăHďź/ďź4 * dotďźHăVďźďźă§ăăăăăăŁăŚăCookTorrance_GGX_sampleé˘ć°ăŤreturn pdfăăŠăĄăźăżăźăčż˝ĺ ăăžăăăă float3 CookTorrance_GGX_sample(float3 n, float3 l, float3 v, Material_pbr m, out float3 FK, out float pdf) { pdf = 0.0; FK = 0.0; n = normalize(n); v = normalize(v); l = normalize(l); float3 h = normalize(v+l);
ăăăŚăăľăłăăŤăŤăźăčŞä˝ăLODăč¨çŽăăăăăŤăŞăăžăăă float LOD_Aparam = ComputeLOD_AParam(); for (uint i=0; i<(uint)uSamplesCount; i++){ float3 H = GGX_Sample(uHammersleyPts[i].xy, m.roughness*m.roughness); H = mul(H, HTransform); float3 LightDir = reflect(-ViewDir, H); float3 specK; float pdf; float3 FK; specK = CookTorrance_GGX_sample(MacroNormal, LightDir, ViewDir, m, FK, pdf); FK_summ += FK; float LOD = ComputeLOD(LOD_Aparam, pdf, LightDir); float3 LightColor = uRadiance.SampleLevel(uRadianceSampler, mul(LightDir.xyz, (float3x3)V_InverseMatrix), LOD).rgb*LightInt; specColor += specK * LightColor; }
lodă使ç¨ăă1024ăľăłăăŤă§ĺžăăăăăŽăčŚăŚăżăžăăăăĺŽç§ăŤčŚăăžăă16ăŤä¸ăăăăăŚ...ăŻăăăăĄăăĺŽç§ă§ăŻăăăžăăăç˛ăăé常ăŤĺ¤§ăăăăźăŤă§ăŻĺ質ăä˝ä¸ăăŚăăăă¨ăăăăăžăăăăăă§ăĺĺă¨ăăŚăăŽĺ質ăŻč¨ąĺŽšă§ăăă¨čăăŚăăžăăĺĺ¸ăŤĺşăĽăăŚăăŻăšăăŁăŽmipăä˝ćăăă°ăĺ質ăăăăŤĺä¸ăăăăă¨ăă§ăăžăăăăŽăă¨ăŻăEpicăŽă§ăăŹăźăłăăźăˇă§ăłă§čŞăżĺăăă¨ăă§ăăăăă§ďźăăťăŻăˇă§ăłăăăăăăăŁăŤăżĺŚçç°ĺ˘ăăăăĺç
§ăăŚăă ăăďźăăăăžă§ăŽéăăăŽč¨äşăŽä¸é¨ă¨ăăŚăĺ¤ĺ
¸çăŞăăŠăăăĺăăăšăŤă¤ăăŚčŞŹćăăăă¨ăććĄăăžăă3.4 Hammersleyăă¤ăłăăťăă
ăŠăłăă ăŞĺ
çˇăčŚăă¨ăćŹ éĽăŻćăăă§ăăăăăăŻăŠăłăă ă§ăăăăăŚăç§ăăĄăŻăă§ăŤlodăăčŞăăă¨ăĺŚăă§ăăăă§ăăă ă大ăăŞćŁćšĺ˝˘ăĺ
çˇă§ăăŁăăăŁăăăă¨čăăŚăăžăăăăăčĄăăŤăŻăĺ
çˇăăăšăăŹăźăăăĺż
čŚăăăăžăăăăľăłăăŞăłă°ăŽéčŚć§ăčć
ŽăăŚăă ăăăăŞăăŞă
CDFăŻĺä¸ăŞĺĺ¸ăĺăăăăĺşé[0; 1ďźă§ăă¤ăłăăĺçăŤĺĺ¸ăăăă ăă§ĺĺă§ăăăĺä¸ăŞĺĺ¸ăŻ2揥ĺ
ă§ăŞăăă°ăŞăăžăăăăăăăŁăŚăăŽăŁăăĺ
ăŽăă¤ăłăăĺçăŤé
罎ăăă ăă§ăŞăăăă¤ăłăéăŽăăŤăŤă座ć¨ăŽčˇé˘ăă§ăăă ă大ăăăăĺż
čŚăăăăžăăHammersleyăă¤ăłăăťăăăŻăăăŽĺ˝šĺ˛ăŤéŠăăŚăăžăăăăă§ăăăŽĺ¤ăăŽăă¤ăłăăŤă¤ăăŚăăĺ°ăčŞăăă¨ăă§ăăžăăĺĺ¸ăŽĺçăŽăżă襨示ăăžăăĺĽăŽăă¤ăłăăçćăăé˘ć°ăćäžăăžăă function HammersleyPoint(const I, N: Integer): TVec2; function radicalInverse_VdC(bits: Cardinal): Single; begin bits := (bits shl 16) or (bits shr 16); bits := ((bits and $55555555) shl 1) or ((bits and $AAAAAAAA) shr 1); bits := ((bits and $33333333) shl 2) or ((bits and $CCCCCCCC) shr 2); bits := ((bits and $0F0F0F0F) shl 4) or ((bits and $F0F0F0F0) shr 4); bits := ((bits and $00FF00FF) shl 8) or ((bits and $FF00FF00) shr 8); Result := bits * 2.3283064365386963e-10; end; begin Result.x := I/N; Result.y := radicalInverse_VdC(I); end;
ăăŽăăăăŽăťăăă§ăăźăŤăŻăŠăŽăăăŤčŚăăžăăďźĺŽéăç§ăŻĺ˝é ăăéčŚĺşŚăľăłăăŞăłă°ăŽä¸č¨ăŽăăšăŚăŽçťĺăŻăăăăăŽăă¤ăłăăŽăťăăă§çćăăăžăăăăŠăłăă ăťăăă§ăŻăĺçăĺ°ăćŞăčŚăăžăďźč¨čă俥ăăžăăďźďź3.5ćžĺ°ç
§ĺşŚăăă
ćĄćŁč˛ăŞăă§ćŽăăăćšćłăčŚăăŚăăžăăďźéčŚĺşŚăľăłăăŞăłă°ă§ăŻććŠĺŽśăŤă¨ăŁăŚćă䞥ĺ¤ăŽăăĺ
çˇăé¸ćăăăăăăéčŚĺşŚăľăłăăŞăłă°ă§ăŻćĄćŁč˛ăăľăłăăŞăłă°ă§ăăžăăăćĄćŁăŽăăăŤăćă䞥ĺ¤ăŽăăăăŽăŻăăŻăćłçˇăŽčĄ¨é˘ăŽçĺăăăŤăăăžăă嚸ăăŞăă¨ăŤăLambertăŽćĄćŁćĺăŻčŚłć¸Źč
ăăĺŽĺ
¨ăŤçŹçŤăăŚăăžăăăăăăŁăŚăçŤćšä˝ăăăă§ç
§ćăč¨çŽă§ăăžăăăžăăč§ĺşŚăĺ¤ć´ăăă¨ç
§ćăŤăăăăŤĺ˝ąéżăăăăăč¨çŽăăăăăăăŽč§Łĺ庌ăŻé常ăŤä˝ăăŞăĺŻč˝ć§ăăăăžăďźăă¨ăă°ă16 x 16ăăŻăťăŤ/čžşďźăäťĺăŻĺš¸éă§ăăăćžĺ°ç
§ĺşŚăăăăŽć§çŻăćąăăłăźăăŻä˝ćăăžăăăăăăă°ăŠă ă使ç¨ăăžăCubeMapGenăcubmapďźLoad Cubemapďź.ddsďźďźăéăăIrradiance cubemapăă§ăăŻăăăŻăšăč¨ĺŽăăOutput Cube Size 16ăé¸ćăăŚăçľćăŽăăĽăźăăăŻăăăăäżĺăăžăďźHDRăăŻăšăăŁăŽĺ ´ĺăçŽçăŽăăŻăšăăŁĺşĺ形ĺźăč¨ĺŽăăăă¨ăĺżăăŞăă§ăă ăăďźăăăŚăIrradianceăăăăč¨çŽăăăŽă§ăăľăłăăŞăłă°ĺžăŤăăŽăăăăă1ă¤ăŽăľăłăăŤăčż˝ĺ ăăă ăă§ăăHLSLăłăźăăŻćŹĄăŽăăăŤăŞăăžăă Out.Color.rgb = 0.0; float3 specColor = 0.0; float3 FK_summ = 0.0; for (uint i=0; i<(uint)uSamplesCount; i++){ float3 H = GGX_Sample(uHammersleyPts[i].xy, m.roughness*m.roughness); H = mul(H, HTransform); float3 LightDir = reflect(-ViewDir, H); float3 specK; float pdf; float3 FK; specK = CookTorrance_GGX_sample(MacroNormal, LightDir, ViewDir, m, FK, pdf); FK_summ += FK; float LOD = ComputeLOD(LOD_Aparam, pdf, LightDir); float3 LightColor = uRadiance.SampleLevel(uRadianceSampler, mul(LightDir.xyz, (float3x3)V_InverseMatrix), LOD).rgb*LightInt; specColor += specK * LightColor; } specColor /= uSamplesCount; FK_summ /= uSamplesCount; float3 LightColor = uIrradiance.Sample(uIrradianceSampler, mul(MacroNormal, (float3x3)V_InverseMatrix)).rgb; Out.Color.rgb = m.albedo*saturate(1.0-FK_summ)*LightColor + specColor;
ĺşĺăŤăŻă16ăľăłăăŤăŽăăŽçťĺăăăăžăăćĄćŁĺ
ăŤăăăďźNăLďźăćăăŞăăă¨ăŤćł¨ćăăŚăă ăăăăăăŻä¸ç¨ŽăŽčŤçă§ăăçľĺąăăăŽăŠă¤ăăŁăłă°ăč¨çŽăăŚăăăăcubmapăŤçźăäťăăžăăăăăŽĺ ´ĺăNă¨LăŻä¸čŹăŤĺăăăŻăăŤă§ăăç§ăăĄăçă¨ăă§ä˝ăćăŁăŚăăăčŚăŚăżăžăăăăďźăă¤ăăŽăăăŤăçŤćšä˝ăŤăźăăăăŽĺ
ăĺä¸ăŤč¨ĺŽăăăăăŞă˘ăŤăŽă˘ăŤăăăĺä¸ăŤč¨ĺŽăă1ăčś
ăăé ĺă辤ă§ĺźˇčŞżčĄ¨ç¤şăăžăăăăăă1024ĺăŽăľăłăăŤăŤă¤ăăŚăăăĺĺžăăžăăăăăŚăăăă§ăŻ16 ĺăŽăľăłăăŤăŤă¤ăăŚă§ăăă茧ăŽă¨ăăăéĺ°ăŞă¨ăăŤăŽăźăŽćăăăŞăćžĺşăăăăăžăăăăăăăŻăăăă§ăăăăăŻăćĄćŁă¨ăăŤăŽăźăăĺ
éăćŁç˘şăŤč¨çŽă§ăăŞăăăă§ăăçľĺąăăăŹăăŤäżć°ăŻéĄé˘ĺĺ°ĺ
ăŽçšĺŽăŽăľăłăăŤăŤĺŻžăăŚăŽăżčć
Žăăăćžĺ°ăăăă§č¨çŽăăăăăšăŚăŽăľăłăăŤăŤä˝żç¨ăăăžăăć˛ăăăăŞăç§ăŻăăăăŠăăăăăăăăžăăăă¤ăłăżăźăăăăŻç§ăŤä˝ăäźăăăă¨ăă§ăăžăăă§ăăăăăăăŁăŚăç§ăŻäťăŽă¨ăăăăăăŤĺćăăăă¨ăććĄăăžăăăăăă§ăăăŻăăéĺ°ă¨ăăŤăŽăźăŽćĺşăŻéčŚă§ăŻăăăžăăă4ććăŤă¤ăăŚăăĺ°ăă
ăăźăŤăăăăăŞăăăfloat3ăŽ2ă¤ăŽăŤăŠăźăŞăăˇă§ăłăăăăă¨ăŤć°ăĽăăăŻăă§ăăăăăŻă˘ăŤăăă¨f0ă§ăăăŠăĄăăçŠççăŞćĺłăăăăžăăăă˛ăźă ă§ăŻăĺĺă¨ăăŚăććăŻéĺąă¨ééĺąăŤĺăăăăžăăĺŽéăééĺąăŻĺ¸¸ăŤă°ăŹăźăšăąăźăŤçŻĺ˛ăŽĺ
ăĺĺ°ăăžăăăĺćăŤč˛ăŽĺ
ăĺćžĺ°ăăžăăĺ寞ăŤăéĺąăŻč˛ăŽă¤ăăĺ
ăĺĺ°ăăžăăăĺćăŤćŽăăĺ¸ĺăăžăăă¤ăžăăéĺąăŽĺ ´ĺďźalbedo = {0ă0ă0}f0 = {RăGăB}čŞéťä˝ăŽĺ ´ĺďźalbedo = {RăGăB}f0 = {XăXăX}ăăăŚ...çšĺŽăŽäżć°[0,1]ăĺ°ĺ
Ľă§ăăăă¨ăăăăăžăăăăăŤăăă襨é˘ăăŠăă ăéĺąă§ăăăă示ăăĺç´ăŤçˇĺ˝˘čŁéăŤăăŁăŚććăčć
ŽăăžăăăăăŻĺŽéăŤăŻĺ¤ăăŽă˘ăźăăŁăšăăčĄăăžăăă㎠3Dă˘ăăŤăăăŚăłăăźăăăžăăăĺŁăŽăăŻăšăăŁăŽäžă揥ăŤç¤şăăžăăăŤăŠăźăăŻăšăăŁďźç˛ăăŽăăŻăšăăŁďźăăăŚćĺžăŤăéĺąć§ăŽăăŻăšăăŁďźä¸č¨ă§č¨ĺăăăăŽďźďźă¤ăłăżăźăăăä¸ăŽç´ ćăŤă¤ăăŚăăĺ°ăčŞăăă¨ăă§ăăžăăäžăă°ăăăŤăăăžăăžăŞă¨ăłă¸ăłăăšăżă¸ăŞăăăžăăžăŞćšćłă§ăăŠăĄăźăżăźăăăăŻă§ăăžăăăĺĺă¨ăăŚăăăšăŚăč˛ăç˛ăăéĺąć§ăä¸ĺżăŤĺąéăăžăăăăăŚćĺžăŤăă˘ăăŤĺ
¨ä˝ă§ăŠăŽăăăŤčŚăăăďźĺˇŚĺ´ăŤăŻăăăźăŤă§ăăšăăăăŽă¨ĺă大čĺ ăăăăžăăĺłĺ´ă§ăŻăç§ăăĄăŽArtoriasăčŞçśăŤăŞăăžăăďźăăăăăŽç°ĺ˘ăăăăŻwww.pauldebevec.com/ProbesăŻCampusă¨ĺźă°ăăžăďźăArtoriasă˘ăăŤăŽă˝ăźăšăłăźăăŻăç§ăŽăăŹăźă ăŻăźăŻăŽăă˘ă§ăăăăăăŤăăăžăăăžăăăăŞăăŽăăăŤăăźă¸ă§ăłăăžă¨ăăŚăăăăŤă˘ăăăăźăăăžăăă5çľčŤ
, . :
1.
2.
3. , -
4.
5.
, ⌠â . , . - .
- , PBR. .