Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

Advanced search

1152072 Posts in 48741 Topics- by 39951 Members - Latest Member: besieger1

August 31, 2015, 05:51:32 pm

Need hosting? Check out Digital Ocean
(more details in this thread)
  Show Posts
Pages: [1] 2 3 ... 16
1  Feedback / DevLogs / Re: Return of the Obra Dinn [Playable Build] on: August 29, 2015, 08:53:26 am
Screen Warping - 1-bit Edition

In modeling the ship and testing things out in-game I got the distinct and unmistakable feeling that "this could use some screen-warping post effects to roughen up the low-poly straight lines everywhere." I'm sure you know the feeling.

I have been down a dark path. Let me take you there.

Starting with this innocent screen:

Testing screen, untouched

The first experiment is with Photoshop's "Wave" distortion filter:

Wobble things around a bit with Photoshop's "Wave" distortion filter

B+. Warps the lines around to make them look less polygonal. The problem is that Photoshop's algorithm doesn't work in 1-bit, so you need to apply it, then re-threshold or re-dither the result. Not a huge deal, but it does double some pixels and erase others. That hurts the legibility so what if there was a way to just shift pixels around and not affect their color at all?

Next try, just offset each pixel by a random amount, using some custom Haxe testing code:

Each pixel shifted by a random amount

Ok, too much. Let's offset large blocks in a random direction instead, to reduce the frequency:

Blocks of pixels shifted by a random amount

Not bad. In motion, there are large stretches of lost or doubled pixels which destroy the nice single-pixel-wide lines and looks more clearly like a post effect than a soft warping which I want. But, altogether a decent solution and solved very quickly... Too quickly. Let's identify an arbitrary problem with this randomized approach that we can spend days and days trying to solve.

The Problem

With the low-res visual style here, and just 1-bit to work with, each pixel is important. The "wireframe" lines make lost or doubled pixels especially ugly. That leads to a rule: If we move one pixel, it shouldn't ever overlap another pixel or leave behind a hole.

... which sounds pretty dumb because of course a pixel can only move in 4 directions (ignore diagonals), and each direction already has a pixel there. The key is that the first pixel move has to go offscreen, leaving a hole - then another pixel can move into that spot, creating another hole - etc. Wind your way around the entire screen this way and you can move each pixel one spot and never overlap or double another pixel. How?

Using Mazes

Build a special 2D maze (with no branches and no dead-ends) where the solution visits each square once, then while walking the solution pick up the pixel in front of you and put it down where you're standing. This shifts each pixel one space along a winding path without overlapping or doubling. If if the maze is sufficiently winding, then the direction you shift each pixel is nearly random. In pictures:

To start, build a maze using the trivial depth-first algorithm, with a bias towards changing directions at every possible step:

Simple depth-first maze. Note the branches and dead ends

Next, this needs to be converted to a unicursal maze - a single path through without any branches or dead-ends. Thanks to Thomas Hooper for the technique for this - it's pretty cool. To convert a normal maze into a unicursal one, first get a solution that visits every square in the maze. Any solving technique will work but the easiest is to just follow the left-hand wall as you walk:

Solving the maze by sticking to the left-hand wall

Next, take that solution and use it to insert a new set of walls between the existing ones:

Solution collapsed to a single line, then added as a new set of walls in-between the existing walls.

The new maze (double the size of the original one) can be solved by walking straight through without any decisions:

Unicursal maze - single solution that visits each square once

So, making a unicursal maze the size of the screen and shifting each pixel one spot along the solution path gives us this:

Shifting each pixel using offsets from a full-screen unicursal maze solution

Ok, that looks cool. Compare it to the random offset image above and it maintains a bit more order. Lines are a consistent width and there are no breaks or extra-thickened areas. But again it's too high-frequency to be considered a gentle warping. We need to reduce the frequency. I'll come back to this image below though.

Instead of generating a full 640x360 maze and applying it directly to the screen, generate a much smaller maze, scale it up, then apply it. This gets its own section...

Maze Scaling

The trick to scaling a (unicursal) maze in this case is that we need to maintain the property that the solution traverses the entire maze. For the mazes above, there's just one solution track so it's easy. When we scale the maze up, there are multiple independent solution tracks - each one must trace uninterrupted through to the end. I now realize that this is hard to describe in words. More pictures are needed.

If we take the unicursal maze above and represent its solution as a "flow":

