@KW
It's not a very complex effect, i'm just not going to explain it very well and make it all seem a lot harder than it is! - it's done by scrolling a lamp intensity (or 'brightness' )texture and using a 'mask' texture to control where the lights appear.
Here's a copy of the effects texture used in the coriolis docking bay, in this example i've faded in the 'skin' texture a bit to help show how the effects map fits in place, also the UV borders are visible as light grey lines too, in the actual effects map the background needs to be completely black.
So basically what's happening is that the green pattern is the light intensity map and it constantly scrolls along from left to right, where it passes over a red dot a glow appears in the texture so you need to be careful how you lay out your Texture UV's - any part you want the lights to scroll over have to be laid out in straight line either horizontally or vertically in the UV map, this is probably the most important bit to keep in mind, if you get stuck on any of the shader code just post on here on in the shaders outpost thread and we can work on adding this effects into your usual shader code.
Right, we need a set of scrolling texture co-ordinates for the green channel and a set of static co-ordinates for the red channel (as we don't want the mask map to scroll along with the intensity map), we already have a set of static texture co-ordinates passed to us from the vertex shader…
….so we just need a modified set of coordinates for the green channel, we'll set up a repeating counter stored as a floating point number and add this to the texture co-ordinate for the green channel, this will give us our scrolling effect (it's the same as using the 'offset' filter in photoshop)
OK, first we need to specify that the effects texture ‘tiles’ itself horizontally otherwise it will scroll past once and that’s it, so we need to set repeating edges to on to ensure that what scrolls off one side reappears on the opposite side (we’re only going to scroll the texture sideways so we just need to switch on repeat for the texture 's' co-ordinate – more on texture co-ordinates later). We specify texture tiling in shipdata.plist, in the 'texture' section in 'shaders':
Code: Select all
textures =
(
"griff_coriolis_dock_diffuse.png",
"griff_coriolis_dock_normal.png",
{name = "griff_coriolis_dock_effects.png"; repeat_s = "yes";}
);
Next we need access to the game clock, it'll be the basis for our counter, in shipdata.plist alongside our texture uniforms we'll also set up an uniform called 'uTime' and link it to the 'universalTime' data from Oolite's game engine
http://wiki.alioth.net/index.php/Shader ... :_uniforms
Code: Select all
uniforms =
{
uColorMap = { type = texture; value = 0; };
uNormalMap = { type = texture; value = 1; };
uEffectsMap = { type = texture; value = 2; };
uTime = "universalTime";
};
in the shader we need to call in this uniform, just setting it up in shipdata.plist isn't enough, so up near the start of the shader code you list your uniforms, i'll just do the uTime one here to keep things simple
Code: Select all
// Uniforms from Oolite
uniform float uTime;
Great, now we have access to a timer we can run it through a mod command to get a repeating set of numbers we can use to offset the texture co-ordinates by - my grasp of maths is total crap, i don't really know what ‘mod’ does - hovering the mouse pointer over it in rendermonkey gives the following tool tip pop-up…
mod(x,y) Modulus. Returns x - y * floor (x/y)
…i don't know if that means anything to you but it certainly sails over the top of my head, all i know is that instead of just using the game time to offset the texture by (which would be a number that started at 0 and kept counting up and up and up) using mod on the game timer gives you a smaller set of numbers that start somewhere around 0.0, count up for a bit then return back to roughly 0.0, perfect for what we need, here’s the code in the shader
(I just noticed the code in the shader in the coriolis oxp is over fiddly and can be simplified, I’ll carry on here using the simplified code and update the oxp to match a bit later)
Code: Select all
// Set up a float to add to the texture coords in order to scroll them
float counter = mod(uTime * 0.25, 1.0);
uTime counts up a bit too quick making the lights scroll by too fast, so multiplying it by 0.25 slows it down to quarter speed which looks a lot nicer, I think the 1.0 sets the upper limit on the numbers so this bit of code gives floating point numbers in the range of 0.000000 to 1.000000 which is perfect for us as it matches UV texture space exactly.
now that we have our texture offset counter, lets set up our scrolling 'lamp intensity' map, we’re only using 1 channel for it (the green channel) so we can store it in a floating point number
We want the texture to scroll from left to right so we only need to manipulate the ‘s’ texture co-ordinate (s,t,p,q are used when referring to textures coordinates in openGl, we’re only using 2D textures here so we only need to deal with the ‘s’ and ‘t’ co-ordinates , ‘t’ is the vertical co-ordinate)
Code: Select all
// set up the scrolling light map
float ScrollingIllumMap = texture2D(uEffectsMap, vec2(vTexCoord.s - counter, vTexCoord.t)).g;
we’re storing the green channel (the .g at the end of the line) from the uEffectsMap texture as a floating point number called ‘ScrollingIllumMap’ and we’re subtracting our counter value from its ‘s’ (horizontal) texture co-ordinate…
…to scroll it along left to right (you could add the counter value to the s coordinate if you want the texture to scroll in the opposite direction) leaving the t (vertical texture co-ordinate) untouched
OK, we’ve got our scrolling map, so now we just need our static 'mask map' to let us control light placement, we’ll use the red channel and leave its texture co-ordinates unmodified, we’ll store it all in a float called
ScrollingIllumMapmask
Code: Select all
float ScrollingIllumMapmask = texture2D(uEffectsMap, vTexCoord).r;
Nearly done now, we’ll need a lamp colour for our lights so we’ll use a vec3 to store the colour in (we use a vec3 because we need red green and blue values to describe a colour), we'll call it called
ScrollingLampColour
Code: Select all
vec3 ScrollingLampColour = vec3(0.7368, 1.0, 0.4736);
All we need to do now is add these elements into the final colour
First multiply the scrolling green channel (ScrollingIllumMap) by the static red channel (ScrollingIllumMapmask) to calculate the light brightness (multiplying by the red channel means that anywhere in the map that there isn’t a red pixel returns a 0 for the light brightness so we can control where the lights will appear by only putting red dots where we want lights)
Code: Select all
(ScrollingIllumMap * ScrollingIllumMapmask)
Next we just multiply our light brightness value by our Lamp Colour to get the final result
The line in full looks like this
Code: Select all
color += (ScrollingIllumMap * ScrollingIllumMapmask) * ScrollingLampColour;
‘color’ has already been calculated further up in the shader using the ‘skin’ texture maps and lighting information, we’re just adding the light maps in at this point and it’s important that this is done after the lighting from the system ‘sun’ has been calculated otherwise you get shadowing on your glow maps which spoils the effect that they are emitting light