Griff's normalmapped ship remakes

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

Moderators: another_commander, winston

User avatar
Cody
Sharp Shooter Spam Assassin
Sharp Shooter Spam Assassin
Posts: 16063
Joined: Sat Jul 04, 2009 9:31 pm
Location: The Lizard's Claw
Contact:

Re: Griff's normalmapped ship remakes

Post by Cody »

Sweet!
I would advise stilts for the quagmires, and camels for the snowy hills
And any survivors, their debts I will certainly pay. There's always a way!
User avatar
montana05
---- E L I T E ----
---- E L I T E ----
Posts: 1166
Joined: Mon May 30, 2016 3:54 am
Location: lurking in The Devils Triangle (G1)

Re: Griff's normalmapped ship remakes

Post by montana05 »

The master of graphics is back, a very warm welcome :)
Scars remind us where we've been. They don't have to dictate where we're going.
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

Re: Griff's normalmapped ship remakes

Post by Griff »

i definately need to read the pbr guide again, i'm certain i'm probaby using an incorrect material
heh, i edit shaders by just trying to copy as much as i can from oolite's default shader before rendermonkey breaks, the ones n the oxp "griff_HP_CobraIII_NPC" and "griff_HP_CobraIII_PLAYER" are the ones i've tried to get as close to what oolite is doing, they just send everything a deep blue in rendermonkey and a bit blueish (i think) in oolte - rendermonkey i think might be doing that as it probabky doesn't set up lights the same as oolite does, so stuff like .ambient might not have a proper value in it inside rendermonkey

it's this line i think
// light energy conservation here
vec4 kD = vec4(vec3(1.0) - fresnel, 1.0);

had to do this to stop the blueness
vec4 kD = vec4(1.0);

plus i also set a fixed specular colour to a warm yellow/orange
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 6557
Joined: Wed Feb 28, 2007 7:54 am

Re: Griff's normalmapped ship remakes

Post by another_commander »

Here it is, with some basic shader treatment. Includes energy conservation, gamma correction and tone mapping.

Image

Image

Image

The modified shader, based on griff_HP_CobraIII_PLAYER, is this:

Code: Select all

#define SUN_RADIANCE	3.0

const vec3 PRIMARY_COLOR[12] = vec3[](vec3(1.0, 0.2176, 0.1889),
                                      vec3(0.6090, 0.0484, 0.0),
                                      vec3(1.0, 0.4109, 0.0),
                                      vec3(0.8271, 0.6382, 0.0),
                                      vec3(0.1880, 0.5414, 0.3770),
                                      vec3(0.0, 0.2707, 0.0557),
                                      vec3(0.2133, 0.5105, 0.6617),
                                      vec3(0.1662, 0.0, 0.6617),
                                      vec3(0.5392, 0.1448, 0.6617),
                                      vec3(0.0, 0.0889, 0.2707),
                                      vec3(0.8571, 0.8150, 0.6510),
                                      vec3(0.2588,0.3083,0.2193));
                                
const vec3 SECONDARY_COLOR[12] = vec3[](vec3(0.5176, 0.0069, 0.0),                                
                                        vec3(0.1805, 0.0, 0.0053),
                                        vec3(0.3910, 0.0260, 0.0),
                                        vec3(0.8, 0.1846, 0.2315),
                                        vec3(0.0484, 0.1486, 0.3083),
                                        vec3(0.0, 0.0016, 0.3233),
                                        vec3(0.1974, 0.2537, 0.5113),
                                        vec3(0.0, 0.0333, 0.3233),
                                        vec3(0.0, 0.0637, 0.5113),
                                        vec3(0.0, 0.3097, 0.3233),
                                        vec3(0.2331, 0.2242, 0.2282),
                                        vec3(0.0, 0.1265, 0.2331));
                                        
// Information from vertex shader
   varying vec2   vTexCoord, scrollvTexCoord;
   varying vec3   vEyeVector, vLight1Vector;

   uniform int    uAlertLevel;  
   uniform int    uDamageAmount; 
   uniform int    uTradeFactor;
    
   uniform float  uDecal1_Rotation;  // rotation settings for decal 1
   uniform float  uDecal2_Rotation; //  rotation settings for decal
   uniform float  uEnginePower;
   uniform float  uGloss;
   uniform float  uHullHeatLevel;
   uniform float  uLaserHeatLevel;
   uniform float  uPaintColScheme;
   uniform float  uTime;

   uniform vec4   uDecal1_Scale_Position; // position & scale settings for decal 1
   uniform vec4   uDecal2_Scale_Position; // position & scale settings for decal 2
   uniform vec4   uExhaustCoreCol;
   uniform vec4   uExhaustPlumeCol;
   uniform vec4   uFogColor;
   
// Texture Uniforms
   uniform sampler2D  uDiffuseMap;
   uniform sampler2D  uNormalMap;
   uniform sampler2D  uEffectsMap;
   uniform sampler2D  uDecalMap;

// Glow color constants
   const vec4  kRedExhaustGlow = vec4(2.0, 0.4, 0.0, 1.0);
   const float kDecalCount = 16.0;
   const vec4  kLampColorNoAlert = vec4(0.0); 
   const vec4  kLampColorYellowAlert = vec4(0.9926, 0.9686, 0.7325, 1.0); 
   const vec4  kLampColorRedAlert = vec4(1.0, 0.1, 0.0, 1.0);
    
// Weathering effect constants
   const float kChipFactor = 4.5;
   const float kSmallChipFactor = 4.0;
   const vec4 kDustColor = vec4(0.3, 0.3, 0.3, 1.0);
   const vec4 kBareMetalColor = vec4(0.2, 0.2, 0.2, 1.0); // a dark grey
   const vec4 kPaintUndercoatColor = vec4(0.0724, 0.1105, 0.1407, 1.0); // a dark grey/blue colour  

// Function - Increase contrast level on supplied texturemap
   float contrast(vec4 inputsettings, float inputmap)
     { 
   float Tempresult = min(max(inputmap - inputsettings.r, 0.0) / (inputsettings.g - inputsettings.r), 1.0);
   float result = mix(inputsettings.b, inputsettings.a,Tempresult);
   return result; 
     }    
     
// Function - Calculate diffuse lighting
   vec4 CalcDiffuseLight(in vec3 lightVector, in vec3 normal, in vec4 lightColor)
     {
      float  intensity = dot(normal, lightVector);
             intensity = max(intensity, 0.0);
      return lightColor * intensity;
     }

// Fuction - Irregular flickering effect 
     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;
      }
   
// Function - Calculate hull temperature effect
   vec4 TemperatureGlow(float level) 
      { 
        vec4 result = vec4(0); 
    
        result.r = level; 
        result.g = level * level * level; 
        result.b = max(level - 0.6, 0.0);
        result.a = 1.0;
        return result * 2.0;    
      }  
     
// Function - return 'On' or 'Off' (used for damage effect on lights and engine glow)
   float Blink_on_off(float stepcutoff, float timeScale)
     {
        float result = step(stepcutoff, sin(uTime * timeScale));
        return result;
     }  
         
// Function - Calculate weapon temperature effect 
   vec4 WeaponGlow(float level)
     {
        vec4 result;
        result.rgb = vec3(1.38, 0.35, 0.20) * level;    
        result.a = 1.0;
        return result;
     } 

// Fuction - 'fizzy' noise effect 
   float rand(vec2 co)
     {
        float noise = 0.5 + fract(sin(dot(co.xy, vec2(12.9898, 78.233)))* 43758.5453);
        float clampednoise = step(noise, 0.9);
        return 2.0 + clampednoise;
     }

