Shader patch

For collaboration on developing the mod capabilities of VS; request new features, report bugs, or suggest improvements

Moderator: Mod Contributor

chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Shader patch

Post by chuck_starchaser »

In default.fp, line 45, the function is commented out, but anyhow, it's buggy when you try to use shininess from spec's alpha. Needs a clamp.
From,

Code: Select all

//float shininessMap(float shininess, vec4 specmap) { return specmap.a*shininess; } // alpha-based shininess modulation
change to

Code: Select all

//float shininessMap(float shininess, vec4 specmap) { return clamp(specmap.a*shininess,1.0,255.0); } // alpha-based shininess modulation
The following is not a bug fix, but is a major improvement. The shininessMap function currently in use, which computes shininess from specularity, needs to be a lot less linear. The way it is now, most materials get way too much shininess; almost as bad as before shaders. Just squaring the luma was a great improvement; but then I found something even better: dotting the spec.rgb by itself, before averaging. This allows colored materials, such as bronze and paints to get more shininess than grey metals, all specularities being equal.
From,

Code: Select all

float shininessMap(float shininess, vec4 specmap){  return clamp(dot(specmap.rgb,vec3(1.0/3.0))*shininess,1.0,256.0); } // luma-based shininess modulation
change to,

Code: Select all

float shininessMap(float shininess, vec4 specmap) // luma-based shininess modulation
{
  float temp = dot( specmap.rgb, specmap.rgb );
  temp *= 0.333;
  return clamp( temp*shininess, 1.0, 255.0 );
}
Next is two bugs in one line of code: envLod is never used. Also, the last multiplying term in that line, envColor.rgb does not belong. Wherever it comes from, it doesn't matter, really. The color of a reflection should be the color of the background it reflects, times the specular color. No other terms are warranted; and removing it improved the visuals. But I also added a 2.0 multiplier to compensate for the dimming in code of the environment spheremaps when they are generated from the background textures. MUCH better, now. From,

Code: Select all

vec3 envMapping(in vec3 reflection, in float shininess, in vec4 specmap)
{
   float envLod = shininess2Lod(shininessMap(shininess,specmap));
   return texture2D(envMap, EnvMapGen(reflection)).rgb * specmap.rgb * envColor.rgb;
}
change to,

Code: Select all

vec3 envMapping(in vec3 reflection, in float shininess, in vec4 specmap)
{
   float envLod = shininess2Lod(shininessMap(shininess,specmap));
   return texture2DLod(envMap, EnvMapGen(reflection), envLod).rgb * specmap.rgb * vec3(2.0);
}
Starting to work...

Image

Also, I don't know why, but I set my shader to "nicest", yet the engine is using default.vp and default.fp.

EDIT:
Just found another bug: The shininessMap() function is being called from two places, which is a waste of instructions, since all functions are inlined, in shaders. Looking into it...

EDIT2:
Make that multiple times...
There's a "lighting" macro that, for each light, instantiates a "call" to a big function, lightingLight(); which in turn "calls" shininessMap(); then shininessMap is "called" again from envMapping(), which is "called" from main() :roll:

EDIT3:
Another bug, 99% probably: That lightingLight function is multiplying environmental reflections by selfshadow. I don't know how this selfshadow stuff works, but I do know for a fact that specular reflections aren't affected by shadows. Mirrors don't receive shadows. This is probably why, as I've noticed, env mapped reflections look darker when you look at a ship from the shadowed side. That's totally incorrect.
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

Indeed, that solved the problem of env reflections being too dark on the shadowed side. Just change the second-last line of lightingLight() from,

Code: Select all

   specular += selfshadow * pow(clamp(RdotL,0.0,1.0), gloss) * lightSpecular.rgb * lightAtt;
to

Code: Select all

   specular += pow(clamp(RdotL,0.0,1.0), gloss) * lightSpecular.rgb * lightAtt;
Suffice it to say that reflections now look as bright on the shady side of the ship as they do on the sunny side; which is as it should be.

Image

If you don't know what I'm talking about, look at the engine on the far-side of the pic in the first post --the first pic I posted--; you'll see that the far engine, which is in darkness, doesn't show much in the way of reflections, even though it should.
It's hard to show on pictures, but with the ship moving, it looks a lot more "real" now.
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

Also, the last line in lightingLight() should be removed:

Code: Select all

ambient  += ambientProduct.rgb;
change to There's no reason why light sources should specify ambient light, and if they do they do so erroneously. Go to a hardware store, pick up a light bulb, and ask the store owner how much ambient, diffuse and specular light it produces, exactly. Or tell her that you bought a light bulb the previous week that produces too much specular light, but not enough ambient...
These are idiotic idiosyncracies of opengl that are best ignored. A light source produces light. That's it. Period.

On the same vein, remove the seventh input parameter in lightingLight(), from,

Code: Select all

