Šviesos laužimas ir atspindėjimas

Iš Wikibooks.

Kaip matėte iš renderinimo šviesos laužimo šeiderio yra regionai, kur nėvyksta šviesos laužimas ir rezultatas yra pilka spalva. Priežastis šito rezultato yra yra ne error'as ar panašus glitch'as, bet naturalus fenomenas kai deramasi su refrakcija.

Jeigu jūs pažiūrėsite į konteinerį vandens, tokį kaip akvariumas, veidu į vandenį, jūs matysite per vandenį be jokių sunkumų. Tačiau jei jūs pažiūrėsite į tą patį konteinerį iš seklaus kampo (iš šono), jis nebus permotomas daugiau ir pradės darytis labiau kaip veidrodis.

Šitas fenomenas vyksta, todėl kad šviesos laužimas nustos vykti peržengus tam tikrą kampą, vadinama kritiniu kampu (critical angle). Šituo kampu, refrakcijos kampas yra 90 laipsnių ir bet kokie krintantys spinduliai vyršyje šitą kampą demonstruoja fenomeną vadinama visiška vidinė reflekcija (total internal reflection (or TIR)), kas iš esmės reiškia, kad paviršius tada bus kaip veidrodis vietoj to, kad butų permatomas.

Mes žinome, kad refrakcija sustos vykti kai yra kritinis kampas arba kitais žodžiais, kai refrakcijos kampas yra lygus 90 laipsnių. Kadangi jūs jau turite sinusą ir kosinusą išeinančio kampo, jūs galite panaudoti šitą reikšmę, kad nustatyti teisingą santykį atspindėtos ir refraktuotos aplinkos. Kadangi sinusas šito kampo yra jau nuo 0 iki 1 intervale, jis yra geras kanditas panaudoti kaip blending faktorių.

Kai jūs nustatėte blendinimo faktorius abiems atpindėjimui ir refrakcijai, kuri irgi bus paduota į pixelių shaderį per vieną iš TEXCOORD kintamųjų, kombinuoti du efektus yra paprasčiausiai dalykas sudejimo dviejų kodo pagrindų kartu yra perduodant blendinimo faktorius, atspindėjimo vektorius, ir refrakcijos vektorius pixelių shaderiui. Kai pakeitimai padaryti, jūs turėtumėte baigti su sekančiu vertex shaderių kodu:

float4x4 view_proj_matrix;
float4 view_position;
struct VS_OUTPUT
{
float4 Pos: POSITION;
float2 TexCoord: TEXCOORD0;
float3 Refract: TEXCOORD1;
float3 Reflect: TEXCOORD2;
float2 Factors: TEXCOORD3;
};
VS_OUTPUT vs_main(float4 inPos: POSITION, float3 inNormal: NORMAL,
float2 inTxr: TEXCOORD0)
{
VS_OUTPUT Out;
// Compute the projected position and send out the texture coordinates
Out.Pos = mul(view_proj_matrix, inPos);
Out.TexCoord = inTxr;
float3 viewVec = normalize(view_position - inPos);
// Compute reflection
Out.Reflect = reflect(-viewVec,inNormal);
// Compute the reflection vector using Snell’s Law
// the refract HLSL function does not always work properly
// n_i * sin(theta_i) = n_r * sin(theta_r)
// sin(theta_i)
float cosine = dot(viewVec, inNormal);
float sine = sqrt(1 - cosine * cosine);
// sin(theta_r)
float sine2 = saturate(1.14 * sine);
float cosine2 = sqrt(1 - sine2 * sine2);
// Determine the refraction vector be using the normal and tangent
// vectors as basis to determine the refraction direction
float3 x = -inNormal;
float3 y = normalize(cross(cross(viewVec, inNormal), inNormal));
Out.Refract = x * cosine2 + y * sine2;
// Determine proper reflection and refraction factors through
// a Fresnel approximation. (x = reflect, y = refract)
Out.Factors.x = sine2;
Out.Factors.y = (1 - sine2);
return Out;
}

Pixelių shaderis šitam kombinuotam atspindėjimo/refrakcijos shaderiui reikia paimti vidun trys reikšmes. Pirmos dvi yra lookup vektoriai for the environment cubemap lookup for the reflection and refraction, ir paskutinė reikšmė yra blendinimo factoriai naudoti. Kai jūs looked up abi environment reikšmes, sukombinuoti jas yra paprastas procesas.

Laikykit mintyse, kad jeigu jūs naudojate textura jūsų objektui, the refraction environment map reikšmė refrakcijai turi būti moduliuota su objekto teksturos reikšme nes textura turi efektą paspalvinti šviesos spindulius kai jie eina per objektą. Sekantis yra pavyzdis pixelių shaderių kodas vaizduojantis kaip refrakcija ir atspindėjimas gali būti sukombinuoti:

sampler Wood;
sampler EnvMap;
float4 ps_main(float2 inTxr: TEXCOORD0,float3 inRefract: TEXCOORD1,
float3 inReflect: TEXCOORD2,float2 inFct: TEXCOORD3) : COLOR
{
// Output texture color with reflection map
// Note the addition of 0.4 to the reflection/refraction
// results to ensure a certain amount of ambient lighting
return inFct.x * texCUBE(EnvMap,inReflect) +
(inFct.y * texCUBE(EnvMap,inRefract) + 0.4)
* tex2D(Wood,inTxr);
}


High_Level_Shading_Language