A flow with one track that traverses the entire maze (starting in the top left)

Scaling that flow up arbitrarily yields this, which breaks our "must trace uninterrupted" rule at the turns:

Scaled flow with broken turns

Turns have to be handled specially during the scale:

Scaled flow with fixed turns - each track can be traced from start to finish

Scaled x5 and animated:

Each track runs through the maze independently. In the end every pixel is visited exactly once

Now we can generate a small maze, scale it up, and use that to shift the screen pixels at a lower frequency:

Small maze scaled up and applied to the screen

Hmm, ok. Every pixel is accounted for. That's good. But there are disjoints where the tracks pass by each other in the opposite direction. This ends up shifting adjoining pixels by 2 spots, which makes some lines appear to break. And with such a low resolution maze the structure is faintly evident. Luckily, we have multiple tracks and can apply a sine wave to the track offsets. Applied to the x5 animated gif above, that would mean shifting the white track by 0 spots, the green track by 1, the cyan by 0, the purple by -1 and the blue track by 0, roughly.

Tracks offset in a sine wave to reduce disjoints

Same effect, exaggerated and applied to a test grid

Obligatory Lena

Multiple mazes at differing resolutions can be stacked. Still no pixels are lost or doubled.

Back in the game, just one low-frequency maze

In motion (rounding errors in my shader are eating some pixels)

Ok! That looks good... Well, it's what I wanted and it holds together pretty well in-game. There's a nice warping which definitely makes it feel more ropey than straight low-poly shapes. Unfortunately it's a bit too distracting. Maybe it'll only be applied in the flashbacks. Maybe not. No surprise then that this rabbit hole has only dirt at the end.


There was something cool in the middle there.

1-Bit Screen Blur

That intermediate, high-frequency maze-offset thing looks a lot like a blur - using just offsets, no blending:

If you don't think this looks cool then go back in time and unread this whole post

This 1-bit blur is something I never wanted or needed but hey let's see what we can do with it anyways.

Just Blur

Here the high-frequency maze is layered with lower-frequency mazes to add irregularity. 
This maintains an important legibility over using randomized offsets

Another spot. This can be globally faded in and out, so may be good for a transition effect or something

Depth of Field

Scaling the effect with distance

Scaling between low and high-frequency mazes based on distance

Focal Point

Scaling the effect based on world distance from a hand-placed focal point

Same thing, different angle

These hold up surprisingly well in motion. I can't prove that though b/c the animated gifs are too big.

That last one might work especially well to highlight the killer/killed in each flashback. Or not. After all this work I'm still not sure where or if it'll end up in the game. I really just wanted an excuse to post those maze-solving animated gifs.
2  Feedback / DevLogs / Re: Return of the Obra Dinn [Playable Build] on: July 11, 2015, 08:29:16 pm
Weird question, I've been noticing that all the rendered lines look really nice and easy to see. Is there anything you specifically did to make them look like that, or did they just turn out nice on their own?

Probably the only particular trick is ensuring that they're always 1 pixel wide, which requires some special handling in the post-processing shader. There's a post here (and some afterwards) about how the lines are rendered.
3  Feedback / DevLogs / Re: Return of the Obra Dinn [Playable Build] on: July 11, 2015, 08:05:10 am
Back to Ship Modeling

I've finally got the entire ship roughed in - all rooms, areas, etc for the top, gun, orlop, and cargo decks. Fitting everything in was a bitch. They didn't design these ships for first person adventure games unfortunately.

I've had to add buffer space here and there to give the player enough room to move around comfortably. And because the ship has to properly articulate for the different flashbacks I couldn't cheat and leave out a critical capstan or threading hole for the anchor ropes for instance.

At the moment I'm going through and decorating each deck. One of the key ways to identify people will be to recognize which rooms they spend most of their time in. So, for example, the carpenter's room has to look the part. This bit is pretty fun to work on.

An in-progress Maya shot of the orlop deck. It'll get a lot busier before it's done:

Orlop deck

Also, this is what OCD looks like:

Old carpenter's walk - off-center grating and passageway width varies along the ship

New carpenter's walk - more centered grating and consistent passageway width

That took ~4 hours to "fix"...
4  Feedback / DevLogs / Re: Return of the Obra Dinn [Playable Build] on: July 10, 2015, 06:39:35 am
[...] You could make marking something in the Muster Roll permanent, too, since you can't exactly erase ink. After you decide on the fate of someone and mark it in the ledger, you get some sort of feedback from the family themselves - a line of dialogue or something small like that. Your role as investigator and arbiter gains some narrative weight, and it's harder to play the game "wrong".

