/// <summary> /// Returns the pre defined Fusee uniform parameters of a vertex shader, depending on the given ShaderEffectProps. /// </summary> /// <param name="effectProps">The ShaderEffectProps.</param> /// <returns></returns> public static string FuseeUniforms(ShaderEffectProps effectProps) { var uniforms = new List <string> { GLSL.CreateUniform(GLSL.Type.Mat4, UniformNameDeclarations.ModelView), GLSL.CreateUniform(GLSL.Type.Mat4, UniformNameDeclarations.ModelViewProjection) }; if (effectProps.MeshProbs.HasNormals) { uniforms.Add(GLSL.CreateUniform(GLSL.Type.Mat4, UniformNameDeclarations.ITModelView)); } if (effectProps.MatProbs.HasSpecular && !effectProps.MeshProbs.HasWeightMap) { uniforms.Add(GLSL.CreateUniform(GLSL.Type.Mat4, UniformNameDeclarations.IModelView)); } if (effectProps.MeshProbs.HasWeightMap) { uniforms.Add(GLSL.CreateUniform(GLSL.Type.Mat4, UniformNameDeclarations.View)); uniforms.Add(GLSL.CreateUniform(GLSL.Type.Mat4, UniformNameDeclarations.Projection)); uniforms.Add(GLSL.CreateUniform(GLSL.Type.Mat4, UniformNameDeclarations.IModelView)); uniforms.Add(GLSL.CreateUniform(GLSL.Type.Mat4, UniformNameDeclarations.Bones + "[" + HeaderShard.BoneDefineVar + "]")); } return(string.Join("\n", uniforms)); }
/// <summary> /// Returns the in parameters for a ShaderEffect, depending on the given ShaderEffectProps. /// </summary> /// <param name="effectProps">The ShaderEffectProps.</param> /// <returns></returns> public static string InParams(ShaderEffectProps effectProps) { var pxIn = new List <string> { GLSL.CreateIn(GLSL.Type.Vec3, VaryingNameDeclarations.ViewDirection), GLSL.CreateIn(GLSL.Type.Vec4, VaryingNameDeclarations.Position), GLSL.CreateIn(GLSL.Type.Vec3, VaryingNameDeclarations.CameraPosition) }; if (effectProps.MeshProbs.HasColors) { pxIn.Add(GLSL.CreateIn(GLSL.Type.Vec3, VaryingNameDeclarations.Color)); } if (effectProps.MeshProbs.HasNormals) { pxIn.Add(GLSL.CreateIn(GLSL.Type.Vec3, VaryingNameDeclarations.Normal)); } if (effectProps.MeshProbs.HasTangents && effectProps.MeshProbs.HasBiTangents) { pxIn.Add(GLSL.CreateIn(GLSL.Type.Vec4, VaryingNameDeclarations.Tangent)); pxIn.Add(GLSL.CreateIn(GLSL.Type.Vec3, VaryingNameDeclarations.Bitangent)); } if (effectProps.MeshProbs.HasUVs) { pxIn.Add(GLSL.CreateIn(GLSL.Type.Vec2, VaryingNameDeclarations.TextureCoordinates)); } return(string.Join("\n", pxIn)); }
internal IEnumerable <ASLShaderVariable> GetOutputs() { foreach (var field in _shader.Fields) { if (field.HasCustomAttributes) { var attrs = field.CustomAttributes.Where(a => a.AttributeType.IsOut() && !a.AttributeType.IsBuiltIn()); if (attrs.Count() > 0) { var attr = attrs.First(); var type = GLSL.ToGLSL(field.FieldType); var isArray = field.FieldType.IsArray; var arrayAttr = field.CustomAttributes.Where(a => a.AttributeType.Is <ArraySizeAttribute>()); var arraySize = (isArray && arrayAttr.Count() > 0 && arrayAttr.First().HasConstructorArguments) ? arrayAttr.First().ConstructorArguments.First().Value.ToString() : string.Empty; var name = field.Name; var commentAttr = field.CustomAttributes.Where(a => a.AttributeType.Is <CommentAttribute>()); var u_comment = (commentAttr.Count() > 0 && commentAttr.First().HasConstructorArguments) ? commentAttr.First().ConstructorArguments.First().Value.ToString() : string.Empty; var d_comment = DebugMode ? field.DeclaringType.FullName + "." + field.Name : string.Empty; var layoutAttr = (this is FragmentShader) ? field.CustomAttributes.Where(a => a.AttributeType.Is <FragmentShader.LayoutAttribute>()) : ((this is GeometryShader) ? field.CustomAttributes.Where(a => a.AttributeType.Is <GeometryShader.LayoutAttribute>()) : null); var layout = (layoutAttr != null && layoutAttr.Count() > 0) ? layoutAttr.First() : null; yield return(new ASLShaderVariable(type, isArray, arraySize, name, u_comment, d_comment, attr.AttributeType, layout)); } } } }
/// <summary> /// Method for calculation the ambient lighting component. /// </summary> public static string AmbientComponent() { var methodBody = new List <string> { $"return vec3(color.xyz * ambientCoefficient);" }; return(GLSL.CreateMethod(GLSL.Type.Vec3, "ambientLighting", new[] { GLSL.CreateVar(GLSL.Type.Float, "ambientCoefficient"), GLSL.CreateVar(GLSL.Type.Vec4, "color") }, methodBody)); }
public static string ToGLSLParamType(ParameterDefinition p) { var t = GLSL.ToGLSL(p.ParameterType.Resolve()); if (p.ParameterType.IsByReference) { return((p.IsOut ? "out " : "inout ") + t); } return(t); }
/// <summary> /// Calculates the attenuation of a point light. /// </summary> /// <returns></returns> public static string AttenuationPointComponent() { var methodBody = new List <string> { $"float distanceToLight = length(lightPos - fragPos);", "float distance = pow(distanceToLight / lightMaxDistance, 2.0);", "return (clamp(1.0 - pow(distance, 2.0), 0.0, 1.0)) / (pow(distance, 2.0) + 1.0);", }; return(GLSL.CreateMethod(GLSL.Type.Float, "attenuationPointComponent", new[] { GLSL.CreateVar(GLSL.Type.Vec3, "fragPos"), GLSL.CreateVar(GLSL.Type.Vec3, "lightPos"), GLSL.CreateVar(GLSL.Type.Float, "lightMaxDistance") }, methodBody)); }
//TODO: At the moment Blender's Principled BSDF material gets translated into a MaterialPBR and internally uses this lighting method for the specular component. //This is not the same lighting method as is used in Blender and will therefor only produce approximately visually correct results. /// <summary> /// Method for calculation the specular lighting component. /// Replaces the standard specular calculation with the Cook-Torrance-Shader /// </summary> public static string PbrSpecularComponent() { var methodBody = new List <string> { $"float roughnessValue = {UniformNameDeclarations.RoughnessValue}; // 0 : smooth, 1: rough", // roughness $"float F0 = {UniformNameDeclarations.FresnelReflectance}; // fresnel reflectance at normal incidence", // fresnel => Specular from Blender "float NdotL = max(dot(N, L), 0.0);", "float specular = 0.0;", "float BlinnSpecular = 0.0;", "", "if(dot(N, L) > 0.0)", "{", " // calculate intermediary values", " vec3 H = normalize(L + V);", " float NdotH = max(dot(N, H), 0.0); ", " float NdotV = max(dot(N, L), 0.0); // note: this is NdotL, which is the same value", " float VdotH = max(dot(V, H), 0.0);", " float mSquared = roughnessValue * roughnessValue;", "", "", "", "", " // -- geometric attenuation", " //[Schlick's approximation of Smith's shadow equation]", " float k= roughnessValue * sqrt(0.5 * 3.14159265);", " float one_minus_k= 1.0 - k;", " float geoAtt = ( NdotL / (NdotL * one_minus_k + k) ) * ( NdotV / (NdotV * one_minus_k + k) );", "", " // -- roughness (or: microfacet distribution function)", " // Trowbridge-Reitz or GGX, GTR2", " float a2 = mSquared * mSquared;", " float d = (NdotH * a2 - NdotH) * NdotH + 1.0;", " float roughness = a2 / (3.14 * d * d);", "", " // -- fresnel", " // [Schlick 1994, An Inexpensive BRDF Model for Physically-Based Rendering]", " float fresnel = pow(1.0 - VdotH, 5.0);", $" fresnel = clamp((50.0 * {UniformNameDeclarations.SpecularColor}.y), 0.0, 1.0) * fresnel + (1.0 - fresnel);", "", $" specular = (fresnel * geoAtt * roughness) / (NdotV * NdotL * 3.14);", " ", "}", "", $"return (k + specular * (1.0-k));" }; return(GLSL.CreateMethod(GLSL.Type.Float, "specularLighting", new[] { GLSL.CreateVar(GLSL.Type.Vec3, "N"), GLSL.CreateVar(GLSL.Type.Vec3, "L"), GLSL.CreateVar(GLSL.Type.Vec3, "V"), GLSL.CreateVar(GLSL.Type.Float, "k") }, methodBody)); }
/// <summary> /// Returns all uniforms, as they are given in the <see cref="MaterialProps"/> object. /// </summary> /// <param name="effectProps">The ShaderEffectProps.</param> /// <returns></returns> public static string MaterialPropsUniforms(ShaderEffectProps effectProps) { var matPropUnifroms = new List <string>(); if (effectProps.MatProbs.HasSpecular) { matPropUnifroms.Add(GLSL.CreateUniform(GLSL.Type.Vec4, UniformNameDeclarations.SpecularColor)); if (effectProps.MatType == MaterialType.MaterialPbr) { matPropUnifroms.Add(GLSL.CreateUniform(GLSL.Type.Float, UniformNameDeclarations.RoughnessValue)); matPropUnifroms.Add(GLSL.CreateUniform(GLSL.Type.Float, UniformNameDeclarations.FresnelReflectance)); matPropUnifroms.Add(GLSL.CreateUniform(GLSL.Type.Float, UniformNameDeclarations.DiffuseFraction)); } else if (effectProps.MatType == MaterialType.Standard) { matPropUnifroms.Add(GLSL.CreateUniform(GLSL.Type.Float, UniformNameDeclarations.SpecularShininess)); matPropUnifroms.Add(GLSL.CreateUniform(GLSL.Type.Float, UniformNameDeclarations.SpecularIntensity)); } } if (effectProps.MatProbs.HasAlbedo) { matPropUnifroms.Add(GLSL.CreateUniform(GLSL.Type.Vec4, UniformNameDeclarations.AlbedoColor)); } if (effectProps.MatProbs.HasEmissive) { matPropUnifroms.Add(GLSL.CreateUniform(GLSL.Type.Vec4, UniformNameDeclarations.EmissiveColor)); } //Textures if (effectProps.MatProbs.HasNormalMap) { matPropUnifroms.Add(GLSL.CreateUniform(GLSL.Type.Sampler2D, UniformNameDeclarations.NormalMap)); matPropUnifroms.Add(GLSL.CreateUniform(GLSL.Type.Float, UniformNameDeclarations.NormalMapIntensity)); } if (effectProps.MatProbs.HasAlbedoTexture) { matPropUnifroms.Add(GLSL.CreateUniform(GLSL.Type.Sampler2D, UniformNameDeclarations.AlbedoTexture)); matPropUnifroms.Add(GLSL.CreateUniform(GLSL.Type.Float, UniformNameDeclarations.AlbedoMix)); } if (effectProps.MatProbs.HasEmissiveTexture) { matPropUnifroms.Add(GLSL.CreateUniform(GLSL.Type.Sampler2D, UniformNameDeclarations.EmissiveTexture)); matPropUnifroms.Add(GLSL.CreateUniform(GLSL.Type.Float, UniformNameDeclarations.EmissiveMix)); } return(string.Join("\n", matPropUnifroms)); }
internal static string GetSignature(MethodDefinition m) { var arraySize = string.Empty; if (m.ReturnType.IsArray && m.MethodReturnType.HasCustomAttributes) { var attr = m.MethodReturnType.CustomAttributes.Where(a => a.AttributeType.Is <ArraySizeAttribute>()).First(); arraySize = attr.ConstructorArguments.First().Value.ToString(); } return(GLSL.ToGLSL(m.ReturnType) + (m.ReturnType.IsArray ? "[" + arraySize + "]" : string.Empty) + " " + m.Name + "(" + GetParameterString(m) + ")"); }
/// <summary> /// Method for calculation the diffuse lighting component. /// </summary> public static string DiffuseComponent() { var methodBody = new List <string> { "return max(dot(N, L), 0.0);" }; return(GLSL.CreateMethod(GLSL.Type.Float, "diffuseLighting", new[] { GLSL.CreateVar(GLSL.Type.Vec3, "N"), GLSL.CreateVar(GLSL.Type.Vec3, "L") }, methodBody)); }
/// <summary> /// Creates the method for calculating whether a fragment is in shadow or not, by using a shadow map (sampler2DCube). /// The cube map is used when calculating the shadows for a point light. /// </summary> /// <returns></returns> public static string ShadowCalculationCubeMap() { var methodBody = new List <string>() { "float pcfKernelSize = pcfKernelHalfSize + pcfKernelHalfSize + 1.0;", "pcfKernelSize *= pcfKernelSize;", "vec3 sampleOffsetDirections[20] = vec3[]", "(", " vec3(pcfKernelHalfSize, pcfKernelHalfSize, pcfKernelHalfSize), vec3(pcfKernelHalfSize, -pcfKernelHalfSize, pcfKernelHalfSize), vec3(-pcfKernelHalfSize, -pcfKernelHalfSize, pcfKernelHalfSize), vec3(-pcfKernelHalfSize, pcfKernelHalfSize, pcfKernelHalfSize),", " vec3(pcfKernelHalfSize, pcfKernelHalfSize, -pcfKernelHalfSize), vec3(pcfKernelHalfSize, -pcfKernelHalfSize, -pcfKernelHalfSize), vec3(-pcfKernelHalfSize, -pcfKernelHalfSize, -pcfKernelHalfSize), vec3(-pcfKernelHalfSize, pcfKernelHalfSize, -pcfKernelHalfSize),", " vec3(pcfKernelHalfSize, pcfKernelHalfSize, 0), vec3(pcfKernelHalfSize, -pcfKernelHalfSize, 0), vec3(-pcfKernelHalfSize, -pcfKernelHalfSize, 0), vec3(-pcfKernelHalfSize, pcfKernelHalfSize, 0),", " vec3(pcfKernelHalfSize, 0, pcfKernelHalfSize), vec3(-pcfKernelHalfSize, 0, pcfKernelHalfSize), vec3(pcfKernelHalfSize, 0, -pcfKernelHalfSize), vec3(-pcfKernelHalfSize, 0, -pcfKernelHalfSize),", " vec3(0, pcfKernelHalfSize, pcfKernelHalfSize), vec3(0, -pcfKernelHalfSize, pcfKernelHalfSize), vec3(0, -pcfKernelHalfSize, -pcfKernelHalfSize), vec3(0, pcfKernelHalfSize, -pcfKernelHalfSize)", ");", "// get vector between fragment position and light position", "vec3 fragToLight = (fragPos - lightPos) * -1.0;", "// now get current linear depth as the length between the fragment and light position", "float currentDepth = length(fragToLight);", "float shadow = 0.0;", "float thisBias = max(bias * (1.0 - dot(normal, lightDir)), bias * 0.01);//0.15;", "int samples = 20;", $"vec3 camPos = {UniformNameDeclarations.IView}[3].xyz;", "float viewDistance = length(camPos - fragPos);", "float diskRadius = 0.5; //(1.0 + (viewDistance / farPlane)) / pcfKernelSize;", "for (int i = 0; i < samples; ++i)", "{", " float closestDepth = texture(shadowMap, fragToLight + sampleOffsetDirections[i] * diskRadius).r;", " closestDepth *= farPlane; // Undo mapping [0;1]", " if (currentDepth - thisBias > closestDepth)", " shadow += 1.0;", "}", "shadow /= float(samples);", "return shadow;" }; return(GLSL.CreateMethod(GLSL.Type.Float, "ShadowCalculationCubeMap", new[] { GLSL.CreateVar(GLSL.Type.SamplerCube, "shadowMap"), GLSL.CreateVar(GLSL.Type.Vec3, "fragPos"), GLSL.CreateVar(GLSL.Type.Vec3, "lightPos"), GLSL.CreateVar(GLSL.Type.Float, "farPlane"), GLSL.CreateVar(GLSL.Type.Vec3, "normal"), GLSL.CreateVar(GLSL.Type.Vec3, "lightDir"), GLSL.CreateVar(GLSL.Type.Float, "bias"), GLSL.CreateVar(GLSL.Type.Float, "pcfKernelHalfSize") }, methodBody)); }
/// <summary> /// Creates the in (with prefix "fu") and out parameters of the vertex shader, depending on the given ShaderEffectProps. /// </summary> /// <param name="effectProps">>The ShaderEffectProps.</param> /// <returns></returns> public static string InAndOutParams(ShaderEffectProps effectProps) { var vertProps = new List <string> { GLSL.CreateOut(GLSL.Type.Vec3, VaryingNameDeclarations.CameraPosition), GLSL.CreateOut(GLSL.Type.Vec4, VaryingNameDeclarations.Position) }; vertProps.Add(GLSL.CreateIn(GLSL.Type.Vec3, UniformNameDeclarations.Vertex)); if (effectProps.MeshProbs.HasTangents && effectProps.MeshProbs.HasBiTangents) { vertProps.Add(GLSL.CreateIn(GLSL.Type.Vec4, UniformNameDeclarations.TangentAttribName)); vertProps.Add(GLSL.CreateIn(GLSL.Type.Vec3, UniformNameDeclarations.BitangentAttribName)); vertProps.Add(GLSL.CreateOut(GLSL.Type.Vec4, VaryingNameDeclarations.Tangent)); vertProps.Add(GLSL.CreateOut(GLSL.Type.Vec3, VaryingNameDeclarations.Bitangent)); } if (effectProps.MatProbs.HasSpecular) { vertProps.Add(GLSL.CreateOut(GLSL.Type.Vec3, VaryingNameDeclarations.ViewDirection)); } if (effectProps.MeshProbs.HasWeightMap) { vertProps.Add(GLSL.CreateIn(GLSL.Type.Vec4, UniformNameDeclarations.BoneIndex)); vertProps.Add(GLSL.CreateIn(GLSL.Type.Vec4, UniformNameDeclarations.BoneWeight)); } if (effectProps.MeshProbs.HasNormals) { vertProps.Add(GLSL.CreateIn(GLSL.Type.Vec3, UniformNameDeclarations.Normal)); vertProps.Add(GLSL.CreateOut(GLSL.Type.Vec3, VaryingNameDeclarations.Normal)); } if (effectProps.MeshProbs.HasUVs) { vertProps.Add(GLSL.CreateIn(GLSL.Type.Vec2, UniformNameDeclarations.TextureCoordinates)); vertProps.Add(GLSL.CreateOut(GLSL.Type.Vec2, VaryingNameDeclarations.TextureCoordinates)); } if (effectProps.MeshProbs.HasColors) { vertProps.Add(GLSL.CreateIn(GLSL.Type.Vec4, UniformNameDeclarations.Color)); vertProps.Add(GLSL.CreateOut(GLSL.Type.Vec4, VaryingNameDeclarations.Color)); } return(string.Join("\n", vertProps)); }
/// <summary> /// Creates the uniform texture parameters for the lighting pass, as used in deferred rendering. /// </summary> /// <returns></returns> public static string DeferredTextureUniforms() { var uniforms = new List <string>(); var texCount = 0; for (var i = 0; i < UniformNameDeclarations.DeferredRenderTextures.Count; i++) { var texName = UniformNameDeclarations.DeferredRenderTextures[i]; uniforms.Add(GLSL.CreateUniform(GLSL.Type.Sampler2D, texName)); texCount++; } return(string.Join("\n", uniforms)); }
/// <summary> /// Returns the pre defined Fusee uniform parameters of a fragment shader, depending on the given ShaderEffectProps. /// </summary> /// <returns></returns> public static string FuseeMatrixUniforms() { var pxFusUniforms = new List <string> { GLSL.CreateUniform(GLSL.Type.Mat4, UniformNameDeclarations.ModelView), GLSL.CreateUniform(GLSL.Type.Mat4, UniformNameDeclarations.IModelView), GLSL.CreateUniform(GLSL.Type.Mat4, UniformNameDeclarations.ITView), GLSL.CreateUniform(GLSL.Type.Mat4, UniformNameDeclarations.IView), GLSL.CreateUniform(GLSL.Type.Mat4, UniformNameDeclarations.View), GLSL.CreateUniform(GLSL.Type.Mat4, UniformNameDeclarations.ITModelView) }; return(string.Join("\n", pxFusUniforms)); }
/// <summary> /// Calculates the cone component of the attenuation of a spot light. /// </summary> /// <returns></returns> public static string AttenuationConeComponent() { var methodBody = new List <string> { "vec3 coneDir = lightDir;", "float lightToSurfaceAngleCos = dot(coneDir, -fragToLightDir);", "float epsilon = cos(innerConeAngle) - cos(outerConeAngle);", "float t = (lightToSurfaceAngleCos - cos(outerConeAngle)) / epsilon;", "return clamp(t, 0.0, 1.0);" }; return(GLSL.CreateMethod(GLSL.Type.Float, "attenuationConeComponent", new[] { GLSL.CreateVar(GLSL.Type.Vec3, "lightDir"), GLSL.CreateVar(GLSL.Type.Vec3, "fragToLightDir"), GLSL.CreateVar(GLSL.Type.Float, "innerConeAngle"), GLSL.CreateVar(GLSL.Type.Float, "outerConeAngle") }, methodBody)); }
/// <summary> /// Creates the method for calculating whether a fragment is in shadow or not, by using a shadow map (sampler2D). /// </summary> /// <returns></returns> public static string ShadowCalculation() { var methodBody = new List <string>() { "float shadow = 0.0;", "int pcfLoop = int(pcfKernelHalfSize);", "float pcfKernelSize = pcfKernelHalfSize + pcfKernelHalfSize + 1.0;", "pcfKernelSize *= pcfKernelSize;", "// perform perspective divide", "vec4 projCoords = fragPosLightSpace / fragPosLightSpace.w;", "projCoords = projCoords * 0.5 + 0.5;", "//float closestDepth = texture(shadowMap, projCoords.xy).r;", "float currentDepth = projCoords.z;", "float thisBias = max(bias * (1.0 - dot(normal, lightDir)), bias / 100.0);", "vec2 texelSize = 1.0 / vec2(textureSize(shadowMap, 0));", "//use this for using sampler2DShadow (automatic PCF) instead of sampler2D", "//float depth = texture(shadowMap, projCoords.xyz).r;", "//shadow += (currentDepth - thisBias) > depth ? 1.0 : 0.0;", "for (int x = -pcfLoop; x <= pcfLoop; ++x)", "{", "for (int y = -pcfLoop; y <= pcfLoop; ++y)", "{", "float pcfDepth = texture(shadowMap, projCoords.xy + vec2(x, y) * texelSize).r;", "shadow += (currentDepth - thisBias) > pcfDepth ? 1.0 : 0.0;", "}", "}", "shadow /= pcfKernelSize;", "return shadow;" }; return(GLSL.CreateMethod(GLSL.Type.Float, "ShadowCalculation", new[] { GLSL.CreateVar(GLSL.Type.Sampler2D, "shadowMap"), GLSL.CreateVar(GLSL.Type.Vec4, "fragPosLightSpace"), GLSL.CreateVar(GLSL.Type.Vec3, "normal"), GLSL.CreateVar(GLSL.Type.Vec3, "lightDir"), GLSL.CreateVar(GLSL.Type.Float, "bias"), GLSL.CreateVar(GLSL.Type.Float, "pcfKernelHalfSize") }, methodBody)); }
private static string CreateDeferredLightingPixelShader(Light lc, bool isCascaded = false, int numberOfCascades = 0, bool debugCascades = false) { var frag = new StringBuilder(); frag.Append(HeaderShard.Version300Es); frag.Append("#extension GL_ARB_explicit_uniform_location : enable\n"); frag.Append("#extension GL_ARB_gpu_shader5 : enable\n"); frag.Append(HeaderShard.EsPrecisionHighpFloat); frag.Append(FragPropertiesShard.DeferredTextureUniforms()); frag.Append(FragPropertiesShard.FuseeMatrixUniforms()); frag.Append(LightingShard.LightStructDeclaration); frag.Append(FragPropertiesShard.DeferredLightAndShadowUniforms(lc, isCascaded, numberOfCascades)); frag.Append(GLSL.CreateIn(GLSL.Type.Vec2, VaryingNameDeclarations.TextureCoordinates)); frag.Append(FragPropertiesShard.ColorOut()); //Shadow calculation methods //-------------------------------------- if (lc.Type != LightType.Point) { frag.Append(LightingShard.ShadowCalculation()); } else { frag.Append(LightingShard.ShadowCalculationCubeMap()); } //Lighting methods //------------------------------------------ frag.Append(LightingShard.AmbientComponent()); frag.Append(LightingShard.SpecularComponent()); frag.Append(LightingShard.DiffuseComponent()); frag.Append(LightingShard.AttenuationPointComponent()); frag.Append(LightingShard.AttenuationConeComponent()); frag.Append(LightingShard.ApplyLightDeferred(lc, isCascaded, numberOfCascades, debugCascades)); return(frag.ToString()); }
/// <summary> /// Method for calculation the specular lighting component. /// </summary> public static string SpecularComponent() { var methodBody = new List <string> { "float specularTerm = 0.0;", "if(dot(N, L) > 0.0)", "{", " // half vector", "vec3 reflectDir = reflect(-L, N);", $" specularTerm = pow(max(0.0, dot(V, reflectDir)), shininess);", "}", "return specularTerm;" }; return(GLSL.CreateMethod(GLSL.Type.Float, "specularLighting", new[] { GLSL.CreateVar(GLSL.Type.Vec3, "N"), GLSL.CreateVar(GLSL.Type.Vec3, "L"), GLSL.CreateVar(GLSL.Type.Vec3, "V"), GLSL.CreateVar(GLSL.Type.Float, "shininess") }, methodBody)); }
/// <summary> /// Creates the uniforms for the deferred lighting pass for one light. /// </summary> /// <param name="lc">The light component, needed to decide if we have a Shadow Cube Map or a standard shadow map.</param> /// <param name="isCascaded">If cascaded shadow mapping is used, this should be set to true.</param> /// <param name="numberOfCascades">If cascaded shadow mapping is used this is the number of cascades.</param> public static string DeferredLightAndShadowUniforms(Light lc, bool isCascaded, int numberOfCascades) { var uniforms = new List <string> { "uniform Light light;" }; if (!isCascaded) { if (lc.IsCastingShadows) { if (lc.Type != LightType.Point) { uniforms.Add(GLSL.CreateUniform(GLSL.Type.Sampler2D, UniformNameDeclarations.ShadowMap)); } else { uniforms.Add(GLSL.CreateUniform(GLSL.Type.SamplerCube, UniformNameDeclarations.ShadowCubeMap)); } } uniforms.Add(GLSL.CreateUniform(GLSL.Type.Mat4, UniformNameDeclarations.LightSpaceMatrix)); } else { //No implementation for GLSL.CreateArrayUniform yet... uniforms.Add($"uniform {GLSL.DecodeType(GLSL.Type.Sampler2D)}[{numberOfCascades}] ShadowMaps;\n"); uniforms.Add($"uniform {GLSL.DecodeType(GLSL.Type.Vec2)}[{numberOfCascades}] ClipPlanes;\n"); uniforms.Add($"uniform {GLSL.DecodeType(GLSL.Type.Mat4)}[{numberOfCascades}] LightSpaceMatrices;\n"); } uniforms.Add(GLSL.CreateUniform(GLSL.Type.Int, UniformNameDeclarations.RenderPassNo)); uniforms.Add(GLSL.CreateUniform(GLSL.Type.Int, UniformNameDeclarations.SsaoOn)); uniforms.Add(GLSL.CreateUniform(GLSL.Type.Vec4, UniformNameDeclarations.BackgroundColor)); return(string.Join("\n", uniforms)); }
public static void ValidateType(TypeReference t) { GLSL.ToGLSL(t); // throws if t is not valid }
/// <summary> /// Creates a single color (vec4) out parameter. /// </summary> public static string ColorOut() { return(GLSL.CreateOut(GLSL.Type.Vec4, OutColorName)); }
/// <summary> /// Wraps all the lighting methods into a single one. /// </summary> public static string ApplyLightForward(ShaderEffectProps effectProps) { var bumpNormals = new List <string> { "///////////////// Normal mapping, tangent space ///////////////////", $"vec3 N = ((texture({UniformNameDeclarations.NormalMap}, {VaryingNameDeclarations.TextureCoordinates}).rgb * 2.0) - 1.0f) * vec3({UniformNameDeclarations.NormalMapIntensity}, {UniformNameDeclarations.NormalMapIntensity}, 1.0);", $"N = (N.x * vec3({VaryingNameDeclarations.Tangent})) + (N.y * {VaryingNameDeclarations.Bitangent}) + (N.z * {VaryingNameDeclarations.Normal});", "N = normalize(N);" }; var normals = new List <string> { $"vec3 N = normalize({VaryingNameDeclarations.Normal});" }; var fragToLightDirAndLightInit = new List <string> { "vec3 L = vec3(0.0, 0.0, 0.0);", "if(lightType == 1){L = -normalize(direction);}", "else", "{", $" L = normalize(position - {VaryingNameDeclarations.Position}.xyz);", "}", $"vec3 V = normalize(-{VaryingNameDeclarations.Position}.xyz);", "if(lightType == 3) {", " L = normalize(vec3(0.0,0.0,-1.0));", "}", $"vec2 o_texcoords = {VaryingNameDeclarations.TextureCoordinates};", "", "vec3 Idif = vec3(0);", "vec3 Ispe = vec3(0);", "" }; var applyLightParams = new List <string>(); applyLightParams.AddRange(effectProps.MatProbs.HasNormalMap ? bumpNormals : normals); applyLightParams.AddRange(fragToLightDirAndLightInit); if (effectProps.MatProbs.HasAlbedo) { //TODO: Test alpha blending between diffuse and texture if (effectProps.MatProbs.HasAlbedoTexture) { applyLightParams.Add( $"vec3 blendedCol = mix({UniformNameDeclarations.AlbedoColor}.rgb, texture({UniformNameDeclarations.AlbedoTexture}, {VaryingNameDeclarations.TextureCoordinates}).rgb, {UniformNameDeclarations.AlbedoMix});" + $"Idif = blendedCol * diffuseLighting(N, L) * intensities.rgb;"); } else { applyLightParams.Add($"Idif = vec3({UniformNameDeclarations.AlbedoColor}.rgb * intensities.rgb * diffuseLighting(N, L));"); } } if (effectProps.MatProbs.HasSpecular) { if (effectProps.MatType == MaterialType.Standard) { applyLightParams.Add($"float specularTerm = specularLighting(N, L, V, {UniformNameDeclarations.SpecularShininess});"); applyLightParams.Add($"Ispe = vec3(({ UniformNameDeclarations.SpecularColor}.rgb * { UniformNameDeclarations.SpecularIntensity} *intensities.rgb) *specularTerm);"); } else if (effectProps.MatType == MaterialType.MaterialPbr) { applyLightParams.Add($"float k = 1.0 - {UniformNameDeclarations.DiffuseFraction};"); applyLightParams.Add("float specular = specularLighting(N, L, V, k);"); applyLightParams.Add($"Ispe = intensities.rgb * {UniformNameDeclarations.SpecularColor}.rgb * (k + specular * (1.0 - k));"); } } var pointLight = new List <string> { $"float att = attenuationPointComponent({VaryingNameDeclarations.Position}.xyz, position, maxDistance);", "lighting = (Idif * att) + (Ispe * att);", "lighting *= strength;" }; //No attenuation! var parallelLight = new List <string> { "lighting = Idif + Ispe;", "lighting *= strength;" }; var spotLight = new List <string> { $"float att = attenuationPointComponent({VaryingNameDeclarations.Position}.xyz, position, maxDistance) * attenuationConeComponent(direction, L, innerConeAngle, outerConeAngle);", "lighting = (Idif * att) + (Ispe * att);", "lighting *= strength;" }; // - Disable GammaCorrection for better colors /*var gammaCorrection = new List<string>() * { * "vec3 gamma = vec3(1.0/2.2);", * "result = pow(result, gamma);" * };*/ var methodBody = new List <string>(); methodBody.AddRange(applyLightParams); methodBody.Add("vec3 lighting = vec3(0);"); methodBody.Add(""); //methodBody.AddRange(attenuation); methodBody.Add("if(lightType == 0) // PointLight"); methodBody.Add("{"); methodBody.AddRange(pointLight); methodBody.Add("}"); methodBody.Add("else if(lightType == 1 || lightType == 3) // ParallelLight or LegacyLight"); methodBody.Add("{"); methodBody.AddRange(parallelLight); methodBody.Add("}"); methodBody.Add("else if(lightType == 2) // SpotLight"); methodBody.Add("{"); methodBody.AddRange(spotLight); methodBody.Add("}"); methodBody.Add(""); //methodBody.AddRange(gammaCorrection); // - Disable GammaCorrection for better colors methodBody.Add(""); methodBody.Add("return lighting;"); return(GLSL.CreateMethod(GLSL.Type.Vec3, "ApplyLight", new[] { GLSL.CreateVar(GLSL.Type.Vec3, "position"), GLSL.CreateVar(GLSL.Type.Vec4, "intensities"), GLSL.CreateVar(GLSL.Type.Vec3, "direction"), GLSL.CreateVar(GLSL.Type.Float, "maxDistance"), GLSL.CreateVar(GLSL.Type.Float, "strength"), GLSL.CreateVar(GLSL.Type.Float, "outerConeAngle"), GLSL.CreateVar(GLSL.Type.Float, "innerConeAngle"), GLSL.CreateVar(GLSL.Type.Int, "lightType"), }, methodBody)); }
public override StringBuilder VisitMemberType(MemberType memberType, int data) { return(new StringBuilder(GLSL.ToGLSL(memberType.Annotation <TypeReference>()))); }
internal IEnumerable <ASLShaderStruct> GetStructures() { foreach (var structure in _shader.NestedTypes) { var isInterfaceBlock = structure.HasCustomAttributes && structure.HasAttribute <InterfaceBlockAttribute>(); TypeReference interfaceBlockType = null; if (isInterfaceBlock) { var attrs = structure.CustomAttributes.Where(a => a.AttributeType.IsIn() || a.AttributeType.IsOut() || a.AttributeType.IsUniform()); if (attrs.Count() == 0) { throw new ASLException("ASL Error: An interface block have to have a qualifier which can be in, out or uniform."); } if (attrs.Count() > 1) { throw new ASLException("ASL Error: An interface block have to have only one qualifier, which can be in, out or uniform."); } interfaceBlockType = attrs.First().AttributeType; } List <ASLShaderVariable> fields = new List <ASLShaderVariable>(); foreach (var field in structure.Fields) { var type = GLSL.ToGLSL(field.FieldType); var isArray = field.FieldType.IsArray; var arrayAttr = field.CustomAttributes.Where(a => a.AttributeType.Is <ArraySizeAttribute>()); var arraySize = (isArray && arrayAttr.Count() > 0 && arrayAttr.First().HasConstructorArguments) ? arrayAttr.First().ConstructorArguments.First().Value.ToString() : string.Empty; var name = field.Name; var commentAttr = field.CustomAttributes.Where(a => a.AttributeType.Is <CommentAttribute>()); var u_comment = (commentAttr.Count() > 0 && commentAttr.First().HasConstructorArguments) ? commentAttr.First().ConstructorArguments.First().Value.ToString() : string.Empty; var d_comment = DebugMode ? field.DeclaringType.FullName + "." + field.Name : string.Empty; TypeReference attrType = null; if (isInterfaceBlock) { var attrs = field.CustomAttributes.Where(a => a.AttributeType.IsIn() || a.AttributeType.IsOut() || a.AttributeType.IsUniform()); if (attrs.Count() > 1) { throw new ASLException("ASL Error: An interface block member have to have only one qualifier, which can be in, out or uniform, according to the interface block qualifier."); } if (attrs.Count() > 0) { if ((interfaceBlockType.IsIn() && (attrs.First().AttributeType.IsOut() || attrs.First().AttributeType.IsUniform())) || (interfaceBlockType.IsUniform() && (attrs.First().AttributeType.IsOut() || attrs.First().AttributeType.IsIn())) || (interfaceBlockType.IsOut() && (attrs.First().AttributeType.IsIn() || attrs.First().AttributeType.IsUniform()))) { throw new ASLException("ASL Error: An interface block member have to have (if he has one) a similar qualifier than the interface block."); } attrType = attrs.First().AttributeType; } } var varLayoutAttr = (this is VertexShader) ? field.CustomAttributes.Where(a => a.AttributeType.Is <VertexShader.LayoutAttribute>()) : ((this is FragmentShader) ? field.CustomAttributes.Where(a => a.AttributeType.Is <FragmentShader.LayoutAttribute>()) : ((this is GeometryShader) ? field.CustomAttributes.Where(a => a.AttributeType.Is <GeometryShader.LayoutAttribute>()) : null)); var varLayout = (varLayoutAttr != null && varLayoutAttr.Count() > 0) ? varLayoutAttr.First() : null; fields.Add(new ASLShaderVariable(type, isArray, arraySize, name, u_comment, d_comment, attrType, varLayout)); } var layoutAttr = (this is VertexShader) ? structure.CustomAttributes.Where(a => a.AttributeType.Is <VertexShader.LayoutAttribute>()) : ((this is FragmentShader) ? structure.CustomAttributes.Where(a => a.AttributeType.Is <FragmentShader.LayoutAttribute>()) : ((this is GeometryShader) ? structure.CustomAttributes.Where(a => a.AttributeType.Is <GeometryShader.LayoutAttribute>()) : null)); var layout = (layoutAttr != null && layoutAttr.Count() > 0) ? layoutAttr.First() : null; yield return(new ASLShaderStruct(structure.Name, isInterfaceBlock, interfaceBlockType, fields, layout)); } }