Skip to main content
GameDev.net gamedev.net
🔒 Locked

Fading the screen

Started by jaran Nov 4, 2004 at 4:21 AM 8 replies 1k views
Original Post
jaran
jaran
Hello, I hope someone can help me with this: I am using Direct3D in C# to create a 3D demo. Things has gone smoothly untill now when I want to fade the whole scene to a specific color. I did some programming with Direct3D in C++ before, and I remember I used the Device::Clear function to fade the whole screen. Now, when I try this in C# I don't manage to make it work. The code for clearing the screen is: Note: The alpha variable is an interpolated int changing from 0 to 255.
device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, System.Drawing.Color.FromArgb(alpha, 
			System.Drawing.Color.Black), 1.0f, 0);
My RenderStates are as follows:

d3dDevice.RenderState.CullMode = Cull.None;
d3dDevice.RenderState.AlphaBlendEnable = true;
d3dDevice.RenderState.AlphaSourceBlend = Blend.SourceAlpha;
d3dDevice.RenderState.AlphaDestinationBlend = Blend.InvSourceAlpha;								
d3dDevice.RenderState.ReferenceAlpha = 0x00;
d3dDevice.RenderState.FillMode = FillMode.Solid;
d3dDevice.RenderState.Lighting = true;
The only thing that happens is that the screen goes blank. No change in alpha. I am quite new to Direct3D, so I have probably just forgotten a renderstate or done some other n00b-messup:) Hope anyone here can help me out. Thanks.
NULL
Asheh
Asheh
Alright well dont use that method, theres somthing called a gamma ramp which you can adjust. Look it up in the SDK i cant remember the code exsactly but its really simple.

It will let you adjust the gamma, hence you can create a nice fade. I used it in one of my games once.
S1CA
S1CA
Alternatively, display a transformed quad which covers the whole screen and is rendered after everything else in the scene. The colour of the quad should be the colour you wish to fade to/from.

Then enable alpha blending as you did above (disable alpha testing), and change the alpha values for the whole quad to fade to and from the colour.


BTW: Clear() does as it sounds - it clears everything in the backbuffer surface; It can't be used to fade the scene to a specific colour.
Simon O'Connor | Technical Director (Newcastle) Lockwood Publishing | LinkedIn | Personal site
jaran
jaran
S1CA, I have been trying to use your method, before I posted here, but I never got it to work. It doesnt fade the "rectangle" that is drawn...

Can you look at my code and see if there is something wrong?

This is the class I have created to create what I guess you call a "quad":

/// <summary>	/// Provides easy access to a colored sprite.	/// </summary>	public class ColoredSprite	{		private Device device;		private Vector3 position;		private Vector3 dimension;		private System.Drawing.Color color;		private VertexBuffer vertexBuffer;		public ColoredSprite(Device d, Vector3 pos, Vector3 dim, System.Drawing.Color c)		{			device = d;			position = pos;			dimension = dim;			color = c;			vertexBuffer = new VertexBuffer(typeof(CustomVertex.PositionColored), 4, device, Usage.None, 					CustomVertex.PositionColored.Format, Pool.Default);			UpdateVertices();		}		/// <summary>		/// Update the vertex buffer with new vertices when the position and/or dimension		/// has been changed.		/// </summary>		private void UpdateVertices()		{			CustomVertex.PositionColored[] vertices = new CustomVertex.PositionColored[4];			vertices[0] = new CustomVertex.PositionColored(				position.X - (dimension.X / 2.0f),				position.Y - (dimension.Y / 2.0f),				position.Z, color.ToArgb());						vertices[1] = new CustomVertex.PositionColored(				position.X - (dimension.X / 2.0f),				position.Y + (dimension.Y / 2.0f),				position.Z, color.ToArgb());			vertices[2] = new CustomVertex.PositionColored(				position.X + (dimension.X / 2.0f),				position.Y - (dimension.Y / 2.0f),				position.Z, color.ToArgb());			vertices[3] = new CustomVertex.PositionColored(				position.X + (dimension.X / 2.0f),				position.Y + (dimension.Y / 2.0f),				position.Z, color.ToArgb());			vertexBuffer.SetData(vertices, 0, LockFlags.None);		}		/// <summary>		/// Property for the position of the sprite.		/// </summary>		public Vector3 Position		{			get			{				return position;			}			set			{				position = value;				UpdateVertices();			}		}		/// <summary>		/// Property for the dimension of the sprite.		/// </summary>		public Vector3 Dimension		{			get			{				return dimension;			}			set			{				dimension = value;				UpdateVertices();			}		}        /// <summary>        /// Property for the fill color of the sprite.        /// </summary>				public System.Drawing.Color Color		{			get			{				return color;			}			set			{				color = value;				UpdateVertices();			}		}		public void RenderSprite()		{						//Set parameters			device.SetStreamSource(0, vertexBuffer, 0);						device.VertexFormat = CustomVertex.PositionColored.Format;			device.TextureState[0].ColorOperation = TextureOperation.Disable;				//Render the sprite			device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);					}	}


