Join us at the Oolite Anniversary Party -- London, 7th July 2024, 1pm
More details in this thread.

Shaders’ Outpost

Discussion and information relevant to creating special missions, new ships, skins etc.

Moderators: winston, another_commander

User avatar
Griff
Oolite 2 Art Director
Oolite 2 Art Director
Posts: 2479
Joined: Fri Jul 14, 2006 12:29 pm
Location: Probably hugging his Air Fryer

Post by Griff »

wow, that was trippy, hope you haven't hidden any subliminal messages in there.
*struggles to resist urge to email Ahruman bank sort code & PIN number*
User avatar
Captain Hesperus
Grand High Clock-Tower Poobah
Grand High Clock-Tower Poobah
Posts: 2310
Joined: Tue Sep 19, 2006 1:10 pm
Location: Anywhere I can sell Trumbles.....

Post by Captain Hesperus »

Griff wrote:
wow, that was trippy, hope you haven't hidden any subliminal messages in there.
*struggles to resist urge to email Ahruman bank sort code & PIN number*
*already has PM'd Ahruman bank security details*

If he can do that with a shader, I'd like him to do something magical with the hideous amount of overdraft I am currently straining under.

Captain Hesperus
The truth, revealed!!
Image
User avatar
JensAyton
Grand Admiral Emeritus
Grand Admiral Emeritus
Posts: 6657
Joined: Sat Apr 02, 2005 2:43 pm
Location: Sweden
Contact:

Post by JensAyton »

Here’s something I smacked together this morning (insomnia’s good for something after all) – “Active Camo” Cobra III NjX, two variants. Requires standard Cobra III NjX OXP.

Testing note: the effect uses the sun colour as outlined above. However, the light in Lave happens to be grey. Reorte and Diso have more colourful suns (purple and green respectively… the two colours incandescent can’t actually be. Oh well.)

It’s not very effective camouflage, but kinda fun.
User avatar
wackyman465
---- E L I T E ----
---- E L I T E ----
Posts: 831
Joined: Thu Nov 06, 2008 10:15 pm
Location: Currently hunting you down in an Imperial Courier

Post by wackyman465 »

(Too lazy to launch Oolite)

Screenshots?
I shot him back first. That is to say, I read his mind and fired before he would have fired on me. No, sir, he wasn't a fugitive.
User avatar
JensAyton
Grand Admiral Emeritus
Grand Admiral Emeritus
Posts: 6657
Joined: Sat Apr 02, 2005 2:43 pm
Location: Sweden
Contact:

Post by JensAyton »

(Too lazy to take screen shots)

Like the pictures on the previous page, only on parts of a ship. :-)
Also, it’s an animation effect. What’s the point of a screen shot?
User avatar
Griff
Oolite 2 Art Director
Oolite 2 Art Director
Posts: 2479
Joined: Fri Jul 14, 2006 12:29 pm
Location: Probably hugging his Air Fryer

Post by Griff »

I've uploaded the normal mapped vresion of the Cobra3 i've been working on here:
http://www.box.net/shared/eltugqkkk0
Image
Gah! Now they've got AI's i couldn't get close enough to them to take a screen shot!

At the moment, this is the normal mapped version of the ship that will only work with the trunk build of Oolite - it won't work with any of the test releases, and the player flyable version isn't in this download either, i'll sort that out tomorrow - it just needs all the external view settings and stuff working out.
edit: added the player flyable version - still only works with the trunk oolite
Last edited by Griff on Sun Jan 25, 2009 2:32 pm, edited 2 times in total.
User avatar
JensAyton
Grand Admiral Emeritus
Grand Admiral Emeritus
Posts: 6657
Joined: Sat Apr 02, 2005 2:43 pm
Location: Sweden
Contact:

Post by JensAyton »

Griff wrote:
Gah! Now they've got AI's i couldn't get close enough to them to take a screen shot!
Your sekrit cheat code for the day: player.ship.target.setAI("dumbAI.plist")
User avatar
Griff
Oolite 2 Art Director
Oolite 2 Art Director
Posts: 2479
Joined: Fri Jul 14, 2006 12:29 pm
Location: Probably hugging his Air Fryer

Post by Griff »

argh! bugs!! sorry, there's errors in the shader if you try the oxp in simple shader mode, i'll get them fixed and re-upload!
edit: Fixed! "vec4 Color" was being defined twice because some #ifndef OO_REDUCED_COMPLEXITY #endif stuff was missing

Thanks for the cheat code Ahruman!
User avatar
Griff
Oolite 2 Art Director
Oolite 2 Art Director
Posts: 2479
Joined: Fri Jul 14, 2006 12:29 pm
Location: Probably hugging his Air Fryer

Post by Griff »

