//TODO: Refactor renderFlag preEffectsInstancingFlag and instancingFlag into an class/struct public ModelRuntimeDescriptor(Model <T, RealtimeMaterial> modelIn, string vShaderName, string fShaderName, VertexRuntimeTypes vertexRuntimeType, PrimitiveTopology primitiveTopology, RenderDescription renderDescription, InstancingRenderDescription instancingRenderDescription) { if (!Verifier.VerifyVertexStruct <T>(vertexRuntimeType)) { throw new ArgumentException($"Type Mismatch ModelRuntimeDescriptor"); } Model = modelIn; Length = modelIn.MeshCount; TotalInstanceCount = 1; _vertexShaderName = vShaderName; _fragmentShaderName = fShaderName; VertexRuntimeType = vertexRuntimeType; PrimitiveTopology = primitiveTopology; RenderDescription = renderDescription; PreEffectsFlag = RenderFlags.PRE_EFFECTS_MASK & renderDescription.RenderModeFlag; PreEffectsInstancingFlag = instancingRenderDescription.PreEffectsFlag; InstancingDataFlag = instancingRenderDescription.RenderModeFlag; var preEffectsInstancing = RenderFlags.GetAllPreEffectFor(PreEffectsInstancingFlag); VertexBufferList = new List <DeviceBuffer>(); IndexBufferList = new List <DeviceBuffer>(); Pipelines = new Pipeline[RenderFlags.EFFCTS_TOTAL_COUNT]; InstanceBufferLists = new List <DeviceBuffer> [RenderFlags.EFFCTS_TOTAL_COUNT]; InstanceBufferLists[RenderFlags.NORMAL_ARRAY_INDEX] = new List <DeviceBuffer>(); foreach (var preEffect in preEffectsInstancing) { InstanceBufferLists[RenderFlags.GetArrayIndexForFlag(preEffect)] = new List <DeviceBuffer>(); } InstanceBuffers = new DeviceBuffer[RenderFlags.EFFCTS_TOTAL_COUNT][]; TextureResourceSetsList = new List <ResourceSet>(); VertexInstanceLayoutGenerationList = new EventHandlerList(); VertexPreEffectsInstanceLayoutGenerationList = new EventHandlerList(); VertexPreEffectShaders = new Shader[RenderFlags.PRE_EFFCTS_TOTAL_COUNT]; GeometryPreEffectShaders = new Shader[RenderFlags.PRE_EFFCTS_TOTAL_COUNT]; FragmentPreEffectShaders = new Shader[RenderFlags.PRE_EFFCTS_TOTAL_COUNT]; // Reserve first spot for base vertex geometry //TODO: Make on list VertexLayouts = new VertexLayoutDescription[InstancingDataFlags.GetSizeOfPreEffectFlag(InstancingDataFlag) + 1]; VertexPreEffectsLayouts = new VertexLayoutDescription[RenderFlags.GetSizeOfPreEffectFlag(PreEffectsInstancingFlag) + 1]; EffectResourceSets = new ResourceSet[RenderFlags.EFFCTS_TOTAL_COUNT][]; for (int i = 0; i < RenderFlags.EFFCTS_TOTAL_COUNT; i++) { EffectResourceSets[i] = new ResourceSet[0]; } }
public void LoadShaders(GraphicsDevice graphicsDevice) { VertexShader = IO.LoadShader(_vertexShaderName, ShaderStages.Vertex, graphicsDevice); FragmentShader = IO.LoadShader(_fragmentShaderName, ShaderStages.Fragment, graphicsDevice); var preEffects = RenderFlags.GetAllPreEffectFor(PreEffectsFlag); foreach (var flag in preEffects) { var arrayIndex = RenderFlags.GetPreEffectArrayIndexForFlag(flag); var name = ShaderNames.PreEffectShaderNames[arrayIndex]; VertexPreEffectShaders[arrayIndex] = IO.LoadShader(name, ShaderStages.Vertex, graphicsDevice); GeometryPreEffectShaders[arrayIndex] = IO.LoadShader(name, ShaderStages.Geometry, graphicsDevice); FragmentPreEffectShaders[arrayIndex] = IO.LoadShader(name, ShaderStages.Fragment, graphicsDevice); } }
/// <summary> /// Sets delegates for runtime command generation. /// Also updates index and vertex buffers, sets pipeline /// </summary> /// <param name="modelDescriptor">Model descriptor.</param> /// <param name="sceneRuntimeDescriptor">Scene runtime descriptor.</param> /// <param name="instancingData">Instance data enumerable.</param> /// <typeparam name="T">The type of Vertex sent to the GPU</typeparam> protected void FillRuntimeDescriptor <T>(ModelRuntimeDescriptor <T> modelDescriptor, SceneRuntimeDescriptor sceneRuntimeDescriptor, IEnumerable <InstanceData> instancingData) where T : struct, VertexRuntime, VertexLocateable { var model = modelDescriptor.Model; modelDescriptor.TextureResourceLayout = modelDescriptor.InvokeTextureResourceLayoutGeneration(_factory); modelDescriptor.TextureSampler = modelDescriptor.InvokeSamplerGeneration(_factory); modelDescriptor.LoadShaders(_graphicsDevice); byte vertexSizeInBytes = model.GetMesh(0).Vertices[0].GetSizeInBytes(); var meshCount = model.MeshCount; for (int i = 0; i < meshCount; i++) { var mesh = model.GetMesh(i); var meshBVH = model.GetMeshBVH(i); DeviceBuffer vertexBuffer = _factory.CreateBuffer(new BufferDescription(mesh.Vertices.LengthUnsigned() * vertexSizeInBytes, BufferUsage.VertexBuffer)); DeviceBuffer indexBuffer = _factory.CreateBuffer(new BufferDescription(mesh.Indices.LengthUnsigned() * sizeof(ushort), BufferUsage.IndexBuffer)); modelDescriptor.VertexBufferList.Add(vertexBuffer); modelDescriptor.IndexBufferList.Add(indexBuffer); var allInstancePreEffects = RenderFlags.GetAllPreEffectFor(modelDescriptor.PreEffectsInstancingFlag); foreach (var instanceData in instancingData) { var instanceDataBuffer = ResourceGenerator.AllocateInstanceDataBuffer(instanceData, _graphicsDevice, _factory); if (instanceDataBuffer != null) { modelDescriptor.InstanceBufferLists[RenderFlags.NORMAL_ARRAY_INDEX].Add(instanceDataBuffer); foreach (var preEffect in allInstancePreEffects) { modelDescriptor.InstanceBufferLists[RenderFlags.GetArrayIndexForFlag(preEffect)].Add(instanceDataBuffer); } } } _graphicsDevice.UpdateBuffer <T>(vertexBuffer, 0, ref mesh.Vertices[0], (vertexSizeInBytes * mesh.VertexCount).ToUnsigned()); _graphicsDevice.UpdateBuffer <ushort>(indexBuffer, 0, ref mesh.Indices[0], (sizeof(ushort) * mesh.IndexCount).ToUnsigned()); var resourceSet = modelDescriptor.InvokeTextureResourceSetGeneration(i, _factory, _graphicsDevice); if (resourceSet != null) { modelDescriptor.TextureResourceSetsList.Add(resourceSet); } } var rasterizerStateCullBack = new RasterizerStateDescription( cullMode: FaceCullMode.Back, fillMode: PolygonFillMode.Solid, frontFace: FrontFace.Clockwise, depthClipEnabled: true, scissorTestEnabled: false ); var rasterizerStateCullFront = new RasterizerStateDescription( cullMode: FaceCullMode.Front, fillMode: PolygonFillMode.Solid, frontFace: FrontFace.Clockwise, depthClipEnabled: true, scissorTestEnabled: false ); var rasterizerStateCullNone = new RasterizerStateDescription( cullMode: FaceCullMode.None, fillMode: PolygonFillMode.Solid, frontFace: FrontFace.Clockwise, depthClipEnabled: true, scissorTestEnabled: false ); modelDescriptor.InvokeVertexLayoutGeneration(); var shadowMapIndex = RenderFlags.GetArrayIndexForFlag(RenderFlags.SHADOW_MAP); var omniShadowMapIndex = RenderFlags.GetArrayIndexForFlag(RenderFlags.OMNI_SHADOW_MAPS); modelDescriptor.Pipelines[shadowMapIndex] = modelDescriptor.ShadowMapEnabled ? _factory.CreateGraphicsPipeline(PipelineGenerator.GenerateShadowMappingPreEffectPipeline(modelDescriptor, _childrenPre[RenderFlags.GetPreEffectArrayIndexForFlag(RenderFlags.SHADOW_MAP)].SceneRuntimeDescriptor, rasterizerStateCullFront, RenderFlags.SHADOW_MAP, _childrenPre[RenderFlags.GetPreEffectArrayIndexForFlag(RenderFlags.SHADOW_MAP)].FrameBuffer)) : null; modelDescriptor.Pipelines[omniShadowMapIndex] = modelDescriptor.OmniShadowMapEnabled ? _factory.CreateGraphicsPipeline(PipelineGenerator.GenerateOmniShadowMappingPreEffectPipeline(modelDescriptor, _childrenPre[0].SceneRuntimeDescriptor, rasterizerStateCullNone, RenderFlags.OMNI_SHADOW_MAPS, _childrenPre[0].FrameBuffer)) : null; var effectLayoutArray = modelDescriptor.FillEffectsResourceSet(_factory, sceneRuntimeDescriptor, _childrenPre); var normalIndex = RenderFlags.GetArrayIndexForFlag(RenderFlags.NORMAL); switch (modelDescriptor.VertexRuntimeType) { // Only cube maps for now case VertexRuntimeTypes.VertexPosition: //TODO: Use proper constants from RenderFlags.cs modelDescriptor.Pipelines[normalIndex] = _factory.CreateGraphicsPipeline(PipelineGenerator.GeneratePipelineP(modelDescriptor, sceneRuntimeDescriptor, rasterizerStateCullFront, _graphicsDevice.SwapchainFramebuffer, effectLayoutArray)); break; case VertexRuntimeTypes.VertexPositionNormal: modelDescriptor.Pipelines[normalIndex] = _factory.CreateGraphicsPipeline(PipelineGenerator.GeneratePipelinePN(modelDescriptor, sceneRuntimeDescriptor, rasterizerStateCullBack, _graphicsDevice.SwapchainFramebuffer, effectLayoutArray)); break; case VertexRuntimeTypes.VertexPositionNormalTextureTangentBitangent: modelDescriptor.Pipelines[normalIndex] = _factory.CreateGraphicsPipeline(PipelineGenerator.GeneratePipelinePNTTB(modelDescriptor, sceneRuntimeDescriptor, rasterizerStateCullBack, _graphicsDevice.SwapchainFramebuffer, effectLayoutArray)); break; case VertexRuntimeTypes.VertexPositionColor: modelDescriptor.Pipelines[normalIndex] = _factory.CreateGraphicsPipeline(PipelineGenerator.GeneratePipelinePC(modelDescriptor, sceneRuntimeDescriptor, rasterizerStateCullBack, _graphicsDevice.SwapchainFramebuffer, effectLayoutArray)); break; case VertexRuntimeTypes.VertexPositionTexture: modelDescriptor.Pipelines[normalIndex] = _factory.CreateGraphicsPipeline(PipelineGenerator.GeneratePipelinePT(modelDescriptor, sceneRuntimeDescriptor, rasterizerStateCullBack, _graphicsDevice.SwapchainFramebuffer, effectLayoutArray)); break; default: throw new NotImplementedException($"{modelDescriptor.VertexRuntimeType.ToString("g")} not implemented"); } }