Search Unity

Just dreaming...

Discussion in 'Shaders' started by antenna-tree, Mar 3, 2007.

  1. antenna-tree

    antenna-tree

    Joined:
    Oct 30, 2005
    Posts:
    5,324
    I've been pondering a game idea for several weeks now. It's a 3D platformer that harkens back to 1930s Disney cartoon aesthetics. Since the game would be black and white I've been thinking about how to combine 8-bit textures into a scheme that allows each channel of a regular 24-bit image into 3 different 8-bit textures. I could map 3 greyscale textures into one 24-bit texture while only calling one channel of the file for different shader. Any help on how to do this?

    My other idea is lighting. How insane am I to think that a shader could be made that affects the saturation of a texture based upon its distance from a pixel light... for instance a pixel light shines down on a scene and saturates a small area of the scene based upon it's reach. It changes the texture from pure desaturation to full color scale based on distance.

    Crazy stuff, any insights very appreciated,
    Ethan
     
  2. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    Not sure if I understood the reason behind the first paragraph about indexing some textures with some other texture... :?

    What if you think the other way around: you have less saturation when something gets less light, right? So with increasing attenuation colors become less saturated (but probably just as bright? or attenuated as well?). That would be pretty easy to do I guess... Not sure if that's what you're after though.
     
  3. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    Here's my attempt at something similar (still not sure if I understood that correctly). This is a vertex lit shader that desaturates "unlit" areas, optionally darkening them as well (Darkening slider). Fragment program hardware required.
    Code (csharp):
    1.  
    2. Shader "Desaturated Darks" {
    3. Properties {
    4.     _Color ("Main Color", Color) = (1,1,1,1)
    5.     _SpecColor ("Spec Color", Color) = (1,1,1,1)
    6.     _Emission ("Emmisive Color", Color) = (0,0,0,0)
    7.     _Shininess ("Shininess", Range (0.01, 1)) = 0.7
    8.     _MainTex ("Base (RGB)", 2D) = "white" {}
    9.     _Darkening ("Darkening", Range (0,1)) = 0.5
    10. }
    11. SubShader {
    12. Pass {
    13.     Material {
    14.         Diffuse [_Color]
    15.         Ambient (0,0,0,0)
    16.         Shininess [_Shininess]
    17.         Specular [_SpecColor]
    18.         Emission [_Emission]
    19.     }
    20.     Lighting On
    21.     SeparateSpecular On
    22.    
    23. CGPROGRAM
    24. // profiles arbfp1
    25. // fragment frag
    26. // fragmentoption ARB_fog_exp2
    27. // fragmentoption ARB_precision_hint_fastest
    28.  
    29. #include "UnityCG.cginc"
    30.  
    31. uniform sampler2D _MainTex;
    32. uniform float _Darkening;
    33. uniform float4 _Color;
    34.  
    35. half4 frag( v2f_vertex_lit i ) : COLOR
    36. {
    37.     // texture
    38.     half4 texcol = tex2D( _MainTex, i.uv ) * _Color;
    39.    
    40.     // intensity of the lighting
    41.     half brightness =
    42.         Luminance( i.diff.xyz + i.spec.xyz * texcol.a ) * 2;
    43.    
    44.     // color of completely unlit  desaturated areas
    45.     half unlit = Luminance(
    46.         lerp( texcol.xyz, texcol.xyz * i.diff.xyz, _Darkening ) );
    47.    
    48.     // final color based on lighting intensity
    49.     half4 c;
    50.     c.xyz = lerp( half3(unlit), texcol.xyz, brightness );
    51.    
    52.     c.w = texcol.w * i.diff.w;
    53.     return c;
    54. }
    55. ENDCG
    56.  
    57.     SetTexture [_MainTex] {}
    58. }    
    59. }
    60. Fallback " VertexLit", 1
    61. }
     
  4. antenna-tree

    antenna-tree

    Joined:
    Oct 30, 2005
    Posts:
    5,324
    Damn! That's awesome Aras! Thanks a bunch!

    Is the only way to do that technique is by affecting the vertices? Could it be done with smoother gradations using a diffuse shader or would that be too performance heavy? Also, could it be done not with lights, but with specially tagged obects that just saturate the shader within a certain radius?

    The question about the 8-bit channels was asking whether or not you can just use say the Red channel of a 24-bit texture for a shader. If you're doing a purely black and white game then you could store separate textures in each channel of an RGB texture and save a ton of VRAM.

    Thanks again Aras,
    Ethan
     
  5. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    Yes, this can be easily turned into a full pixel lit shader, and it would not be expensive. I could do that if the effect is actually what you want.

    Regarding objects affecting saturation: well, something in the game with some radius that affects the way things look - that sounds very much like a point light to me :)

    About channels of the textures: sure, that's easy to do. However that would require writing three versions of the shaders I think: one that uses R, one for G and one for B. Sampling a single channel is easy in Cg, something like:
    Code (csharp):
    1. float myvalue = tex2D( _MainTex, i.uv ).r; // this gets R
    However, if you pack completely separate textures into different channels and then do DXT compression on that, the results can be worse than expected. DXT works on colors and the way eye sees them (lower sensitivity to blue intensity etc.), so packing completely arbitrary data does not produce good results. And without DXT you're not actually saving memory :)
     
  6. antenna-tree

    antenna-tree

    Joined:
    Oct 30, 2005
    Posts:
    5,324
    lol, yeah true. I guess I'm curious if there could be some performance saved by not having them lights. But then of course the calculations used to do this effect is similar to lighting. But I do just want the saturation to be affected and not the lighting (which you did with the darkening slider). The idea for the game is to turn the environment from a black/white cartoon into a color one so in the end there might be dozens of lights around to completely saturate the level. Would this get too slow by that point?

    That's really interesting. I'll have to do some tests on that to see just how DXT compresses each RGB channel. For this type of cartoony stuff it might be as simple as bumping up the brightness/contrast on say the Blue channel? Thanks for the insights Aras.
     
  7. antenna-tree

    antenna-tree

    Joined:
    Oct 30, 2005
    Posts:
    5,324
    Could you please help me with that? I'd love it to be pixel based and to be able to use cookies so I can map some cloud textures to the lighting. Clouds roll over the scene saturating the environment where the sun shines through.
     
  8. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
  9. antenna-tree

    antenna-tree

    Joined:
    Oct 30, 2005
    Posts:
    5,324
    That's just amazing! I really appreciate it Aras and I hope other people besides me find this shader useful (or at least a useful jumping off point for creating other shaders of this type).
     
  10. milkytreat

    milkytreat

    Joined:
    Jan 15, 2007
    Posts:
    267
    actually this is exactly what i need as well! but for a different reason,

    actually it would solve two of my graphical problems if its possible to change darkness for alpha/opacity

    Would it be better going a vertex or pixel based for that? (i have no idea what im asking about)