Orange light = green walls? Far out experiences with colored light

Having quite some lava in my current map, I placed a couple orange lights (1 0.4 0.1 or thereabouts in RGB) with a “light” value of 600 each in various lava pools to make them emit a strong orange glow. The lightmap was properly orange, but the actual result was far from orange:

Green walls! How did that happen?

It turns out that the wall colour is a result of multiplying the lightmap with the wall texture, scaling for overbrights, and clamping the end result. The texture in this case is Quake’s standard greyish metal/stone wall, metal4_4. Now if you take a closer look at that texture, you’ll notice it has a lot of blue/grey and a large amount of green pixels in it. It is actually rather green when compared to a real grey texture. It has practically no red.

What happens has to do with a) the existing colors of the wall texture and b) the “clamping” of the light value. The latter clips away any “excess” light value above 255…

Apparently my light setting of 600 was so strong that it amplified the red component of the light (1 0.4 0.1, remember, R G B) so much that it got clipped at 255. However, the green component was also hugely amplified. This made the green component appear relatively stronger than it normally does.

MH explained it like this: The area just seems to be far too bright which is causing the red contribution to clamp at 255 and the green to contibute more than it otherwise would.

On top of that, the wall texture contains lots of blue and green pixels, but practically no red. Again, green gets amplified while red loses out. Spike:

05:58 < Spoike> that texture is mostly blue, right?
05:58 < Spoike> a little green, but no red?
05:59 < Spoike> in which case 0*red = 0, 0.5*green = 0.5 1*blue = 0
05:59 < Spoike> hence green

So how do I avoid the clamping of my red component? By keeping the light value relatively low. This sadly means that if you try to have very bright, high intensity colored lights in GLQuake, nasty color shifts in the wall textures may appear.

So I set the light value way under 200 and that made the color shift disappear. Then, step by step, I went higher. Currently it’s at 200. The downside of this is that your light doesn’t reach as far as a 600 light one and the general impression is less intense. However, you can somewhat make up for this by setting a very low “wait” value. By that I mean, 0.5 or less. A wait of 0.5 will double the falloff distance of the light. I’m currently at 0.4 (!).

Now this is better. I’m using the Quake retexturing Project pk3 there (hi res textures), but you can still compare the rune textures, which are the same. It’s clearly a lot more orange. What happened is that the clamping is avoided, and the falloff distance of the lights is artificially increased.

This does away with most of the sickening green color shift even with the original low-res metal4_4 texture. Learn something new every day. More shots, again using largely QRP textures:

The brighter orange to the front right stems from a few large flame braziers. I might shift that a little more towards white still. But notice the orange in the corridor – it’s the lava beneath. This also looked very green previously.

This area as well – compare this to the screenshots in the Demo #2 announcement below. Again, the greenish tinge is largely gone. I consider this something of a success, but it pissed me off to no end until I slowly lurched closer to the ideal values. Not quite there yet, but better.


8 responses to “Orange light = green walls? Far out experiences with colored light

  • blob

    Oh. Green walls were kinda cool, gave a “doom” feeling to it.

  • =peg=

    Would it not make sense to have the clamping done proportionally to the same ratio as the original RGB values on each channel, so that even when one (or more) channels get clamped, the others won’t be raised higher then a certain value (determined by the relative ratio in the _color values) that would maintain the intended color?

    example: _color 1 .75 .5

    If the value on the red channel gets clamped to 255, clamp the green and blue to 192 and 128 respectively.

    Now, I don’t know if this would have to be done in the light tool or in the engine, but at least it would make a mappers job a lot easier. Heck, maybe even switching to HSV/HSL color space makes even more sense here? πŸ˜‰

    Anyways.. just a thought..

  • mh

    None of the above, it’s all happening in the driver so it’s outside of our control. Even doing it in a shader didn’t work. 😦

  • metlslime

    Quake3’s light compiler would proportionately clamp all three channels when necessary to preserve color saturation. So you would generally not see bright colored lights wash out in the middle. It still looks odd under extreme conditions (the ‘hot spot’ near a light source was sometimes oddly dim) but it’s a more graceful way to handle it.

    basically what =peg= said.

    now, i realize it’s more difficult in quake 1 because styled lights are additively combined at runtime, so you’d also have to do additional work in the engine to make sure the final result was proportinately clamped again every time the lightstyles are updated.

    And then there are dlights… πŸ˜›

  • mh

    @metl: “you’d also have to do additional work in the engine to make sure the final result was proportinately clamped again every time the lightstyles are updated.”

    Been there, done that, didn’t work. It also was too much of a speed drain. 😦

  • kneedeepinthedoomed

    Since it can mostly be avoided, if one knows how, it is one of the restrictions I can live with.
    There are a couple things that will simply require a more recent platform to accomplish, like idtech4 / cryengine / Unreal. It’s very interesting to see how far you can push Quake, though, as well as being shown the limits because you bumped head first into them.
    So far it seems that a lot of things are possible, with reasonable effort (although what we call reasonable, others might call outrageous). Only a handful of things have requirements that are convincingly too steep for us.
    Supa joked about splines and on-texture GUIs. I guess those are things that can be left to Doom3 & co. Same for volumetric fog. I do think though that there isn’t much in Quake 4 that we can’t have in RMQ at this point. Of course everything looks more cute in Q1, but everybody knows that cute, furry things can deliver deadly lightning bolts.
    Although I might wake up one day and it’s 2012 and we have some of those new fangled toys. Never say never. Just imagine what happens once we have no more feature requests and mh gets bored. Frightening thought. πŸ™‚
    We are proceeding atm into terrain that just a few months ago seemed like the place of daydreams and fantasies. Maybe there is such a thing as critical mass.
    The rotating entities business was a good example of what can happen if a few coders and some content creators work on the same thing, even if it was comparatively half-assed, unorganized, and required several iterations.
    Even though the community is full of self important whiny bitches and armchair mappers, and I won’t even exclude myself from that list, there is a lot of potential that can be unleashed by making the right connections and flogging the horse until it comes back to life.

  • metlslime

    Agreed, this is something that is best to work around by making content that doesn’t have this problem. At best a code solution is going to flatten your lighting; better to just make lighting that looks good to begin with.

    BTW fullbrights in that last screenshot πŸ™‚

  • kneedeepinthedoomed

    Fullbrights, yes sir πŸ™‚

    will fix.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: