Post subject: Adding a voxel engine to FCEUX
Joined: 10/10/2013
Posts: 38
Hello. I'm in the process of working on something experimental, and I wanted to share some of it while asking for assistance. Essentially, I am writing a voxel engine to be incorporated into the OpenGL renderer of FCEUX. It's an expansion of an idea that I had a while back when I considered doing something similar in MAME (see this thread in MAMEWorld). I found trying to demystify MAME's renderer a little too daunting, but I recently resurrected the idea and have made a fair bit of progress with FCEUX. It also only really works well with games that have a single solid color for a background (e.g. black for older arcade games, the blue sky in Super Mario Bros.) The renderer takes the color in the upper left corner and treats that as the clear color while at the same time ignoring any pixel in the image buffer composed of that color (no voxel). I have a couple of questions: 1) I'm developing within the SDL version (linux), but I'm not very familiar with scons. I see the whole bit about checking for OPENGL support and adding -DOPENGL to the CCFLAGS. Is there anyway to enforce the addition of -lGLU to the LIBS? Cuz right now I made my own script to link the resulting .o files against -lGLU, but there's got to be a way to have it work with scons. 2) Is anyone here fairly familiar with OpenGL? My lighting isn't working the way I had hoped (I think it has to do with my failure to switch matrix modes from MODELVIEW to PROJECTION, but I don't have enough experience with that. Also, my FPS is pretty poor, even though I'm using a Display List to render the voxels. 3) Would anyone on the official development team have any interest in supporting this concept and/or accepting the final result into the official source code? 4) Does the FCEUX using community at large have any interest in this project? Thanks very much for your time and assistance. Procyon P.S. I'll get some screenshots up as soon as I have some decent looking to share. Right now it just looks like blobs of blocks, and it's not very impressive. I want to attach the mouse to the movement of the camera so you can see more impressive angles.
Post subject: Re: Adding a voxel engine to FCEUX
Emulator Coder, Skilled player (1114)
Joined: 5/1/2010
Posts: 1217
ProcyonSJJ wrote:
1) I'm developing within the SDL version (linux), but I'm not very familiar with scons. I see the whole bit about checking for OPENGL support and adding -DOPENGL to the CCFLAGS. Is there anyway to enforce the addition of -lGLU to the LIBS?
-DOPENGL means to define preprocssor symbol OPENGL. So in the code, one can use:
#ifdef OPENGL
<code for opengl>
#endif
Or
#ifdef OPENGL
<code for opengl>
#else
<code for non-opengl>
#endif
Post subject: Re: Adding a voxel engine to FCEUX
AnS
Emulator Coder, Experienced player (728)
Joined: 2/23/2006
Posts: 682
This concept is rather intriguing, but personally I would do it for Windows (since the userbase is presumably larger).
ProcyonSJJ wrote:
The renderer takes the color in the upper left corner and treats that as the clear color
The correct way would be this: take the background color value from actual PPU RAM where the palette data is stored. http://sourceforge.net/p/fceultra/code/HEAD/tree/fceu/trunk/src/drivers/win/video.cpp#l657
unsigned char r, g, b;
FCEUD_GetPalette(0x80 | PALRAM[0], &r, &g, &b);
blitfx.dwFillColor = (r << 16) + (g << 8) + b;
Joined: 10/10/2013
Posts: 38
Thank you both for your replies, a couple of responses: @Ilari: Thanks for the explanation about the preprocessor, I appreciate it. However, are you aware of how I can instruct scons to include -lGLU in the list of libraries to link against? I had assumed that the OPENGL section of scons was also responsible for including -lGL, but I could not see how that was being enforced. @AnS: Presumably when I am finished, whatever code I am writing will be portable enough to employ under any platform. That's the nice thing about OpenGL, it should be the same everywhere. I'm merely more comfortable (for now) developing the initial phase of my experiment in linux. Once I get closer to a final product, I will worry about getting it running elsewhere (or ask for assistance in porting). Thanks so much for providing me with the information about the background color. I suspected that the NES might have such a concept, but I didn't know enough about the architecture to know where it might be held.
Emulator Coder, Skilled player (1114)
Joined: 5/1/2010
Posts: 1217
ProcyonSJJ wrote:
@Ilari: Thanks for the explanation about the preprocessor, I appreciate it. However, are you aware of how I can instruct scons to include -lGLU in the list of libraries to link against? I had assumed that the OPENGL section of scons was also responsible for including -lGL, but I could not see how that was being enforced.
You mean the scons script doesn't include -lGLU in OpenGL case and you need something from that library?
Joined: 10/10/2013
Posts: 38
Ilari wrote:
You mean the scons script doesn't include -lGLU in OpenGL case and you need something from that library?
Exactly. It does link in GL, but it does not automatically link in GLU, and I'd like to instruct scons to include it rather than using my own bash script.
Joined: 10/10/2013
Posts: 38
I hit another stumbling block tonight. I am trying to tie the camera movement to the mouse. I see where the line
	t = SDL_GetMouseState (&x, &y);