// Function - recolor engine glow when using 'Torus Drive'
   vec4 InjectorColGlow(vec4 ExhaustPlumeCol, float level) 
     { 
        vec4 result = ExhaustPlumeCol; 
        float TorusDimmer = smoothstep(0.0, 32.0, level);
          if (level > 1.0) // if > 1.0 ship is using afterburners, modify the glow rgb values
             { 
               result.r += level;
               result.g -= level; 
               result.b *= level; 
               result.a = 1.0;
                  
               vec4 moddedglow = vec4(0.0);
               moddedglow.r = min(result.r, 1.5);
               moddedglow.g = max(result.g, 0.0);
               moddedglow.b = min(result.b, 1.0);
               moddedglow.a = 1.0;
               result = moddedglow;
               result.rg += max(3.5 - level, 0.0); // add a brief flash of glow intensity when engpow>1.0  < 3.5
             } 
          else  
             {
               result * level; 
             }
         
           if (level > 8.0) // if > 8.0 ship is using Torus, dim the glow
             {
               result = mix(result, result * 0.3, TorusDimmer);
             }  
       return result;
     } 

/*
   Fuction - Part of new GGX lighting model. More physically accurate specular lighting models
   This is based on the GLSL code from FS2 SCP ( https://github.com/scp-fs2open )
*/

   vec3 FresnelSchlick(vec3 specColor, vec3 light, vec3 halfVec)
     {
       return specColor + (vec3(1.0) - specColor) * pow(1.0 - clamp(dot(light, halfVec), 0.0, 1.0), 5.0);
     }

   vec3 CalcSpecularGGX(vec3 light, vec3 normal, vec3 halfVec, vec3 view, float gloss, vec3 fresnel)
     {
       float NdotL = clamp(dot(normal, light), 0.0, 1.0);
       float roughness = clamp(1.0 - gloss, 0.0, 1.0);
       float alpha = roughness * roughness;
      
       float NdotH = clamp(dot(normal, halfVec), 0.0, 1.0);
       float NdotV = clamp(dot(normal, view), 0.0, 1.0);
      
       float alphaSqr = alpha * alpha;
       float pi = 3.14159;
       float denom = NdotH * NdotH * (alphaSqr - 1.0) + 1.0;
       float distribution = alphaSqr / (pi * denom * denom);
      
   // fresnel comes in pre-calculated
   
       float alphaPrime = roughness + 1.0;
       float k = alphaPrime * alphaPrime / 8.0;
       float g1vNL = NdotL / (NdotL * (1.0 - k) + k);
       float g1vNV = NdotV / (NdotV * (1.0 - k) + k);
       float visibility = g1vNL * g1vNV;
      
       return distribution * fresnel * visibility * NdotL / max(4.0 * NdotL * NdotV, 0.001);
}

// Function - Calculate position, scale and rotatation for the supplied decal texture
   vec4 the_decaliser(vec4 Your_Decal_Settings, float Your_decal_Rotation) 
      { 
      // Setup the basic texture co-ords for the decals 
         vec2 decal_TexCoord = vTexCoord; 
    
      // Position the decal     
         decal_TexCoord -= vec2(Your_Decal_Settings.s, Your_Decal_Settings.t - (0.5 / Your_Decal_Settings.p)); 

      // Orientate & scale the decal  
         float decal_s = sin(Your_decal_Rotation); 
         float decal_c = cos(Your_decal_Rotation); 

      // Nvidia Driver Workaround:
         vec2 DecalRotTemp = decal_TexCoord * mat2(decal_c, decal_s, -decal_s, decal_c);
         decal_TexCoord = DecalRotTemp; 
         decal_TexCoord += vec2(0.5 / Your_Decal_Settings.p); 
         decal_TexCoord *= vec2(Your_Decal_Settings.p, Your_Decal_Settings.p); 
 
      // Get texture values. 
         vec4 decal_Tex = texture2D(uDecalMap, decal_TexCoord);
		 decal_Tex.rgb = pow(decal_Tex.rgb, vec3(2.2));

      // Modify the Decals texture co-oords 
         decal_TexCoord.s += 1.0;
         decal_Tex *= step(1.0, decal_TexCoord.s) * 
                      step(0.0, decal_TexCoord.t) * 
                      step(-2.0, -decal_TexCoord.s) * 
                      step(-1.0, -decal_TexCoord.t); 
                 
      // Use the Alpha in the decal as a transparency mask so you can 'cutout' your decal from it's background
         float alpha = decal_Tex.a + 0.2; // strengthen the alpha a bit as otherwise the decals are too transparent
 
      // Return the scaled, position & rotated decal, it's mixed into the colour texture further on in the shader . 
         return alpha * decal_Tex;
     }
   
