News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

3D effect by accident {now working}

Started by thomas_remkus, June 06, 2007, 03:26:12 AM

Previous topic - Next topic

thomas_remkus

I have been working on a project to better understand how to do things I already know how to do in C/C++. My painful education of loops has really been fun, but I created this effect that I wish I hadn't.

Here is my code (posted below). I am trying to really just average my pixels together at this point but I seem to be pushing them around. This creates the fun effect ... Argh! it's not what I was trying for. Is there an op-code-rule I'm missing or just not understanding?

Please note that I am just trying to get this to work. No super optimized, just working. So if help can just point me at how I've mistakenly created this effect I'll optimize later (most likely with forum help).


; this code has been removed because a later posting by this author has a working version of the desired output


Tedd

To see what's going on:
- reduce the timer to about 20ms
- comment out drawing of the 'cross lines'
- change the inside of the ball to yellow
- build & run, move the ball around
- notice the red goes one way, blue goes the other, and green is unaffected {this is partly because of which you've commented out in the summing code}


* check which pixels you're actually copying into the "pt" array (big hint: you're taking the wrong offsets into diPix)
* don't average over an odd number of pixels - it seems the rounding error causes noise to appear and mess it all up;
  either do just the four sides (top, bottom, left, right), or the eight sides+corners {..or any even combination to get some interesting effects}



And I think you could make use of these :wink
RGB_BLACK       equ 0000000h
RGB_DKGRAY      equ 0404040h
RGB_GRAY        equ 0808080h
RGB_SILVER      equ 0c0c0c0h
RGB_WHITE       equ 0ffffffh
RGB_MAROON      equ 0000080h
RGB_RED         equ 00000ffh
RGB_LEAF        equ 0008000h
RGB_GREEN       equ 000ff00h
RGB_NAVY        equ 0800000h
RGB_BLUE        equ 0ff0000h
RGB_OLIVE       equ 0008080h
RGB_YELLOW      equ 000ffffh
RGB_TEAL        equ 0808000h
RGB_CYAN        equ 0ffff00h
RGB_PURPLE      equ 0800080h
RGB_MAGENTA     equ 0ff00ffh

No snowflake in an avalanche feels responsible.

daydreamer

I use olly to singlestep and see where regs behave like you intended and where it goes haywire when your regs have values you don't intended they to have, there you can pinpoint exactly where it goes wrong
but a little harder with your code which has lots of apicalls, compared to mine more lowlevel approach with ddraw

thomas_remkus

I don't feel that it's the APIs that are causing me issues here. I think it's the loop and the understanding of how to get the correct pixel information so I can average the area. Frankly, it's causing me much heartache but I'm staying with it. If I go a few more days with just banging my head against the wall I'll respond here with a bloody forehead requesting more help. As it stands, Tedd is pointing out some very valid points that I am focused on (maybe too much as I should be working ... and not on this) and I think I have made some minor corrections.

I'll post here some of the changes so far:


;upper left
mov ebx, diPix[eax]
mov pt, ebx
;upper
mov ebx, diPix[eax + 4]
mov pt[4], ebx
;upper right
mov ebx, diPix[eax + 8]
mov pt[8], ebx
;left
mov ebx, diPix[ecx + 4]
mov pt[12], ebx
;origin
mov ebx, diPix[ecx]
mov pt[16], ebx
;left
mov ebx, diPix[ecx - 4]
mov pt[20], ebx


... the above has made the calculations better and it's more focused on the right pixels I think.


xor eax, eax
mov al, pt[0].colors.red
add ebx, eax
mov al, pt[4].colors.red
add ebx, eax
mov al, pt[8].colors.red
add ebx, eax
;mov al, pt[12].colors.red
;add ebx, eax
mov al, pt[16].colors.red
add ebx, eax
;mov al, pt[20].colors.red
;add ebx, eax
;mov al, pt[24].colors.red
;add ebx, eax
;mov al, pt[28].colors.red
;add ebx, eax
;mov al, pt[32].colors.red
;add ebx, eax
mov eax, ebx
;shr eax, 1
mov ebx, 4
div ebx


