Alpha not getting to 1

BlitzMax Forums/BlitzMax Beginners Area/Alpha not getting to 1

u2o(Posted 2006) [#1]
Can anyone ease my head and tell me when executing the code below why the 'Alpha' never (or only occasionaly) make it to 1.00000000?



	Strict
	
	Type TMyType
		
		Field Alpha:Float
		Field StartTime:Float
		Field ElapsedTime:Float
		
		
		Method ResetAlpha()
			Alpha = 0
		End Method
		
		
		Method ResetTimers()
			StartTime = MilliSecs()
			ElapsedTime = 0
		End Method
		
		
		Method CalculateElapsedTime()
			ElapsedTime = MilliSecs()-StartTime
		End Method
		
		
		Method Fade(FadeTimer:Int = 5000)
			ResetTimers()
			
			While ElapsedTime <= FadeTimer
				Alpha = ElapsedTime/FadeTimer
				Draw()
				CalculateElapsedTime()
			Wend
			
			DrawText "Done. Final Alpha: "+ Alpha , 0, 0
			Flip
		End Method
		
		
		Method Draw()
			SetBlend ALPHABLEND
			SetAlpha Alpha
			
			SetColor 255, 255, 255
			DrawText Alpha, 0, 0
			DrawText "Working", 0, 10
			
			Flip 1; Cls
		End Method
		
		
	End Type
	
	
	
	
	Local iRefreshRate:Int = GetDeviceCaps(GetDC(PrimaryDevice.hwnd), VREFRESH)


	SetGraphicsDriver GLMax2DDriver()
	Graphics 800, 600, 32, iRefreshRate


	' And the code..
	Local myScreen:TMyType = New TMyType
	
	myScreen.Fade()

	
	WaitKey


If I change the screen refresh to 60 (instead of the current refresh rate) the 'Alpha' makes it to 1.00000000

If I change 'Flip 1' to 'Flip 0', again 'Alpha' makes it to 1.00000000

I am a little tierd, and cant seem to figure it out!

Many thanks,


Perturbatio(Posted 2006) [#2]
at a guess, and without looking at the code, it's probably a floating point precision issue. You could check to see if it's close to 1.0 and if so, just set it.


H&K(Posted 2006) [#3]
As a wild guess, I bet it only reaches 1.0 on screen refreshes that divide into 5000 ;)

Its because somtimes the elapsed time is greater than the fade time
While ElapsedTime <= FadeTimer
It will happen whenever (Milliseconds Per Frame) isnt a denominator of fadetimer

EG 4980 + 60 Milli is grater then your 5000 Fadetimer, so it dosent run a cycle with it as one.

To fix it make FadeTimer a multiple of the refresh rate (ie 5040 for 60Hz)


u2o(Posted 2006) [#4]
H&K: I see what you are saying, but I don't think this is correct because why would it work okay (every time) when I set Flip to 0 (Flip 0) and the screen refresh is either 60 or my desktop (actually 75)?

I am pretty sure that it wont matter what the refresh rate is if Flip is 0, it will always work.

I am still stumped :(

Just a thought.. If I change the following:
		Method Fade(FadeTimer:Int = 5000)
			ResetTimers()
			
			While ElapsedTime <= FadeTimer
				Alpha = ElapsedTime/FadeTimer
				Draw()
				CalculateElapsedTime()
			Wend
			
			DrawText "Done. Final Alpha: "+ Alpha , 0, 0
			Flip
		End Method


to

		Method Fade(FadeTimer:Int = 5000)
			ResetTimers()
			
			Repeat
				Alpha = ElapsedTime/FadeTimer
				Draw()
				CalculateElapsedTime()
			Until ElapsedTime >= FadeTimer
			
			DrawText "Done. Final Alpha: "+ Alpha , 0, 0
			Flip
		End Method

That might do it? (I cant try it now, I am still at work)


Dreamora(Posted 2006) [#5]
Because with flip 0 it has no 60hz (it disables VSync unless it is enforced as always on in driver). With todays GPUs its most likely like 120 - 200 in which case its much more likely that it hits the right spot.


Modifying the code a little should solve it:

Method Fade(FadeTimer:Int = 5000)
			ResetTimers()
			
			While ElapsedTime <= FadeTimer
				Alpha = ElapsedTime/FadeTimer
				Draw()
				CalculateElapsedTime()
			Wend
                        if Alpha < 1
                          Alpha = 1
                          Draw()
                          CalculateElapsedTime()
                        endif
			
			DrawText "Done. Final Alpha: "+ Alpha , 0, 0
			Flip
		End Method



H&K(Posted 2006) [#6]
If sync is 0, then the flip occurs as soon as possible. If sync is 1, then the flip occurs on the next vertical blank.
Just change the 5000, to 5040. (for 60 hz) or5025 for 75 hrz.

WHY, do you print the question, then say Naar your wrong, without even looking at the Anwser


u2o(Posted 2006) [#7]
Yes! That will do it, thanks Dreamora!!!


u2o(Posted 2006) [#8]
H&K, I didnt say you are wrong, because I dont know at this point. I said "I don't think this is correct", big difference.

However, I didnt mean to offend you either way, so sorry :)


H&K(Posted 2006) [#9]
Hang on, you mean you actually cut and pasted Dreams code, Yet couldnt be bothered to change 2 didits when I told you the anwser?
Im sorry but yes I am annoyed at you. (I was alredy A bit annoyed when you reprinted your code without changing the 5000)


u2o(Posted 2006) [#10]
H&K: I have not tried any of the code (still at work). I just mulled it over in my head, and Dreamora's made more sense. Although I got what you are aiming at.

Thanks H&K for you reply!


H&K(Posted 2006) [#11]
This is H&K's big brother. You've gone and made him cry

Ok yep Dreams makes more sence.
That because in anwser to your "Alpha doesnt reach 1" dream sudgests you just make it equal 1

The reason it wasnt equaling one is the reason I gave.
I didnt mention the flip 0 not being synced the first time, because I (Incorrectly it seems), simply assumed you knew that.

Whats happening when flip is 1, is that 1000/(Hertz frame rate) is being added to elapsedtime each flip.
Now if 1000/(Hertz frame rate) doesnt divide without remainder into fadetime, then alpha will never reach 1.
When Flip is 0, probally the flip time is as Dream said very very quick, so Frametime*x has more chance of being 5000 exactly


Dreamora(Posted 2006) [#12]
Btw: you could use H&K suggestion as well but in an automatic way:

Just calculate the difference from hertz to fadetimer:

At the beginning of the function

FadeTimer :+ (GraphicsHertz() - (FadeTimer mod GraphicsHertz()) )

That way the FadeTimer is always int divideable with Flip 1 and should reach alpha = 1 as well. I say should because I'm not sure that the GraphicsHertz() bug with DX has been fixed.


H&K(Posted 2006) [#13]
@dream, I did think of presenting my first anwser like that, but decided to keep it simpler.
However on my computer it sometimes drops from 60htz to 59htz unexpectedly. (Well not really unexpectidly, cos you can predict when its going to happen)

When it does this, you need to just do what you have done and catch it ;)

ie Your solution was the better one to use

But thats because my answer was to show "Why alpha doesnt equal 1" by forceing u2o to look at what was specificaly wrong with his logic to make the while loop fail before it reached 1 (Edit: This makes me sound like a total git dosent it?)

Which, given that I hate being given my sort of anwser, is probably not the way to do it.
But I do think that there should be a fundimentaly different type of anwser depending on which thread, (begginer/programing) the post is in


u2o(Posted 2006) [#14]
Thanks for the replies, much appreciated :)