ProcyonSJJ already mentioned they were using display lists earlier on. I think it's just the drawing of thousands of cubes one by one that's causing problems, which is why I suggested using glDrawElements.
Of course, it could also be that some non-drawing aspect of the code is being slow; I guess the question is how slow things are when the game is paused but the view is manipulated.
Pyrel - an open-source rewrite of the Angband roguelike game in Python.
Lol, so it turns out my performance is actually just fine. I'm running Ubuntu on a laptop with the nVidea Optimus technology that shuts down the 3D acceleration to preserve the battery life unless you specifically ask for it. All this time, I forgot to add "optirun" to the command line, so I was not using 3D acceleration. Once I remembered to do that and tested the software, my FPS were much higher. Not always 60, but usually close. Obviously, this code will require 3D acceleration to be any good, but just about everyone who tries this will likely have that, so I'm not too worried. Obviously, it could still be optimized, but it shouldn't be terribly necessary just to get decent performance.
@Derakon: Would love to do a circle if I could figure out the math for that. Horiz/Vert/Diagonal waves are simple arithmetic. Can you think of a good formula to use based on n frames?
@Patashu: Anti-aliasing and fog would be great, I will work on adding that. Tinting the Ambient light is a great idea, I will work on adding that too. And like Derakon confirmed, I am using Display Lists for each cube (I took out the backface... seemed kind of pointless.)
Procyon: for a circular ripple effect, your Z displacement should be based on your distance from the center of the ripple. Something like
z = sin(sqrt((x - cX)^2 + (y - cY)^2) + n / pi)
where x and y are the pixel location and cX/cY are the center of the ripple, and n is the frame number. You might not even need the sqrt; I think that removing it would mean that the ripple density would increase as you get further away, though, which is kind of counterintuitive. Bet it'd look neat though.
Glad to hear you got the performance issues sorted!
Pyrel - an open-source rewrite of the Angband roguelike game in Python.
In order to map the wave properly to a circle, I'd probably still need square and sqrt, or the ripples would come out from the center in a diamond.
Thanks, I was really beginning to wonder what I was doing that was so intensive that a 2012 model GeForce couldn't really handle.
Float operations aren't as expensive as you think - don't avoid using sin, cos, sqrt, tan, atan2, etc until you've determined it's a performance bottleneck.
Joined: 4/17/2010
Posts: 11475
Location: Lake Chargoggagoggmanchauggagoggchaubunagungamaugg
Please unembed that wide picture.
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting.
OK, I've done so, but... why?
A quick update, got a lot of performance increases just by optimizing the code and pulling out one-time calculations that I stupidly left inserted inside the rendering loop. Wrote an email to an OpenGL guru to ask how to improve the lighting/reflection, and what to do about the moire artifacts that I see when there a huge number of voxels drawn on the screen.
Here's another quick snapshot. The effect with SMB3 is weird because most of the sprites are outlined in black. So you don't really get a sense of the lighting. I'd embed the picture like I did the others, but I don't want to violate any rules... if such rules exist?
http://i43.tinypic.com/33ll73a.png
Not everyone has wide display (and browser set to wide enough), the effect if it isn't is very annoying.
Understood. Just a quick update, I have a beta version of the code ready to go. It correctly incorporates itself into the rest of the SDL code, and has a single checkbox to turn the voxel engine on and off. Ultimately, I would like to have a separate dialog where you can set various settings including:
That will be in version two, but the main goal tonight was just to make sure that I could include the code cleanly into the existing code base without hijacking any methods. So far so good. I went on IRC to see if punkrockguy was around, but no dice.
Wait, are you still using that wrong method of getting background color, or sample means something else?
Yeah, I meant to update that point: I tried the method you mentioned AnS, but unfortunately, it didn't work. Not because you gave me the wrong information, but rather because I guess developers didn't use that information correctly. For example, in Super Mario Bros., the background fill color is black even when most of the background sky is blue. So unfortunately, it didn't work in many cases.
It could still be a possible setting though. In case people don't want to try and pick a coordinate, they could try their luck with the system BG color, and see if it matches and produces a good result. In my experience though, if the background wasn't strictly black, most games didn't really do a good job setting that color.
Another option you could try would be using the current most-common color as the background color. Obviously this won't work in all situations, but I don't think there is a solution that will work in all cases.
Pyrel - an open-source rewrite of the Angband roguelike game in Python.
For example, in Super Mario Bros., the background fill color is black even when most of the background sky is blue.
No, in SMB the background fill is blue (and black in World 3-1, etc).
You can check this by running Windows version of FCEUX and resizing the window.
Although, yes, there are games where most of screen pixels are drawn using different color, so there should be a way to specify BG color manually. But default value should be taken from PPU.
ProcyonSJJ wrote:
In my experience though, if the background wasn't strictly black, most games didn't really do a good job setting that color.
You know what, I might not have done it correctly the first time. I gave it another shot, and it seems to be working better this time. That being said, it's still a case of being great for some games, and not for others. For example, most Mega Man games just leave the BG color black. So even when I play, say, the first Mega Man, the boss selection screen is rendered as one giant blue block against a black background. When I select Bomb Man, whose stage is predominantly blue sky, it's the same effect. Whereas the Super Mario Bros. series uses it correctly. I guess Nintendo just used the feature more consistently than other companies.
So AnS' technique works better for some side scrollers (SMB, Gradius) and worse for others (Mega Man), which means I'll probably still need to find a way to implement both solutions (system BG color vs coordinate sample) and have it configurable to the user. Unfortunately, games like Zelda 1 and map-heavy RPGs like Final Fantasy or Dragon Warrior just don't make suitable candidates for this effect. I was wondering, however, about another possible experimental mode which I'll describe below.
Current issues
At the moment, my biggest problem is tracking the mouse. This is important to have full control over the camera. Right now I can only reposition the camera when I hold a mouse button down. I was hoping to read the mouse whether the button was pressed or not, so that the camera could be moved around on the fly. I added:
to sdl/gui.cpp but like I said, it will only work if a mouse button is held. Punkrockguy, if you know anything about this, please let me know. Also, I need to start talking with you about how to host the code so that others can start playing with this and beta testing it.
For now, a little sign of progress. It's not much, but it's coming along:
Experimental thought
For games like Zelda, and others that have a top-down or birds eye view, I was thinking of another way to deal with the 3D effect. I imagine the emulator must know when it is rendering a background object versus a player or enemy sprite. If that is the case, it might be possible to have a secondary 256*256 buffer that serves as a depth buffer. Even if it's just 0 for bg and 1 for fg, that would be enough info to let the renderer know that a fg object should be drawn at a depth closer to the camera, so that it "floats" above the background. Any idea if that's easily doable? Without screwing up the emulation too much, because this is the only feature that could possibly take advantage of it.
For example, most Mega Man games just leave the BG color black.
Actually, even they use BG color, just not as a "skybox" fill. For example, I remember, in Megaman 2 screen flashes for a frame when using Flashman attack, and when you receive an item from Dr.Light:
So, I guess most of time you'll need to filter out voxels of two colors: of the BG color and of the predominant color.
BTW, the predominant color is better stored not as some coordinates of a pixel, but as an index of the palette entry (e.g. PALRAM[6]). Of course user should be able to define this index by simply clicking screen (then the program retrieves the pixel at these coordinates and finds out which palette entry the pixel uses at the moment). This method will work even in side-scrollers.
ProcyonSJJ wrote:
For games like Zelda, and others that have a top-down or birds eye view, I was thinking of another way to deal with the 3D effect. I imagine the emulator must know when it is rendering a background object versus a player or enemy sprite. If that is the case, it might be possible to have a secondary 256*256 buffer that serves as a depth buffer. Even if it's just 0 for bg and 1 for fg, that would be enough info to let the renderer know that a fg object should be drawn at a depth closer to the camera, so that it "floats" above the background. Any idea if that's easily doable? Without screwing up the emulation too much, because this is the only feature that could possibly take advantage of it.
This is not easily doable, as it requires a certain code injection in the core (ppu.cpp).
Once you successfully implement everything else, I can take the risk of carefully doing this.
Actually, even they use BG color, just not as a "skybox" fill.
Ah, you are correct. Well, you'll be able to see in the options below that I worked out a way to make the color selection configurable.
AnS wrote:
So, I guess most of time you'll need to filter out voxels of two colors: of the BG color and of the predominant color.
I don't see how that's possible to do. Only one color can be used as the fill color. In the SMB3 example, you pretty much have to go with the sky color and then run into a "sea" of black voxels at the end (unless you use my original method of choosing a sample coordinate, which allows the fill color to be more dynamic based on what's happening on the screen.)
AnS wrote:
BTW, the predominant color is better stored not as some coordinates of a pixel, but as an index of the palette entry (e.g. PALRAM[6]). Of course user should be able to define this index by simply clicking screen (then the program retrieves the pixel at these coordinates and finds out which palette entry the pixel uses at the moment).
I like this idea, and would like to try to implement it after "version 1" of this is released.
AnS wrote:
This is not easily doable, as it requires a certain code injection in the core (ppu.cpp).
Once you successfully implement everything else, I can take the risk of carefully doing this.
I figured as much. Again, this would be more a of "version 2" idea. Here's a screenshot of the completed voxel config dialog. Enough options for everyone?
Everything is plugged in and working. Though, truth be told, Transparency sucks. I don't know if it's due to the way I set OpenGL or what, but all it seems to do is reduce the quality of the picture. It doesn't do what I hoped it would do, which would be to make the voxels more "crystalline" in appearance. As for wave choices, you can pick Horizontal, Vertical, and both \ and / diagonals. I'm still using my cheesy pre-mapped wave method. Derakon, I'll get circle waves in for v2.
This thing is nearly complete. At the moment my three biggest hurdles are:
1) lack of solid control over polling the mouse, to allow for better camera control.
2) too many hard-coded values for the screen size. I've been doing 100% of my testing in 1024x768 windowed, and haven't tried anything else. I need to start making the code more flexible, and to read the values that are currently being used for screen resolution, etc.
3) Providing a good way for everyone to access the source code.
BTW, AnS, I started to look over the Windows specific code, and I realize that it's using DirectDraw, but not Direct3D, which makes perfect sense. But the lack of a proper 3D interface upon which to implement this means it may forever be an SDL-only feature. My knowledge of D3D has always been poor, and substantially weaker than my knowledge of OpenGL. A Windows solution may only come about through a willing volunteer who can undertake the port.
So, I guess most of time you'll need to filter out voxels of two colors: of the BG color and of the predominant color.
I don't see how that's possible to do. Only one color can be used as the fill color.
I mean, use one color as the fill, but remove voxels of both colors.
ProcyonSJJ wrote:
Though, truth be told, Transparency sucks. I don't know if it's due to the way I set OpenGL or what, but all it seems to do is reduce the quality of the picture.
Have you tried more ideas, like making the transparency depend on the distance from camera (so that nearest voxels are more transparent), or making the face of voxels to be more opaque than sides and backface?
ProcyonSJJ wrote:
It doesn't do what I hoped it would do, which would be to make the voxels more "crystalline" in appearance.
As far as I understand the effect, it's more about the play of light, not about actual transparency. Instead of simple transparency it is translucency that makes magic (and some advanced lighting + shaders, which I don't know anyway).
ProcyonSJJ wrote:
BTW, AnS, I started to look over the Windows specific code, and I realize that it's using DirectDraw, but not Direct3D, which makes perfect sense. But the lack of a proper 3D interface upon which to implement this means it may forever be an SDL-only feature. My knowledge of D3D has always been poor, and substantially weaker than my knowledge of OpenGL. A Windows solution may only come about through a willing volunteer who can undertake the port.
That's too bad. I hoped the engine could gain some popularity among casual players.
I mean, use one color as the fill, but remove voxels of both colors.
But if we did that, in the SMB3 example, the stage would not end in black, it would continue to be the color of the sky.
AnS wrote:
That's too bad. I hoped the engine could gain some popularity among casual players.
I didn't mean to sound so pessimistic, I think it certainly could be ported to Windows specific code relatively easily. On the one hand, SDL and GTK libraries are available for Windows, so that's one route. On the other hand, OpenGL can play just as nicely with DirectDraw as it can with SDL, so that's always a possibility. That would make the port even simpler. I think it can and will happen, it's just a matter of finding the right assistance.
But if we did that, in the SMB3 example, the stage would not end in black, it would continue to be the color of the sky.
Well, there, if user prefers to see a sea of black blocks, he can uncheck the 2nd option ("Hide voxels using the palette of sample pixel"). So everyone will be able to choose whatever he considers the lesser evil. For example, I think omitting the black ending entirely isn't as bad as the sea of black voxels.
Your method of sliding pixel may solve this specific situation, but the color will change abruptly (from blue to black) and user will see first the approaching sea of black voxels and then suddenly the sea of blue pixels... IMO it's better to remove both.
ProcyonSJJ wrote:
I didn't mean to sound so pessimistic, I think it certainly could be ported to Windows specific code relatively easily. On the one hand, SDL and GTK libraries are available for Windows, so that's one route. On the other hand, OpenGL can play just as nicely with DirectDraw as it can with SDL, so that's always a possibility. That would make the port even simpler. I think it can and will happen, it's just a matter of finding the right assistance.
Glad to hear! I guess it's the matter of scale. It's always like this. It's pretty easy to make a proof of concept or a prototype to show friends, but once we start considering wider public, the new scale of the project suddenly brings us some unexpected tasks, like the need to think about UI and performance, to obey some 3rd-party code licenses, to write portable code, to write documentation, and, in general, to learn new stuff.
HUGE progress tonight with one very tiny accomplishment: I got the mouse polling to work without having to press the mouse button. It was an aspect of GTK that I was very unfamiliar with, mouse polling is initially disabled until you make a call like:
Took a lot of Googling but I finally figured it out. As a plus, I also got scrolling working, so zooming in and out works great! Now I really feel like I have good control over the camera.
(As a side note, this could lead to the addition of a crosshair in the SDL version for Zapper games, should anyone be inclined to add one.)
Anyway, current limitations thus far are:
1) I realize now that the resolution of the window is determined by the X and Y scales in the configuration. The only reason I've been testing in a 1024 x 768 window is because I had X and Y set to 4.0 and 3.0 respectively. That may not be ideal for viewing the voxels, but I'm not sure what else to base the window size upon. AnS, do you have any thoughts about this?
2) Mouse/Camera controls work great in window mode, not so much in full screen mode. I need to tackle that side of things as well.
3) The aforementioned issue with the lighting and general look of the voxels, but my hope is that once the code is released into the wild, someone with more OpenGL experience will be able to enhance the look of things.[/code]
Edit: I absolutely have to get some screen video recording software on here and start taking movies of this stuff to put on YouTube. I will get working on that ASAP.
1) I realize now that the resolution of the window is determined by the X and Y scales in the configuration. The only reason I've been testing in a 1024 x 768 window is because I had X and Y set to 4.0 and 3.0 respectively. That may not be ideal for viewing the voxels, but I'm not sure what else to base the window size upon. AnS, do you have any thoughts about this?
Ideally, the window should be freely resizable (also don't forget about saving the size/camera angle/position and other settings to config file). Something like 1024x896 (considering 256x224 as a native resolution of NTSC NES) sounds like a good default value, but users should be able to both increase and decrease the size.
ProcyonSJJ wrote:
3) The aforementioned issue with the lighting and general look of the voxels, but my hope is that once the code is released into the wild, someone with more OpenGL experience will be able to enhance the look of things.
Well, I wouldn't rely too much on the help. To get people so interested in your project (up to the point of contributing), you have to make it already valuable from the initial release. So I suggest adding a bit of polish.
Ugh, every single f-ing screen recorder I tried crashes. I tried Kazam, RecordMyDesktop, VokoScreen, and RecordItNow. Every single one of them dies on me mid-way through. I don't know if it's because I'm tapping the 3D acceleration and there's not enough processing power left to buffer the video or what. Tempted to just hold the camera on my phone up to the screen, but I'm afraid that will give a crummy image. Does anyone have any other ideas?
Have you tried:
Open Broadcasting Software
xsplit
Camtasia
Camstudio
Fraps
If you still can't get anything to work, what OS, video card and video driver + version are you using?