I've noticed there were a few errors in the normal mapped cobra i uploaded above, the repeat along S option was missing from the decal texture which meant that some decals had their edges missing and i'd totally forgotten to put the shipyard.plist file in which meant that the cobras would not have appeard for sale anywhere, plus i think some stats were missing from the player version of the ship (energy rate and stuff like that).
I'm sure i've now fixed the oxp and re-uploaded it here
Griff_NormalMapped Cobra 3
http://www.box.net/shared/eltugqkkk0

I've also finished the non-normal mapped version of the oxp which should now work in any version Oolite from v.171 and up, that's uploaded here:
Griff_No_NormalMap_Cobra3
http://www.box.net/shared/buguehovmt
Last edited by Griff on Sun Jan 25, 2009 3:51 pm, edited 1 time in total.
User avatar
ClymAngus
---- E L I T E ----
---- E L I T E ----
Posts: 2508
Joined: Tue Jul 08, 2008 12:31 am
Location: London England
Contact:

Post by ClymAngus »

Griff wrote:
I've noticed there were a few errors in the normal mapped cobra i uploaded above, the repeat along S option was missing from the decal texture which meant that some decals had their edges missing and i'd totally forgotten to put the shipyard.plist file in which meant that the cobras would not have appeard for sale anywhere, plus i think some stats were missing from the player version of the ship (energy rate and stuff like that).
I'm sure i've now fixed the oxp and re-uploaded it here
Griff_NormalMapped Cobra 3http://www.box.net/shared/eltugqkkk0

I've also finished the non-normal mapped version of the oxp which should now work in any version Oolite from v.171 and up, that's uploaded here:
Griff_No_NormalMap_Cobra3
http://www.box.net/shared/buguehovmt
I'm going to have to take a long hard look at that code sir. This is the future, after all.
User avatar
Simon B
---- E L I T E ----
---- E L I T E ----
Posts: 836
Joined: Thu Oct 23, 2008 5:54 am
Location: Red Beach NZ
Contact:

Post by Simon B »

For Ubuntu (and presumably Debian etc) users - there is a free software analog to that nvidia normal-map plugin for photoshop that Griff keeps going on about ...

sudo apt-get install gimp-normalmap
Normal map plugin for GIMP
This is a plugin for GIMP version 2.0+. It allows you to convert images into
RGB normal maps for use in per-pixel lighting applications. The goal is to
completely clone NVIDIA's photoshop plugin, with a few new useful features.
Naturally the sorce code is available...

I did it the other way around - starting with nvidia website links ... thanks Griff.

The other GIMP plugins are worth considering - texturize, for eg, does "make seamless" but without the wallpaper effect.

BTW: I had thought of redoing the coriolis statian in dark-tones (black and graphite) with wee lights and etched textures ... only to find that Griff has already done it!

Now to mosey along to the skinners den...
Simon Bridge
[re2dux] [neolite]
"Everything is perfect down to every last flaw..."
HBT: The Book of Verse - Principia Discordia
User avatar
Kaks
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 3009
Joined: Mon Jan 21, 2008 11:41 pm
Location: The Big Smoke

Post by Kaks »

Simon B wrote:
BTW: I had thought of redoing the coriolis station in dark-tones (black and graphite) with wee lights and etched textures ... only to find that Griff has already done it!
Yep, no flies on that Griff guy!

...and while I'm posting, I really need to say thank you! Watching what you 'graphic' guys are able to do with textures & models is simply ...well... awe-inspiring is probably the best way to put it...

Cheers,
Kaks.
Hey, free OXPs: farsun v1.05 & tty v0.5! :0)
User avatar
JensAyton
Grand Admiral Emeritus
Grand Admiral Emeritus
Posts: 6657
Joined: Sat Apr 02, 2005 2:43 pm
Location: Sweden
Contact:

Post by JensAyton »

As some may have guessed, my enthusiasm for Oolite is at the low end of the cycle at the moment. As usual, this means I’ve been playing. Today’s toy project is an implementation of distance mapping, a useful technique for decals. If you’ve played Half-Life 2 and derivatives, or Fallout 3, you may have seen it used for in-game text on signs and similar.

Distance mapping is a technique that allows low-resolution textures to represent sharp-edged shapes which can be magnified almost without limit. The tradeoff is that it only represents shapes, with no colour, shading or transparency (although you could of course have one shape per channel).

Here is an example shape and its corresponding distance map:

Image

Image

This looks a lot like any old blur, but it isn’t exactly. Each pixel of the distance map texture represents the distance to the nearest edge of the shape. Values below 0.5 indicate a point outside the shape, while values above 0.5 indicate a point inside the shape. You’ll also note that the distance map is 1/256th of the size of the original, which is not to be sneezed at. (My code for generating distance maps is in the Oolite source tree, and a pre-built Mac version is available here).

To use the distance map in a shader, you read the texture map in the usual way. If the value is greater than or equal to 0.5, the current fragment is inside the shape, otherwise it’s outside:

Code: Select all