... the above code is working better and I can average more pixels for a better response.

But other than that I don't have anything significant. I'm going to create a backup and really break this down and see if there was something I'm just tripping over. For some reason I'm getting enough of what I want but when I try for a little more I either get static or I get a hard crash.

thomas_remkus

Tedd, with your nudging I was able to locate much about my code that need modifications. Now, I'm not sure why I can't use the origin pixel and div by 9 but that's really not too concerning right now. I have basically the exact same project now in MASM as I did with my prototype in C/C++ and now it's time to see what the difference in performance is.

I'm including my final code, for what *I* was able to accomplish with help, so others can check it out, offer suggestions, and maybe learn from my efforts. Thanks for the help!!

[attachment deleted by admin]

Tedd

A few adjustments/fixes/comments here and there..

The main issue was that you was off by one on many of the calculations, meaning you wasn't averaging all the pixels (skipping the very first and last) and the top/bottom row blanking crept one pixel onto the next row. {If you want to check this for yourself: fill the whole buffer with white, blank the rows in gray, and force the average of every pixel to come out red (though without fixing the "PixRGB" struct, it comes out blue).}

(most of) my changes labelled with ";**"

Nice work otherwise :U

(...now to clean it up and make it burn! :bdg)


[attachment deleted by admin]
No snowflake in an avalanche feels responsible.

thomas_remkus

Tedd, thanks for all the help! I didn't even think about this being off by one. I did notice some more that was wrong but it wasn't the "off by one" issue. Thanks for your help. I also like the way you used "dec" and your "shl ., 3" for division by 8 ... that was nice too!

Red vs Blue ... I didn't even think about that and because it was being used I just sort of didn't matter. Thanks for correcting that. I will study these changes and add what I have done last night (long night trying to get more into this project and understand what's going on).

I must say, this is much harder than I expected but I'm so hooked. It's like programming crack without the side effects. Well, actually, it does have some side effects: I'm boring all my friends with this toy and thinking on how I can do more, More, MORE in MASM. I am very grateful for all the continued help! My next post should have this updated and more corrected. I still don't know why I can't use the middle pixel. Is it just not allowed for division by 9?

Tedd

That's why I labelled them as "off-by-one" - it's such a common mistake that people rarely even realise, it has its own name!
Learn how to test your code, even when you think it's correct and it looks like it works :wink

The thing with the middle pixel, isn't the middle pixel itself - there's nothing too special about it - you can use it if you want. It just seems to be a side-effect of this effect that if you average over an odd number of pixels then it comes out messy (it may even jsut be the magic number 9 - I haven't really tested extensively.) You can still use the middle pixel and average, say, (top+left+middle+right)/4, which gives a drifting effect; you can play about with the combinations to get different results - including the orginal 'mistake' you made in the first instance (red component dirfts one way, blue drifts the other.. and what the hey, green another :lol) The thing with the middle pixel is that it's still used as an edge pixel for all of the other pixels around it, so the fact you 'ignore' it in the one instance where you're averaging that pixel itself doesn't actually spoil the effect.

As for other things you can do with it.. as far as the effect itself goes, that's about it. You can vary the 'drifts', and maybe do some weird things like averaging in a checkerboard pattern (can give a fairly good smoke effect).. It can be done with a 256-colour palette insted, which gives some quite nice effects if you choose the right palette - rather than just fading red through red, you can fade the colours through the rainbow, or set a nice 'fire' gradient and fade through that.
For your program, maybe some fireworks or 'sparks', or see what happens when two objects get too close to each other and their aurae merge..
Show the mouse pointer, get rid of the 'ball', and then have it draw on a left-button press (and change colour on right-click?) Which will allow you to test the effect better and see how it 'reacts' to different shapes.. (One adjustment to this is to NOT average pixels with a 255 component - which will allow persistent shapes, though they will still glow as their neighbours are still averaged to include them.)
Basically just play until you stumble on something :toothy
No snowflake in an avalanche feels responsible.