void lightingLight(
   in vec3 light, in vec3 normal, in vec3 vnormal, in vec3 eye, in vec3 reflection, 
   in vec4 lightDiffuse, in vec4 lightSpecular, in float lightAtt, 
   in vec4 diffusemap, in vec4 specmap, in float shininess,
   in vec4 ambientProduct,
   inout vec3 diffuse, inout vec3 specular, inout vec3 ambient)
{
to

Code: Select all

void lightingLight(
   in vec3 light, in vec3 normal, in vec3 vnormal, in vec3 eye, in vec3 reflection, 
   in vec4 lightDiffuse, in float lightAtt, 
   in vec4 diffusemap, in vec4 specmap, in float shininess,
   in vec4 ambientProduct,
   inout vec3 diffuse, inout vec3 specular, inout vec3 ambient)
{
and change the second last line (now the last), from,

Code: Select all

   specular += pow(clamp(RdotL,0.0,1.0), shininessMap(shininess,specmap)) * lightSpecular.rgb * lightAtt;
to

Code: Select all

   specular += pow(clamp(RdotL,0.0,1.0), shininessMap(shininess,specmap)) * lightDiffuse.rgb * lightAtt;
Then change the macro,

Code: Select all

#define lighting(name, lightno_gl, lightno_tex) \
void name( \
   in vec3 normal, in vec3 vnormal, in vec3 eye, in  vec3 reflection, \
   in vec4 diffusemap, in vec4 specmap, \
   inout vec3 diffuse, inout vec3 specular, inout vec3 ambient) \
{ \
   lightingLight( \
      normalize(gl_TexCoord[lightno_tex].xyz), normal, vnormal, eye, reflection, \
      gl_FrontLightProduct[lightno_gl].diffuse, \
      gl_FrontLightProduct[lightno_gl].specular, \
      gl_TexCoord[lightno_tex].w, \
      diffusemap, specmap, gl_FrontMaterial.shininess, \
      gl_FrontLightProduct[lightno_gl].ambient, \
      diffuse, specular, ambient); \
}
to

Code: Select all

#define lighting(name, lightno_gl, lightno_tex) \
void name( \
   in vec3 normal, in vec3 vnormal, in vec3 eye, in  vec3 reflection, \
   in vec4 diffusemap, in vec4 specmap, \
   inout vec3 diffuse, inout vec3 specular, inout vec3 ambient) \
{ \
   lightingLight( \
      normalize(gl_TexCoord[lightno_tex].xyz), normal, vnormal, eye, reflection, \
      gl_FrontLightProduct[lightno_gl].diffuse, \
      gl_TexCoord[lightno_tex].w, \
      diffusemap, specmap, gl_FrontMaterial.shininess, \
      gl_FrontLightProduct[lightno_gl].ambient, \
      diffuse, specular, ambient); \
}
EDIT:
And it keeps looking better and better.

EDIT2:
The last parameter passed to lightingLight() is now not needed. Changing from

Code: Select all

void lightingLight(
   in vec3 light, in vec3 normal, in vec3 vnormal, in vec3 eye, in vec3 reflection, 
   in vec4 lightDiffuse, in float lightAtt, 
   in vec4 diffusemap, in vec4 specmap, in float shininess,
   in vec4 ambientProduct,
   inout vec3 diffuse, inout vec3 specular, inout vec3 ambient)
{
to

Code: Select all

void lightingLight(
   in vec3 light, in vec3 normal, in vec3 vnormal, in vec3 eye, in vec3 reflection, 
   in vec4 lightDiffuse, in float lightAtt, 
   in vec4 diffusemap, in vec4 specmap, in float shininess,
   in vec4 ambientProduct,
   inout vec3 diffuse, inout vec3 specular)
{
which means that the last parameter the macro passes is a goner, from,

Code: Select all

      diffuse, specular, ambient); \
}
to

Code: Select all

      diffuse, specular); \
}
which implies that the last parameter in the function the macro instantiates is dead. Change from,

Code: Select all

