Posted on 11/27/2015 - 17:18
So, ah, looks like my "trusty" old MacBook Pro may have gone to the big Apple Store in the sky.
As I was browsing a twitter feed during lunch, the video glitched out and froze the machine. Hard-resetting resulted in a glitchy-looking Apple boot screen, then the "Kernel Panic" message. Several hours of research and debugging steps later, I may have to call it: my GPU is fried.
Unfortunately, it's in that sweet spot of repair cost ~= replacement cost. And even then, I'd have a "new" MacBook Pro with the same possible issue. (Faulty nVidia 8600)
This laptop was how I made Mac and Linux builds for NEO Scavenger. I could probably find another way to do it with my desktop, but this MacBook also was one of those machines that ran OSX/Windows 7/Ubuntu with a triple boot setup, and that was a killer feature for working away from home. And besides, it helps to have a natural Mac for testing Mac-specific things (e.g. trackpad, hardware weirdness, etc.)
Soooo, I'm looking at options. I could try to get a new MacBook and set it up similarly. This'd likely be $1200-2000. I could also try to replace exactly what I had (2008 model), which will probably run about $500. There are also "Hackintoshes," which are non-Mac machines loaded with OSX. These tend to be cheaper, since one can buy non-Mac hardware. But they are also more dodgy in their support of OSX. Plus, they wouldn't allow me to test Mac-specific issues as well (and might even cloud my testing).
This was not the problem I hoped to be tackling today. I hoped to be working on shader and lighting stuff. I only barely got some of that done, but not much more to show. (I did happen to see some old OpenFL shader example code with new eyes, so to speak. I may have missed some tricks they did when I first saw them because I was still figuring out how OpenGL worked.)
Anyway, kind of a downer to end the week on. But hey, could be worse! Anyway, have a good weekend!
Posted on 11/26/2015 - 17:14
Hey Folks! Those of you following my Twitter account (@dcfedor) may have already seen hints of this, but it appears I've got the OpenGL lighting shader working in the ship editor!
Above, I've split the screenshot down the middle with flat-shaded HaxeFlixel sprites on the left, and the OpenGL normal-mapped shader sprites on the right. Essentially, the right side is a 3D scene with a dynamic light near the mouse and ambient light everywhere else.
I can place and remove prefabs, and both the HaxeFlixel and OpenGL sprites will add/remove to the scene accordingly. And I've even hooked up the OpenGL view matrix to the WASD scrolling in the editor, so both will scroll the same amounts, keeping things lined-up. Looks pretty neat so far!
For anyone interested, a simple HaxeFlixel project source code to do this can be found here.
However, it's not without its flaws.
For one thing, you can see that the z-sorting is wrong, so some sub-structure stuff appears above the floor, and walls are hidden by sub-structure, etc. Weird that this is an issue in the 3D scene, but I think I may have the depth-sorting feature turned-off. So this may be solvable via a simple switch (since each prefab has a z-value already for layer-hiding purposes, and I can just use this).
Secondly, performance is a bit rough. I'm getting maybe 21fps with debug code on Windows in this scene. And this scene is probably a bit simpler than the final scene complexity I'm picturing. Now, performance is usually slow at first in a project, and I have a lot to learn about optimization. But this was the best I could get with quick optimizations to the code. "Release" mode in windows is 60fps, so that's encouraging. But it'll dip down into the 40s with just a few dozen more parts on-screen. I might have to learn a lot more about OpenGL to make this work, or else explore the OpenFL implementation of GL to see if I can leverage that instead. (My code kind of bypasses the "right" way to do things in OpenFL.)
Thirdly, this nice-looking lighting ignores shadows. Nothing is in place yet for walls blocking light. There are ways to do this, and with this shader framework in place, it might be doable. But again, not there yet.
Finally, while it looks nice, I'm not sure if it looks that nice. The subtle shading is pretty, but I was expecting more highlights on the walls. This could be down to the way I hand-drew the normal maps, since they have razor-thin "edges" drawn-in.
It's progress, but it'll warrant some careful consideration of the pros vs. cons.
Oh, and Happy Thanksgiving, all!
Posted on 11/25/2015 - 10:16
From now until December 2nd, NEO Scavenger is 50% right here at the official site!
The purchase price includes DRM-free downloads, one Steam key, and the browser version, so you can play anywhere, anytime you want!
This is actually the first time I've offered a discount at the official site, and it is a bit of an experiment to see how it works. If you have any trouble with it, or any other feedback, let me know!
Posted on 11/24/2015 - 17:21
I decided to stress test my normal-mapped OpenGL project today, to get an idea for how feasible it would be. For reference, my early estimates on ship complexity are about 200 sprites. That's a ship larger than the screen, about the scale of the Millenium Falcon for crew of 32-pixel diameter. And that ship has skeletal beam sprites underneath floor and wall sprites.
The test setup was using the same 512x512 cushion texture with diffuse and normal maps, and the point light plus ambient light shader I showed yesterday. Using the neko VM, I was able to get about 300-350 sprites before framerate dipped below 60. Not bad! Neko, though, is mainly for testing purposes due to its quick compile time. The VM makes it a bit slower than native apps.
Switching to a native Windows target in release mode, I was able to get 1350 sprites with 54fps. I think I can work with that :) Scaling it down to 500 sprites kept framerate pegged at 60, so I think it'll work.
Now the tricky part: how do I integrate this with the ship-building and simulation prototype I've been making in HaxeFlixel?
The stuff I've been doing is raw OpenGL. HaxeFlixel abstracts a lot of that to make things simpler, and to protect me from doing dumb things that break on certain platforms. And realistically, HaxeFlixel would probably run faster than what I could write in raw OpenGL. But the problem is that it doesn't support the arbitrary shader code that I've written for this lighting.
OpenFL (note, not GL, FL) is the medium-level code that HaxeFlixel is built upon. And it's also where I wrote my raw GL code. So in theory, there's a way to smush these together.
So far, however, I haven't seen a clean way to do so. I could probably get my ship code to initialize a GL sprite at the correct position and orientation, and shim an GL render call in there when the HaxeFlixel stuff renders. But I'm not sure how those would layer. (Probably HaxeFlixel on top of GL, at a guess.)
But then, I worry that my raw GL code is going to fall apart as soon as it goes to, say, Linux, or Android. In theory, it should be okay, since OpenFL is designed to catch this stuff. But I'm not sure if I'm using OpenFL correctly. Like, are there certain conditional compiler branches that OpenFL does behind the scenes when using its built-in sprite stuff? Branches that I'd be missing if I skipped OpenFL's sprite.shader technique, and just jammed vertex arrays and shaders straight into GL?
That's where I am now. And this is pretty virgin territory. Little, if any documentation is out there on doing this in HaxeFlixel. I know of a few out there doing experiments with this, and even OpenFL/HaxeFlixel devs on github are building better tools for this. But I'm just kinda bobbing on a rickety scaffold I cobbled together from moldy blueprints I pieced together from various sources.
I hope I don't fall :)
Posted on 11/23/2015 - 17:24
Hey Folks! Hope everyone had a good weekend. I kept meaning to sit down and work on an RPG design presentation for a possible developer's talk, but I barely would get into it when baby stuff came up. Such is parent life :)
Conversely, I did manage to finally sort out a working lighting shader in OpenFL using OpenGL Views. Almost another day passed with little success, and lots of my wrestling with transforms. Every time I'd suspect I found an error in the shader, it'd still turn out wrong. And all of the debugging tricks I could think of (rendering colors based on direction, distance, etc.) weren't yielding any answers.
But in the afternoon, I finally broke-down and decided to try rewriting the shader in world space to start debugging it. (This tutorial, for those interested.)
Thinking the removal of view-space would uncomplicate things a tad, I fired it up...and it worked?
I was dumbfounded. I still am, a bit. I mean, it seemed like everything I was doing before was by the book. As far as I can tell, I must've been doing something before that was world-space instead of view-space, and now that the shader was setup for world-space, things worked. And in all likelihood, it was the setup of one of my transform matrices in the app, or the TBN matrix in the vertex shader.
Whatever the case, here's what I've been striving for:
This whole thing screams Disney's "Aladdin" all of the sudden.
Hopefully, the improvements over last week's screenshot are obvious. We now have lighting which correctly highlights each surface from an appropriate direction, and it works regardless of the plane's orientation or position.
And, as a bonus, you can see a few additional lighting components at work. For one thing, the light has a color (yellowish orange), and it casts a warm color contrasting with a cooler, ambient blue-violet that lights everywhere else. There's also a falloff component which fades light intensity based on distance from the light, which helps illuminate areas directly under the light (which were dark without it).
This means I can have separate control over ambient lighting and point-source lighting, each with their own colors and intensities. Theoretically, additional lights are possible, too.
Now, this isn't the end goal. It's a huge step forward, and the backbone of the proposed lighting system. However, there is at least one additional piece missing: composing multiple ship parts of various orientations into a scene with lighting.
For that to work, I can see two possible approaches. The first is to simply render each ship part as planar geometry with this shader attached, and appropriate textures, and let the GPU do all the work. This would basically be a 3D engine rendered from a 2D, top-down perspective, and is maybe overkill.
The second approach would be to render all the ship parts onto a scene with their relative positions and orientations, and then do one giant lighting calculation on the whole screen. For this to work, I'd have to render the color information to one screen-sized texture, render the normal map info to another texture, then combine the two in a shader with lighting info. Also, that normal map texture would need each sprite's normals adjusted for orientation, which means transforming their normal map colors based on orientation. This, too, is pretty complex.
Before I can do that, however, I think I need to figure out how OpenGL handles multiple render targets, so I can have one for each scene texture (diffuse color, normal map, and any others I might need, like depth or occlusion info).
More on that tomorrow. For now, my brain needs a rest!
Posted on 11/20/2015 - 16:02
Just a quick update today as I need to head out in a few minutes.
A chunk of today was lost to an errand. But the time when I did work I was focused on memory optimization. Steve pointed out that NEO Scavenger was starting to consume 200+MB of memory when all the data was loaded, and that'd cause problems on some mobile hardware. We needed to look into trimming that fat.
It took a few hours of trial and error, and learning how Haxe/OpenFL deals with memory, but I think we found a solution. Namely, the XML parsing we do needed some explicit clean-up of XML.parse objects and strings when it was done.
That, and the encounters file needed to be split up. The file was originally larger than all other data files combined, and it was causing memory usage to balloon unnecessarily. Splitting that up, combined with the parser object nulls between each step, seems to have kept memory allocation under control. Current load is about 80MB.
So hopefully, crisis averted! I guess we'll have to keep an eye on this as we develop further, though.
That's all for this week. Have a good weekend, all!
Posted on 11/19/2015 - 17:45
I think I'm making progress on the OpenFL+GLSL shaders. It was a close call, but by the end of the day, I finally wrote my own normal map vertex and fragment shaders, and they seem to be displaying like they should.
If nothing else, I'm learning OpenGL, GLSL, and a lot about 3D display math. For example, one thing my previous attempts did wrong was to use deprecated OpenGL uniforms. Namely, things like gl_Normal, gl_NormalMatrix, gl_ModelViewMatrix, etc. Silly me thought, "The shader already has those values? That's really handy!"
No, no it doesn't. Instead, I needed to feed my shader these values, or else piece them together within the shader. So when I finally figured that out, I was able to make some headway on a shader that uses actual data instead of unknown values.
And the result?
So what we're looking at here is a 512x512 plane with a cushion texture applied to it, and a light where the crudely-drawn white starburst is. This cushion texture has a "normal map" (which is a texture that sort of defines surface bumpiness), and the light highlights and shadows the bumpy parts.
A few days ago, I had a version of this working almost flawlessly, with one drawback: it didn't change if the cushion square moved around or rotated. The lighting would always come from the same direction (like it was drawn permanently onto the cushion.)
This newer shader updates the highlights and shadows based on both the position and rotation of the cushion. And this is important because I'd like to try ship parts that can be rotated and placed and have the lighting react accordingly. Without this, I'd probably have to have 4 separate copies of each ship part, with normal maps for each rotation (costly/tedious to draw, and uses lots of memory).
Now, this isn't perfect. For example, there's an area directly underneath the light that should probably be lit, but seems to be in shadow. Also, the "peaks" of the cushions seem to have a rough texture to them. I'm thinking this may be a problem with the way I'm combining cushion color with the light component, or else the light is so close to the cushion that individual threads in the cushion material are causing shadows.
It's a start. I've been "wasting" a lot of time on this, but I'm still optimistic the outcome will be worth it. Especially since figuring this out now should mean I don't have to mess with it much again later, as it'll be the basis for most lighting effects used in the prototype. Just gotta figure this beast out...
Posted on 11/18/2015 - 17:36
Hey Folks! Today started off with a bit more tablet parsing work. And later, more shader investigation.
I think I've finished putting all the data type and parser code together, and Steve is going to plug those into his encounter processing to see if things run normally. Depending on how that goes, there may be more stuff I can do to help shoulder the burden of the mobile port. 4 years of code is a lot to convert!
Once that was done, I turned my attention back to shaders. I'm still having trouble wrapping my head around the transforms necessary to do normal-mapping. Though, as I'm discovering, a lot of the problem lies in differences between conventions in one language vs. another, and from site to site.
For example, some sites list 4x4 transform matrices as having their translation components in the final column, while others list it in the final row (i.e. transposed). Even after looking up column-major and row-major, I'm unsure which is which. Thankfully, OpenGL documentation clears this up by explicitly stating that the translation components are indices 12-15 in the Matrix array. No confusing that!
Another example is that the initial normal map tutorial I followed created a "ModelViewMatrix" while other tutorials had "Model" and "View" matrices. I later learned that the combined ModelViewMatrix is more common, but at the time, I couldn't figure out for the life of me how I was supposed to tease these apart. (In the process, though, I learned how OpenFL's Matrix3D.Create2D() function works, which is basically a translated top-down view matrix pointed at 0,0.)
Combine the above confusion with a general rustiness (or lack of experience) with matrices, and we get a pretty wide gap between what I know and what I'm trying to do.
I still think it's worth it, though. Matrix math has haunted me for years, and this is pretty integral stuff to game dev. Maybe slightly less-so for 2D games, but as per yesterday's example shaders, it can add some really juicy visuals if used cleverly.
I think tomorrow will continue this line of work. I feel like I'm making progress, albeit slowly. Learning how the 2D view matrix is made, how translation matrices look, and now, getting a better handle on tangent and binormal calcs, I think I'll be getting there soon. Just have to hang in there, brain!
Posted on 11/17/2015 - 17:36
I decided to switch back to prototyping for a day. The siren's call of OpenGL and shader programming lured me back, despite previously crashing upon jagged shores.
In case you're wondering why I keep looking into shaders, it might help to show a few examples:
In other words, shaders can do some pretty cool visual tricks. And since most desktops and many handheld/mobile devices have GPU hardware designed to use shaders, it's pretty fast, too!
In theory, Haxe/OpenFL has a way to display these shaders. And in practice, I've got this working no problem. (They have several helpful samples and demos to get you started.)
The tricky part, however, is getting this to play nice with HaxeFlixel. Right now, HaxeFlixel will support shaders that get applied to the whole camera. So this can be useful for post-process effects (antialiasing, scaling, blur, etc.).
However, it's harder to get these shaders per-sprite. And I think that's what I'm going to need if I want to try to apply lighting/highlights to individual ship parts. (An alternative to the grid-based lighting I was trying before.)
Although, now that I write about it a bit, maybe that isn't the case. Maybe I don't need to have individual sprites with shaders if I can render a whole scene to a texture, and feed that texture to a shader that selectively processes regions of the scene? E.g. one texture shows the ship sprites' actual colors, another texture shows those sprites' normals (bumps), and a third texture highlights areas where the shader should be active vs. ignored. This way, the shader would just process lighting for pixels in one area of the mask, and ignore other areas entirely (such as the GUI).
Hmm. This might save me from a lot of matrix transformation headaches.
Or, no. No it won't. I still have the problem of a rotated ship piece having normal maps that are pointing the wrong way. The shader would need to know that these ship pieces were rotated in order to light them correctly.
Anyway, the good news is that I've got a normal map shader already running. I can move it around and see the lighting on it change accordingly. The missing parts are
1 - if that item gets rotated, the lighting doesn't behave correctly
2 - this is entirely an OpenFL GLView scene, and bypasses HaxeFlixel.
The first issue is a well-known problem, and it's just a matter of me learning how to transform my vectors appropriately in the vertex shader and pass that info to the fragment shader where lighting is figured out.
The second issue is more of an unknown. I know I can composite OpenFL (or HaxeFlixel) sprites on top of a GLView scene, but I haven't been able to have a GLView scene blend with them at all. I suspect it's doable by having the shader sample the game's frameBuffer or something, but I haven't learned enough about that to sling those around yet.
But at least I made progress today! It was damned frustrating, and my brain is starting to show its age. But I'm excited for the prospects of playing with shaders in my next game!
Posted on 11/16/2015 - 17:12
NEO Scavenger is now officially updated to v1.13! Since the test builds have been relatively stable, I've just finished updating the default builds to 1.13 on all sites. The "test" links are no longer necessary, and have been removed for now.
This updates the following builds:
- Flash version on the official site
- Downloadable versions on official site
- Steam default builds
- DRM-free downloads at Humble Bundle, GOG (pending approval), ShinyLoot (pending approval), and IndieGameStand
New changes include:
- Changed SampleMod to be self-contained in one folder.
- Changed old _readme.txt about modding to be stored in SampleMod's folder.
- Changed loading screen to only show last line of log, and to tell user how to see whole log.
- Fixed a bug in treasures with a variable output that would return one less than the specified max.
- Fixed a bug that allowed the dome light to be used in making noise traps.
- Fixed a bug that caused 4-week pickup truck extension at St. James to be free.
- Fixed a bug that deleted arrows/spears that stuck in wounds as a creature died.
The major changes here are the sample mod and loading screen. The sample mod is now stored neatly away inside its own folder, instead of having some files and other folders littering the game's main folder. And the loading screen now shows only the last line of the log messages, as well as a tip on how to see the rest. Both of these changes should help avoid confusion in new users, and prevent mod users from reporting harmless "file not found" log messages.
The bug fixes for loot will slightly increase some treasure amounts when a variable number was returned, and dying targets will no longer destroy ranged weapons impaled in their corpse. Also, the St. James parkade should behave better now.
As always, if there are any issues with the new build, let me know on the forums!