Problems with Lightmaps + dynamic lights


#21

[quote=“globus”][quote=“rasteron”]
…, in fact it is one of my favorite topics when it comes to engine and game optimization. :smiley: I’m not a shader guy though…
[/quote]

I fully support your attitude towards optimization.
Lightmapping big step in that direction.

I like the old style of game engines. (Old-Gen engines)
There are a lot of old games that are fun to replay again.
Previously, developers were limited in resources and do miracles of optimization.

And there’s a huge mass of modern games they look very best
but with mercilessly loaded hardware and which are not fun to play.

[spoiler]

Also, Fable: The Lost Chapters, Rune and mass of other old games.

Not very old but well optimized:
COD: Modern Warfare 2 and Dead Space 2-3[/spoiler][/quote]

Thanks globus, I’m sure a lot of game devs appreciate this and are also using it with other engines. But in the case with Urho3d, there’s still a lot of improvement needed to accomplish this seamless and optimized pipeline. :wink:


#22

For me is strange when:

I play game FarCry 1-2 on computer -
i see the beauty with the high settings.

Then i play FarCry 3 - disconnect all that is possible disable including shadows.
Make resolution to 800x600. FPS is low and it look like Quake1.

For me, this is an indicator that the new engines are not very optimized.
Probably because, they initially made for powerful computers.


#23

Far Cry 3 runs more complex content (and AI, physics) than the previous, and there’s limits on how low you can scale, e.g. you can disable things like particles, decals and extra clutter, but you can’t scale AI and player/enemy physics down without changing fundamentally how it plays. Also, it depends on realtime fullscreen effects like ambient occlusion to look good, while the previous don’t.

You’re right that because they started with a more powerful minimum spec, they probably can afford to be a little lazy. Or they optimize for different things, that don’t scale well for older computers, like taking advantage of multiple cores. Probably the converse is also true, that if you’d try to run FC3 content/world in the FC2 engine, it’d run like shit, because it was not made ready for that.


#24

Has anyone worked out a nice solution to this yet?
I’ve tried adding a lighting pass and just applying the shadows as suggested on the first page, but as someone else also mentioned since the lighting is additive there’s really no way to do it there.
So at this point I’m trying to see if I can introduce the shadows in the base pass by modifying the output color there, which is proving tricky (I’m no shader expert :slight_smile: )


#25

Hi, i’m do not working yet with this issue, but I guessing what we are have free alpha channel in viewport RT until we drawing opaque passes and not alpha passes.
if we try to write to alpha by default 0 (black) and if technique has lightmap technique we write precomputed AO from texture (0-255)
after all opaque passes we will have some sort of BW map in alpha channel.
and then we add quad command pass exactly after post opaque pass and do blending with substract with this BW from viewport, or custom screen shaded with multiplying (in case mul I guessing we must write 1 by default instead 0)


#26

I did get a working solution, though it feels like a bit of a hack. I use the lighting pass, but set it to subtractive:

<technique vs="LitSolid" ps="LitSolid" psdefines="DIFFMAP">
    <pass name="base" vsdefines="ENVCUBEMAP LIGHTMAP" psdefines="ENVCUBEMAP LIGHTMAP" />
    <pass name="prepass" psdefines="PREPASS" />
    <pass name="light" vsdefines="LIGHTMAP" psdefines="LIGHTMAP" depthtest="equal" depthwrite="false" blend="subtract" />
    <pass name="material" vsdefines="ENVCUBEMAP LIGHTMAP" psdefines="MATERIAL ENVCUBEMAP LIGHTMAP" depthtest="equal" depthwrite="false" />
    <pass name="deferred" vsdefines="ENVCUBEMAP LIGHTMAP" psdefines="DEFERRED ENVCUBEMAP LIGHTMAP" />
    <pass name="depth" vs="Depth" ps="Depth" />
    <pass name="shadow" vs="Shadow" ps="Shadow" />
</technique>

And then in the pixel shader I use the LIGHTMAP define to essentially output the inverse of the shadow:

#if defined(LIGHTMAP) && defined(SHADOW)
    float diff = 1-GetShadow(iShadowPos, iWorldPos.w);

    finalColor = diff * diffColor.rgb * cAmbientColor;

    oColor = float4(GetLitFog(finalColor, fogFactor), diffColor.a);
