public void Build(CommandList commandList, LightSpot lightSpot) { int[] indices; if (lightSpot.ProjectiveTexture != null) // If no projection texture has been supplied, we render the regular cone: { indices = BuildRectangleIndexBuffer(); vertexBuffer = Buffer.Vertex.New(graphicsDevice, new VertexPositionNormalTexture[9], GraphicsResourceUsage.Dynamic); RebuildRectangleVertexBuffer(commandList, lightSpot); } else // If a projection texture has been supplied, we render a rectangular frustum instead: { indices = BuildConeIndexBuffer(); vertexBuffer = Buffer.Vertex.New(graphicsDevice, new VertexPositionNormalTexture[4 * Tesselation + 1], GraphicsResourceUsage.Dynamic); RebuildConeVertexBuffer(commandList, lightSpot); } MeshDraw = new MeshDraw { PrimitiveType = PrimitiveType.LineList, DrawCount = indices.Length, IndexBuffer = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indices), true, indices.Length), VertexBuffers = new[] { new VertexBufferBinding(vertexBuffer, VertexPositionNormalTexture.Layout, vertexBuffer.ElementCount) }, }; }
public void Build(CommandList commandList, CameraParameters parameters) { var indices = new [] { 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 }; vertexBuffer = Buffer.Vertex.New(graphicsDevice, new VertexPositionNormalTexture[8], GraphicsResourceUsage.Dynamic); RebuildVertexBuffer(commandList, parameters); MeshDraw = new MeshDraw { PrimitiveType = PrimitiveType.LineList, DrawCount = indices.Length, IndexBuffer = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indices), true, indices.Length), VertexBuffers = new[] { new VertexBufferBinding(vertexBuffer, VertexPositionNormalTexture.Layout, vertexBuffer.ElementCount) }, }; }
public static unsafe Buffer SetDataFromStream(this Buffer buffer, CommandList commandList, Stream stream) { var pool = ArrayPool <byte> .Shared; var chunk = pool.Rent(Math.Min(buffer.SizeInBytes, 0x10000)); try { fixed(byte *chunkPtr = chunk) { var offset = 0; while (stream.CanRead) { var bytesRead = stream.Read(chunk, 0, chunk.Length); if (bytesRead > 0) { var dp = new DataPointer(chunkPtr, bytesRead); buffer.SetData(commandList, dp, offset); offset += bytesRead; } } } } finally { pool.Return(chunk); } return(buffer); }
public static unsafe Buffer New <TData>(GraphicsDevice device, Spread <TData> fromData, BufferFlags bufferFlags, GraphicsResourceUsage usage) where TData : struct { var immutableArray = fromData._array; var array = Unsafe.As <ImmutableArray <TData>, TData[]>(ref immutableArray); return(Buffer.New(device, array, bufferFlags, usage)); }
private static unsafe bool getMeshOutputs(Xenko.Rendering.Mesh modelMesh, out List <Vector3> positions, out List <int> indicies) { if (modelMesh.Draw is StagedMeshDraw) { StagedMeshDraw smd = modelMesh.Draw as StagedMeshDraw; object verts = smd.Verticies; if (verts is VertexPositionNormalColor[]) { VertexPositionNormalColor[] vpnc = verts as VertexPositionNormalColor[]; positions = new List <Vector3>(vpnc.Length); for (int k = 0; k < vpnc.Length; k++) { positions[k] = vpnc[k].Position; } } else if (verts is VertexPositionNormalTexture[]) { VertexPositionNormalTexture[] vpnc = verts as VertexPositionNormalTexture[]; positions = new List <Vector3>(vpnc.Length); for (int k = 0; k < vpnc.Length; k++) { positions[k] = vpnc[k].Position; } } else if (verts is VertexPositionNormalTextureTangent[]) { VertexPositionNormalTextureTangent[] vpnc = verts as VertexPositionNormalTextureTangent[]; positions = new List <Vector3>(vpnc.Length); for (int k = 0; k < vpnc.Length; k++) { positions[k] = vpnc[k].Position; } } else { positions = null; indicies = null; return(false); } // take care of indicies indicies = new List <int>((int[])(object)smd.Indicies); } else { Xenko.Graphics.Buffer buf = modelMesh.Draw?.VertexBuffers[0].Buffer; Xenko.Graphics.Buffer ibuf = modelMesh.Draw?.IndexBuffer.Buffer; if (buf == null || buf.VertIndexData == null || ibuf == null || ibuf.VertIndexData == null) { positions = null; indicies = null; return(false); } if (ModelBatcher.UnpackRawVertData(buf.VertIndexData, modelMesh.Draw.VertexBuffers[0].Declaration, out Vector3[] arraypositions, out Core.Mathematics.Vector3[] normals, out Core.Mathematics.Vector2[] uvs,
private static unsafe bool getMeshOutputs(Xenko.Rendering.Mesh modelMesh, out List <Vector3> positions, out List <int> indicies) { if (modelMesh.Draw is StagedMeshDraw) { StagedMeshDraw smd = modelMesh.Draw as StagedMeshDraw; object verts = smd.Verticies; if (verts is VertexPositionNormalColor[]) { VertexPositionNormalColor[] vpnc = verts as VertexPositionNormalColor[]; positions = new List <Vector3>(vpnc.Length); for (int k = 0; k < vpnc.Length; k++) { positions.Add(vpnc[k].Position); } } else if (verts is VertexPositionNormalTexture[]) { VertexPositionNormalTexture[] vpnc = verts as VertexPositionNormalTexture[]; positions = new List <Vector3>(vpnc.Length); for (int k = 0; k < vpnc.Length; k++) { positions.Add(vpnc[k].Position); } } else if (verts is VertexPositionNormalTextureTangent[]) { VertexPositionNormalTextureTangent[] vpnc = verts as VertexPositionNormalTextureTangent[]; positions = new List <Vector3>(vpnc.Length); for (int k = 0; k < vpnc.Length; k++) { positions.Add(vpnc[k].Position); } } else { throw new ArgumentException("Couldn't get StageMeshDraw mesh, unknown vert type for " + modelMesh.Name); } // take care of indicies indicies = new List <int>(smd.Indicies.Length); for (int i = 0; i < smd.Indicies.Length; i++) { indicies.Add((int)smd.Indicies[i]); } } else { Xenko.Graphics.Buffer buf = modelMesh.Draw?.VertexBuffers[0].Buffer; Xenko.Graphics.Buffer ibuf = modelMesh.Draw?.IndexBuffer.Buffer; if (buf == null || buf.VertIndexData == null || ibuf == null || ibuf.VertIndexData == null) { throw new ArgumentException("Couldn't get mesh for " + modelMesh.Name + ", buffer wasn't stored probably. Try Xenko.Graphics.Buffer.CaptureAllModelBuffers to true."); } if (ModelBatcher.UnpackRawVertData(buf.VertIndexData, modelMesh.Draw.VertexBuffers[0].Declaration, out Vector3[] arraypositions, out Core.Mathematics.Vector3[] normals, out Core.Mathematics.Vector2[] uvs,
// public static unsafe void WriteToDisk(this Buffer buffer, string filepath) // { // } // public static unsafe void WriteToDisk(this Buffer buffer, Stream stream) // { // buffer.GetData() // var pool = ArrayPool<byte>.Shared; // var chunk = pool.Rent(Math.Min(buffer.SizeInBytes, 0x10000)); // try // { // fixed (byte* chunkPtr = chunk) // { // var offset = 0; // while (stream.CanRead) // { // var bytesRead = stream.Read(chunk, 0, chunk.Length); // if (bytesRead > 0) // { // var dp = new DataPointer(chunkPtr, bytesRead); // buffer.SetData(commandList, dp, offset); // offset += bytesRead; // } // } // } // } // finally // { // pool.Return(chunk); // } // } //} public static unsafe Buffer SetDataFromFile(this Buffer buffer, CommandList commandList, string filepath) { using (var stream = File.Open(filepath, FileMode.Open, FileAccess.Read, FileShare.Read)) { buffer.SetDataFromStream(commandList, stream); } return(buffer); }
/// <summary> /// Copies the <paramref name="fromData"/> to the given <paramref name="buffer"/> on GPU memory. /// </summary> /// <typeparam name="TData">The type of the T data.</typeparam> /// <param name="buffer">The <see cref="Buffer"/>.</param> /// <param name="commandList">The <see cref="CommandList"/>.</param> /// <param name="fromData">The data to copy from.</param> /// <param name="offsetInBytes">The offset in bytes to write to.</param> /// <exception cref="ArgumentException"></exception> /// <remarks> /// See the unmanaged documentation about Map/UnMap for usage and restrictions. /// </remarks> /// <returns>The GPU buffer.</returns> public static unsafe Buffer SetData <TData>(this Buffer buffer, CommandList commandList, Spread <TData> fromData, int offsetInBytes = 0) where TData : struct { var immutableArray = fromData._array; var array = Unsafe.As <ImmutableArray <TData>, TData[]>(ref immutableArray); buffer.SetData(commandList, array, offsetInBytes); return(buffer); }
public static unsafe Buffer SetDataFromXenkoAssetURL(this Buffer buffer, CommandList commandList, Game game, string url) { using (var stream = game.Content.OpenAsStream(url, StreamFlags.None)) { buffer.SetDataFromStream(commandList, stream); } return(buffer); }
public static CommandList CopyResource(this CommandList commandList, Buffer sourceBuffer, Buffer targetBuffer) { var bufferS = (SharpDX.Direct3D11.Buffer)nativeDeviceChildFi.GetValue(sourceBuffer); var bufferT = (SharpDX.Direct3D11.Buffer)nativeDeviceChildFi.GetValue(targetBuffer); commandList.GetNativeDeviceContext().CopyResource(bufferS, bufferT); return(commandList); }
public static CommandList CopyStructureCount(this CommandList commandList, Buffer sourceBuffer, Buffer targetBuffer, int destinationAlignedByteOffset) { var buffer = (SharpDX.Direct3D11.Buffer)nativeDeviceChildFi.GetValue(targetBuffer); var uav = (SharpDX.Direct3D11.UnorderedAccessView)unorderedAccessViewFi.GetValue(sourceBuffer); commandList.GetNativeDeviceContext().CopyStructureCount(buffer, destinationAlignedByteOffset, uav); return(commandList); }
public void ReleaseBuffers(RenderDrawContext renderDrawContext) { // Release the temporary vertex buffer if (VertexBuffer != null) { renderDrawContext.GraphicsContext.Allocator.ReleaseReference(VertexBuffer); VertexBuffer = null; } }
/// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// </summary> public override void Dispose() { if (VertexBuffer != null && !VertexBuffer.IsDisposed) { VertexBuffer.Dispose(); } if (effect != null && !effect.IsDisposed) { effect.Dispose(); } }
public static bool DisposeBufferBySpecs(Xenko.Graphics.Buffer buf, int count) { if (buf == null || buf.ElementCount != count) { if (buf != null) { buf.Dispose(); } return(true); } return(false); }
private bool NeedToRecreateBuffer(Xenko.Graphics.Buffer buf, int count) { if (buf == null || buf.ElementCount != count) { if (buf != null) { buf.Dispose(); } return(true); } return(false); }
public void UpdateTempStorage(VoxelStorageContext context) { storageUints = (tempStorageCounter + 31) / 32; tempStorageCounter = 0; var resolution = ClipMapResolution; int fragments = (int)(resolution.X * resolution.Y * resolution.Z) * ClipMapCount; if (VoxelUtils.DisposeBufferBySpecs(FragmentsBuffer, storageUints * fragments) && storageUints * fragments > 0) { FragmentsBuffer = Xenko.Graphics.Buffer.Typed.New(context.device, storageUints * fragments, PixelFormat.R32_UInt, true); } }
public void Build() { var indices = new int[2 * Tesselation * 3]; var vertices = new VertexPositionNormalTexture[(Tesselation + 1) * 3]; int indexCount = 0; int vertexCount = 0; // the two rings for (int j = 0; j < 3; j++) { var rotation = Matrix.Identity; if (j == 1) { rotation = Matrix.RotationX((float)Math.PI / 2); } else if (j == 2) { rotation = Matrix.RotationY((float)Math.PI / 2); } for (int i = 0; i <= Tesselation; i++) { var longitude = (float)(i * 2.0 * Math.PI / Tesselation); var dx = (float)Math.Cos(longitude); var dy = (float)Math.Sin(longitude); var normal = new Vector3(dx, dy, 0); Vector3.TransformNormal(ref normal, ref rotation, out normal); if (i < Tesselation) { indices[indexCount++] = vertexCount; indices[indexCount++] = vertexCount + 1; } vertices[vertexCount++] = new VertexPositionNormalTexture(normal, normal, new Vector2(0)); } } vertexBuffer = Buffer.Vertex.New(graphicsDevice, vertices); MeshDraw = new MeshDraw { PrimitiveType = PrimitiveType.LineList, DrawCount = indices.Length, IndexBuffer = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indices), true, indices.Length), VertexBuffers = new[] { new VertexBufferBinding(vertexBuffer, VertexPositionNormalTexture.Layout, vertexBuffer.ElementCount) }, }; }
/// <inheritdoc/> protected override void InitializeCore() { base.InitializeCore(); RenderFeatures.CollectionChanged += RenderFeatures_CollectionChanged; foreach (var renderFeature in RenderFeatures) { renderFeature.AttachRootRenderFeature(this); renderFeature.Initialize(Context); } // Create an empty buffer to compensate for missing vertex streams emptyBuffer = Buffer.Vertex.New(Context.GraphicsDevice, new Vector4[1]); }
protected override void Destroy() { foreach (var renderFeature in RenderFeatures) { renderFeature.Dispose(); } RenderFeatures.CollectionChanged -= RenderFeatures_CollectionChanged; descriptorSets.Dispose(); emptyBuffer?.Dispose(); emptyBuffer = null; base.Destroy(); }
public void Dispose() { performStage = null; if (_vertexBuffer != null) { _vertexBuffer.Dispose(); } if (_indexBuffer != null) { _indexBuffer.Dispose(); } _vertexBuffer = null; _indexBuffer = null; }
private static byte[] GetDataSafe(this Buffer buffer, CommandList commandList = null) { var data = buffer.GetSerializationData(); if (data != null) { return(data.Content); } if (commandList == null) { throw new InvalidOperationException("Could not find underlying CPU buffer data and no command list was given to extract them from GPU"); } return(buffer.GetData <byte>(commandList)); }
public override void Unload() { // Dispose GPU resources lightClusters?.Dispose(); lightClusters = null; lightIndicesBuffer?.Dispose(); lightIndicesBuffer = null; pointLightsBuffer?.Dispose(); pointLightsBuffer = null; spotLightsBuffer?.Dispose(); spotLightsBuffer = null; base.Unload(); }
public void Dispose() { performStage = null; if (_vertexBuffer != null) { StagedBufferTrashBin.Enqueue(_vertexBuffer); } if (_indexBuffer != null) { StagedBufferTrashBin.Enqueue(_indexBuffer); } _vertexBuffer = null; _indexBuffer = null; }
public void Build() { var indices = new int[12 * 2]; var vertices = new VertexPositionNormalTexture[8]; vertices[0] = new VertexPositionNormalTexture(new Vector3(-1, 1, -1), Vector3.UnitY, Vector2.Zero); vertices[1] = new VertexPositionNormalTexture(new Vector3(-1, 1, 1), Vector3.UnitY, Vector2.Zero); vertices[2] = new VertexPositionNormalTexture(new Vector3(1, 1, 1), Vector3.UnitY, Vector2.Zero); vertices[3] = new VertexPositionNormalTexture(new Vector3(1, 1, -1), Vector3.UnitY, Vector2.Zero); int indexOffset = 0; // Top sides for (int i = 0; i < 4; i++) { indices[indexOffset++] = i; indices[indexOffset++] = (i + 1) % 4; } // Duplicate vertices and indices to bottom part for (int i = 0; i < 4; i++) { vertices[i + 4] = vertices[i]; vertices[i + 4].Position.Y = -vertices[i + 4].Position.Y; indices[indexOffset++] = indices[i * 2] + 4; indices[indexOffset++] = indices[i * 2 + 1] + 4; } // Sides for (int i = 0; i < 4; i++) { indices[indexOffset++] = i; indices[indexOffset++] = i + 4; } vertexBuffer = Buffer.Vertex.New(graphicsDevice, vertices); MeshDraw = new MeshDraw { PrimitiveType = PrimitiveType.LineList, DrawCount = indices.Length, IndexBuffer = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indices), true, indices.Length), VertexBuffers = new[] { new VertexBufferBinding(vertexBuffer, VertexPositionNormalTexture.Layout, vertexBuffer.ElementCount) }, }; }
private void Init() { _tribuf = Buffer.New(GraphicsDevice, new[] { new Vector4(-0.5f, 0.5f, 0, 1), new Vector4(0.5f, 0.5f, 0, 1), new Vector4(0, -0.5f, 0, 1) }, BufferFlags.VertexBuffer, GraphicsResourceUsage.Immutable); simpleEffect = new EffectInstance(new Effect(GraphicsDevice, SpriteEffect.Bytecode)); simpleEffect.Parameters.Set(SpriteBaseKeys.MatrixTransform, Matrix.Identity); simpleEffect.UpdateEffect(GraphicsDevice); pipelineState = new MutablePipelineState(GraphicsDevice); pipelineState.State.SetDefaults(); pipelineState.State.InputElements = VertexDeclaration.CreateInputElements(); pipelineState.State.PrimitiveType = PrimitiveType; }
public void Dispose() { performStage = null; if (_vertexBuffer != null) { _vertexBuffer.DestroyNow(); _vertexBuffer.Dispose(); Disposed++; } if (_indexBuffer != null) { _indexBuffer.DestroyNow(); _indexBuffer.Dispose(); } _vertexBuffer = null; _indexBuffer = null; }
private Model CreateModel() { // https://doc.xenko.com/latest/en/manual/scripts/create-a-model-from-code.html var indexBuffer = new Buffer(); var indexBufferBinding = new IndexBufferBinding(indexBuffer, true, 10); var vertexBufferBinding = new VertexBufferBinding(); VertexBufferBinding[] vertexBufferBindings = { vertexBufferBinding }; var meshDraw = new MeshDraw { VertexBuffers = vertexBufferBindings, IndexBuffer = indexBufferBinding }; ParameterCollection parms = null; var mesh = new Xenko.Rendering.Mesh(meshDraw, parms); var model = new Model { mesh }; return(model); }
private unsafe Mesh ConvertToMesh(GraphicsDevice graphicsDevice, PrimitiveType primitiveType, LightProbeRuntimeData lightProbeRuntimeData) { // Generate data for vertex buffer var vertices = new VertexPositionNormalColor[lightProbeRuntimeData.LightProbes.Length]; for (var i = 0; i < lightProbeRuntimeData.LightProbes.Length; i++) { vertices[i] = new VertexPositionNormalColor(lightProbeRuntimeData.Vertices[i], Vector3.Zero, Color4.White); } // Generate data for index buffer var indices = new int[lightProbeRuntimeData.Faces.Count * 6]; for (var i = 0; i < lightProbeRuntimeData.Faces.Count; ++i) { var currentFace = lightProbeRuntimeData.Faces[i]; // Skip infinite edges to not clutter display // Maybe we could reenable it when we have better infinite nodes if (currentFace.Vertices[0] >= lightProbeRuntimeData.UserVertexCount || currentFace.Vertices[1] >= lightProbeRuntimeData.UserVertexCount || currentFace.Vertices[2] >= lightProbeRuntimeData.UserVertexCount) { continue; } indices[i * 6 + 0] = currentFace.Vertices[0]; indices[i * 6 + 1] = currentFace.Vertices[1]; indices[i * 6 + 2] = currentFace.Vertices[1]; indices[i * 6 + 3] = currentFace.Vertices[2]; indices[i * 6 + 4] = currentFace.Vertices[2]; indices[i * 6 + 5] = currentFace.Vertices[0]; } var boundingBox = BoundingBox.Empty; for (int i = 0; i < vertices.Length; i++) { BoundingBox.Merge(ref boundingBox, ref vertices[i].Position, out boundingBox); } // Compute bounding sphere BoundingSphere boundingSphere; fixed(void *verticesPtr = vertices) BoundingSphere.FromPoints((IntPtr)verticesPtr, 0, vertices.Length, VertexPositionNormalTexture.Size, out boundingSphere); var layout = vertices[0].GetLayout(); var meshDraw = new MeshDraw { IndexBuffer = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indices).RecreateWith(indices), true, indices.Length), VertexBuffers = new[] { new VertexBufferBinding(Buffer.New(graphicsDevice, vertices, BufferFlags.VertexBuffer).RecreateWith(vertices), layout, vertices.Length) }, DrawCount = indices.Length, PrimitiveType = primitiveType, }; wireframeResources.Add(meshDraw.VertexBuffers[0].Buffer); wireframeResources.Add(meshDraw.IndexBuffer.Buffer); return(new Mesh { Draw = meshDraw, BoundingBox = boundingBox, BoundingSphere = boundingSphere }); }
private static unsafe void ProcessMaterial(List <BatchingChunk> chunks, MaterialInstance material, Model prefabModel, HashSet <Entity> unbatched = null) { //actually create the mesh List <VertexPositionNormalTextureTangent> vertsNT = null; List <VertexPositionNormalColor> vertsNC = null; List <uint> indiciesList = new List <uint>(); BoundingBox bb = new BoundingBox(new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity), new Vector3(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity)); uint indexOffset = 0; for (int i = 0; i < chunks.Count; i++) { BatchingChunk chunk = chunks[i]; if (unbatched != null && unbatched.Contains(chunk.Entity)) { continue; // don't try batching other things in this entity if some failed } if (chunk.Entity != null) { chunk.Entity.Transform.UpdateLocalMatrix(); chunk.Entity.Transform.UpdateWorldMatrixInternal(true, false); } Matrix worldMatrix = chunk.Entity == null ? (chunk.Transform ?? Matrix.Identity) : chunk.Entity.Transform.WorldMatrix; Matrix rot; if (worldMatrix != Matrix.Identity) { worldMatrix.GetRotationMatrix(out rot); } else { rot = Matrix.Identity; } for (int j = 0; j < chunk.Model.Meshes.Count; j++) { Mesh modelMesh = chunk.Model.Meshes[j]; //process only right material if (modelMesh.MaterialIndex == chunk.MaterialIndex) { Vector3[] positions = null, normals = null; Vector4[] tangents = null; Vector2[] uvs = null; Color4[] colors = null; //vertexes if (CachedModelData.TryGet(modelMesh, out var information)) { // clone positions and normals, since they may change positions = (Vector3[])information.positions.Clone(); normals = (Vector3[])information.normals.Clone(); tangents = information.tangents; uvs = information.uvs; colors = information.colors; for (int k = 0; k < information.indicies.Length; k++) { indiciesList.Add(information.indicies[k] + indexOffset); } } else if (modelMesh.Draw is StagedMeshDraw) { StagedMeshDraw smd = modelMesh.Draw as StagedMeshDraw; object verts = smd.Verticies; if (verts is VertexPositionNormalColor[]) { VertexPositionNormalColor[] vpnc = verts as VertexPositionNormalColor[]; positions = new Vector3[vpnc.Length]; normals = new Vector3[vpnc.Length]; colors = new Color4[vpnc.Length]; for (int k = 0; k < vpnc.Length; k++) { positions[k] = vpnc[k].Position; normals[k] = vpnc[k].Normal; colors[k] = vpnc[k].Color; } } else if (verts is VertexPositionNormalTexture[]) { VertexPositionNormalTexture[] vpnc = verts as VertexPositionNormalTexture[]; positions = new Vector3[vpnc.Length]; normals = new Vector3[vpnc.Length]; uvs = new Vector2[vpnc.Length]; for (int k = 0; k < vpnc.Length; k++) { positions[k] = vpnc[k].Position; normals[k] = vpnc[k].Normal; uvs[k] = vpnc[k].TextureCoordinate; } } else if (verts is VertexPositionNormalTextureTangent[]) { VertexPositionNormalTextureTangent[] vpnc = verts as VertexPositionNormalTextureTangent[]; positions = new Vector3[vpnc.Length]; normals = new Vector3[vpnc.Length]; uvs = new Vector2[vpnc.Length]; tangents = new Vector4[vpnc.Length]; for (int k = 0; k < vpnc.Length; k++) { positions[k] = vpnc[k].Position; normals[k] = vpnc[k].Normal; uvs[k] = vpnc[k].TextureCoordinate; tangents[k] = vpnc[k].Tangent; } } else { // unsupported StagedMeshDraw if (unbatched != null) { unbatched.Add(chunk.Entity); } continue; } // take care of indicies for (int k = 0; k < smd.Indicies.Length; k++) { indiciesList.Add(smd.Indicies[k] + indexOffset); } // cache this for later CachedModelData.Add(modelMesh, new CachedData() { colors = colors, indicies = smd.Indicies, normals = (Vector3[])normals.Clone(), positions = (Vector3[])positions.Clone(), tangents = tangents, uvs = uvs } ); } else { Xenko.Graphics.Buffer buf = modelMesh.Draw?.VertexBuffers[0].Buffer; Xenko.Graphics.Buffer ibuf = modelMesh.Draw?.IndexBuffer.Buffer; if (buf == null || buf.VertIndexData == null || ibuf == null || ibuf.VertIndexData == null) { if (unbatched != null) { unbatched.Add(chunk.Entity); } continue; } if (UnpackRawVertData(buf.VertIndexData, modelMesh.Draw.VertexBuffers[0].Declaration, out positions, out normals, out uvs, out colors, out tangents) == false) { if (unbatched != null) { unbatched.Add(chunk.Entity); } continue; } CachedData cmd = new CachedData() { colors = colors, positions = (Vector3[])positions.Clone(), normals = (Vector3[])normals.Clone(), uvs = uvs, tangents = tangents }; // indicies fixed(byte *pdst = ibuf.VertIndexData) { int numIndices = modelMesh.Draw.IndexBuffer.Count; cmd.indicies = new uint[numIndices]; if (modelMesh.Draw.IndexBuffer.Is32Bit) { var dst = (uint *)(pdst + modelMesh.Draw.IndexBuffer.Offset); for (var k = 0; k < numIndices; k++) { // Offset indices cmd.indicies[k] = dst[k]; indiciesList.Add(dst[k] + indexOffset); } } else { var dst = (ushort *)(pdst + modelMesh.Draw.IndexBuffer.Offset); for (var k = 0; k < numIndices; k++) { // Offset indices cmd.indicies[k] = dst[k]; indiciesList.Add(dst[k] + indexOffset); } } } CachedModelData.Add(modelMesh, cmd); } // what kind of structure will we be making, if we haven't picked one already? if (vertsNT == null && vertsNC == null) { if (uvs != null) { vertsNT = new List <VertexPositionNormalTextureTangent>(positions.Length); } else { vertsNC = new List <VertexPositionNormalColor>(positions.Length); } } // bounding box/finish list bool needmatrix = worldMatrix != Matrix.Identity; for (int k = 0; k < positions.Length; k++) { if (needmatrix) { Vector3.Transform(ref positions[k], ref worldMatrix, out positions[k]); if (normals != null) { Vector3.TransformNormal(ref normals[k], ref rot, out normals[k]); } } // update bounding box? Vector3 pos = positions[k]; if (pos.X > bb.Maximum.X) { bb.Maximum.X = pos.X; } if (pos.Y > bb.Maximum.Y) { bb.Maximum.Y = pos.Y; } if (pos.Z > bb.Maximum.Z) { bb.Maximum.Z = pos.Z; } if (pos.X < bb.Minimum.X) { bb.Minimum.X = pos.X; } if (pos.Y < bb.Minimum.Y) { bb.Minimum.Y = pos.Y; } if (pos.Z < bb.Minimum.Z) { bb.Minimum.Z = pos.Z; } if (vertsNT != null) { vertsNT.Add(new VertexPositionNormalTextureTangent { Position = positions[k], Normal = normals != null ? normals[k] : Vector3.UnitY, TextureCoordinate = uvs[k], Tangent = tangents != null ? tangents[k] : Vector4.UnitW }); } else { vertsNC.Add(new VertexPositionNormalColor { Position = positions[k], Normal = normals != null ? normals[k] : Vector3.UnitY, Color = colors != null ? colors[k] : Color4.White }); } } indexOffset += (uint)positions.Length; } } } if (indiciesList.Count <= 0) { return; } uint[] indicies = indiciesList.ToArray(); // make stagedmesh with verts StagedMeshDraw md; if (vertsNT != null) { var vertsNTa = vertsNT.ToArray(); md = StagedMeshDraw.MakeStagedMeshDraw <VertexPositionNormalTextureTangent>(ref indicies, ref vertsNTa, VertexPositionNormalTextureTangent.Layout); } else if (vertsNC != null) { var vertsNCa = vertsNC.ToArray(); md = StagedMeshDraw.MakeStagedMeshDraw <VertexPositionNormalColor>(ref indicies, ref vertsNCa, VertexPositionNormalColor.Layout); } else { return; } Mesh m = new Mesh { Draw = md, BoundingBox = bb, MaterialIndex = prefabModel.Materials.Count }; prefabModel.Add(m); if (material != null) { prefabModel.Add(material); } }
public virtual void Collect(RenderContext Context, IShadowMapRenderer ShadowMapRenderer) { renderVoxelVolumes = Context.VisibilityGroup.Tags.Get(CurrentRenderVoxelVolumes); if (renderVoxelVolumes == null) { return; } Vector3 resolutionMax = new Vector3(0, 0, 0); int fragmentsMax = 0; int fragmentsCountMax = 0; //Create per-volume textures foreach (var pair in renderVoxelVolumes) { var volume = pair.Value; var bounds = volume.ClipMapMatrix.ScaleVector; var resolution = bounds / volume.AproxVoxelSize; //Calculate closest power of 2 on each axis resolution.X = (float)Math.Pow(2, Math.Round(Math.Log(resolution.X, 2))); resolution.Y = (float)Math.Pow(2, Math.Round(Math.Log(resolution.Y, 2))); resolution.Z = (float)Math.Pow(2, Math.Round(Math.Log(resolution.Z, 2))); resolution = new Vector3(resolution.X, resolution.Z, resolution.Y);//Temporary Vector3 ClipMapResolution = new Vector3(resolution.X, resolution.Y, resolution.Z * volume.ClipMapCount); Vector3 MipMapResolution = resolution / 2; RenderVoxelVolumeData data; if (!renderVoxelVolumeData.TryGetValue(pair.Key, out data)) { renderVoxelVolumeData.Add(pair.Key, data = new RenderVoxelVolumeData()); } data.ClipMapResolution = resolution; if (NeedToRecreateTexture(data.ClipMaps, ClipMapResolution)) { data.ClipMaps = Xenko.Graphics.Texture.New3D(Context.GraphicsDevice, (int)ClipMapResolution.X, (int)ClipMapResolution.Y, (int)ClipMapResolution.Z, new MipMapCount(false), Xenko.Graphics.PixelFormat.R16G16B16A16_Float, TextureFlags.ShaderResource | TextureFlags.UnorderedAccess); } if (NeedToRecreateTexture(data.MipMaps, resolution)) { data.MipMaps = Xenko.Graphics.Texture.New3D(Context.GraphicsDevice, (int)MipMapResolution.X, (int)MipMapResolution.Y, (int)MipMapResolution.Z, new MipMapCount(true), Xenko.Graphics.PixelFormat.R16G16B16A16_Float, TextureFlags.ShaderResource | TextureFlags.UnorderedAccess); } resolutionMax = Vector3.Min(new Vector3(256), Vector3.Max(resolutionMax, resolution)); fragmentsMax = Math.Max(fragmentsMax, (int)(ClipMapResolution.X * ClipMapResolution.Y * ClipMapResolution.Z)); fragmentsCountMax = Math.Max(fragmentsCountMax, (int)(ClipMapResolution.X * ClipMapResolution.Y) * volume.ClipMapCount); } //Create re-usable textures float resolutionMaxSide = Math.Max(Math.Max(resolutionMax.X, resolutionMax.Y), resolutionMax.Z); if (NeedToRecreateTexture(MSAARenderTarget, new Vector3(resolutionMaxSide, resolutionMaxSide, 1))) { MSAARenderTarget = Texture.New(Context.GraphicsDevice, TextureDescription.New2D((int)resolutionMaxSide, (int)resolutionMaxSide, new MipMapCount(false), PixelFormat.R8G8B8A8_UNorm, TextureFlags.RenderTarget, 1, GraphicsResourceUsage.Default, MultisampleCount.X8), null); } if (NeedToRecreateBuffer(Fragments, fragmentsMax)) { Fragments = Xenko.Graphics.Buffer.Structured.New(Context.GraphicsDevice, fragmentsMax, 24, true); } if (NeedToRecreateBuffer(FragmentsCounter, fragmentsCountMax)) { FragmentsCounter = Xenko.Graphics.Buffer.Typed.New(Context.GraphicsDevice, fragmentsCountMax, PixelFormat.R32_SInt, true); } Vector3 MipMapResolutionMax = resolutionMax / 2; if (TempMipMaps == null || !TextureDimensionsEqual(TempMipMaps[0], MipMapResolutionMax)) { if (TempMipMaps != null) { for (int i = 0; i < TempMipMaps.Length; i++) { TempMipMaps[0].Dispose(); } } int mipCount = 1 + (int)Math.Floor(Math.Log(Math.Max(MipMapResolutionMax.X, Math.Max(MipMapResolutionMax.Y, MipMapResolutionMax.Z)), 2)); TempMipMaps = new Xenko.Graphics.Texture[mipCount]; for (int i = 0; i < TempMipMaps.Length; i++) { TempMipMaps[i] = Xenko.Graphics.Texture.New3D(Context.GraphicsDevice, (int)MipMapResolutionMax.X, (int)MipMapResolutionMax.Y, (int)MipMapResolutionMax.Z, false, Xenko.Graphics.PixelFormat.R16G16B16A16_Float, TextureFlags.ShaderResource | TextureFlags.UnorderedAccess); MipMapResolutionMax /= 2; MipMapResolutionMax = Vector3.Max(new Vector3(1), MipMapResolutionMax); } } if (Generate3DMipmaps == null) { Generate3DMipmaps = new Xenko.Rendering.ComputeEffect.ComputeEffectShader(Context) { ShaderSourceName = "Generate3DMipmaps" }; ClearBuffer = new Xenko.Rendering.ComputeEffect.ComputeEffectShader(Context) { ShaderSourceName = "ClearBuffer" }; ArrangeFragments = new Xenko.Rendering.ComputeEffect.ComputeEffectShader(Context) { ShaderSourceName = "ArrangeFragments" }; } //Create all the views reflectiveVoxelViews.Clear(); foreach (var pair in renderVoxelVolumes) { var volume = pair.Value; var data = renderVoxelVolumeData[pair.Key]; var bounds = volume.ClipMapMatrix.ScaleVector; var shadowRenderView = new RenderView(); float nearClip = 0.1f; float farClip = 999.7f; //Currently hard coded and kinda odd shadowRenderView.View = Matrix.Translation(0.0f, 1.0f, 0.0f) * Matrix.RotationX(-3.1415f / 2.0f); shadowRenderView.Projection = Matrix.OrthoRH(bounds.X * (float)Math.Pow(2, volume.ClipMapCount), bounds.Z * (float)Math.Pow(2, volume.ClipMapCount), nearClip, farClip); Matrix.Multiply(ref shadowRenderView.View, ref shadowRenderView.Projection, out shadowRenderView.ViewProjection); shadowRenderView.Frustum = new BoundingFrustum(ref shadowRenderView.ViewProjection); shadowRenderView.CullingMode = CameraCullingMode.Frustum; shadowRenderView.ViewSize = new Vector2(1024, 1024); float maxRes = Math.Max(Math.Max(data.ClipMapResolution.X, data.ClipMapResolution.Y), data.ClipMapResolution.Z); var rotmat = new Matrix(1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1);//xzy var viewToTexTrans = Matrix.Translation(0.5f, 0.5f, 0.5f); var viewToTexScale = Matrix.Scaling(0.5f, 0.5f, 0.5f); var viewportAspect = Matrix.Scaling(data.ClipMapResolution / maxRes); // Matrix BaseVoxelMatrix = transmat * scalemat * rotmat; Matrix BaseVoxelMatrix = volume.ClipMapMatrix * Matrix.Identity; BaseVoxelMatrix.Invert(); BaseVoxelMatrix = BaseVoxelMatrix * Matrix.Scaling(2f, 2f, 2f) * rotmat; data.Matrix = BaseVoxelMatrix * viewToTexScale * viewToTexTrans; data.ViewportMatrix = BaseVoxelMatrix * viewportAspect; data.ClipMapCount = volume.ClipMapCount; shadowRenderView.NearClipPlane = nearClip; shadowRenderView.FarClipPlane = farClip; shadowRenderView.RenderStages.Add(VoxelStage); reflectiveVoxelViews.Add(shadowRenderView, pair.Key); // Add the render view for the current frame Context.RenderSystem.Views.Add(shadowRenderView); // Collect objects in shadow views Context.VisibilityGroup.TryCollect(shadowRenderView); ShadowMapRenderer?.RenderViewsWithShadows.Add(shadowRenderView); } }