/// <summary>Creates glow attenuation data from a half distance and a mode. The resulting value can be later passed to SplitGlowAttenuationData in order to reconstruct the parameters.</summary> /// <param name="HalfDistance">The distance at which the glow is at 50% of its full intensity. The value is clamped to the integer range from 1 to 4096. Values less than or equal to 0 disable glow attenuation.</param> /// <param name="Mode">The glow attenuation mode.</param> /// <returns>A System.UInt16 packed with the information about the half distance and glow attenuation mode.</returns> public static ushort GetAttenuationData(double HalfDistance, GlowAttenuationMode Mode) { if (HalfDistance <= 0.0 | Mode == GlowAttenuationMode.None) { return(0); } if (HalfDistance < 1.0) { HalfDistance = 1.0; } else if (HalfDistance > 4095.0) { HalfDistance = 4095.0; } return((ushort)((int)System.Math.Round(HalfDistance) | ((int)Mode << 12))); }
/// <summary>Gets the current intensity glow intensity, using the glow attenuation factor</summary> /// <param name="ModelMatrix">The model transformation matrix to apply</param> /// <param name="Vertices">The verticies to which the glow is to be applied</param> /// <param name="Face">The face which these vertices make up</param> /// <param name="GlowAttenuationData">The current glow attenuation</param> /// <param name="mode">The returned glow attenuation mode</param> /// <returns></returns> public static double GetDistanceFactor(Matrix4D ModelMatrix, VertexTemplate[] Vertices, ref MeshFace Face, ushort GlowAttenuationData, out GlowAttenuationMode mode) { mode = GlowAttenuationMode.None; if (Face.Vertices.Length == 0) { return(1.0); } double halfdistance; Glow.SplitAttenuationData(GlowAttenuationData, out mode, out halfdistance); int i = (int)Face.Vertices[0].Index; Vector3 d = new Vector3(Vertices[i].Coordinates.X, Vertices[i].Coordinates.Y, -Vertices[i].Coordinates.Z); d.Transform(ModelMatrix); switch (mode) { case GlowAttenuationMode.DivisionExponent2: { double t = d.NormSquared(); return(t / (t + halfdistance * halfdistance)); } case GlowAttenuationMode.DivisionExponent4: { double t = d.NormSquared(); t *= t; halfdistance *= halfdistance; return(t / (t + halfdistance * halfdistance)); } default: return(1.0); } }
/// <summary>Recreates the half distance and the glow attenuation mode from a packed System.UInt16 that was created by GetGlowAttenuationData.</summary> /// <param name="Data">The data returned by GetGlowAttenuationData.</param> /// <param name="Mode">The mode of glow attenuation.</param> /// <param name="HalfDistance">The half distance of glow attenuation.</param> public static void SplitAttenuationData(ushort Data, out GlowAttenuationMode Mode, out double HalfDistance) { Mode = (GlowAttenuationMode)(Data >> 12); HalfDistance = (double)(Data & 4095); }
/// <summary>Recreates the half distance and the glow attenuation mode from a packed System.UInt16 that was created by GetGlowAttenuationData.</summary> /// <param name="Data">The data returned by GetGlowAttenuationData.</param> /// <param name="Mode">The mode of glow attenuation.</param> /// <param name="HalfDistance">The half distance of glow attenuation.</param> internal static void SplitGlowAttenuationData(ushort Data, out GlowAttenuationMode Mode, out double HalfDistance) { Mode = (GlowAttenuationMode)(Data >> 12); HalfDistance = (double)(Data & 4095); }
/// <summary>Creates glow attenuation data from a half distance and a mode. The resulting value can be later passed to SplitGlowAttenuationData in order to reconstruct the parameters.</summary> /// <param name="HalfDistance">The distance at which the glow is at 50% of its full intensity. The value is clamped to the integer range from 1 to 4096. Values less than or equal to 0 disable glow attenuation.</param> /// <param name="Mode">The glow attenuation mode.</param> /// <returns>A System.UInt16 packed with the information about the half distance and glow attenuation mode.</returns> internal static ushort GetGlowAttenuationData(double HalfDistance, GlowAttenuationMode Mode) { if (HalfDistance <= 0.0 | Mode == GlowAttenuationMode.None) return 0; if (HalfDistance < 1.0) { HalfDistance = 1.0; } else if (HalfDistance > 4095.0) { HalfDistance = 4095.0; } return (ushort)((int)Math.Round(HalfDistance) | ((int)Mode << 12)); }
public void RenderFace(Shader Shader, ObjectState State, MeshFace Face, Matrix4D modelMatrix, Matrix4D modelViewMatrix, bool IsDebugTouchMode = false) { if (State.Prototype.Mesh.Vertices.Length < 1) { return; } MeshMaterial material = State.Prototype.Mesh.Materials[Face.Material]; VertexArrayObject VAO = (VertexArrayObject)State.Prototype.Mesh.VAO; if (lastVAO != VAO.handle) { VAO.Bind(); lastVAO = VAO.handle; } if (!OptionBackFaceCulling || (Face.Flags & MeshFace.Face2Mask) != 0) { GL.Disable(EnableCap.CullFace); } else if (OptionBackFaceCulling) { if ((Face.Flags & MeshFace.Face2Mask) == 0) { GL.Enable(EnableCap.CullFace); } } // matrix Shader.SetCurrentModelViewMatrix(modelViewMatrix); Shader.SetCurrentTextureMatrix(State.TextureTranslation); if (OptionWireFrame || IsDebugTouchMode) { if (material.Color != lastColor) { Shader.SetMaterialAmbient(material.Color); lastColor = material.Color; } Shader.SetOpacity(1.0f); Shader.SetBrightness(1.0f); VAO.Draw(PrimitiveType.LineLoop, Face.IboStartIndex, Face.Vertices.Length); return; } // lighting if (OptionLighting) { if (material.Color != lastColor) { Shader.SetMaterialAmbient(material.Color); Shader.SetMaterialDiffuse(material.Color); Shader.SetMaterialSpecular(material.Color); //TODO: Ambient and specular colors are not set by any current parsers } if ((material.Flags & MeshMaterial.EmissiveColorMask) != 0) { Shader.SetMaterialEmission(material.EmissiveColor); Shader.SetMaterialEmissive(true); } else { Shader.SetMaterialEmissive(false); } Shader.SetMaterialShininess(1.0f); } else { if (material.Color != lastColor) { Shader.SetMaterialAmbient(material.Color); } //As lighting is disabled, the face cannot be emitting light.... Shader.SetMaterialEmissive(false); } lastColor = material.Color; PrimitiveType DrawMode; switch (Face.Flags & MeshFace.FaceTypeMask) { case MeshFace.FaceTypeTriangles: DrawMode = PrimitiveType.Triangles; break; case MeshFace.FaceTypeTriangleStrip: DrawMode = PrimitiveType.TriangleStrip; break; case MeshFace.FaceTypeQuads: DrawMode = PrimitiveType.Quads; break; case MeshFace.FaceTypeQuadStrip: DrawMode = PrimitiveType.QuadStrip; break; default: DrawMode = PrimitiveType.Polygon; break; } // daytime polygon { // texture if (material.DaytimeTexture != null && currentHost.LoadTexture(material.DaytimeTexture, (OpenGlTextureWrapMode)material.WrapMode)) { Shader.SetIsTexture(true); if (LastBoundTexture != material.DaytimeTexture.OpenGlTextures[(int)material.WrapMode]) { GL.BindTexture(TextureTarget.Texture2D, material.DaytimeTexture.OpenGlTextures[(int)material.WrapMode].Name); LastBoundTexture = material.DaytimeTexture.OpenGlTextures[(int)material.WrapMode]; } } else { Shader.SetIsTexture(false); } // Calculate the brightness of the poly to render float factor; if (material.BlendMode == MeshMaterialBlendMode.Additive) { //Additive blending- Full brightness factor = 1.0f; GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.One); Shader.SetIsFog(false); } else if ((material.Flags & MeshMaterial.EmissiveColorMask) != 0) { //As material is emitting light, it must be at full brightness factor = 1.0f; } else if (material.NighttimeTexture == null || material.NighttimeTexture == material.DaytimeTexture) { //No nighttime texture or both are identical- Darken the polygon to match the light conditions float blend = inv255 * material.DaytimeNighttimeBlend + 1.0f - Lighting.OptionLightingResultingAmount; if (blend > 1.0f) { blend = 1.0f; } factor = 1.0f - 0.7f * blend; } else { //Valid nighttime texture- Blend the two textures by DNB at max brightness factor = 1.0f; } Shader.SetBrightness(factor); float alphaFactor; GlowAttenuationMode mode = GlowAttenuationMode.None; if (material.GlowAttenuationData != 0) { alphaFactor = (float)Glow.GetDistanceFactor(modelMatrix, State.Prototype.Mesh.Vertices, ref Face, material.GlowAttenuationData, out mode); } else { alphaFactor = 1.0f; } if (material.BlendMode == MeshMaterialBlendMode.Additive) { Shader.SetMaterialAdditive(1 + (int)mode); } else { Shader.SetMaterialAdditive(0); } Shader.SetOpacity(inv255 * material.Color.A * alphaFactor); // render polygon VAO.Draw(DrawMode, Face.IboStartIndex, Face.Vertices.Length); } // nighttime polygon if (material.NighttimeTexture != null && material.NighttimeTexture != material.DaytimeTexture && currentHost.LoadTexture(material.NighttimeTexture, (OpenGlTextureWrapMode)material.WrapMode)) { // texture Shader.SetIsTexture(true); if (LastBoundTexture != material.NighttimeTexture.OpenGlTextures[(int)material.WrapMode]) { GL.BindTexture(TextureTarget.Texture2D, material.NighttimeTexture.OpenGlTextures[(int)material.WrapMode].Name); LastBoundTexture = material.NighttimeTexture.OpenGlTextures[(int)material.WrapMode]; } GL.Enable(EnableCap.Blend); // alpha test GL.Enable(EnableCap.AlphaTest); GL.AlphaFunc(AlphaFunction.Greater, 0.0f); // blend mode float alphaFactor; if (material.GlowAttenuationData != 0) { alphaFactor = (float)Glow.GetDistanceFactor(modelMatrix, State.Prototype.Mesh.Vertices, ref Face, material.GlowAttenuationData); float blend = inv255 * material.DaytimeNighttimeBlend + 1.0f - Lighting.OptionLightingResultingAmount; if (blend > 1.0f) { blend = 1.0f; } alphaFactor *= blend; } else { alphaFactor = inv255 * material.DaytimeNighttimeBlend + 1.0f - Lighting.OptionLightingResultingAmount; if (alphaFactor > 1.0f) { alphaFactor = 1.0f; } } Shader.SetOpacity(inv255 * material.Color.A * alphaFactor); // render polygon VAO.Draw(DrawMode, Face.IboStartIndex, Face.Vertices.Length); RestoreBlendFunc(); RestoreAlphaFunc(); } // normals if (OptionNormals) { Shader.SetIsTexture(false); Shader.SetBrightness(1.0f); Shader.SetOpacity(1.0f); VertexArrayObject NormalsVAO = (VertexArrayObject)State.Prototype.Mesh.NormalsVAO; NormalsVAO.Bind(); lastVAO = NormalsVAO.handle; NormalsVAO.Draw(PrimitiveType.Lines, Face.NormalsIboStartIndex, Face.Vertices.Length * 2); } // finalize if (material.BlendMode == MeshMaterialBlendMode.Additive) { RestoreBlendFunc(); Shader.SetIsFog(OptionFog); } }