Saturday, September 26, 2015

A handful of tweaks

The updates for this weekend (so far) have been a few smaller changes, none of which individually merit a post of their own. Here's what's been happening:

Lag spikes
Moving around in the world caused noticeably jumpy behavior. After spending weeks adding timers and looking at inscrutable performance graphs, I finally decided to go with my gut. At least one category of lag spikes was pretty obviously happening when the player crossed block boundaries (the terrain in Playform is divided into blocks of 8m x 8m x 8m), so I experimented with effectively disabling different parts of the code that were sensitive to block transitions. It didn't take long to find out that the major offender was the code that updates the render state. Playform has a separate thread to deal with OS I/O (specifically, to deal with all SDL-specific things, since a single thread to deal with SDL and OpenGL is not-uncommonly a system requirement), which includes things like mouse movement, window focus, and rendering.

Because of the single thread (and the message-passing style used to communicate with it), the "move the camera to where the player is" messages weren't being treated differently from the "now start displaying this piece of terrain" messages. Basically, crossing the boundary of a terrain block caused some LOD (Level-Of-Detail) switching to happen, which slowed down the processing of camera movement events (and other events, which were less noticeable, like sun position updates). The solution was to split the updates into two separate queues, and to give terrain changes their own, lower-priority queue. The code is really hacky right now (I mostly just copy-pasted code and added "0" and "1" suffixes to things). I also capped the amount of time (1ms) that a thread can spend on a given task before it "leaves work for next time". The code is starting to look a little repetitive, and I'm considering creating some abstraction for the general idea of "prioritized budgeted processing". where you have several code blocks that have some total budget, and that run in some (prioritized) specified order.

Loading Surroundings
When you start up Playform, your player hovers in the air for quite a time while the terrain loads. I'd like to say I fixed this, but the fix adds some incredible (and unacceptable) lag. I still think the basic idea is sound, though, which is that the server prioritizes "give me this block" requests from the client based on how far the block is from the player. Ideally, the load priority would also favor more recent requests within a given "priority tranche".

Biomes, Mountains
I've added a preliminary stone material for the preliminary mountain biome. This is the kind of thing that feels very productive, even though the code changes are minuscule (I'll pat myself on the back here for making some solid abstractions).



I also accidentally placed a tree.



Internal
Other than those changes, I've made some internal changes: I've created a "voxel" crate, which separates out the generic voxel-y parts of the code; and a "terrain" crate, which separates out the terrain data structures and terrain gen code. I'm creating the crates based on a loose idea of abstraction boundaries of "I want code to exist that I don't actually use, for completionist purposes". For instance, the different biome code, or the different voxel materials. Playform is built with a specific biome in mind, but I still want to have the code for other biomes lying around in the terrain crate.

Saturday, September 5, 2015

Trees are back!

After a long absence, trees have made it back into Playform!

Development
One of the big requirements was the voxel material system, because I didn't just want to have tree-shaped dirt. The leaves are still shaded using the grass shader though, because I was too lazy to work on a better texture.

On that note, you might notice that the terrain has a more textured look! I put some time into making passable-looking procedural texture shaders, instead of the embarrassing sine-wave-based mixing between plain green and plain brown. The grassiness of the terrain is controlled by a noise function (huge thanks to ashima/webgl-noise!), and also the slope of the terrain - the steeper the terrain, the less grass it has, on average.

All this texturing is done in the shaders right now. I do want to eventually move these into real textures, and let the user "paint" the terrain.

The trees themselves are defined through the same code that defines the terrain and the sphere brushes, although this that code's changed a little with the material system. You map every point in space to a material. Since the trees are placed with a brush, it's also valid to say "I don't touch this point". This code isn't the nicest to write: even with the trees as simple as they are right now, there's a fair amount of "wait am I in this part of the tree? Oh I'm not? Alright, how about THIS ONE?" I plan to put some work into composing shapes like trees out of smaller shapes like spheres and columns.

TODOs
The trees don't spawn naturally right now; the user can place them with a left click.

They also all look exactly the same. Branches and better leaves are a must-have. Different kinds of trees would also be nice.