float dmap = texture2D(tex, texCoords).r;
float mask = step(dmap, 0.5);
vec4 color = mix(kWhite, kBlack, mask);
So what does this win you? The clever part is that the bilinear filtering used to scale textures up interpolates the distance map much better than it does hard edges in a normal texture. Additionally, the trilinear mipmap filter used to scale textures down does a decent job of simplifying the shape. Here’s the result of the above snippet:

Image

It’s not magic; if you look closely you can see that it’s a piecewise linear approximation of the original shape, and the tip of the tail is clipped off in a funny way. Still, not bad for a 64 × 64 px texture, apart from the unacceptable aliasing.

To fix the aliasing, we’re going to cheat and blur the edge. This is easily done using a distance field: instead of using the step() function to introduce a hard edge at the 0.5 threshold, we use two slightly different threshold values and the smoothstep() function, whose hermite interpolation happens to produce a good blur profile.

Code: Select all

float dmap = texture2D(tex, texCoords).r;
float mask = smoothstep(0.5 - aaFactor, 0.5 + aaFactor, dmap);
The next question is how to select aaFactor. Ideally, it would be a value such that the blur covers about one screen pixel, but that distance in texture space varies depending on camera distance and so forth. Fortunately, GLSL provides us with the mysterious fragment processing approximate derivative functions, dFdx(), dFdy() and fwidth(). Without going into the details, we want to use fwidth() on the texture coordinates, average the x and y coordinates of the result, and multiply by a fudge factor (which is 3 in my example). This gives us:

Code: Select all

vec2 fw = fwidth(texCoords);
float aaFactor = (fw.x + fw.y) * 1.5;
Unfortunately, not all implementations give useful results. The broken hardware I’ve encountered always produces 0, so we can recognise this case and substitute a fixed blur factor instead:

Code: Select all

aaFactor = (aaFactor == 0.0) ? 0.03 : aaFactor;
The result (with a working fwidth()) looks like this:
Image

Image

Apart from anti-aliasing, varying the threshold can be used to find boundaries at different distances from the shape – in other words, to create outlines, like this (inner threshold: 0.52, outer threshold: 0.49):
Image

Image

I have a variation in mind that would allow randomized damage/paint chipping to be applied without the outline following the contours of the chipping.

Here’s my test shader:

Code: Select all

uniform sampler2D tex;

const float kThreshold = 0.5;
const float kFallbackAAFactor = 0.03;

const vec4 kBlack = vec4(0.0, 0.0, 0.0, 1.0);
const vec4 kWhite = vec4(1.0);
const vec4 kRed = vec4(1.0, 0.0, 0.0, 1.0);
const vec4 kBlue = vec4(0.0, 0.0, 1.0, 1.0);


float DistanceMap(sampler2D texture, vec2 texCoords, float threshold)
{
    float dmap = texture2D(tex, texCoords).r;
    
    // Fake anti-aliasing with a hermite blur.
    // The fwidth() term lets us scale this appropriately for the screen.
    vec2 fw = fwidth(texCoords);
    float aaFactor = (fw.x + fw.y) * 1.5;
    // If fwidth() doesn't provide useful data, use a fixed blur instead.
    // Setting kFallbackAAFactor to zero gives you aliased output in the fallback case.
    aaFactor = (aaFactor == 0.0) ? kFallbackAAFactor : aaFactor;
    return smoothstep(threshold - aaFactor, threshold + aaFactor, dmap);
}


void main()
{
#if 1
    // NOTE: in real code, reuse the dmap value instead of sampling twice.
    float inner = DistanceMap(tex, gl_TexCoord[0].xy, kThreshold + 0.01);
    float outer = DistanceMap(tex, gl_TexCoord[0].xy, kThreshold - 0.02);
    
    vec4 decalColor = mix(kBlack, kRed, inner);
    decalColor = mix(kWhite, decalColor, outer);
#else
    float mask = DistanceMap(tex, gl_TexCoord[0].xy, kThreshold);
    vec4 decalColor = mix(kWhite, kBlack, mask);
#endif
    
    gl_FragColor = decalColor;
}
User avatar
DaddyHoggy
Intergalactic Spam Assassin
Intergalactic Spam Assassin
Posts: 8512
Joined: Tue Dec 05, 2006 9:43 pm
Location: Newbury, UK
Contact:

Post by DaddyHoggy »

:shock: Wow!

Ahruham, the scale of your genius never ceases to amaze me...

So what will Griff produce now based on this new wizardry I wonder...
Selezen wrote:
Apparently I was having a DaddyHoggy moment.
Oolite Life is now revealed here
User avatar
JensAyton
Grand Admiral Emeritus
Grand Admiral Emeritus
Posts: 6657
Joined: Sat Apr 02, 2005 2:43 pm
Location: Sweden
Contact:

Post by JensAyton »

DaddyHoggy wrote:
:shock: Wow!

Ahruham, the scale of your genius never ceases to amaze me...
Thanks, but I just read about this on the intertubes last week. It’s very easy to implement, most of the time was spend writing support functions in the tool that generates the distance map.
Post Reply