// Main loop
void main(void)
{
   vec4 totalColor = vec4(0.0);
   vec3 eyeVector = normalize(vEyeVector);
   vec2 texCoord = vTexCoord;

// Free up the blue channel from the normal map so we can use if for the weathering map
   vec2  normalRG = texture2D(uNormalMap, vTexCoord).rg * 2.0 - 1.0;
   float normalB  = sqrt(1.0 - normalRG.r * normalRG.r - normalRG.g * normalRG.g);
   vec3  normal = vec3(normalRG, normalB);

   vec4  diffuseMapColor = texture2D(uDiffuseMap, texCoord); // alpha channel is paintmask
   vec4  effectsMap = texture2D(uEffectsMap, texCoord);      // alpha channel is glossyness
   
   diffuseMapColor.rgb = pow(diffuseMapColor.rgb, vec3(2.2));
   effectsMap.rgb = pow(effectsMap.rgb, vec3(2.2));
   
   float glossMap = effectsMap.a;
   float glowMap = texture2D(uNormalMap, texCoord).a;
   float wearMap = texture2D(uNormalMap, vTexCoord).b;    // weathering map in b channel
   vec4  LampColor = diffuseMapColor; // light colour now baked into the colour map

// Trade Factor 'weathering' - do this early as we need the results to modify the gloss texture a but further down in the code
   float dustamount = (float(uTradeFactor) - 75.0) / 25.0;
   float chipamount = (float(uTradeFactor) - 10.0) / 90.0;
   float chipamountsmaller = (float(uTradeFactor) - 2.0) / 98.0;
   float EngMisFireLV = 1.0 - dustamount;

// Get light vectors
   vec3 lightVector = normalize(vLight1Vector);
   vec3 halfVector = normalize(lightVector + eyeVector);
   
// Get ambient colour
   vec4 ambientLight = gl_LightModel.ambient;

// Calculate diffuse lighting level
   vec4 diffuseLight = vec4(0);
   diffuseLight += CalcDiffuseLight(lightVector, normal, gl_LightSource[1].diffuse * SUN_RADIANCE);

// Calculate the decal texture, position, scale and rotation
   vec4 decals = the_decaliser(uDecal1_Scale_Position, uDecal1_Rotation) + the_decaliser(uDecal2_Scale_Position, uDecal2_Rotation);

// Darken the glossmap with the decal tex so decals appear less shiny that the metal they are painted on
   glossMap =mix(glossMap, min(decals.a, 0.2), decals.a); // darken the Glossmap with the decal so it appears more matte
   glossMap -= max(mix(diffuseMapColor.a, 0.0, dustamount), 0.0); // darken the glossmap by the paintmap. the paintmap areas are the most glossy, this dulls that

// Darken the glossmap by the dust amount so the ship appears more dull and less shiny in dusty areas 
   float DustLayer = smoothstep(dustamount, 1.0, contrast(vec4(0.5, 0.9, 0.0, 1.0), wearMap));
   glossMap =mix(glossMap, min(DustLayer, 0.0), DustLayer);

// Add the 'PaintChip' layer, we'll edge the chips with a slightly lighter version of the shape, to do this we need two copies of the chip shape, one slightly smaller than the other
   float PaintChip = step(chipamount, wearMap); // try glossMap, it's the same texture but with some manipulation by now 

// This is the smaller chip shape, subtracted from the large chip shape to find the chip edges later on in the shader...
   float PaintChipsmaller = step(chipamountsmaller, wearMap); 

// Subtract the smaller PaintChip from the bigger one to leave just the very edge of the shape
   float PaintChipEdge = PaintChip - PaintChipsmaller;
   
// Darken the glossmap by the larger paint chip, so that these areas are less glossy
   glossMap =mix(glossMap, min(PaintChipsmaller, 0.0), PaintChipsmaller);  // note: change the 0.0 to 1.0 and the chipped areas are made shiny
      
// Get specular parameters
   float specularExponentLevel = pow(glossMap, 2.0) + 0.001;
   #define APPLY_MAPPED_EXPONENT exponent = (exponent - 1.0) * specularExponentLevel + 1.0

   vec4 specularColor = gl_FrontMaterial.specular;

   vec3 fresnel = vec3(0.0);
   
// Calculate specular light
   vec4 specularLight = vec4(0);
   float exponent = gl_FrontMaterial.shininess;
   APPLY_MAPPED_EXPONENT;
   
   fresnel = FresnelSchlick(specularColor.rgb, lightVector, halfVector);  
   float gloss = uGloss;
         gloss *= glossMap * 1.5;

   
   
   vec4 ambientColor = gl_FrontMaterial.ambient;
   vec4 diffuseColor = gl_FrontMaterial.diffuse;

// Begin repaint the colour texture - Select the paint scheme from the two arrays
   int  PaintIndex = int(uPaintColScheme);
   vec4 PaintPrimaryCol   = vec4(vec3(PRIMARY_COLOR[PaintIndex]), 1.0);
   vec4 PaintSecondaryCol = vec4(vec3(SECONDARY_COLOR[PaintIndex]), 1.0);

// Calculate the mixing effect for the two paint colours, we'll run the paintMap (diffuseMapColor A) texture through the increse contrast function to get a map we can use to control the mix
   float paintmixmap = contrast(vec4(0.5, 0.8, 0.2, 1.0), diffuseMapColor.a);
   vec4 paintmix = mix(PaintSecondaryCol, PaintPrimaryCol, paintmixmap);
   vec4 painteddiffuseMap = mix(diffuseMapColor, paintmix, diffuseMapColor.a);
  
// Mix the colour for the decal back into the main colour texture
   vec4 decalTex = mix(painteddiffuseMap, decals, decals.a);  // change diffuseMapColor to vec4(0.0) if you want to place the decal on a black background 
   vec4 decalpainteddiffuseMapcolor = mix(painteddiffuseMap, decalTex, decals.a);
  
// Dull the paint by mixing between a colour and a greyscale version
   float GreyMixLevel = max(0.65, dustamount); // set the amount to mix between colour & greyscale versions of the texture, cap it a 65% color, 35% greyscale
   float average = (decalpainteddiffuseMapcolor.r + decalpainteddiffuseMapcolor.g + decalpainteddiffuseMapcolor.b) / 3.0;
   vec4 greyscaleversion = vec4(average, average, average, 1.0) ; 
   vec4 greycolor = mix(greyscaleversion, decalpainteddiffuseMapcolor, GreyMixLevel); // mix between the greyscale & colour versions of the texture, use the dulllevel to control the mix

// Add the dust layer   
   vec4 dustaddedcolor  = mix(greycolor, kDustColor, DustLayer);

// Colour then mix in the PaintChip layers       
   vec4  PaintChipLayer = PaintChip * kBareMetalColor;
         PaintChipLayer += PaintChipEdge * kPaintUndercoatColor;   
   vec4 chippedpaint = mix(dustaddedcolor, PaintChipLayer, PaintChip);  
  
// Put everything created so far back into the color texture   
   diffuseMapColor = chippedpaint;

// Calculate the lighting color  
   diffuseColor  *= diffuseMapColor;
   ambientColor  *= diffuseMapColor;
//   specularColor *= diffuseMapColor; // We're not using a specular colour map, so colour the spec with the colour texturemap

	specularLight = vec4(CalcSpecularGGX(lightVector, normal, halfVector, eyeVector, gloss * (1.0 - decals.a), fresnel), 0.0);
   specularLight.a = 1.0; 

// light energy conservation here
   vec4 kD = vec4(vec3(1.0) - fresnel, 1.0);

   totalColor += (diffuseColor * diffuseLight * kD) + (ambientColor * ambientLight);

// Apply Specular
   totalColor += specularLight * gl_LightSource[1].specular * SUN_RADIANCE;

// calculate the hull lights
   vec4 Lamp_pass = mix(vec4(0.0), diffuseMapColor, glowMap); 

// Engine glow animation effect
   vec2 scrolloffset = vec2(vTexCoord.s + effectsMap.r, vTexCoord.t + effectsMap.b); 
   float scrollingheatMap = texture2D(uDiffuseMap, scrollvTexCoord + scrolloffset).a * effectsMap.r;
    
// Call the function to modify the engine glow colour depending on current ship speed
   vec4 PlumeColGLow = InjectorColGlow(uExhaustPlumeCol, uEnginePower);

// Calculate random engine flicker
   vec2 twmp = vec2(vTexCoord * uTime);
   float engnoise = rand(twmp);
   float engineburp = max(0.8, sin(Pulse(uTime, 0.2))); // calculate small 'blip' for engine core glow level     
     
// Check if ship is hostile, adjust lampColor accordingly
   if (uAlertLevel  > 0)
      { 
        totalColor -= glowMap;
        LampColor = (uAlertLevel > 2) ? kLampColorRedAlert  * max(mod(uTime, 1.0), 0.5): kLampColorYellowAlert; 
      }   
   else 
      { 
        LampColor =  kLampColorNoAlert; 
      }
 
// Calculate the amount to ship damage to apply
   float tempvar = float(uDamageAmount); 
   float DamageAmount = mod(tempvar, 100.0) / 100.0;
   
// Calculate the engine and lamp glows
   float LowLevelCoreGlow = smoothstep(0.0, 1.0, uEnginePower);
   vec4 Lampglow = Lamp_pass * LampColor * Pulse(2.0, 1.0) * (1.0  - DamageAmount);  
   vec4 PlumeGlow = PlumeColGLow * effectsMap.b * Pulse(min(uEnginePower, 1.0), 1.0); 

// Add a very low speed core glow colour, fade it out as speed increases
   if (uEnginePower > 0.001) 
      { 
        totalColor += uExhaustCoreCol * effectsMap.b * max(0.0, 1.0 - LowLevelCoreGlow) * 0.2;
      }
   vec4 CoreGlow = uExhaustCoreCol * effectsMap.r * Pulse(min(uEnginePower, 1.0), 1.0) ;      
        CoreGlow  += uExhaustCoreCol * engineburp * effectsMap.r * step(0.001, uEnginePower); // add in core glow level 'jitter'
        CoreGlow  *= engnoise;
   vec4 FinalCoreGlow = mix(CoreGlow, CoreGlow * scrollingheatMap, min(uEnginePower, 0.8));

// Calculate a red glow for the engine core to simulate heated metal. This glow stays visible whilst the rest of the engine effect flickers from shipdamage
   vec4 ConstCoreGlow = kRedExhaustGlow * effectsMap.r * Pulse(min(uEnginePower, 1.0), 1.0) * Blink_on_off(0.5, Pulse(1.0, 0.6));
        ConstCoreGlow += kRedExhaustGlow * effectsMap.r * Pulse(min(uEnginePower, 1.0), 1.0) * Blink_on_off(0.5, Pulse(1.0, 0.7));

// Apply the engine and lamp glows  
   totalColor += mix(Lampglow + PlumeGlow + FinalCoreGlow,  
               ConstCoreGlow + 
               Lampglow * Blink_on_off(0.5, Pulse(1.0, 0.4)) * 4.0 + 
              PlumeGlow * Blink_on_off(0.5, Pulse(1.0, 1.0)), max(0.0, DamageAmount - 0.4));

// Apply the lasergun heat glow   
   totalColor += WeaponGlow(effectsMap.g * Pulse(min(uLaserHeatLevel, 1.0), 1.0));
        
// Calculate an engine misfire flicker, this only kick in when Tradefactor pases 80%                                            
   float EngineMisFire = effectsMap.b * uEnginePower * max(0.0, EngMisFireLV - 0.8);
   totalColor += kRedExhaustGlow * Blink_on_off(0.9, Pulse(0.5, 0.9)) * EngineMisFire; // use vec4(5.0) to get a really strong white flash
 
// Apply the hull temperature glow
   float hullHeat = max(uHullHeatLevel - 0.5, 0.0) * 2.0; 
   hullHeat = Pulse(hullHeat * hullHeat, 0.1); 
   totalColor += TemperatureGlow(hullHeat);  
   
   
	vec3 x = max(vec3(0.0), totalColor.rgb - 0.004);
	totalColor.rgb = (x * (6.2 * x + 0.5)) / (x * (6.2 * x + 1.7) + 0.06);

gl_FragColor = mix(totalColor, vec4(uFogColor.xyz, 1.0), 0.0); // change 0.0 to uFogColor.w for oolite

}
and the modification to the player shipdata entry:

