void RenderGraphObject(GraphObject graphObject, RenderFlags renderFlags) { // visibility check if (!graphObject.Visible) { return; } // render-flag check if (!renderFlags.HasFlag(RenderFlags.Ceilings) && graphObject.HasRenderFlag(GraphObjectRenderFlags.Ceiling)) { return; } if (!renderFlags.HasFlag(RenderFlags.FourthWalls) && graphObject.HasRenderFlag(GraphObjectRenderFlags.FourthWall)) { return; } // matrix transformations GL.PushMatrix(); TransformMatrix(graphObject.Position, graphObject.Rotation, graphObject.Scale); // bounding box if (renderFlags.HasFlag(RenderFlags.BoundingBox)) { GL.Disable(EnableCap.Lighting); GL.Disable(EnableCap.Texture2D); GL.Color3(Color.Yellow); GLUtility.WireCube(graphObject.BoundingBox * GlobalScaleReciprocal); GL.Color3(Color.White); GL.Enable(EnableCap.Texture2D); GL.Enable(EnableCap.Lighting); } if (graphObject.HasRenderFlag(GraphObjectRenderFlags.FullBright)) { GL.Disable(EnableCap.Lighting); } // Render parts. foreach (var part in graphObject) { if (shaders[part.ShaderIndex].Tint.A > 0 && ((shaders[part.ShaderIndex].Tint.A == Color.Opaque && renderFlags.HasFlag(RenderFlags.Opaque)) || (shaders[part.ShaderIndex].Tint.A < Color.Opaque && renderFlags.HasFlag(RenderFlags.Translucent)))) { RenderPart(part, renderFlags); } } GL.Enable(EnableCap.Lighting); // Render children. for (int childIndex = graphObject.ChildIndex; childIndex >= 0; childIndex = graphObjects[childIndex].NextIndex) { RenderGraphObject(graphObjects[childIndex], renderFlags); } GL.PopMatrix(); }
void RenderGrid(int gridSize) { GL.Disable(EnableCap.Lighting); GLUtility.DisableTexture2D(); GL.Begin(BeginMode.Lines); for (int z = -gridSize; z <= gridSize; z++) { GL.Color3(Color.White); GL.Vertex3(-gridSize, 0.0f, z); GL.Vertex3(gridSize, 0.0f, z); } for (int x = -gridSize; x <= gridSize; x++) { GL.Color3(Color.White); GL.Vertex3(x, 0.0f, -gridSize); GL.Vertex3(x, 0.0f, gridSize); } GL.End(); GLUtility.EnableTexture2D(); GL.Enable(EnableCap.Lighting); }
void RenderPart(Part part, RenderFlags renderFlags) { GL.Material(MaterialFace.Front, MaterialParameter.Diffuse, shaders[part.ShaderIndex].Tint.ToColor4()); var batch = batches[part.BatchIndex]; if (batch.UseNBT) // Render with bump map. { int binormalAttribute = GL.GetAttribLocation(Program.EmbossProgram, "inBinormal"); int tangentAttribute = GL.GetAttribLocation(Program.EmbossProgram, "inTangent"); int diffuseMap = GL.GetUniformLocation(Program.EmbossProgram, "diffuseMap"); int bumpMap = GL.GetUniformLocation(Program.EmbossProgram, "bumpMap"); int embossFactor = GL.GetUniformLocation(Program.EmbossProgram, "embossScale"); Program.EmbossProgram.Use(); GL.ActiveTexture(TextureUnit.Texture0 + 0); GL.Enable(EnableCap.Texture2D); GL.BindTexture(TextureTarget.Texture2D, glTextures[materials[shaders[part.ShaderIndex].MaterialIndex[0]].textureIndex]); GLUtility.SetTexture2DWrapModeS(materials[shaders[part.ShaderIndex].MaterialIndex[0]].wrapS); GLUtility.SetTexture2DWrapModeT(materials[shaders[part.ShaderIndex].MaterialIndex[0]].wrapT); GL.Uniform1(diffuseMap, 0); GL.ActiveTexture(TextureUnit.Texture0 + 1); GL.Enable(EnableCap.Texture2D); GL.BindTexture(TextureTarget.Texture2D, glTextures[materials[shaders[part.ShaderIndex].MaterialIndex[1]].textureIndex]); GLUtility.SetTexture2DWrapModeS(materials[shaders[part.ShaderIndex].MaterialIndex[1]].wrapS); GLUtility.SetTexture2DWrapModeT(materials[shaders[part.ShaderIndex].MaterialIndex[1]].wrapT); GL.Uniform1(bumpMap, 1); GL.Uniform1(embossFactor, 2.0f); foreach (var primitive in batch) { GL.Begin(primitive.GLType); foreach (var vertex in primitive) { GL.MultiTexCoord2(TextureUnit.Texture0 + 0, ref texCoord0s[vertex.UVIndex[0].Value]); GL.MultiTexCoord2(TextureUnit.Texture0 + 1, ref texCoord1s[vertex.UVIndex[1].Value]); GL.Normal3(normals[vertex.NormalIndex.Value]); GL.VertexAttrib3(tangentAttribute, ref normals[vertex.BinormalIndex.Value + 1]); GL.VertexAttrib3(binormalAttribute, ref normals[vertex.TangentIndex.Value + 2]); GL.Vertex3(positions[vertex.PositionIndex.Value]); } GL.End(); } GL.UseProgram(0); } else // Render without bump map. { for (int texUnit = 0; texUnit < 8; texUnit++) { if (shaders[part.ShaderIndex].MaterialIndex[texUnit] < 0) { continue; } var material = materials[shaders[part.ShaderIndex].MaterialIndex[texUnit]]; GL.ActiveTexture(TextureUnit.Texture0 + texUnit); GL.Enable(EnableCap.Texture2D); GL.BindTexture(TextureTarget.Texture2D, glTextures[material.textureIndex]); GLUtility.SetTexture2DWrapModeS(material.wrapS); GLUtility.SetTexture2DWrapModeT(material.wrapT); } foreach (var primitive in batch) { GL.Begin(primitive.GLType); foreach (var vertex in primitive) { if (vertex.UVIndex[0] != null) { GL.MultiTexCoord2(TextureUnit.Texture0, ref texCoord0s[vertex.UVIndex[0].Value]); } if (vertex.NormalIndex != null) { GL.Normal3(normals[vertex.NormalIndex.Value]); } GL.Vertex3(positions[vertex.PositionIndex.Value]); } GL.End(); } } GLUtility.DisableTexture2D(); // normals if (renderFlags.HasFlag(RenderFlags.NBT)) { const float normalLength = 0.0625f; GL.Disable(EnableCap.Lighting); GL.Begin(BeginMode.Lines); foreach (var primitive in batch) { foreach (var vertex in primitive) { if (vertex.NormalIndex != null) { GL.Color4(Color.Red.ToColor4()); GL.Vertex3(positions[vertex.PositionIndex.Value]); GL.Vertex3(positions[vertex.PositionIndex.Value] + normals[vertex.NormalIndex.Value] * normalLength); } if (vertex.TangentIndex != null) { GL.Color4(Color.Green.ToColor4()); GL.Vertex3(positions[vertex.PositionIndex.Value]); GL.Vertex3(positions[vertex.PositionIndex.Value] + normals[vertex.TangentIndex.Value + 2] * normalLength); } if (vertex.BinormalIndex != null) { GL.Color4(Color.Blue.ToColor4()); GL.Vertex3(positions[vertex.PositionIndex.Value]); GL.Vertex3(positions[vertex.PositionIndex.Value] + normals[vertex.BinormalIndex.Value + 1] * normalLength); } } } GL.End(); GL.Enable(EnableCap.Lighting); } }
void Render() { // Refresh. GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); // Enable crap. GL.Enable(EnableCap.Blend); GL.Enable(EnableCap.CullFace); GL.Enable(EnableCap.DepthTest); GL.Enable(EnableCap.LineSmooth); GLUtility.EnableTexture2D(); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); GL.FrontFace(FrontFaceDirection.Cw); GL.Hint(HintTarget.LineSmoothHint, HintMode.Nicest); GL.LineWidth(1.0f); GL.PolygonMode(MaterialFace.Front, polygonMode); GL.ShadeModel(ShadingModel.Smooth); // Set the viewpoint. GL.MatrixMode(MatrixMode.Modelview); GL.LoadIdentity(); Matrix4 cameraMatrix = CameraMatrix; GL.Rotate(camera.rot.Z, Vector3.UnitZ); GL.Rotate(camera.rot.X, Vector3.UnitX); GL.Rotate(camera.rot.Y, Vector3.UnitY); GL.Scale(1.0f, 1.0f, 1.0f); GL.MultMatrix(ref cameraMatrix); // Set up lighting. GL.Enable(EnableCap.Lighting); GL.Light(LightName.Light0, LightParameter.Ambient, new Color(127).ToColor4()); GL.Light(LightName.Light0, LightParameter.Position, new Vector4(camera.pos.ToVector3(), 1.0f)); GL.Enable(EnableCap.Light0); // Render models (opaque first, then translucent). if (HasModelsLoaded) { RenderFlags flags = RenderFlags.None; if (showBoundingBoxes) { flags |= RenderFlags.BoundingBox; } if (showCeilings) { flags |= RenderFlags.Ceilings; } if (showFourthWalls) { flags |= RenderFlags.FourthWalls; } if (showNBT) { flags |= RenderFlags.NBT; } loadedModels.ForEach(model => model.Render(RenderFlags.Opaque | flags)); loadedModels.ForEach(model => model.Render(RenderFlags.Translucent | flags)); } // Render grid. if (showGrid) { RenderGrid(20); } // Swap the front and back buffers. gl_frame.SwapBuffers(); }