/// <summary> /// Creates a cached shader for the specifed shader, using the specified shader enumeration /// as a lookup key. /// </summary> private ShaderProgram CreateCachedShader(EverlookShader shader) { if (!Enum.IsDefined(typeof(EverlookShader), shader)) { throw new ArgumentException("An unknown shader was passed to the rendering cache.", nameof(shader)); } Log.Info($"Creating cached shader for \"{shader}\""); ShaderProgram shaderProgram; switch (shader) { case EverlookShader.Plain2D: { shaderProgram = new Plain2DShader(); break; } case EverlookShader.WorldModel: { shaderProgram = new WorldModelShader(); break; } case EverlookShader.BoundingBox: { shaderProgram = new BoundingBoxShader(); break; } case EverlookShader.GameModel: { shaderProgram = new GameModelShader(); break; } case EverlookShader.BaseGrid: { shaderProgram = new BaseGridShader(); break; } default: { throw new ArgumentOutOfRangeException ( nameof(shader), "No implemented shader class for this shader." ); } } _shaderCache.Add(shader, shaderProgram); return(shaderProgram); }
/// <inheritdoc /> public void Initialize() { ThrowIfDisposed(); if (this.IsInitialized) { return; } this.IsInitialized = true; this.Shader = this.Cache.GetShader(EverlookShader.WorldModel) as WorldModelShader; if (this.Shader == null) { throw new ShaderNullException(typeof(WorldModelShader)); } InitializeDoodads(); // TODO: Load and cache sound emitters // Load the textures used in this model foreach (string texture in this.Model.GetTextures()) { if (!string.IsNullOrEmpty(texture)) { if (!this.TextureLookup.ContainsKey(texture)) { this.TextureLookup.Add(texture, this.Cache.GetTexture(texture, this.GameContext.Assets)); } } } // TODO: Upload visible block vertices // TODO: Upload portal vertices for debug rendering // TODO: Load lights into some sort of reasonable structure // TODO: Load fog as OpenGL fog // TODO: Implement antiportal handling. For now, skip them // TODO: Upload convex planes for debug rendering foreach (ModelGroup modelGroup in this.Model.Groups) { InitializeModelGroup(modelGroup); } this.IsInitialized = true; }
/// <summary> /// Initializes the required data for rendering. /// </summary> public void Initialize() { this.Shader = this.Cache.GetShader(EverlookShader.WorldModel) as WorldModelShader; if (this.Shader == null) { throw new ShaderNullException(typeof(WorldModelShader)); } this.Shader.Wireframe.SetWireframeColour(EverlookConfiguration.Instance.GetWireframeColour()); // TODO: Load and cache doodads in their respective sets // TODO: Load and cache sound emitters // Load the textures used in this model foreach (string texture in this.Model.GetTextures()) { if (!string.IsNullOrEmpty(texture)) { CacheTexture(texture); } } // TODO: Upload visible block vertices // TODO: Upload portal vertices for debug rendering // TODO: Load lights into some sort of reasonable structure // TODO: Load fog as OpenGL fog // TODO: Implement antiportal handling. For now, skip them // TODO: Upload convex planes for debug rendering // TODO: Upload vertices, UVs and normals of groups in parallel buffers foreach (ModelGroup modelGroup in this.Model.Groups) { /* * Buffers */ int vertexBufferID; GL.GenBuffers(1, out vertexBufferID); int normalBufferID; GL.GenBuffers(1, out normalBufferID); int coordinateBufferID; GL.GenBuffers(1, out coordinateBufferID); int vertexIndicesID; GL.GenBuffers(1, out vertexIndicesID); int boundingBoxVertexBufferID; GL.GenBuffers(1, out boundingBoxVertexBufferID); // Upload all of the vertices in this group float[] groupVertexValues = modelGroup .GetVertices() .Select(v => v.Flatten()) .SelectMany(f => f) .ToArray(); GL.BindBuffer(BufferTarget.ArrayBuffer, vertexBufferID); GL.BufferData ( BufferTarget.ArrayBuffer, (IntPtr)(groupVertexValues.Length * sizeof(float)), groupVertexValues, BufferUsageHint.StaticDraw ); this.VertexBufferLookup.Add(modelGroup, vertexBufferID); // Upload all of the normals in this group float[] groupNormalValues = modelGroup .GetNormals() .Select(v => v.Flatten()) .SelectMany(f => f) .ToArray(); GL.BindBuffer(BufferTarget.ArrayBuffer, normalBufferID); GL.BufferData ( BufferTarget.ArrayBuffer, (IntPtr)(groupNormalValues.Length * sizeof(float)), groupNormalValues, BufferUsageHint.StaticDraw ); this.NormalBufferLookup.Add(modelGroup, normalBufferID); // Upload all of the UVs in this group float[] groupTextureCoordinateValues = modelGroup .GetTextureCoordinates() .Select(v => v.Flatten()) .SelectMany(f => f) .ToArray(); GL.BindBuffer(BufferTarget.ArrayBuffer, coordinateBufferID); GL.BufferData ( BufferTarget.ArrayBuffer, (IntPtr)(groupTextureCoordinateValues.Length * sizeof(float)), groupTextureCoordinateValues, BufferUsageHint.StaticDraw ); this.TextureCoordinateBufferLookup.Add(modelGroup, coordinateBufferID); // Upload vertex indices for this group ushort[] groupVertexIndexValuesArray = modelGroup.GetVertexIndices().ToArray(); GL.BindBuffer(BufferTarget.ElementArrayBuffer, vertexIndicesID); GL.BufferData ( BufferTarget.ElementArrayBuffer, (IntPtr)(groupVertexIndexValuesArray.Length * sizeof(ushort)), groupVertexIndexValuesArray, BufferUsageHint.StaticDraw ); this.VertexIndexBufferLookup.Add(modelGroup, vertexIndicesID); // Upload the corners of the bounding box float[] boundingBoxVertices = modelGroup.GetBoundingBox() .ToOpenGLBoundingBox() .GetCorners() .Select(v => v.AsSIMDVector().Flatten()) .SelectMany(f => f) .ToArray(); GL.BindBuffer(BufferTarget.ArrayBuffer, boundingBoxVertexBufferID); GL.BufferData ( BufferTarget.ArrayBuffer, (IntPtr)(boundingBoxVertices.Length * sizeof(float)), boundingBoxVertices, BufferUsageHint.StaticDraw ); this.BoundingBoxVertexBufferLookup.Add(modelGroup, boundingBoxVertexBufferID); } // The bounding box indices never differ for objects, so we'll initialize that here int boundingBoxVertexIndicesBufferID; GL.GenBuffers(1, out boundingBoxVertexIndicesBufferID); this.BoundingBoxVertexIndexBufferID = boundingBoxVertexIndicesBufferID; byte[] boundingBoxIndexValuesArray = { 0, 1, 1, 2, 2, 3, 3, 0, 0, 4, 4, 7, 7, 3, 2, 6, 6, 7, 6, 5, 5, 4, 5, 1 }; GL.BindBuffer(BufferTarget.ArrayBuffer, boundingBoxVertexIndicesBufferID); GL.BufferData ( BufferTarget.ArrayBuffer, (IntPtr)(boundingBoxIndexValuesArray.Length * sizeof(byte)), boundingBoxIndexValuesArray, BufferUsageHint.StaticDraw ); this.IsInitialized = true; }