Best posts made by Pavel
posted in MudRunner - Off-Topic read more

Spintires started back in 2008, for Havok Physics Innovation Contest, and here is the first screenshot:
0_1521481888790_screen.jpg

It was originally using OpenGL instead of DirectX, and PhysX instead of Havok!
And original game idea was something like Besiege (which didn't exist back then obviously).

The next idea was aircraft simulator:
0_1521482006162_screen4.jpg

But eventually it evolved into offroad truck simulator:
0_1521482282559__vk2.png

But the codebase started developing even before that! Have a look at one of the first versions of the Level Editor:
0_1521482775204_x.bmp

Thats a pendulum movement research that I had fun with in Institute! 🙂

Best regards,
Pavel

posted in MudRunner read more

Hello guys!
Thank you for continued interest in the game! 🙂

I've seen some people mentioning that there is nothing new in this DLC.
I can understand that, but read this - we finally had a big team or artists working on new trucks and maps - some 15 people or more (all the old maps and content was done by maybe 5 people), plus a lot of people working on securing the license deals for the brands - which I'm sure people familiar with the vehicles will appreciate.
So while it is true that new DLC doesn't bring new features like tracked vehicles, the quality and detalisation is not something we could afford before.
On the other hand, thanks to lots of talented and dedicated mod-makers on PC, new content is not something players can be easily impressed with 🙂

So we've taken time to tune the maps so they are played differently compared to the old maps, giving a bit of a new flavour to the game.

After all, like I've written here before, when I look at Mudrunner, game seems pretty well-rounded and complete to me, so its really time to focus on the next big thing!
I agree that multiplayer part needs a lot of polishing (lights/sounds sync etc) but please understand - it is not a trivial thing to do, and it is much more efficient to do those improvements along with other improvements to the principal gameplay. In the end that would make you recieve new cool game sooner!

Best regards,
Pavel

posted in MudRunner read more

@knight25 It is true that we originally planned to include tracked vehicles into one of the updates to Mudrunner - it was not a lie. But plans have changed 🙂
So thank you for buying MR - but as many people have contributed a lot to this game - me included - I really don't feel ashamed by its quality (especially given the discount to original Mudrunner owners) 🙂 In fact I'm pretty proud of what we with Saber and Focus were able to accomplish!

@ewgenij84 Working mirrors are technically challenging - and it doesnt really add much value to the game itself because you use third-person view most of the time (I've seen many players agree with that and even here we can see some people have never used first person view!)

posted in MudRunner read more

@unster said in American Wilds Update 27/12/2018:

  • Force feedback is still dead unless the wheel is turned off and on in the controls menu.

Hello!
It just got to our attention that force feedback was indeed completely broken, hehe!
Thank you for bearing this, next patch will fix that! (and improve force feedback behaviour in general too)

Next patch will further improve light vehicles performance, which I think is one of the most important things patches can do at this point, given the amout of said vehicles in workshop.

Best regards,
Pavel

posted in MudRunner - Modding read more

@sodoma Hello again!
Thank you for the analysis!
Like I said, I'm sure there are better ways to simulate the gearbox in the game - but I've never even researched that - because the vehicle in Mudrunner is driven by the wheels (physics bodies) - not the engine! And wheels don't interact "mathematically correctly" with the ground.
So before changing the math of the gearbox, we need to change the math of the wheels - that's a planned improvement! When the vehicle starts to move fast, physics bodies of the wheels need to be replaced by the procedural wheels (their positions computed mathematically, and this allows you to compute everything else mathematically) - without player noticing of course.
Thats the easy way 🙂

The hard way is to do our own physics of the wheels instead of Havok - and this is actually planned too, because I want the wheels to be truly soft! Stay tuned!

Best regards!
Pavel.

posted in MudRunner - Welcome Area read more

Hello from Pavel!

So... I've been working on Spintires for maybe 9 years now!

There are a lot of people who helped build and improve this game, from all around the world, some remaining interested in it from the very first versions, and it feels like there is a whole community of Spintires fans - which everyone in our team really value!

We had several releases so far, starting from Havok Physics Innovation contest, then Intel Level Up 2009, Kickstarter version, Spintires Steam released with Oovee, and now MudRunner cross-platform release with Focus and Saber!

First of all, I can see some of the players being frustrated about the game being developed in not exactly the direction they would want. A big part of it is that we still have a very small development team so we have to do each small improvement one by one and it takes a long time!

But rest assured, MudRunner is much better than its predecessor, and we worked really hard so that it won’t disappoint and will just be a fun and entertaining experience for you! Of course there is always room from improvement, and we will support this game with patches and DLCs, with a big emphasis on modding tools.

Stay positive and stay tuned, best regards!

posted in MudRunner - Off-Topic read more

I often use nickname "Kopavel". Thats because when we played Tibia back in school my friends used nicknames "Kolian" (from Nickolay) and "Koleg" (from Oleg). 🙂

posted in MudRunner - Modding read more

@sodoma said in truck lua object:

@Pavel
May I ask you for some kind of presentation how physics of trucks, more specificaly propelling of trucks (engine+gearbox) works? Something as it was there for mud and water. This could be very helpful in here...
Pretty please...😇

Hello! There is not too much to tell, and gearbox physics is not something I'm particularly proud of. So just let me know what exactly you need!

Overview:
Choose number of gears and "optimal wheels angular velocity" (fGearAngVel) for each gear ("Gear/AngVel" XML file parameter).
And engine power (fEngineTorque, "Motor/Torque" XML file parameter)

For each gear, game operates with following parameters:
fGearAngVelMin = fGearAngVel * 0.25 - 2.0
fGearAngVelOpt = fGearAngVel
fGearAngVelMax = fGearAngVel * 2.0 + 5.0
fGearEngineTorque = fEngineTorque / pow(max(fGearAngVel / 2.0, 1.0), 0.5)

"High" (1+) gear:
fGearAngVelMin = 0.4
fGearAngVelOpt = fGearAngVel
fGearAngVelMax = fGearAngVel + 2.0
fGearEngineTorque = fEngineTorque * 1.25

Game computes "engine force multiplier" (engineCoef), based on
minAngVel,maxAngVel - minimum/maximum angular velocity of any wheel (that has torque)

float engineAngVel = lerp(maxAngVel, minAngVel, .5f);
float engineCoef;
if (engineAngVel < fGearAngVelMin) {
engineCoef = 0;
} else if (engineAngVel < fGearAngVelOpt) {
engineCoef = (engineAngVel - fGearAngVelMin) / (fGearAngVelOpt - fGearAngVelMin);
} else if (engineAngVel < fGearAngVelMax) {
engineCoef = (engineAngVel - fGearAngVelOpt) / (fGearAngVelMax - fGearAngVelOpt);
} else {
engineCoef = 0;
}

(lerp - linear interpolation of 2 parameters)
So the actual force that is applied to the wheel is computed like that:

wheelForceMultiplier = engineCoef * fGearEngineTorque * fAngVelSlowdownMult * pWheel->fCurrentTorqueRatio;
(I dropped some of parameters for simplicity)

fAngVelSlowdownMult is a parameter that prevents the vehicle from accelerating too fast (it compensates for lack of real-world inertia of mechanical parts of the engine), computed like that:

fAngVelSlowdownMult = saturate(0.0 - pWheel->fDeltaAngVel / fMaxDeltaAngVel * 2.0);
fAngVelSlowdownMult = saturate(fAngVelSlowdownMult +
max(pWheel->fWheelLinVel - 2.0, 0.0) / 10.0 +
1.0 - saturate((fabs(pWheel->fWheelAngVel) - 1.0) / 2.0));

Here fMaxDeltaAngVel is XML file parameter "Motor/MaxDeltaAngVel".

pWheel->fCurrentTorqueRatio is computed for each wheel based on diff lock mode. Let me know if you need documentation for that (It's a lot of hardcoded math too).

Hope this helps,
Best regards!

posted in MudRunner read more

MudRunner is the ultimate version of Spintires, released on PC, and for the first time on consoles.

Like Spintires before it, MudRunner will put players in the driver’s seat of a variety of incredible all-terrain vehicles, venturing across extreme Siberian landscapes with only a map and compass as their guides.

In this blog, we'll be discussing how we render and simulate water in MudRunner. Previously, we discussed how MudRunner renders mud here.

Let’s take an in-game screenshot and deconstruct it:

alt text

Disable SSAO, FXAA, DOF, Sharpen Effect, Color Correction, Motion Blur and Bloom Effect:

alt text

Taking away the layers in the reverse order they are applied:

  1. Particles
    Probably any game has that kind of effect. Particles in MudRunner can be of two types:
  • “billboard” particles: a quad with spray texture, oriented towards the camera
  • “subparticles”: small bits of substance that collide with water, terrain and vehicle wheels. Spawned in large quantities (about 14000 on that screenshot!) and are heavily optimized (spawned and deleted in chunks of 16)

alt text

LUA scripts are used to spawn the particles. Given wheel and chassis positions, velocities, sizes, current water penetration depth and other parameters, scripts compute initial position and velocity for each particle. The advantage of this approach is that it is very customizable – you can tune particles dynamics in any way you want on the fly. The disadvantage is that this process is very technical.

2. Geometric Water Waves

alt text

This layer actually consists of two different effects, have a look at their wireframes:

alt text

Both meshes are generated on the CPU, with a lot of empirical constants involved, and have a very vague connection with the real-world physics of the water.

3. Terrain Wet Decals (will get back to it later)
alt text

And now we are left with the water surface itself:
alt text

Have a look at its wireframe:
alt text

WATER SHADER

Water in MudRunner can flow in different directions, with varying speed, at any angle, it can have different colour and transparency, and it can get foamy (when vehicles strike it or simply due to its flow intensity). So how does it work?
Any water shader in any game needs to simulate the water waves. There are many different ways to do this. In MudRunner, as you’ve seen above, the water mesh has relatively high tessellation, so our waves are actually geometric. Most simple way (but far from the most realistic) to render the water waves is to mix several instances of texture like this (MudRunner mixes 5 layers while applying different texture coordinates scale and offset):

0_1510391294005__water_texture__.bmp
This texture is actually a procedural noise that you can generate in Photoshop. But different character of that texture yields different character of water surface in a game.

But as will be explained later, if you want your water to flow in any direction at any speed, you will actually need to do the above-mentioned arithmetic 4 times. And if you want your water to be foamy, you will need to do the whole thing with the foam texture too! And that sums down to a lot of shader arithmetic that just won’t work in a real-world scenario. MudRunner’s solution is to pre-mix water waves and water foam texture:

0_1510391884770__water_texture_anim__.jpg
Animated water texture. The only small trick is to make sure those textures can be seamlessly tiled which is easily achieved with some shader math. In the same way, we generate ANIMATED CAUSTICS TEXTURE which we will reference later.

So how do you make your water actually flow? Simple – you scroll the texture coordinates over time. But in which direction, and at what pace? Obviously, that depends on the water direction and water flow speed. In MudRunner, to define water direction and flow speed, map author places “water rivers” in the Level Editor:

0_1510337450913_editor_curves.jpg
Each “river” is a curve with varying width.

When building a level (preparing it for the game), Level Editor generates continuous water surface by mixing all “water rivers” together:

0_1510338520731_editor_water.jpg
Vertices that define water surface. “Rivers” are not used by the game itself.

Map author uses a brush to paint water flow intensity. So in the end, additionally to the water surface, Level Editor generates that A8R8G8B8 texture for the game to use when it renders water:

0_1510338552552_editor_water_tex.jpg
Water data per terrain block (terrain blocks are described in the MUD OF MUDRUNNER paper).

So water shader knows water direction and flow intensity (speed), which is actually merely a 2d vector, let’s call it “flowDir”. They key concept to understanding next step is discretization. It means that we pick one of let’s say 16 possible water directions, a direction that is closest to “flowDir” (let’s call it “flowDir1”), and its “neighbor” direction (“flowDir2”), so that
(here and later HLSL code is used)
flowDir = lerp(flowDir1, flowDir2, flowT);

Where “flowT“ is the interpolation parameter of the two directions.
Having “worldPos” as a world position, water shader can now compute texture coordinates for each direction:
float2 angTC1 = float2(
dot(float2(+flowDir1.x, +flowDir1.y), worldPos.xz),
dot(float2(-flowDir1.y, +flowDir1.x), worldPos.xz));
float2 angTC2 = float2(
dot(float2(+flowDir2.x, +flowDir2.y), worldPos.xz),
dot(float2(-flowDir2.y, +flowDir2.x), worldPos.xz));

Which can actually be used to sample animated water texture (having “g_fTime” as animation time, “tcScale” and “tcScrollSpeed” – arbitrary constants):

float2 tcScroll = float2(g_fTime, 0) * tcScrollSpeed;
float4 waves = lerp(
tex2D(g_samWaves, (angTC1 + tcScroll) * tcScale),
tex2D(g_samWaves, (angTC2 + tcScroll) * tcScale), flowT);

We have omitted the water flow speed discretization for simplicity here, but it follows the same idea, and thus you need the 4 samples to the animated water texture (“g_samWaves” sampler in the code above) which were mentioned earlier.

But the water waves need to be shaded. The recipe for that is pretty common, and it basically involves two components: Reflections and Refractions.

alt text
Refractions: objects seen through water. Notice caustics effect that we will get back to later.

alt text
Reflections: objects that are mirrored by the water surface. To render reflections, you can put the camera below the water surface and point it upwards (“reflect the camera”), then use a technique called “oblique clipping plane”. But that only works well if your water surface is “planar” – which is not the case for MudRunner. MudRunner uses a technique called “Screen Space Reflections” (SSR - this technique is well documented in a multitude of sources). MudRunner uses SSR only for water reflections, so its version is highly optimized and very lightweight. One of the optimizations is, we render the “water reflections mesh” (see picture) instead of full-screen quad, so we know the position of the shaded fragment from vertex shader instead of having to do z-unprojection, and don’t need to do SSR pixel shader for the entire screen.

WATER SIMULATION

MudRunner uses a very simple algorithm to compute water simulation, it involves two A8R8G8B8 textures. In the same fashion as mud simulation, we build and draw special primitives into a render target texture:

alt text
With a knowledge of wheels and chassis positions, their size and velocities, their current water penetration depth, and water speed and direction, CPU forms various “primitives” and draws them into render target textures, which is then read back by GPU. That is pure empirics, and have very vague connection to real-world physics of the water!

The first texture with simulation data looks like this:
alt text
After the primitives are drawn into that texture, MudRunner performs a “GPU simulation shader” that does a simple propagation of foam, water, height and mud parameters to neighbour texture samples. So two instances of each texture are involved: one for read-back, one for output, and they are swapped each frame.

The second texture only stores “WATER MUD”. Note – there are algorithms that simulate much more realistic water dynamics, but they all require floating point textures for the data, which makes algorithm somewhat more resources-heavy.

Let’s have a look at another peculiar effect. For the water render pass, we generate special low-res texture, which we call “water domain texture”:

alt text
Water domain texture uses a concept, similar to parallax effect, and allows mud (not seen at above picture) and foam to be seen “through” the water. It also stores “water flow speed” that we use to pick the mip level of the “animated caustics texture”. The caustics themselves are simply z-projected when water is drawn. Note that water caustics in MudRunner cannot be seen above the water – drawing the caustics above the water would be a nice improvement in the future!

WATER DECALS

As referenced in the “MUD OF MUDRUNNER”, there are 4 types of decals in MudRunner:

  • Mud decals, produced by “mud” particles and applied to the terrain.
  • Wet decals, produced by “water” particles and applied to the terrain AND water.
  • Oil slick decals – produced by working vehicle engine and emulates slick on the water surface, applied to water only.
  • Dry oil decals – same as oil decals, but emulates oil marks on dry surfaces, so applied to terrain only.

Let’s have a look at oil decals:

alt text

The render process is similar to rendering mud decals:

alt text
Water needs to output a mask when it’s rendered, so decals can distinguish the surface type they are applied to. Water also writes screen normals that decals use for shading.

Thank you for reading!
09/11/2017
Pavel.

posted in MudRunner - General Discussion read more

@8up-local said in Gameplay Content and the Future:

i would not say these things are dumb or silly, but more a bit of a long stretch for the way the game is designed really imo. after all this began as a school project about deformable terrain and that needed something to show it off. hence the trucks and has morphed into what it is today to make a sellable product.

@Pavel care to comment and correct me if i am wrong on this?

Hello sir!
Yes, you get it 100% correctly!

Really most of the game design comes from the "Left 4 Dead" - quick game sessions with very simple objectives, stressless. From that point of view, I'm personally quite happy with the current state of the game - and I play it a lot myself, hehe. It doesn't mean there is no room for improvement of course! So stay positive, stay tuned, there are great plans for Spintires/Mudrunner!

posted in MudRunner read more

Let’s take a game screenshot and deconstruct it.

How about this one?

alt text

Let’s start by disabling post-processing: SSAO (ambient shadows), FXAA (softens object edges), DOF (blurs foreground), Sharpen Effect and Color Correction:

alt text

Now let’s take away all the layers in the reverse order they are applied when the game renders a frame.

1. Terrain Mud Decals (will get back to it later)

alt text

2. Wheel Tracks (which we will get back to later)

alt text

3. Mud Particles
Those objects float on top of the mud and are affected by vehicle wheels (can stick to them even), they only act as decoration and don’t affect the physics. Mud particles are simulated by the CPU in a separate thread. A lockless synchronization technique makes this whole effect very performance-friendly.
alt text

4. Mud Chunks
These are bigger chunks of mud, each is a full-fledged rigid body so they interact with the physics world properly and they even break into smaller chunks, when vehicles drive over.
They are maintained by the same systems that simulate and render all other plant types in the game. (A “plant” is an object that is scattered over the terrain in large quantities, like rocks or trees.)

alt text

5. Road Overlays with Parallax Effect.
Roads, that map author places within Level Editor, are then baked into a special data that game uses to draw them efficiently. They are not actually rendered as a separate layer and are embedded into terrain shaders.

alt text

Now we are left with the mud itself, which is a simple heightfield (essentially a 2d mesh):

alt text

Have a look at its wireframe.

alt text

Most of the game level terrain is actually rendered at lower resolution. So if vehicles have not deformed terrain, its wireframe would have looked like this:

alt text

Now let’s take a closer look at each layer…

MUD HEIGHTFIELD
Game levels in MudRunner can be up to 1km x 1km in size. They are subdivided into a grid of 16m x 16m blocks. Each block contains a list of plants (trees, rocks, etc.), base terrain data, mud data (optional), and other data. The game only draws blocks that are inside camera “frustum”. Only blocks that are near the truck that player is driving are “active”. The game only performs plant physics simulation, mud simulation and water simulation for “active” blocks.

The mud simulation consists of mud-vehicle physics processing (performed by the CPU) and rendering of the mud (performed by the GPU). For a number of reasons (the CPU and GPU are out of sync on PC, high level of detail required for rendering is not required for physics, etc..), these two tasks operate with completely different sets of data. We won’t go into details of physics simulation here, but in short, there is no rocket science involved, but it’s not something Havok (the physics engine in MudRunner) can do out of the box.

In order to draw the mud, the vertex shader takes in a simple 2D grid of vertices, then fetches two A8R8G8B8 textures that look like this:

alt text
Texture 1. 25x25 in size for each block, is used for rendering both low-res base terrain and the high-res mud.
R (red) channel – packed height (elevation). This is unpacked into real-world height with a little math.
G (green) channel – grass/dirt materials mix factor. Currently, each block can only mix 2 materials.
B (blue) channel – “tint” factor. Tint adds some color variation to the environment, and illustrates physics properties (“tinted” terrain is softer).
A (alpha) channel – marks portions of base terrain that are substituted by the mud, it’s the only channel that is dynamically updated as vehicles deform terrain.

alt text
Texture 2. 128x128 in size, is only allocated for blocks with mud.
R (red) channel – “mud height”, is relative to elevation of the base terrain. It gets unpacked into a floating point value with simple multiplication.
GB (green, blue) channels – used for “mud offset” effect (the mud slides away from vehicles wheels as they move).
A (alpha) channel – “mud tracks”, a blending factor of the terrain shader into the mud shader, In combination with A channel of Texture 1 that makes mud transition into terrain unnoticeable.

The visual part of mud simulation boils down to properly updating Texture 2:

alt text
With knowledge of wheels and chassis positions, their size and velocities, and their current mud penetration depth, the CPU forms various “primitives” and draws them into a “Texture 2” RT (render target), which is then read back by GPU. That is an approximation and has a very vague connection to real world physics!

The mud pixel shader itself is nothing fancy, and it simply blends few diffuse textures based on the normal which it derives from the heightfield data.

Now let’s get to more interesting stuff…

WHEEL TRACKS
Let’s take another game screenshot and see the steps involved in rendering wheel tracks:

alt text

Wheel tracks are rendered after terrain and most of the environment. So by then we already have screen normals and “wheel tracks screen mask” (which masks a portion of the screen, on top of which tracks shouldn’t be rendered), in addition to the Z buffer, of course. The mesh itself is a simple series of trapezes that follow the path of a wheel. But for the parallax effect, that gives tire treads a cool volumetric look, we first need to render wheel track “heights”:

alt text
Wheel track heights are required for a parallax effect. The textures are projected onto the terrain using Z-buffer. The tricky part is ordering tracks properly (more recent tracks should cover older tracks). There are several approaches to do this, we use GPU-only method: render tracks with their own z-buffer (so no hardware z-test against scene), and offset more recent tracks towards the camera in vertex shader. Z-test against the scene is performed manually inside pixel shader.

The wheel tracks mesh is then drawn again for a second, final, pass:

alt text

Traditional parallax effects take multiple samples from associated “heights” textures and then offsets texture coordinates accordingly (we won’t go into details of the math of it). Problem is, if you are z-projecting your texture onto z-buffer, there is no easy way to make said samples. That is why wheel tracks are rendered in 2 passes. The visual artifacts are neglectable with that approach, you just need to make sure you don’t sample from parts of the texture where you don’t have wheel track height info at (that’s what green mark-up of wheel track heights texture is for).

TERRAIN MUD DECALS

When vehicle’s chassis or wheels move through the mud at high speed, or when a wheel spins in a mud, it launches mud particles. Mud particles affect per-vertex mud data of most of the environmental assets, and they also generate terrain mud decals:

alt text

Each terrain mud decal has a mesh of oriented box:
0_1507645197081__decals.jpg

In the same fashion as wheel tracks, after the terrain and most of environment is rendered (it’s called “Color Pass” and it uses MRT – multiple render targets), we have screen normals (used to compute lighting) and terrain decals screen mask (masks out objects that decals shouldn’t be rendered on top of). Color Pass also write occlusion factor for terrain decals so they can be lit more naturally. Decals are z-projected on top of the scene.

Most of the games now feature z-projected decals, so it’s nothing really fancy. But the same system that generates Terrain Mud Decals in MudRunner actually also generates 3 other types of decals: Terrain Wet Decals, Terrain/Water Oil Decals and Terrain/Water Wet decals! But that’s a topic for another day…

10/10/2017
Pavel.