I'm making a orthographic isometric game, and I want to be able to edit lighting from the three directions of geometry you can see (top, left, and right). How could I do this, what type of shader would I need? I want to do this myself so could I just get instruction? Cheers!
I've done some research and I'd like to rephrase my question. How could I give each face of my cube its own vertex so that I can hard color each face and it opposite face independently of the rest?
I would take a look at the free matcap shaders on the asset store. It's very fast, view-direction-based fake lighting that is easy to customize. It comes with a few matcap textures, but it's pretty straight-forward to make your own either with a matcap generator tool or simply by hand.
Not what I'm looking for. I would like a shader that will let me independently hard color each side of a cube so I fake lighting for my for a poly game easily. Pretty much make three surface lights, any ideas?
I don't know how it's done but it sounds like this shader asset fits the bill. It's not free though https://www.assetstore.unity3d.com/en/#!/content/57591
It sounds like a good situation to use vertex colours (which you can apply on your mesh procedurally) and a shader which will display those vertex colours. http://docs.unity3d.com/ScriptReference/Mesh-colors.html
pixpusher that is exactly what I was looking for, but I'm 16 and broke so buying something even as cheap as that isn't a option. Is there a way I could make a dumbed down version that simulates three directional light shining on my geometry? With hard colors no blending.
Not sure this is what you're looking for, but I did a simple shader in Shader Forge a while ago that takes a left, right, and top color and blends those based on a mesh's normals. It's only going to do "hard" colors on cubes, since those have normals that point 100% in each color's direction, but if your geometry is cube-based, it could work. I think it's kosher to share the compiled output from Shader Forge, so I can post it if you're interested. This scene has no lights: Here are the properties (I have an optional texture you can mix in, but I don't remember why):
Sure, here's the .shader file: https://dl.dropboxusercontent.com/u/28342849/Unity_misc/ShaderForge/DirectionalUnlitBlending.shader You'll probably get a warning, since you need the Shader Forge asset imported into your project to be able to edit it with Shader Forge, but I don't think that should cause any issues. You can probably just remove the junk at the top to get rid of the Shader Forge data. Once compiled, it'll show up under "Shader Forge" in your shader list. You can change the source to make it something else.
@Dev.Undead are you asking what the logic is in the shader or how to use it? The "meat" of it is really just this one line. It takes each color and multiplies it by one of the normal vector's three coordinates, then multiplies all of those together. Super simple as shaders go and it's probably overkill to use Shader Forge for it. The texture part of it I could probably just take out. float3 emissive = (_Texture_var.rgb*((_LeftColor.rgb*i.normalDir.r)+(_TopColor.rgb*i.normalDir.g)+(_RightColor.rgb*i.normalDir.b))); This value is set as the output pixel with an alpha of 1.0.
Is there a way I could color the opposite side as well? E.g. Top and bottom one color, left and right, front and back?
When I do (_Texture_var.rgb*((_LeftColor.rgb*i.normalDir.r)+(_TopColor.rgb*i.normalDir.g)+(_RightColor.rgb*i.normalDir.b))^2); it does both sides but messes up the color
Here's one that works with all six sides. I used Shader Forge to create another input of the normal, inverted it, did the same sort of math with three new colors, then did a Blend with the Lighten option to combine everything. In the generated code, it used "saturate" for that. Seems to work! https://dl.dropboxusercontent.com/u/28342849/Unity_misc/ShaderForge/SixColorlUnlitBlending.shader
You just need to do a lerp, and you'd want to do it in the vertex shader. There's no point in doing per-pixel calculations on an interpolated normal. Code (csharp): Removed Edit: Fixed normal scale and bias Edit Again: Apparently, had a copy/paste malfunction that messed it all up. Should be right now. Edit #3: Added scale by dot product for each axis. Should be working now, but no guarantees, exchanges, or refunds. Edit #4: Still wrong, haha. I'm going to sit down and make sure it's right before I post a new version.
Yeah, you'd only want to do the math in the frag shader if you wanted to add a bump map to your object. Then, you'd have no choice but to do the interpolations after sampling the bump map texture.
@CaptainScience your code works nicely but it messes up the colors. Ill look into finding a solution myself tho also this https://gyazo.com/ee2006956656eadab3627a5a2014aa8d
Did you try my solution? The second shader? It's not efficient, though I suspect optimizing such a simple shader isn't necessary.
Yeah, I just whipped that up so I just added all three axes together, but you'd actually want to scale them by the dot product. Code (csharp): Removed That should keep the canonical colors for each of the six sides, and then interpolate between them. Edit: Removed code here
I'm working all the kinks out. I really want to be independent when it comes to shaders, when I come here and ask for one it feels like I'm taking. So im working out all the kinks on my own. Heres what I've got: https://gyazo.com/56945487ed59ce0bfb90d3699c212abe However with the rgb color code its made me notice some small errors in my level shown here: https://gyazo.com/9b8bf0d1b6da7f320a825d02323a9120 anyone know how to fix these?
Yes, I thought about it and realized there was still a problem with the shader so I posted a new, simpler version. Just a dot product (scaled to 0...1) for each color so that should do it.
Working on everything but angles, whats the issue? Screenshot: https://gyazo.com/8072d225c15705d49eba1146c0e9459c Code: http://hastebin.com/utipuxipon.avrasm
Took a look at the shader, and tested it a bit. This version should work, and have decent interpolation between the colors. The last one I had posted was a bit wonky so I wanted to have a working version up in case someone Googles this in the future. It might be able to be optimized a bit, but this runs on the vertex shader and dot products are cheap. Code (csharp): Properties { _UpColor ("UpColor", Color) = (1,0,0,1) _DownColor ("DownColor", Color) = (0,0,0,1) _LeftColor ("LeftColor", Color) = (0,1,0,1) _RightColor ("RightColor", Color) = (0,0,0,1) _BackColor ("BackColor", Color) = (0,0,1,1) _FrontColor ("FrontColor", Color) = (0,0,0,1) } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag //makefog work #pragma multi_compile_fog #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float4 normal : NORMAL; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 color : COLOR; UNITY_FOG_COORDS(1) float4 vertex : SV_POSITION; }; float4 _UpColor; float4 _DownColor; float4 _LeftColor; float4 _RightColor; float4 _BackColor; float4 _FrontColor; v2f vert (appdata v) { v2f o; o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); UNITY_TRANSFER_FOG(o,o.vertex); float3 normal = UnityObjectToWorldNormal(v.normal); o.color = float4(0,0,0,0); o.color += _RightColor * saturate(dot(normal, float3(-1,0,0))) + _LeftColor * saturate(dot(normal, float3(1,0,0))); o.color += _DownColor * saturate(dot(normal, float3(0,-1,0))) + _UpColor * saturate(dot(normal, float3(0,1,0))); o.color += _FrontColor* saturate(dot(normal, float3(0,0,-1))) + _BackColor * saturate(dot(normal, float3(0,0,1))); return o; } fixed4 frag (v2f i) : SV_Target { fixed4 col = i.color; //apply fog UNITY_APPLY_FOG(i.fogCoord, col); return col; } ENDCG } } }
That actually looks like an issue with your model having hard edges. Its either the smoothing in your modelling program, or the smoothing angle when you imported the model into Unity.
You could just use a cubemap. Should be much faster and cheaper. edit: example Here's the cubemap I used (it's that tiny little image ->) Code (CSharp): Shader "CubeMapLighting" { Properties { _Tint ("Color", Color) = (1,1,1,1) _MainTex ("Texture", 2D) = "white" {} [NoScaleOffset] _Cube ("Lighting", Cube) = "grey" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; half3 normal : NORMAL; }; struct v2f { half3 normal : NORMAL; float2 uv : TEXCOORD0; UNITY_FOG_COORDS(1) float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; samplerCUBE _Cube; fixed4 _Tint; v2f vert (appdata v) { v2f o; o.normal = UnityObjectToWorldNormal(v.normal); o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); UNITY_TRANSFER_FOG(o,o.vertex); return o; } fixed4 frag (v2f i) : SV_Target { // sample the texture fixed4 col = tex2D(_MainTex, i.uv) * _Tint; fixed4 lighting = texCUBE(_Cube, i.normal) * 2.0; col.rgb *= lighting.rgb; // apply fog UNITY_APPLY_FOG(i.fogCoord, col); return col; } ENDCG } } }
Here are some lighting examples to be used with your surface shaders to fake extra lights: EDIT: You have to define _LightColorBack, _LightColorSide properties. Bidirectional (2 lights, one from the opposite side of the main light): Code (CSharp): fixed4 _LightColorBack; inline fixed4 LightingTOZ_BiDirectional(SurfaceOutput s, fixed3 lightDir, fixed atten) { //Diffuse term fixed diff1 = max(dot(s.Normal, lightDir), 0); fixed diff2 = max(dot(s.Normal, -lightDir), 0); fixed lum = Luminance(_LightColor0.rgb); //Sum fixed4 c; c.rgb = s.Albedo * ((_LightColor0.rgb * diff1) + ((lum * _LightColorBack.rgb) * diff2)) * (atten * 2); c.a = s.Alpha; return c; } Hemispheric (like ambient): Code (CSharp): fixed4 _LightColorBack; inline fixed4 LightingTOZ_Hemispheric(SurfaceOutput s, fixed3 lightDir, fixed atten) { //Diffuse term fixed diff = (dot(s.Normal, lightDir) + 1.0) * 0.5; fixed lum = Luminance(_LightColor0.rgb); //Sum fixed4 c; c.rgb = s.Albedo * lerp((lum * _LightColorBack.rgb), _LightColor0.rgb, diff) * (atten * 2); c.a = s.Alpha; return c; } Tridirectional (One main light, another light from opposite, another light from the side): Code (CSharp): fixed4 _LightColorBack, _LightColorSide; inline fixed4 LightingTOZ_TriDirectional(SurfaceOutput s, fixed3 lightDir, fixed atten) { //Diffuse Term fixed diff1 = max(dot(s.Normal, lightDir), 0); fixed diff2 = 1.0 - abs(dot(s.Normal, lightDir)); fixed diff3 = max(dot(s.Normal, -lightDir), 0); fixed lum = Luminance(_LightColor0.rgb); //Sum fixed4 c; c.rgb = s.Albedo * (_LightColor0.rgb * diff1 + (lum * _LightColorBack.rgb) * diff2 + (lum * _LightColorSide.rgb) * diff3) * (atten * 2); c.a = s.Alpha; return c; } Good luck.