Showing posts with label rendering. Show all posts
Showing posts with label rendering. Show all posts

Wednesday, 7 March 2012

Tweaks

Minor tweaks of late.

Restructured the rendering quite a bit. Keeping things very, very simple still: the rendering thread owns a list of functions that execute each frame, in the order in which they were added. Dumb as a pile of bricks, and assumes that each such render-function will actually do a bunch of stuff including culling.

Originally the rendering functions were all nullary and their results discarded. I swapped this over to each taking a single state argument, a hash map of arbitrary rendering guff, and each returns a (potentially modified) state blob. So the core of the rendering loop is a nice, cuddly-ish*
(reduce (fn [s f] (f s)) initial-state render-funcs).

Right now the uses for this blob are limited. I'm just bunging a few things which were previously updated from different threads in there, such as camera data (ad-hoc derefing of atoms and such gives inconsistent rendering and general ickyness). So it's more like a way to carry around an immutable copy of the game state as of the start of the frame than anything truy useful. Suspect it'll be handy later to mirror the GL state and avoid heavy state-changing operations where they're not necessary, do pre- and post-invariant checks and other contract-y things, accumulate frame stats such as objects rendered... stuff.


Image is just some randomly coloured lights scattered around, this time with a bit less gloom. Still quite gloomy. I find myself wondering if it might be better to work with entirely solid hexagonal prisms as a starting point, rather than more elaborate geometry. Hmm.


* Cuddly-ish, but not very cuddly. I would really rather use something like (flip apply) instead of the embedded anonymous function, but cannot quite seem to conjure the right way to do this without doing something slightly horrible. Will look at it later with fresh eyes and doubtless slap my forehead at my own stupidity.

Monday, 27 February 2012

Lights!


Decided it was time to fling some deferred rendering at the project, because who doesn't like taking huge chunks of VRAM to do simple things? Thanks to Jotaf's comments last week, I have a much easier method for making and rendering walls, so it only took a few minutes of Blender-torture to generate new ones.

The question of style is one I haven't resolved yet, alas. Making tech is far, far easier than trying to hang a scene together as a coherent whole. I know the cultural roots the game world will draw from, but not whether to go for a cell-shaded or painterly or somewhat realistic approach. The latter is probably most tedious in terms of rendering tech and modelling, but is almost certainly the easier to at least rough out textures based on photographic sources.

Friday, 27 August 2010

Side Projects: Xibalba

This is actually the project around which this blog formed, a turn based roguelike-like game of procedural dungeons, faint mesoamerican stylings, dice rolls, and general geekery.

So far it's seen more use as a rendering playpen than an actual game, although messing around with various representations of immutable game state has been fun.

Oh, and for the curious, I did indeed mis-spell the name for a goodly portion of the project. This is what happens when you start naming things at dark o'clock one night and don't check them for ages.

On the graphics side:
  • Deferred shading forms the core of the pipeline. I wanted lots of light sources, and wanted an excuse to mess around with deferred rendering. It's been fun.
  • A single main light uses a conventional forward-rendering technique with exponential shadow maps. This forms the focal point, being centred on the player character, and also serves to illustrate line of sight.
  • Transparent objects are forward-rendered after the deferred pass, although I don't like this approach at all. Planning on doing some stuff with screen-door transparency for water at least, essentially stealing the work done by Media Molecule for LBP.
  • Zeroth order particle systems! I've a minor obsession with these, entirely deterministic effects with all particle motion calculated in the vertex shader for a given time.
  • Star-shaped bloom. This is just a very boring post-process, but it's summed over many increasingly downsampled versions of the final image so has quite a large effect considering the main blur kernel is rather small.
  • SSAO. Actually, this is no longer a 'proper' SSAO implementation. After messing around with a few different approaches, I eventually settled on a very crude approximation of the depth Laplacian using difference of gaussians, plus some falloff over large distance deltas. This gives a rather stylized effect that I really like. It only works well for quite compressed scenes due to fixed kernel size - perfect for a top-down view though!

First working implementation of the deferred render targets:


Prototyping water, note that only the main (forward rendered, shadowed) light affects the water surface:


The 'notSSAO' post process, dialled up to 11. This also shows a chunk of the map lit almost entirely by deferred lights cenred on the glowing mushrooms:


And last repeat screenshot for this post, the basic particles with a simple lit and shadowed alpha-tested rendering mode:


I'll try to get this running on my partner's PC and get some new screenshots of this for a later post. Have to admit, it was nice going over the early screenshots and see it evolve.