is called in sdl/input.cpp, and I tried tapping into it, but I could only ever get x and y updated as soon as the application started, and never again, no matter how much I moved the mouse around. Yet when I tried out Duck Hunt, it's clearly registering the position of the mouse cuz I can shoot the ducks. All I tried doing was passing the value of x and y to another method after SDL_GetMouseState is called and use those values, but they never change. Is there something that I'm missing? Thanks. I realized my own problem. I'm running in a window, so I'm forced to rely on the GTK results, not the SDL results. I was going nuts...
Joined: 7/2/2007
Posts: 3960
This is probably a stupid question, but you are calling SDL_GetMouseState each time you want new values, right? When you pass x and y to another function, they get copied by value, creating new variables in a different part of memory, that won't be modified when another bit of code calls SDL_GetMouseState.
Pyrel - an open-source rewrite of the Angband roguelike game in Python.
Joined: 10/10/2013
Posts: 38
No, no, it was entirely my fault, I was relying on the wrong values (see the edit above). I was double checking and triple checking my code to make sure that I was doing it on every update of the mouse, just didn't realize that the SDL values are only useful in fullscreen mode.
Joined: 10/10/2013
Posts: 38
A bit of progress. Not quite the quality I would have hoped for, these images never really do seem to look 3D, but that's because I have no clue what I'm doing when it comes to lighting, so everything looks matte. I need to find someone who really understand basic OpenGL lighting principles very well. Problems I'm having so far: 1) Obviously, I have a clipping issue in the back corner there, need to expand the frustum, 2) The lighting issue I mentioned earlier, can't really make it look 3D until I can make the edges reflect differently. 3) I'm only able to read the mouse with Zapper games, and only when I press click (hence the Duck Hunt shot). I need to poll the mouse continuously even in non-Zapper games. 4) Performance. Depending on how many voxels get drawn, I'm going anywhere from 10 FPS to 53. Plus, the image quality isn't even all that great... lots of jaggies. Again I think if I consulted with someone who was stronger with OpenGL, I'd be able to resolve that. Any takers?
Patashu
He/Him
Joined: 10/2/2005
Posts: 4045
re: Lighting in OpenGL, have you read The Red Book? http://www.glprogramming.com/red/
My Chiptune music, made in Famitracker: http://soundcloud.com/patashu My twitch. I stream mostly shmups & rhythm games http://twitch.tv/patashu My youtube, again shmups and rhythm games and misc stuff: http://youtube.com/user/patashu
Joined: 10/10/2013
Posts: 38
@Patashu: No, I haven't, thanks very much, I'll take a look! Fixed the mouse issue, gave me a lot more choices to play with. Some more progress (dunno how long these tinypic links last for...):
Joined: 7/2/2007
Posts: 3960
If all you want to do is pan/rotate/scale/etc the display, then the simplest approach would be to render the emulator to a texture, and then play with that on a textured quad. But I'm guessing you knew that already and have bigger plans. Is your current drawing system doing a colored quad (or cube, or whatever) for each pixel in the original display? That's probably going to be pretty slow even when compiled into a display list. My OpenGL is rusty and outdated and I've never had to push performance, but I'm pretty sure there's some mechanism for "do this operation once for each point in this provided array". Then you'd just compile a set of arrays, one per color, and tell OpenGL to draw one square (or cube, or whatever) per vertex in each array.
Pyrel - an open-source rewrite of the Angband roguelike game in Python.
Post subject: Re: Adding a voxel engine to FCEUX
Emulator Coder
Joined: 8/12/2008
Posts: 42
ProcyonSJJ wrote:
Hello. I'm in the process of working on something experimental, and I wanted to share some of it while asking for assistance. Essentially, I am writing a voxel engine to be incorporated into the OpenGL renderer of FCEUX. It's an expansion of an idea that I had a while back when I considered doing something similar in MAME (see this thread in MAMEWorld). I found trying to demystify MAME's renderer a little too daunting, but I recently resurrected the idea and have made a fair bit of progress with FCEUX. It also only really works well with games that have a single solid color for a background (e.g. black for older arcade games, the blue sky in Super Mario Bros.) The renderer takes the color in the upper left corner and treats that as the clear color while at the same time ignoring any pixel in the image buffer composed of that color (no voxel). I have a couple of questions: 1) I'm developing within the SDL version (linux), but I'm not very familiar with scons. I see the whole bit about checking for OPENGL support and adding -DOPENGL to the CCFLAGS. Is there anyway to enforce the addition of -lGLU to the LIBS? Cuz right now I made my own script to link the resulting .o files against -lGLU, but there's got to be a way to have it work with scons. 2) Is anyone here fairly familiar with OpenGL? My lighting isn't working the way I had hoped (I think it has to do with my failure to switch matrix modes from MODELVIEW to PROJECTION, but I don't have enough experience with that. Also, my FPS is pretty poor, even though I'm using a Display List to render the voxels. 3) Would anyone on the official development team have any interest in supporting this concept and/or accepting the final result into the official source code? 4) Does the FCEUX using community at large have any interest in this project? Thanks very much for your time and assistance. Procyon P.S. I'll get some screenshots up as soon as I have some decent looking to share. Right now it just looks like blobs of blocks, and it's not very impressive. I want to attach the mouse to the movement of the camera so you can see more impressive angles.
Hi there, Sounds like an interesting project you are working on. 1) Yes. You could add something like "env.Append(LINKFLAGS = ["-lGLU"])" to the SConstruct and that flag will be passed on to the linker. 2) My experience with OpenGL is very limited so I won't be able to provide much help with that. 3) I'm the SDL maintainer of fceux and I would welcome a patch for this feature. If you have some questions about the SDL codebase, feel free to drop by the fceu IRC channel on freenode (irc.freenode.net - channel #fceu). You may not get an immediate response (I idle in there) but I will see your question and respond when I get a chance. Sounds pretty cool and I wish you the best of luck with this! If I can help out at all (some of the source code is rather.. erm... mystical? heh) let me know
** FceuX SDL Developer/Maintainer ** get the latest source http://sourceforge.net/p/fceultra/code/
Emulator Coder
Joined: 8/12/2008
Posts: 42
ProcyonSJJ wrote:
I hit another stumbling block tonight. I am trying to tie the camera movement to the mouse. I see where the line
	t = SDL_GetMouseState (&x, &y);
is called in sdl/input.cpp, and I tried tapping into it, but I could only ever get x and y updated as soon as the application started, and never again, no matter how much I moved the mouse around. Yet when I tried out Duck Hunt, it's clearly registering the position of the mouse cuz I can shoot the ducks. All I tried doing was passing the value of x and y to another method after SDL_GetMouseState is called and use those values, but they never change. Is there something that I'm missing? Thanks. I realized my own problem. I'm running in a window, so I'm forced to rely on the GTK results, not the SDL results. I was going nuts...
Yup, unfortunately this is one of the headaches of dealing with two toolkits simultaneously (SDL and GTK)
** FceuX SDL Developer/Maintainer ** get the latest source http://sourceforge.net/p/fceultra/code/
Emulator Coder
Joined: 8/12/2008
Posts: 42
ProcyonSJJ wrote:
r, can't really make it look 3D until I can make the edges reflect differently. 3) I'm only able to read the mouse with Zapper games, and only when I press click (hence the Duck Hunt shot). I need to poll the mouse continuously even in non-Zapper games. 4) Performance. Depending on how many voxels get drawn, I'm going anywhere from 10 FPS to 53. Plus, the image quality isn't even all that great... lots of jaggies. Again I think if I consulted with someone who was stronger with OpenGL, I'd be able to resolve that. Any takers?
3) What mouse coordinates are you looking for? Absolute mouse coordinates or mouse coordinates in relation to the SDL surface? I remember mouse input being a mess in FCEUX but I doubt its something that cannot be resolved. I'll have to look into the code and get back to you Are you hosting the code to this publicly somewhere? If so let me know - I'd be interested in perusing the changes and try to give input where I can
** FceuX SDL Developer/Maintainer ** get the latest source http://sourceforge.net/p/fceultra/code/
Joined: 10/10/2013
Posts: 38
Derakon wrote:
Is your current drawing system doing a colored quad (or cube, or whatever) for each pixel in the original display? That's probably going to be pretty slow even when compiled into a display list. My OpenGL is rusty and outdated and I've never had to push performance, but I'm pretty sure there's some mechanism for "do this operation once for each point in this provided array". Then you'd just compile a set of arrays, one per color, and tell OpenGL to draw one square (or cube, or whatever) per vertex in each array.
You're correct about my current implementation. I have considered doing edge detection, and only rendering the sides if they bump up against the background color. That would enable me to render only a front facing square instead of all six sides if it's surrounded on four sides by a non-background colored pixel. Should result in some significant savings. Although, it may look weird if/when I add some translucency to the voxels.
"punkrockguy318 wrote:
Sounds pretty cool and I wish you the best of luck with this! If I can help out at all (some of the source code is rather.. erm... mystical? heh) let me know
Thanks so much punkrockguy, I really appreciate the support. I may just drop by on the IRC if I have some time over the weekend. Some replies: 1) Thanks so much for the info about scons, I had a feeling it was something like that. That will help me out quite a bit. 2) I'm using the absolute mouse coordinates in relation to (to be precise) the GTK window (since I'm not yet running this full screen. I'm leaving a terminal open to watch the debug output.) So GTKMouseData[0] and GTKMouseData[1] are what I'm currently using. 3) I would be more than happy to host this publicly it's just that, _a) I've never hosted code before, so if I could get your help walking me through the process, I'd be grateful. But more importantly... _b) ...this thing is a mess right now, I've hacked up stuff terribly just to hijack existing methods with no real respect paid to user settings, etc. Ultimately, when I'm done with the proof of concept phase, I'll take some time to clean it all up, give it a new home, and hopefully add some configuration settings that will distinguish this behavior as a new feature instead of hijacking an existing one. I'm at (real world) work right now, so I only work on this at night when I'm home. My current hurdle is still the lighting, and I won't be moving on to the rest of this list until I get that sorted out, but among the finishing touches I have planned, I will be trying to: 1) Expand the mouse control over the camera. Right now, it can simply move around to the left, right, up and down (it automatically zooms in/out relative to how close to the edge of the screen it gets.) I hope to add manual zooming as well, and possibly absolute positioning and roll (not sure why anyone would roll the camera, but just for fun), and also possibly the ability to swing the camera all the way around to the back side of the rendering (to see the game in reverse). 2) Add the ability to play with the size and spacing of the voxels. Right now, they are all 2x2 cubes with 0 space between them. Users should ultimately have the ability to add some space between the voxels if they wish, and fatten them up in any of the three dimensions. Fattening them up along Z (depth) should be the most interesting to play with, since that will go a long way to making the whole scene look more three dimensional. 3) Have some fun playing with the Z (depth) position of the voxels, incorporating waves into the scene while the game is playing (so it looks like ripples are crossing the scene. Could be vertical, horizontal, or diagonal. If I'm really feeling ambitious, I'll try circular out from the center... 4) Add the ability to swap the voxels for little spheres (using the glutSolidSphere method instead of my display list). More to come, hopefully tonight. Thanks again for all the responses!
Joined: 7/2/2007
Posts: 3960
ProcyonSJJ wrote:
Derakon wrote:
Is your current drawing system doing a colored quad (or cube, or whatever) for each pixel in the original display? That's probably going to be pretty slow even when compiled into a display list. My OpenGL is rusty and outdated and I've never had to push performance, but I'm pretty sure there's some mechanism for "do this operation once for each point in this provided array". Then you'd just compile a set of arrays, one per color, and tell OpenGL to draw one square (or cube, or whatever) per vertex in each array.
You're correct about my current implementation. I have considered doing edge detection, and only rendering the sides if they bump up against the background color. That would enable me to render only a front facing square instead of all six sides if it's surrounded on four sides by a non-background colored pixel. Should result in some significant savings. Although, it may look weird if/when I add some translucency to the voxels.
Yeah, I wouldn't rush into hacks like that just yet. Consider also that you might want to try e.g. a beveled voxel mode (where each pixel is "rounded" at the edges). Keep things pure for now. You should take a look at glDrawElements. I think that's the function I was referring to earlier where you just hand it an array of vertices and it does a bunch of drawing for you. All you need to do is call it with GL_TRIANGLES and an array of vertices that specifies all the triangles you want (presumably 12 triangles per voxel, so 36 verts per voxel). I think your workflow then would look something like this:
Arrange all displayed pixels by their color
for color in colors:
  vertArray = []
  for pixel in pixels of that color:
    pixelVerts = generate vertices for a voxel at pixel's position
    append pixelVerts to vertArray
  glColor3fv(color)
  glDrawElements(GL_TRIANGLES, number of pixels * 12, GL_UNSIGNED_INT (probably), 0)