There's a cool idea here. This game is probably too fantasy-oriented to work exactly like this - I'm not planning on injecting any pathos for the families, or including them at all really. But the idea that the fate entries have to be "finalized" before getting feedback is interesting.

Maybe I could have a "finalize these fates" button on each page, or a global "finalize all current fates" that can be used X times. Then you can "spend" those finalizations to find out if you're correct. Players could game this a little bit into something like Mastermind, but not much. Or they could wait until the end and just hit it once and get some special reward if they're all correct.

I think this is at least better than instantly getting feedback on page 1.

okay this is fantastic, despite the fact that when i looked at the sky with white pepper noises i feel like my screen is going to explode at certain extent, everything is so nice and unique!

I promise to fix the sky :D
5  Feedback / DevLogs / Re: Return of the Obra Dinn [Playable Build] on: June 25, 2015, 06:41:04 am
80 > 60

Finished sculpting and painting faces for 60 passengers and crew. 

From a distance

There's supposed to be 80 people in the game - I'm cutting the remaining 20. If I find an easy way to add them back later in I may go for it. 60 is way too few for sailing a boat of this size (120 would be a realistic minimum), but I just don't think I can build out that much content in a reasonable time. The character models themselves aren't actually that hard, it's integrating the characters into the story, adding them in flashbacks, and making sure the player has enough information about each one to deduce their identity. Also there are some UI issues with enabling the player to efficiently sort through that many characters; even 60 will be a bitch.

Feature Randomizer

At my fastest, I was able to sculpt+paint 6 faces in one day. That rate was mostly thanks to a simple feature randomizer tool I built from blend targets. I could either select the features manually or hit a button to generate randomized facial geometry. Most combinations were useless but after a few clicks something inspirational would come up that I could tweak and paint fairly quickly.

Making heads from randomized blend target sets. Textures are hand-painted after finding something good.

Reference and Consistency

Most of the faces are just sketched from my imagination but I did use references for some. Referenced faces took a lot longer, and the detail gives them a slightly different look. Overall I wasn't able to stay very consistent with my technique. Some faces are realistically detailed and some are more painterly. Luckily, in-game this comes across as making the characters look unique (a useful thing for the mechanics) as opposed to out of place. Another benefit of outputting to 1-bit 640x360.

Russian sailor reference and hand-painted result

Two different characters. Left is off-the-cuff, right is from reference.

Accessories Etc

The next step for the characters is to model and attach all their clothes and accessories and add unique scars/tattoos/etc. That process is pretty straightforward so I may take a detour and assemble some flashbacks first. Would be nice to know if 60 people is actually enough, and how hard it is to arrange that many characters.
6  Feedback / DevLogs / Re: Return of the Obra Dinn [Playable Build] on: June 25, 2015, 02:25:00 am
Did you find a solution to the magically open doors?
You could do something such as when the flashback ends, the player is in the position where he was in the flashback. That way he can be behind doors that were closed, and can undo a latch or just open them from the inside.

I don't have a good solution for this yet. Restoring the player's last flashback position is potentially way more complicated than it looks in the dev build. The configuration of the ship (cargo, crew, broken stuff) will change a lot more between flashbacks so some places you could stand in a flashback won't translate to the current time.

More than that though, I kinda like the idea that viewing a flashback is completely passive and you're always reset afterwards. I'd really like a better mechanic than "magically opening doors" but part of the problem is that I only plan on having 3 locked door gates in the whole game. So either I integrate a proper mechanic and use it a lot more or I punt on the whole thing and just swing the doors open when needed.
7  Feedback / DevLogs / Re: Return of the Obra Dinn [Playable Build] on: June 02, 2015, 10:00:25 pm
These tools are amazing. You make me feel like I don't push myself nearly hard enough with my own games when I see you putting this much detail and attention into your work. Inspiring and soul-shattering all at the same time.

Thanks! Don't sell yourself short though. I just played your Masochisia alpha and it's great.

The only thing that I did not find cool amazeballs is in a previous post it seems that you used the 8-head proportion for the characters.
The 8-head is an heroic, super-hero proportion, if you are still changing things regarding character models I would suggest playing with 6, 7 head proportion, just to see how it looks.
But then I am not a 3D artist, and it is not a big deal either.

