Sign in to follow this  
Daniel E

day & night cycle sky shader for you

Recommended Posts

Hi, so here's my first contribution to this site i've learned so much from. a day & night cycle sky shader written in hlsl. here's a video of it on youtube: the shader is written for ps/vs 2.0 and uses one pass. Credits go to RaveniX for some lines i translated from his glsl shader that he posted here. I've produced a little demo application that uses the shader: download sky shader demo app source The sky itself renders at a fps rate of 2000+ on my ati hd 4850. Feel free to use it for your projects. Any feedback or optimization advice would be highly appreciated. i hope somebody likes it :) here's the hlsl of the shader:
vector SunPos = {1.0, 1.0, 1.0, 1.0 };

float time_of_day;

vector Zenith  = { 0.00, 0.34, 0.71, 0.00 };
vector Horizon = { 0.70, 0.40, 0.20, 0.00 };

float4x4 MatWVP 	: ViewProjection;
float4x4 MatViewInv	: ViewInverse;
float4x4 MatWorld	: World;

float3 LightDir	= {1.0f, 1.0f, 1.0f };

sampler TextureOne = sampler_state
{
   MipFilter = LINEAR;
   MinFilter = LINEAR;
   MagFilter = LINEAR;
   ADDRESSU = WRAP;
   ADDRESSV = WRAP;
   ADDRESSW = WRAP;
};

sampler TextureTwo = sampler_state
{
   MipFilter = LINEAR;
   MinFilter = LINEAR;
   MagFilter = LINEAR;
   ADDRESSU = WRAP;
   ADDRESSV = WRAP;
   ADDRESSW = WRAP;
};

sampler TextureThree = sampler_state
{
   MipFilter = LINEAR;
   MinFilter = LINEAR;
   MagFilter = LINEAR;
   ADDRESSU = WRAP;
   ADDRESSV = WRAP;
   ADDRESSW = WRAP;
};

struct VS_input
{
	float4 Position : POSITION0;
	float2 tex1 : TEXCOORD0;
};

struct VS_output
{
	float4 Position : POSITION0;
   	float2 tex1 : TEXCOORD0;
	float3 Vertex : TEXCOORD1;
};

struct PS_output
{
   float4 diffuse : COLOR0;
};

VS_output vs_main( VS_input input )
{
   VS_output output;

   output.Vertex = input.Position;

   output.Position = mul( float4(input.Position.xyz , 1.0f) , MatWVP);
   
   output.tex1 = input.tex1;

   return( output );
}


PS_output ps_main(in VS_output input)
{
   	PS_output output = (PS_output)0;
   	
	float3 norm = normalize(input.Vertex).xyz;
	float3 Sun = normalize(SunPos.xyz);
	float  SunDot = dot(Sun, norm);

    	float2 cycle = {fmod(SunPos.w, 100.0), 0};
    	float fact_clouds = saturate(SunPos.y * 4.0) * 0.3;
   	fact_clouds *= time_of_day;
	
	// first texture: clouds

    	float4 clouds1 = tex2D(TextureOne, input.tex1 * 2.0 + cycle);   
	clouds1.rgb *= fact_clouds;
   	
    	// second texture: stars
    
    	float3 stars = tex2D(TextureTwo, input.tex1 * 4.0  - cycle);
	stars *= 1 - saturate(time_of_day * 1.5);
    
   	// third texture: more clouds

   	float4 clouds2 = tex2D(TextureThree, input.tex1 + cycle * 1.5 );    
	clouds2.rgb *= fact_clouds;
	
	// brighten up the clouds near the sun

	vector rays = 0.7f * pow( max(0.0, SunDot), 60.0f );
	rays *= clouds2.a;

	// use alpha from the clouds to hide stars behind clouds
	
	float clouds_alpha = max(clouds1.a, clouds2.a);

	stars *= 1 - clouds_alpha * time_of_day;
    
    	// moon and sun

	vector light = 0.8f * pow( max(0.0001, SunDot), 360.0f );
	//vector moon  = 0.3f * pow( max(0.0, dot(-Sun, norm)), 60.0f );

	// atmosphere
	
	float Curve = 0.25f * (2.0f - SunPos.y);

	vector sky = Zenith * (1-Curve) + Horizon * Curve;
	sky = sky * (1+SunDot) + Zenith * -SunDot;
	sky *= (1.0-clouds_alpha*(1.0-time_of_day));
	sky *= saturate(SunPos.y+2.0);
			
	// combine everything

    	output.diffuse.rgb = sky + clouds1 + stars + clouds2 + light + rays; // + moon 
	output.diffuse.a = 1.0f;

	return output;

} 


