Shadows and Reflections and forced upgrades

Playing in the water with Arashi and Ket
Playing in the water with Arashi and Ket
So after a full week of HLSL and RenderTarget2D mastery, I have got my water effect to look just about where I want it to. There’s two other effects I’d like to add, but attempting to add the first one – a secondary water ripple (is it a ripple?) when objects are placed in the water on top of the ripple from motion caused the FPS to drop a bit. I think I’ve reached my limit of full screen draws for effects, so I’ll have to see if there’s a way to localize this sort of effect, but given the poor access to the backbuffer in XNA 4 (more on that later), there aren’t many options I can see.
Also, as you might note in these screenshots, I’ve finally got rid of the generic circular shadows that had been in the game since practically day one. Now frame-accurate shadows are cast on the ground, which certainly adds a bit more depth than I was expecting when I tossed it in there. Since the water reflection code was very similar to shadows, I figured “why not?” and sure enough, I’m relatively happy with how it came out. 🙂
A nighttime run is good once in awhile
A nighttime run is good once in awhile
Unfortunately, with the “Way Things Are”, I recently had to update the entire game from XNA 3.1 to XNA 4.0. If there’s anything that gets me angsty it’s having to take days recoding things that already worked just because someone thinks the changes are for the better (here’s a hint, it’s really not). I’m still not happy with the changes to blending… there are some blending behaviors that are impossible to reproduce from XNA 3.1 which changed a lot of subtle things, and as a graphics designer that kind of thing drives me up the wall. The sad thing is the “quick fix” offered by the XNA team and others who have used XNA 4.0 doesn’t really fix the problems I’m talking about. But enough whining, at least it’s done and over with.
Arashi and Ket at the riverside
Arashi and Ket at the riverside

I know it seems a bit late in the development to finally get to a major graphics engine improvement like this, but in my opinion there’s no better time.  Honing in the final look of the game means I’m finally getting to the real meat of production, with one more final addition – handling the Z-coordinate so Arashi can climb stairs and cross bridges – that should be the last time I need to tinker with such things.

About Astrael

A long-time independent game developer that was lucky(?) enough to have grown up with the gaming industry. I am a programmer, a game designer, a concept and pixel artist, a music composer, and a novelist. This has been my dream for as long as I can remember, and I am determined to take advantage of every talent I hope I have to make it happen!

