Transparency blending with cg shaders

I'm trying to find the right blendfunc to make transparent windows work properly.

When I use blendfunc=blend, it makes this "negative" effect, depending on the brightness of the front texture - eg. where the clouds are reflecting, the seat appears blue, while it's red without the cloud reflection. The driver's hair/face also invert brightness.

Along the top edge of the window, the texture is 100% opaque - shouldn't be getting any of the object behind it. But the same "blue" from the seat is visible there too in the reflection.

negativerefl.jpg

Here's one on a brighter day showing the same thing. The reflection is more blue but it's a similar effect.
negativerefl2.jpg


I'm not sure why the colour of the closer layer would be affected like this.


Part of the problem, of course, is that the reflect_window_v/f.cg is not up to date with the new fresnel functions. Using the normal reflect_v.cg doesn't work for windows because it doesn't adjust transparency at all. I ended up fixing these first.

dyn_standard_reflect_window_v.cg
Code:
#include \\\\\\"fresnel.cg\\\\\\"
[...] 

  // Fresnel
  const float fresnelBias=0.15; //0.2;
  const float fresnelScale=0.85; //0.9
  const float fresnelPower=3.0; //4.0;
  I=normalize(I);
  OUT.fresnel=Fresnel(fresnelBias,fresnelScale,fresnelPower,I,N);
This substitutes the Fresnel function used by other shaders for the old version, which was the same thing done manually. I think the old values were also 0, 1, 2, which I changed to 0.15 0.85 3.0 because that seems closer to glass.

dyn_standard_reflect_window_f.cg
Code:
#include \\\\\\"fresnel.cg\\\\\\"
[...]

{
  float3 skyColor;

  // Get sky gradient color
  skyColor.rgb=GetSkyColor(lightDirection,IN.Direction,IN.RayleighColor,IN.MieColor,atmosRayleigh,atmosMie,lightColor,lightAmbient);

  // Get base texture color
  float4 baseCol=tex2D(baseMap,IN.tc0);

  // Reflection
  //const float Kr=0.5f;
  float4 envColor=texCUBE(envMap,IN.R);
//envColor*=3.0f;

  // Lighting
  float3 ambient,diffuse,specular;
  LightingSun(Ke,Ka,Kd,Ks,shininess,lightDirection,lightColor,lightAmbient,IN.Position,IN.normal,eyePosW,
    ambient,diffuse,specular);
  baseCol.rgb=baseCol*(ambient+Ke)+baseCol*diffuse*lightColor+specular;

  // HDR toning of sky
  //skyColor.rgb=1.0-exp(-exposure*skyColor.rgb);
  
  // Add reflection
  //baseCol=lerp(baseCol,envColor,Kr);
  //baseCol.rgb+=envColor.rgb*Kr*IN.fresnel;
  //baseCol.rgb=FresnelMix(baseCol.rgb,envColor.rgb,Kr,IN.fresnel);
  baseCol.rgba=FresnelGlassMix(baseCol.rgba,envColor.rgb,Kr,IN.fresnel);
//baseCol.rgb+=envColor.rgb; //*Kr*IN.fresnel;
  // Reflection influences opaque-ness
  //baseCol.a=1; //max(baseCol.a,envColor.g);
  //baseCol.a=max(baseCol.a,envColor.g);
//baseCol.rgb+=envColor.rgb; //*Kr*IN.fresnel;
//baseCol=envColor;

  // Mix sky with texture color based on atmospheric influence
  outColor.rgb=lerp(skyColor,baseCol,IN.extinction);
//outColor.rgb=IN.fresnel;
//outColor.rgb=baseCol;
//outColor.rgb=Kr;

  // Blending
  outColor.a=baseCol.a;
//outColor.a=1;
}
I changed the functions a little more here, to get it working right. I also ended up writing in a new function in fresnel.cg to calculate the alpha transparency at the same time as the rest:
fresnel.cg
Code:
float4 FresnelGlassMix(float4 diffCol,float3 envCol, float Kr, float fresnel)
// mix with alpha
{
  float4 retCol = diffCol;
  retCol.rgb = (diffCol.rgb+envCol*Kr*fresnel)*diffCol.a + (1-diffCol.a)*envCol;
 // retCol.rgb += envCol*Kr*fresnel;
  retCol.a = max(diffCol.a, envCol.g*Kr*fresnel);
  return retCol;
}
Without multiplying by Kr and fresnel, envCol.g was overpowering the transparency of the glass. Really, doing this could have stayed in _reflect_window_f.cg. But it's easier to find the function here.


After these changes, it looks quite a bit nicer, and it became more clear to me what blending function I want.
glassclouds.jpg


The problem is that the reflection off of glass is only visible where it's brighter than the backing. So what I really need is something more like a maximum -
blendfunc = max(refl_color, dst.rgb)
Where refl_color = glass.a * glass.rgb + (1 - glass.a) * dst.rgb, ie. the normal blend, and dst is the background it's being overlaid onto.