#define lighting(name, lightno_gl, lightno_tex) \
void name( \
   in vec3 normal, in vec3 vnormal, in vec3 eye, in  vec3 reflection, \
   in vec4 diffusemap, in vec4 specmap, \
   inout vec3 diffuse, inout vec3 specular, inout vec3 ambient) \
{ \
to

Code: Select all

#define lighting(name, lightno_gl, lightno_tex) \
void name( \
   in vec3 normal, in vec3 vnormal, in vec3 eye, in  vec3 reflection, \
   in vec4 diffusemap, in vec4 specmap, \
   inout vec3 diffuse, inout vec3 specular) \
{ \
And the above results in that we don't need that last parameter in the calls in main(). Change from,

Code: Select all

  // Do lighting for every active light
  if (light_enabled[0] != 0)
     lighting0(normal, vnormal, eye, reflection, diffusemap, specmap, diffuse, specular, ambient);
  if (light_enabled[1] != 0)
     lighting1(normal, vnormal, eye, reflection, diffusemap, specmap, diffuse, specular, ambient);
to

Code: Select all

  // Do lighting for every active light
  if (light_enabled[0] != 0)
     lighting0(normal, vnormal, eye, reflection, diffusemap, specmap, diffuse, specular);
  if (light_enabled[1] != 0)
     lighting1(normal, vnormal, eye, reflection, diffusemap, specmap, diffuse, specular);
EDIT3:
Hell; even the ugliest ship we got is starting to look, well, not "decent", but at least it looks like something and not nothing...

Image

Too bad I didn't take a "before" screenshot. But, you see?, the specular texture of this course is probably white; but in any case, whereas before it only speculated on the bright side, it didn't much on the dark side, so you couldn't even recognize its being made of any material we're familiar with. Now the environmental reflections are independent of direct light, and it speculates from all directions, so it looks like entirely chrome-plated.
Well, not entirely, because something that's white in specular can't be anything but black in diffuse; but this abomination has specular+diffuse>1 sins all over the place. Whoever textured it should be hanged from the toes for a week, then shot. But I digress; the shader keeps looking better.
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

Okay, PU's highend and default fragment shaders are now committed to our svn, --totally revamped, and identical to each other. Hellcat said to me that a lot of hardware out there doesn't support texture2DLod(), and that that is the reason the default shader uses texture2D(). I say to hell with that; let's see how true that is. If we start getting a lot of complaints, I'll bow to the vs wisdom, but I'm highly skeptical.
Another reason for my putting texture2DLod() in the default shader is that in PU, for some reason, the highshader is not being used, even if you choose "nicest" in setup, --and yes, in the config file it says #set Shaders highshader

All of the bugs and shortcomings noted in the previous posts have been addressed, and I've probably reduced instructions by at least 5%. And it looks MUCH better than before.

If you guys are interested, here's our new code:

Code: Select all

uniform int light_enabled[gl_MaxLights];
uniform int max_light_enabled;
uniform sampler2D diffuseMap;
uniform sampler2D envMap;
uniform sampler2D specMap;
uniform sampler2D glowMap;
uniform sampler2D normalMap;
uniform sampler2D damageMap;
uniform sampler2D detail0Map;
uniform sampler2D detail1Map;
uniform vec4 cloaking;
uniform vec4 damage;
uniform vec4 envColor;

vec3 matmul(vec3 tangent, vec3 binormal, vec3 normal,vec3 lightVec) {
  return vec3(dot(lightVec,tangent),dot(lightVec,binormal),dot(lightVec,normal));
}
vec3 imatmul(vec3 tangent, vec3 binormal, vec3 normal,vec3 lightVec) {
  return lightVec.xxx*tangent+lightVec.yyy*binormal+lightVec.zzz*normal;
}

vec2 EnvMapGen(vec3 f) {
   float fzp1=f.z+1.0;
   float m=2.0*sqrt(f.x*f.x+f.y*f.y+(fzp1)*(fzp1));
   return vec2(f.x/m+.5,f.y/m+.5);
}

float bias(float f){ return f*0.5+0.5; }
vec2  bias(vec2 f) { return f*0.5+vec2(0.5); }
vec3  bias(vec3 f) { return f*0.5+vec3(0.5); }
vec4  bias(vec4 f) { return f*0.5+vec4(0.5); }

float expand(float f){ return f*2.0-1.0; }
vec2  expand(vec2 f) { return f*2.0-vec2(1.0); }
vec3  expand(vec3 f) { return f*2.0-vec3(1.0); }
vec4  expand(vec4 f) { return f*2.0-vec4(1.0); }

float lerp(float f, float a, float b){return (1.0-f)*a+f*b; }
vec2  lerp(float f, vec2 a, vec2 b) { return (1.0-f)*a+f*b; }
vec3  lerp(float f, vec3 a, vec3 b) { return (1.0-f)*a+f*b; }
vec4  lerp(float f, vec4 a, vec4 b) { return (1.0-f)*a+f*b; }

//float selfshadowStep(float VNdotL) { return step(0.0,VNdotL); } // fast but hard selfshadow function
float selfshadowStep(float VNdotL) { return smoothstep(0.0,0.25,VNdotL); } // costly but soft and nice selfshadow function
//float shininessMap(float shininess, vec4 specmap) { return clamp(specmap.a*shininess,1.0,255.0); } // alpha-based shininess modulation
float shininessMap(float shininess, vec4 specmap) // luma-based shininess modulation
{
  float temp = dot( specmap.rgb, specmap.rgb );
  temp *= 0.333;
  return clamp( temp*shininess, 1.0, 255.0 );
}
float shininess2Lod(float shininess) { return max(0.0,7.0-log2(shininess+1.0))+3.0*(1.0+envColor.a); }

void lightingLight(
   in vec3 light, in vec3 normal, in vec3 vnormal, in vec3 eye, in vec3 reflection, 
   in vec4 lightDiffuse, in float lightAtt, 
   in vec4 diffusemap, in vec4 specmap, in float shininess,
   in vec4 ambientProduct,
   inout vec3 diffuse, inout vec3 specular)
{
   float NdotL = dot(normal,light);
   float VNdotL= dot(vnormal,light);
   float RdotL = dot(reflection,light);
   float selfshadow = selfshadowStep(VNdotL);
   
   diffuse  += selfshadow * clamp(NdotL,0.0,1.0) * lightAtt * lightDiffuse.rgb;
   specular += pow(clamp(RdotL,0.0,1.0), shininessMap(shininess,specmap)) * lightDiffuse.rgb * lightAtt;
}

#define lighting(name, lightno_gl, lightno_tex) \
void name( \
   in vec3 normal, in vec3 vnormal, in vec3 eye, in  vec3 reflection, \
   in vec4 diffusemap, in vec4 specmap, \
   inout vec3 diffuse, inout vec3 specular) \
{ \
   lightingLight( \
      normalize(gl_TexCoord[lightno_tex].xyz), normal, vnormal, eye, reflection, \
      gl_FrontLightProduct[lightno_gl].diffuse, \
      gl_TexCoord[lightno_tex].w, \
      diffusemap, specmap, gl_FrontMaterial.shininess, \
      gl_FrontLightProduct[lightno_gl].ambient, \
      diffuse, specular); \
}

lighting(lighting0, 0, 5)
lighting(lighting1, 1, 6)

vec3 lightingClose(in vec3 diffuse, in vec3 specular, in vec3 ambient, in vec4 diffusemap, in vec4 specmap)
{
   return (diffuse + ambient) * diffusemap.rgb + specular * specmap.rgb;
}

vec3 envMapping(in vec3 reflection, in float gloss, in vec4 specmap)
{
   float envLod = shininess2Lod(gloss);//shininessMap(shininess,specmap));
   return texture2DLod(envMap, EnvMapGen(reflection), envLod).rgb * specmap.rgb * vec3(2.0);
}

void main() 
{
  // Retrieve normals
  vec3 iNormal=gl_TexCoord[1].xyz;
  vec3 iTangent=gl_TexCoord[2].xyz;
  vec3 iBinormal=gl_TexCoord[3].xyz;
  vec3 vnormal=iNormal;
  //vec3 normal=normalize(imatmul(iTangent,iBinormal,iNormal,expand(texture2D(normalMap,gl_TexCoord[0].xy).yxz)*vec3(-1.0,1.0,1.0)));
  vec3 normal=normalize(imatmul(iTangent,iBinormal,iNormal,expand(texture2D(normalMap,gl_TexCoord[0].xy).wyz)));
  
  // Other vectors
  vec3 eye = gl_TexCoord[4].xyz;
  vec3 reflection = -reflect(eye,normal);
  
  // Init lighting accumulators
  vec3 diffuse = vec3(0.0);
  vec3 specular= vec3(0.0);
  vec3 ambient = vec3(0.0);
  
  // Sample textures
  vec4 damagecolor = texture2D(damageMap , gl_TexCoord[0].xy);
  vec4 diffusecolor= texture2D(diffuseMap, gl_TexCoord[0].xy);
  vec4 speccolor   = texture2D(specMap   , gl_TexCoord[0].xy);
  vec4 glowcolor   = texture2D(glowMap   , gl_TexCoord[0].xy);
  vec4 diffusemap  = lerp(damage.x, diffusecolor, damagecolor);
  vec4 specmap     = speccolor;
  float specdamage = clamp(1.0 - dot(damagecolor.xyz,vec3(1.0/3.0)) * damage.x * 2.0, 0.0, 1.0);
  specmap.rgb     *= specdamage;
  specmap.a       *= bias(specdamage);
  float gloss      = shininessMap(gl_FrontMaterial.shininess,specmap);
  
  // Do lighting for every active light
  if (light_enabled[0] != 0)
     lighting0(normal, vnormal, eye, reflection, diffusemap, specmap, diffuse, specular);
  if (light_enabled[1] != 0)
     lighting1(normal, vnormal, eye, reflection, diffusemap, specmap, diffuse, specular);

  vec4 result;
  result.rgb  = lightingClose(diffuse, specular, ambient, diffusemap, specmap)
              + glowcolor.rgb
              + envMapping(reflection,gloss,specmap);
  result.a = diffusemap.a;
  result *= cloaking.rrrg;
  
  gl_FragColor = result;
}
Still to do is a further code reduction by passing the (new variable in main) "gloss" to lightingLight(), and eliminating its call to shininessMap().
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

DISCLAIMER:

The shader can't fix models and textures.
Crap will continue to look like crap.

Image

I tried adding a sanity enfocement piece of code:

Code: Select all

  //sanity enforcement:
  float temp = 1.0 - max( diffusecolor.r, max( diffusecolor.g, diffusecolor.b ) );
  speccolor.r = min( speccolor.r, temp );
  speccolor.g = min( speccolor.g, temp );
  speccolor.b = min( speccolor.b, temp );
But even that can't cope with the vs engine's nasty habit of assuming that a missing specular texture means that white was intended...
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

I was never quite sure I was seeing a bug, until now. It most definitely is.
Turning your ship in F7 external view (not sure which key that's bound to in Vegastrike, but F7 in PU is like the old F7 in VS),
does weird things to the light's direction. It seems to follow your ship around.
Not quite exactly fixed relative to your ship... but almost...
I was never quite sure because, in that view, rolling the ship causes the
camera to roll on its axis in some weird way, and it's hard to orient oneself.

But now, with a reference structure in the background,
I managed to capture this strange phenomenon on camera:

Image

Image

Image

Image

Image

Image

This was with the ship stationary and almost not turning, except for my pressing the roll key ("/" in PU) continuously, and
taking snapshots every 1/2 turn.

So, where's the light? Above or below?
klauss
Elite
Elite
Posts: 7243
Joined: Mon Apr 18, 2005 2:40 pm
Location: LS87, Buenos Aires, República Argentina

Post by klauss »

Chuck, it almost sounds like you're trying to fix with shader code changes problems of the model. I'd say that's a bad idea.

At least all the changes to the mapping from alpha to shininess seems like that - just change the alpha on the texture! (I'd accept some nonlinearity to avoid precision issues, but rather than squaring, you'd have to square-root instead). You seem to be making it all upside down just because your textures or materials are wrong. Fix them instead of the shader.

Same thing about removing ambient from the equation. Not really though. Space scenes shouldn't have any ambient coloring, but it's not the shader's problem but rather the dataset - make lights have black ambient. One could say, though... if you won't have ambient, why waste instructions on it?
So I guess I'm not that opposed to removing ambient ;)

Calling things twice is not wasting anything on GLSL - the compiler knows which function is referentially transparent and which is not, and will optimize as usual. Ie: it will call it only once. If you want to make it explicit... ok, it only hurts readability. But try checking the generated code (I use nvshaderperf for that and it's quite useful).

And you're wrong with removing the selfshadow term. First, it doesn't affect reflections themselves, it must be an illusion. Check carefully, since reflections are added in the end, outside of lightingLight(), through envMapping(). Second, the only thing that gets modulated by that selfshadow is specular reflections (direct reflections from a light source). Yo do want shadows there, or you'll get totally unrealistic highlights. Cool highlights maybe, at times, but totally ridiculous at other times. Ie: try a heavily normalmapped sphere.

BTW: very very recently I stumbled upon null pointer dereferences resulting from not setting some textures on the bfxm. Since it seemed totally ridiculous to force some objects into a white texture, I fixed that (to my knowledge), and now objects can have no texture (as opposed to an implicit white texture). But that only works when not using shaders I believe. Since shaders need a texture, you'll get the usual implicit texture (sometimes white, sometimes black, sometimes blue).

EDIT: Sorry, forgot to say. Envcolor is used to switch between "modes" of the shader. In one mode, environment mapping is used as just that - reflections. In the other, the material is supposedly opaque so there should be no (obvious) reflections. Then, enviornment mapping is used as some sort of GI replacement (ambient lighting). In that mode, rgb of envcolor is 0.5 (half of a visible hemisphere of background is illuminating the object - but granted this is hugely arbitrary), and alpha is set to 1.0 (to greatly blur reflections and thus kind of make it into a second diffuse). I don't know, maybe you just don't like the effect. I thought it makes for much better lighting in general.
Oíd mortales, el grito sagrado...
Call me "Menes, lord of Cats"
Wing Commander Universe
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

klauss wrote:Chuck, it almost sounds like you're trying to fix with shader code changes problems of the model. I'd say that's a bad idea.
Which problems?
At least all the changes to the mapping from alpha to shininess seems like that - just change the alpha on the texture!
What are you talking about, Klauss? I did no such thing as changing alpha to shininess conversions. All I added was a clamp. When the alpha was zero, shininess went to zero and there were pixelated black shadows creeping all over. That's a bug in the code, not a problem with the data. Zero alpha should map to a shininess of 1.
What I did change the linearity of was the specularity to shininess conversion. That's an AD-HOC function, by your own admission, so it's perfectly fair to change it if it doesn't work; at it certainly didn't the way it was.
(I'd accept some nonlinearity to avoid precision issues, but rather than squaring, you'd have to square-root instead). You seem to be making it all upside down just because your textures or materials are wrong. Fix them instead of the shader.
Klauss, you've misinterpreted something I said. Otherwise, I can't think of what your statement means. What precision issues? I squared the specularity because it was giving too much shininess. Hell, think about it for a moment, Klauss: If my specular is white, you give me a 255 shininess mirror. Fine. If my material is 50% grey in specular you give me 128 shininess? Are you mad? That's almost a mirror, still. How dark do I have to make my material in specular to get a shininess of 20? How do you want me to represent stainless steel, or titanium, which are like 70% and 50% specular but with low shininess? And these are the materials I need MOST!
Same thing about removing ambient from the equation. Not really though. Space scenes shouldn't have any ambient coloring, but it's not the shader's problem but rather the dataset - make lights have black ambient. One could say, though... if you won't have ambient, why waste instructions on it?
So I guess I'm not that opposed to removing ambient ;)
Glad to hear that! :D I'm not opposed to ambient light. But ambient light is specified in the .system files; the lights have no say and no business whatsoever specifying ambient light. Where ambient light needs to come from, really, is from averaging the color of the backgrounds.
Calling things twice is not wasting anything on GLSL - the compiler knows which function is referentially transparent and which is not, and will optimize as usual. Ie: it will call it only once. If you want to make it explicit... ok, it only hurts readability. But try checking the generated code (I use nvshaderperf for that and it's quite useful).
Functions in shaders are always inlined. There's no "call". It's a deep pipeline, not a Von Newmann machine.
And you're wrong with removing the selfshadow term. First, it doesn't affect reflections themselves, it must be an illusion. Check carefully, since reflections are added in the end, outside of lightingLight(), through envMapping(). Second, the only thing that gets modulated by that selfshadow is specular reflections (direct reflections from a light source). Yo do want shadows there, or you'll get totally unrealistic highlights. Cool highlights maybe, at times, but totally ridiculous at other times. Ie: try a heavily normalmapped sphere.
You are most definitely wrong, Klauss. Reflections, whether specular spots or env mappings, are NOT affected by shadows. How would a photon reflecting of a surface know whether another photon is passing by at cross directions or not? And I saw a dramatic improvement to the realism of the scene after I removed that selfshadow multiplication; but perhaps it was due to specular spots and not to env mappings. But the improvement was there, for sure.
BTW: very very recently I stumbled upon null pointer dereferences resulting from not setting some textures on the bfxm. Since it seemed totally ridiculous to force some objects into a white texture, I fixed that (to my knowledge), and now objects can have no texture (as opposed to an implicit white texture). But that only works when not using shaders I believe. Since shaders need a texture, you'll get the usual implicit texture (sometimes white, sometimes black, sometimes blue).
The best thing the engine could do, when a texture is not found, is write to stderr, flush, and crash. That way those things would get fixed. Hell, at PU we WANT to fix things, but we have no way to know what's wrong because the damned engine is designed with as much fault tolerance as a life support system or Mars lander OS...
Last edited by chuck_starchaser on Fri Apr 04, 2008 8:21 pm, edited 1 time in total.
klauss
Elite
Elite
Posts: 7243
Joined: Mon Apr 18, 2005 2:40 pm
Location: LS87, Buenos Aires, República Argentina

Post by klauss »

chuck_starchaser wrote:
At least all the changes to the mapping from alpha to shininess seems like that - just change the alpha on the texture!
What are you talking about, Klauss? I did no such thing as changing alpha to shininess conversions. All I added was a clamp. When the alpha was zero, shininess went to zero and there were pixelated black shadows creeping all over. That's a bug in the code, not a problem with the data. Zero alpha should map to a shininess of 1.
What I did change the linearity of was the specularity to shininess conversion. That's an AD-HOC function, by your own admission, so it's perfectly fair to change it if it doesn't work; at it certainly didn't the way it was.
:oops: Oh. I misread then. I thought you had done all that to the alpha based function. Sorry then.
Oíd mortales, el grito sagrado...
Call me "Menes, lord of Cats"
Wing Commander Universe
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

Hahaha, I thought so. Not a bad idea, though. In fact, I thought of it first! :D Stick shininess with gamma 0.5, then square it in the shader. But not now; don't worry :)
klauss
Elite
Elite
Posts: 7243
Joined: Mon Apr 18, 2005 2:40 pm
Location: LS87, Buenos Aires, República Argentina

Post by klauss »

chuck_starchaser wrote:
And you're wrong with removing the selfshadow term. First, it doesn't affect reflections themselves, it must be an illusion. Check carefully, since reflections are added in the end, outside of lightingLight(), through envMapping(). Second, the only thing that gets modulated by that selfshadow is specular reflections (direct reflections from a light source). Yo do want shadows there, or you'll get totally unrealistic highlights. Cool highlights maybe, at times, but totally ridiculous at other times. Ie: try a heavily normalmapped sphere.
You are most definitely wrong, Klauss. Reflections, whether specular spots or env mappings, are NOT affected by shadows. How would a photon reflecting of a surface know whether another photon is passing by at cross directions or not? And I saw a dramatic improvement to the realism of the scene after I removed that selfshadow multiplication; but perhaps it was due to specular spots and not to env mappings. But the improvement was there, for sure.
You'd normally be right, except on specular reflections. Specular reflections happen when the reflection vector (the direction in which light must come to reach your eye) hit the near vecinity of a light source. Normally, if a lightsource shadows the surface, reflections don't mind, as you say. But with specularity, when it happens, then it means there's an obstruction between the lightsource and the surface. That's where the reflection vector is going! So... the reflection path must be occluded as well, and there should be no highlight.
chuck_starchaser wrote:The best thing the engine could do, when a texture is not found, is write to stderr, flush, and crash.
Ya, but the cases I found were totally legal. Namely, I wanted a red emissive box. I thought: make a box, make it have black diffuse/spec, red emissive, and no textures at all. Bang! crash. In VS, things need textures in order not to crash the engine! I fixed just that. In other situations, a missing textured is interpreted as a desire for a "neutral" texture (black for glow, white for dif/spec, blue for normal). I think it makes sense. What doesn't, as you say, is that VS doesn't crash when it fails to load a referenced texture. It should... shouldn't it? At least it should whine about it. I think why it doesn't is that it regularly and normally find itself trying to load missing textures because of automatic factionalization - it routinely tries (and fails) to load "<faction>_tex.png" where it says "tex.png"
Oíd mortales, el grito sagrado...
Call me "Menes, lord of Cats"
Wing Commander Universe
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

klauss wrote:
chuck_starchaser wrote:
And you're wrong with removing the selfshadow term. First, it doesn't affect reflections themselves, it must be an illusion. Check carefully, since reflections are added in the end, outside of lightingLight(), through envMapping(). Second, the only thing that gets modulated by that selfshadow is specular reflections (direct reflections from a light source). Yo do want shadows there, or you'll get totally unrealistic highlights. Cool highlights maybe, at times, but totally ridiculous at other times. Ie: try a heavily normalmapped sphere.
You are most definitely wrong, Klauss. Reflections, whether specular spots or env mappings, are NOT affected by shadows. How would a photon reflecting of a surface know whether another photon is passing by at cross directions or not? And I saw a dramatic improvement to the realism of the scene after I removed that selfshadow multiplication; but perhaps it was due to specular spots and not to env mappings. But the improvement was there, for sure.
You'd normally be right, except on specular reflections. Specular reflections happen when the reflection vector (the direction in which light must come to reach your eye) hit the near vecinity of a light source. Normally, if a lightsource shadows the surface, reflections don't mind, as you say. But with specularity, when it happens, then it means there's an obstruction between the lightsource and the surface. That's where the reflection vector is going! So... the reflection path must be occluded as well, and there should be no highlight.
Ahhh, I understand, now. Okay, I guess I'll put that back, then. Damn! I don't know what I saw, then, but after that change, something about the scene seemed a lot better. I'll have to experiment, I gues...
chuck_starchaser wrote:The best thing the engine could do, when a texture is not found, is write to stderr, flush, and crash.
Ya, but the cases I found were totally legal. Namely, I wanted a red emissive box. I thought: make a box, make it have black diffuse/spec, red emissive, and no textures at all. Bang! crash. In VS, things need textures in order not to crash the engine! I fixed just that. In other situations, a missing textured is interpreted as a desire for a "neutral" texture (black for glow, white for dif/spec, blue for normal). I think it makes sense. What doesn't, as you say, is that VS doesn't crash when it fails to load a referenced texture. It should... shouldn't it? At least it should whine about it. I think why it doesn't is that it regularly and normally find itself trying to load missing textures because of automatic factionalization - it routinely tries (and fails) to load "<faction>_tex.png" where it says "tex.png"
Well, "white for dif/spec" doesn't make ANY sense to me at all. That's as if you bought a stove, and it decided that if you don't push any buttons or turn any dials on it, it should turn on the burners...
If the point is to assume a ***safe*** default value, the only safe value for specular is black. Let the ship be matte. But white for specular is THE worst possible assumption. The ship would have to be totally black in diffuse... Any amount of diffuse color looks like crap with white specular. Just look at the Drayman. A complete abomination.

Remember my Polka Dots post? THAT would be a good compromise. Put some ridiculous texture, hippy motifs, flowers... A mesh is missing? Substitute a generic tea-pot. That way at least one KNOWS what the problem is...
klauss
Elite
Elite
Posts: 7243
Joined: Mon Apr 18, 2005 2:40 pm
Location: LS87, Buenos Aires, República Argentina

Post by klauss »

chuck_starchaser wrote:Remember my Polka Dots post? THAT would be a good compromise. Put some ridiculous texture, hippy motifs, flowers... A mesh is missing? Substitute a generic tea-pot. That way at least one KNOWS what the problem is...
Not a bad idea, I have to say.
Oíd mortales, el grito sagrado...
Call me "Menes, lord of Cats"
Wing Commander Universe
pyramid
Expert Mercenary
Expert Mercenary
Posts: 988
Joined: Thu Jun 15, 2006 1:02 am
Location: Somewhere in the vastness of space
Contact:

Post by pyramid »

Looks absolutely amazing. Even the good old Llama.

Some planets seem to get too much shininess or specular in the lit parts. look e.g. at Broadway in Cephid_17. Also suns seem to look too bright.
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

pyramid wrote:Looks absolutely amazing. Even the good old Llama.
Hahaha, thanks! Glad somebody tried it, finally.
Some planets seem to get too much shininess or specular in the lit parts. look e.g. at Broadway in Cephid_17. Also suns seem to look too bright.
Yeah, my specular dot specular trick favors colored materials with shininess; --this is so that paints look glossier than metals, at equal specular lumas--; but planets should be pretty dark --make that black-- in specular, except for oceans and ice --and even these pretty dark. If they are getting too much shininess it's probably because they have more specular than they should.

About suns, I don't know; they shouldn't have changed, unless they've been set to reflect light as well as emit it, or some such diabolic thing... Suns should be black in diffuse and specular; only have a non-black glow texture. But if they have NO diffuse and specular textures, beware that the engine makes the ridiculous assumption that you want them to be white.
If this is the case, all you need is single-texel (1x1) black textures for them, for diffuse and specular.
pyramid
Expert Mercenary
Expert Mercenary
Posts: 988
Joined: Thu Jun 15, 2006 1:02 am
Location: Somewhere in the vastness of space
Contact:

Post by pyramid »

..planets... If they are getting too much shininess it's probably because they have more specular than they should.
...suns... If this is the case, all you need is single-texel (1x1) black textures for them, for diffuse and specular.
This means that with the new shader also the system definition files need to be adapted?
Currently there is only one texture (diffuse / ambient ) defined for planets / suns. So I'd need to define additional spec maps for planets and suns and additional diffuse for suns?
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

Uh, hold on; I know nothing about how these things work... Never did any planet work, except separatey from the vs engine ... BUT ... How on Earth can one depict a planet with a single texture?, like, without having separate diffuse, specular, glow and normal, anyways?
Even to have city lights on the night side you need a separate glow.
And without specularity control, planets ought to look ridiculous: Oceans without specularity ought to look like painted on stucco; or if the engine is assuming some specularity, contintinents would look like a continuation of the ocean material, as if you were looking at a shiny mapa-mundi, where everything is painted. You'll never be able to have realistic looking planets using a single texture unless you program artificial intelligence into the shader.
Furthermore, here's yet another example where shininess cannot be computed on the basis of specularity. Shininess for a planet needs to be at the very bottom for continents, regardless of specular color; and oceans need medium shininess. Heck, they also need Fresnel... BADLY.

Frankly, planets are a complete different animal from ships and stations; and they need to have a separate shader. Here's Earth with the shader klauss was developing a year ago or so:

Image

But there's vehement opposition to shader specialization from at least one corner the vs powers that be.
pyramid
Expert Mercenary
Expert Mercenary
Posts: 988
Joined: Thu Jun 15, 2006 1:02 am
Location: Somewhere in the vastness of space
Contact:

Post by pyramid »

chuck_starchaser wrote:How on Earth can one depict a planet with a single texture?, like, without having separate diffuse, specular, glow and normal, anyways?
Even to have city lights on the night side you need a separate glow.
And without specularity control, planets ought to look ridiculous.
Maybe I'm diverging too far from the shader question already. Planets can have all of those maps defined with the current state of the art engine. However, only few planets have the maps defined partially, most of them just have the diffuse map defined. This applies to VS the game as much as to PU.
chuck_starchaser wrote:Oceans without specularity ought to look like painted on stucco; or if the engine is assuming some specularity, continents would look like a continuation of the ocean material, as if you were looking at a shiny mapa-mundi, where everything is painted. You'll never be able to have realistic looking planets using a single texture unless you program artificial intelligence into the shader.
My plea at this point would rather go to the developers, in case your new shader model is integrated in VS, that the engine at least defaults specular to black if no specular map is given in the planet definition. There is nothing wrong with your shader from this perspective.
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

I pray to all pantheons that your plea be granted.

In the meantime, it should take about 2.5 minutes per planet type to add a spec-map; roughly:

1) Load diffuse texture into Gimp
2) Select Areas by Color tool, click on water.
3) Brighten a bit.
4) Add correlated noise, about 5 to 10
5) Blur with a radius of 5 or so
6) Invert Selection,
7) Darken quite a bit
8) Select -> None
9) Colors -> Desaturate