Code: Select all

"griff_HP_CobraIII_player" = 
	{
	like_ship = "oolite_template_cobra3";
	aft_eject_position = "0.0 -7.7913 -15.047";
	exhaust = (		
				"5.6  0.0 -12.3 3.0 2.0 1.5",
				"-5.6 0.0 -12.3 3.0 2.0 1.5",
				"15.8 0.05 -12.3 1.0 1.0 1.5",
				"-15.8 0.05 -12.3 1.0 1.0 1.5" 
			);
	materials = 
		{ 
			"Hull" = 
			{ 
				diffuse_map = "griff_HP_CobraIII_diffuse.png"; 
				specular_color = ( 0.04, 0.04, 0.04 );  // Applies when specular map is not used (no shaders) 
				shininess = 35; 
				gloss = 0.72;
				emission_map = { name = "griff_HP_CobraIII_normal.png"; extract_channel = "a"; }; 
				emission_modulate_color = (0.9926, 0.9686, 0.7325); 
			}; 
		};
	missile_launch_position = "0.0 -2.7316 10.1303";
	model = "griff_HP_CobraIII.dat"; 
	scoop_position = "0.0 -3.0757 6.61";
	roles = "player";	
	shaders = 
		{ 
            "Hull" = 
			{ 
				specular_color = (0.72, 0.72, 0.72);
                vertex_shader = "griff_normalmap_ships_withScroll.vertex"; 
		//		fragment_shader = "NoEnergyConservation_PLAYERShader.fragment"; // hardcoded SpecCol, no EnergyConservation
              fragment_shader = "griff_HP_CobraIII_PLAYER.fragment";  // more similar to Oolite Default Shader

                textures = 
						(
						{name = "griff_HP_CobraIII_diffuse.png"; repeat_s = "yes"; repeat_t = "yes";},
								"griff_HP_CobraIII_normal.png",
								"griff_HP_CobraIII_effects.png",
								"griff_HP_cobraIII_playerdecal.png"
						);
				uniforms =
						{
						uDiffuseMap = { type = texture; value = 0; };
						uNormalMap = { type = texture; value = 1; };
						uEffectsMap = { type = texture; value = 2; };
						uDecalMap = { type = texture; value = 3; };	

						uAlertLevel = "alertCondition";
						uDamageAmount = "damage";
						uTradeFactor = "tradeInFactor"; 	

						uDecal1_Rotation = { type = "float"; value = 0.75; };  
					    uDecal2_Rotation = { type = "float"; value = -1.0; };
						uEnginePower = "speedFactor"; 
						uGloss = { type = "float"; value = 1.0; };
						uHullHeatLevel = "hullHeatLevel";	
						uLaserHeatLevel = "laserHeatLevel";
						uPaintColScheme = { type = "randomFloat"; scale = 11.0;};
						uTime = "universalTime";

					    uDecal1_Scale_Position = { type = vector; value = "0.18 0.22 12.0"; };
					    uDecal2_Scale_Position = { type = vector; value = "0.59 0.34 20.0"; };
						uExhaustCoreCol = {type = vector; value = "0.4549 0.8062 0.8431";};
						uExhaustPlumeCol = {type = vector; value = "0.0 0.3471 1.0";};
						uFogColor = "fogUniform";
						}; 
			};
		};
						
			view_position_aft = "0.0 2.4489 -12.3025";
			view_position_forward = "0.0 1.2416 8.1737";
			view_position_port = "-18.4308 -0.19 -2.2775";
			view_position_starboard = "18.4308 -0.19 -2.2775";
			weapon_position_forward = "0.0 0.1997 13.2055";
			weapon_position_aft = "0.0 1.7538 -12.3025";
			weapon_position_port = "-18.4308 -0.5321 -2.2775";
			weapon_position_starboard = "18.4308 -0.5321 -2.2775";
		custom_views =
				(
					{
						view_description = "Rear View";
						view_orientation = "1.0 0.0 0.0 0.0";
						view_position = "0.0 6.0 -55.00";
						weapon_facing = "FORWARD";
					},
					{
						view_description = "Rear Right View";
						view_orientation = "0.9239 0.0 0.3827 0.0";
						view_position = "38.8909 6.0 -38.8909";
						weapon_facing = "FORWARD";
					},
					{
						view_description = "Right View";
						view_orientation = "0.7071 0.0 0.7071 0.0";
						view_position = "55.0 6.0 0.0 ";
						weapon_facing = "FORWARD";
					},
					{
						view_description = "Front Right View";
						view_orientation = "0.3827 0.0 0.9239 0.0";
						view_position = "38.8909 6.0 38.8909";
						weapon_facing = "FORWARD";
					},
					{
						view_description = "Front View";
						view_orientation = "0.0 0.0 1.0 0.0";
						view_position = "0.0 6.0 55.0";
						weapon_facing = "FORWARD";
					},
					{
						view_description = "Front Left View";
						view_orientation = "0.3827 0.0 -0.9239 0.0";
						view_position = "-38.8909 6.0 38.8909";
						weapon_facing = "FORWARD";
					},
					{
						view_description = "Left View";
						view_orientation = "0.7071 0.0 -0.7071 0.0";
						view_position = "-55.0 6.0 0.0";
						weapon_facing = "FORWARD";
					},
					{
						view_description = "Rear Left View";
						view_orientation = "0.9239 0.0 -0.3827 0.0";
						view_position = "-38.8909 6.0 -38.8909";
						weapon_facing = "FORWARD";
					},
					{
						view_description = "Top View";
						view_orientation = "-0.7071 0.7071 0.0 0.0";
						view_position = "0.0 65.0 0.0";
						weapon_facing = "FORWARD";
					},
					{
						view_description = "Bottom View";
						view_orientation = "0.0 0.0 0.7071 0.7071";
						view_position = "0.0 -85.0 0.0";
						weapon_facing = "FORWARD";
					}
				);	
	};
