/// <summary> /// Render 3D scene<para/> /// Отрисовка 3D сцены /// </summary> static void Render3D() { // Setting up camera // Подготовка камеры CameraManager.Setup3D(); // Render opaque objects, saving transparent for later use // Отрисовка непрозрачных объектов с сохранением прозрачных List <Renderers.RendererBase> transMeshes = new List <Renderers.RendererBase>(); // Enabling states // Активация стейтов GL.Enable(EnableCap.Texture2D); // Rendering sky // Отрисовка неба GL.DepthMask(false); Renderers.SkyRenderer.Render(); GL.DepthMask(true); GL.Enable(EnableCap.DepthTest); // Rendering or storing surfaces // Отрисовка или сохранение сурфейсов if (RenderQueue.Count > 0) { Renderers.RendererBase r = RenderQueue.Dequeue(); while (true) { if (r.IsVisible()) { r.Render(false); } if (r.IsAlphaBlended()) { transMeshes.Add(r); } if (RenderQueue.Count > 0) { r = RenderQueue.Dequeue(); } else { break; } } } // Rendering transparent meshes // Отрисовка прозрачных мешей if (transMeshes.Count > 0) { switch (TransparencyRenderingMode) { // Default VC mode // Обычный режим, как в оригинале case TransparencyRendering.Classic: ClassicTransparencyRender(transMeshes); break; } } // Disabling states // Отключение стейтов GL.Disable(EnableCap.DepthTest); GL.Disable(EnableCap.Texture2D); }
/// <summary> /// Drawing GL data<para/> /// Отрисовка GL-данных /// </summary> void DrawGL(RendererBase renderer, TextureDictionary td, bool trans, bool force) { // Sending vertex data // Отправка вершинных данных if (vertexBuffer!=0) { GL.EnableClientState(ArrayCap.VertexArray); GL.BindBuffer(BufferTarget.ArrayBuffer, vertexBuffer); GL.VertexPointer(3, VertexPointerType.Float, 0, IntPtr.Zero); } // Sending normals // Отправка нормалей if (normalBuffer!=0) { GL.EnableClientState(ArrayCap.NormalArray); GL.BindBuffer(BufferTarget.ArrayBuffer, normalBuffer); GL.NormalPointer(NormalPointerType.Float, 0, IntPtr.Zero); } // Sending colors // Отправка цветов if (colorBuffer != 0) { GL.EnableClientState(ArrayCap.ColorArray); GL.BindBuffer(BufferTarget.ArrayBuffer, colorBuffer); GL.ColorPointer(4, ColorPointerType.UnsignedByte, 0, IntPtr.Zero); } // Drawing surfaces // Отрисовка поверхностей foreach (Surface s in Surfaces) { if (s.IndexBuffer != 0 && (s.Material.HasAlpha == trans || force)) { // Binding material // Присвоение материала BindMaterial(renderer, s, td); // Drawing tris // Отрисовка треугольников PrimitiveType pt = PrimitiveType.Triangles; int triCount = s.IndexCount/3; if (s.IsTriangleStrip) { pt = PrimitiveType.TriangleStrip; triCount = s.IndexCount - 2; } GL.BindBuffer(BufferTarget.ElementArrayBuffer, s.IndexBuffer); GL.DrawElements(pt, s.IndexCount, DrawElementsType.UnsignedShort, IntPtr.Zero); GL.DisableClientState(ArrayCap.TextureCoordArray); // Incrementing counters // Увеличение счётчиков Renderer.TrisRendered += triCount; Renderer.DrawCalls++; } } // Unbinding the buffers // Отключаем буфферы GL.BindBuffer(BufferTarget.ArrayBuffer, 0); GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); // Disabling states // Отключение стейтов if (vertexBuffer != 0) { GL.DisableClientState(ArrayCap.VertexArray); } if (normalBuffer != 0) { GL.DisableClientState(ArrayCap.NormalArray); } if (colorBuffer != 0) { GL.DisableClientState(ArrayCap.ColorArray); } }
/// <summary> /// Bind material data<para/> /// Присвоение материала /// </summary> void BindMaterial(RendererBase renderer, Surface surf, TextureDictionary td) { Material mat = surf.Material; if (mat.Textures!=null) { Texture t = (Texture)mat.Textures[0]; TextureDictionary.Texture tex = t.CachedTexture; // Caching texture // Кешируем текстуру if (tex != null) { if (tex.State == TextureDictionary.ReadyState.Obsolette) { tex = null; } } if (tex == null) { string lname = t.Name.ToLower(); if (td.Textures.ContainsKey(lname)) { tex = td.Textures[lname]; t.CachedTexture = tex; } } // Binding texture coord array // Установка массива текстурных координат GL.EnableClientState(ArrayCap.TextureCoordArray); GL.BindBuffer(BufferTarget.ArrayBuffer, tex1Buffer); GL.TexCoordPointer(2, TexCoordPointerType.Float, 0, IntPtr.Zero); // Binding it // Установка текстуры if (tex!=null) { if (tex.State == TextureDictionary.ReadyState.Complete) { // Binding tex // Установка текстуры tex.Bind(); // Setting up addressing and filtering // Установка адресации и фильтрации TextureFile.FilterMode fm = t.Filter; if (true) {//!tex.Mipmapped) { switch (t.Filter) { case TextureFile.FilterMode.MipNearest: fm = TextureFile.FilterMode.Nearest; break; case TextureFile.FilterMode.MipLinear: fm = TextureFile.FilterMode.Nearest; break; case TextureFile.FilterMode.LinearMipNearest: fm = TextureFile.FilterMode.Linear; break; case TextureFile.FilterMode.LinearMipLinear: fm = TextureFile.FilterMode.Linear; break; } } switch (fm) { case TextureFile.FilterMode.Nearest: GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Nearest); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Nearest); break; case TextureFile.FilterMode.Linear: GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear); break; case TextureFile.FilterMode.MipNearest: GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.NearestMipmapNearest); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Nearest); break; case TextureFile.FilterMode.MipLinear: GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.NearestMipmapLinear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Nearest); break; case TextureFile.FilterMode.LinearMipNearest: GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.LinearMipmapNearest); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear); break; case TextureFile.FilterMode.LinearMipLinear: GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.LinearMipmapLinear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear); break; default: throw new Exception("[Model] Invalid value for FilterMode"); } // U addressing // Адресация текстуры по горизонтали switch (t.AddressU) { case TextureFile.AddressMode.Repeat: GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.Repeat); break; case TextureFile.AddressMode.Mirror: GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.MirroredRepeat); break; case TextureFile.AddressMode.Clamp: GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.Clamp); break; default: throw new Exception("[Model] Invalid value for AddressMode"); } // V addressing // Адресация текстуры по вертикали switch (t.AddressV) { case TextureFile.AddressMode.Repeat: GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.Repeat); break; case TextureFile.AddressMode.Mirror: GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.MirroredRepeat); break; case TextureFile.AddressMode.Clamp: GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.Clamp); break; default: throw new Exception("[Model] Invalid value for AddressMode"); } } } else { GL.BindTexture(TextureTarget.Texture2D, Renderer.EmptyTexture); } }else{ GL.BindTexture(TextureTarget.Texture2D, Renderer.EmptyTexture); } renderer.SetupSurface(surf, mat, geometry); }
/// <summary> /// Render this submesh<para/> /// Отрисовка этого меша /// </summary> /// <param name="td">Textures to use<para/>Текстуры для использования</param> /// <param name="trans">Transparent mode<para/>Полупрозрачный режим</param> public void Render(RendererBase renderer, TextureDictionary td, bool trans, bool force = false) { if (State != ReadyState.Obsolette) { if (State == ReadyState.Empty) { Build(); State = ReadyState.NotSent; } else if (State == ReadyState.Complete) { DrawGL(renderer, td, trans, force); } } ParentModel.UseCount++; }