/// <summary> /// Lighting Main method for forward rendering. /// </summary> /// <param name="effectProps">The <see cref="ShaderEffectProps"/> which function as a basis to build the correct lighting method.</param> /// <returns></returns> public static string ForwardLighting(ShaderEffectProps effectProps) { string fragColorAlpha = effectProps.MatProbs.HasAlbedo ? $"{UniformNameDeclarations.AlbedoColor}.w" : "1.0"; var fragMainBody = new List <string> { $"vec4 result = vec4(0,0,0,0);", $"vec3 ambient = ambientLighting(0.2, {UniformNameDeclarations.AlbedoColor});", $"for(int i = 0; i < {LightingShard.NumberOfLightsForward};i++)", "{", "if(allLights[i].isActive == 0) continue;", "vec3 currentPosition = allLights[i].position;", "vec4 currentIntensities = allLights[i].intensities;", "vec3 currentConeDirection = allLights[i].direction;", "float currentAttenuation = allLights[i].maxDistance;", "float currentStrength = allLights[i].strength;", "float currentOuterConeAngle = allLights[i].outerConeAngle;", "float currentInnerConeAngle = allLights[i].innerConeAngle;", "int currentLightType = allLights[i].lightType; ", "result.rgb += ApplyLight(currentPosition, currentIntensities, currentConeDirection, ", "currentAttenuation, currentStrength, currentOuterConeAngle, currentInnerConeAngle, currentLightType);", "}", effectProps.MatProbs.HasAlbedoTexture ? $"oFragmentColor = vec4(ambient + result.rgb, mix({UniformNameDeclarations.AlbedoColor}.a, texture({UniformNameDeclarations.AlbedoTexture}, {VaryingNameDeclarations.TextureCoordinates}).a, {UniformNameDeclarations.AlbedoMix}));" : $"oFragmentColor = vec4(result.rgb + ambient, {UniformNameDeclarations.AlbedoColor}.a);", }; return(ShaderShardUtil.MainMethod(fragMainBody)); }
/// <summary> /// Creates the main method for the vertex shader, used in forward rendering. /// The naming of the out parameters is the same as in the <see cref="VertPropertiesShard"/>. /// </summary> /// <param name="effectProps">The <see cref="ShaderEffectProps"/> is the basis to decide, which calculations need to be made. E.g. do we have a weight map? If so, adjust the gl_Position.</param> /// <returns></returns> public static string VertexMain(ShaderEffectProps effectProps) { var vertMainBody = new List <string> { "gl_PointSize = 10.0;" }; if (effectProps.MeshProbs.HasNormals && effectProps.MeshProbs.HasWeightMap) { vertMainBody.Add("vec4 newVertex;"); vertMainBody.Add("vec4 newNormal;"); vertMainBody.Add( $"newVertex = ({UniformNameDeclarations.Bones}[int({UniformNameDeclarations.BoneIndex}.x)] * vec4({UniformNameDeclarations.Vertex}, 1.0) ) * {UniformNameDeclarations.BoneWeight}.x ;"); vertMainBody.Add( $"newNormal = ({UniformNameDeclarations.Bones}[int({UniformNameDeclarations.BoneIndex}.x)] * vec4({UniformNameDeclarations.Normal}, 0.0)) * {UniformNameDeclarations.BoneWeight}.x;"); vertMainBody.Add( $"newVertex = ({UniformNameDeclarations.Bones}[int({UniformNameDeclarations.BoneIndex}.y)] * vec4({UniformNameDeclarations.Vertex}, 1.0)) * {UniformNameDeclarations.BoneWeight}.y + newVertex;"); vertMainBody.Add( $"newNormal = ({UniformNameDeclarations.Bones}[int({UniformNameDeclarations.BoneIndex}.y)] * vec4({UniformNameDeclarations.Normal}, 0.0)) * {UniformNameDeclarations.BoneWeight}.y + newNormal;"); vertMainBody.Add( $"newVertex = ({UniformNameDeclarations.Bones}[int({UniformNameDeclarations.BoneIndex}.z)] * vec4({UniformNameDeclarations.Vertex}, 1.0)) * {UniformNameDeclarations.BoneWeight}.z + newVertex;"); vertMainBody.Add( $"newNormal = ({UniformNameDeclarations.Bones}[int({UniformNameDeclarations.BoneIndex}.z)] * vec4({UniformNameDeclarations.Normal}, 0.0)) * {UniformNameDeclarations.BoneWeight}.z + newNormal;"); vertMainBody.Add( $"newVertex = ({UniformNameDeclarations.Bones}[int({UniformNameDeclarations.BoneIndex}.w)] * vec4({UniformNameDeclarations.Vertex}, 1.0)) * {UniformNameDeclarations.BoneWeight}.w + newVertex;"); vertMainBody.Add( $"newNormal = ({UniformNameDeclarations.Bones}[int({UniformNameDeclarations.BoneIndex}.w)] * vec4({UniformNameDeclarations.Normal}, 0.0)) * {UniformNameDeclarations.BoneWeight}.w + newNormal;"); // At this point the normal is in World space - transform back to model space vertMainBody.Add($"{VaryingNameDeclarations.Normal} = mat3({UniformNameDeclarations.ITModelView}) * newNormal.xyz;"); } if (effectProps.MatProbs.HasSpecular) { vertMainBody.Add($"vec3 vCamPos = {UniformNameDeclarations.IModelView}[3].xyz;"); vertMainBody.Add(effectProps.MeshProbs.HasWeightMap ? $"{VaryingNameDeclarations.ViewDirection} = normalize({VaryingNameDeclarations.CameraPosition} - vec3(newVertex));" : $"{VaryingNameDeclarations.ViewDirection} = normalize({VaryingNameDeclarations.CameraPosition} - {UniformNameDeclarations.Vertex});"); } if (effectProps.MeshProbs.HasUVs) { vertMainBody.Add($"{VaryingNameDeclarations.TextureCoordinates} = fuUV;"); } if (effectProps.MeshProbs.HasNormals && !effectProps.MeshProbs.HasWeightMap) { vertMainBody.Add($"{VaryingNameDeclarations.Normal} = normalize(mat3({UniformNameDeclarations.ITModelView}) * {UniformNameDeclarations.Normal});"); } vertMainBody.Add($"{VaryingNameDeclarations.Position} = ({UniformNameDeclarations.ModelView} * vec4({UniformNameDeclarations.Vertex}, 1.0));"); if (effectProps.MeshProbs.HasTangents && effectProps.MeshProbs.HasBiTangents) { vertMainBody.Add($"{VaryingNameDeclarations.Tangent} = {UniformNameDeclarations.TangentAttribName};"); vertMainBody.Add($"{VaryingNameDeclarations.Bitangent} = {UniformNameDeclarations.BitangentAttribName};"); } vertMainBody.Add(effectProps.MeshProbs.HasWeightMap ? $"gl_Position = {UniformNameDeclarations.ModelViewProjection} * vec4(vec3(newVertex), 1.0);" : $"gl_Position = {UniformNameDeclarations.ModelViewProjection} * vec4({UniformNameDeclarations.Vertex}, 1.0);"); return(ShaderShardUtil.MainMethod(vertMainBody)); }
/// <summary> /// Wraps all the lighting methods into a single one. For deferred rendering, this equals the "main" method. /// </summary> public static string ApplyLightDeferred(Light lc, bool isCascaded = false, int numberOfCascades = 0, bool debugCascades = false) { var methodBody = new List <string> { $"vec3 normal = texture({UniformNameDeclarations.DeferredRenderTextures[(int)RenderTargetTextureTypes.Normal]}, {VaryingNameDeclarations.TextureCoordinates}).rgb;" }; //Do not do calculations for the background - is there a smarter way (stencil buffer)? //--------------------------------------- methodBody.AddRange( new List <string>() { "if(normal.x == 0.0 && normal.y == 0.0 && normal.z == 0.0)", "{" }); methodBody.Add($" {FragPropertiesShard.OutColorName} = {UniformNameDeclarations.BackgroundColor};"); methodBody.Add(@" return;"); methodBody.Add("}"); methodBody.Add($"vec4 fragPos = texture({UniformNameDeclarations.DeferredRenderTextures[(int)RenderTargetTextureTypes.Position]}, {VaryingNameDeclarations.TextureCoordinates});"); methodBody.Add($"vec4 diffuseColor = texture({UniformNameDeclarations.DeferredRenderTextures[(int)RenderTargetTextureTypes.Albedo]}, {VaryingNameDeclarations.TextureCoordinates}).rgba;"); methodBody.Add($"vec3 occlusion = texture({UniformNameDeclarations.DeferredRenderTextures[(int)RenderTargetTextureTypes.Ssao]}, {VaryingNameDeclarations.TextureCoordinates}).rgb;"); methodBody.Add($"vec3 specularVars = texture({UniformNameDeclarations.DeferredRenderTextures[(int)RenderTargetTextureTypes.Specular]}, {VaryingNameDeclarations.TextureCoordinates}).rgb;"); //Lighting calculation //------------------------- methodBody.AddRange(new List <string>() { "// then calculate lighting as usual", "vec3 lighting = vec3(0,0,0);", "", $"if({UniformNameDeclarations.RenderPassNo} == 0)", "{", " vec3 ambient = ambientLighting(0.2, diffuseColor).xyz;", "", $" if({UniformNameDeclarations.SsaoOn} == 1)", " ambient *= occlusion;", " lighting += ambient;", "}", "", "if(light.isActive == 1)", "{", " float shadow = 0.0;", "", " vec3 lightColor = light.intensities.xyz;", " vec3 lightPosition = light.position;", " vec3 lightDir = normalize(lightPosition - fragPos.xyz);", "", " //attenuation", " float attenuation = 1.0;", "switch (light.lightType)", "{", " //Point", " case 0:", " {", " attenuation = attenuationPointComponent(fragPos.xyz, lightPosition, light.maxDistance);", " break;", " }", " //Parallel", " case 1:", " lightDir = -light.direction;", " break;", " //Spot", " case 2:", " {", " attenuation = attenuationPointComponent(fragPos.xyz, lightPosition, light.maxDistance) * attenuationConeComponent(light.direction, lightDir, light.innerConeAngle, light.outerConeAngle);", " break;", " }", " case 3:", " lightDir = -light.direction;", " break;", "}" }); if (lc.IsCastingShadows) { methodBody.Add(GetShadow(lc, isCascaded, numberOfCascades)); } // diffuse methodBody.AddRange( new List <string>() { "vec3 diffuse = diffuseLighting(normal, lightDir) * diffuseColor.xyz * lightColor;", "lighting += (1.0 - shadow) * (diffuse * attenuation * light.strength);" }); // specular methodBody.AddRange( new List <string>() { "vec3 viewDir = normalize(-fragPos.xyz);", "float shininess = specularVars.r * 256.0;", "float specularStrength = specularVars.g;", "", "float specularTerm = specularLighting(normal, lightDir, viewDir, shininess);", "", "vec3 specular = specularStrength * specularTerm * lightColor;", "lighting += (1.0 - shadow) * (specular * attenuation * light.strength);" }); if (isCascaded && debugCascades) { methodBody.Add(ColorDebugCascades()); } methodBody.Add("}"); methodBody.Add($"{FragPropertiesShard.OutColorName} = vec4(lighting, 1.0);"); return(ShaderShardUtil.MainMethod(methodBody)); }
/// <summary> /// The main method for rendering into a G-Buffer object. /// </summary> /// <param name="effectProps">The ShaderEffectProps.</param> /// <returns></returns> public static string RenderToGBuffer(ShaderEffectProps effectProps) { var fragMainBody = new List <string>(); var ssaoString = "Ssao"; for (int i = 0; i < UniformNameDeclarations.DeferredRenderTextures.Count; i++) { var texName = UniformNameDeclarations.DeferredRenderTextures[i]; if (texName == ssaoString) { continue; } switch (i) { case (int)RenderTargetTextureTypes.Position: fragMainBody.Add($"{texName} = vec4({VaryingNameDeclarations.Position});"); break; case (int)RenderTargetTextureTypes.Albedo: if (effectProps.MatProbs.HasAlbedoTexture) { fragMainBody.Add($"{texName} = vec4(mix({UniformNameDeclarations.AlbedoColor}.xyz, texture({UniformNameDeclarations.AlbedoTexture}, {VaryingNameDeclarations.TextureCoordinates}).xyz, {UniformNameDeclarations.AlbedoMix}), 1.0);"); } else { fragMainBody.Add($"{texName} = vec4({UniformNameDeclarations.AlbedoColor}.xyz, 1.0);"); } break; case (int)RenderTargetTextureTypes.Normal: fragMainBody.Add($"{texName} = vec4(normalize({VaryingNameDeclarations.Normal}.xyz), 1.0);"); break; case (int)RenderTargetTextureTypes.Depth: fragMainBody.Add($"{texName} = vec4(gl_FragCoord.z, gl_FragCoord.z, gl_FragCoord.z, 1.0);"); break; case (int)RenderTargetTextureTypes.Specular: { if (effectProps.MatProbs.HasSpecular) { if (effectProps.MatType == MaterialType.MaterialPbr) { fragMainBody.Add($"{texName} = vec4({UniformNameDeclarations.RoughnessValue}, {UniformNameDeclarations.FresnelReflectance}, {UniformNameDeclarations.DiffuseFraction}, 1.0);"); } else if (effectProps.MatType == MaterialType.Standard) { fragMainBody.Add($"{texName} = vec4({UniformNameDeclarations.SpecularIntensity}, {UniformNameDeclarations.SpecularShininess}/256.0, 1.0, 1.0);"); } } else { fragMainBody.Add($"{texName} = vec4(0.0, 0.0, 1.0, 1.0);"); } break; } } } return(ShaderShardUtil.MainMethod(fragMainBody)); }