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: another_commander, winston

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

Post by Griff »

from https://bb.oolite.space/viewtopic.php?t=4494&start=1662


I've been doing the recolouring as follows, there's probably much more sophisticated ways of doing it that don't lead to such muddy colours in the lower range of tones

The re-painting can be thought of as simply taking a greyscale 'paintmask' image, recolouring it and mixing it into the underlying texturemap (the paint mask is used

to control the effect and limit it to only certain areas of the ship - black areas in the paintmask won't be recoloured, white areas will get the maximum amount of

re-colouring).

Taking the griff_normalmapped cobraIII as an example:
The cobra has 2 paintmasks, these are stored are the green channel and the alpha channel in the 'Griff_cobra_mk3_cleaner_mainhull_effects.png' image.

In the fragment shader (Griff_Cobra_mk3_Mainhull_Cleaner.fragment) the re-painting effect is included in the same function that creates the decal, the function is

called diffuseColor and is found at lines 120-146:

Code: Select all

vec4 diffuseColor() 
{ 
// Calculate decal texture co-ordinates. 
   vec2 decalTexCoord = vTexCoord; 
   decalTexCoord -= vec2(kDecalS, kDecalT - (0.5 / kDecalSize)); 
   decalTexCoord *= vec2(kDecalSize / kDecalCount, kDecalSize); 
    
// Select the desired decal from the set. 
   float offset = floor(uDecalSelect * kDecalCount) / kDecalCount; 
   decalTexCoord.s += offset; 
    
// Get texture values. 
   vec4 baseTex = texture2D(uColorMap, vTexCoord); 
   vec2 PaintMap = texture2D(uEffectsMap, vTexCoord).ga; 
   float decalTex = texture2D(uDecalMap, decalTexCoord).b; 
        baseTex += PaintMap.x * PaintColor1;
        baseTex += PaintMap.y * PaintColor2;
        decalTex *= step(offset, decalTexCoord.s) * 
                    step(0.0, decalTexCoord.t) * 
                    step(-1.0 / kDecalCount - offset, -decalTexCoord.s) * 
                    step(-1.0, -decalTexCoord.t); 
    
// Composite decal over base. 
   return baseTex + decalTex * DecalColor; 
}      
the lines we are interested in here are:

Code: Select all

   vec2 PaintMap = texture2D(uEffectsMap, vTexCoord).ga; 
this line creates a 2 component vector and stores the green and alpha channels from the 'uEffectsMap' texture - (see the cobras shipdata.plist and line 3 in the shader

to see the lines that link the Griff_cobra_mk3_cleaner_mainhull_effects.png to the shader as an 'uniform' called uEffectsMap)

aargh, i just realise i've started in the wrong place with the explanation, so skip back up the fragment shader to lines 25 & 26

Code: Select all

   uniform vec4   PaintColor1; // used with paintmask map to tint diffuse texture
   uniform vec4   PaintColor2; // used with paintmask map to tint diffuse texture