12 thoughts on “Shadows and Reflections and forced upgrades

  1. I know that for you (since you’ll publish it on XBLA) it is not possible, but it is because of things like this that I switched from Ogre3D to DirectX. I’ts frustrating when the graphics engine, or any other kind of engine for that matter, gets in your way, instead of helping.
    Poor backbuffer access being one of the main reasons. (Ogre3D got in the way a lot, not only graphic, but also got in the way of everything else with it’s resource loading techniques)
    Ogre3D forced me to redraw the entire scene to get a “HUD-less” version of the backbuffer, so, I had to render everything twice, something that could have been done using a backbuffer copy function, and that would be way faster.

    1. XNA 3.1 used to contain a special render target called ResolveTarget2D that was eliminated because of its redundancy with RenderTarget2D – they were practically the same thing except (from a non-technical point of view) the ResolveTarget2D was basically locked into being a copy of the backbuffer and all its settings. There were some other paramters I never experimented with like indexing, but that was the gist of it. I fully understood the reason for them removing it, because in the end both classes really did do the same thing.

      The thing that confuses me is the fact there -was- a GraphicsDevice.ResolveBackbuffer() method that copied the backbuffer to this ResolveTarget, but they simply removed it instead of updating it to use a RenderTarget2D. The reason for this was “it’s slow on PCs and WP7”. But not on the 360, which had something special about it I can’t quite remember. So now, instead of a native method to copy the backbuffer, it has to be done manually by declaring a blank texture and copying a huge Color data array to the texture, so 5~6 lines (probably CPU rather than GPU intensive due to the code) to do what used to be a function of XNA (and because it’s not optimized as it’s not part of the library, it’s REALLY slow). And I know for a fact that this is a common set of code other XNA programmers use because I found the sample no less than 20 times and that was just glancing the first few pages of search results. Backbuffer copying may be slow, but there are some effects that can only be done by using it without making a billion rendertarget copies which is limited by RAM and probably just as slow in the long run… it’s just annoying it was removed.

      As for blending, the other thing they toyed with, I have no words. I still can’t figure out what exactly they did, and why when I follow their advice to turn off PreMultipliedAlpha (to “use the 3.1 style of blending”) it does an entirely DIFFERENT sort of weird behavior… getting my game to look 95% of how it used to was more mix-and-match of the various blend states and texture settings than any standard answer, and having to do guess work to replicate previously working code is just a waste of time. Not to mention, there’s still stuff that doesn’t look quite right, but mostly minor enough only to bother me as it wasn’t my original intent (and still doesn’t look too bad).

  2. So, this function you are not forced to use is copying the backbuffer to a texture manually, reading an array of color data from the GPU? So that’s why it is so slow, reading data from the GPU is already slow, and uploading it back to the GPU every frame just makes things worse.

    Don’t know if it would work, but you could just use RenderTarget2D to render everything, and then, find a way to copy that to the backbuffer, or, just use your RenderTarget2D as the backbuffer somehow. Maybe, drawing a big rectangle and using your RenderTarget2D as a texture, this way, you could use RenderTarget2D.GetTexture() to get the contents of your scene without the need to use the CPU at all.

    Looking on Google for answers returns nothing useful, most people are comfortable rendering a scene twice to do effects like this (actually most of them don’t use effects like this at all).

    I can just imagine the XNA devs saying: “Hey, look at this function. It is slow on PC and on our phone, and few people use it! Let’s remove it so that the few people who use it have to do the same thing, but now it is way slower! Now this is improvement!”

    1. Yeah that’s exactly why I’m upset. There WAS a function that was all GPU-driven, but now they’ve removed it. I did eventually have to recode the entire Draw() method to start with a rendertarget2D as the backbuffer, and then use that until the final effects were applied. It’s more memory I have to allot but it works, just annoying (and again, a waste of time to have to recode an entire section this late in the game that already worked fine).

      But try arguing with the XNA team about its merits. Most people are convinced XNA 4 is superior in every way to 3.1. It does have some nicer things, but not everything is perfect. I hope they address them in 4.1 when they add Kinect support (and possibly achievements).

      BTW I have utmost respect for the XNA team, so don’t take this as me not appreciating the library they put together. 🙂

  3. And I understand how you’re feeling about the blending modes.
    I remember when I used a certain game engine, they didn’t support vertex colors, and the worst part is that no one cared. I tried to contact the responsible team they didn’t care about it at all, since I was a single client (and it was not a free engine, by the way) out of don’t-know-how-many-other-else costumers who was complaining about that.
    The worst part is that I was using vertex color to do all the shading for my map, and when importing the model, it got plain and with a lot of visible artifacts, completely flat, and no shading at all!
    It completely destroyed my background, I was so upset that I switched to another engine. (and, other things happened with other engines, and now I’m using DirectX)

  4. Oh, by the way, you said that you reached the maximum number of effects on screen.
    Ripple effects using the backbuffer copy technique are quite light, they weren’t supposed to cause any kind of major FPS drop. Are you uploading all tiles of your background to the GPU every frame?

    There aren’t much in the screen at the same time there, at least it is what it looks like in the screenshots. Did you try profiling your game to find the bottleneck?
    A background with 1024×1024 tiles, for instance, each tile being two triangles, will result in 2,097,152 triangles, uploading that much every frame probably will cause a major performance loss, and it is even worse if they aren’t in the same vertex buffer, state changes (textures, for instance) also can cause the game to become slower.

    I saw in one of your tweets that you PC is old, but. How old it is? What are the specs?
    Maybe the bottleneck is somewhere in your code, assuming you didn’t optimize or fix it already.

    1. I think it’s not the effect itself that was causing the FPS drop, it’s the fact I had to swap the rendertargets so many times in one frame that was starting to drop framerate slightly, and the effect needed another capture of mid-processing graphic data. My tiles are actually pretty small and I only draw them once at the very start of the frame before all other objects are drawn so I can produce more varied maps without eating up as much disk space, and the water layer is actually a completely independent layer to produce the effect I was going for. Honestly I’m happy with how it is running and looks, so changing things now probably won’t do me any favors lol. BUT there is an overloaded method for GetData on the Texture Class I didn’t see before that lets me take a small sample out (this is how I check to see if Arashi’s feet are completely submerged by the water in the current frame to add another effect and the right footstep sound, something I had to do because just checking tile coordinates wouldn’t work because water doesn’t stay constrained to tiles), so I am going to use that to take a small sample around Arashi and distort just that.

      My PC is 8 years old, it’s a top of the line single core P4, but the motherboard only supports basic AGP video cards which is my main performance bottleneck. It can’t even run my music software very well usually, but that’s fine, it works. The game runs fine on a laptop I am borrowing and even better on the 360. Anyways, I’m not that strong of a coder to really optimize well, and my philosophy would make a purist coder cry: Just get the damn thing working, and then worry about it lol. I have to refrain from headbutting people when they argue coding practices with me. XD (btw, I really mean no offense, so if I do ever seem aggro about it to you now or in the future, it’s nothing personal, just a heads up on who I am lol)

  5. Your specs are similar to my old one then.

    Well, if it’s running fine on X360 and on that laptop you borrowed, then it’s fine, I guess you can’t help it on your PC then, because optimizing it to run fast on your PC might mean you would need to rewrite the entire map drawing routines, and that would be not worth the trouble if it is running fine elsewhere.

    Still, trying to think what is happening on your PC, I think I can guess, probably…
    If you are uploading the entire map geometry (tiles), even the ones who are not visible, while this is not a problem for the GPU, it may be clogging your AGP bus, causing slowdowns. If you were to optimize it, you would have to write a routine to check which tiles were visible and upload only tiles that passed the testing, but, like I said, it would not be worth the trouble now, since it’s a only problem on older PCs.

    Now, about taking a small sample around what is going to be deformed. I think it may be not necessary, you can just take a copy of the whole screen in mid-rendering and use the same texture for all objects that are going to deform, so you can use the same texture on all ripples, this way, so you don’t need to take samples, and you can make more ripples without any extra cost.

    I wish I had something to show you so I can illustrate this idea, but right now I have nothing solid to use as an example.

    By the way, how you’re planning to make Arashi or other NPC/Objects to sink halfway in water? it seems you are not using depthbuffer, or are you?

    And one last thing, about you coding philosophy: well, it’s the same as mine, even though I’m supposedly a C++ programmer, I like to code in a more “C” way, using lots of pointers, structs, low level functions, arrays instead of std::vector, and things that make OOP purists cringe in anger.
    It’s really hard to argue with people like one friend, who thinks what I do is absolutely wrong. Well, at least I get things done and they look how I wanted it to… Despite the huge amount of bugs, uninitialized variables and unpredictable behavior. lol

    1. Actually this was pretty basic logic, literally day one of programming I had alread done the tile engine to only draw the tiles actually visible. The maps are just too large to draw 100sx100s of tiles at once with no reason.

      I also can’t just take the drawing mid-render (to a certain degree). Only the very final water fx rendertarget has the blend correct to distort for the presence of ripples. I do, however, reuse this last rendertarget as a mask for other effects in the frame, and catching if the water has moved enough to cover Arashi’s feet.

      I already have a custom z-sorting routine, it was required because linear depthsorting was failing just in the very first room due to the nature of the 3rd dimension in the game.

      I have most of the major, fundamental programming stuff done and personally never want to deal with it again, so while I appreciate the suggestions or analysis, I won’t change anything at this point unless it is acting inconsistently with bugs (I’m a QA tester as my day job, so I test the crap out of it when I code a new method, I won’t move on until the bugs are gone), hehe. It’s been a year coding the engine, and it’s really not a simple one compared to most 2D RPGs, given the sandbox nature of the decorative elements, plus I’ve seen AAA games mess up what I’m doing with more errors so I don’t feel too bad XD It’s practically a 3D game behind the scenes >_>

  6. I’m sorry I assumed you didn’t know about that kind of stuff. Because often when I look at most indie devs projects, most of time they barely know how the underlying hardware works, so they just do things the wrong way without knowing, but well, thankfully I was wrong on your case.

    And, so you are reading a lot of data back from the GPU, right? That explains why the relatively small bandwidth of the AGP bus can’t keep up with your game. (Also, the penalty for reading back information from GPU on PCI-e is lower than AGP, since PCI-e is bidirectional and has roughly double bandwidth compared to AGP)

    So, I watched the gameplay footage right now. I don’t know if I misread, but did you say somewhere you are not planning to animating menus and HUD or screen elements?
    If you aren’t planning on doing that, I think you should, at least make them fade-in and out. In the video, the character portrait sudden popping in front of the screens feels artificial/amateurish, and no transition animation whatsoever between different text and different portraits feels awkward. If you don’t like that letter-by-letter most RPG games use, you can just make the entire text fade-in, but it just appearing out of nowhere like this, at least for me, makes the gameplay less comfortable.

    Of course, I don’t know how this is on WRPGs, but I vaguely remember playing one and it had no animations on dialog boxes and menus. I’m used to JRPGs and console games, so for me, as someone who plays mostly Japanese games, this lack of animation feels extremely awkward.

    1. No worries!

      I’ve brought up animating/transitioning menus many times, so I don’t know how you’d think I wouldn’t want to do it 😉 In fact in the recent gamasutra blog I also had to explain that was on my to-do list. The menu transitions are very important to me. That gameplay footage is EXTREMELY rough, I have to reiterate. It doesn’t show anything except the game exists, and a few other minor things. You’re not the first person to comment on the menus, so I gotta make it clear that this is really early footage, I only posted because people were asking me to despite my protests. The UI to-do list has been my project for March and even a few days after publishing it I had already implemented a lot of polish that wasn’t there before, such as HP meter portraits shaking when damaged and changing expressions and better organization and sub menu layouts. Heck, I hadn’t even had time to fix the text formatting because I just increased the font size right before recording the video, but that’s taken care of. The task list for this game is enormous but extremely thorough, but I work a full time day job so I only have so much time to get things done quickly. Pretty confident just about everything is covered in it though, cause that’s just who I am, including stuff like replacing the Item Wheel with a macro bar for PC version and clock for time of day under the minimap.

      And code for animating portraits is already in place. It’s dynamic though, so if there is no animation defined for the character and their scripted emotion, it just displays the default picture. You can see maybe half a year ago on the blog I did have a simple placeholder animation on my first full body dialog portraits, I just haven’t gotten around to animating the new portraits yet because I am probably going to change Arashi and Ket’s portraits one last time. Saving all my final art tasks for later, hehe.

  7. Are you planing to animate just the mouth and eyes, or are you planning to do something similar to Disgaea 4?
    Animating just the mouth and eyes is fine, trying to animate the whole portrait may be too much work since you’re working on it alone, but would be very impressive…
    Well, you DID animate the character in 4 different directions for your sprites, so I don’t doubt you can do the same with portraits, but it would take a lot of time.

    Talking about animations, are you planning to make your text appear letter by letter?
    I know how to make it appear fading in letter by letter, just like in Tales of*, and some other games, but my way is probably a hack. I store an array of floats according to the number of characters that will be displayed and then fade them in one by one according do the speed setting. Then I just feed the float values to the vertex color of each text glyph, the problem is, that to do that you need to create your own text generation code. I did the same on Ogre3D and DirectX, and I created my own Font format, that was basically a hex file with the definitions for each glyph mapping, spacing and height, with a DDS texture file inside. The problem is that it only supports ASCII, so translating the game to non-ASCII languages would require rewriting the text generation routines. And, by the way, I still have no idea how I’m supposed to do to support non ASCII-encoding.

Comments are closed.