#else
    float diff = GetDiffuse(normal, iWorldPos.xyz, lightDir);

    #ifdef SHADOW
        diff *= GetShadow(iShadowPos, iWorldPos.w);
    #endif

    #if defined(SPOTLIGHT)
        lightColor = iSpotPos.w > 0.0 ? Sample2DProj(LightSpotMap, iSpotPos).rgb * cLightColor.rgb : 0.0;
    #elif defined(CUBEMASK)
        lightColor = SampleCube(LightCubeMap, iCubeMaskVec).rgb * cLightColor.rgb;
    #else
        lightColor = cLightColor.rgb;
    #endif

    #ifdef SPECULAR
        float spec = GetSpecular(normal, cCameraPosPS - iWorldPos.xyz, lightDir, cMatSpecColor.a);
        finalColor = diff * lightColor * (diffColor.rgb + spec * specColor * cLightColor.a);
    #else
        finalColor = diff * lightColor * diffColor.rgb;
    #endif

    #ifdef AMBIENT
        finalColor += cAmbientColor * diffColor.rgb;
        finalColor += cMatEmissiveColor;
        oColor = float4(GetFog(finalColor, fogFactor), diffColor.a);
    #else
        oColor = float4(GetLitFog(finalColor, fogFactor), diffColor.a);
    #endif
#endif

#27

[quote=“flintza”]I did get a working solution, though it feels like a bit of a hack. I use the lighting pass, but set it to subtractive:

<technique vs="LitSolid" ps="LitSolid" psdefines="DIFFMAP">
    <pass name="base" vsdefines="ENVCUBEMAP LIGHTMAP" psdefines="ENVCUBEMAP LIGHTMAP" />
    <pass name="prepass" psdefines="PREPASS" />
    <pass name="light" vsdefines="LIGHTMAP" psdefines="LIGHTMAP" depthtest="equal" depthwrite="false" blend="subtract" />
    <pass name="material" vsdefines="ENVCUBEMAP LIGHTMAP" psdefines="MATERIAL ENVCUBEMAP LIGHTMAP" depthtest="equal" depthwrite="false" />
    <pass name="deferred" vsdefines="ENVCUBEMAP LIGHTMAP" psdefines="DEFERRED ENVCUBEMAP LIGHTMAP" />
    <pass name="depth" vs="Depth" ps="Depth" />
    <pass name="shadow" vs="Shadow" ps="Shadow" />
</technique>

And then in the pixel shader I use the LIGHTMAP define to essentially output the inverse of the shadow:

[code]
#if defined(LIGHTMAP) && defined(SHADOW)
float diff = 1-GetShadow(iShadowPos, iWorldPos.w);

finalColor = diff * diffColor.rgb * cAmbientColor;

oColor = float4(GetLitFog(finalColor, fogFactor), diffColor.a);

#else
float diff = GetDiffuse(normal, iWorldPos.xyz, lightDir);

#ifdef SHADOW
    diff *= GetShadow(iShadowPos, iWorldPos.w);
#endif

#if defined(SPOTLIGHT)
    lightColor = iSpotPos.w > 0.0 ? Sample2DProj(LightSpotMap, iSpotPos).rgb * cLightColor.rgb : 0.0;
#elif defined(CUBEMASK)
    lightColor = SampleCube(LightCubeMap, iCubeMaskVec).rgb * cLightColor.rgb;
#else
    lightColor = cLightColor.rgb;
#endif

#ifdef SPECULAR
    float spec = GetSpecular(normal, cCameraPosPS - iWorldPos.xyz, lightDir, cMatSpecColor.a);
    finalColor = diff * lightColor * (diffColor.rgb + spec * specColor * cLightColor.a);
#else
    finalColor = diff * lightColor * diffColor.rgb;
#endif

#ifdef AMBIENT
    finalColor += cAmbientColor * diffColor.rgb;
    finalColor += cMatEmissiveColor;
    oColor = float4(GetFog(finalColor, fogFactor), diffColor.a);
#else
    oColor = float4(GetLitFog(finalColor, fogFactor), diffColor.a);
#endif

#endif
[/code][/quote]

First of, welcome! :slight_smile: This looks interesting, could you post some screenshots of this result and perhaps a working sample?

Thanks!


#28

Hmm, I don’t have a screenshot I could share just yet (NDA and all that), I’ll see what I can organize. As for a working sample, I’m doing this in Atomic Game Engine, and we do have a material sample level we hope to put into examples repo sometime next year but not just yet :slight_smile:


#29

Hmmm… this seems interesting , however the problem is way more complicated. If you use subtractive shadows on a material, that will disable additive light pass (e.g you can’t have flashlight in the game… ) This probably has to be solved on light level. Maybe lights should have a flag of using it as a pure additive (default) or a lightmap light.

LIGHTMODE_ADDITITVE, // default behavior
LIGHTMODE_LIGHTMAP, // This light casts subtractive shadow on materials that have LIGHTMAP defined , but works normal on other materials

But (i assume) this requires 2 separate depth maps for shadows (additive and subtractive at the same time)


#30

Ok , so finally i think i found a solution for this. It’s a workaround and it is a level editor/modeller software dependant. So instead of subtracting the shadows , i will disable direct lighting and bake only the global illumination (AO , indirect lighting , color bleeding , etc). And use dynamic lighting for direct lights. This will lit and cast shadows properly on lightmapped meshes , and it’s possible to combine with shaders. And it could work perfectly with dragonCASTjosh’s PBR