This is good feedback. I'm not a fan of hero proportions either and I chose an "average male" reference of 7.5 heads for this game. That seems pretty normal after a quick google check.

Something I have found though is that due to the first person view/perspective, the character's proportions feel more top-heavy in-game. Changing it to 6 or even 7 heads might push things a little too cartoony so I'll probably just leave it where it is. I will keep this in mind though, thanks.
8  Feedback / DevLogs / Re: Return of the Obra Dinn [Playable Build] on: June 01, 2015, 06:41:28 pm
Do you feel pretty confident that most of the tools (and scripts?) you've written so far have (or will) save you time and hassle in the long run?

Well, I hope it'll save me time in the end. It's really distracting for me to work with inefficient tools so I'm always tempted to smooth out any rough edges. I guess that motivates me more than something concrete like saving X hours or whatnot. I try to be a little careful though. One reason why I avoided Blender for this project is that I could get seriously sidetracked making source-level changes there.

Are you thinking through the plot and puzzle flow throughout the process?  Have you come across anything that's caused you to reconsider the scope of the game?

Yeah, I'm always rolling the plot/characters/flashbacks/fates around in my head. The only big semi-recent change is that I'll probably limit the number of flashbacks to ~20. I was originally thinking around 60 but that's both too much work for me and too open of a playing field to sort through for the player. So there'll be a fair few characters that either survive, die "off camera", or die simultaneously.
9  Feedback / DevLogs / Re: Return of the Obra Dinn [Playable Build] on: June 01, 2015, 01:07:55 am
Thanks again everyone for the encouragement. Right, then.. character tools.

Character Tools

From the start of this project I knew creating all the sailors was gonna be a huge task. I looked around at various "create a character" libraries and wasn't impressed so I decided I'd just try to make them all myself. For the dev build I settled on a pretty basic system of blend targets applied to a common base character, with animated weighting to switch between them. That worked ok for a few characters in a few scenes but I could see pretty quickly that it wouldn't scale up to 80 characters in >20 scenes.

It took me a while, with lots of trial and error, and now I've finally got the character pipeline sorted. My goal was to be able to quickly create characters as both original builds and as components of existing pieces. I also wanted to keep things fairly flexible so I could build characters piecemeal - going back to edit or adjust them whenever I felt like. The current result is a set of tools: ObraHumans, ObraPainter, ObraSculptor (all Maya MEL-scripts), and ComposeHuman (Haxe command-line app).


This the main tool for creating and editing characters in Maya. There's no special meaning for "human" here, I just went through most of the obvious names with previous tools (character, crew, sailor, etc) and wanted something new.

Flipping between characters in the ObraHumans tool

For this game I've modeled and rigged only a single base "neutral" character - unique characters are created as variations of this. Each unique character is made up of:

  • The neutral base body mesh (rigged)
  • Blend targets on the body for changing features (always 100%, non-animated: face shape, injuries, expressions, etc)
  • Separate hair/clothing/hat/etc meshes (optional)
  • An overall scale (applied to the rig, so elongating limbs instead of a raw scale factor)

Switching between characters is a process of applying blend targets, showing/hiding different piece meshes, and setting a rig scale. The script handles this for me and I can easily add variations, new clothes, hats, etc, then choose them from the drop-downs for any character. It works a lot like a typical character builder, just integrated into Maya and organized for easy additions.

Adjusting pieces/targets/clothes on one character


ComposeHuman is a command-line tool for compositing the texture layers. The compositing logic is based on the stuff I wrote about earlier, encoding a sort of alpha value into RGB-painted textures. I originally had a fairly complicated process here but moving that complexity to the ObraHumans script let me simplify ComposeHuman a lot.

ObraHumans calls out to ComposeHuman whenever adding or removing a piece to a character. That updates the texture and it's reloaded into Maya. In the end, each character has two unique textures (body and clothes) that are composited based on the selected pieces. Most pieces just use the body texture but some clothes actually have to overlay the body and need the separate texture for that.

ComposeHuman has just two modes: "build" or "paint". Build does a simple composite:

> ComposeHuman build seaman2 base-male face-seaman2 pants-long

Compositing layers into a single texture

Paint mode also composites but tints the base layers so they can later be separated. This is the texture that I paint on directly using ObraPainter (explained below).
> ComposeHuman paint face-seaman2 <workingDir> base-male

