private static void RenderFace(ref MeshMaterial Material, VertexTemplate[] Vertices, OpenGlTextureWrapMode wrap, ref MeshFace Face, Vector3 Camera, bool IsDebugTouchMode = false) { // texture if (Material.DaytimeTexture != null) { if (Textures.LoadTexture(Material.DaytimeTexture, wrap)) { if (!TexturingEnabled) { GL.Enable(EnableCap.Texture2D); TexturingEnabled = true; } if (Material.DaytimeTexture.OpenGlTextures[(int)wrap] != LastBoundTexture) { GL.BindTexture(TextureTarget.Texture2D, Material.DaytimeTexture.OpenGlTextures[(int)wrap].Name); LastBoundTexture = Material.DaytimeTexture.OpenGlTextures[(int)wrap]; } } else { if (TexturingEnabled) { GL.Disable(EnableCap.Texture2D); TexturingEnabled = false; LastBoundTexture = null; } } } else { if (TexturingEnabled) { GL.Disable(EnableCap.Texture2D); TexturingEnabled = false; LastBoundTexture = null; } } // blend mode float factor; if (Material.BlendMode == MeshMaterialBlendMode.Additive) { factor = 1.0f; if (!BlendEnabled) { GL.Enable(EnableCap.Blend); } GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.One); if (FogEnabled) { GL.Disable(EnableCap.Fog); } } else if (Material.NighttimeTexture == null) { float blend = inv255 * (float)Material.DaytimeNighttimeBlend + 1.0f - OptionLightingResultingAmount; if (blend > 1.0f) { blend = 1.0f; } factor = 1.0f - 0.7f * blend; } else { factor = 1.0f; } if (Material.NighttimeTexture != null) { if (LightingEnabled) { GL.Disable(EnableCap.Lighting); LightingEnabled = false; } } else { if (OptionLighting & !LightingEnabled) { GL.Enable(EnableCap.Lighting); LightingEnabled = true; } } // render daytime polygon int FaceType = Face.Flags & MeshFace.FaceTypeMask; if (!IsDebugTouchMode) { switch (FaceType) { case MeshFace.FaceTypeTriangles: GL.Begin(PrimitiveType.Triangles); break; case MeshFace.FaceTypeTriangleStrip: GL.Begin(PrimitiveType.TriangleStrip); break; case MeshFace.FaceTypeQuads: GL.Begin(PrimitiveType.Quads); break; case MeshFace.FaceTypeQuadStrip: GL.Begin(PrimitiveType.QuadStrip); break; default: GL.Begin(PrimitiveType.Polygon); break; } } else { GL.Begin(PrimitiveType.LineLoop); } if (Material.GlowAttenuationData != 0) { float alphafactor = (float)Glow.GetDistanceFactor(Vertices, ref Face, Material.GlowAttenuationData, World.AbsoluteCameraPosition); if (OptionWireframe) { GL.Color4(inv255 * (float)Material.Color.R * factor, inv255 * Material.Color.G * factor, inv255 * (float)Material.Color.B * factor, 1.0f); } else { GL.Color4(inv255 * (float)Material.Color.R * factor, inv255 * Material.Color.G * factor, inv255 * (float)Material.Color.B * factor, inv255 * (float)Material.Color.A * alphafactor); } } else { if (OptionWireframe) { GL.Color4(inv255 * (float)Material.Color.R * factor, inv255 * Material.Color.G * factor, inv255 * (float)Material.Color.B * factor, 1.0f); } else { GL.Color4(inv255 * (float)Material.Color.R * factor, inv255 * Material.Color.G * factor, inv255 * (float)Material.Color.B * factor, inv255 * (float)Material.Color.A); } } if ((Material.Flags & MeshMaterial.EmissiveColorMask) != 0) { GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, new float[] { inv255 *(float)Material.EmissiveColor.R, inv255 * (float)Material.EmissiveColor.G, inv255 * (float)Material.EmissiveColor.B, 1.0f }); } else { GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, new float[] { 0.0f, 0.0f, 0.0f, 1.0f }); } if (Material.DaytimeTexture != null) { if (LightingEnabled) { for (int j = 0; j < Face.Vertices.Length; j++) { GL.Normal3(Face.Vertices[j].Normal.X, Face.Vertices[j].Normal.Y, Face.Vertices[j].Normal.Z); GL.TexCoord2(Vertices[Face.Vertices[j].Index].TextureCoordinates.X, Vertices[Face.Vertices[j].Index].TextureCoordinates.Y); if (Vertices[Face.Vertices[j].Index] is ColoredVertex) { ColoredVertex v = (ColoredVertex)Vertices[Face.Vertices[j].Index]; GL.Color3(v.Color.R, v.Color.G, v.Color.B); } GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - Camera.X), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - Camera.Y), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - Camera.Z)); } } else { for (int j = 0; j < Face.Vertices.Length; j++) { GL.TexCoord2(Vertices[Face.Vertices[j].Index].TextureCoordinates.X, Vertices[Face.Vertices[j].Index].TextureCoordinates.Y); if (Vertices[Face.Vertices[j].Index] is ColoredVertex) { ColoredVertex v = (ColoredVertex)Vertices[Face.Vertices[j].Index]; GL.Color3(v.Color.R, v.Color.G, v.Color.B); } GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - Camera.X), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - Camera.Y), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - Camera.Z)); } } } else { if (LightingEnabled) { for (int j = 0; j < Face.Vertices.Length; j++) { GL.Normal3(Face.Vertices[j].Normal.X, Face.Vertices[j].Normal.Y, Face.Vertices[j].Normal.Z); if (Vertices[Face.Vertices[j].Index] is ColoredVertex) { ColoredVertex v = (ColoredVertex)Vertices[Face.Vertices[j].Index]; GL.Color3(v.Color.R, v.Color.G, v.Color.B); } GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - Camera.X), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - Camera.Y), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - Camera.Z)); } } else { for (int j = 0; j < Face.Vertices.Length; j++) { if (Vertices[Face.Vertices[j].Index] is ColoredVertex) { ColoredVertex v = (ColoredVertex)Vertices[Face.Vertices[j].Index]; GL.Color3(v.Color.R, v.Color.G, v.Color.B); } GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - Camera.X), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - Camera.Y), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - Camera.Z)); } } } GL.End(); // render nighttime polygon if (Material.NighttimeTexture != null && Textures.LoadTexture(Material.NighttimeTexture, wrap)) { if (!TexturingEnabled) { GL.Enable(EnableCap.Texture2D); TexturingEnabled = true; } if (!BlendEnabled) { GL.Enable(EnableCap.Blend); } GL.BindTexture(TextureTarget.Texture2D, Material.NighttimeTexture.OpenGlTextures[(int)wrap].Name); LastBoundTexture = null; GL.AlphaFunc(AlphaFunction.Greater, 0.0f); GL.Enable(EnableCap.AlphaTest); switch (FaceType) { case MeshFace.FaceTypeTriangles: GL.Begin(PrimitiveType.Triangles); break; case MeshFace.FaceTypeTriangleStrip: GL.Begin(PrimitiveType.TriangleStrip); break; case MeshFace.FaceTypeQuads: GL.Begin(PrimitiveType.Quads); break; case MeshFace.FaceTypeQuadStrip: GL.Begin(PrimitiveType.QuadStrip); break; default: GL.Begin(PrimitiveType.Polygon); break; } float alphafactor; if (Material.GlowAttenuationData != 0) { alphafactor = (float)Glow.GetDistanceFactor(Vertices, ref Face, Material.GlowAttenuationData, Camera); float blend = inv255 * (float)Material.DaytimeNighttimeBlend + 1.0f - OptionLightingResultingAmount; if (blend > 1.0f) { blend = 1.0f; } alphafactor *= blend; } else { alphafactor = inv255 * (float)Material.DaytimeNighttimeBlend + 1.0f - OptionLightingResultingAmount; if (alphafactor > 1.0f) { alphafactor = 1.0f; } } if (OptionWireframe) { GL.Color4(inv255 * (float)Material.Color.R * factor, inv255 * Material.Color.G * factor, inv255 * (float)Material.Color.B * factor, 1.0f); } else { GL.Color4(inv255 * (float)Material.Color.R * factor, inv255 * Material.Color.G * factor, inv255 * (float)Material.Color.B * factor, inv255 * (float)Material.Color.A * alphafactor); } if ((Material.Flags & MeshMaterial.EmissiveColorMask) != 0) { GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, new float[] { inv255 *(float)Material.EmissiveColor.R, inv255 * (float)Material.EmissiveColor.G, inv255 * (float)Material.EmissiveColor.B, 1.0f }); } else { GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, new float[] { 0.0f, 0.0f, 0.0f, 1.0f }); } for (int j = 0; j < Face.Vertices.Length; j++) { GL.TexCoord2(Vertices[Face.Vertices[j].Index].TextureCoordinates.X, Vertices[Face.Vertices[j].Index].TextureCoordinates.Y); if (Vertices[Face.Vertices[j].Index] is ColoredVertex) { ColoredVertex v = (ColoredVertex)Vertices[Face.Vertices[j].Index]; GL.Color3(v.Color.R, v.Color.G, v.Color.B); } GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - Camera.X), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - Camera.Y), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - Camera.Z)); } GL.End(); RestoreAlphaFunc(); if (!BlendEnabled) { GL.Disable(EnableCap.Blend); } } // normals if (OptionNormals) { if (TexturingEnabled) { GL.Disable(EnableCap.Texture2D); TexturingEnabled = false; } for (int j = 0; j < Face.Vertices.Length; j++) { GL.Begin(PrimitiveType.Lines); GL.Color4(inv255 * (float)Material.Color.R, inv255 * (float)Material.Color.G, inv255 * (float)Material.Color.B, 1.0f); GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - Camera.X), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - Camera.Y), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - Camera.Z)); GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X + Face.Vertices[j].Normal.X - Camera.X), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y + Face.Vertices[j].Normal.Y - Camera.Y), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z + Face.Vertices[j].Normal.Z - Camera.Z)); GL.End(); } } // finalize if (Material.BlendMode == MeshMaterialBlendMode.Additive) { GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); if (!BlendEnabled) { GL.Disable(EnableCap.Blend); } if (FogEnabled) { GL.Enable(EnableCap.Fog); } } }
public void RenderFaceImmediateMode(ObjectState State, MeshFace Face, bool IsDebugTouchMode = false) { if (State.Prototype.Mesh.Vertices.Length < 1) { return; } VertexTemplate[] vertices = State.Prototype.Mesh.Vertices; MeshMaterial material = State.Prototype.Mesh.Materials[Face.Material]; if (!OptionBackFaceCulling || (Face.Flags & MeshFace.Face2Mask) != 0) { GL.Disable(EnableCap.CullFace); } else if (OptionBackFaceCulling) { if ((Face.Flags & MeshFace.Face2Mask) == 0) { GL.Enable(EnableCap.CullFace); } } Matrix4D modelMatrix = State.ModelMatrix * Camera.TranslationMatrix; // matrix unsafe { GL.MatrixMode(MatrixMode.Projection); GL.PushMatrix(); fixed(double *matrixPointer = &CurrentProjectionMatrix.Row0.X) { GL.LoadMatrix(matrixPointer); } GL.MatrixMode(MatrixMode.Modelview); GL.PushMatrix(); fixed(double *matrixPointer = &CurrentViewMatrix.Row0.X) { GL.LoadMatrix(matrixPointer); } double *matrixPointer2 = &modelMatrix.Row0.X; { GL.MultMatrix(matrixPointer2); } GL.MatrixMode(MatrixMode.Texture); GL.PushMatrix(); fixed(double *matrixPointer = &State.TextureTranslation.Row0.X) { GL.LoadMatrix(matrixPointer); } } if (OptionWireFrame) { GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); } // lighting if (material.NighttimeTexture == null) { if (OptionLighting) { GL.Enable(EnableCap.Lighting); } } if ((material.Flags & MeshMaterial.EmissiveColorMask) != 0) { GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, new Color4(material.EmissiveColor.R, material.EmissiveColor.G, material.EmissiveColor.B, 255)); } else { GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, new Color4(0.0f, 0.0f, 0.0f, 1.0f)); } // fog if (OptionFog) { GL.Enable(EnableCap.Fog); } 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) { if (currentHost.LoadTexture(material.DaytimeTexture, (OpenGlTextureWrapMode)material.WrapMode)) { GL.Enable(EnableCap.Texture2D); 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]; } } } // blend mode float factor; if (material.BlendMode == MeshMaterialBlendMode.Additive) { factor = 1.0f; GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.One); GL.Disable(EnableCap.Fog); } else if (material.NighttimeTexture == null) { float blend = inv255 * material.DaytimeNighttimeBlend + 1.0f - Lighting.OptionLightingResultingAmount; if (blend > 1.0f) { blend = 1.0f; } factor = 1.0f - 0.7f * blend; } else { factor = 1.0f; } float alphaFactor; if (material.GlowAttenuationData != 0) { alphaFactor = (float)Glow.GetDistanceFactor(modelMatrix, vertices, ref Face, material.GlowAttenuationData); } else { alphaFactor = 1.0f; } GL.Begin(DrawMode); if (OptionWireFrame) { GL.Color4(inv255 * material.Color.R * factor, inv255 * material.Color.G * factor, inv255 * material.Color.B * factor, 1.0f); } else { GL.Color4(inv255 * material.Color.R * factor, inv255 * material.Color.G * factor, inv255 * material.Color.B * factor, inv255 * material.Color.A * alphaFactor); } for (int i = 0; i < Face.Vertices.Length; i++) { GL.Normal3(Face.Vertices[i].Normal.X, Face.Vertices[i].Normal.Y, -Face.Vertices[i].Normal.Z); GL.TexCoord2(vertices[Face.Vertices[i].Index].TextureCoordinates.X, vertices[Face.Vertices[i].Index].TextureCoordinates.Y); if (vertices[Face.Vertices[i].Index] is ColoredVertex) { ColoredVertex v = (ColoredVertex)vertices[Face.Vertices[i].Index]; GL.Color3(v.Color.R, v.Color.G, v.Color.B); } GL.Vertex3(vertices[Face.Vertices[i].Index].Coordinates.X, vertices[Face.Vertices[i].Index].Coordinates.Y, -vertices[Face.Vertices[i].Index].Coordinates.Z); } GL.End(); } // nighttime polygon if (material.NighttimeTexture != null && currentHost.LoadTexture(material.NighttimeTexture, (OpenGlTextureWrapMode)material.WrapMode)) { // texture GL.Enable(EnableCap.Texture2D); 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, 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; } } GL.Begin(DrawMode); if (OptionWireFrame) { GL.Color4(inv255 * material.Color.R, inv255 * material.Color.G, inv255 * material.Color.B, 1.0f); } else { GL.Color4(inv255 * material.Color.R, inv255 * material.Color.G, inv255 * material.Color.B, inv255 * material.Color.A * alphaFactor); } for (int i = 0; i < Face.Vertices.Length; i++) { GL.Normal3(Face.Vertices[i].Normal.X, Face.Vertices[i].Normal.Y, -Face.Vertices[i].Normal.Z); GL.TexCoord2(vertices[Face.Vertices[i].Index].TextureCoordinates.X, vertices[Face.Vertices[i].Index].TextureCoordinates.Y); if (vertices[Face.Vertices[i].Index] is ColoredVertex) { ColoredVertex v = (ColoredVertex)vertices[Face.Vertices[i].Index]; GL.Color3(v.Color.R, v.Color.G, v.Color.B); } GL.Vertex3(vertices[Face.Vertices[i].Index].Coordinates.X, vertices[Face.Vertices[i].Index].Coordinates.Y, -vertices[Face.Vertices[i].Index].Coordinates.Z); } GL.End(); RestoreBlendFunc(); RestoreAlphaFunc(); } GL.Disable(EnableCap.Texture2D); // normals if (OptionNormals) { for (int i = 0; i < Face.Vertices.Length; i++) { GL.Begin(PrimitiveType.Lines); GL.Color4(new Color4(material.Color.R, material.Color.G, material.Color.B, 255)); GL.Vertex3(vertices[Face.Vertices[i].Index].Coordinates.X, vertices[Face.Vertices[i].Index].Coordinates.Y, -vertices[Face.Vertices[i].Index].Coordinates.Z); GL.Vertex3(vertices[Face.Vertices[i].Index].Coordinates.X + Face.Vertices[i].Normal.X, vertices[Face.Vertices[i].Index].Coordinates.Y + +Face.Vertices[i].Normal.Z, -(vertices[Face.Vertices[i].Index].Coordinates.Z + Face.Vertices[i].Normal.Z)); GL.End(); } } // finalize if (OptionWireFrame) { GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); } if (material.BlendMode == MeshMaterialBlendMode.Additive) { RestoreBlendFunc(); } GL.PopMatrix(); GL.MatrixMode(MatrixMode.Modelview); GL.PopMatrix(); GL.MatrixMode(MatrixMode.Projection); GL.PopMatrix(); }
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); } }
public void RenderFace(Shader Shader, ObjectState State, MeshFace Face, Vector3 EyePosition, bool IsDebugTouchMode = false) { if (State.Prototype.Mesh.Vertices.Length < 1) { return; } VertexTemplate[] vertices = State.Prototype.Mesh.Vertices; MeshMaterial material = State.Prototype.Mesh.Materials[Face.Material]; VertexArrayObject VAO = (VertexArrayObject)State.Prototype.Mesh.VAO; VertexArrayObject NormalsVAO = (VertexArrayObject)State.Prototype.Mesh.NormalsVAO; 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 Matrix4D modelMatrix = State.Scale * State.Rotate * State.Translation * Matrix4D.CreateTranslation(-EyePosition); Matrix4D modelViewMatrix = modelMatrix * CurrentViewMatrix; Shader.SetCurrentProjectionMatrix(CurrentProjectionMatrix); Shader.SetCurrentModelViewMatrix(modelViewMatrix); Shader.SetCurrentNormalMatrix(Matrix4D.Transpose(Matrix4D.Invert(modelViewMatrix))); Shader.SetCurrentTextureMatrix(State.TextureTranslation); if (OptionWireFrame || IsDebugTouchMode) { VAO.Bind(); VAO.Draw(Shader.VertexLayout, PrimitiveType.LineLoop, Face.IboStartIndex, Face.Vertices.Length); VAO.UnBind(); return; } // lighting if (material.NighttimeTexture == null) { if (OptionLighting) { Shader.SetIsLight(true); Shader.SetLightPosition(new Vector3(Lighting.OptionLightPosition.X, Lighting.OptionLightPosition.Y, -Lighting.OptionLightPosition.Z)); Shader.SetLightAmbient(new Color4(Lighting.OptionAmbientColor.R, Lighting.OptionAmbientColor.G, Lighting.OptionAmbientColor.B, 255)); Shader.SetLightDiffuse(new Color4(Lighting.OptionDiffuseColor.R, Lighting.OptionDiffuseColor.G, Lighting.OptionDiffuseColor.B, 255)); Shader.SetLightSpecular(new Color4(Lighting.OptionSpecularColor.R, Lighting.OptionSpecularColor.G, Lighting.OptionSpecularColor.B, 255)); Shader.SetMaterialAmbient(new Color4(material.Color.R, material.Color.G, material.Color.B, material.Color.A)); // TODO Shader.SetMaterialDiffuse(new Color4(material.Color.R, material.Color.G, material.Color.B, material.Color.A)); Shader.SetMaterialSpecular(new Color4(material.Color.R, material.Color.G, material.Color.B, material.Color.A)); // TODO if ((material.Flags & MeshMaterial.EmissiveColorMask) != 0) { Shader.SetMaterialEmission(new Color4(material.EmissiveColor.R, material.EmissiveColor.G, material.EmissiveColor.B, 255)); } else { Shader.SetMaterialEmission(new Color4(0.0f, 0.0f, 0.0f, 1.0f)); } Shader.SetMaterialShininess(1.0f); Lighting.OptionLightingResultingAmount = (Lighting.OptionAmbientColor.R + Lighting.OptionAmbientColor.G + Lighting.OptionAmbientColor.B) / 480.0f; if (Lighting.OptionLightingResultingAmount > 1.0f) { Lighting.OptionLightingResultingAmount = 1.0f; } } else { Shader.SetMaterialAmbient(new Color4(material.Color.R, material.Color.G, material.Color.B, material.Color.A)); // TODO } } else { Shader.SetMaterialAmbient(new Color4(material.Color.R, material.Color.G, material.Color.B, material.Color.A)); // TODO } // fog if (OptionFog) { Shader.SetIsFog(true); Shader.SetFogStart(Fog.Start); Shader.SetFogEnd(Fog.End); Shader.SetFogColor(new Color4(Fog.Color.R, Fog.Color.G, Fog.Color.B, 255)); } 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) { if (currentHost.LoadTexture(material.DaytimeTexture, (OpenGlTextureWrapMode)material.WrapMode)) { GL.Enable(EnableCap.Texture2D); Shader.SetIsTexture(true); Shader.SetTexture(0); GL.BindTexture(TextureTarget.Texture2D, material.DaytimeTexture.OpenGlTextures[(int)material.WrapMode].Name); } } // blend mode float factor; if (material.BlendMode == MeshMaterialBlendMode.Additive) { factor = 1.0f; GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.One); Shader.SetIsFog(false); } else if (material.NighttimeTexture == null) { float blend = inv255 * material.DaytimeNighttimeBlend + 1.0f - Lighting.OptionLightingResultingAmount; if (blend > 1.0f) { blend = 1.0f; } factor = 1.0f - 0.7f * blend; } else { factor = 1.0f; } Shader.SetBrightness(factor); float alphaFactor; if (material.GlowAttenuationData != 0) { alphaFactor = (float)Glow.GetDistanceFactor(modelMatrix, vertices, ref Face, material.GlowAttenuationData); } else { alphaFactor = 1.0f; } Shader.SetOpacity(inv255 * material.Color.A * alphaFactor); // render polygon VAO.Bind(); VAO.Draw(Shader.VertexLayout, DrawMode, Face.IboStartIndex, Face.Vertices.Length); VAO.UnBind(); GL.BindTexture(TextureTarget.Texture2D, 0); } // nighttime polygon if (material.NighttimeTexture != null && currentHost.LoadTexture(material.NighttimeTexture, (OpenGlTextureWrapMode)material.WrapMode)) { // texture GL.Enable(EnableCap.Texture2D); Shader.SetIsTexture(true); Shader.SetTexture(0); GL.BindTexture(TextureTarget.Texture2D, material.NighttimeTexture.OpenGlTextures[(int)material.WrapMode].Name); 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, 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(alphaFactor); // render polygon VAO.Bind(); VAO.Draw(Shader.VertexLayout, DrawMode, Face.IboStartIndex, Face.Vertices.Length); VAO.UnBind(); GL.BindTexture(TextureTarget.Texture2D, 0); RestoreBlendFunc(); RestoreAlphaFunc(); } GL.Disable(EnableCap.Texture2D); // normals if (OptionNormals) { Shader.SetIsTexture(false); Shader.SetBrightness(1.0f); Shader.SetOpacity(1.0f); NormalsVAO.Bind(); NormalsVAO.Draw(Shader.VertexLayout, PrimitiveType.Lines, Face.NormalsIboStartIndex, Face.Vertices.Length * 2); NormalsVAO.UnBind(); } // finalize if (material.BlendMode == MeshMaterialBlendMode.Additive) { RestoreBlendFunc(); } }