technique sky
{
   pass Pass_0
   {
      VertexShader = compile vs_2_0 vs_main();
      PixelShader = compile ps_2_0 ps_main();

   }
}


Share this post


Link to post
Share on other sites
The YouTube video looks fantastic, however your demo app presents me with a window with a white background and nothing else (well, except the menu).

This is compiling and running on Vista x64 with VS2008.

Share this post


Link to post
Share on other sites
@adt7:

thank you! I just downloaded and tested the demo and it works fine here.

Which kind of graphics device are you using? I have only tested this on a hd4850 and geforce 6200.

Maybe try changing

d3dpp.AutoDepthStencilFormat = D3DFMT_D24X8;

to

d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

in MhDirectx.cpp line 38

maybe this could cause problems on some hardware.

i hope we can fix this :)

Share this post


Link to post
Share on other sites
well it worked on my buddy's 9300gs...

maybe something about my project and vista?

i created it using VS 2005 and XP 32 bit.

Share this post


Link to post
Share on other sites
Quote:
Original post by adt7
The YouTube video looks fantastic, however your demo app presents me with a window with a white background and nothing else (well, except the menu).

This is compiling and running on Vista x64 with VS2008.
What do the Debug Runtimes say?

Share this post


Link to post
Share on other sites
Your problem appears to be that your effect won't compile. D3DXCreateEffectFromFile is returning INVALIDDATA, and compiling with fxc gives a really bizarre error. The problems seem to be stemming from the line where you do the fmod on SunPos.w. I think it's a compiler bug...disabling optimizations or the preshader gets it to compile with fxc. Still won't compile in the app, though...

Share this post


Link to post
Share on other sites
Test subject:
A8Js (notebook)
Nvidia Geforce Go 7700
512mb AGP (dedicated)
Shader model: 3.0
2GB Ram
Core2Duo 2GHZ

Debug build: (and mode)
FPS:
Starts at 8 then slowly goes down to 3.
Can reach a peek of 4 fps when the sun has gone up.
FPS drops to ~2.2 when the world is turning dark.

Errors upon exit:
D3DSemArbVS05.exe has triggered a breakpoint (free.c)

Comments:
What i found odd in this sample is that it was running at 8fps when it started, only to slowly drop to 3 fps, and never to return to it's previous speed.
Is this a flaw in the fps calculation, or is it actually running slower and slower?


Release build:
FPS is at ~steady 147.

Errors upon exit:
D3DSemArbVS05.exe has triggered a breakpoint.

Comments:
Still loaded with DirectX debug runtimes, FPS can be expected to exceed 147 with standard runtimes.
Decreasing fps not witnessed on release build.

[Edited by - marius1930 on June 20, 2009 3:41:31 AM]

Share this post


Link to post
Share on other sites
this line fails:
D3DXCreateEffectFromFile( device, "shaders/sky.fx", 0, 0, 0, 0, &effect, 0);

When i compile it with D3DXSHADER_NO_PRESHADER|D3DXSHADER_SKIPOPTIMIZATION|D3DXSHADER_DEBUG
then i get this error msg:

shaders\sky.fx(79,11): error X5608: Compiled shader code uses too many arithmetic instruction slots (100). Max. allowed by the target (ps_2_0) is 64.
(1,1): error X5609: Compiled shader code uses too many instruction slots (103). Max. allowed by the target (ps_2_0) is 96.

Share this post


Link to post
Share on other sites
hrmm got it to compile & work by changing it to:
D3DXCreateEffectFromFile( device, "shaders/sky.fx", 0, 0, D3DXSHADER_NO_PRESHADER|D3DXSHADER_DEBUG, 0, &effect, null);

Share this post


Link to post
Share on other sites
Hi! Thanks to you all for testing this!

The number of arithmetic instructions was actually be below 60 in FX Composer. I always test my shaders in FX Composer. The shader works in FX Composer for me.

Changing the shader versions to 3.0 might help if there are too many instructions.

It's strange that you get like 4 fps on your 7700. The whole scene with water and terrain runs at 20-25 fps on a 6200 gs. I don't get an error on exit either :/

i'm using the directx sdk from december 2006 btw.

my system specs are:

intel e6400 (core 2 duo)
ati hd 4850
2gb ram
Win XP 32 Bit SP3


I will inspect the project again but since it works on my pc i have no idea what causes the problems lol.


Here's a screenshot after i dropped the fx file from the demo app onto a sphere in fx composer:



Asm output in FXC says: approximately 60 instruction slots used (3 texture, 57 arithmetic)

edit: just removed LightDir from shader because it wasnt used.

[Edited by - Daniel E on June 20, 2009 6:58:34 AM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this