public Vector4 FS(PixelInput input) { float alphaMapSample = Sample(AlphaMap, AlphaMapSampler, input.TexCoord).X; if (alphaMapSample == 0) { Discard(); } Vector4 surfaceColor = Sample(SurfaceTexture, RegularSampler, input.TexCoord); Vector4 ambientLight = new Vector4(.4f, .4f, .4f, 1f); // Point Diffuse Vector4 pointDiffuse = new Vector4(0, 0, 0, 1); Vector4 pointSpec = new Vector4(0, 0, 0, 1); for (int i = 0; i < PointLights.NumActiveLights; i++) { PointLightInfo pli = PointLights.PointLights[i]; Vector3 lightDir = Vector3.Normalize(pli.Position - input.Position_WorldSpace); float intensity = Saturate(Vector3.Dot(input.Normal, lightDir)); float lightDistance = Vector3.Distance(pli.Position, input.Position_WorldSpace); intensity = Saturate(intensity * (1 - (lightDistance / pli.Range))); pointDiffuse += intensity * new Vector4(pli.Color, 1) * surfaceColor; // Specular Vector3 vertexToEye0 = Vector3.Normalize(CameraInfo.CameraPosition_WorldSpace - input.Position_WorldSpace); Vector3 lightReflect0 = Vector3.Normalize(Vector3.Reflect(lightDir, input.Normal)); float specularFactor0 = Vector3.Dot(vertexToEye0, lightReflect0); if (specularFactor0 > 0) { specularFactor0 = Pow(Abs(specularFactor0), MaterialProperties.SpecularPower); pointSpec += (1 - (lightDistance / pli.Range)) * (new Vector4(pli.Color * MaterialProperties.SpecularIntensity * specularFactor0, 1.0f)); } } pointDiffuse = Saturate(pointDiffuse); pointSpec = Saturate(pointSpec); // Directional light calculations //re-homogenize position after interpolation input.LightPosition /= input.LightPosition.W; input.LightPosition.W = 1; // if position is not visible to the light - dont illuminate it // results in hard light frustum if (input.LightPosition.X < -1.0f || input.LightPosition.X > 1.0f || input.LightPosition.Y < -1.0f || input.LightPosition.Y > 1.0f || input.LightPosition.Z < 0.0f || input.LightPosition.Z > 1.0f) { return(WithAlpha((ambientLight * surfaceColor) + pointDiffuse + pointSpec, surfaceColor.X)); } // transform clip space coords to texture space coords (-1:1 to 0:1) input.LightPosition.X = input.LightPosition.X / 2 + 0.5f; input.LightPosition.Y = input.LightPosition.Y / -2 + 0.5f; Vector3 L = -1 * Vector3.Normalize(LightInfo.LightDir); float diffuseFactor = Vector3.Dot(Vector3.Normalize(input.Normal), L); float cosTheta = Clamp(diffuseFactor, 0, 1); float bias = 0.0005f * Tan(Acos(cosTheta)); bias = Clamp(bias, 0, 0.01f); input.LightPosition.Z -= bias; //sample shadow map - point sampler float ShadowMapDepth = Sample(ShadowMap, ShadowMapSampler, new Vector2(input.LightPosition.X, input.LightPosition.Y)).X; //if clip space z value greater than shadow map value then pixel is in shadow if (ShadowMapDepth < input.LightPosition.Z) { return(WithAlpha((ambientLight * surfaceColor) + pointDiffuse + pointSpec, surfaceColor.X)); } //otherwise calculate ilumination at fragment diffuseFactor = Clamp(diffuseFactor, 0, 1); Vector4 specularColor = new Vector4(0, 0, 0, 0); Vector3 vertexToEye = Vector3.Normalize(CameraInfo.CameraPosition_WorldSpace - input.Position_WorldSpace); Vector3 lightReflect = Vector3.Normalize(Vector3.Reflect(LightInfo.LightDir, input.Normal)); Vector3 lightColor = new Vector3(1, 1, 1); float specularFactor = Vector3.Dot(vertexToEye, lightReflect); if (specularFactor > 0) { specularFactor = Pow(Abs(specularFactor), MaterialProperties.SpecularPower); specularColor = new Vector4(lightColor * MaterialProperties.SpecularIntensity * specularFactor, 1.0f); } return(WithAlpha(specularColor + (ambientLight * surfaceColor) + (diffuseFactor * surfaceColor) + pointDiffuse + pointSpec, surfaceColor.X)); }
public Vector4 FS(PixelInput input) { Vector4 surfaceColor = Sample(SurfaceTexture, RegularSampler, input.TexCoord); Vector4 ambientLight = new Vector4(0.3f, 0.3f, 0.3f, 1f); Vector3 lightDir = -LightInfo.Direction; Vector4 directionalColor = ambientLight * surfaceColor; float shadowBias = 0.0005f; float lightIntensity = 0f; // Specular color Vector4 directionalSpecColor = new Vector4(); Vector3 vertexToEye = Vector3.Normalize(CameraInfo.CameraPosition_WorldSpace - input.Position_WorldSpace); Vector3 lightReflect = Vector3.Normalize(Vector3.Reflect(LightInfo.Direction, input.Normal)); float specularFactor = Vector3.Dot(vertexToEye, lightReflect); if (specularFactor > 0) { specularFactor = Pow(Abs(specularFactor), MaterialProperties.SpecularPower); directionalSpecColor = new Vector4(LightInfo.Color.XYZ() * MaterialProperties.SpecularIntensity * specularFactor, 1.0f); } // Directional light influence float depthTest = input.FragDepth; Vector2 shadowCoords_0 = ClipToTextureCoordinates(input.LightPosition1); Vector2 shadowCoords_1 = ClipToTextureCoordinates(input.LightPosition2); Vector2 shadowCoords_2 = ClipToTextureCoordinates(input.LightPosition3); float lightDepthValues_0 = input.LightPosition1.Z / input.LightPosition1.W; float lightDepthValues_1 = input.LightPosition2.Z / input.LightPosition2.W; float lightDepthValues_2 = input.LightPosition3.Z / input.LightPosition3.W; int shadowIndex = 3; Vector2 shadowCoords = Vector2.Zero; float lightDepthValue = 0; if ((depthTest < DepthLimits.NearLimit) && InRange(shadowCoords_0.X, 0, 1) && InRange(shadowCoords_0.Y, 0, 1)) { shadowIndex = 0; shadowCoords = shadowCoords_0; lightDepthValue = lightDepthValues_0; } else if ((depthTest < DepthLimits.MidLimit) && InRange(shadowCoords_1.X, 0, 1) && InRange(shadowCoords_1.Y, 0, 1)) { shadowIndex = 1; shadowCoords = shadowCoords_1; lightDepthValue = lightDepthValues_1; } else if (depthTest < DepthLimits.FarLimit && InRange(shadowCoords_2.X, 0, 1) && InRange(shadowCoords_2.Y, 0, 1)) { shadowIndex = 2; shadowCoords = shadowCoords_2; lightDepthValue = lightDepthValues_2; } if (shadowIndex != 3) { // We are within one of the shadow maps. float shadowMapDepth = SampleDepthMap(shadowIndex, shadowCoords); float biasedDistToLight = (lightDepthValue - shadowBias); if (biasedDistToLight < shadowMapDepth) { // In light (no occluders between light and fragment). lightIntensity = Saturate(Vector3.Dot(input.Normal, lightDir)); if (lightIntensity > 0.0f) { directionalColor = surfaceColor * (lightIntensity * LightInfo.Color); } } else { // In shadow. directionalColor = ambientLight * surfaceColor; directionalSpecColor = Vector4.Zero; } } else { // We are outside of all shadow maps. Pretend like the object is not shadowed. lightIntensity = Saturate(Vector3.Dot(input.Normal, lightDir)); if (lightIntensity > 0.0f) { directionalColor = surfaceColor * lightIntensity * LightInfo.Color; } } // Point lights Vector4 pointDiffuse = new Vector4(0, 0, 0, 1); Vector4 pointSpec = new Vector4(0, 0, 0, 1); for (int i = 0; i < PointLights.NumActiveLights; i++) { PointLightInfo pli = PointLights.PointLights[i]; Vector3 ptLightDir = Vector3.Normalize(pli.Position - input.Position_WorldSpace); float intensity = Saturate(Vector3.Dot(input.Normal, ptLightDir)); float lightDistance = Vector3.Distance(pli.Position, input.Position_WorldSpace); intensity = Saturate(intensity * (1 - (lightDistance / pli.Range))); pointDiffuse += intensity * new Vector4(pli.Color, 1) * surfaceColor; // Specular Vector3 vertexToEye0 = Vector3.Normalize(CameraInfo.CameraPosition_WorldSpace - input.Position_WorldSpace); Vector3 lightReflect0 = Vector3.Normalize(Vector3.Reflect(ptLightDir, input.Normal)); float specularFactor0 = Vector3.Dot(vertexToEye0, lightReflect0); if (specularFactor0 > 0) { specularFactor0 = Pow(Abs(specularFactor0), MaterialProperties.SpecularPower); pointSpec += (1 - (lightDistance / pli.Range)) * (new Vector4(pli.Color * MaterialProperties.SpecularIntensity * specularFactor0, 1.0f)); } } return(Saturate(directionalSpecColor + directionalColor + pointSpec + pointDiffuse)); }