0 Members and 1 Guest are viewing this topic.
[15:11:42] <+SirCmpwn> so the reason that grayscale works in the first place is that pixels on the screen fade between on and off, but very quickly [15:12:10] <+SirCmpwn> so if you are fast enough, you can get in the middle of that process and, if you time it right, you can come close to keeping it at a constant faded value [15:12:22] <+SirCmpwn> this is accomplished by quickly changing a pixel from black to white [15:12:25] <+SirCmpwn> and back again [15:12:25] <+OmnomIRC> (O)<DJ_O> False. [15:12:28] <+SirCmpwn> over and over very quickly [15:12:30] <+OmnomIRC> (O)<DJ_O> jk [15:12:55] <+SirCmpwn> Let's say you have an 8x8 sprite [15:13:10] <+SirCmpwn> no, we'll make it 2x2 to make it easier [15:13:18] <+OmnomIRC> (O)<ztrumpet> 2x2 O.o [15:13:33] <+SirCmpwn> it looks like this, where W is white, X is light gray, Y is dark gray, and Z is black [15:13:35] <+SirCmpwn> WX [15:13:36] <+SirCmpwn> YZ [15:14:04] <+SirCmpwn> you cycle through three frames of grayscale [15:14:29] <+SirCmpwn> so on frame one, it looks like this: [15:14:38] <+SirCmpwn> where W is white and X is black [15:14:42] <+SirCmpwn> WX [15:14:44] <+SirCmpwn> WX [15:14:48] <+SirCmpwn> frame two: [15:14:49] <+SirCmpwn> WW [15:14:51] <+SirCmpwn> XX [15:14:55] <+SirCmpwn> and frame three: [15:14:56] <+SirCmpwn> WW [15:14:57] <+SirCmpwn> XX [15:15:22] <+OmnomIRC> (O)<ztrumpet> (Sometimes it's different, but that's one example) [15:15:24] <+SirCmpwn> this way, the light gray pixel is black for 1/3 of the time, and the dark gray pixel is on for 2/3 of the time [15:15:31] <+SirCmpwn> ztrumpet is right, it is usually a little different [15:15:51] <+SirCmpwn> the black and white pixels are constantly black or constantly white [15:15:58] <+OmnomIRC> (O)<DJ_O> it creates diagonal scanlines, moving [15:16:04] <+SirCmpwn> yes [15:16:08] <+SirCmpwn> but let's keep this basic [15:16:22] <+SirCmpwn> everyone follow at this point? [15:16:28] <+OmnomIRC> (O)<leafiness0> lol storytime [15:16:29] <+OmnomIRC> (O)<ztrumpet> yup [15:16:37] <+OmnomIRC> (O)* ztrumpet likes Sir's story [15:16:50] <+SirCmpwn> now let's look at a single dark gray pixel [15:16:55] <+SirCmpwn> in extremely slow motion [15:17:20] <+SirCmpwn> I'll assign it a value from 0-10 based on it's current actual appearance on screen, where 10 is black [15:17:30] <+OmnomIRC> (O)<DJ_O> yes [15:17:41] <+SirCmpwn> it changes like this over time: 6, 7, 8, 7, 6, 7, 8, 7, 6, 7, 8, and so on [15:17:56] <+SirCmpwn> there is, of course, variation on this [15:18:04] <+OmnomIRC> (O)<ztrumpet> Over a period of three frames to a number? [15:18:08] <+SirCmpwn> no [15:18:12] <+SirCmpwn> this isn't frame counts [15:18:17] <+SirCmpwn> this is in between frames [15:18:18] <+OmnomIRC> (O)<ztrumpet> Oh, I see [15:18:22] <+SirCmpwn> let me define it more specifically [15:18:51] <+SirCmpwn> [sets pixel to black] 6, 7, 8, [sets pixel to white], 7, 6, [sets pixel to black], 7, 8, etc [15:19:07] <+OmnomIRC> (O)<ztrumpet> Ah, yes [15:19:18] <+SirCmpwn> there is more or less deviation depending on the quality of grayscale [15:19:25] <+SirCmpwn> for perfect grayscale, it is a constant 7 [15:19:33] <+SirCmpwn> the more the deviation, the more flicker you notice [15:19:57] <+SirCmpwn> so imagine two pixels now [15:20:05] <+SirCmpwn> still with a value of 00-10 [15:20:16] <+SirCmpwn> here's what you want them to look like over time: [15:20:21] <+SirCmpwn> [dark gray][white] [15:20:24] <+OmnomIRC> (O)<DJ_O> ah i get it now, i didnt understand the 67876 thing [15:20:33] <+SirCmpwn> DJ_O good [15:20:40] <+SirCmpwn> anyone can stop and ask questions, for the record [15:20:52] <+SirCmpwn> so here's the evolution of that pixel over time: [15:20:57] <+SirCmpwn> *those pixels [15:21:05] <+OmnomIRC> (O)* ztrumpet wonders why I've never heard this awesome way of stating it before [15:21:10] <+OmnomIRC> (O)<ztrumpet> *I've = he's [15:21:19] <+OmnomIRC> (O)<leafiness0> lol [15:21:29] <+PixelBoy> (Am I allowed to ask a question about DCS7?) [15:21:34] <+SirCmpwn> [07][00], [08][00], sets to white, [07][00], [06][00], sets to black, and so on [15:21:40] <+SirCmpwn> PixelBoy: can it wait [15:21:41] <+SirCmpwn> ? [15:22:08] <+SirCmpwn> now imagine if you were to move the dark gray pixel to the right [15:22:16] <+SirCmpwn> this is where it gets complex [15:22:26] <+SirCmpwn> the frame before you move it, it looks like [07][00] [15:22:33] <+SirCmpwn> then you apply the changes to the screen [15:22:37] <+SirCmpwn> and it starts to do this: [15:23:17] <+SirCmpwn> [06][01], [05][02], [04][03], [03][04], [02][05], [01][06], [00][07] [15:23:51] <+SirCmpwn> however, it doesn't actually happen like that, because you're still updating grayscale [15:24:12] <+SirCmpwn> you never set the left pixel to black again, so it constantly drops. Its evolution is guaranteed to look like this: [15:24:31] <+SirCmpwn> [07], [06], [05], [04], [03], [02], [01], [00] [15:24:39] <+SirCmpwn> the right pixel is a different story [15:24:52] <+SirCmpwn> you keep updating grayscale as it evolves [15:25:00] <+SirCmpwn> meaning that you flicker it between black and white [15:25:03] <+SirCmpwn> so it looks like this: [15:25:06] <+OmnomIRC> (O)<ztrumpet> ...and eventually it just looks like a moving blob [15:25:18] <+OmnomIRC> (O)<ztrumpet> ;) [15:25:52] <+SirCmpwn> [00], [01], [02], set to white, [01], set to black. [02], [03], set to white, [02], set to black, [03], [04], set to white, [03], set to black, [04], [05], etc [15:26:15] <+SirCmpwn> all the way back up to the normal dark gray evolution of [07]-[06]-[07]-[08] [15:26:37] <+SirCmpwn> so any pixel set from white to gray will have a similar evolution [15:26:43] <+SirCmpwn> the same applies to black to gray [15:27:13] <+SirCmpwn> so you can tell that moving a single dark gray pixel will look generally mediocre [15:27:26] <+SirCmpwn> but imagine if you were doing 4 level grayscale smooth scrolling on the whole screen [15:27:31] <+SirCmpwn> _every_ pixel is moved [15:27:45] <+SirCmpwn> not only that, but in our example, the left pixel stayed white [15:27:52] <+SirCmpwn> but on a full screen tilemap, it probably wonot [15:27:54] <+SirCmpwn> *wont [15:28:14] <+SirCmpwn> and if you scroll again before the sequence fully evolves, it gets even worse [15:28:38] <+OmnomIRC> (O)<ztrumpet> Woah, are you talking about with just one DispGraphrr instead of three? [15:28:45] <+SirCmpwn> yes [15:28:47] <+OmnomIRC> (O)<ztrumpet> O.o [15:28:50] <+SirCmpwn> there is still bad quality with three [15:28:52] <+OmnomIRC> (O)<ztrumpet> Yeah, don't do that [15:29:12] <+SirCmpwn> the CPU time that it takes to scroll worsens the situation [15:29:21] <+SirCmpwn> it takes more time to scroll than to not scroll, obviously [15:29:29] * +JustCause ([email protected]) Quit (Remote host closed the connection) [15:29:33] <+SirCmpwn> so your pixel deviation increases [15:29:42] <+OmnomIRC> (O)<ztrumpet> You almost need four buffers - two to operate on and two to display with [15:29:48] <+SirCmpwn> at the same time that all of this is happening [15:29:53] <+SirCmpwn> and you don't really need four buffers [15:29:55] * leafy ([email protected]) has joined #omnimaga [15:29:55] * Netbot45 sets mode: +v leafy [15:30:05] <+SirCmpwn> you already have 3, technically [15:30:11] <+SirCmpwn> two to operate on, and the screen to display with [15:30:29] <+OmnomIRC> (O)<ztrumpet> There's another one at E8000 (if you add three bytes of Asm() ) [15:30:41] <+SirCmpwn> you don't need to use any more [15:31:05] <+SirCmpwn> there is no really good solution to this problem [15:31:21] <+SirCmpwn> the best ways to fix this is to allow the pixels time to reach their normal evolution after scrolling [15:31:38] <+SirCmpwn> find something to do between the scrolling and the screen update, but nothing too big [15:31:43] <+shmibs> so choppier scrolling on more disparate intervals [15:31:57] <+SirCmpwn> yes [15:32:18] <+SirCmpwn> to reduce pixel deviation, get as much logic out of the loop as you possibly can [15:32:29] <+SirCmpwn> DispGraphrr three times in a row for ideal deviation removal [15:32:49] <+SirCmpwn> and in the rest of your loop, don't even think about redrawing the whole screen every frame [15:33:05] <+OmnomIRC> (O)<ztrumpet> How many DispGraphrrs do you hav in your entire main loop for Motherload? [15:33:09] <+SirCmpwn> redraw very sparingly, only on the parts of the screen that change [15:33:23] <+SirCmpwn> ztrumpet: the loop executes differently every time, but there is at most six per frame [15:33:32] <+OmnomIRC> (O)<ztrumpet> O.o [15:33:39] <+OmnomIRC> (O)<ztrumpet> That's some awesome sounding code [15:33:45] <+leafy> xD [15:34:00] <+SirCmpwn> I update 3 times every loop [15:34:11] <+SirCmpwn> on physics frames, I do an early update beforehand [15:34:11] <+OmnomIRC> (O)<ztrumpet> All in a row? [15:34:15] <+SirCmpwn> in a row, yes [15:34:28] <+OmnomIRC> (O)<ztrumpet> physics frames? [15:34:41] <+SirCmpwn> I split up my frame-to-frame operations three ways [15:34:49] <+SirCmpwn> every third frame, physics updates [15:35:02] <+OmnomIRC> (O)<calc84maniac> or you could time the updates with interrupts and do as much processing code you want [15:35:02] <+OmnomIRC> (O)<ztrumpet> Oh, cool! [15:35:18] <+SirCmpwn> calc84maniac: _all_ of RAM is tied up [15:35:32] <+OmnomIRC> (O)<ztrumpet> calc84, that;s how I like it [15:35:35] <+OmnomIRC> (O)<calc84maniac> okay, I have no idea what we're talking about then :P [15:35:43] <+SirCmpwn> every third frame, in a different frame than physics, I update scrolling [15:35:44] <+OmnomIRC> (O)<calc84maniac> I thought you were just talking about grayscale in general [15:35:46] <+OmnomIRC> (O)<ztrumpet> Motherload [15:35:51] <+SirCmpwn> ^ [15:35:57] <+SirCmpwn> I have a massive map taking up most of RAM [15:36:05] <+SirCmpwn> it kinda gets in the way of things [15:36:08] <+OmnomIRC> (O)<ztrumpet> calc84, Cube Droid has grayscale timed by interrupts [15:36:27] <+OmnomIRC> (O)<calc84maniac> chip's challenge does too [15:36:27] <+SirCmpwn> and the map can be modified by the user, and I don't think I want the user modifying my interrupt table ;) [15:36:32] <+OmnomIRC> (O)<ztrumpet> nice [15:36:44] <+OmnomIRC> (O)<calc84maniac> since I need 7 updates per frame, heh [15:36:52] <+OmnomIRC> (O)<ztrumpet> lol [15:36:56] <+OmnomIRC> (O)<calc84maniac> I don't want to time that manually [15:37:15] <+SirCmpwn> ztrumpet: the guts of the story is that I have an entirely different main loop on each one of three frames [15:37:17] <+OmnomIRC> (O)<ztrumpet> thepenguin'd use the crystal timers [15:37:25] <+SirCmpwn> one of them updates the screen 3 times [15:37:30] <+SirCmpwn> the other two update the screen 6 times [15:37:34] <+OmnomIRC> (O)<ztrumpet> Sir, I understand, and it's awesome [15:37:46] <+SirCmpwn> k [15:37:51] <+OmnomIRC> (O)<ztrumpet> :D [15:37:53] <+OmnomIRC> (O)<jimbauwens> ephan [15:37:55] <+leafy> Oo [15:37:57] <+SirCmpwn> any questions on the overall grayscale discussion that started this? [15:38:42] <+SirCmpwn> it's best to just sit there and put some thought into how the screen works and how grayscale works, and you'll eventually understand it if you don't already