And this is the code I use for rendering the sprite:

int alpha = (int)fadeOutInter.Interpolate();										spriteOverlay.Color = System.Drawing.Color.FromArgb(alpha, System.Drawing.Color.Black);					spriteOverlay.RenderSprite();


Thanks for your replies so far...
NULL
Supernat02
Supernat02
You're setting the color operation of the first texture stage state to disabled. Though it's valid to do so, you must also disable your alpha stage 0. And also no texture mapping at all can occur. So, don't do that.

Disable color and alpha stages 1. Set color stage 0 to Select Arg 1. Set Color Arg 1 to Diffuse. Set Alpha arg 1 to Diffuse and alpha op stage 0 to select arg 1. Disable lighting. Enable Alpha Blend. Disable Alpha Test.

I beleive the gamma ramp is a much faster operation if you're concerned with that. However, it's not supported by all hardware (newer hardware probably all supports it, I don't know)

Chris
Chris ByersMicrosoft DirectX MVP - 2005
jaran
jaran
Thanks a bunch. Bed-time here now, so I will have to look more at it tomorrow. I would like to use the quad solution if I can, so I will try to figure that out first.

Thanks again for your help.

Jaran.
NULL
Jacob Roman
Jacob Roman
I know this is in VB but it shouldn't be too hard to convert to C#. This is my gamma correction sub that I use in DirectX8. If you are using DirectX9, I'm not sure if you need to make some changes or not. Be sure to use decimals in the GammaFactor. 1 is normal, anything less is darker. 3 would make it really bright. 10 would probably whiten everything. So having a loop go from 0 to 1 in small increments should help you fade it in and vice versa.

Public Sub DirectX8_Set_Gamma(ByVal GammaFactor As Single, Red As Integer, Green As Integer, Blue As Integer)        Direct3D_Device.GetDeviceCaps Direct3D_Caps    'I commented these out but it helps find whether the video card is supporting Gamma Correction or not.    'If (Direct3D_Caps.Caps2 And D3DCAPS2_FULLSCREENGAMMA) <> D3DCAPS2_FULLSCREENGAMMA Then Exit Sub    'If (Direct3D_Caps.Caps2 And D3DCAPS2_CANCALIBRATEGAMMA) <> D3DCAPS2_CANCALIBRATEGAMMA Then Exit Sub        Dim Gamma_Ramp As D3DGAMMARAMP        Dim Red_Value As Long    Dim Green_Value As Long    Dim Blue_Value As Long        Dim Unsigned_Integer_Red As Long    Dim Unsigned_Integer_Green As Long    Dim Unsigned_Integer_Blue As Long        Dim Current_Color As Long    'create linear gamma ramp    For Current_Color = 0 To 255                Unsigned_Integer_Red = 0        Red_Value = Current_Color * GammaFactor * Red        If Red_Value > 32767 Then Red_Value = Red_Value - 32767: Unsigned_Integer_Red = 1        If Red_Value > 32767 Then Red_Value = 32767                Unsigned_Integer_Green = 0        Green_Value = Current_Color * GammaFactor * Green        If Green_Value > 32767 Then Green_Value = Green_Value - 32767: Unsigned_Integer_Green = 1        If Green_Value > 32767 Then Green_Value = 32767                Unsigned_Integer_Blue = 0        Blue_Value = Current_Color * GammaFactor * Blue        If Blue_Value > 32767 Then Blue_Value = Blue_Value - 32767: Unsigned_Integer_Blue = 1        If Blue_Value > 32767 Then Blue_Value = 32767        'manipulate bits to handle unsigned integers        Gamma_Ramp.Red(Current_Color) = Red_Value Or (-32768 * Unsigned_Integer_Red)        Gamma_Ramp.Green(Current_Color) = Green_Value Or (-32768 * Unsigned_Integer_Green)        Gamma_Ramp.Blue(Current_Color) = Blue_Value Or (-32768 * Unsigned_Integer_Blue)            Next Current_Color    'send gamma ramp to device    Call Direct3D_Device.SetGammaRamp(D3DSGR_NO_CALIBRATION, Gamma_Ramp)End Sub
jaran
jaran
Hmmm... I am getting further but still having some problems. At least now the sprite renders in the color I want, but the alpha is not working:-/ Can anyone see what I do wrong?

Here's the sprite (or quad) class:

using System;using Microsoft.DirectX;using Microsoft.DirectX.Direct3D;namespace Jaranweb.Direct3D{	/// <summary>	/// Provides easy access to a colored sprite.	/// </summary>	public class ColoredSprite	{		private Device device;		private Vector3 position;		private Vector3 dimension;		private System.Drawing.Color color;		private VertexBuffer vertexBuffer;		public ColoredSprite(Device d, Vector3 pos, Vector3 dim, System.Drawing.Color c)		{			device = d;			position = pos;			dimension = dim;			color = c;			vertexBuffer = new VertexBuffer(typeof(CustomVertex.PositionColored), 4, device, Usage.None, 					CustomVertex.PositionColored.Format, Pool.Default);			UpdateVertices();		}		/// <summary>		/// Update the vertex buffer with new vertices when the position and/or dimension		/// has been changed.		/// </summary>		private void UpdateVertices()		{						CustomVertex.PositionColored[] vertices = new CustomVertex.PositionColored[4];			vertices[0] = new CustomVertex.PositionColored(				position.X - (dimension.X / 2.0f),				position.Y - (dimension.Y / 2.0f),				position.Z, color.ToArgb());						vertices[1] = new CustomVertex.PositionColored(				position.X - (dimension.X / 2.0f),				position.Y + (dimension.Y / 2.0f),				position.Z, color.ToArgb());			vertices[2] = new CustomVertex.PositionColored(				position.X + (dimension.X / 2.0f),				position.Y - (dimension.Y / 2.0f),				position.Z, color.ToArgb());			vertices[3] = new CustomVertex.PositionColored(				position.X + (dimension.X / 2.0f),				position.Y + (dimension.Y / 2.0f),				position.Z, color.ToArgb());									vertexBuffer.SetData(vertices, 0, LockFlags.None);		}		/// <summary>		/// Property for the position of the sprite.		/// </summary>		public Vector3 Position		{			get			{				return position;			}			set			{				position = value;				UpdateVertices();			}		}		/// <summary>		/// Property for the dimension of the sprite.		/// </summary>		public Vector3 Dimension		{			get			{				return dimension;			}			set			{				dimension = value;				UpdateVertices();			}		}        /// <summary>        /// Property for the fill color of the sprite.        /// </summary>				public System.Drawing.Color Color		{			get			{				return color;			}			set			{				color = value;				UpdateVertices();			}		}		public void RenderSprite()		{						//Set parameters			device.SetStreamSource(0, vertexBuffer, 0);						device.VertexFormat = CustomVertex.PositionColored.Format;									device.RenderState.Lighting = false;			device.TextureState[1].ColorOperation = TextureOperation.Disable;						device.TextureState[1].AlphaOperation = TextureOperation.Disable;						device.TextureState[0].ColorOperation = TextureOperation.SelectArg1;			device.TextureState[0].ColorArgument1 = TextureArgument.Diffuse;			device.TextureState[0].AlphaArgument1 = TextureArgument.Diffuse;			device.TextureState[0].AlphaOperation = TextureOperation.SelectArg1;															//Render the sprite			device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);					}	}}


And here is the render states I set when the whole thing is initialized:

d3dDevice.RenderState.CullMode = Cull.None;				d3dDevice.RenderState.AlphaBlendEnable = true;				d3dDevice.RenderState.AlphaSourceBlend = Blend.SourceAlpha;				d3dDevice.RenderState.AlphaDestinationBlend = Blend.InvSourceAlpha;												d3dDevice.RenderState.ReferenceAlpha = 0x00;				d3dDevice.RenderState.FillMode = FillMode.Solid;				d3dDevice.RenderState.Lighting = true;				d3dDevice.RenderState.AlphaTestEnable = false;


It must just be a small thing left before it wroks, but I can't figure out what is wrong... :P
NULL
Promit
Promit
I just want to jump in and warn against gamma ramping as a method of fading. It's overkill, and it really, really tends to cause problems should you try to run your program in windowed mode, since gamma is a fullscreen effect.
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.
marcus12024
marcus12024
I just thought that I would point out that using the quad that is stretched to the whole screen really does make the most sense. I just load in an 8x8 white .bmp onto a texture of whatever size my screen is, and then set the color of that and change the alpha value every frame.

This method is quick, fairly easy, and fast.

Also, it allows you to do something that the other methods listed can't possibly achieve: say your game has a four player split-screen mode, and one of the players dies...and you want to fade their quarter-screen to red (or black, whatever). Using this textured quad method, you can just fade a quad that is the same size as that player's screen.

Works nicely.
Life's Short. Make Games.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.