Optionally scale down 50% with interpolation = None

Save as, spec.png

If you want to get fancier than that, you could try to increase specular brightness in proportion to green channel brightness for land, as plant leafs are more specular than bare soil, but from orbital distances, the random orientations of shiny leafs boil down to ultra-low shininess; and for as long as we have to live with this curse of shininess computation based on specularity, making green areas more specular, as they should be, will also make them more glossy, as they shouldn't be.
Or you could try and lower the shininess at the mesh level; but the problem with that is that oceans need shininess, even though their specularity should be pretty low --er... well, low when face-on, but high at shallow angles... IOW, Fresnel...

If you want to stick a shininess into the alpha channel in lieu of it's being used hopefully soon, after step 2 above (oceans selected), add an alpha channel, select it, fill selected areas with like 25% dark grey, invert selection, fill with black. Well, don't take me literally; can't remember how one edits the alpha channel in Gimp; I prefer to use Blender noodles.

Hey, I can make a noodle for you to do this automatically.
Hold on; I'll be back with it in a couple of hours.
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

DONE!

You can just svn checkout planet speccer from:
https://svn.wcjunction.com/utils/lagrande/planetspeccer
Username is username and password is password.
Then, probably the first thing you want to do is double-click planetspeccer.blend.
If you don't have blender, get it from here:
http://download.blender.org/release/Blender2.46rc/
I already put a planet texture in the svn folder, for testing.
Once the file opens up, there's a button [Use Nodes]; click it.
Click it again. Now you see numbers revolving down --as the cursor.
In about 10 or 15 seconds, it's done.
From the diffuse input texture:

Image

it produces, first a height map, based on ad-hoc rules:

Image

then a normalmap:

Image

then a specularity:

Image

then a shininess:

Image

and finally a png with specularity in rgb and shininess in alpha. This one I won't show here; it's too transparent to see.

So, everything except the normal map and the combined spec.png are just for inspection.

Right now ocean detection is keyed to bluishness. If you need methane oceans and whatnot, I'll have to put some configurable color keying in it.

The easiest way to use it, probably, is to copy the blend file to the master planets folder, and change the name of the input file from "diffuse.png"
to the name of each planet texture you want to speculize and normalize. The output texture names are always the same; just rename the files.

EDIT:
There's one catch: The normalmap will show a seam. The only way to get rid of it is to increase the size of the input
texture by 4 pixels on each side, then copy a vertical strip 4 pixels wide from the right end of the texture and paste
it on the left; then take a strip from the left and paste it on the right. Then let blender produce outputs; then resize
back the results.
Blender's filters and translation nodes don't feature tile-able wraparound mode.

EDIT2:
DISCAIMER:
Haven't tried the results in-game. I'll wait for your feedback. Normalmap may need inverting x or y. I'm pretty sure it should work as-is, tho.
pyramid
Expert Mercenary
Expert Mercenary
Posts: 988
Joined: Thu Jun 15, 2006 1:02 am
Location: Somewhere in the vastness of space
Contact:

Post by pyramid »

pyramid wrote:Planets can have all of those maps defined with the current state of the art engine.
That's what I thought, at least judging by the original comment from klauss: http://vegastrike.sourceforge.net/wiki/ ... s_required
I could not find the correct statements for sector definition files to include specular and normal maps (see http://vegastrike.sourceforge.net/wiki/ ... stem_Files).
I need to look through the code to see if my statement is true and the howtos were not updated or if the situation is on the contrary and those maps cannot be defined for planets (since they are not meshes defined in the same way units are).

EDIT:
star_system_xml.cpp definitely only supports diffuse and shininess (glow aka citylights) maps. Unfortunately, though the noodle is working fine, it will be of no use with the current engine unless the sequence of textures that can be defined in a planet statement is being treated as those different maps. Today, it is possible to define

Code: Select all

<Planet name="Broadway" file="sol/ganymede.png|planets/rock.png" ...>
Anyway, the error with specular on Cephid_17 / Broadway planet seems to come from a double definition of diffuse textures (see above), so maybe the second one is being treated as specular. I'll check this out.

EDIT2:
Indeed, second map in the file statement is treated as specular. This means that with this new shader both specular and shininess can be included. Unfortunately the night side of the planet is not rendered correctly with maps having spec+shining or even spec only without shininess (see image 4).
Also, the specularity seems to be too much (image 3).
And the coastline seems darkened (image 5).

Here are some shots of university planet

1) VS shader with diffuse
Image