Or, maybe
reflection_strength = min(0, (refl - dst))
blend = reflection_strength*refl + (1 - reflection_strength)*dst
This represents the opacity of the reflection increasing with the difference between the reflection and its backing. If the backing was entirely dark then it should reflect more completely.
 
Hm Nice, I was hoping this would actually solve a problem I'm having with CG shaders and windows, seems they like to be transparent and not show anything under them for me, not sure whats going wrong myself. But this problem only seems to happen at certain angles, and with CG shaders. heres a picture to give you an idea of my problem the rear window is showing well nothing really and the door window, you can see the interior. :ooh:
 
Oh right, I forgot about the shader I'm using currently.

Code:
vf_glass
{
  vertex_shader
  {
    file=dyn_standard_reflect_window_v.cg
  }
  fragment_shader
  {
    file=dyn_standard_reflect_window_f.cg
  }
}
shader_glass~vf_glass
{
  sort_offset=1
  reflect=0.8
  layer0
    {
      map=glass.tga
      blendfunc=blend
    }
  layer1
    {
      map=$trackenvmap
    }
}
I think sort_offset is supposed to fix objects not showing through each other, positive numbers means they're drawn later from what I know.

I reordered the parts of _window_f.cg a little in my original post and the problem seems to be fixed. I guess I got the right transparency/colour being output somehow.

lambowindow.jpg

Looks more natural to me, especially around the headlight where it's reflecting the treeline.
 
  • Tiberius

That glass shader bothered me too, I noticed the problem but didn't get around to working out what was wrong :)


Hm Nice, I was hoping this would actually solve a problem I'm having with CG shaders and windows, seems they like to be transparent and not show anything under them for me, not sure whats going wrong myself.

I just usually chuck a depthwrite=0 into each layer for the glass shader. That will fix most problems, also make sure that you don't have any blendfunc or alphafunc stuff on the first layer of your normal shaders - they can cause depth buffer problems. AFAIK, sort offsets were mainly to help prevent depth fighting on faces rendered close together (drive a car on Speedest 2 and watch the trackcams, parts of the car will flicker at a distance, that's depth fighting). I never had much luck using sort offsets for anything really, things work better now that I have most parts of the car in different objects though :).
 
Raphael Buthmann asked for the .cg files and I'm not sure if I can attach them here directly so I hosted them on my site.

For normal glass I find a dark blue-green texture works ok, alpha around 30-50. In terms of tints I guess you'd just match the percent tint as transparency and leave the base color nearer to black.

I tweaked this a bit since the version in the first post and I think it looks more natural. Just download the 3 cg files and replace the ones in /data/renderer/shaders_hdr/.

http://www.jonbuder.com/Stereo/Racer/

Simple shader I said above is enough to get them looking right.
 
  • Tiberius

Nice, big improvement over the bugged Racer shader But, I think the blending needs tweaking, on the X I've got the 'masks' around the edges of the windows mapped to alpha=255 so that they're fully opaque - I think they should be getting the same level of reflection as the rest of the window? It's difficult for me to explain, look at these shots:



Stereo, I found a....I thinks it's a bug lol.

That's not a bug with the shader, I've had lines like that on the edges of the cubemap ever since HDR came in. I mentioned it a couple of times but nobody ever took any notice, so.. :)

I'm getting the distorted black/red/yellow sun spot too but also getting it on Racer's version of the glass shader, totally no idea what's causing that one.
 
All I can really say is "that's odd, it didn't do that for me" :p The RX-7 is modeled with similar black framing on the windows and those work fine.

I did kill the specular highlight on the RX-7's windows because it was coming out badly. Missing 'shininess' value tended to do weird things so I left it in.
Code:
      shininess=20
      specular=0 0 0 1
I'm still developing on 0.8.7 at the moment though (I have no real way to download a 50MB file) so maybe there's some other shader difference going on to the latest version. I've definitely done unspecified tweaks to my atmosphere.cg but I can't think how that would affect blending here.
 
glass1.jpgglass2.jpg
Your shader doesn't allow putting an image of an object inside a glass cylinder which I use on my Cy Cops car to make a rotating lite on top. The image is done in views.ini.

There are a few other problems which I'm working on and will post them later along with the shader that I use which appears to me to work with just a couple of minor problems such as the reflection doesn't match up all over the glass window. There are sections where the reflections are distorted from the other sections.
 
  • Tiberius

Stereo: It's weird, I'm running 087 too (have 088 but haven't shifted everything over yet..), I also have the specular in there too. If it helps, the whole texture is black, just the alpha on the part of the texture where the masks are is white. Maybe it's me who has altered something, all I can think is that I turn the motion blur off, maybe I've done something else by mistake.

Also, any idea what causes this bug?:



Again, it's not just with your shader, I get it with the default glass one too. Seems the sun spot is so bright that it renders red/black/yellow and dims the auto expose as far as it will go. I've no idea what causes it, maybe you can work it out.

Boomer: All the CG glass shaders cut the 3D gauges for me, it's not a fault with Stereo's shader

Reflections never match up for me either, I get very noticeable edges on the cube map at times..but again, ever since CG came in, not an issue with any particular shader. Also, if you have a track which goes far enough away from the origin, at some angles you'll get 2 suns, like a double yolked egg :D. Again, it's just another weird bug with Racer, not a shader issue AFAIK :)
 
