- Home /
Why does my shader only shade objects based on their normals in the X axis?
I am trying to implement a shader with Gouraud style shading in which the shading is dominated by vertex color. However, my shader only seems to want to use normals that are facing in the X axis to shade, regardless of where the light source is, what type, or if there are even light sources! I know that I am probably missing something blatant, but what?
Shader "Gouraud"
{
Properties
{
_MainTex ("Base (RGB)", 2D) = "white" {}
_Color ("Diffuse Material Color", Color) = (1,1,1,1)
_SpecColor ("Specular Material Color", Color) = (1,1,1,1)
_Shininess ("Shininess", Float) = 1
}
SubShader
{
Pass
{
Tags { "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
// User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess;
// color of light source (from "Lighting.cginc")
uniform float4 _LightColor0;
// Vertex and Fragment Structs
struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 col : COLOR;
};
vertexOutput vert(vertexInput v)
{
vertexOutput output;
// Compute directional vectors
float3 normalDir = normalize(float3(mul(float4(v.normal, 0.0), _World2Object)));
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz - v.vertex);
float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - v.vertex);
// Compute the ambient term
float3 ambientTerm = float3(UNITY_LIGHTMODEL_AMBIENT) * float3(_Color);
// Compute the diffuse term
float diffuseLight = max(0.0, dot(normalDir, lightDir));
float3 diffuseTerm = _Color * diffuseLight;
// Compute the specular term
float3 halfwayDir = normalize(lightDir + viewDir);
float specularLight = pow(max( 0,dot(normalDir, halfwayDir)), 1);
// If we have no diffuse component, then we have no specular component
if(diffuseLight <= 0.0)
{
specularLight = 0;
}
float3 specularTerm = specularLight * _LightColor0 * _SpecColor;
// Assign final color and position output
output.col = float4(ambientTerm + diffuseTerm + specularTerm, 1.0);
output.pos = mul(UNITY_MATRIX_MVP, v.vertex);
return output;
}
float4 frag(vertexOutput input) : COLOR
{
return input.col;
}
ENDCG
}
}
}
Answer by whydoidoit · Mar 21, 2013 at 08:36 AM
Well there are a few problems I can spot:
A normal is a direction and they are converted using this code:
half3 normal = normalize(mul((float3x3) UNITY_MATRIX_IT_MV, v.normal));
Your code for the light position won't work with directional lights, usually that would be:
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz - (v.vertex * _WorldSpaceLightPos0.w));
w will be 0 for directional lights.
Specular lights normally need their specular element calculating in the fragment shader - or you are only getting specularity on vertices and interpolating the results.
Your answer
Follow this Question
Related Questions
how can i catch the sky box and do a reflection in object 0 Answers
Getting vertex data from lighting function in shaders. 1 Answer
Vertex/Fragment shaders - transparency ignoring Render Queue 3 Answers
Refraction Shader. Strange Artifacts 0 Answers
Vertex shader breaks render to texture - camera preview and render texture not the same 1 Answer