Paint-ready texture with ignored pixels in blue/cyan


ObraPainter is the MEL-based painting script. Maya's built-in 3dpaint tool is so limited and buggy that I needed to add a bunch of workarounds and features to get a smooth pipeline. ComposeHuman was a big part of that (all the alpha-in-RGB and compositing stuff) but I also had to add a custom file-based undo/redo system since Maya's was so flaky. And the ObraPainter window includes the most useful shortcuts for brush colors, alpha values, showing wireframes, toggling reflection, etc.

All the actual painting is done in Maya by hand on a Bamboo tablet. For non-stroke stuff I can also quickly edit the texture in Photoshop - to shift some pixels around or whatever.

Painting a character


The last character tool is a simple mode-switching helper. Since all of the character variations are defined as blend targets for the base body mesh, I needed an easy way to edit these. You don't want to edit the base mesh directly, and you don't want all your blend targets hanging around visible in your scene most of the time. That's what I had while making the dev build and it was getting way out of control. So ObraSculptor just unhides the desired mesh and sets it up for vertex editing.

Sculpting a character's blend target

In Use

With all this character tool work mostly solved I've been able to start proper arting on the sailors. It's a huge relief that the pipeline actually works ok. Everything is fast enough that I can make around 2 characters per day, which puts me on track to finish all of them in a month or two.

Right now they all look sorta samey, especially in-game with 1-bit rendering. I'm not too worried about that as most people do like kinda similar anyways. Still, identifying sailors by appearance is important in this game so hopefully after adding clothing variations, tattoos, and other custom stuff they'll differentiate more.

Here's a few faces I've done so far:

10  Feedback / DevLogs / Re: Return of the Obra Dinn [Playable Build] on: May 28, 2015, 12:31:28 am
Tool Talk

Making this game by myself has been something. I like changing between the multiple tasks often but I've learned that in my heart I'm more of an engineer than an artist. Drarring n stuff is great but what really keeps me happy is writing code. Obra Dinn is overall a fairly straight-forward game technically so that itch doesn't get scratched as much. I often find myself making excuses to write code instead of model or draw.

One of the best ways to quench that thirst is by writing tools. A good tool can save a lot of time and given how over-my-head I am on this project art-wise, I need all the time savers I can get. Here's a couple Maya tools I've written to both keep my inner engineer happy and my inner artist lazy and unproductive.

Wrapped Ropes

More rope scripts. As I was filling some of the lower decks, I had a need to secure objects to keep them from moving around. As before, nothing gets used as much on a sailing ship as a good rope. You'll often see ropes wrapped around things to keep them in place. Unfortunately, wrapping ropes around things is not a well-supported feature of most modeling packages. I took a stab at using extruded splines, but lining up the points just right is a huge pain. And any adjustment to the objects being wrapped requires basically remodeling the ropes too.

Mel script and a fun technical challenge to the rescue again. In this case, I decided to specify rope-wrapping volumes that get intersected with a set of target objects to define a convex hull, which is then munged to get me a nice closed rope. Here's an example where I need to secure two galley stools to the fore mast:

Rope volumes used to generate wrapped ropes


If I move the stools around or add another object there that needs to also get wrapped, I just hit Ctrl-R twice and it drops me back to the original volumes and regenerates the ropes. A few more examples:

Wrap everything securely

There were a lot of little quirks to getting this working right, mostly due to Maya's totally worthless boolean operations. Boolean ops for arbitrary 3D models is a difficult problem - solved convincingly 30 years ago. That Maya's boolean ops don't just work in 2015 is some kind of criminal offense. Anyways, I lucked out that the rope volumes are always closed box shapes. I can just use plane slicing instead of actual boolean intersections for the operations I need.

What is nice about Maya is that this procedure was possible in Mel without any complex math programming. Mel is a pretty crappy language altogether, but it's very domain-specific and you're able to plug directly into all (most) of Maya's built-in features. So things that you'd normally write a big complex model editing function for can usually just be done with one or two Mel commands instead. Sometimes you need to get a little clever to get what you want but that's fun too.

Tiedown Ropes

The first cousin of wrapping things with ropes is tying them down with ropes. Actually tiedowns are probably more important than wraps, but I didn't have a need for these until later. The basic idea is to again have a rope volume that defines where a rope attaches (at two ends) and where it passes over to "tie down" something.

Generating tiedowns over a set of crates by script