2) VS shader with citylights
Image

3) PU shader with diffuse + specular with shininess
Image

4) PU shader with diffuse + specular; left: nightside; right:dayside
Image

5) PU shader coastline
Image
Last edited by pyramid on Sun Apr 06, 2008 10:13 pm, edited 1 time in total.
klauss
Elite
Elite
Posts: 7243
Joined: Mon Apr 18, 2005 2:40 pm
Location: LS87, Buenos Aires, República Argentina

Post by klauss »

Thing is, planets really do need separate shaders. It's not a question of which textures are needed, but the computations, the lighting model itself is radically different. I've been having illuminating ideas on how to accomplish this with little work. Ie: right now the oposition to multiple shaders is that it would be a ton of work. Well, I believe I finally came up with a hack to avoid this :D
Stay tuned. This weekend is the weekend of code (WoC) for VS ;)
Oíd mortales, el grito sagrado...
Call me "Menes, lord of Cats"
Wing Commander Universe
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

I can't imagine how that's happening, pic number 4. I removed self-shadowing, which is the only thing I can think of. But standard lighting should not do that. Unless the selfshadow bit was masking some other bug.
klauss
Elite
Elite
Posts: 7243
Joined: Mon Apr 18, 2005 2:40 pm
Location: LS87, Buenos Aires, República Argentina

Post by klauss »

I smell bad shininess. Try removing the part about luma-based shininess variation and specular-shininess normalization.

I KNOW - remove the nightside and everything will work right.
Oíd mortales, el grito sagrado...
Call me "Menes, lord of Cats"
Wing Commander Universe
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

klauss wrote:I smell bad shininess. Try removing the part about luma-based shininess variation and specular-shininess normalization.
Sorry? What parts? Of what? The shader? If that was at fault, how come everything looks right in PU?
Post Reply