I really dig the blue light emitted from the engines.
User avatar
Cholmondely
Archivist
Archivist
Posts: 5006
Joined: Tue Jul 07, 2020 11:00 am
Location: The Delightful Domains of His Most Britannic Majesty (industrial? agricultural? mainly anything?)
Contact:

Re: Griff's normalmapped ship remakes

Post by Cholmondely »

Inspiring!

I'd really rather like one...

Not too sure where I'd keep it ... our coach-house is a tad on the small side ...
Comments wanted:
Missing OXPs? What do you think is missing?
Lore: The economics of ship building How many built for Aronar?
Lore: The Space Traders Flight Training Manual: Cowell & MgRath Do you agree with Redspear?
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

Re: Griff's normalmapped ship remakes

Post by Griff »

wow that looks great, thanks for fixing the shader A_C, :) i'll copy the fixes and update the oxp, i'll set t player version to use multiple decals too
User avatar
Redspear
---- E L I T E ----
---- E L I T E ----
Posts: 2645
Joined: Thu Jun 20, 2013 10:22 pm

Re: Griff's normalmapped ship remakes

Post by Redspear »

Love it!

That near equilateral triangle at the nose really brings the flavour of the original elite model... while the detailing takes it to another level entirely.

Good job Griff! (and nicely fixed a_c) 8)
User avatar
Cody
Sharp Shooter Spam Assassin
Sharp Shooter Spam Assassin
Posts: 16063
Joined: Sat Jul 04, 2009 9:31 pm
Location: The Lizard's Claw
Contact:

Re: Griff's normalmapped ship remakes

Post by Cody »

Griff wrote: Wed Nov 25, 2020 4:10 pm
... i'll set t player version to use multiple decals too
Music to my ears, amigo!
I would advise stilts for the quagmires, and camels for the snowy hills
And any survivors, their debts I will certainly pay. There's always a way!
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 6557
Joined: Wed Feb 28, 2007 7:54 am

Re: Griff's normalmapped ship remakes

Post by another_commander »

I have made a few more edits on the Cobra shader in order to comment a bit better the things I changed and also because I found that some of the calculations done were not actually used and could be omitted. Also reduced slightly the overall gloss applied by the shader, so that we get back the nice cockpit reflection present in the original shader. Here is the modified griff_HP_CobraIII_PLAYER.fragment shader in its current form:

Code: Select all

#define SUN_RADIANCE	3.0

const vec3 PRIMARY_COLOR[12] = vec3[](vec3(1.0, 0.2176, 0.1889),
                                      vec3(0.6090, 0.0484, 0.0),
                                      vec3(1.0, 0.4109, 0.0),
                                      vec3(0.8271, 0.6382, 0.0),
                                      vec3(0.1880, 0.5414, 0.3770),
                                      vec3(0.0, 0.2707, 0.0557),
                                      vec3(0.2133, 0.5105, 0.6617),
                                      vec3(0.1662, 0.0, 0.6617),
                                      vec3(0.5392, 0.1448, 0.6617),
                                      vec3(0.0, 0.0889, 0.2707),
                                      vec3(0.8571, 0.8150, 0.6510),
                                      vec3(0.2588,0.3083,0.2193));
                                
const vec3 SECONDARY_COLOR[12] = vec3[](vec3(0.5176, 0.0069, 0.0),                                
                                        vec3(0.1805, 0.0, 0.0053),
                                        vec3(0.3910, 0.0260, 0.0),
                                        vec3(0.8, 0.1846, 0.2315),
                                        vec3(0.0484, 0.1486, 0.3083),
                                        vec3(0.0, 0.0016, 0.3233),
                                        vec3(0.1974, 0.2537, 0.5113),
                                        vec3(0.0, 0.0333, 0.3233),
                                        vec3(0.0, 0.0637, 0.5113),
                                        vec3(0.0, 0.3097, 0.3233),
                                        vec3(0.2331, 0.2242, 0.2282),
                                        vec3(0.0, 0.1265, 0.2331));
                                        
// Information from vertex shader
   varying vec2   vTexCoord, scrollvTexCoord;
   varying vec3   vEyeVector, vLight1Vector;

   uniform int    uAlertLevel;  
   uniform int    uDamageAmount; 
   uniform int    uTradeFactor;
    
   uniform float  uDecal1_Rotation;  // rotation settings for decal 1
   uniform float  uDecal2_Rotation; //  rotation settings for decal
   uniform float  uEnginePower;
   uniform float  uGloss;
   uniform float  uHullHeatLevel;
   uniform float  uLaserHeatLevel;
   uniform float  uPaintColScheme;
   uniform float  uTime;

   uniform vec4   uDecal1_Scale_Position; // position & scale settings for decal 1
   uniform vec4   uDecal2_Scale_Position; // position & scale settings for decal 2
   uniform vec4   uExhaustCoreCol;
   uniform vec4   uExhaustPlumeCol;
   uniform vec4   uFogColor;
   
// Texture Uniforms
   uniform sampler2D  uDiffuseMap;
   uniform sampler2D  uNormalMap;
   uniform sampler2D  uEffectsMap;
   uniform sampler2D  uDecalMap;

// Glow color constants
   const vec4  kRedExhaustGlow = vec4(2.0, 0.4, 0.0, 1.0);
   const float kDecalCount = 16.0;
   const vec4  kLampColorNoAlert = vec4(0.0); 
   const vec4  kLampColorYellowAlert = vec4(0.9926, 0.9686, 0.7325, 1.0); 
   const vec4  kLampColorRedAlert = vec4(1.0, 0.1, 0.0, 1.0);
    
// Weathering effect constants
   const float kChipFactor = 4.5;
   const float kSmallChipFactor = 4.0;
   const vec4 kDustColor = vec4(0.3, 0.3, 0.3, 1.0);
   const vec4 kBareMetalColor = vec4(0.2, 0.2, 0.2, 1.0); // a dark grey
   const vec4 kPaintUndercoatColor = vec4(0.0724, 0.1105, 0.1407, 1.0); // a dark grey/blue colour  

// Function - Increase contrast level on supplied texturemap
   float contrast(vec4 inputsettings, float inputmap)
     { 
   float Tempresult = min(max(inputmap - inputsettings.r, 0.0) / (inputsettings.g - inputsettings.r), 1.0);
   float result = mix(inputsettings.b, inputsettings.a,Tempresult);
   return result; 
     }    
     
// Function - Calculate diffuse lighting
   vec4 CalcDiffuseLight(in vec3 lightVector, in vec3 normal, in vec4 lightColor)
     {
      float  intensity = dot(normal, lightVector);
             intensity = max(intensity, 0.0);
      return lightColor * intensity;
     }

// Fuction - Irregular flickering effect 
     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;
      }
   
// Function - Calculate hull temperature effect
   vec4 TemperatureGlow(float level) 
      { 
        vec4 result = vec4(0); 
    
        result.r = level; 
        result.g = level * level * level; 
        result.b = max(level - 0.6, 0.0);
        result.a = 1.0;
        return result * 2.0;    
      }  
     
