Archive 17/01/2023.

Playing with Low-poly

Victor

So, I decided to explore a low-poly route for my game after being inspired by Kingdoms and Castles. I think the SSAO post process shader here: https://discourse.urho3d.io/t/ssao-post-process/2390, still needs a bit of work. So I’m trying to tweak it as much as possible.

(edit, updated sampling for SSAO)

bmcorser

Looks nice. I like the UI styling :+1:

Victor

Thanks @bmcorser!

For anyone interested, here are the tweaks I made to the SSAO shader. They’re not crazy tweaks though, just changing the value, and removing the “depth” transition. I can’t say I fully understand the shader, however the paper referenced in it does help. The low/high sample settings can cause a performance hit.

#include "Uniforms.glsl"
#include "Samplers.glsl"
#include "Transform.glsl"
#include "ScreenPos.glsl"
varying highp vec2 vScreenPos;
#ifdef COMPILEVS
void VS()
{
    mat4 modelMatrix = iModelMatrix;
    vec3 worldPos = GetWorldPos(modelMatrix);
    gl_Position = GetClipPos(worldPos);
    vScreenPos = GetScreenPosPreDiv(gl_Position);
}
#endif
#ifdef COMPILEPS
uniform highp vec2 cScreenSize;
// Port from: https://github.com/jsj2008/Zombie-Blobs/blob/278e16229ccb77b2e11d788082b2ccebb9722ace/src/postproc.fs
// see T M?ller, 1999: Efficiently building a matrix to rotate one vector to another
mat3 rotateNormalVecToAnother(vec3 f, vec3 t) {
    vec3 v = cross(f, t);
    float c = dot(f, t);
    //float h = (1.0 - c) / (1.0 - c * c);
    float h = (c) / (c * c);
    return mat3(c + h * v.x * v.x, h * v.x * v.y + v.z, h * v.x * v.z - v.y,
                h * v.x * v.y - v.z, c + h * v.y * v.y, h * v.y * v.z + v.x,
                h * v.x * v.z + v.y, h * v.y * v.z - v.x, c + h * v.z * v.z);
}
vec3 normal_from_depth(float depth, highp vec2 texcoords) {
    // One pixel: 0.001 = 1 / 1000 (pixels)
    const vec2 offset1 = vec2(0.0, 0.001);
    const vec2 offset2 = vec2(0.001, 0.0);
    float depth1 = DecodeDepth(texture2D(sEmissiveMap, texcoords + offset1).rgb);
    float depth2 = DecodeDepth(texture2D(sEmissiveMap, texcoords + offset2).rgb);
    vec3 p1 = vec3(offset1, depth1 - depth);
    vec3 p2 = vec3(offset2, depth2 - depth);
    highp vec3 normal = cross(p1, p2);
    normal.z = -normal.z;
    return normalize(normal);
}
void PS()
{
    const float aoStrength = 2.5;
    highp vec2 tx = vScreenPos;
    highp vec2 px = vec2(1.0 / cScreenSize.x, 1.0 / cScreenSize.y);
    float depth = DecodeDepth(texture2D(sEmissiveMap, vScreenPos).rgb);
    vec3  normal = normal_from_depth(depth, vScreenPos);
    // radius is in world space unit
    const float radius = 0.025;

    //float farClip = 1.0;
    //float nearClip = 0.1;
    //float zRange = radius / (farClip - nearClip);
    float zRange = radius / (cFarClipPS - cNearClipPS);
    // calculate inverse matrix of the normal by rotate it to identity
    mat3 InverseNormalMatrix = rotateNormalVecToAnother(normal, vec3(0.0, 0.0, 1.0));
    // result of line sampling
    // See Loos & Sloan: Volumetric Obscurance
    // http://www.cs.utah.edu/~loos/publications/vo/vo.pdf
    float hemi = 0.0;
    float maxi = 0.0;
    float screenSample = 2;
    int lowSample = -6;
    int highSample = 6;
    for (int x = lowSample; x <= highSample; ++x) {
        for (int y = lowSample; y <= highSample; ++y) {
            // make virtual sphere of unit volume, more closer to center, more ambient occlusion contributions
            float rx = 0.03 * float(x);
            float ry = 0.03 * float(y);
            float rz = sqrt(1.0 - rx * rx - ry * ry);
            highp vec3 screenCoord = vec3(float(x) * px.x, float(y) * px.y, 0.0);
            // 0.25 times smaller when farest, 5.0 times bigger when nearest.
            //highp vec2 coord = tx + (5.0 - 4.75 * depth) * screenCoord.xy;
            highp vec2 coord = tx + (screenSample * screenCoord.xy);
            // fetch depth from texture
            screenCoord.z = DecodeDepth(texture2D(sEmissiveMap, coord).rgb);
            // move to origin
            screenCoord.z -= depth;
            // ignore occluders which are too far away
            //if (screenCoord.z < -zRange) continue;

            // Transform to normal-oriented hemisphere space
            highp vec3 localCoord = InverseNormalMatrix * screenCoord;
            // ralative depth in the world space radius
            float dr = localCoord.z / zRange;
            // calculate contribution
            float v = clamp(rz + dr * aoStrength, 0.0, 2.0 * rz);

            maxi += rz;
            hemi += v;
        }
    }

    float ao = clamp(hemi / maxi, 0.0, 1.0);
    ao = mix(ao, 1.0, 0.4);
    vec3 finalColor = texture2D(sDiffMap, vScreenPos).rgb * ao;
    gl_FragColor = vec4(finalColor, 1.0);
}
#endif
Victor