This script re-uses some of the logic of the wrap rope script and integrates it with the rigging rope script. So the rope volumes here are used to first generate a convex hull over the target shapes. Then a spline is built along that hull down the center of the original rope volume. That spline is then passed through the rigging rope logic to extrude it and put anchors at the ends. The nice thing is that, once the anchor points are marked with two red vertices, the rope volume can encompass any shape and look ok.

These would be pretty laborious to model by hand


I made a bunch of character tools too. Will post about those soon.
11  Feedback / DevLogs / Re: Return of the Obra Dinn [Playable Build] on: May 27, 2015, 11:12:02 pm
Hey guys! Still alive! Still working!

There've been a bunch of small things keeping me from posting here, biggest one being that a lot of my work in the last 2 months or so has been on tools and there's just not much to show. I'll make a post about some of those tools in a minute though.

How much time do you think it will take/takes at this point to play through the entire game?

Honestly I have no idea. I think in the end it depends on how streamlined I want to make traveling between all the different flashbacks. I could make that quick and easy or I could make it ponderous as in the current dev build. I prefer quick and easy even if it shortens the overall game time.
12  Feedback / DevLogs / Re: ◁ DO NOT CROSS ▷ on: April 12, 2015, 01:57:56 am
Wow! Love the concept and the art. Your first-person view looks especially great.
13  Feedback / DevLogs / Re: Return of the Obra Dinn [Playable Build] on: April 01, 2015, 02:41:14 am
what I was wondering: do you have night and day-scenes? does the sun position change in your flash-backs? If I recall correctly you are not always jumping back to the same day/time. the last composed image would have to be night, but the shadows are strong. I hope the moon is up Smiley

The moon is up, but yeah I just now notice that the screenshots seem weird with the bright light and black sky when the moon is to your back. It feels ok when you're in the game when you can see a bit of the moon light source though.

Are you changing the mesh geometry each frame? That's the only way you'd be sending a lot of stuff to the GPU. Mesh data resides on the GPU's memory after it's allocated by the driver. I'd say it's likely the slowdown was because of Unity dynamic batching breaking down due to your multi-pass shader, resulting in excessive draw calls.

Except for a few small objects, all meshes are static and marked for static batching. There's not much room for dynamic batching to help. I render each pass with Camera.RenderWithShader, not as in-shader "Pass"es. I don't know even know how to do it in-shader with a render target switch between passes.

Also, the old sectioning pass used very fast forward rendering and the old lighting/sectioning pass used deferred. The new single pass is just deferred. So there might've been room for multipass optimizations, but it's hard to make guarantees about Unity's batching and it'd never be as fast as a single pass.
14  Feedback / DevLogs / Re: Return of the Obra Dinn [Playable Build] on: March 28, 2015, 07:54:54 pm

Working on the lower decks, some performance problems have been building up for awhile now. Even though the game's resolution is super low and there's no obviously fancy surface shaders going on, the geometry/object count is pretty high. Normally that wouldn't be a problem but since the 1-bit rendering technique requires two passes, sending all the geometry to the GPU twice eats up a lot of frame time. Yesterday I decided to sit down and see if I could get all the rendering done in a single pass (plus post-processing). 

The Old Way

The original technique required rendering the scene in two passes:

Scene Pass 1: Sectioning 

The sectioning pass just draws the vertex colors, which have been pre-processed to define areas that should be separated by edges. Wireframe lines are later drawn along these edges in post. 

Old method: Sectioning pass

     RED = Tool-generated random hash (lower bits)
     GREEN  = Manually-set adjustment color
     BLUE = Tool-generated random hash (upper bits)
     ALPHA = unused

Scene Pass 2: Lighting/Texturing

Lighting/texturing runs the full Unity SurfaceShader pipeline to generate lightmaps + dynamic light + textures. Dithering and other logic is applied to these results in post.

Old method: Lighting/texturing pass

     RED = Light value
     GREEN = Markup value (0: normal, 0.5: ordered dithering, 1:dust)
     BLUE = Texture value
     ALPHA = unused

Post-processing Combiner

These scene passes are written to two render textures which are then combined in a post process to make the final buffer. Having the light and texture in separate channels from the lighting/texturing buffer enables me to adjust their gradient ramps separately, which I use to make the hard shadows and blown-out textures that help with legibility.

The final post-processed output, 30fps