Monday, 18 January 2010

May Have Been Driven Mad By Sparkles.



OK, I deliberately pushed the particles way into HDR territory to get the bloom filter to explode. And there are too many particles to start with, this was supposed to be a collection of gently background fluff (fireflies, dust, magical plankton... that kinda thing).

I was playing with the property browser thing for the particle material and accidentally changed the wrong digit in a colour (0.9 -> 9.9, easy enough to do). At this point I think a bit of my mind snapped, so here we have CRAZY sparkles, whirling in madness.

Those not blinded by sparkles may note that the player now has a trail of arrows, showing the last ten moves. Although the final intention is to display only the actions of the current turn (thanks Jotaf! This idea is really growing on me), a possible extension to display a limited action history may also be useful. It might help in making the AI behaviour more transparent to the player, or maybe just as a hint as to where an entity might be if it dives out of line-of-sight.

Tuesday, 22 December 2009

::tap-tap:: Is this thing still on?

Oh! Hi there.

Amazingly, I have been working on this little project. It's been slow going.



The rendering system has been refactored considerably. It is very much still a nasty mass of imperative wrongness, but its also a bit more consistent and less fragile. I've been experimenting with different methods of generating the world geometry. I've tried half a dozen implementations of a game-entity framework, none of which seemed adequate. I added a quick random map generator (screenshot taken from one such random map), and worked on the water shader a little. It looks OK in motion, but definitely needs to be somewhat more obvious generally. Those little divots in the ground are shallow water, the light source being the player (who's mesh has temporarily elected to disappear).

Oh, and I gave Clojure a spin too. Experimenting with the property-bag approach in a Lisp is relatively joyous, especially with Clojure's explicit syntax for hash maps. I found it hard to scale projects up, though. I'm too used to arranging things in terms of objects and classes, both Haskell and Clojure befuddle me with a mass of functions. My failing entirely, the languages have much to recommend them.

I started using Mercurial SCM for source control on this little project. Although I do find myself wanting a P4Win-like GUI front end (which may well exist somewhere), the command-line tools are quite lovely and I refuse to give up on them before becoming at least somewhat proficient.


Now for some design babble. This idea surfaced recently when trying out a few entity and time-handling systems, and I think has some interesting gameplay connotations. Here's the gist:

  • Every turn, collect actions from all agents in the game world

  • Execute all actions, regardless of validity, to produce a new world state. Each agent also tracks the actions that changed it this turn.

  • Resolve the world state by resolving invalid conditions


The third step is obviously the tricky one, but also where the most interesting aspects spring from. The first two steps merely simplify some aspects of mutating the game world.

So this tricky 'resolve' stage... what happens here? Well, take a very simple set of verbs: agents can either stand still, or move one space each turn. More than one agent occupying a space is invalid. If two agents occupy the same space, do some basic conflict resolution and then generate a valid world state based on that. The losing agent could be displaced back to its original position (and also presumably lose some health, in a standard Roguelike game of HP and damage rolls...), whilst the winner occupies the contested space. In the case of a tie, both agents are returned to their starting positions. An agent who didn't move in this turn gets some manner of defensive bonus, but if it loses the conflict will be displaced away from the attacker.

There are immediate problems with this simple method. What happens if another agent occupies the starting position of the losing agent in a conflict? How do we handle three or more agents in a space? What about an agent surrounded by enemy agents, such that no position is valid after losing? Conflict in dead end corridors?

Some embellishments to the system should allow most of these to be resolved. For example, agents could be in a standing or prone state, and not occupy any space when prone. Losing agents with no valid moves can be knocked prone. And so on.

But what do we gain from this approach?
  • Most interestingly, this represents a gateway to yomi, as described in the linked post. As every action is essentially simultaneous, a suitable number of counter moves and counter-counter moves allow for much greater potential depth in conflict. There aren't enough in the simple example above, but it at least admits the possibility. In order to be really satisfying, either the AI behaviour needs to be tractable for the player, or multiplayer might be considered.

  • Strategic positioning - this is a big part of what I'd like to capture in combat. Being able to 'bull rush' opponents is crucial; several character development options suggest themselves to allow more tactical control over the way a battle evolves. This feels a lot easier to approach when all potential movement is handled in a single step.

  • I think this system is less predictable. As everything happens at once, actions are more likely to fail and rather harder to evaluate. Rather than just considering the success chance of a given action, the player must consider all the possible actions of relevant agents that could interfere with its execution. This is a good thing in general.


And what is lost...
  • Agents all move at a uniform speed, or at integer multiples of that speed. We lose the fine-grained ordering of agents based on some intrinsic properties and/or the execution time of actions. All actions take one turn. We can allow for slower agents by forcing them to take null actions except every N turns. In theory we can also allow faster agents by slowing down the rest of the world in much the same way, but that seems inelegant - as many actions will require a graphical representation and time to be displayed, doing this will slow the game for the player.

  • The system is less predictable. Players can no longer easily guess the outcome of an action, as it depends on the actions taken by other agents in the same turn. This could be a bad thing for transparency.


It needs more thought, and the implementation details could get very messy for the semi-mystical 'fix the world' step.

Monday, 8 September 2008

Even more deferred tentacles

Just a quicky today.

These are lighting-only shots showing the same scene with and without screen-space ambient occlusion, the latest hacktastic post process to take the rendering world by storm. Unfortunately I have to concede that even my less than stellar implementation does add a lot to the rendering, for a moderate cost, so I guess I'll be jumping on the bandwagon. It's an especially useful technique when combined with deferred lighting, as attempting any real shadowing with a bucketload of small point lights is very bonkers, so the illusion that the faked ambient occlusion provides is doubly useful.

As an aside, I do like my dungeon fairy lights. They add such a nice ambience...

Before (no SSAO):



After (mit SSAO):

Friday, 5 September 2008

Deferred Tentacles

Further work on the deferred rendering side. I finally found an example online using FBOs with a stencil buffer, and thereby discovered that despite using a combined depth-stencil renderbuffer it needs to be attached to the frame buffer object twice, once as a depth attachment and once as a stencil attachment. Sigh.

That done, efficient rendering of small lights via z-and-stencil-tested spheres works nicely!

Behold the scene, containing no less than fifty ickle lights, plus the large shadow-casting light from the player's avatar.


The majority of the screen is taken up by the final composite image. On the right, small sections show a sample of the buffers involved (yes, I don't even turn off my debugging chuffle before posting, I'm that lazy). Top is the SSAO term (very low intensity in the final image, as it looks pants). Below that are the lighting accumulation buffer, world-space normal, and finally unlit diffuse buffers.

Lastly, the image displays some filthy aliasing as the source render targets are only 512x512, violently scaled up to match the screen resolution. I should fix that.

Edit: here's a version using 1024x768 buffers throughout. Ouch, bye-bye framerate. Need to fix my absurd pixel shader usage methinks.

Tuesday, 2 September 2008

Hordes


Nothing important today, just been sounding out the pitfalls and quicksand that abound in OpenGL. This time it's so-called 'pseudo-instancing', providing more or less the equivalent of DX9's SetStreamSourceFreq-style instancing for geometry. I'm testing it with the anemone mesh, because I still have yet to get around to authoring more models. I'm lazy and emacs is more friendly than Blender.

Technical sorta-details: a position/scale and quaternion rotation are stuffed in a couple of spare texture coordinates using OpenGL's immediate mode, on a per instance basis. It's a bit of extra mucking about but seems viable in terms of performance. A per-instance colour should round out the system for maximum variation at a small overhead.

I think I'll be using this a lot for semi-dynamic clutter - rocks, vegetation, refuse and the like. Static objects will probably benefit more from being baked into world space in large batches, assuming memory is not a concern, but smaller things may need to be moved or animated.

Wednesday, 27 August 2008

Visual fluffs


As my other post is waffly and dull, I thought I'd post some equally dull screenshots.

First, we have soft shadows and a general framerate improvement. I found I wasn't using buffer objects for my mesh streams (bad!), switched to position-only streams for shadow rendering when possible and changed the shadow buffer format to rgba16f. All this has reduced the frame time hugely, even after I started adding more crazy stuff. For comparison, a similar scene with blurred shadows was previously in the single-figure frame rate. Ouch. Still vastly too slow at the moment of course, but moving in the correct direction.

The soft shadows are done with a simple 3x3 guassian blur over the cube. It has errors on the cube edges for some reason, as can be seen in the nice black line across the lower right quarter of the image, but even with fairly low res maps and a small kernel the reduction in aliasing makes things look nicer. Hooray!


The second screenshot shows a half-finished unsmoothed SSAO post process. It's using a deferred rendering setup, with a few render targets for diffuse, normal, depth and lighting information at the moment, although for this screenshot only the depth info is used of course. Lots to do here, and I'd like to get a scene with more interesting visual fluff to show off the AO effect better...

Anyway, hopefully that helped balance up the wordiness of the previous post.

Friday, 15 August 2008

Baby Steps


No big changes, but:
  • Hex floor generation cleaned up
  • Block-edge normals much less broken
  • Mipmap brokenness caused by discontinuous texture coordinates fixed
  • Shadow res bumped up (shadows are currently a huge rendering bottleneck, hence terrible frame rate)
  • Shadow acne removed with a teeny epsilon
The mipmap fixes have also introduced a LoD bias, but I quite like the way it looks. Textures do repeat too much at this scale though, and there's little to break up the tiling. Will be looking at potential fixes for this soon.

My big low-res chasm-filling geometry seems to have wandered off as well, not sure why. Eh, it'll come back when it's hungry...

Thursday, 7 August 2008

Monsterous

Many bugs to fix, but instead of fixing 'em I've been dithering between the best way to represent my world using immutable state (I suspect monads may be involved, and these horrors just won't fit in my brain) and... getting a model in game!

In this case, a very crappy monster has made the long and torturous transition from Blender to screen. Behold, the Cave Anemone (the five-tentacled starfish thingy):


It even casts shadows! Doesn't receive them yet, and frankly it needs better normal and diffuse textures than a few minutes in the GIMP can supply.

The screenshot also highlights the evil problems with normals at block boundaries (witness the horizontal and vertical smears visible to the left of the brave @dventurer) and the general horror that are the shadows. If you look closely, you can even see the wonderful mipmapping errors introduced by the sub-textures on the floor.

First goal will be to slap some more meshes in there, even if they're placeholders. I want one other monster type (Tentacle Mouse?), at least one inventory item and a player model. This will be enough to finally dispose of the glowing unlit spheres and @ model, and give a better clue as to scale issues.

Wednesday, 30 July 2008

Hexy texture madness



Testing out the sub-texture stuff with normal maps and shadows. Right hand images apply textures on a per-hex basis, whereas the others just have random perlin smeariness.

Interpolation between hexes is still enborkinated, so the hex edges display some very rough geometry and there're no smooth variations. Also, the ugliness of the shadows is getting to me...

Tuesday, 24 June 2008

Shadows!


Yay! It took quite a bit of wrestling with formats, but it seems to work now. At least on one PC.

I greatly reduced the ambient lighting and removed all other light sources for testing, so the shadows are rather stark and flat. Also there are a metric fuckload of subtle problems - light bleeding where the depth complexity is even moderately high (the downside of using VSM), speckles due to depth precision problems, streaks and blobs caused by the low resolution shadow map... I'm sure there are plenty more, too.

But the important thing is it's a start, and it's quite essential for that claustrophobic RL feeling.

Next big problem will be making sure this is consistent with logical line-of-sight. LoS calculations need to be somewhat permissive to account for the character moving around within its cell, and only take into account the logical properties of grid cells (i.e. blocks vision or... not) rather than the exact nature of any occluding geometry. Shadow maps, by contrast, are far more precise. Hmm. Giving information to the player based on what their character could see may make the shadows seem wrong or incomplete (e.g. knowing that there's a goblin fishmonger a few squares to your right, despite it being entirely in shadow), whilst denying them information about, say, a monster which is clearly illuminated by the character's light source (but 'shadowed' according to logical LoS) is also broken.

Wednesday, 4 June 2008

Rooms and stuff

Natural caverns do not a varied environment make. With this in mind, terrain generation now creates two sets of geometry. One is the natural cavern, the other encompasses built features. Both use the same marching cubes set and are generated from the text file map format, but the 'built' portions use much more boring density functions and will eventually have matching textures.

I'm increasingly getting concerned at the sanity of having a flat text file as my only map representation. For the moment, the key looks like this:

[#] => rock wall

[.] => rock floor
[n] => rock platform
[v] => rock ditch
[~][=] => rock pool (shallow and deep, resp.)
["]['] => vegetation (not implemented)
[:] => rubble (not implemented)

[%] => built wall

[,] => tiled floor
[_] => tiled platform
[+] => archway (not implemented)
[o] => pillar (not implemented)


Continuing to use different-but-similar characters for natural and built terrain features could be a pain in the arse. One possible solution would be to make this implicit, for example [~] could be represented as a rocky pool when surrounded by [.][#] but by a decorative water feature when surrounded by [,][%].

Speaking of water, I added yet another hack to the shader to colour areas below water level light blue. This should help with generating valid dungeons with water areas, and eventually should help debugging water meshes.

Anyway, a view of the 'room' bit of the dungeon with new geometry, moat and hideous textures: