/// <summary> /// Initializes a new instance of the <see cref="Mesh" /> class. /// </summary> /// <param name="meshDraw">The mesh draw.</param> /// <param name="parameters">The parameters.</param> /// <exception cref="System.ArgumentNullException">parameters</exception> public Mesh(MeshDraw meshDraw, ParameterCollection parameters) { if (meshDraw == null) { throw new ArgumentNullException("meshDraw"); } if (parameters == null) { throw new ArgumentNullException("parameters"); } Draw = meshDraw; Parameters = parameters; }
private InputElementDescription[] PrepareInputElements(PipelineStateDescription pipelineState, MeshDraw drawData) { // Get the input elements already contained in the mesh's vertex buffers var availableInputElements = drawData.VertexBuffers.CreateInputElements(); var inputElements = new List <InputElementDescription>(availableInputElements); // In addition, add input elements for all attributes that are not contained in a bound buffer, but required by the shader foreach (var inputAttribute in pipelineState.EffectBytecode.Reflection.InputAttributes) { var inputElementIndex = FindElementBySemantic(availableInputElements, inputAttribute.SemanticName, inputAttribute.SemanticIndex); // Provided by any vertex buffer? if (inputElementIndex >= 0) { continue; } inputElements.Add(new InputElementDescription { AlignedByteOffset = 0, Format = PixelFormat.R32G32B32A32_Float, InputSlot = drawData.VertexBuffers.Length, InputSlotClass = InputClassification.Vertex, InstanceDataStepRate = 0, SemanticIndex = inputAttribute.SemanticIndex, SemanticName = inputAttribute.SemanticName, }); } return(inputElements.ToArray()); }
/// <inheritdoc/> public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { var commandList = context.CommandList; foreach (var renderFeature in RenderFeatures) { renderFeature.Draw(context, renderView, renderViewStage, startIndex, endIndex); } // TODO: stackalloc? var descriptorSetsLocal = descriptorSets.Value; if (descriptorSetsLocal == null || descriptorSetsLocal.Length < EffectDescriptorSetSlotCount) { descriptorSetsLocal = descriptorSets.Value = new DescriptorSet[EffectDescriptorSetSlotCount]; } MeshDraw currentDrawData = null; int emptyBufferSlot = -1; for (int index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; var renderNode = GetRenderNode(renderNodeReference); var renderMesh = (RenderMesh)renderNode.RenderObject; var drawData = renderMesh.ActiveMeshDraw; // Get effect // TODO: Use real effect slot var renderEffect = renderNode.RenderEffect; if (renderEffect.Effect == null) { continue; } // Bind VB if (currentDrawData != drawData) { for (int slot = 0; slot < drawData.VertexBuffers.Length; slot++) { var vertexBuffer = drawData.VertexBuffers[slot]; commandList.SetVertexBuffer(slot, vertexBuffer.Buffer, vertexBuffer.Offset, vertexBuffer.Stride); } // If the mesh's vertex buffers miss any input streams, an additional input binding will have been added to the pipeline state. // We bind an additional empty vertex buffer to that slot handle those streams gracefully. if (emptyBufferSlot != drawData.VertexBuffers.Length) { commandList.SetVertexBuffer(drawData.VertexBuffers.Length, emptyBuffer, 0, 0); emptyBufferSlot = drawData.VertexBuffers.Length; } if (drawData.IndexBuffer != null) { commandList.SetIndexBuffer(drawData.IndexBuffer.Buffer, drawData.IndexBuffer.Offset, drawData.IndexBuffer.Is32Bit); } currentDrawData = drawData; } var resourceGroupOffset = ComputeResourceGroupOffset(renderNodeReference); // Update cbuffer renderEffect.Reflection.BufferUploader.Apply(context.CommandList, ResourceGroupPool, resourceGroupOffset); // Bind descriptor sets for (int i = 0; i < descriptorSetsLocal.Length; ++i) { var resourceGroup = ResourceGroupPool[resourceGroupOffset++]; if (resourceGroup != null) { descriptorSetsLocal[i] = resourceGroup.DescriptorSet; } } commandList.SetPipelineState(renderEffect.PipelineState); commandList.SetDescriptorSets(0, descriptorSetsLocal); // Draw if (drawData.IndexBuffer == null) { if (renderMesh.InstanceCount > 0) { commandList.DrawInstanced(drawData.DrawCount, renderMesh.InstanceCount, drawData.StartLocation); } else { commandList.Draw(drawData.DrawCount, drawData.StartLocation); } } else { if (renderMesh.InstanceCount > 0) { commandList.DrawIndexedInstanced(drawData.DrawCount, renderMesh.InstanceCount, drawData.StartLocation); } else { commandList.DrawIndexed(drawData.DrawCount, drawData.StartLocation); } } } }
public void LoadAssetTest(Vector3 position) { // Create a new entity and add it to the scene. var entity = new Entity(); var rootScene = SceneSystem.SceneInstance.RootScene; entity.Transform.RotationEulerXYZ = new Vector3(0, 20, 0); entity.Transform.Scale = new Vector3(0.2f, 0.2f, 0.2f); entity.Transform.Position = position; // Create a new model from code // https://doc.xenko.com/latest/en/manual/scripts/create-a-model-from-code.html // Create a model and assign it to the model component. var model = new Stride.Rendering.Model(); entity.GetOrCreate <ModelComponent>().Model = model; // Add one or more meshes using geometric primitives (eg spheres or cubes). //var meshDraw = Stride.Graphics.GeometricPrimitives.GeometricPrimitive.Sphere.New(GraphicsDevice).ToMeshDraw(); //var mesh = new Stride.Rendering.Mesh { Draw = meshDraw }; //model.Meshes.Add(mesh); // create the Mesh // https://github.com/stride3d/stride/blob/master/sources/editor/Stride.Assets.Presentation/AssetEditors/Gizmos/LightSpotGizmo.cs#L168 var CWD = System.IO.Directory.GetCurrentDirectory(); var assetBase = System.IO.Path.GetFullPath(System.IO.Path.Combine(CWD, @"..\..\..\DynLoadAssets\drone2\")); var assetPath = (System.IO.Path.Combine(assetBase, "Drone2.obj")); if (!System.IO.File.Exists(assetPath)) { // not sure why, but DebugText.Print isn't working at the time of testing this... DebugText.Print("Cannot find wavefront OBJ file at : " + assetPath, new Int2(50, 50)); return; } // load the wavefront OBJ file... var wfData = new SimpleScene.Util3d.WavefrontObjLoader(assetPath); // TODO: iterate over materials / multiple materials on the same mesh... { VertexPositionNormalTexture[] vertices; UInt32[] triIndices; Wavefront_VertexSoup_Stride3d.generateDrawIndexBuffer(wfData, wfData.materials[0], out triIndices, out vertices); // convert into a graphics VB / IB pair var vertexBuffer = Stride.Graphics.Buffer.Vertex.New(GraphicsDevice, vertices, GraphicsResourceUsage.Dynamic); var indexBuffer = Stride.Graphics.Buffer.Index.New(GraphicsDevice, triIndices); // add them to the drawing var meshDraw = new Stride.Rendering.MeshDraw { /* Vertex buffer and index buffer setup */ PrimitiveType = Stride.Graphics.PrimitiveType.TriangleList, DrawCount = triIndices.Length, VertexBuffers = new[] { new VertexBufferBinding(vertexBuffer, VertexPositionNormalTexture.Layout, vertexBuffer.ElementCount) }, IndexBuffer = new IndexBufferBinding(indexBuffer, true, triIndices.Length), }; // GenerateTangentBinormal() won't work on a GPU buffer. It has to be run when the data is attached to a // fake CPU buffer. (see build pipeline code) // meshDraw.GenerateTangentBinormal(); var customMesh = new Stride.Rendering.Mesh { Draw = meshDraw }; // set the material index for this mesh // customMesh.MaterialIndex = 0; // add the mesh to the model model.Meshes.Add(customMesh); } // load a texture from a file // var diffuseTextureFilename = System.IO.Path.Combine(assetBase,wfData.materials[0].mtl.diffuseTextureResourceName); // var diffTexStream = System.IO.File.Open(diffuseTextureFilename,System.IO.FileMode.Open,System.IO.FileAccess.Read); // var diffuseTexture = Texture.Load(GraphicsDevice,diffTexStream); // TODO: handle null textures var diffuseTexture = textureObjectForWfTex(System.IO.Path.Combine(assetBase, wfData.materials[0].mtl.diffuseTextureResourceName)); var specularTexture = textureObjectForWfTex(System.IO.Path.Combine(assetBase, wfData.materials[0].mtl.specularTextureResourceName)); var emissiveTexture = textureObjectForWfTex(System.IO.Path.Combine(assetBase, wfData.materials[0].mtl.ambientTextureResourceName)); // note: bump/normal mapping won't won't work until Bitangents are calculated // var bumpTexture = textureObjectForWfTex(System.IO.Path.Combine(assetBase,wfData.materials[0].mtl.bumpTextureResourceName)); var cc = new ComputeColor(); #if (true) { // load textures var materialDescription = new Stride.Rendering.Materials.MaterialDescriptor { Attributes = { DiffuseModel = new MaterialDiffuseLambertModelFeature(), Diffuse = new MaterialDiffuseMapFeature(new ComputeTextureColor(diffuseTexture)), SpecularModel = new MaterialSpecularMicrofacetModelFeature { }, Specular = new MaterialSpecularMapFeature { SpecularMap = new ComputeTextureColor(specularTexture) }, MicroSurface = new MaterialGlossinessMapFeature { GlossinessMap = new ComputeFloat(0.7f) }, Emissive = new MaterialEmissiveMapFeature(new ComputeTextureColor(emissiveTexture)), // note: normal maps won't work until bitangents are calculated // https://gist.github.com/johang88/3f175b045c8e8b55fb815cc19e6128ba // see TNBExtensions.GenerateTangentBinormal(this MeshDraw meshData) //Surface = new MaterialNormalMapFeature { // NormalMap = new ComputeTextureColor(bumpTexture), // IsXYNormal = true, // ScaleAndBias = true, // }, // this is for a solid color rendering... // Diffuse = new MaterialDiffuseMapFeature(new ComputeColor { Key = MaterialKeys.DiffuseValue }), } }; var material = Material.New(GraphicsDevice, materialDescription); material.Passes[0].Parameters.Set(MaterialKeys.EmissiveIntensity, 5.0f); model.Materials.Add(material); } #else // this is for solid color rendering... var material = Material.New(GraphicsDevice, new MaterialDescriptor()); material.Passes[0].Parameters.Set(MaterialKeys.DiffuseValue, Color.Red); model.Materials.Add(material); #endif SceneSystem.SceneInstance.RootScene.Entities.Add(entity); }