// Function - return 'On' or 'Off' (used for damage effect on lights and engine glow)
   float Blink_on_off(float stepcutoff, float timeScale)
     {
        float result = step(stepcutoff, sin(uTime * timeScale));
        return result;
     }  
         
// Function - Calculate weapon temperature effect 
   vec4 WeaponGlow(float level)
     {
        vec4 result;
        result.rgb = vec3(1.38, 0.35, 0.20) * level;    
        result.a = 1.0;
        return result;
     } 

// Fuction - 'fizzy' noise effect 
   float rand(vec2 co)
     {
        float noise = 0.5 + fract(sin(dot(co.xy, vec2(12.9898, 78.233)))* 43758.5453);
        float clampednoise = step(noise, 0.9);
        return 2.0 + clampednoise;
     }

// Function - recolor engine glow when using 'Torus Drive'
   vec4 InjectorColGlow(vec4 ExhaustPlumeCol, float level) 
     { 
        vec4 result = ExhaustPlumeCol; 
        float TorusDimmer = smoothstep(0.0, 32.0, level);
          if (level > 1.0) // if > 1.0 ship is using afterburners, modify the glow rgb values
             { 
               result.r += level;
               result.g -= level; 
               result.b *= level; 
               result.a = 1.0;
                  
               vec4 moddedglow = vec4(0.0);
               moddedglow.r = min(result.r, 1.5);
               moddedglow.g = max(result.g, 0.0);
               moddedglow.b = min(result.b, 1.0);
               moddedglow.a = 1.0;
               result = moddedglow;
               result.rg += max(3.5 - level, 0.0); // add a brief flash of glow intensity when engpow>1.0  < 3.5
             } 
          else  
             {
               result * level; 
             }
         
           if (level > 8.0) // if > 8.0 ship is using Torus, dim the glow
             {
               result = mix(result, result * 0.3, TorusDimmer);
             }  
       return result;
     } 

/*
   Function - Part of new GGX lighting model. More physically accurate specular lighting models
   This is based on the GLSL code from FS2 SCP ( https://github.com/scp-fs2open )
*/

   vec3 FresnelSchlick(vec3 specColor, vec3 light, vec3 halfVec)
     {
       return specColor + (vec3(1.0) - specColor) * pow(1.0 - clamp(dot(light, halfVec), 0.0, 1.0), 5.0);
     }

   vec3 CalcSpecularGGX(vec3 light, vec3 normal, vec3 halfVec, vec3 view, float gloss, vec3 fresnel)
     {
       float NdotL = clamp(dot(normal, light), 0.0, 1.0);
       float roughness = clamp(1.0 - gloss, 0.0, 1.0);
       float alpha = roughness * roughness;
      
       float NdotH = clamp(dot(normal, halfVec), 0.0, 1.0);
       float NdotV = clamp(dot(normal, view), 0.0, 1.0);
      
       float alphaSqr = alpha * alpha;
       float pi = 3.14159;
       float denom = NdotH * NdotH * (alphaSqr - 1.0) + 1.0;
       float distribution = alphaSqr / (pi * denom * denom);
      
   // fresnel comes in pre-calculated
   
       float alphaPrime = roughness + 1.0;
       float k = alphaPrime * alphaPrime / 8.0;
       float g1vNL = NdotL / (NdotL * (1.0 - k) + k);
       float g1vNV = NdotV / (NdotV * (1.0 - k) + k);
       float visibility = g1vNL * g1vNV;
      
       return distribution * fresnel * visibility * NdotL / max(4.0 * NdotL * NdotV, 0.001);
}

// Function - Calculate position, scale and rotatation for the supplied decal texture
   vec4 the_decaliser(vec4 Your_Decal_Settings, float Your_decal_Rotation) 
      { 
      // Setup the basic texture co-ords for the decals 
         vec2 decal_TexCoord = vTexCoord; 
    
      // Position the decal     
         decal_TexCoord -= vec2(Your_Decal_Settings.s, Your_Decal_Settings.t - (0.5 / Your_Decal_Settings.p)); 

      // Orientate & scale the decal  
         float decal_s = sin(Your_decal_Rotation); 
         float decal_c = cos(Your_decal_Rotation); 

      // Nvidia Driver Workaround:
         vec2 DecalRotTemp = decal_TexCoord * mat2(decal_c, decal_s, -decal_s, decal_c);
         decal_TexCoord = DecalRotTemp; 
         decal_TexCoord += vec2(0.5 / Your_Decal_Settings.p); 
         decal_TexCoord *= vec2(Your_Decal_Settings.p, Your_Decal_Settings.p); 
 
      // Get texture values. 
         vec4 decal_Tex = texture2D(uDecalMap, decal_TexCoord);
	  // Remove gamma correction from the texture - we're going to do math on the color values so we need them
	  // to be in linear colorspace
		 decal_Tex.rgb = pow(decal_Tex.rgb, vec3(2.2));

      // Modify the Decals texture co-oords 
         decal_TexCoord.s += 1.0;
         decal_Tex *= step(1.0, decal_TexCoord.s) * 
                      step(0.0, decal_TexCoord.t) * 
                      step(-2.0, -decal_TexCoord.s) * 
                      step(-1.0, -decal_TexCoord.t); 
                 
      // Use the Alpha in the decal as a transparency mask so you can 'cutout' your decal from it's background
         float alpha = decal_Tex.a + 0.2; // strengthen the alpha a bit as otherwise the decals are too transparent
 
      // Return the scaled, position & rotated decal, it's mixed into the colour texture further on in the shader . 
         return alpha * decal_Tex;
     }
   