Again, it's not just with your shader, I get it with the default glass one too. Seems the sun spot is so bright that it renders red/black/yellow and dims the auto expose as far as it will go. I've no idea what causes it, maybe you can work it out.

Well, my ATI card can't handle autoexpose so I have that turned off, maybe it makes a difference?

Boomer: If you can find solutions to those problems I'll be sure to update what I have posted, if I knew what worked I would do it.



The rotating light seems like it could be implemented like the waving flags via a special cg shader on a modeled object, as long as it rotates just based on time. I guess I'll look at that when I have an opportunity.
 
test 1.jpgtest 2.jpg
Test 1 was made with a cuved glass and straght vertical black panel which gave very good reflections which lined up nicely.

Test 2 shows the distortion I'm getting that I know not how to correct, the side panel is one solid panel and the tree is located behind and to the right of the car. Also the glass has more than one reflection on it. Perhaps texture baking will help.

The best example of reflections I've found is Mr Whippy's BMW M3 using my glass shader!

My glass shader, no cg's required and it allows tinting of the glass. I generally use the same glass texture for all my cars:
shader_glass
{
sort_offset=53
compression=0
; ambient=1.00 0.05 0.05
shininess=1 ;80 ; adjust size of specular highlight
; specular=0.5 0.5 0.5 ; color of specular
reflect=0.9 ;amount of reflectivity
tangents=1 ; was in Lambo?
layer0
{
map=glass.tga
alphafunc=greater 254 ;# must be greater than alpha # to make glass transparent
blendfunc=blend
depthwrite=1 ; might need = 1 if objects with alpha bleed thru glass
}
layer1
{
map=$trackenvmap
texgen_s=reflection_map
texgen_t=reflection_map
texgen_r=reflection_map
blendfunc=src_color one_minus_src_color
depthwrite=0
}
layer2
{
map=glass.tga
alphafunc=notequal 0 ;notequal 0 for color, must use alphafunc
; alphafunc=notequal 143 ;notequal 143 for no color, must use alphafunc
blendfunc=src_alpha one_minus_src_alpha
ambient=-1.0 -1.0 -1.0 1 ; minus values give deeper color - sequence rgb dark glass
; ambient=1.0 -1.0 -1.0 1 ; minus values give deeper color - sequence rgb red glass
; ambient=-0.10 -0.10 0.80 1 ; minus values give deeper color - sequence rgb blue tint
depthwrite=0
}
}

Note the sort offset=53 which is used to keep the fence in the background behind the glass, a number lower than 50 lets it appear in front of the glass.

I use sort offset 1 thru 49 for tracks and 50 thru 99 for cars, haven't figured out - numbers
 
  • Tiberius

Well, my ATI card can't handle autoexpose so I have that turned off, maybe it makes a difference?

No, just tried without auto expose and still getting the bug, also tried with motion blur turned on (usually keep it turned it off because it kills my eyes). Can't turn bloom off because it gives me weird graphics glitches in 087 and 088, but from what I can see the bug is still there with the bloom off.

I'm running a GF 9800, maybe it's a compatibility thing between both brands of cards?

About the rotating beacon, AFAIK the code in the shader David Iau made for the spinning radiator fan would work if you can find the shader somewhere, I made a rotating cloud shader with it a while back.
 
  • Tiberius

Note the sort offset=53 which is used to keep the fence in the background behind the glass, a number lower than 50 lets it appear in front of the glass.

I use sort offset 1 thru 49 for tracks and 50 thru 99 for cars, haven't figured out - numbers

I (think?) that sort_offset is just relative? So a face will render above as long as its sort_offset is higher than the face below it, no matter what numbers you use? On the X I have both exterior and interior glass, the interior mapped to a basic blend shader which doesn't reflect. Both internal and external glass are copies of the same faces in exactly the same position, except that the internal window's faces are pointing inwards. with no sort_offset I get depth fighting and both sets of faces flickering - add sort_offset=-1 to the internal window's shader and sort_offset=1 to the external window's shader, it all renders like it should.
 
Stereo. Did you change another cg shaders? Like atmosfere or lightning? Maybe it can be uncompatible shaders.

I did change my sky shader but as far as I know, not a function that's used in this shader. (clouds were glowing neon bright and it looked weird in the evening, they're still too bright in my opinion but I got them to be dimmer than the sun)

When I get an opportunity I'll unzip a clean 0.8.7 or 0.8.8 install and try these there, since apparently they only work right for me. And I've never seen that black/red/yellow sun glitch so I can't comment on it.
 

Latest News

Online or Offline racing?

  • 100% online racing

    Votes: 84 7.4%
  • 75% online 25% offline

    Votes: 122 10.7%
  • 50% online 50% offline

    Votes: 166 14.6%
  • 25% online 75% offline

    Votes: 315 27.7%
  • 100% offline racing

    Votes: 447 39.3%
  • Something else, explain in comment

    Votes: 4 0.4%
Back
Top