Comments

Weather duty

Hi there! While kinnas and the art team are busy concepting and modelling away, I’m on day/night cycle and weather duty. The main challenge here is to squeeze as much visual variation out of as little pre-rendered pixels (and final game size) as we can. We wouldn’t want to be rendering separate background images for day and night, snow and rain, etc.

The above is also the reason we are not going purely 2D but instead using very basic 3D geometry as a canvas. This gives us some extras like partially real time shadows (see below) and visual feedback when placing in-engine assets like characters.

Interior vs exterior lighting

L5QXrLrKinnas has only mentioned interior rendering because lighting interiors and exteriors is a very different task and warrant different optimizations and even separate shaders to make them efficient.

The main difference between the two being the behaviour of natural light. Exteriors have pretty much uniform light direction at each point in time, with light and shadows changing direction throughout the day. In contrast, interiors have light shine in from the windows (that is, each room having its own light direction which stays constant throughout the day) and daytime modulates only the light’s intensity and warmth based on the window’s direction. The latter is achieved by kinnas’s mentioned lightflow map and screencaps above.

Lighting exteriors

Since interiors have quite diffuse shadows always pointing away from the windows, we can get away with a single shadow map for the whole day cycle. Exteriors, however, are not so forgiving. You have the sun forming radically different shadows as it travels across the sky. To make those shadows happen, we would need to import enough geometry to make them detailed enough and it still wouldn’t look as good as a pre-rendered raytraced shadow.

So we are not going to do that.

We are going to bake shadows for morning, noon and night and use time manipulation and weather trickery to make them work so the player won’t notice. Here’s an excerpt from a map with the three shadows for evening, noon and morning.

LOUIguY

6w0ayCZ

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Et, laboriosam, harum. Aspernatur enim repudiandae vitae inventore iure mollitia hic culpa illo sint harum, magni doloremque numquam molestias, officia debitis magnam, possimus vero? Voluptatibus itaque quae, quibusdam labore. Voluptatibus, excepturi voluptates.

These channels are to be multiplied to the background albedo map each at a certain time of day. Lack of a color means that spot is in shadow and the brightness of red, green and blue means the area is lit at the corresponding time of day at that intensity.

8KWZDaS

Here’s the result switching between the shadow maps with light and shadow color grading going on as well:

I might still play around with some ideas to keep it pretty but pack the shadow information down to something less than full-size RGB map.

Also note that shadow casting between the characters and the background is real time (based on our super simple world geometry) which still needs work and is another can of worms to be discussed in another post.

Some of the switching between the pre-baked shadow states can be handled by summoning clouds for an overcast weather but that would look suspicious three times a day. We’ll need some classic card trick misdirection while the player is busy and shuffling between interiors and exteriors.

A quick weather generator

Switching shadows and daytime isn’t enough though, a world needs weather to be believable. Since these two things go hand-in-hand, I’m also doing the rain dance.

Here’s a span of three days starting out with a warm but rainy evening and half a day of snow and fog on the morning of third day.ma4QKul

Generated by adding up some sine functions to make random but plausible looking weather data

This is what the graph says:

  • X axis is for days (full numbers being midnight, n+0.5 midday)
  • Y axis is for temperature/probability.
  • blue: air temperature
  • red: dew point temperature
  • orange: precipitation (red minus blue)
  • green: fog probability

The weather generator itself is going to use the above data and follow very simple rules:

  • If precipitation is above 0 and temperature is above 0, it rains.
  • If precipitation is above 1.5 and temperature is above 2, there’s lightning.
  • If precipitation is above 0 and temperature is below 0, it snows.
  • If precipitation is above -0.5, green dictates amount of fog.
  • Precipitation levels between -1 and 1 give us varying amounts of cloudiness from clear to overcast to gloomy. (should have called it humidity)

With some tinkering, these functions and rules result in mostly dry weather with some foggy mornings, now and again some rain and the occasional snowfall and the very rare lightning.

Now that we have meteorological data generated, let’s have it modulate our lighting and weather effects.

Raining makes things wet

bejoVBLI misuse a shadow map to mask whatever comes down from sky. Looking from straight above anything in “shadow” remains dry and rest of the scene gets affected by rain, snow, hail, etc. As it comes out, this a very fun map. I can rotate the caster to simulate wind. I can add the wet areas to background’s spec map to really make it wet. I can use edge detection to map splashes under the eaves and edges of objects. With some work, I can even wet the background spot by spot instead of doing it uniformly. Finally I can use the sun’s shadow map to dry it off at different rates. Sounds like pet project material, I’ll keep you updated which of that I can squeeze in. I should probably get back to the big tasks like day/night cycles and the actual weather machine.

Unrelated

K7BNpjO

Here’s some normals debugging for a piece of UI.

Comments

Shedding light

Hi there.
I am the technical artist of this project, chiming in with some technical tidbits. Gentleman

Interior lighting system

tl;dr: this scene has no in-engine lights. All lighting is computed from:
– RGB neutral render with paintover
– BW shade/light multiplier map encoded into albedo map’s alpha channel
– RGB light direction map
– global sun/shade color variables for each time of day

Additive shade map didn’t work out because it tended to have inverted color information in dark areas (pretty obvious in hindsight, duh). Converting additive map into BW resulted in super-saturated dark areas (pretty obvious in hindsight, duh).
Multiplicative light/shade map seemed to be acting nicely if it weren’t for the 0-to-1 clamp of the PNG format. Let’s not go into minifloats or EXR for now.