// Main loop
void main(void)
{
   vec4 totalColor = vec4(0.0);
   vec3 eyeVector = normalize(vEyeVector);
   vec2 texCoord = vTexCoord;

// Free up the blue channel from the normal map so we can use if for the weathering map
   vec2  normalRG = texture2D(uNormalMap, vTexCoord).rg * 2.0 - 1.0;
   float normalB  = sqrt(1.0 - normalRG.r * normalRG.r - normalRG.g * normalRG.g);
   vec3  normal = vec3(normalRG, normalB);

   vec4  diffuseMapColor = texture2D(uDiffuseMap, texCoord); // alpha channel is paintmask
   vec4  effectsMap = texture2D(uEffectsMap, texCoord);      // alpha channel is glossyness
   
// Remove gamma correction and get the required texture colors in linear color space - we're 
// going to do math on them
   diffuseMapColor.rgb = pow(diffuseMapColor.rgb, vec3(2.2));
   effectsMap.rgb = pow(effectsMap.rgb, vec3(2.2));
   
   float glossMap = effectsMap.a;
   float glowMap = texture2D(uNormalMap, texCoord).a;
   float wearMap = texture2D(uNormalMap, vTexCoord).b;    // weathering map in b channel
   vec4  LampColor = diffuseMapColor; // light colour now baked into the colour map

// Trade Factor 'weathering' - do this early as we need the results to modify the gloss texture a but further down in the code
   float dustamount = (float(uTradeFactor) - 75.0) / 25.0;
   float chipamount = (float(uTradeFactor) - 10.0) / 90.0;
   float chipamountsmaller = (float(uTradeFactor) - 2.0) / 98.0;
   float EngMisFireLV = 1.0 - dustamount;

// Get light vectors
   vec3 lightVector = normalize(vLight1Vector);
   vec3 halfVector = normalize(lightVector + eyeVector);
   
// Get ambient colour
   vec4 ambientLight = gl_LightModel.ambient;

// Calculate diffuse lighting level
   vec4 diffuseLight = vec4(0);
   diffuseLight += CalcDiffuseLight(lightVector, normal, gl_LightSource[1].diffuse * SUN_RADIANCE);

// Calculate the decal texture, position, scale and rotation
   vec4 decals = the_decaliser(uDecal1_Scale_Position, uDecal1_Rotation) + the_decaliser(uDecal2_Scale_Position, uDecal2_Rotation);

// Darken the glossmap with the decal tex so decals appear less shiny that the metal they are painted on
   glossMap =mix(glossMap, min(decals.a, 0.2), decals.a); // darken the Glossmap with the decal so it appears more matte
   glossMap -= max(mix(diffuseMapColor.a, 0.0, dustamount), 0.0); // darken the glossmap by the paintmap. the paintmap areas are the most glossy, this dulls that

// Darken the glossmap by the dust amount so the ship appears more dull and less shiny in dusty areas 
   float DustLayer = smoothstep(dustamount, 1.0, contrast(vec4(0.5, 0.9, 0.0, 1.0), wearMap));
   glossMap =mix(glossMap, min(DustLayer, 0.0), DustLayer);

// Add the 'PaintChip' layer, we'll edge the chips with a slightly lighter version of the shape, to do this we need two copies of the chip shape, one slightly smaller than the other
   float PaintChip = step(chipamount, wearMap); // try glossMap, it's the same texture but with some manipulation by now 

// This is the smaller chip shape, subtracted from the large chip shape to find the chip edges later on in the shader...
   float PaintChipsmaller = step(chipamountsmaller, wearMap); 

// Subtract the smaller PaintChip from the bigger one to leave just the very edge of the shape
   float PaintChipEdge = PaintChip - PaintChipsmaller;
   
// Darken the glossmap by the larger paint chip, so that these areas are less glossy
   glossMap =mix(glossMap, min(PaintChipsmaller, 0.0), PaintChipsmaller);  // note: change the 0.0 to 1.0 and the chipped areas are made shiny
      
// Get specular parameters
   vec4 specularColor = gl_FrontMaterial.specular;

   vec3 fresnel = vec3(0.0);
   
// Calculate specular light
   vec4 specularLight = vec4(0);
   
   fresnel = FresnelSchlick(specularColor.rgb, lightVector, halfVector);  
   float gloss = uGloss;
         gloss *= glossMap;

   
   
   vec4 ambientColor = gl_FrontMaterial.ambient;
   vec4 diffuseColor = gl_FrontMaterial.diffuse;

// Begin repaint the colour texture - Select the paint scheme from the two arrays
   int  PaintIndex = int(uPaintColScheme);
   vec4 PaintPrimaryCol   = vec4(vec3(PRIMARY_COLOR[PaintIndex]), 1.0);
   vec4 PaintSecondaryCol = vec4(vec3(SECONDARY_COLOR[PaintIndex]), 1.0);

// Calculate the mixing effect for the two paint colours, we'll run the paintMap (diffuseMapColor A) texture through the increse contrast function to get a map we can use to control the mix
   float paintmixmap = contrast(vec4(0.5, 0.8, 0.2, 1.0), diffuseMapColor.a);
   vec4 paintmix = mix(PaintSecondaryCol, PaintPrimaryCol, paintmixmap);
   vec4 painteddiffuseMap = mix(diffuseMapColor, paintmix, diffuseMapColor.a);
  
// Mix the colour for the decal back into the main colour texture
   vec4 decalTex = mix(painteddiffuseMap, decals, decals.a);  // change diffuseMapColor to vec4(0.0) if you want to place the decal on a black background 
   vec4 decalpainteddiffuseMapcolor = mix(painteddiffuseMap, decalTex, decals.a);
  
// Dull the paint by mixing between a colour and a greyscale version
   float GreyMixLevel = max(0.65, dustamount); // set the amount to mix between colour & greyscale versions of the texture, cap it a 65% color, 35% greyscale
   float average = (decalpainteddiffuseMapcolor.r + decalpainteddiffuseMapcolor.g + decalpainteddiffuseMapcolor.b) / 3.0;
   vec4 greyscaleversion = vec4(average, average, average, 1.0) ; 
   vec4 greycolor = mix(greyscaleversion, decalpainteddiffuseMapcolor, GreyMixLevel); // mix between the greyscale & colour versions of the texture, use the dulllevel to control the mix

// Add the dust layer   
   vec4 dustaddedcolor  = mix(greycolor, kDustColor, DustLayer);

// Colour then mix in the PaintChip layers       
   vec4  PaintChipLayer = PaintChip * kBareMetalColor;
         PaintChipLayer += PaintChipEdge * kPaintUndercoatColor;   
   vec4 chippedpaint = mix(dustaddedcolor, PaintChipLayer, PaintChip);  
  
// Put everything created so far back into the color texture   
   diffuseMapColor = chippedpaint;

// Calculate the lighting color  
   diffuseColor  *= diffuseMapColor;
   ambientColor  *= diffuseMapColor;

   specularLight = vec4(CalcSpecularGGX(lightVector, normal, halfVector, eyeVector, gloss * (1.0 - decals.a), fresnel), 0.0);
   specularLight.a = 1.0; 

// light energy conservation here
   vec4 kD = vec4(vec3(1.0) - fresnel, 1.0);

// Apply diffuse + ambient
   totalColor += (diffuseColor * diffuseLight * kD) + (ambientColor * ambientLight);

// Apply Specular
   totalColor += specularLight * gl_LightSource[1].specular * SUN_RADIANCE;

// calculate the hull lights
   vec4 Lamp_pass = mix(vec4(0.0), diffuseMapColor, glowMap); 

// Engine glow animation effect
   vec2 scrolloffset = vec2(vTexCoord.s + effectsMap.r, vTexCoord.t + effectsMap.b); 
   float scrollingheatMap = texture2D(uDiffuseMap, scrollvTexCoord + scrolloffset).a * effectsMap.r;
    
// Call the function to modify the engine glow colour depending on current ship speed
   vec4 PlumeColGLow = InjectorColGlow(uExhaustPlumeCol, uEnginePower);

// Calculate random engine flicker
   vec2 twmp = vec2(vTexCoord * uTime);
   float engnoise = rand(twmp);
   float engineburp = max(0.8, sin(Pulse(uTime, 0.2))); // calculate small 'blip' for engine core glow level     
     
// Check if ship is hostile, adjust lampColor accordingly
   if (uAlertLevel  > 0)
      { 
        totalColor -= glowMap;
        LampColor = (uAlertLevel > 2) ? kLampColorRedAlert  * max(mod(uTime, 1.0), 0.5): kLampColorYellowAlert; 
      }   
   else 
      { 
        LampColor =  kLampColorNoAlert; 
      }
 
// Calculate the amount to ship damage to apply
   float tempvar = float(uDamageAmount); 
   float DamageAmount = mod(tempvar, 100.0) / 100.0;
   
// Calculate the engine and lamp glows
   float LowLevelCoreGlow = smoothstep(0.0, 1.0, uEnginePower);
   vec4 Lampglow = Lamp_pass * LampColor * Pulse(2.0, 1.0) * (1.0  - DamageAmount);  
   vec4 PlumeGlow = PlumeColGLow * effectsMap.b * Pulse(min(uEnginePower, 1.0), 1.0); 

// Add a very low speed core glow colour, fade it out as speed increases
   if (uEnginePower > 0.001) 
      { 
        totalColor += uExhaustCoreCol * effectsMap.b * max(0.0, 1.0 - LowLevelCoreGlow) * 0.2;
      }
   vec4 CoreGlow = uExhaustCoreCol * effectsMap.r * Pulse(min(uEnginePower, 1.0), 1.0) ;      
        CoreGlow  += uExhaustCoreCol * engineburp * effectsMap.r * step(0.001, uEnginePower); // add in core glow level 'jitter'
        CoreGlow  *= engnoise;
   vec4 FinalCoreGlow = mix(CoreGlow, CoreGlow * scrollingheatMap, min(uEnginePower, 0.8));

// Calculate a red glow for the engine core to simulate heated metal. This glow stays visible whilst the rest of the engine effect flickers from shipdamage
   vec4 ConstCoreGlow = kRedExhaustGlow * effectsMap.r * Pulse(min(uEnginePower, 1.0), 1.0) * Blink_on_off(0.5, Pulse(1.0, 0.6));
        ConstCoreGlow += kRedExhaustGlow * effectsMap.r * Pulse(min(uEnginePower, 1.0), 1.0) * Blink_on_off(0.5, Pulse(1.0, 0.7));

// Apply the engine and lamp glows  
   totalColor += mix(Lampglow + PlumeGlow + FinalCoreGlow,  
               ConstCoreGlow + 
               Lampglow * Blink_on_off(0.5, Pulse(1.0, 0.4)) * 4.0 + 
              PlumeGlow * Blink_on_off(0.5, Pulse(1.0, 1.0)), max(0.0, DamageAmount - 0.4));

// Apply the lasergun heat glow   
   totalColor += WeaponGlow(effectsMap.g * Pulse(min(uLaserHeatLevel, 1.0), 1.0));
        
// Calculate an engine misfire flicker, this only kick in when Tradefactor pases 80%                                            
   float EngineMisFire = effectsMap.b * uEnginePower * max(0.0, EngMisFireLV - 0.8);
   totalColor += kRedExhaustGlow * Blink_on_off(0.9, Pulse(0.5, 0.9)) * EngineMisFire; // use vec4(5.0) to get a really strong white flash
 
// Apply the hull temperature glow
   float hullHeat = max(uHullHeatLevel - 0.5, 0.0) * 2.0; 
   hullHeat = Pulse(hullHeat * hullHeat, 0.1); 
   totalColor += TemperatureGlow(hullHeat);  
   
// Apply gamma correction to return to sRGB colorpsace and apply tone mapping. This should be the very last thing
// we do before sending the output to display.
// Using the J. Hejl & R. Burgess-Dawson forumla
	vec3 x = max(vec3(0.0), totalColor.rgb - 0.004);
	totalColor.rgb = (x * (6.2 * x + 0.5)) / (x * (6.2 * x + 1.7) + 0.06);

gl_FragColor = mix(totalColor, vec4(uFogColor.xyz, 1.0), 0.0); // change 0.0 to uFogColor.w for oolite

}
Edit: Griff, regarding your blue tinting issue, it was because of this line:

