public bool DeleteFromRegistry(ModelMeshPart mesh, TransformMatrix worldMatrix) { for (var i = 0; i < Index; i++) { MeshLibrary meshLib = _meshLib[i]; if (meshLib.HasMesh(mesh)) { if (meshLib.DeleteFromRegistry(worldMatrix)) //if true, we can delete it from registry { for (var j = i; j < Index - 1; j++) { //slide down one _meshLib[j] = _meshLib[j + 1]; } Index--; } break; } } if (Index <= 0) { return(true); //this material is no longer needed. } return(false); }
public void Register(ModelMeshPart mesh, TransformMatrix worldMatrix, BoundingSphere boundingSphere) { bool found = false; //Check if we already have a model like that, if yes put it in there! for (var i = 0; i < Index; i++) { MeshLibrary meshLib = _meshLib[i]; if (meshLib.HasMesh(mesh)) { meshLib.Register(worldMatrix); found = true; break; } } //We have no Lib yet, make a new one. if (!found) { _meshLib[Index] = new MeshLibrary(); _meshLib[Index].SetMesh(mesh); _meshLib[Index].SetBoundingSphere(boundingSphere); _meshLib[Index].Register(worldMatrix); Index++; } //If we exceeded our array length, make the array bigger. if (Index >= _meshLib.Length) { MeshLibrary[] tempLib = new MeshLibrary[Index + 1]; _meshLib.CopyTo(tempLib, 0); _meshLib = tempLib; } }
public void Draw(RenderType renderType, GraphicsDevice graphicsDevice, Matrix viewProjection, bool lightViewPointChanged = false, bool hasAnyObjectMoved = false, bool outlined = false, int outlineId = 0, Matrix?view = null) { //if (renderType != RenderType.Alpha) //{ graphicsDevice.BlendState = BlendState.Opaque; // graphicsDevice.RasterizerState = RasterizerState.CullNone; //} //For shadowmaps we need to find out whether any object has moved and if so if it is rendered. If yes, redraw the whole frame, if no don't do anything if (!lightViewPointChanged && hasAnyObjectMoved) { bool discardFrame = true; for (int index1 = 0; index1 < Index; index1++) { MaterialLibrary matLib = MaterialLib[index1]; //We determined beforehand whether something changed this frame if (matLib.HasChangedThisFrame) { for (int i = 0; i < matLib.Index; i++) { //Now we have to check whether we have a rendered thing in here MeshLibrary meshLib = matLib.GetMeshLibrary()[i]; for (int index = 0; index < meshLib.Index; index++) { //If it's set to "not rendered" skip for (int j = 0; j < meshLib.Rendered.Length; j++) { if (meshLib.Rendered[j]) { discardFrame = false; break; } } if (!discardFrame) { break; } } } if (!discardFrame) { break; } } } if (discardFrame) { return; } //graphicsDevice.Clear(new Color(0.51f, 0.501f, 0, 0)); graphicsDevice.Clear(Color.TransparentBlack); } for (int index1 = 0; index1 < Index; index1++) { MaterialLibrary matLib = MaterialLib[index1]; if (matLib.Index < 1) { continue; } //if none of this materialtype is drawn continue too! bool isUsed = false; for (int i = 0; i < matLib.Index; i++) { MeshLibrary meshLib = matLib.GetMeshLibrary()[i]; for (int index = 0; index < meshLib.Index; index++) { //If it's set to "not rendered" skip for (int j = 0; j < meshLib.Rendered.Length; j++) { if (meshLib.Rendered[j]) { isUsed = true; //if (meshLib.GetWorldMatrices()[j].HasChanged) // hasAnyObjectMoved = true; } if (isUsed)// && hasAnyObjectMoved) { break; } } if (isUsed)// && hasAnyObjectMoved) { break; } } } if (!isUsed) { continue; } //Count the draws of different materials! MaterialEffect material = /*GameSettings.DebugDrawUntextured==2 ? Art.DefaultMaterial :*/ matLib.GetMaterial(); //Check if alpha or opaque! Effect shader = null; //todo: We only need textures for non shadow mapping, right? Not quite actually, for alpha textures we need materials if (renderType == RenderType.TextureBuffer) { shader = Shaders.GBufferEffect; if (GameSettings.d_defaultMaterial) { Shaders.GBufferEffectParameter_Material_DiffuseColor.SetValue(Color.Gray.ToVector3()); Shaders.GBufferEffectParameter_Material_Roughness.SetValue(GameSettings.m_defaultRoughness > 0 ? GameSettings.m_defaultRoughness : 0.3f); Shaders.GBufferEffectParameter_Material_Metallic.SetValue(0.0f); Shaders.GBufferEffectParameter_Material_MaterialType.SetValue(0); Shaders.GBufferEffect.CurrentTechnique = Shaders.GBufferEffectTechniques_DrawBasic; } else { if (material.HasDisplacement) { Shaders.GBufferEffectParameter_Material_Texture.SetValue(material.AlbedoMap); Shaders.GBufferEffectParameter_Material_NormalMap.SetValue(material.NormalMap); Shaders.GBufferEffectParameter_Material_DisplacementMap.SetValue(material.DisplacementMap); Shaders.GBufferEffect.CurrentTechnique = Shaders.GBufferEffectTechniques_DrawTextureDisplacement; } else if (material.HasMask) //Has diffuse for sure then { if (material.HasNormalMap && material.HasRoughnessMap) { Shaders.GBufferEffectParameter_Material_MaskMap.SetValue(material.Mask); Shaders.GBufferEffectParameter_Material_Texture.SetValue(material.AlbedoMap); Shaders.GBufferEffectParameter_Material_NormalMap.SetValue(material.NormalMap); Shaders.GBufferEffectParameter_Material_RoughnessMap.SetValue(material.RoughnessMap); Shaders.GBufferEffect.CurrentTechnique = Shaders.GBufferEffectTechniques_DrawTextureSpecularNormalMask; } else if (material.HasNormalMap) { Shaders.GBufferEffectParameter_Material_MaskMap.SetValue(material.Mask); Shaders.GBufferEffectParameter_Material_Texture.SetValue(material.AlbedoMap); Shaders.GBufferEffectParameter_Material_NormalMap.SetValue(material.NormalMap); Shaders.GBufferEffect.CurrentTechnique = Shaders.GBufferEffectTechniques_DrawTextureNormalMask; } else if (material.HasRoughnessMap) { Shaders.GBufferEffectParameter_Material_MaskMap.SetValue(material.Mask); Shaders.GBufferEffectParameter_Material_Texture.SetValue(material.AlbedoMap); Shaders.GBufferEffectParameter_Material_RoughnessMap.SetValue(material.RoughnessMap); Shaders.GBufferEffect.CurrentTechnique = Shaders.GBufferEffectTechniques_DrawTextureSpecularMask; } else { Shaders.GBufferEffectParameter_Material_MaskMap.SetValue(material.Mask); Shaders.GBufferEffectParameter_Material_Texture.SetValue(material.AlbedoMap); Shaders.GBufferEffect.CurrentTechnique = Shaders.GBufferEffectTechniques_DrawTextureSpecularMask; } } else { if (material.HasNormalMap && material.HasRoughnessMap && material.HasDiffuse && material.HasMetallic) { Shaders.GBufferEffectParameter_Material_Texture.SetValue(material.AlbedoMap); Shaders.GBufferEffectParameter_Material_NormalMap.SetValue(material.NormalMap); Shaders.GBufferEffectParameter_Material_RoughnessMap.SetValue(material.RoughnessMap); Shaders.GBufferEffectParameter_Material_MetallicMap.SetValue(material.MetallicMap); Shaders.GBufferEffect.CurrentTechnique = Shaders.GBufferEffectTechniques_DrawTextureSpecularNormalMetallic; } else if (material.HasNormalMap && material.HasRoughnessMap && material.HasDiffuse) { Shaders.GBufferEffectParameter_Material_Texture.SetValue(material.AlbedoMap); Shaders.GBufferEffectParameter_Material_NormalMap.SetValue(material.NormalMap); Shaders.GBufferEffectParameter_Material_RoughnessMap.SetValue(material.RoughnessMap); Shaders.GBufferEffect.CurrentTechnique = Shaders.GBufferEffectTechniques_DrawTextureSpecularNormal; } else if (material.HasNormalMap && material.HasDiffuse) { Shaders.GBufferEffectParameter_Material_Texture.SetValue(material.AlbedoMap); Shaders.GBufferEffectParameter_Material_NormalMap.SetValue(material.NormalMap); Shaders.GBufferEffect.CurrentTechnique = Shaders.GBufferEffectTechniques_DrawTextureNormal; } else if (material.HasMetallic && material.HasRoughnessMap && material.HasDiffuse) { Shaders.GBufferEffectParameter_Material_Texture.SetValue(material.AlbedoMap); Shaders.GBufferEffectParameter_Material_RoughnessMap.SetValue(material.RoughnessMap); Shaders.GBufferEffect.CurrentTechnique = Shaders.GBufferEffectTechniques_DrawTextureSpecularMetallic; } else if (material.HasRoughnessMap && material.HasDiffuse) { Shaders.GBufferEffectParameter_Material_Texture.SetValue(material.AlbedoMap); Shaders.GBufferEffectParameter_Material_RoughnessMap.SetValue(material.RoughnessMap); Shaders.GBufferEffect.CurrentTechnique = Shaders.GBufferEffectTechniques_DrawTextureSpecular; } else if (material.HasDiffuse) { Shaders.GBufferEffectParameter_Material_Texture.SetValue(material.AlbedoMap); Shaders.GBufferEffect.CurrentTechnique = Shaders.GBufferEffectTechniques_DrawTexture; } else { Shaders.GBufferEffect.CurrentTechnique = Shaders.GBufferEffectTechniques_DrawBasic; } } if (!material.HasDiffuse) { if (material.Type == MaterialEffect.MaterialTypes.Emissive && material.EmissiveStrength > 0) { //{ Shaders.GBufferEffectParameter_Material_DiffuseColor.SetValue(material.DiffuseColor * material.EmissiveStrength); } //* Math.Max(material.EmissiveStrength,1)); //} else { //{ Shaders.GBufferEffectParameter_Material_DiffuseColor.SetValue(material.DiffuseColor); } //} } if (!material.HasRoughnessMap) { Shaders.GBufferEffectParameter_Material_Roughness.SetValue(GameSettings.m_defaultRoughness > 0 ? GameSettings.m_defaultRoughness : material.Roughness); } Shaders.GBufferEffectParameter_Material_Metallic.SetValue(material.Metallic); Shaders.GBufferEffectParameter_Material_MaterialType.SetValue(material.MaterialTypeNumber); } } for (int i = 0; i < matLib.Index; i++) { MeshLibrary meshLib = matLib.GetMeshLibrary()[i]; //Initialize the mesh VB and IB graphicsDevice.SetVertexBuffer(meshLib.GetMesh().VertexBuffer); graphicsDevice.Indices = (meshLib.GetMesh().IndexBuffer); int primitiveCount = meshLib.GetMesh().PrimitiveCount; int vertexOffset = meshLib.GetMesh().VertexOffset; //int vCount = meshLib.GetMesh().NumVertices; int startIndex = meshLib.GetMesh().StartIndex; //Now draw the local meshes! for (int index = 0; index < meshLib.Index; index++) { //If it's set to "not rendered" skip //if (!meshLib.GetWorldMatrices()[index].Rendered) continue; if (!meshLib.Rendered[index]) { continue; } Matrix localWorldMatrix = meshLib.GetWorldMatrices()[index].World; if (renderType == RenderType.TextureBuffer) { Shaders.GBufferEffectParameter_World.SetValue(localWorldMatrix); Shaders.GBufferEffectParameter_WorldViewProj.SetValue(localWorldMatrix * viewProjection); Matrix world = Matrix.Transpose(Matrix.Invert(localWorldMatrix)); Shaders.GBufferEffectParameter_WorldIT.SetValue(world); shader.CurrentTechnique.Passes[0].Apply(); } else if (renderType == RenderType.FinalMesh) { Shaders.GBufferEffectParameter_WorldViewProj.SetValue(localWorldMatrix * viewProjection); Shaders.GBufferEffectTechniques_DrawBasicMesh.Passes[0].Apply(); } if (material.RenderCClockwise) { graphicsDevice.RasterizerState = RasterizerState.CullClockwise; } GameStats.MeshDraws++; try { graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, vertexOffset, startIndex, primitiveCount); } catch (Exception) { // do nothing } if (material.RenderCClockwise) { graphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise; } //only once if (renderType == RenderType.TextureBuffer) { return; } } } } //Update the drawcalls in our stats }
/// <summary> /// Update whether or not Objects are in the viewFrustum and need to be rendered or not. /// </summary> /// <param name="entities"></param> /// <param name="boundingFrustrum"></param> /// <param name="hasCameraChanged"></param> public bool FrustumCulling(List <BasicEntity> entities, BoundingFrustum boundingFrustrum, bool hasCameraChanged, Vector3 cameraPosition) { //Check if the culling mode has changed if (_previousMode != GameSettings.g_CPU_Culling) { if (_previousMode) { //If we previously did cull and now don't we need to set all the submeshes to render for (int index1 = 0; index1 < Index; index1++) { MaterialLibrary matLib = MaterialLib[index1]; for (int i = 0; i < matLib.Index; i++) { MeshLibrary meshLib = matLib.GetMeshLibrary()[i]; for (int j = 0; j < meshLib.Rendered.Length; j++) { meshLib.Rendered[j] = _previousMode; } } } } _previousMode = GameSettings.g_CPU_Culling; } if (!GameSettings.g_CPU_Culling) { return(false); } for (int index1 = 0; index1 < entities.Count; index1++) { BasicEntity entity = entities[index1]; if (!hasCameraChanged && !entity.WorldTransform.HasChanged)// && entity.DynamicPhysicsObject == null) { continue; } if (entity.WorldTransform.HasChanged)// || entity.DynamicPhysicsObject != null) { entity.ApplyTransformation(); } } bool hasAnythingChanged = false; //Ok we applied the transformation to all the entities, now update the submesh boundingboxes! // Parallel.For(0, Index, index1 => for (int index1 = 0; index1 < Index; index1++) { float distance = 0; int counter = 0; MaterialLibrary matLib = GameSettings.g_CPU_Sort ? MaterialLib[MaterialLibPointer[index1]] : MaterialLib[index1]; for (int i = 0; i < matLib.Index; i++) { MeshLibrary meshLib = matLib.GetMeshLibrary()[i]; float? distanceSq = meshLib.UpdatePositionAndCheckRender(hasCameraChanged, boundingFrustrum, cameraPosition, _defaultBoundingSphere); //If we get a new distance, apply it to the material if (distanceSq != null) { distance += (float)distanceSq; counter++; hasAnythingChanged = true; } } if (Math.Abs(distance) > 0.00001f) { distance /= counter; matLib.DistanceSquared = distance; matLib.HasChangedThisFrame = true; } } //); //finally sort the materials by distance. Bubble sort should in theory be fast here since little changes. if (hasAnythingChanged) { SortByDistance(); } return(hasAnythingChanged); }