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
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.
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): Shader "Desaturated Darks" { Properties { _Color ("Main Color", Color) = (1,1,1,1) _SpecColor ("Spec Color", Color) = (1,1,1,1) _Emission ("Emmisive Color", Color) = (0,0,0,0) _Shininess ("Shininess", Range (0.01, 1)) = 0.7 _MainTex ("Base (RGB)", 2D) = "white" {} _Darkening ("Darkening", Range (0,1)) = 0.5 } SubShader { Pass { Material { Diffuse [_Color] Ambient (0,0,0,0) Shininess [_Shininess] Specular [_SpecColor] Emission [_Emission] } Lighting On SeparateSpecular On CGPROGRAM // profiles arbfp1 // fragment frag // fragmentoption ARB_fog_exp2 // fragmentoption ARB_precision_hint_fastest #include "UnityCG.cginc" uniform sampler2D _MainTex; uniform float _Darkening; uniform float4 _Color; half4 frag( v2f_vertex_lit i ) : COLOR { // texture half4 texcol = tex2D( _MainTex, i.uv ) * _Color; // intensity of the lighting half brightness = Luminance( i.diff.xyz + i.spec.xyz * texcol.a ) * 2; // color of completely unlit desaturated areas half unlit = Luminance( lerp( texcol.xyz, texcol.xyz * i.diff.xyz, _Darkening ) ); // final color based on lighting intensity half4 c; c.xyz = lerp( half3(unlit), texcol.xyz, brightness ); c.w = texcol.w * i.diff.w; return c; } ENDCG SetTexture [_MainTex] {} } } Fallback " VertexLit", 1 }
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
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): 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
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.
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.
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).
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)