Enter the arctangent encoding

You take a value from 0 to infinity and arctan() it to squeeze it into the 0-1 range. You take the map in engine and do a quick tan() before multiplying it onto your map. You have high resolution near 0 and degrading accuracy towards infinity which hasn’t been detectable by eye as of yet.

Lightfield map

This (currently hand-crafted) map describes the direction and magnitude of a single ray of light in each point of a 2D space. So technically a very very simple lightfield wannabe. This is a vague, efficient and apparently good-enough description of which direction the natural light is coming from. This technique relies on lighting conditions being very low frequency and similar on and behind the objects and characters.

The white blobbing you see there is alpha channel we are using to map out faux indirect illumination where low alpha values near the windows result in a strongly directional light with stronger shades/shadows whereas high alpha values mean light bouncing around more. So the shaders wrap more light around objects and lighten up shade/shadows a bit.

Highlighting of interactables

This was apparently a headache and a half! I consider myself pretty knowledgeable in common game graphics techniques but it came as a surprise that apparently finding the outlines of 3d objects is a relatively difficult task. Shows what I know. I’m told it’s done by enlarging 3d objects along the normals? We ended up using masks and edge detection for various reasons but that’s another post by kuubaas waiting to happen.

As we witnessed while testing, the normal-extruded outline method is and looks cheap.
For now I’ll just say we use shader replacement to render a mask RenderTexture which is then edge-detected. For silhouette outlines it’s less hassle, more reliable and looks better than any geometry-based solution I’ve seen. (you also get free AA with edge detection, yay).
It’s quite a plain vanilla solution but the colouring technique could be interesting to write further about. Will do a post this month.

Comments

So the first month of 2016 has come and gone

So the first month of 2016 has come and gone. We begun January with finishing up the prototype we made for Christmas. The game was far enough along that dialogue was sort..of.. displaying? You could click a button to open up a facsimile of a dialogue window which read content from an xml file. The basics of importing text from Articy into Unity was in place. You could select your options and get your answers based on the dialogue node tree.

Some stuff didn’t work so well however.. The main character was a black ghostly silhouette of a man which could path-find its way around but on some computers got stuck in a Lynchian horror nightmare where you run as fast as your legs can go yet move at a glacial 5cm/h pace. We’ve since fixed that but as with all bugs and graphical glitches it’s excellent dream sequence fodder.

So here’s what got done in January:

Interior lighting system

 

We tried a bunch of different ways to light up our interiors with natural sunlight which would change by time of day. Four states in total: morning, noon, evening and night. For a while we had an additive system which used a basic background image, a neutrally lit render for me to paint over. Upon the background we added a light map with information about how much light and what colour came from which window. This had information on bounced light and transferred colour from object to object. While this gave us beautiful rich colours and a realistic global illumination look it also had the downside of adding several full resolution images to the pile of assets making up levels. That’s a map per time of day + the neutral base map. What’s more the additive layer contained too much information which meant that it tended to overwrite any hand painted brushwork I had done on the neutral background image. So that’s no good.

In the end the breakthrough came while we were trying to figure out how to light up characters in interior scenes.

A naive implementation would have cast the neutral background image in shadow and used in-engine lights to illuminate the scene and light up characters in one go. This is essentially what we do with exteriors during the night. However this method would have looked bland since real time doesn’t really get us that coveted and beautiful diffused bounce light ambience that we can get with prerendering. In the end we lit characters up with a mixture of a lightfield map for natural light coming in the window and in engine light sources for artificial illumination such as desk lamps and the sort. The lightfield map is essentially a normal map which dictates which direction light is moving on any given pixel. It’s also very small since we don’t need it to be terribly precise.

5GTSYGdTurns out that the lightfield map is useful for other stuff as well! We can render out a single channel B&W image of the background as illuminated only by natural light. By using this shadow map with the lightfield map we can dim and colourize background art based on time of day and the weather outside. While not as exquisite as the additive method it’s a lot more efficient, saves us a ton of hard drive space and makes the base background layer the only image with color information which means I’m free to paint over it as I wish!

jxhVvI9

Neutral render with some light hand painted touches, not final in any way or form:

XugKDle

gbolk6Z

Highlighting of interactables

pncnDOx

This was apparently a headache and a half! I consider myself pretty knowledgeable in common game graphics techniques but it came as a surprise that apparently finding the outlines of 3d objects is a relatively difficult task. Shows what I know. I’m told it’s done by enlarging 3d objects along the normals? We ended up using masks and edge detection for various reasons but that’s another post by kuubaas waiting to happen.

Attaching dialogue to interactable objects

Combine this with the highlighting and you have a game! There’s this imposter syndrome article making the rounds on the internet about creatives who feel like they’re still faking it. Not for me, no sir, the moment an object got highlighted on mouseover and clicking on it opened up a dialogue I felt like a super-MLG-pro-designer. What I’m trying to say it it feels good to have immediate feedback mechanics in the game finally.

Character scale matrix

hI7Do7x

We dicked around with a character shape matrix, a simple two slider system for adjusting thickness and height for npc variety using blend shapes. This posed some problems with floating feet but in general the proof of concept implementation seems promising so far. We’re also working on an IK system for placing feet on stairs which might tap into the floating feet problem.

Basic inventory & equipping system

Take all your clothes off, put them back on again, like a normal human being does every day.

Functional doors

They block pathfinding and can check said inventory for keys. Imagine a world with door tech which helps you out by checking whether you have your trousers on or not.