Closed fuzun closed 6 years ago
This was supposed to get updated to support phase swaps and bunch of other things along actually.
Discussion: https://forums.blurbusters.com/viewtopic.php?f=7&t=3815&p=30401
New prototype:
void R_Strobe(void)
{
...
if ((SwapPhaseInfo.fCounter % 2) == 0) //Starts with +
{
++SwapPhaseInfo.pCounter;
SwapPhaseInfo.isPositive = true;
}
else
{
++SwapPhaseInfo.nCounter;
SwapPhaseInfo.isPositive = false;
}
if (swapInterval < 0)
swapInterval = abs(swapInterval);
if ((swapInterval != 0) && (getInterval % 2 != 0)) //Swapping is not enabled for even intervals. Because it makes it like r_strobe -interval . It is not needed anyway since even intervals do not cause burn in problem.
{
currentTime = Sys_DoubleTime();
delta = currentTime - recentTime;
if ((delta >= (double)(swapInterval)) && (delta < (double)(2 * swapInterval)))
{
SwapPhaseInfo.isInverted = true;
}
else if (delta < (double)(swapInterval))
{
SwapPhaseInfo.isInverted = false;
}
else
{
recentTime = currentTime;
}
}
if (SwapPhaseInfo.isPositive == true && SwapPhaseInfo.isInverted == false)
{
if (abs(getInterval) % 2 == 0)
SwapPhaseInfo.isNormal = (((SwapPhaseInfo.pCounter - 1) % (abs(getInterval) + 1)) == 0) ? true : false; //even
else
SwapPhaseInfo.isNormal = (((SwapPhaseInfo.pCounter -1) % ((abs(getInterval) + 1) / 2)) == 0) ? true : false; //odd
if (abs(getInterval) == 1)
SwapPhaseInfo.isNormal = true;
}
else if (SwapPhaseInfo.isPositive == true && SwapPhaseInfo.isInverted == true)
{
if ((abs(getInterval) % 2) == 0)
SwapPhaseInfo.isNormal = (((SwapPhaseInfo.pCounter - 1) % (abs(getInterval) + 1)) == (abs(getInterval) / 2)) ? true : false; //even
else
SwapPhaseInfo.isNormal = false;
if (abs(getInterval) == 1)
SwapPhaseInfo.isNormal = false;
}
else if (SwapPhaseInfo.isPositive == false && SwapPhaseInfo.isInverted == false)
{
if ((abs(getInterval) % 2) == 0)
SwapPhaseInfo.isNormal = (((SwapPhaseInfo.nCounter - 1) % (abs(getInterval) + 1)) == (abs(getInterval) / 2)) ? true : false; //even
else
SwapPhaseInfo.isNormal = false;
if (abs(getInterval) == 1)
SwapPhaseInfo.isNormal = false;
}
else if (SwapPhaseInfo.isPositive == false && SwapPhaseInfo.isInverted == true)
{
if (abs(getInterval) % 2 == 0)
SwapPhaseInfo.isNormal = (((SwapPhaseInfo.nCounter - 1) % (abs(getInterval) + 1)) == 0) ? true : false; //even
else
SwapPhaseInfo.isNormal = (((SwapPhaseInfo.nCounter - 1) % ((abs(getInterval) + 1) / 2)) == 0) ? true : false; //odd
if (abs(getInterval) == 1)
SwapPhaseInfo.isNormal = true;
}
if (getInterval < 0)
SwapPhaseInfo.isNormal = !SwapPhaseInfo.isNormal;
if (SwapPhaseInfo.isNormal) //Show normal
{
R_Set2DMode(false);
if (SwapPhaseInfo.isPositive)
++SwapPhaseInfo.pNCounter;
else
++SwapPhaseInfo.nNCounter;
}
else //Show black frame
{
gl_GenerateBlackFrame();
if (SwapPhaseInfo.isPositive)
++SwapPhaseInfo.pBCounter;
else
++SwapPhaseInfo.nBCounter;
}
++SwapPhaseInfo.fCounter;
}
Maybe revert and re-open the pull request? Or leave this as is and I will open a new pull request soon?
Just open new PR based on formatting fixes from master. I did it as an example for you. Please, follow them. :)
Everything else is good, and I can't wait for further development of such cool feature for engine.
Yeah the idea is pretty cool actually. As far as I know it will be the first 3D engine that has built-in software based strobing. I want to know if you would like to see strobe settings in the video configuration setting. I can work on that as well.
@fuzun yes. You can try to add them in menu. Just send PR to mainui_cpp repository.
@fuzun Sorry for late answer, I was busy these two days. Great work!
I will completely review and test it, with next PR.
There is also some problems with strobing on Mesa drivers. They are pretty bad with VSync and tear-free, but I think it's not your trouble. Meanwhile it works on my Android device perfectly, although my RN4X have 60Hz screen.
New Version: #353
Simple strobe support with black frame insertion (replacement) technique.
Purpose Provides motion clarity by eliminating motion blur on high frequency monitors.
How Replaces certain amount of consequent frames with black frames. This makes a scanning effect like CRT monitors.
Usage Set r_strobe cvar to the black frame insertion interval (black frame count) you want (ideal values for 144hz monitors are probably -2, -1 = 1, 2, 3) . Frame display interval can be changed with gl_swapInterval cvar. Use cl_showfps 1 to see the actual / effective fps (displayed non-black frame count in 1 second).
Note that V-Sync must be active to enable this! (gl_swapInterval != 0)
If r_strobe is positive, some rendered frames will be replaced with black frame For example result of r_strobe = 3 will be: black-black-black-normal-black-black-black-normal-black-black-black-normal
If r_strobe is negative, the procedure will be the opposite. For example result of r_strobe = -4 will be: normal-normal-normal-normal-black-normal-normal-normal-normal-black
Issues
Actual brightness gets reduced to half (and perceived brightness will be lowered but not as much as actual brightness) if _rstrobe is set to 1 more if >1 less if <-1. This can be corrected somehow by altering gamma and brightness I believe. Because this is just like pulse width modulation synchronized to v-sync frames. And there are several methods to overcome PWM brightness issue. Implementing adaptive version of this is on todo list.
FPS will always be lowered. Actual or effective FPS (frames that are not black) gets reduced to half if _rstrobe is set to 1 or -1 more if >1 less if <-1 .
This will trigger epileptic attacks on epileptic patients.
Even on 144hz monitors, flickering may happen.
Perceived picture quality will be worse. Much worse on IPS, VA or slow TN panels.
Frames that will be black are rendered for no rational reason. TODO: Consider vsync timings and do not render the supposed black frame at all.
Ghosting effect may increase.
Web Demo: https://www.testufo.com/blackframes#count=2&bonusufo=0&equalizer=1&background=000000
Not tested on Android yet!