Here we're reading in the paint colours from the cobraIII's shipdata.plist and storing them in the shader as 2 '4 component vectors' (that's too many components

really, the 4th one isn't really going to be used - bad shader writing on my part, we could have used a vec3 for Red, Green, and Blue)

next, skip down the fragment shader to line 134

Code: Select all

 vec4 baseTex = texture2D(uColorMap, vTexCoord); 
here we're reading in the cobras basic texture 'skin' image and storing it in a vec4 called baseTex, see the shipdata.plist and line 1 in the shader for the setting up

of the uniform to link 'Griff_cobra_mk3_cleaner_mainhull_diffuse_spec.png' to the uniform binding 'uColorMap'

now we just need to mix our 2 paintmask images with our 2 paintColors and add them into the basetexture,this is done in lines 137 & 138

Code: Select all

        baseTex += PaintMap.x * PaintColor1;
        baseTex += PaintMap.y * PaintColor2;
then line 145 outputs the final texture (as a vec4) from the function where it is used in line 170 onwards

the random paint colours are generated by oolite using the following info in the shipdata.plist

Code: Select all

PaintColor1 = {type = "randomUnitVector"; scale = 0.4;};
PaintColor2 = {type = "randomUnitVector"; scale = 0.4;};
the scale is used as an upper limit for the values generated, anything more vivid that 0.4 gets a bit lurid in the game, notice how the player ship has it's paint

colours set to black:

Code: Select all

PaintColor1 = { type = vector; value = "0.0 0.0 0.0"; }; 
PaintColor2 = { type = vector; value = "0.0 0.0 0.0"; };
we can't use random colours for the player as the ship would change it's paint job every game session. As the paint effects are added into the underlying texturemap,

setting the paint colour to black has no effect on the under lying texture as your basically just adding a 0.0 to whatever the current colour value is.

edit: as suggested by Zieman in the post below, 'baseTexCoord' wasn't actually needed it was just a duplicate of the vTexCoord vec2, i've ammended the example above to remove it and also the problematic references to gl_TexCoord[0].st
Last edited by Griff on Thu Apr 08, 2010 7:23 pm, edited 1 time 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:
we can't use random colours for the player as the ship would change it's paint job every game session.
This is now fixed in trunk – entity personalities are saved, and also copied from display models in the shipyard.
User avatar
Svengali
Commander
Commander
Posts: 2370
Joined: Sat Oct 20, 2007 2:52 pm

Post by Svengali »

Would it help to avoid problems with oxp-shaders if we'd use the preprocessor directive #version for our shaders?
User avatar
Zieman
---- E L I T E ----
---- E L I T E ----
Posts: 680
Joined: Tue Sep 01, 2009 11:55 pm
Location: in maZe

Post by Zieman »

Griff wrote:
...

Code: Select all

...
{ 
   vec2 baseTexCoord = gl_TexCoord[0].st; 
...
...
Should this be fixed?
ATI users are in trouble with that gl_TexCoord[0].st part.
...and keep it under lightspeed!

Friendliest Meteor Police that side of Riedquat

[EliteWiki] Far Arm ships
[EliteWiki] Z-ships
[EliteWiki] Baakili Far Trader
[EliteWiki] Tin of SPAM
User avatar
Svengali
Commander
Commander
Posts: 2370
Joined: Sat Oct 20, 2007 2:52 pm

Post by Svengali »

Zieman wrote:
Should this be fixed?
ATI users are in trouble with that gl_TexCoord[0].st part.
Can you test if Snoopers, BuoyRepair or Vector are working for you? If so, this is not the problem then...

Quite interesting stuff with differences betwen ATI and Nvidia, sometimes even between series of cards of the same manufactorer )-:
User avatar
Griff
Oolite 2 Art Director
Oolite 2 Art Director
Posts: 2478
Joined: Fri Jul 14, 2006 12:29 pm
Location: Probably hugging his Air Fryer

Post by Griff »

i've edited the example above to remove (as Zieman correctly suggests) the gl_TexCoord[0].st blunder, it neededn't have been in the shader, proper ATI friendly texture coords were already being passed from the vertex shader to the fragment shader using the varying vec 2 'vTexCoord' , i've no idea where i got the gl_TexCoord[0] from, probably from an example shader i found on the internet and copied without having a clue what it did
User avatar
Zieman
---- E L I T E ----
---- E L I T E ----
Posts: 680
Joined: Tue Sep 01, 2009 11:55 pm
Location: in maZe

Post by Zieman »

Svengali wrote:
Can you test if Snoopers, BuoyRepair or Vector are working for you? If so, this is not the problem then...
Vector 1.3 is not working. Looks like the textures don't load - all faces are black.

Oolite 1.73.4 test
WinXP pro SP3 32 bit
ATI HD3870
Catalyst 10.3

Latest.log clear (= no errors reported)

EDIT: I listed here: https://bb.oolite.space/viewtopic.php?p=106344#106344 those OXPs I have installed and use problematic shaders = everything is either black or in shades of grey, totally untextured.
Last edited by Zieman on Thu Apr 08, 2010 7:56 pm, edited 1 time in total.
...and keep it under lightspeed!

Friendliest Meteor Police that side of Riedquat

[EliteWiki] Far Arm ships
[EliteWiki] Z-ships
[EliteWiki] Baakili Far Trader
[EliteWiki] Tin of SPAM
User avatar
Svengali
Commander
Commander
Posts: 2370
Joined: Sat Oct 20, 2007 2:52 pm

Post by Svengali »

Zieman wrote:
Svengali wrote:
Can you test if Snoopers, BuoyRepair or Vector are working for you? If so, this is not the problem then...
Vector 1.3 is not working. Looks like the textures don't load - all faces are black.
Good to know - thanks for checking and reporting, Zieman.
User avatar
Zieman
---- E L I T E ----
---- E L I T E ----
Posts: 680
Joined: Tue Sep 01, 2009 11:55 pm
Location: in maZe

Post by Zieman »

You're welcome. :)
...and keep it under lightspeed!

Friendliest Meteor Police that side of Riedquat

[EliteWiki] Far Arm ships
[EliteWiki] Z-ships
[EliteWiki] Baakili Far Trader
[EliteWiki] Tin of SPAM
User avatar
Griff
Oolite 2 Art Director
Oolite 2 Art Director
Posts: 2478
Joined: Fri Jul 14, 2006 12:29 pm
Location: Probably hugging his Air Fryer

Post by Griff »

possible fix is to use the new code from ahrumans later shaders, i've added it in to the vector shaders here (i haven't checked if vector has been updated since v1.0 which is the one i've got downloaded in my oolite folder)

The shaders below set up a varying vec2 called vTexCoord to pass texture coordinates from the vertex to the fragment shader, texture coords are now set up using gl_MultiTexCoord0.st instead of gl_TexCoord[0].st, this seems to be more AMD friendly
ahruman_sv_ship_vector.vertex

Code: Select all

varying vec3			v_normal;		// Surface normal
varying vec3			v_pos;		// Vertex/fragment position in eye space
varying vec2         vTexCoord;

void main()
{
	v_normal = normalize(gl_NormalMatrix * gl_Normal);
	v_pos = vec3(gl_ModelViewMatrix * gl_Vertex);
	
    vTexCoord = gl_MultiTexCoord0.st;
	gl_Position = ftransform();
}
ahruman_sv_ship_vector.fragment

Code: Select all

// Information from Oolite.
uniform sampler2D		tex0;
uniform sampler2D		tex1;
				
uniform float			uTime;
uniform float			uEngineLevel;
uniform float			uLaserHeatLevel;
uniform float			uHullHeatLevel;


// Information from vertex shader.
varying vec3			v_normal;		// Surface normal
varying vec3			v_pos;			// Vertex/fragment position in eye space
varying vec2         vTexCoord;

// intensity proportional to level.
vec4 EngineGlow(float level)
{
	return vec4(vec3(1.0, 0.6, 0.3) * level, 1);
}


// Colour ramp
vec4 TemperatureGlow(float level)
{
	// Load texture data
	vec4 colorMap = texture2D(tex0, vTexCoord);
	vec4 effectMap = texture2D(tex1, vTexCoord);

	vec4 result = vec4(0);
	
	result.r = effectMap.r * level * 4.0 + colorMap.r * level * 8.0;
	result.g = effectMap.g * level * 4.0 + colorMap.g * level * 2.3;
	result.b = effectMap.b * level * 4.0 + colorMap.b * level * 1.2;
	result.a = 1.0;
	
	return result;	
}


#ifdef OO_REDUCED_COMPLEXITY
float Pulse(float value, float timeScale)
{
	return 0.95 * value;
}
#else
// Version of wave() from Freaky Thargoid broken to produce irregular flickering.
float Pulse(float value, float timeScale)
{
	float t = uTime * timeScale;

	float s0 = t;
	s0 -= floor(s0);
	float sum = abs( s0 - 0.5);
	
	float s1 = t * 0.7 - 0.05;
	s1 -= floor(s1);
	sum += abs(s1 - 0.5) - 0.25;
	
	float s2 = t * 1.3 - 0.3;
	s2 -= floor(s2);
	sum += abs(s2 - 0.5) - 0.25;
	
	float s3 = t * 5.09 - 0.6;
	s3 -= floor(s3);
	sum += abs(s3 - 0.5) - 0.25;

	return (sum * 0.1 + 0.9) * value;
}
#endif


// Calculate the contribution of a single light. Ought to be a function, but OS X's GLSlang implementation isn't sufficiently clever.
#define LIGHT(idx) \
	{ \
		vec3 lightVector	= normalize(gl_LightSource[idx].position.xyz); \
		vec3 reflection	= normalize(-reflect(lightVector, v_normal)); \
		diffuse += gl_FrontMaterial.diffuse * gl_LightSource[idx].diffuse * max(dot(v_normal, lightVector), 0.0); \
		specular += gl_LightSource[idx].diffuse * pow(max(dot(reflection, eyeVector), 0.0), 20.0); \
	}


void main(void)
{
	vec4 diffuse = vec4(0), specular = vec4(0);
	vec3 eyeVector = normalize(-v_pos);
	
/*	Light 0 is the "showroom" light, but also the only light with an ambient component.
	Light 0 is currently disabled, because there's no way for the shader to know when it's turned off.
	The solution for this will probably be for Oolite to set its diffuse and specular components to
	black when it's not being used.
	
	Light 1 is the sun.
	*/
#ifdef OO_LIGHT_0_FIX
	LIGHT(0);
#endif
	LIGHT(1);
    diffuse += gl_FrontMaterial.ambient * gl_LightModel.ambient;
	
	// Load texture data
	vec4 colorMap = texture2D(tex0, vTexCoord);
	vec4 effectMap = texture2D(tex1, vTexCoord);
	
	// Add in constant glow (window and fuel scoop)
	diffuse += effectMap.b;
	
	// Apply part of engine effect before applying colour, so it is partially texture-dependant
	float engineAlpha = effectMap.r;
	vec4 engineEffect = engineAlpha * EngineGlow(min(uEngineLevel, 1.0));
	diffuse += 0.8 * engineEffect;
	
	// Multiply illumination by base colour
	vec4 color = diffuse * colorMap + specular;
	
	// Apply rest of engine effect (texture-invariant component, so yellow centre of engines also glows a bit)
	color += 1.0 * engineEffect;
	
	// ...and heat effects
	float laserAlpha = Pulse(effectMap.g, 0.7);
	float hullHeat;
	hullHeat = max(uHullHeatLevel - 0.5, 0.0) * 2.0;
	hullHeat = Pulse(hullHeat * hullHeat, 0.1);
	float heat = hullHeat + uLaserHeatLevel  * laserAlpha;
	color += TemperatureGlow(heat);
	
	gl_FragColor = color;
}
important note: if you copy and paste the above into your shaders, make sure you check for blank spaces after the \ at the end of every line in the light macro in the fragment shader (lines 74 - 79) - there musn't be any, if there are, your shader won't run and you'll have a whole load of errors in your log - basically nearly almost everyline in the shader will be flagged up as having an error in it
User avatar
Zieman
---- E L I T E ----
---- E L I T E ----
Posts: 680
Joined: Tue Sep 01, 2009 11:55 pm
Location: in maZe

Post by Zieman »

Quick test:
fixed the shaders in Vector 1.3 OXP (see Griff's post about "Ahruman's later shaders" and now they seem to work, clean Latest.log and now I can see the ship. :)
...and keep it under lightspeed!

Friendliest Meteor Police that side of Riedquat

[EliteWiki] Far Arm ships
[EliteWiki] Z-ships
[EliteWiki] Baakili Far Trader
[EliteWiki] Tin of SPAM
User avatar
Svengali
Commander
Commander
Posts: 2370
Joined: Sat Oct 20, 2007 2:52 pm

Post by Svengali »

Griff wrote:
The shaders below set up a varying vec2 called vTexCoord to pass texture coordinates from the vertex to the fragment shader, texture coords are now set up using gl_MultiTexCoord0.st instead of gl_TexCoord[0].st, this seems to be more AMD friendly
:-) Gracias Griff.
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:
important note: if you copy and paste the above into your shaders, make sure you check for blank spaces after the \ at the end of every line in the light macro in the fragment shader (lines 74 - 79) - there musn't be any, if there are, your shader won't run and you'll have a whole load of errors in your log - basically nearly almost everyline in the shader will be flagged up as having an error in it
I strongly recommend not using macros like that. Since 1.73, the default shader uses two functions – CalcDiffuseLight() and CalcSpecularLight() – instead.
User avatar
Arexack_Heretic
Dangerous Subversive Element
Dangerous Subversive Element
Posts: 1878
Joined: Tue Jun 07, 2005 7:32 pm
Location: [%H] = Earth surface, Lattitude 52°10'58.19"N, longtitude 4°30'0.25"E.
Contact:

Post by Arexack_Heretic »

Could someone give me a redirect to a howto for normal maps?
I've been looking, but not very successfully. thanks:)
Riding the Rocket!
User avatar
JazHaz
---- E L I T E ----
---- E L I T E ----
Posts: 2991
Joined: Tue Sep 22, 2009 11:07 am
Location: Enfield, Middlesex
Contact:

Post by JazHaz »

Arexack_Heretic wrote:
Could someone give me a redirect to a howto for normal maps?
I've been looking, but not very successfully. thanks:)
Closest to what you want is here, but its quite technical. Ahruman wrote it! :wink:
JazHaz

Gimi wrote:
drew wrote:
£4,500 though! :shock: <Faints>
Cheers,
Drew.
Maybe you could start a Kickstarter Campaign to found your £4500 pledge. 8)
Thanks to Gimi, I got an eBook in my inbox tonight (31st May 2014 - Release of Elite Reclamation)!
Post Reply