Separating the two passes like this makes sense for a couple reasons:

  1. Easy to visualize the two main features of the rendering style: wireframe lines and dithered 1-bit surfaces
  2. Two 32-bit RGBA buffers gives plenty of space for the data.

Both of those reasons aren't worth the framerate hit though. Unity's not very good at reusing scene data for subsequent passes, so even when the sectioning pass runs at +100fps, sending all the geometry twice bogs things down too much.


So the goal was to combine the two scene passes into one with the hope that performance improves on lower end video cards. That last bit is important because it precludes me from using MRT. For a single pass, everything has to fit in 32-bits.

One particular complication is that Unity's SurfaceShaders by default don't allow writing to the alpha channel, so you're effectively limited to just 24-bits in an RGBA buffer. I tried to be happy with that for a long time before finally tracking down a fix, which just became possible in Unity 5.

The problem. Alpha being "helped" to 1 for all surface shaders.

You can't easily edit the generated code directly, but you can redefine the offending macro in your own code, which is thankfully included after UnityCG.cginc:

The fix requires undefining the macro in your own surface shaders

With that, you have use of the full 32-bits and can write anything to the alpha as long as it's non-zero.

Single Scene Pass

So now I just had to pack 48 bits from the two separate passes into 32 bits for the single scene pass. The basic idea was to chop off the lower 8 bits of the sectioning hash (leaving 16 bits), reduce the lighting/texturing output to a single 8-bit channel, and use the alpha as a markup value to specify which "pass" the RGB values were coming from. Because the final output is dithered 1-bit, very few bits are actually required for the lighting/texturing. The result:



I was also able to use Unity's shader Queue tags to control draw order: set the sky shader to "Queue = Background" and the dust shader to "Queue = Transparent". 

Post-processing Combiner

The post-processing step now just has to do the edge detection (with 2 channels instead of 3), the darkness check (to invert wireframe lines in darkness), the dithering (bluenoise or ordered based on the alpha bits), and the dust inversion. There is some extra cost to doing more of the lighting/texturing combination in the scene shader instead of the post processing shader. But the final output looks identical to the old two-pass method, and it runs significantly faster.

Single scene pass, 60fps

Optimizing Early

There's always a danger in doing optimizations like this before the game content is mostly done. Now that I have an extra 30fps to work with there's a good chance I'll paint myself back in to poor performance. A common trick for smarter programmers is to keep a few secret optimizations in their pocket until the very end. If you optimize too early, the artists will just fill up the scene again and you'll be in a spot where it's much harder to get in framerate. I'll have to rely on self-discipline instead.

I am glad this worked out ok though. There's a (justified) perception that a 640x360 1-bit game should not have framerate problems on any machine. There's a lot going on behind the scenes that makes the rendering more intensive than it looks initially, but I'd rather match the perception than make excuses.
15  Feedback / DevLogs / Re: Return of the Obra Dinn [Playable Build] on: March 15, 2015, 09:02:06 pm
[...]Out of curiosity, have you tried talking to a historian about the game? I'm sure there must be some out there willing to help...[...]

I've thought about it off and on. Actually it's a great idea that I'll probably follow up on a little later. If Panurge isn't careful I might hit him up for a few things.

Have you read the Master & Commander series of historical fiction novels? Apart from being super reading they are also set in the same time period & go into lots of carefully-researched detail.

So far I've tried to stay away from fiction. Everywhere I look these novels come up though so I'm currently teetering on the edge of reading at least the first one.

working hard... researching hammocks... Smiley
I wasn't going to say anything, but I think Crawl would have been vastly improved if a little more attention had been paid to the hammock physics.  Wink

16  Feedback / DevLogs / Re: Return of the Obra Dinn [Playable Build] on: February 24, 2015, 05:28:05 am
You probably don't need any more book recommendations but 'The British Seaman' by Christopher Lloyd (not that Christopher Lloyd) is pretty good, as is 'The Wooden World'.

I'll grab both of these, thanks Lee.