Code: Select all

vec4 specularColor = vec4(0.9,0.4,0.1,1.0); // forcing the spec color to a warm yellow
This enables colored specular on a material that emits diffuse color. This is in violation of natural laws and creates an impossible material. Because of light energy conservation, the shader is trying to paint the non-reflective areas with the color that is complementary to yellow, i.e. blue, thus tinting whatever diffuse color is emitted at those areas. The only materials that can have colorized specular are metals and those do not emit diffuse (or, in other words, diffuse color for metals is black in the specular-gloss PBR workflow that we use).

As a final note, we don't seem to have a specular map. This leaves room for further improvement on this otherwise excellent model, by allowing multiple reflectivities across the surface of the ship. Combined with the existing gloss map, there is a lot of potential to be exploited here if you want to.
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

Re: Griff's normalmapped ship remakes

Post by Griff »

Thanks for picking through all this and fixing stuff A_C, i was just having a read of the lighting guide, https://bb.oolite.space/viewtopic.ph ... c4427c452e - the lightbulb floating above my head is very dim but slowly starting to brighten :)

it's not the guide's fault, it's excellent but i'm struggling a bit, i think i might have confused gloss and spec intensity in my textures

I'm totally up for adding a specular map, is that just a greyscale 'intensity' texture, or do i need the rgb channels for specular_color and the alpha channel for the intensity? and if i do use rgb for specular colour, then that's just to have color on the pure metal parts and not on the 'painted metal' parts like the top of the hull (they'd be black in the spec colour map?)
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 6557
Joined: Wed Feb 28, 2007 7:54 am

Re: Griff's normalmapped ship remakes

Post by another_commander »

Griff wrote: Thu Nov 26, 2020 10:10 am
if i do use rgb for specular colour, then that's just to have color on the pure metal parts and not on the 'painted metal' parts like the top of the hull (they'd be black in the spec colour map?)
Exactly this. The spec map is RGB and for most non-metallic materials it should consist of various shades of gray depending on the reflectivity you want to achieve (although most non metals should have a specular of (0.04, 0.04, 0.04) but on the net you can find specific values for specific materials like here). When it is colored, it would normally refer to metallic surfaces and the diffuse of these surfaces would be black.

In the core shaders the alpha of the specmap is used for gloss, but I see that you are handling it differently on your shader. That's fine and you can use the alpha of your specular for something else, although the spec intensity is basically already determined by how white or black the spec rgb texture is. You may want to experiment with different combinations of gloss and specular to fully understand what each of them does, I know it's a bit tricky getting one's head around all this.
Commander_X
---- E L I T E ----
---- E L I T E ----
Posts: 666
Joined: Sat Aug 09, 2014 4:16 pm

Re: Griff's normalmapped ship remakes

Post by Commander_X »

another_commander wrote: Wed Nov 25, 2020 2:57 pm
[...]
I really dig the blue light emitted from the engines.
Ooooh, momma! Not to mention there are 4 of them :-D
User avatar
Cody
Sharp Shooter Spam Assassin
Sharp Shooter Spam Assassin
Posts: 16063
Joined: Sat Jul 04, 2009 9:31 pm
Location: The Lizard's Claw
Contact:

Re: Griff's normalmapped ship remakes

Post by Cody »

Griff - I'm having problems downloading from this link: https://drive.google.com/drive/folders/ ... sp=sharing (updated today, yes?)
I would advise stilts for the quagmires, and camels for the snowy hills
And any survivors, their debts I will certainly pay. There's always a way!
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

Re: Griff's normalmapped ship remakes

Post by Griff »

hmm, it does look like it's picky about the browser, just tried in Internet Explorer and i got a page saying the website wasn't compatible
Just in case i've done something wrong trying to share the folder earlier i think this is a direct link to the multidecal player version of the oxp

https://drive.google.com/file/d/1NEpm7a ... sp=sharing

it's a bit weird, i follow that link and then i get a page that seems to let me explore inside the .zip file and see all the sub folders instead of downloading the file, but there's a small download arrow up in the top right of the page that does seem to allow downloading the whole zip
If this still doesn't work i think my box.com login account still works, i could put it up on there
User avatar
Cody
Sharp Shooter Spam Assassin
Sharp Shooter Spam Assassin
Posts: 16063
Joined: Sat Jul 04, 2009 9:31 pm
Location: The Lizard's Claw
Contact:

Re: Griff's normalmapped ship remakes

Post by Cody »

That got it - thanks! Have you still got access to your folder in my Box, btw?
I would advise stilts for the quagmires, and camels for the snowy hills
And any survivors, their debts I will certainly pay. There's always a way!
Post Reply