Finished up a few menus, working on the “in-game” map editing.

Victor

New color correction and water shader. Also tweaked the values a bit more on the ambient occlusion shader. Wrapped up the map editing system as well, so this weekend I hope to start adding some characters onto the map.

Victor

Over the weekend I decided to use textures for the map instead of solid colors. So now the forest area has more of a dirt texture than a grass texture. However, the buildings will still remain texture-less, and I’ll just use the material colors.

Modanung

Looking really nice!
Maybe cut down on the AO a bit?

Victor

Yeah, I believe you’re right! In my settings.txt file I’ve added a “high, medium, low” AO setting for anyone to adjust to their taste (or increase FPS on their machine). There is a setting to turn it off completely as well. :smiley:

Modanung

I do think it adds a lot, but to me it feels wrong for the AO around the buildings to be darker than the shadows.

Victor

Ah, I see what you’re saying. Yeah, last night I did make a change to the shadow intensity, but I didn’t adjust the AO along with it. I’ll try to fix that this week.

smellymumbler

That’s so beautiful! Is that cursor pointer a 3D model? If so, kudos for the creativity!

Victor

I cannot take credit for the 3D cursor, that along with the shore edges were inspired by Kingdom and Castles (equally beautiful game). However, my game isn’t a city builder, but rather a strategy game. Thanks for the compliment, I wish I could take 100% of the credit :smiley:

Victor

Been having a lot of fun scripting out some characters and events. This weekend I should proper cities and bandit camps in place.

The northmen know not yet how to die…

But soon they’ll know some fear

Victor

Thinks are starting to feel more like a fully playable game. This week has been redoing/finishing a lot of the UI. Icons are from http://game-icons.net which has one of the best icon repository of icons I’ve seen :slight_smile:

The city walls are still a work in progress, but I thought I’d display the progress.

Don

That UI looks excellent! Is it using the built-in Urho UI system with different textures, or is it entirely separate?

Victor

Yes, this is using Urho’s UI :slight_smile:

It’s mostly just coloring with BorderImage for the icons. To create elements however, I actually created my own scripting engine (before I even knew about Urho) to handle building out and positioning the UI.

So my ui scripts look something like this (which is used to build out the UIElements)

Victor

I haven’t updated in a while, figured I would today. Been mostly working on the different interfaces for the game. Very much inspired by the CK2 style.

TrevorCash

This looks like an awesome project!

voidhawk

Hey this looks really nice!