Your attention to detail is what sets you apart from your peers (Also the fact that you're still on TIG and devlogging your work after finding success). Cheers!

17  Feedback / DevLogs / Re: Return of the Obra Dinn [Playable Build] on: February 20, 2015, 03:42:59 am

Researching the period, the ships, and the sailors for this project has been a lot of fun. It's not so much a dedication to accuracy as it is having no idea where to even start and needing the reference. The only problem is most of the information covering these topics is in books and most of those are old and/or expensive. And whereas there's a ton of information about Ships of the Line and Nelson's Big Heroic Whatever, there's much less on the merchantmen. Where I can, I try to dig up PDF or Kindle versions online.

Digital reference

If I can't find a digital version then I have to look for a physical copy. All the good ones are no longer in print so I've been buying mostly used books.

Actual books, made of paper

Reading through the really old books is enlightening. Some are proto-OCD material, where every detail is listed in the driest possible tone. And there were a lot of details about the East India Company and their ships. Better books have a little flavor that chips away at the EIC's shiny exterior. All the ship porn is great. When this is all over I kinda want to buy (not make) a big wooden model ship.


I'm working on the lower decks now and every once in a while, the stupidest things take forever. On ships like this sailors slept in rows of hammocks hung from the ceiling. I wasted a bunch of time modeling these.

Exhibit A: Ship hammock

My first mistake was ignoring this basic structure and trying to model a more complicated hammock, with support bars. Second problem was trying to use dynamics to form the hammock naturally. Maya's dynamics are pretty good but as usual trying to use their editing UI is an exercise in rage control. After some poorly-controlled rage:

Not using this hammock

Finally I threw all that shit out and just modeled a banana-shape that's much simpler, way fewer polys, and looks better in context anyways. The dynamics hammock was cool in some ways, but too much work to set up, and too many polys. I may go back and hook up the simpler hammock to dynamics if I find it hard to add the sleeping sailors by hand.

Bad, bad, good.
18  Feedback / DevLogs / Re: Return of the Obra Dinn [Playable Build] on: February 20, 2015, 12:52:01 am

You've basically hit on the two main challenges with the design.

1. Where are all the corpses?
2. How can the story/revelations be structured in a way that makes sense.

#1 is tricky because any dead body would've been quickly pitched overboard. So it's inherent to the setting that there not be a bunch of bodies around. I have a relatively simple solution for that. It requires careful sequencing of events but not much beyond that.

#2 is a lot harder. People don't give a lot of exposition in the ~15 seconds before they die. Well, not in good stories they don't. But that dialog just before dying is all I've got to communicate anything complex to the player. This is a nut I haven't cracked yet. I first want to focus on the mechanical requirements - the player has to piece together the identities of the crew. Once I'm confident with that I can weave a larger narrative into the functional parts.

I'm still worried about both of these problems though so no promises.  Grin

If you haven't read it already, I suggest the seminar work of Peter Linebaugh
The Many Headed Hydra, even though it covers a bit earlier period.

I'll check it out, thanks!

Uncharted is an action game though, right? I think you can get away with this in a slower paced game such as this.

Yeah, you're right. I've sorta bitten off more than I can chew with this game though, and this is one feature that would only get in if I had time to spare.
19  Feedback / DevLogs / Re: Return of the Obra Dinn [Playable Build] on: February 08, 2015, 12:52:14 am

The basic outline of the story is more of less decided and I'm currently doing some research to fill in the details. Reading this book for some inspiration:

A collection of naval disasters, published in 1813

I've learned two things:

 1. Life was cheap in 1700-1800
 2. If you want to survive a shipwreck, sneak off in the working launch boat ASAP before anyone notices.

There's nothing in here I can use directly but it's useful to get the tone of how shit hits the fan so spectacularly when a sailing ship runs into trouble.

Surprisingly the biggest problem I have now is how exactly to lay out the crew. I can't find a good list of specific crew roles for merchant sailing ships of the time. The muster role in the dev log is all just placeholder. Will probably just wing it and make something up soon.
20  Feedback / DevLogs / Re: Return of the Obra Dinn [Playable Build] on: February 04, 2015, 08:59:47 pm
[...]Judging by the animated screenshots, all wind animations (ropes and sails) look maybe some 200% too fast. [...]

Good eye, but I think this is just the gifs. The wind animation combines some fast low-amplitude waves with slower bigger ones. It looks ok in-game.

[...]Do you have any plans in mind to turn the crew muster roll into something more physical, so that when you press tab it seems like you are opening a book rather than accessing an interface?

I may add something like this but it's not a high priority. Uncharted 1 shows an animation as Drake brings his journal up to read it and that slight delay, even though it looks cool, always bothered me. So if I put an animation in there it'd probably only show the first few times you open it.
Pages: [1] 2 3 ... 16
Theme orange-lt created by panic