Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Lerp and int/float conversions
#1
Just about got the "Barrel" sample converted to C#, just have to add Simon, easy - it's math that's not my strong point! But I think the answer will help me with the rest of the conversions.

The scanlines aren't scaling properly to create the tunnel effect. I know the problem will have to do with my interpretation of when to convert between float and int.  Something else that's throwing me off is the way that lerp is using 5 parameters, but all implementations I can find use 3, which makes sense to me - point a, and b, and how far between.   So I don't understand how the 5 parameters are used (and couldn't find any examples on the net so far).

I've attached the project (Barrel.csproj is the concern), and also pasted the section of the problem code for your convenience.

    /* raster effects (virtual HBLANK) */
    static void MyRasterEffects(int line)
    {
        float angle;
        float factor;
        int size;
        int index;
        int dx;

        angle = lerp(line, 0, Vres - 1, 0.0f, M_PI);
        factor = (float)((1.0 - System.Math.Sin((double)angle)) * 0.4 + 1.0);
        size = (int)((float)Hres * factor);
        dx = (int)(((float)(size - Hres) / 2) / factor);
        transform.sx = factor;

        background.SetTransform(transform.angle, transform.dx, transform.dy, transform.sx, transform.sy);

        if (line < 70)
        {
            index = (int)lerp(line, 0, 70, 0, 7);
            background.Palette = palettes[index];
        }
        else if (line > 170)
        {
            index = (int)lerp(line, 170, Vres, 7, 0);
            background.Palette = palettes[index];
        }
        else
            background.Palette = palettes[7];
    }

    /* linear interploation */
    static float lerp(int x, int x0, int x1, float fx0, float fx1)
    {
        return fx0 + (fx1 - fx0) * (float)((x - x0) / (x1 - x0));
    }


Attached Files
.zip   csharp.zip (Size: 48.17 KB / Downloads: 0)
Reply
#2
Don't worry! I just converted every parameter in "lerp" to be floats, no more ints, and the effect is perfect!

*facepalm*

I also learnt an important difference between C++ and C# here;
  • With C++, if you throw even one float variable into the calculation, the output will be a float. But if all of them are ints, the output will be an int, even if accuracy will be lost (eg. a division).
  • With C#, if you do any sort of mixing between floats and ints, the compiler itself stops and complains that you can't automatically just mix them, you need to step in and manually cast each one to a float or int before it will proceed, forcing you to make a decision.

Man, I think I prefer the way C++ works here. It does the calculation using the most accurate variable type in the equation - this is simple to remember, and I can always just cast down to a simpler type if I need it. I know C# is attempting to be "safer" by asking you to manually convert each one, but I think this just introduces more chances of human error...

I'm sure there's an argument for either way though.
Reply
#3
C and C++ do "type promotion", that is: automatically convert the resulting type of an expression to the type of the term that requires most precision. For what you have discovered, C# doesn't. Interesting!

The linear interpolation you talked about (with 3 terms) is the simplified one, where the source and target intervals are assumed to start at 0. Yo just need the source value to convert, the source limit and the target limit. But the general formula accepts arbitrary intrevals that don't start at 0. Take  look at this article, and you'll find the formula I use in the samples:
https://en.wikipedia.org/wiki/Linear_interpolation
Reply
#4
Perhaps it was just MonoDevelop, but yeah, it was stopping me at the compilation phase...

Well, the wiki page still uses the 3 parameter version that I know!  But looking again at your code, particularly this line, because I know what it's doing now; index = (int)lerp(line, 170, Vres, 7, 0);

I can work out; lerp(cur_pos, min_pos, max_pos, min_output, max_output)

So you're converting the line position to an index in the palette based on its position between the min_pos and max_pos... I like it!  I can see how the palette output is inverted for the bottom half of the screen. Thinking back I always used to do this in a 2 step process - get the position between two points as a percentage, then use that percentage to work out the position between two other points. Now I can use this handy dandy function to do it in one line of code.
Reply
#5
This sample function in the wiki:

Code:
float lerp(float v0, float v1, float t) {
 return v0 + t * (v1 - v0);
}

Is the simplified one, it only works if the independent variable t ranges from [0,1]. What if your t goes in the range [3, 5] for example?

But you figured out well the meaning of the line you talk about: returns an index in the interval [7, 0] from the current scanline value in the range [170, vres], that is the lower portion of the screen where the palette lightening happens. Raster effects in action Smile
Reply
#6
It's very exciting, I'm really digging these raster effects... I thought it'd be a tonne of math, but I can handle math inside a simple function like lerp - I just need to know what it does and how to use it, I don't really need to understand the math 100%.

After converting all the samples to CSharp, I plan to fill out your "Raster effects" section of your document, with each of the effects displayed in the samples, I thought that'd be a good idea Smile
Reply
#7
Math for raster effects couldn't be complex back in the day, many effects are based on precalculated fixed-point trigonometric and delta tables that are reused as much as possible.

Some examples explained on the "raster effects" section is a good idea, but listing them all is impossible, because they're just a blank canvas. Take a look at how the 3D floor effect was made on a "Mickey Mania" level: impressive, the only limit is the imagination and skill of the developer using them.
https://www.youtube.com/watch?v=nt-AxAqlrOo
Reply
#8
That's another reason why I love retro stuff - it's so much simpler, hahah.

Ah in case I wasn't clear - I would be doing an explanation of each of the samples you've already included.  For the same reason you clearly decided to include just those samples - they're a nice introduction to what kinds of things can be achieved, so that seems like the logical choice to flesh out the "Raster effects" heading of your document.  I actually assumed that's what you were going to do there?

But yeah I LOVE that gamehut channel.  Another awesome one is "Retro Game Mechanics Explained" misleading title - it actually gets very technical, and is hardware based Smile maybe you know it?
Reply
#9
I haven't checked the "Retro Game Mechanics Explained" channel you recommended until today. Awesome! It has great subjects and presentation. I knew about some of the subjects exposed, but not about the channel itself. It's on mi favourites playlist now. Thanks for sharing!
Reply
#10
Glad you like it - I think it's amazing that he visually animates everything he talks about. Some of them there's no way he's doing it by hand, it has to be programmatically somehow...
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)