No guarantees that this will actually work; I'm no OpenGL expert. But it seems like the path you'll want to be taking to improve your performance.
Pyrel - an open-source rewrite of the Angband roguelike game in Python.
Joined: 10/10/2013
Posts: 38
Derakon wrote:
Arrange all displayed pixels by their color
for color in colors:
  vertArray = []
  for pixel in pixels of that color:
    pixelVerts = generate vertices for a voxel at pixel's position
    append pixelVerts to vertArray
  glColor3fv(color)
  glDrawElements(GL_TRIANGLES, number of pixels * 12, GL_UNSIGNED_INT (probably), 0)
That's a really interesting idea, I definitely see how it would generate some savings. I wonder, however, if the savings gained would be lost in the process of sweeping through a 256*256 buffer several times in search of particular colors. Perhaps the vertArray should be a two dimensional array, one array for each color, and the whole buffer gets processed once, dropping vertices into each "paint bucket" so to speak as unique colors are encountered. Definitely something to consider. Edit: Nevermind, I see what you mean by "Arrange all displayed pixels by their color" now. That would essentially sweep through the buffer once and organize a list of all pixels that correspond to each color, then I build a vertArray from those lists, effectively accomplishing the same thing.
Joined: 10/10/2013
Posts: 38
So, adding normals to your surfaces sure goes a long way to help lighting out :) I had the lighting all right, I just didn't set the normals on any of my surfaces. Truth be told, for some reason I thought they were calculated automatically, but I have no idea why I thought that... Still not all the way done messing with lighting, but I consider this is a huge step of progress:
Patashu
He/Him
Joined: 10/2/2005
Posts: 4045
Yeah, looking good. Now try messing around with defining ambient, diffuse and specular lighting separately. You could even have the light source(s) such as the 'sun' slowly rotate, have acceleration/momentum or respond to player input in some way.
My Chiptune music, made in Famitracker: http://soundcloud.com/patashu My twitch. I stream mostly shmups & rhythm games http://twitch.tv/patashu My youtube, again shmups and rhythm games and misc stuff: http://youtube.com/user/patashu
Joined: 10/10/2013
Posts: 38
Patashu wrote:
Yeah, looking good. Now try messing around with defining ambient, diffuse and specular lighting separately. You could even have the light source(s) such as the 'sun' slowly rotate, have acceleration/momentum or respond to player input in some way.
That's a great idea, I never thought of that. I will have to come up with some way to incorporate that. I added the wave effect and it's pretty funny, albeit a little disorienting. If I a) had a YouTube account and b) knew how to record from my own screen, I'd post a video of it running, but neither case is true for me. I should work on correcting that. This is definitely coming rapidly out of the "proof of concept" phase. As far as my previously mentioned plans go: 1) I tried to add a g_signal_connect on "motion-notify-event", but it will only read the mouse when a button is held down for some reason :( I was hoping it would work whether I press the button or not. Definitely a discussion to have with punkrockguy on the IRC. 2) I'm pretty happy with the voxels having more depth than width and height. It heightens the 3-D effect. But I'll still try to make it user definable. 3) Like I said, got the waves going. Pretty funny to watch. I'll find a way to make that user configurable as well. 4) I tried replacing the voxels with spheres using glutSolidSphere, but that was kind of a disaster. Slowed things way down, and the visual effect wasn't even that great. So that idea is out. Once I get the code considerably cleaned up, I'd like to get this up somewhere public so that you can all try it out for yourselves. I'll try to meet up with punkrockguy over the weekend and set something up for everyone.
Joined: 10/10/2013
Posts: 38
Forgot to provide some new pics. Who says you need a 3DS to play Mario in 3D? http://i43.tinypic.com/i6invm.jpg Fun with waves! http://i40.tinypic.com/2d8kvhk.jpg
Joined: 7/2/2007
Posts: 3960
Looking good! I dig the wave effect; now you need to do a circular ripple. :) Spheres are gonna be expensive; they have massively more surfaces in them than cubes do. A UV sphere with only 6 circumferences and 6 great circles would have, if I did the math right, 98 tris in it.
Pyrel - an open-source rewrite of the Angband roguelike game in Python.
Patashu
He/Him
Joined: 10/2/2005
Posts: 4045
Some ideas 1) Turn on anti-aliasing and fog: http://www.glprogramming.com/red/chapter06.html 2) Make ambient light lightly tinted the same colour as the background colour (similar to how on Earth, since the sky is blue, shadows are slightly tinted blue) 3) If you aren't using display lists yet, you can get a big performance boost by using them: http://www.glprogramming.com/red/chapter07.html
My Chiptune music, made in Famitracker: http://soundcloud.com/patashu My twitch. I stream mostly shmups & rhythm games http://twitch.tv/patashu My youtube, again shmups and rhythm games and misc stuff: http://youtube.com/user/patashu