Jump to content
  • Advertisement
Sign in to follow this  
cppcdr

Atmospheric scattering problem

This topic is 3704 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I am currently working on the sky rendering for my engine based on the paper here: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter16.html I have also looked at: href="http://www.gamedev.net/community/forums/topic.asp?topic_id=461747&PageSize=25&WhichPage=2 I have gotten the sky to look ok, but i'm missing the sun. Mayby i'm mistaken, but shouldn't the shader automatically generate the sun? Here is my shader code:
matrix worldViewProj;
float3 cameraPos;

float time;

float dispX;
float dispZ;

Texture2D colorTexture;
Texture2D starsTexture;

static float3 v3LightDir = {0, 0, 0};		// Light direction
static float3 v3CameraPos = {0, 10.00, 0};		// Camera's current position
static float3 v3Wavelength =  {0.650f, 0.570f, 0.475f};
static float3 v3InvWavelength = 1 / pow(v3Wavelength, 4);	// 1 / pow(wavelength, 4) for RGB channels

static float fCameraHeight = length(v3CameraPos);
static float fCameraHeight2 = fCameraHeight * fCameraHeight;
static float fInnerRadius = 10.0;
static float fInnerRadius2 = fInnerRadius * fInnerRadius;
static float fOuterRadius = 10.25;
static float fOuterRadius2 = fOuterRadius * fOuterRadius;

// Scattering parameters
static float ESun = 20.00;
static float KrESun = 0.0025f * ESun;			// Kr * ESun
static float KmESun = 0.0010f * ESun;			// Km * ESun
static float Kr4PI = 0.0025f * 4 * 3.14159265f;
static float Km4PI = 0.0010f * 4 * 3.14159265f;

// Phase function
static float g = -0.991;
static float g2 = g * g;

static float fScale = 4;			// 1 / (outerRadius - innerRadius) = 4 here
static float fScaleDepth = 0.25;		// Where the average atmosphere density is found
static float fScaleOverScaleDepth = fScale / fScaleDepth;	// scale / scaleDepth
static float fSkydomeRadius = 512;	// Skydome radius (allows us to normalize skydome distances etc)

static int numSamples = 5;
static float samples = (float)numSamples;

// Calculates the Mie phase function
float getMiePhase(float fCos, float fCos2, float g, float g2)
{
	return 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos2) / pow(1.0 + g2 - 2.0*g*fCos, 1.5);
}

// Calculates the Rayleigh phase function
float getRayleighPhase(float fCos2)
{
	//return 1.0;
	return 0.75 + 0.75*fCos2;
}

struct PSInput
{
    float4 Pos : SV_POSITION;
    float4 RayleighColor : COLOR0;
    float4 MieColor	: COLOR1;
    float3 Direction : TEXCOORD0;
};

SamplerState samLinear
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap;
    AddressV = Clamp;
};

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))));
}

//
// Vertex Shader
//
PSInput VS(float4 Pos : POSITION, float2 Tex : TEXCOORD)
{
	PSInput output;
	
	v3LightDir.x = 0;
	v3LightDir.y = sin(time/100);
	v3LightDir.z = cos(time/100);
	
	// Get the ray from the camera to the vertex, and it's length (far point)
	float3 v3Pos = Pos / (fSkydomeRadius) * 10.25;
	float3 v3Ray = v3Pos - v3CameraPos;
	float fFar = length(v3Ray);
	v3Ray /= fFar;
	
	v3Ray = v3Pos - v3CameraPos;
	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(-fHeight/H0);
	float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight));
	
	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 = {0, 0, 0};
	for (int i = 0; i < numSamples; i++)
	{
		float fHeight = length(v3SamplePoint);
		//fDepth = exp(-fHeight/H0);
		fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight));
		
		float3 v3Up = {0, 1, 0};
		
		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;
	}
	
	output.RayleighColor.xyz = color * v3InvWavelength * KrESun;
	output.RayleighColor.w = 1.0f;
	
	output.MieColor.xyz = color * KmESun;
	output.MieColor.w = 1.0f;
	
	output.Direction = v3CameraPos - v3Pos;
	
	output.Pos = mul(Pos, worldViewProj);
	
    return output;
}


//
// Pixel Shader
//
float4 PS(PSInput input) : SV_Target
{	
	float fCos = dot(v3LightDir, input.Direction) / length(input.Direction);
	float fCos2 = fCos*fCos;

	return input.RayleighColor * getRayleighPhase(fCos2) + input.MieColor * getMiePhase(fCos, fCos2, g, g2);
}


technique10 Render
{
    pass P0
    {
        SetVertexShader( CompileShader( vs_4_0, VS() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, PS() ) );
    }
}



I've gone through it many times and can't find anything wierd about it. Mayby someone can point out what is wrong?

Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!