Proposal: Pre-computing shininess in code
Moderator: Mod Contributor
-
- Elite
- Posts: 7243
- Joined: Mon Apr 18, 2005 2:40 pm
- Location: LS87, Buenos Aires, República Argentina
Damn, Chuck! There's a ton ofimprovement even with "broken" shaders (and I say "broken" because your shaders are more suited to your dataset, the only fix I'd import into VS is environment x2 and bye bye ambient).
At first things look odd, highlights are too strong on high-shininess parts, but that kind of makes sense: if you get used to it, you'll notice the increased realism.
Thumbs up!
At first things look odd, highlights are too strong on high-shininess parts, but that kind of makes sense: if you get used to it, you'll notice the increased realism.
Thumbs up!
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
Peek taken, thanks! Take a peek at the edit in my last post, nowklauss wrote:Take a peek at the previous post, I've added the right formula
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
Glad to hear. (Damn!, my room-mate is going to kill me; I was supposed to do the dishes after breakfast, and that has now become impossible...).
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
Could you post your shader, klauss? I'm having trouble finding the right place to insert this, now. Like, it seems I would need to pass a new parameter to lightingLight()?
BTW, there's no such thing as a "PU dataset". Everything in PU is inherited garbage we're just beginning to fix.
Having separate diffuse and specular light is a BUG, even if it came curtesy of opengl.
BTW, there's no such thing as a "PU dataset". Everything in PU is inherited garbage we're just beginning to fix.
Having separate diffuse and specular light is a BUG, even if it came curtesy of opengl.
Last edited by chuck_starchaser on Sun Apr 06, 2008 4:54 pm, edited 1 time in total.
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- Elite
- Posts: 7243
- Joined: Mon Apr 18, 2005 2:40 pm
- Location: LS87, Buenos Aires, República Argentina
Maybe. But I wouldn't. There may be truly point light sources out there later on. Maybe a better thing is to use area lighting when you're very close to the sun. I have area lighting shaders over there in RenderMonkey, they're much more complex. I always wanted to use them eventually, the engine would choose which to use based on apparent star size (if the star looks big enough, it uses area lighting). But that's not possible right now because a single shader has to do all lights.chuck_starchaser wrote: EDIT:
HECK! Shininess itself needs to be limited for light spots!!! Stars are not point light sources!
Higher shininesses than some 20 or 30 should ONLY apply to env mapping.
So feel free to hack it the way you see fit to compensate for that limitation. If you do limit shininess, please, make it distance-to-light-dependant?
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
Got it. Not sure how, though; I'll have to pass star distance from the vp to the fp.klauss wrote:If you do limit shininess, please, make it distance-to-light-dependant?
Or better yet, star diameter/distance, but I'm not sure how.
So far I only got this done:
Code: Select all
float limited_shininessMap(float shininess, float specmap)
{
float limit = 50; //fixed for now
float shine = shininessMap(shininess,specmap);
return shine*limit/(shine+limit);
}
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
Your formula simplifies to,
Correct?
What does "1+..." do? Maybe that's the problem at low shininess values.
Code: Select all
specular = 0.6*(1+shininess/10)^1.7
What does "1+..." do? Maybe that's the problem at low shininess values.
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
Code: Select all
float limited_shininessMap(float shininess, float specmap)
{
float limit = 20; //20^1.7 is 162. 162*0.0117 = 1.9 --enough risk of saturation!
float shine = shininessMap(shininess,specmap);
return shine*limit/(shine+limit);
}
float shininess_to_brightness(float shininess)
{
//specular = 1.0 / (1.7/(1+shininess/10))^1.7;
//specular = 0.588*(1+shininess/10)^1.7
//but the 1+ term is dubious. If we get rid of it, we get
//specular = 0.588*(shininess/10)^1.7 which simplifies to
//specular = 0.011736837 * shininess^1.7
return 0.011736837 * pow( shininess, 1.7 );
}
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
DONE!
Yeah, looks a lot more realistic. Even with subtle differences in shininess, such as between the bronze in the exhaust and the stainless in the body of the engine, one can see the increased brightness of the light spot on the bronze:
I was mentioning elsewhere the bug with the light source appearing to turn around with the ship when you turn the ship in F7 view. Here I caught the bug again on the evil deed... In the picture below:
Notice how, judging for where the refletions are, the light source would be behind us and to the right?
Look what happens when I press the roll key for a second:
The light that was behind us and to the right seems to have moved to a totally different place.
I'm beginning to form a thought that THIS is why the shader seems to work better without that self-shadow term. Not because the term is unwarranted, but because there's a bug with the lighting.
Nice and shiny, those thinner, aluminium pipes...
Code: Select all
float limited_shininessMap(float shininess, float specmap)
{
float limit = 30; //30^1.7 is 324. 324*0.005 = 1.62 --enough risk of saturation!
float shine = shininessMap(shininess,specmap);
return shine*limit/(shine+limit);
}
float shininess_to_brightness(float shininess)
{
//specular = 1.0 / (1.7/(1+shininess/10))^1.7;
//specular = 0.588*(1+shininess/10)^1.7
//but the 1+ term is dubious. If we get rid of it, we get
//specular = 0.588*(shininess/10)^1.7 which simplifies to
//specular = 0.011736837 * shininess^1.7 but make that .005...
return 0.005 * pow( shininess, 1.7 );
}
float lightspot_brightness( float shininess, float specmap )
{
return limited_shininessMap( shininess, specmap ) * shininess_to_brightness( shininess );
}
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) * lightDiffuse.rgb * lightAtt ;
specular += pow(clamp(RdotL,0.0,1.0), lightspot_brightness(shininess,specmap)) * lightDiffuse.rgb * lightAtt;
}
I was mentioning elsewhere the bug with the light source appearing to turn around with the ship when you turn the ship in F7 view. Here I caught the bug again on the evil deed... In the picture below:
Notice how, judging for where the refletions are, the light source would be behind us and to the right?
Look what happens when I press the roll key for a second:
The light that was behind us and to the right seems to have moved to a totally different place.
I'm beginning to form a thought that THIS is why the shader seems to work better without that self-shadow term. Not because the term is unwarranted, but because there's a bug with the lighting.
Nice and shiny, those thinner, aluminium pipes...
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
Yep. I commented out the selfshadow term in the direct light contribution and that improves the visuals.
I'm not exactly sure what is improving, but it looks better.
I think, either this self-shadow thing is using wrong incoming light direction data, or else it's buggy.
Removed for now...
Looks more "natural" to me...
How's the self-shadow thing supposed to work, anyways?
I've no clue what VNdotL is supposed to mean. If I look where it comes from, it comes from
and vnormal comes from main, where,
and iNormal comes from,
so, this would seem to boil down to dot(light,normal), which is what diffuse lighting already does.
Are we multiplying the whole lighting by (1+0.25*cos(light's angle)) or something? :-/
I'm not exactly sure what is improving, but it looks better.
I think, either this self-shadow thing is using wrong incoming light direction data, or else it's buggy.
Removed for now...
Looks more "natural" to me...
How's the self-shadow thing supposed to work, anyways?
Code: Select all
//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
Code: Select all
float VNdotL= dot(vnormal,light);
Code: Select all
vec3 vnormal=iNormal;
Code: Select all
// Retrieve normals
vec3 iNormal=gl_TexCoord[1].xyz;
vec3 iTangent=gl_TexCoord[2].xyz;
vec3 iBinormal=gl_TexCoord[3].xyz;
Are we multiplying the whole lighting by (1+0.25*cos(light's angle)) or something? :-/
Last edited by chuck_starchaser on Sun Apr 06, 2008 7:01 pm, edited 3 times in total.
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- ISO Party Member
- Posts: 387
- Joined: Tue Mar 21, 2006 2:37 pm
- Location: Netherlands
- Contact:
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
Good question. I haven't the faintest clue what the hull is made of, I confess.
It's basically a grey material with pretty low specularity; that's all I can say.
And the reason it's that way is that that is what Nate and I concluded the material in the original Tarsus from Origin was
like, judging from the reference images. So, it's just trying to be "canonical material"
Giving it low specularity, with the current shader, implies low shininess, which implies it's metallic, or some matte paint.
If we wanted to make it be a baked or enamel paint, we'd probably want even lower specularity; but it would be a
dielectric... with much higher shininess ... plus fresnel...
Next shader will be able to do that.
It's basically a grey material with pretty low specularity; that's all I can say.
And the reason it's that way is that that is what Nate and I concluded the material in the original Tarsus from Origin was
like, judging from the reference images. So, it's just trying to be "canonical material"
Giving it low specularity, with the current shader, implies low shininess, which implies it's metallic, or some matte paint.
If we wanted to make it be a baked or enamel paint, we'd probably want even lower specularity; but it would be a
dielectric... with much higher shininess ... plus fresnel...
Next shader will be able to do that.
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- ISO Party Member
- Posts: 387
- Joined: Tue Mar 21, 2006 2:37 pm
- Location: Netherlands
- Contact:
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
True; and it's looking better now, after some new shader changes...
Getting a lot lower shininess, as it should if it's a matte paint.
Squaring the spec rgb terms was not enough. I now cubed them and I get MUCH better shininesses...
Also, instead of 1.7 as the power of shininess to modulate brightness of specular spots, I changed that to 2.0.
Watch the brighness of that bar under the cockpit as it passes through the right angle. It probably saturates...
And here we see, first of all, a better differenciation between the shininesses of bronze and stainless,
and a more noticeably brighter light-spot:
My current shader code:
One more pic: I just caught the light just right...
Getting a lot lower shininess, as it should if it's a matte paint.
Squaring the spec rgb terms was not enough. I now cubed them and I get MUCH better shininesses...
Also, instead of 1.7 as the power of shininess to modulate brightness of specular spots, I changed that to 2.0.
Watch the brighness of that bar under the cockpit as it passes through the right angle. It probably saturates...
And here we see, first of all, a better differenciation between the shininesses of bronze and stainless,
and a more noticeably brighter light-spot:
My current shader 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
{
float3 temp = specmap.rgb;
temp *= specmap.rgb;
temp *= specmap.rgb;
temp.b = (temp.r+temp.g)*0.75;
return clamp( temp.b*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); }
float limited_shininessMap(float shininess, float specmap)
{
float limit = 30; //30^1.7 is 324. 324*0.005 = 1.62 --enough risk of saturation!
float shine = shininessMap(shininess,specmap);
return (shine*limit)/(shine+limit);
}
float shininess_to_brightness(float shininess)
{
return 0.0025 * shininess * shininess;
}
float lightspot_brightness( float shininess, float specmap )
{
return limited_shininessMap( shininess, specmap ) * shininess_to_brightness( shininess );
}
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 += clamp(NdotL,0.0,1.0) * lightDiffuse.rgb * lightAtt ;
specular += pow(clamp(RdotL,0.0,1.0), lightspot_brightness(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);
//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 );
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;
}
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- Elite Mercenary
- Posts: 1329
- Joined: Thu Mar 27, 2003 11:51 pm
- Location: Manchester, UK
- Contact:
Very impressive work chuck.
Free Gamer - free software games compendium and commentary!
FreeGameDev forum - open source game development community
FreeGameDev forum - open source game development community
-
- Elite
- Posts: 7243
- Joined: Mon Apr 18, 2005 2:40 pm
- Location: LS87, Buenos Aires, República Argentina
Chuck, don't change the 1.7, it was a hand-picked fit for the mathematically correct function. Doing so would sacrifice the correctness of lower shininess values. Rather, I believe you want to raise the limit on shininess.
BTW: I don't get how that limiting function you use works. I would have expected something like clamp().
The selfshadow term is intended to black out specularity when the geometry is facing away from the light. Right now, there are two things that control the normals (and thus specular highlights): vertex normals, and the normalmap.
Normal mapping is supposed to model small features on the surface that change normal direction. They're not supposed to be big enough to shadow anything. Vertex normal captures big, gross geometry features. When vertex normals face away from the light, it's not supposed that normalmapped features will change the fact that they're in the shadowed side of the model. So, the term does that: when a pixel is in the shadowed side of a model (vertex normal pointing away from the light). no amount of normalmapping can create any lighting. So, selfshadow darkens everything. The function just does that smoothly, because doing it hardly (ie: (VNdotL > 0) ? 1 : 0 ) simply looks weird.
Perhaps it's too soft. Try making it harder, decreasing the 0.25.
BTW: Beware of misim(ex)ported vertex normals. Weird lighting tends to be the result of that.
BTW: I don't get how that limiting function you use works. I would have expected something like clamp().
The selfshadow term is intended to black out specularity when the geometry is facing away from the light. Right now, there are two things that control the normals (and thus specular highlights): vertex normals, and the normalmap.
Normal mapping is supposed to model small features on the surface that change normal direction. They're not supposed to be big enough to shadow anything. Vertex normal captures big, gross geometry features. When vertex normals face away from the light, it's not supposed that normalmapped features will change the fact that they're in the shadowed side of the model. So, the term does that: when a pixel is in the shadowed side of a model (vertex normal pointing away from the light). no amount of normalmapping can create any lighting. So, selfshadow darkens everything. The function just does that smoothly, because doing it hardly (ie: (VNdotL > 0) ? 1 : 0 ) simply looks weird.
Perhaps it's too soft. Try making it harder, decreasing the 0.25.
BTW: Beware of misim(ex)ported vertex normals. Weird lighting tends to be the result of that.
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
It looks perfect to me, at two; I can notice the difference in brightness more. On the other hand, my smooth limiting function is probably doing much of lowering that power.klauss wrote:Chuck, don't change the 1.7, it was a hand-picked fit for the mathematically correct function. Doing so would sacrifice the correctness of lower shininess values. Rather, I believe you want to raise the limit on shininess.
Clamping is non-linear, and would look absolutely horrible. My function is a very smooth function yielding "lower of two numbers", namely "product over sum". The formula comes from electronics. If you have two resistors in parallel, total resistance is the product over the sum of their resistances. If the two are equal, you get half --e.g. 7x7 / (7+7) = 3.5; so when the input shininess is 30 the output shininess is 15.BTW: I don't get how that limiting function you use works. I would have expected something like clamp().
Ah, interesting.The selfshadow term is intended to black out specularity when the geometry is facing away from the light. Right now, there are two things that control the normals (and thus specular highlights): vertex normals, and the normalmap.
Normal mapping is supposed to model small features on the surface that change normal direction. They're not supposed to be big enough to shadow anything. Vertex normal captures big, gross geometry features. When vertex normals face away from the light, it's not supposed that normalmapped features will change the fact that they're in the shadowed side of the model. So, the term does that: when a pixel is in the shadowed side of a model (vertex normal pointing away from the light). no amount of normalmapping can create any lighting. So, selfshadow darkens everything. The function just does that smoothly, because doing it hardly (ie: (VNdotL > 0) ? 1 : 0 ) simply looks weird.
Perhaps it's too soft. Try making it harder, decreasing the 0.25.
Now I understand.
In the Tarsus I don't see any problems because my normalmap is only a faint randomization of surface normal. (The only place you can actually see it is on the front window, which is flat and high shininess; but only when using shininess from alpha.)
In any case, we're already computing NdotL... Doh! I see.., We do need NVdotL...
I've no idea what that is.BTW: Beware of misim(ex)ported vertex normals. Weird lighting tends to be the result of that.
EDIT:
I'd rather make that smothstep go like
Code: Select all
float selfshadowStep(float VNdotL) { return smoothstep(-0.0625,0.0625,VNdotL); }
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- Confed Special Operative
- Posts: 298
- Joined: Sun Jul 30, 2006 1:38 pm
- Location: Sweden
- Contact:
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
I don't have enough jitter in the normalmapt to test this. I made the self shadow function go like,
and I see nothing wrong, but then again, I wouldn't.
What I do see wrong, and this is an old OGL problem, is transitions that are too fast between light and shadow. The problem of treating light sources as point sources. There must be a way of hacking the light equation to get something better than NdotL...
Code: Select all
float selfshadowStep(float VNdotL) { return smoothstep(-0.0625,0.0625,VNdotL); }
What I do see wrong, and this is an old OGL problem, is transitions that are too fast between light and shadow. The problem of treating light sources as point sources. There must be a way of hacking the light equation to get something better than NdotL...
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
Updated code:Reinstated selfshadow stuff.
Changed selfshadowing step to go from -0.0625 to +0.125 VNdotL
Changed shininess limit from 30 to 50, and multiplier for shininess_to_brightness to 0.001.
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.0625,0.125,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
{
float3 temp = specmap.rgb;
temp *= specmap.rgb;
temp *= specmap.rgb;
temp.b = (temp.r+temp.g)*0.75;
return clamp( temp.b*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); }
float limited_shininessMap(float shininess, float specmap)
{
float limit = 50; //50^2 is 2500. 2500*0.001 = 2.5 --enough risk of saturation!
float shine = shininessMap(shininess,specmap);
return (shine*limit)/(shine+limit);
}
float shininess_to_brightness(float shininess)
{
return 0.001 * shininess * shininess;
}
float lightspot_brightness( float shininess, float specmap )
{
return limited_shininessMap( shininess, specmap ) * shininess_to_brightness( shininess );
}
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) * lightDiffuse.rgb * lightAtt ;
specular += selfshadow * pow(clamp(RdotL,0.0,1.0), lightspot_brightness(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);
//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 );
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;
}
Changed selfshadowing step to go from -0.0625 to +0.125 VNdotL
Changed shininess limit from 30 to 50, and multiplier for shininess_to_brightness to 0.001.
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- Elite
- Posts: 7243
- Joined: Mon Apr 18, 2005 2:40 pm
- Location: LS87, Buenos Aires, República Argentina
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
Well, like I said, I don't have a proper bumpmap to try this with.
I was thinking, the sun has a diameter of 0.5 degrees in the sky, from Earth.
Considering atmospheric scattering, we could push it up to one degree.
I know there's no scattering in space, but to me the important thing is whether
things shade the way we're ***used to*** seeing them shade.
With the NdotL, a flat surface turning from shadow into light makes a sudden
jump. How hard would it be to compute a modified NdotL that gives a smoother
transition?
Suppose we did something like
Here's some pics.
NdotL is a cosine wave from the perspective of angle to the normal:
1 minus the square of it:
square that again:
square that again
Multiplying by NdotL now:
And we subtract the result from NdotL:
Now we can shift this function a tiny bit up, to get half a degree extra around cylinders for diffuse light; and shift it a little bit down for bump shadowing.
By the way, another way to do the self-shadowing would be,
One minus...
...already has a bit of a squarish shape. Mul that by 100 and then limit it by computing it / ( it + 1 )
Not sure if this is cheaper than smooth step; but probably.
I was thinking, the sun has a diameter of 0.5 degrees in the sky, from Earth.
Considering atmospheric scattering, we could push it up to one degree.
I know there's no scattering in space, but to me the important thing is whether
things shade the way we're ***used to*** seeing them shade.
With the NdotL, a flat surface turning from shadow into light makes a sudden
jump. How hard would it be to compute a modified NdotL that gives a smoother
transition?
Suppose we did something like
Code: Select all
float NdotL = dot( N * L );
float temp = 1 - NdotL*NdotL
//temp is now a sine wave twice the frequency of NdotL, shifted positive
temp = temp * temp;
temp = temp * temp;
temp = temp * temp;
//now temp shows a narrower pulse at each zero-crossing of NdotL
temp *= NdotL;
//This caused the pulses to be turned into wavelets with zero-crossings
//in phase with NdotL
float smootherNdotL = NdotL - (K * temp);
//With the right value for K, we got zero-cross distortions on NdotL that
//make its zero-crossings shallower.
NdotL is a cosine wave from the perspective of angle to the normal:
1 minus the square of it:
square that again:
square that again
Multiplying by NdotL now:
And we subtract the result from NdotL:
Now we can shift this function a tiny bit up, to get half a degree extra around cylinders for diffuse light; and shift it a little bit down for bump shadowing.
By the way, another way to do the self-shadowing would be,
One minus...
...already has a bit of a squarish shape. Mul that by 100 and then limit it by computing it / ( it + 1 )
Not sure if this is cheaper than smooth step; but probably.
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
Correction on the previous post: The last part needs to be based on VNdotL, of course. Just a momentary inattention.
I've implemented the "softNdotL" algorithm above, with good results:
Notice the soft penumbras.
More importantly, but I cannot show it here without making a movie out of it, is that, as I turn the Tarsus around,
flat faces that go from darkness to light don't "jump" so suddenly into light.
The only problem is the specular light-spots seem to be in the wrong places.
I'm not sure if this is something new. I don't believe I touched them... :-/
Here's the modified ligthingLight():
EDIT:
Problem with spotlights went away; it was just messed up smooth groups in the refinery mesh.
Here's softNdotL at work on Perry (which also has messed up smooth groups, but not as bad):
Attention: There's no normalmap on Perry; that's all just plain texture work with bump shadows burnt into the diffuse.
EDIT2:
Klauss, what's happening with the Tangents? We really... ***really*** need them.
I can come up with some improvements to that code, by the way, like making wider angle triangles weight more
on the determination of the tangent; but I'd rather wait to hear that the basic code is working, first.
The Llama will get an instant improvement, as parts of its UV map are rotated relative to the main island, and
therefore normalmap incorrectly.
Plus, I have a "Legacy Mixer" blender noodle that can already take diffuse, spec, glow and ambient occlusion bake as
input, and produce ao-modulated diffuse and spec, glow map with baked ambient light, and shininess in spec alpha.
I can easily add a few more nodes to make a normalmap based on luma, and then make it available to Vegastrike.
But with the unwraps following no orientation rules, as they are, the normalmap can only work if we have TANGENTS...
I've implemented the "softNdotL" algorithm above, with good results:
Notice the soft penumbras.
More importantly, but I cannot show it here without making a movie out of it, is that, as I turn the Tarsus around,
flat faces that go from darkness to light don't "jump" so suddenly into light.
The only problem is the specular light-spots seem to be in the wrong places.
I'm not sure if this is something new. I don't believe I touched them... :-/
Here's the modified ligthingLight():
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)
{
float NdotL = dot(normal,light);
float VNdotL= dot(vnormal,light);
float s = 1.0 - (NdotL*NdotL);
float RdotL = dot(reflection,light);
float selfshadow = selfshadowStep(VNdotL);
float temp = clamp( NdotL - (0.94 * s * s * s * s * NdotL) + 0.005, 0.0, 1.01 );
specular += ( selfshadow * pow(clamp(RdotL,0.0,1.0), lightspot_brightness(shininess,specmap)) * lightDiffuse.rgb * lightAtt );
diffuse += ( selfshadow * temp * lightDiffuse.rgb * lightAtt );
}
Problem with spotlights went away; it was just messed up smooth groups in the refinery mesh.
Here's softNdotL at work on Perry (which also has messed up smooth groups, but not as bad):
Attention: There's no normalmap on Perry; that's all just plain texture work with bump shadows burnt into the diffuse.
EDIT2:
Klauss, what's happening with the Tangents? We really... ***really*** need them.
I can come up with some improvements to that code, by the way, like making wider angle triangles weight more
on the determination of the tangent; but I'd rather wait to hear that the basic code is working, first.
The Llama will get an instant improvement, as parts of its UV map are rotated relative to the main island, and
therefore normalmap incorrectly.
Plus, I have a "Legacy Mixer" blender noodle that can already take diffuse, spec, glow and ambient occlusion bake as
input, and produce ao-modulated diffuse and spec, glow map with baked ambient light, and shininess in spec alpha.
I can easily add a few more nodes to make a normalmap based on luma, and then make it available to Vegastrike.
But with the unwraps following no orientation rules, as they are, the normalmap can only work if we have TANGENTS...
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
Klauss, here's a MUCH cheaper way to compute bump self-shadow (and smoother, and more correct, to boot):
IOW, I'm just preventing NdotL from ever being more than 4 * VNdotL.
Guess what NdotL has to be when VNdotL is zero...
Haven't tried it yet, hold on...
(The price for this is TANGENTS...)
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)
{
float VNdotLx4= clamp( 4.0 * dot(vnormal,light), 0.0, 1.0 ); // <-***** modified
float NdotL = clamp( dot(normal,light), -1.0, VNdotLx4 ); // <-***** modified
float RdotL = clamp( dot(reflection,light), 0.0, VNdotLx4 ); // <-***** modified
float s = 1.0 - (NdotL*NdotL); //soft penumbra stuff
//float selfshadow = selfshadowStep(VNdotL); // <-***** removed
float temp = clamp( NdotL - (0.94 * s * s * s * s * NdotL) + 0.005, 0.0, 1.01 ); //soft penumbra stuff
specular += ( pow( RdotL, lightspot_brightness(shininess,specmap)) * lightDiffuse.rgb * lightAtt ); // <-***** modified
diffuse += ( temp * lightDiffuse.rgb * lightAtt );
}
Guess what NdotL has to be when VNdotL is zero...
Haven't tried it yet, hold on...
(The price for this is TANGENTS...)
Last edited by chuck_starchaser on Tue Apr 08, 2008 9:08 pm, edited 1 time in total.
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
Heh... Worked like a charm first time; no debugging:
Updated shader:
More natural bump self-shadowing, and it should take a lot less shader instructions.
Updated shader:
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 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
{
float3 temp = specmap.rgb;
temp *= specmap.rgb;
temp *= specmap.rgb;
temp.b = (temp.r+temp.g)*0.75;
return clamp( temp.b*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); }
float limited_shininessMap(float shininess, float specmap)
{
float limit = 50; //50^2 is 2500. 2500*0.001 = 2.5 --enough risk of saturation!
float shine = shininessMap(shininess,specmap);
return (shine*limit)/(shine+limit);
}
float shininess_to_brightness(float shininess)
{
return 0.001 * shininess * shininess;
}
float lightspot_brightness( float shininess, float specmap )
{
return limited_shininessMap( shininess, specmap ) * shininess_to_brightness( shininess );
}
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 VNdotLx4= clamp( 4.0 * dot(vnormal,light), 0.0, 1.0 ); // <-***** modified
float NdotL = clamp( dot(normal,light), -1.0, VNdotLx4 ); // <-***** modified
float RdotL = clamp( dot(reflection,light), 0.0, VNdotLx4 ); // <-***** modified
float s = 1.0 - (NdotL*NdotL); //soft penumbra stuff
//float selfshadow = selfshadowStep(VNdotL); // <-***** removed
float temp = clamp( NdotL - (0.94 * s * s * s * s * NdotL) + 0.005, 0.0, 1.01 ); //soft penumbra stuff
specular += ( pow( RdotL, lightspot_brightness(shininess,specmap)) * lightDiffuse.rgb * lightAtt ); // <-***** modified
diffuse += ( temp * 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);
//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 );
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;
}
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.