float4x4 WorldViewProj;
float3 v3LightDir; // Light direction
float3 v3CameraPos; // Camera's current position
float3 v3InvWavelength; // 1 / pow(wavelength, 4) for RGB channels
float fCameraHeight;
float fCameraHeight2;
float fInnerRadius;
float fInnerRadius2;
float fOuterRadius;
float fOuterRadius2;
// Scattering parameters
float KrESun; // Kr * ESun
float KmESun; // Km * ESun
float Kr4PI; // Kr * 4 * PI
float Km4PI; // Km * 4 * PI
// Phase function
float g;
float g2;
float fScale; // 1 / (outerRadius - innerRadius) = 4 here
float fScaleDepth; // Where the average atmosphere density is found
float fScaleOverScaleDepth; // scale / scaleDepth
float fSkydomeRadius; // Skydome radius (allows us to normalize skydome distances etc)
int numSamples;
float samples;
// Application to vertex structure
struct a2v
{
float4 Position : POSITION0;
};
// Vertex to pixel shader structure
struct v2p
{
float4 Position : POSITION0;
float4 RayleighColor : COLOR0;
float4 MieColor : COLOR1;
float3 Direction : TEXCOORD0;
};
float scale(float cos)
{
float x = 1.0 - cos;
return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));
}
void RenderSkyVS(in a2v IN, out v2p OUT)
{
// Transform to clipspace
OUT.Position = mul(IN.Position, WorldViewProj);
// Get the ray from the camera to the vertex, and it's length (far point)
float3 v3Pos = IN.Position / fSkydomeRadius + fInnerRadius;
float3 v3Ray = v3Pos - v3CameraPos;
float fFar = length(v3Ray);
v3Ray /= fFar;
// Calculate the ray's starting position, then calculate its scattering offset
float3 v3Start = v3CameraPos;
float fHeight = length(v3Start);
float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fCameraHeight));
float fStartAngle = dot(v3Ray, v3Start) / fHeight;
float fStartOffset = fDepth * scale(fStartAngle);
// Init loop variables
float fSampleLength = fFar / samples;
float fScaledLength = fSampleLength * fScale;
float3 v3SampleRay = v3Ray * fSampleLength;
float3 v3SamplePoint = v3Start + v3SampleRay * 0.5f;
// Loop the ray
float3 color;
for (int i = 0; i < numSamples; i++)
{
float fHeight = length(v3SamplePoint);
float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius-fHeight));
float fLightAngle = dot(v3LightDir, v3SamplePoint) / fHeight;
float fCameraAngle = dot(v3Ray, v3SamplePoint) / fHeight;
float fScatter = (fStartOffset + fDepth*(scale(fLightAngle) - scale(fCameraAngle)));
float3 v3Attenuate = exp(-fScatter * (v3InvWavelength * Kr4PI + Km4PI));
// Accumulate color
v3Attenuate *= (fDepth * fScaledLength);
color += v3Attenuate;
// Next sample point
v3SamplePoint += v3SampleRay;
}
// Finally, scale the Mie and Rayleigh colors
OUT.RayleighColor.xyz = color * (v3InvWavelength * KrESun);
OUT.RayleighColor.w = 1.0f;
OUT.MieColor.xyz = color * KmESun;
OUT.MieColor.w = 1.0f;
OUT.Direction = v3CameraPos - v3Pos;
}
float4 RenderSkyPS(in v2p IN) : COLOR0
{
float cos = dot(v3LightDir, IN.Direction) / length(IN.Direction);
//float rayleighPhase = 0.75f * (1.0f + cos*cos);
float miePhase = 1.5f * ((1.0f - g2) / (2.0f + g2)) *
(1.0f + cos*cos) / pow(1.0f + g2 - 2.0f * g * cos, 1.5f);
//return rayleighPhase * IN.RayleighColor + miePhase * IN.MieColor;
return IN.RayleighColor + miePhase * IN.MieColor;
}
technique RenderSky
{
pass p0
{
VertexShader = compile vs_2_0 RenderSkyVS();
PixelShader = compile ps_2_0 RenderSkyPS();
ZWriteEnable = 0;
}
}
D3DXVECTOR4 vecCamera = *objRenderer->GetCameraPos();
D3DXMATRIX matWVP;
D3DXVECTOR3 vecPos;
D3DXQUATERNION quatRotate;
D3DXVECTOR3 vecScale;
D3DXMatrixDecompose(&vecScale, &quatRotate, &vecPos, objRenderer->GetViewMatrix());
D3DXMatrixRotationQuaternion(&matWVP, &quatRotate);
D3DXMatrixMultiply(&matWVP, &matWVP, objRenderer->GetSkydomeProjectionMatrix());
D3DXVECTOR4 vSunDir = m_pAtmosphere->GetDirection();
vSunDir.w = 1.0;
float fMieMult = m_pAtmosphere->GetBetaMieMultiplier();
float fRayMult = m_pAtmosphere->GetBetaRayleighMultiplier();
float g = m_pAtmosphere->GetHeyseyG();
D3DXVECTOR4 vSunColourIntensity = m_pAtmosphere->GetColorAndIntensity();
D3DXVECTOR4 vInvWavelength;
float m_fWavelength[3];
float m_fWavelength4[3];
m_fWavelength[0] = 0.650f;//650e-9f; // 650 nm for red
m_fWavelength[1] = 0.570f;//570e-9f; // 570 nm for green
m_fWavelength[2] = 0.475f;//475e-9f; // 475 nm for blue
m_fWavelength4[0] = powf(m_fWavelength[0], 4.0f);
m_fWavelength4[1] = powf(m_fWavelength[1], 4.0f);
m_fWavelength4[2] = powf(m_fWavelength[2], 4.0f);
vInvWavelength.x = 1.0f / m_fWavelength4[0];
vInvWavelength.y = 1.0f / m_fWavelength4[1];
vInvWavelength.z = 1.0f / m_fWavelength4[2];
float fInnerRadius = 10.0f;
float fOuterRadius = 10.25f;
float fScale = 1 / (fOuterRadius - fInnerRadius);
float fScaleDepth = 0.0125f;//0.25f;//(fOuterRadius - fInnerRadius) / 2.0f;
float fScaleOverScaleDepth = 16.0f;//fScale / fScaleDepth;
vecCamera /= fSkydomeRadius;
// Gets sun when commented but loses everything else
vecCamera.y += fInnerRadius;
if (vecCamera.y <= fInnerRadius)
vecCamera.y = fInnerRadius + 1.0e-6f;
vecCamera.x = 0;
vecCamera.z = 0;
float fCameraHeight = vecCamera.y;
float fkr4PI = fRayMult * 4.0f * PI;
float fkm4PI = fMieMult * 4.0f * PI;
float fKrESun = fRayMult * vSunColourIntensity.w;
float fKmESun = fMieMult * vSunColourIntensity.w;
pSkydomeScatterFX->SetMatrix(m_pWorldViewProj, &matWVP);
pSkydomeScatterFX->SetVector(m_pv3LightDir, &vSunDir);
pSkydomeScatterFX->SetVector(m_pv3CameraPos, &vecCamera);
pSkydomeScatterFX->SetVector(m_pv3InvWavelength, &vInvWavelength);
pSkydomeScatterFX->SetFloat(m_pfCameraHeight,fCameraHeight);
pSkydomeScatterFX->SetFloat(m_pfCameraHeight2,fCameraHeight*fCameraHeight);
pSkydomeScatterFX->SetFloat(m_pfInnerRadius, fInnerRadius);
pSkydomeScatterFX->SetFloat(m_pfInnerRadius2, fInnerRadius * fInnerRadius);
pSkydomeScatterFX->SetFloat(m_pfOuterRadius, fOuterRadius);
pSkydomeScatterFX->SetFloat(m_pfOuterRadius2, fOuterRadius * fOuterRadius);
pSkydomeScatterFX->SetFloat(m_pKrESun,fKrESun);
pSkydomeScatterFX->SetFloat(m_pKmESun,fKmESun);
pSkydomeScatterFX->SetFloat(m_pKr4PI, fkr4PI);
pSkydomeScatterFX->SetFloat(m_pKm4PI, fkm4PI);
pSkydomeScatterFX->SetFloat(m_pg, g);
pSkydomeScatterFX->SetFloat(m_pg2, g*g);
pSkydomeScatterFX->SetFloat(m_pfScale, fScale);
pSkydomeScatterFX->SetFloat(m_pScaleDepth, fScaleDepth);
pSkydomeScatterFX->SetFloat(m_pScaleOverScaleDepth, fScaleOverScaleDepth);
pSkydomeScatterFX->SetFloat(m_pfSkydomeRadius, fSkydomeRadius);
pSkydomeScatterFX->SetInt(m_pnumSamples, iNumSamples);
pSkydomeScatterFX->SetInt(m_psamples, iNumSamples);






