void LoadAssets() { // Allocate one region of memory for the uniform buffer dynamicConstantBuffer = device.CreateBuffer(max_bytes_per_frame, 0); dynamicConstantBuffer.Label = "UniformBuffer"; // Load the fragment program into the library IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("lighting_fragment"); // Load the vertex program into the library IMTLFunction vertexProgram = defaultLibrary.CreateFunction("lighting_vertex"); // Setup the vertex buffers vertexBuffer = device.CreateBuffer <float> (cubeVertexData, (MTLResourceOptions)0); vertexBuffer.Label = "Vertices"; // Create a reusable pipeline state var pipelineStateDescriptor = new MTLRenderPipelineDescriptor { Label = "MyPipeline", SampleCount = 1, VertexFunction = vertexProgram, FragmentFunction = fragmentProgram, DepthAttachmentPixelFormat = MTLPixelFormat.Depth32Float }; pipelineStateDescriptor.ColorAttachments [0].PixelFormat = MTLPixelFormat.BGRA8Unorm; NSError error; pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error); if (pipelineState == null) { Console.WriteLine("Failed to created pipeline state, error " + error); } var depthStateDesc = new MTLDepthStencilDescriptor { DepthCompareFunction = MTLCompareFunction.Less, DepthWriteEnabled = true }; depthState = device.CreateDepthStencilState(depthStateDesc); }
public static IMTLBuffer CreateBuffer <T> (this IMTLDevice This, T [] data, MTLResourceOptions options) where T : struct { var handle = GCHandle.Alloc(data, GCHandleType.Pinned); // This requires a pinned GCHandle, since it's not possible to use unsafe code to get the address of a generic object. try { IntPtr ptr = handle.AddrOfPinnedObject(); return(This.CreateBuffer(ptr, (nuint)(data.Length * Marshal.SizeOf(typeof(T))), options)); } finally { handle.Free(); } }
public static IMTLBuffer CreateBuffer <T> (this IMTLDevice This, T [] data, MTLResourceOptions options) where T : struct { var handle = GCHandle.Alloc(data, GCHandleType.Pinned); try { IntPtr ptr = handle.AddrOfPinnedObject(); return(This.CreateBuffer(ptr, (nuint)(data.Length * Marshal.SizeOf(typeof(T))), options)); } finally { handle.Free(); } }
void LoadAssets() { // Generate meshes MDLMesh mdl = MDLMesh.CreateBox(new Vector3(2f, 2f, 2f), new Vector3i(1, 1, 1), MDLGeometryType.Triangles, false, new MTKMeshBufferAllocator(device)); NSError error; boxMesh = new MTKMesh(mdl, device, out error); // Allocate one region of memory for the uniform buffer dynamicConstantBuffer = device.CreateBuffer(MaxBytesPerFrame, (MTLResourceOptions)0); dynamicConstantBuffer.Label = "UniformBuffer"; // Load the fragment program into the library IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("lighting_fragment"); // Load the vertex program into the library IMTLFunction vertexProgram = defaultLibrary.CreateFunction("lighting_vertex"); // Create a vertex descriptor from the MTKMesh MTLVertexDescriptor vertexDescriptor = MTLVertexDescriptor.FromModelIO(boxMesh.VertexDescriptor); vertexDescriptor.Layouts[0].StepRate = 1; vertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex; // Create a reusable pipeline state var pipelineStateDescriptor = new MTLRenderPipelineDescriptor { Label = "MyPipeline", SampleCount = view.SampleCount, VertexFunction = vertexProgram, FragmentFunction = fragmentProgram, VertexDescriptor = vertexDescriptor, DepthAttachmentPixelFormat = view.DepthStencilPixelFormat, StencilAttachmentPixelFormat = view.DepthStencilPixelFormat }; pipelineStateDescriptor.ColorAttachments[0].PixelFormat = view.ColorPixelFormat; pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error); if (pipelineState == null) { Console.WriteLine("Failed to created pipeline state, error {0}", error); } var depthStateDesc = new MTLDepthStencilDescriptor { DepthCompareFunction = MTLCompareFunction.Less, DepthWriteEnabled = true }; depthState = device.CreateDepthStencilState(depthStateDesc); }
// Designated initializer public Quad (IMTLDevice device) { if (device == null) throw new Exception ("ERROR: Invalid device!"); vertexBuffer = device.CreateBuffer<Vector4> (quadVertices, MTLResourceOptions.CpuCacheModeDefault); if (vertexBuffer == null) Console.WriteLine ("ERROR: Failed creating a vertex buffer for a quad!"); vertexBuffer.Label = "quad vertices"; texCoordBuffer = device.CreateBuffer<Vector2> (quadTexCoords, MTLResourceOptions.CpuCacheModeDefault); if (texCoordBuffer == null) Console.WriteLine ("ERROR: Failed creating a 2d texture coordinate buffer!"); texCoordBuffer.Label = "quad texcoords"; vertexIndex = 0; texCoordIndex = 1; Aspect = 1f; scale = Vector2.One; }
bool PrepareTransformBuffer() { // allocate regions of memory for the constant buffer transformBuffer = device.CreateBuffer((nuint)Marshal.SizeOf <Matrix4> (), MTLResourceOptions.CpuCacheModeDefault); if (transformBuffer == null) { return(false); } transformBuffer.Label = "TransformBuffer"; return(true); }
public AmtDeviceMemory(IMTLDevice device, MgMemoryAllocateInfo pAllocateInfo) { if (pAllocateInfo == null) { throw new ArgumentNullException(nameof(pAllocateInfo)); } if (pAllocateInfo.AllocationSize > nuint.MaxValue) { throw new ArgumentOutOfRangeException(nameof(pAllocateInfo.AllocationSize) + " must be <= nuint.MaxValue"); } AllocationSize = (nuint)pAllocateInfo.AllocationSize; var options = MTLResourceOptions.CpuCacheModeDefault; InternalBuffer = device.CreateBuffer(AllocationSize, options); }
public MetalKitEssentialsSubmesh(MTKSubmesh mtkSubmesh, MDLSubmesh mdlSubmesh, IMTLDevice device) { materialUniforms = device.CreateBuffer ((nuint)Marshal.SizeOf <MaterialUniforms> (), MTLResourceOptions.CpuCacheModeDefault); var uniforms = Marshal.PtrToStructure <MaterialUniforms> (materialUniforms.Contents); submesh = mtkSubmesh; for (nuint i = 0; i < mdlSubmesh.Material.Count; i++) { MDLMaterialProperty property = ObjectAtIndexedSubscript (mdlSubmesh.Material, i); if (property == null) continue; if (property.Name == "baseColorMap") { if (property.Type != MDLMaterialPropertyType.String) continue; var textureURL = new NSUrl (string.Format ("file://{0}", property.StringValue)); var textureLoader = new MTKTextureLoader (device); NSError error; diffuseTexture = textureLoader.FromUrl (textureURL, null, out error); if (diffuseTexture == null) throw new Exception (string.Format ("Diffuse texture load: {0}", error.LocalizedDescription)); } else if (property.Name == "BlinnSpecularColor") { if (property.Type == MDLMaterialPropertyType.Float4) uniforms.specularColor = property.Float4Value; else if (property.Type == MDLMaterialPropertyType.Float3) uniforms.specularColor = new Vector4 (property.Float3Value); } else if (property.Name == "emission") { if(property.Type == MDLMaterialPropertyType.Float4) uniforms.emissiveColor = property.Float4Value; else if (property.Type == MDLMaterialPropertyType.Float3) uniforms.emissiveColor = new Vector4 (property.Float3Value); } } Marshal.StructureToPtr (uniforms, materialUniforms.Contents, true); }
public override void ViewDidLoad() { base.ViewDidLoad(); // Set the view to use the default device device = MTLDevice.SystemDefault; if (device == null) { Console.WriteLine("Metal is not supported on this device"); View = new NSView(View.Frame); } // Create a new command queue commandQueue = device.CreateCommandQueue(); // Load all the shader files with a metal file extension in the project defaultLibrary = device.CreateDefaultLibrary(); // Setup view mtkView = (MTKView)View; mtkView.Delegate = this; mtkView.Device = device; mtkView.SampleCount = 1; mtkView.DepthStencilPixelFormat = MTLPixelFormat.Depth32Float_Stencil8; mtkView.ColorPixelFormat = MTLPixelFormat.BGRA8Unorm; mtkView.PreferredFramesPerSecond = 60; mtkView.ClearColor = new MTLClearColor(0.5f, 0.5f, 0.5f, 1.0f); // Load the vertex program into the library IMTLFunction triangleVertexProgram = defaultLibrary.CreateFunction("triangle_vertex"); IMTLFunction cubeVertexProgram = defaultLibrary.CreateFunction("cube_vertex"); // Load the fragment program into the library IMTLFunction triangleFragmentProgram = defaultLibrary.CreateFunction("triangle_fragment"); IMTLFunction cubeFragmentProgram = defaultLibrary.CreateFunction("cube_fragment"); // Triangle vertex descriptor MTLVertexDescriptor triangleVertexDescriptor = new MTLVertexDescriptor(); triangleVertexDescriptor.Attributes[0].Format = MTLVertexFormat.Float4; triangleVertexDescriptor.Attributes[0].BufferIndex = 0; triangleVertexDescriptor.Attributes[0].Offset = 0; triangleVertexDescriptor.Attributes[1].Format = MTLVertexFormat.Float4; triangleVertexDescriptor.Attributes[1].BufferIndex = 0; triangleVertexDescriptor.Attributes[1].Offset = 4 * sizeof(float); triangleVertexDescriptor.Layouts[0].Stride = 8 * sizeof(float); triangleVertexDescriptor.Layouts[0].StepRate = 1; triangleVertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex; // Cube vertex descriptor MTLVertexDescriptor cubeVertexDescriptor = new MTLVertexDescriptor(); cubeVertexDescriptor.Attributes[0].Format = MTLVertexFormat.Float4; cubeVertexDescriptor.Attributes[0].BufferIndex = 0; cubeVertexDescriptor.Attributes[0].Offset = 0; cubeVertexDescriptor.Attributes[1].Format = MTLVertexFormat.Float2; cubeVertexDescriptor.Attributes[1].BufferIndex = 0; cubeVertexDescriptor.Attributes[1].Offset = 4 * sizeof(float); cubeVertexDescriptor.Layouts[0].Stride = 6 * sizeof(float); cubeVertexDescriptor.Layouts[0].StepRate = 1; cubeVertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex; // Create buffers triangleVertexBuffer = device.CreateBuffer(triangleVertexData, MTLResourceOptions.CpuCacheModeDefault); cubeVertexBuffer = device.CreateBuffer(cubeVertexData, MTLResourceOptions.CpuCacheModeDefault); this.clock = new System.Diagnostics.Stopwatch(); clock.Start(); this.view = CreateLookAt(new Vector3(0, 0, 5), new Vector3(0, 0, 0), Vector3.UnitY); var aspect = (float)(View.Bounds.Size.Width / View.Bounds.Size.Height); this.proj = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, aspect, 0.1f, 100); this.cubeParameters.WorldViewProjection = Matrix4.Identity; cubeConstantBuffer = device.CreateBuffer((uint)Marshal.SizeOf(this.cubeParameters), MTLResourceOptions.CpuCacheModeDefault); // Create Pipeline Descriptor var trianglePipelineStateDescriptor = new MTLRenderPipelineDescriptor { SampleCount = mtkView.SampleCount, VertexFunction = triangleVertexProgram, FragmentFunction = triangleFragmentProgram, VertexDescriptor = triangleVertexDescriptor, DepthAttachmentPixelFormat = mtkView.DepthStencilPixelFormat, StencilAttachmentPixelFormat = mtkView.DepthStencilPixelFormat, }; var cubePipelineStateDescriptor = new MTLRenderPipelineDescriptor { SampleCount = mtkView.SampleCount, VertexFunction = cubeVertexProgram, FragmentFunction = cubeFragmentProgram, VertexDescriptor = cubeVertexDescriptor, DepthAttachmentPixelFormat = mtkView.DepthStencilPixelFormat, StencilAttachmentPixelFormat = mtkView.DepthStencilPixelFormat, }; MTLRenderPipelineColorAttachmentDescriptor triangleRenderBufferAttachment = trianglePipelineStateDescriptor.ColorAttachments[0]; triangleRenderBufferAttachment.PixelFormat = mtkView.ColorPixelFormat; MTLRenderPipelineColorAttachmentDescriptor cubeRenderBufferAttachment = cubePipelineStateDescriptor.ColorAttachments[0]; cubeRenderBufferAttachment.PixelFormat = mtkView.ColorPixelFormat; NSError error; trianglePipelineState = device.CreateRenderPipelineState(trianglePipelineStateDescriptor, out error); if (trianglePipelineState == null) { Console.WriteLine("Failed to created pipeline state, error {0}", error); } cubePipelineState = device.CreateRenderPipelineState(cubePipelineStateDescriptor, out error); if (cubePipelineState == null) { Console.WriteLine("Failed to created pipeline state, error {0}", error); } var depthStencilDescriptor = new MTLDepthStencilDescriptor { DepthCompareFunction = MTLCompareFunction.Less, DepthWriteEnabled = true }; depthStencilState = device.CreateDepthStencilState(depthStencilDescriptor); // Texture NSImage image = NSImage.ImageNamed("crate.png"); MTKTextureLoader mTKTextureLoader = new MTKTextureLoader(device); this.cubeTexture = mTKTextureLoader.FromCGImage(image.CGImage, new MTKTextureLoaderOptions(), out error); MTLSamplerDescriptor samplerDescriptor = new MTLSamplerDescriptor() { MinFilter = MTLSamplerMinMagFilter.Linear, MagFilter = MTLSamplerMinMagFilter.Linear, SAddressMode = MTLSamplerAddressMode.Repeat, TAddressMode = MTLSamplerAddressMode.Repeat, }; this.sampler = device.CreateSamplerState(samplerDescriptor); // Create FrameBuffer texture IMTLTexture drawableTexture = mtkView.CurrentDrawable.Texture; MTLTextureDescriptor textureDescriptor = new MTLTextureDescriptor() { Width = drawableTexture.Width, Height = drawableTexture.Height, PixelFormat = drawableTexture.PixelFormat, TextureType = drawableTexture.TextureType, MipmapLevelCount = drawableTexture.MipmapLevelCount, ArrayLength = drawableTexture.ArrayLength, SampleCount = drawableTexture.SampleCount, Depth = drawableTexture.Depth, CpuCacheMode = drawableTexture.CpuCacheMode, Usage = MTLTextureUsage.RenderTarget, StorageMode = MTLStorageMode.Managed, }; this.colorFrameBufferTexture = device.CreateTexture(textureDescriptor); }
public override void ViewDidLoad() { base.ViewDidLoad(); // Set the view to use the default device device = MTLDevice.SystemDefault; if (device == null) { Console.WriteLine("Metal is not supported on this device"); View = new NSView(View.Frame); } // Create a new command queue commandQueue = device.CreateCommandQueue(); // Load all the shader files with a metal file extension in the project defaultLibrary = device.CreateDefaultLibrary(); // Setup view view = (MTKView)View; view.Delegate = this; view.Device = device; view.SampleCount = 1; view.DepthStencilPixelFormat = MTLPixelFormat.Depth32Float_Stencil8; view.ColorPixelFormat = MTLPixelFormat.BGRA8Unorm; view.PreferredFramesPerSecond = 60; view.ClearColor = new MTLClearColor(0.5f, 0.5f, 0.5f, 1.0f); // Load the vertex program into the library IMTLFunction vertexProgram = defaultLibrary.CreateFunction("triangle_vertex"); // Load the fragment program into the library IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("triangle_fragment"); // Create a vertex descriptor from the MTKMesh MTLVertexDescriptor vertexDescriptor = new MTLVertexDescriptor(); vertexDescriptor.Attributes[0].Format = MTLVertexFormat.Float4; vertexDescriptor.Attributes[0].BufferIndex = 0; vertexDescriptor.Attributes[0].Offset = 0; vertexDescriptor.Attributes[1].Format = MTLVertexFormat.Float4; vertexDescriptor.Attributes[1].BufferIndex = 0; vertexDescriptor.Attributes[1].Offset = 4 * sizeof(float); vertexDescriptor.Layouts[0].Stride = 8 * sizeof(float); vertexDescriptor.Layouts[0].StepRate = 1; vertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex; vertexBuffer = device.CreateBuffer(vertexData, MTLResourceOptions.CpuCacheModeDefault);// (MTLResourceOptions)0); // Create a reusable pipeline state var pipelineStateDescriptor = new MTLRenderPipelineDescriptor { SampleCount = view.SampleCount, VertexFunction = vertexProgram, FragmentFunction = fragmentProgram, VertexDescriptor = vertexDescriptor, DepthAttachmentPixelFormat = view.DepthStencilPixelFormat, StencilAttachmentPixelFormat = view.DepthStencilPixelFormat }; pipelineStateDescriptor.ColorAttachments[0].PixelFormat = view.ColorPixelFormat; NSError error; pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error); if (pipelineState == null) { Console.WriteLine("Failed to created pipeline state, error {0}", error); } var depthStateDesc = new MTLDepthStencilDescriptor { DepthCompareFunction = MTLCompareFunction.Less, DepthWriteEnabled = true }; depthState = device.CreateDepthStencilState(depthStateDesc); this.rectangle = new MTLScissorRect(125, 166, 250, 444); }
public override void ViewDidLoad() { base.ViewDidLoad(); // Set the view to use the default device device = MTLDevice.SystemDefault; if (device == null) { Console.WriteLine("Metal is not supported on this device"); View = new NSView(View.Frame); } // Create a new command queue commandQueue = device.CreateCommandQueue(); // Load all the shader files with a metal file extension in the project defaultLibrary = device.CreateDefaultLibrary(); // Setup view mtkView = (MTKView)View; mtkView.Delegate = this; mtkView.Device = device; mtkView.SampleCount = 1; mtkView.DepthStencilPixelFormat = MTLPixelFormat.Depth32Float_Stencil8; mtkView.ColorPixelFormat = MTLPixelFormat.BGRA8Unorm; mtkView.PreferredFramesPerSecond = 60; mtkView.ClearColor = new MTLClearColor(0.5f, 0.5f, 0.5f, 1.0f); // Load the vertex program into the library IMTLFunction vertexProgram = defaultLibrary.CreateFunction("cube_vertex"); // Load the fragment program into the library IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("cube_fragment"); // Create a vertex descriptor from the MTKMesh MTLVertexDescriptor vertexDescriptor = new MTLVertexDescriptor(); vertexDescriptor.Attributes[0].Format = MTLVertexFormat.Float4; vertexDescriptor.Attributes[0].BufferIndex = 0; vertexDescriptor.Attributes[0].Offset = 0; vertexDescriptor.Attributes[1].Format = MTLVertexFormat.Float4; vertexDescriptor.Attributes[1].BufferIndex = 0; vertexDescriptor.Attributes[1].Offset = 4 * sizeof(float); vertexDescriptor.Layouts[0].Stride = 8 * sizeof(float); vertexDescriptor.Layouts[0].StepRate = 1; vertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex; vertexBuffer = device.CreateBuffer(vertexData, MTLResourceOptions.CpuCacheModeDefault);// (MTLResourceOptions)0); this.clock = new System.Diagnostics.Stopwatch(); clock.Start(); this.view = CreateLookAt(new Vector3(0, 0, 5), new Vector3(0, 0, 0), Vector3.UnitY); var aspect = (float)(View.Bounds.Size.Width / View.Bounds.Size.Height); proj = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, aspect, 0.1f, 100); constantBuffer = device.CreateBuffer(64, MTLResourceOptions.CpuCacheModeDefault); // Create a reusable pipeline state var pipelineStateDescriptor = new MTLRenderPipelineDescriptor { SampleCount = mtkView.SampleCount, VertexFunction = vertexProgram, FragmentFunction = fragmentProgram, VertexDescriptor = vertexDescriptor, DepthAttachmentPixelFormat = mtkView.DepthStencilPixelFormat, StencilAttachmentPixelFormat = mtkView.DepthStencilPixelFormat, }; MTLRenderPipelineColorAttachmentDescriptor renderBufferAttachment = pipelineStateDescriptor.ColorAttachments[0]; renderBufferAttachment.PixelFormat = mtkView.ColorPixelFormat; renderBufferAttachment.BlendingEnabled = true; renderBufferAttachment.SourceRgbBlendFactor = MTLBlendFactor.One; renderBufferAttachment.DestinationRgbBlendFactor = MTLBlendFactor.SourceAlpha; renderBufferAttachment.SourceAlphaBlendFactor = MTLBlendFactor.One; renderBufferAttachment.DestinationAlphaBlendFactor = MTLBlendFactor.OneMinusSourceAlpha; renderBufferAttachment.RgbBlendOperation = MTLBlendOperation.Add; renderBufferAttachment.AlphaBlendOperation = MTLBlendOperation.Add; NSError error; pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error); if (pipelineState == null) { Console.WriteLine("Failed to created pipeline state, error {0}", error); } var depthStateDesc = new MTLDepthStencilDescriptor { DepthCompareFunction = MTLCompareFunction.Less, DepthWriteEnabled = true }; depthState = device.CreateDepthStencilState(depthStateDesc); }
public override void ViewDidLoad() { base.ViewDidLoad(); // Set the view to use the default device device = MTLDevice.SystemDefault; if (device == null) { Console.WriteLine("Metal is not supported on this device"); View = new NSView(View.Frame); } // Create a new command queue commandQueue = device.CreateCommandQueue(); NSError error; // Setup view view = (MTKView)View; view.Delegate = this; view.Device = device; view.SampleCount = 1; view.DepthStencilPixelFormat = MTLPixelFormat.Depth32Float_Stencil8; view.ColorPixelFormat = MTLPixelFormat.BGRA8Unorm; view.PreferredFramesPerSecond = 60; view.ClearColor = new MTLClearColor(0, 0, 0, 1.0f); // Functions var source = System.IO.File.ReadAllText("Triangle.metal"); MTLCompileOptions compileOptions = new MTLCompileOptions() { LanguageVersion = MTLLanguageVersion.v2_0, }; IMTLLibrary customLibrary = device.CreateLibrary(source, compileOptions, out error); IMTLFunction kernelFunction = customLibrary.CreateFunction("tessellation_kernel_triangle"); IMTLFunction vertexFunction = customLibrary.CreateFunction("tessellation_vertex_triangle"); IMTLFunction fragmentFunction = customLibrary.CreateFunction("tessellation_fragment"); // Create a vertex descriptor MTLVertexDescriptor vertexDescriptor = new MTLVertexDescriptor(); vertexDescriptor.Attributes[0].Format = MTLVertexFormat.Float4; vertexDescriptor.Attributes[0].BufferIndex = 0; vertexDescriptor.Attributes[0].Offset = 0; vertexDescriptor.Layouts[0].Stride = 4 * sizeof(float); vertexDescriptor.Layouts[0].StepRate = 1; vertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerPatchControlPoint; // Create RenderPipeline var renderPipelineStateDescriptor = new MTLRenderPipelineDescriptor { SampleCount = view.SampleCount, VertexFunction = vertexFunction, FragmentFunction = fragmentFunction, VertexDescriptor = vertexDescriptor, DepthAttachmentPixelFormat = view.DepthStencilPixelFormat, StencilAttachmentPixelFormat = view.DepthStencilPixelFormat, MaxTessellationFactor = 16, IsTessellationFactorScaleEnabled = false, TessellationFactorFormat = MTLTessellationFactorFormat.Half, TessellationControlPointIndexType = MTLTessellationControlPointIndexType.None, TessellationFactorStepFunction = MTLTessellationFactorStepFunction.Constant, TessellationOutputWindingOrder = MTLWinding.Clockwise, TessellationPartitionMode = MTLTessellationPartitionMode.FractionalEven, }; renderPipelineStateDescriptor.ColorAttachments[0].PixelFormat = view.ColorPixelFormat; renderPipelineState = device.CreateRenderPipelineState(renderPipelineStateDescriptor, out error); if (renderPipelineState == null) { Console.WriteLine("Failed to created pipeline state, error {0}", error); } MTLDepthStencilDescriptor depthStateDesc = new MTLDepthStencilDescriptor { DepthCompareFunction = MTLCompareFunction.Less, DepthWriteEnabled = true }; depthState = device.CreateDepthStencilState(depthStateDesc); computePipelineState = device.CreateComputePipelineState(kernelFunction, out error); // Buffers tessellationFactorsBuffer = device.CreateBuffer(256, MTLResourceOptions.StorageModePrivate); tessellationFactorsBuffer.Label = "Tessellation Factors"; controlPointsBuffer = device.CreateBuffer(controlPointPositionsTriangle, MTLResourceOptions.StorageModeManaged); controlPointsBuffer.Label = "Control Points Triangle"; }
public override void ViewDidLoad() { base.ViewDidLoad(); // Set the view to use the default device device = MTLDevice.SystemDefault; if (device == null) { Console.WriteLine("Metal is not supported on this device"); View = new NSView(View.Frame); } // Create a new command queue commandQueue = device.CreateCommandQueue(); // Load all the shader files with a metal file extension in the project defaultLibrary = device.CreateDefaultLibrary(); // Setup view mtkView = (MTKView)View; mtkView.Delegate = this; mtkView.Device = device; mtkView.SampleCount = 1; mtkView.DepthStencilPixelFormat = MTLPixelFormat.Depth32Float_Stencil8; mtkView.ColorPixelFormat = MTLPixelFormat.BGRA8Unorm; mtkView.PreferredFramesPerSecond = 60; mtkView.ClearColor = new MTLClearColor(0.5f, 0.5f, 0.5f, 1.0f); // Load the vertex program into the library IMTLFunction vertexProgram = defaultLibrary.CreateFunction("cube_vertex"); // Load the fragment program into the library IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("cube_fragment"); // Create a vertex descriptor from the MTKMesh MTLVertexDescriptor vertexDescriptor = new MTLVertexDescriptor(); vertexDescriptor.Attributes[0].Format = MTLVertexFormat.Float4; vertexDescriptor.Attributes[0].BufferIndex = 0; vertexDescriptor.Attributes[0].Offset = 0; vertexDescriptor.Attributes[1].Format = MTLVertexFormat.Float3; vertexDescriptor.Attributes[1].BufferIndex = 0; vertexDescriptor.Attributes[1].Offset = 4 * sizeof(float); vertexDescriptor.Attributes[2].Format = MTLVertexFormat.Float2; vertexDescriptor.Attributes[2].BufferIndex = 0; vertexDescriptor.Attributes[2].Offset = 7 * sizeof(float); vertexDescriptor.Layouts[0].Stride = 9 * sizeof(float); vertexDescriptor.Layouts[0].StepRate = 1; vertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex; // Primitive Torus(1.0f, 0.3f, 28, out List <PositionNormalTexture> vertexData, out List <ushort> indexData); vertexBuffer = device.CreateBuffer(vertexData.ToArray(), MTLResourceOptions.CpuCacheModeDefault);// (MTLResourceOptions)0); indexDataArray = indexData.ToArray(); indexBuffer = device.CreateBuffer(indexDataArray, MTLResourceOptions.CpuCacheModeDefault); // Use clock this.clock = new System.Diagnostics.Stopwatch(); clock.Start(); Vector3 cameraPosition = new Vector3(0, 0, 1.5f); this.view = CreateLookAt(cameraPosition, new Vector3(0, 0, 0), Vector3.UnitY); var aspect = (float)(View.Bounds.Size.Width / View.Bounds.Size.Height); proj = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, aspect, 0.1f, 100); // Constant Buffer this.param = new Parameters() { CameraPosition = cameraPosition, WorldViewProjection = Matrix4.Identity, World = Matrix4.Identity, WorldInverseTranspose = Matrix4.Identity, }; this.constantBuffer = device.CreateBuffer((uint)Marshal.SizeOf(this.param), MTLResourceOptions.CpuCacheModeDefault); // Create a reusable pipeline state var pipelineStateDescriptor = new MTLRenderPipelineDescriptor { SampleCount = mtkView.SampleCount, VertexFunction = vertexProgram, FragmentFunction = fragmentProgram, VertexDescriptor = vertexDescriptor, DepthAttachmentPixelFormat = mtkView.DepthStencilPixelFormat, StencilAttachmentPixelFormat = mtkView.DepthStencilPixelFormat, }; MTLRenderPipelineColorAttachmentDescriptor renderBufferAttachment = pipelineStateDescriptor.ColorAttachments[0]; renderBufferAttachment.PixelFormat = mtkView.ColorPixelFormat; NSError error; pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error); if (pipelineState == null) { Console.WriteLine("Failed to created pipeline state, error {0}", error); } var depthStateDesc = new MTLDepthStencilDescriptor { DepthCompareFunction = MTLCompareFunction.Less, DepthWriteEnabled = true }; depthState = device.CreateDepthStencilState(depthStateDesc); MTKTextureLoader mTKTextureLoader = new MTKTextureLoader(device); // Texture NSUrl url = NSBundle.MainBundle.GetUrlForResource("cubemap2", "ktx"); this.texture = mTKTextureLoader.FromUrl(url, new MTKTextureLoaderOptions(), out error); Console.WriteLine("Failed to created pipeline state, error {0}", error); MTLSamplerDescriptor samplerDescriptor = new MTLSamplerDescriptor() { MinFilter = MTLSamplerMinMagFilter.Linear, MagFilter = MTLSamplerMinMagFilter.Linear, MipFilter = MTLSamplerMipFilter.Linear, SAddressMode = MTLSamplerAddressMode.ClampToEdge, TAddressMode = MTLSamplerAddressMode.ClampToEdge, }; this.sampler = device.CreateSamplerState(samplerDescriptor); }
public override void ViewDidLoad() { base.ViewDidLoad(); // Set the view to use the default device device = MTLDevice.SystemDefault; if (device == null) { Console.WriteLine("Metal is not supported on this device"); View = new NSView(View.Frame); } // Create a new command queue commandQueue = device.CreateCommandQueue(); // Load all the shader files with a metal file extension in the project defaultLibrary = device.CreateDefaultLibrary(); // Setup view mtkView = (MTKView)View; mtkView.Delegate = this; mtkView.Device = device; mtkView.SampleCount = 1; mtkView.DepthStencilPixelFormat = MTLPixelFormat.Depth32Float_Stencil8; mtkView.ColorPixelFormat = MTLPixelFormat.BGRA8Unorm; mtkView.PreferredFramesPerSecond = 60; mtkView.ClearColor = new MTLClearColor(0.5f, 0.5f, 0.5f, 1.0f); // Load the vertex program into the library IMTLFunction vertexProgram = defaultLibrary.CreateFunction("mesh_vertex"); // Load the fragment program into the library IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("mesh_fragment"); // Generate meshes MTKMeshBufferAllocator mtkBufferAllocator = new MTKMeshBufferAllocator(device); NSUrl url = NSBundle.MainBundle.GetUrlForResource("Fighter", "obj"); MDLAsset mdlAsset = new MDLAsset(url, new MDLVertexDescriptor(), mtkBufferAllocator); MDLObject mdlObject = mdlAsset.GetObject(0); MDLMesh mdlMesh = mdlObject as MDLMesh; NSError error; objMesh = new MTKMesh(mdlMesh, device, out error); // Create a vertex descriptor from the MTKMesh MTLVertexDescriptor vertexDescriptor = MTLVertexDescriptor.FromModelIO(objMesh.VertexDescriptor); vertexDescriptor.Layouts[0].StepRate = 1; vertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex; this.clock = new System.Diagnostics.Stopwatch(); clock.Start(); this.view = CreateLookAt(new Vector3(0, 1, 2), new Vector3(0, 0, 0), Vector3.UnitY); var aspect = (float)(View.Bounds.Size.Width / View.Bounds.Size.Height); this.proj = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, aspect, 0.1f, 100); this.constantBuffer = device.CreateBuffer((uint)Marshal.SizeOf(this.param), MTLResourceOptions.CpuCacheModeDefault); // Create a reusable pipeline state var pipelineStateDescriptor = new MTLRenderPipelineDescriptor { SampleCount = mtkView.SampleCount, VertexFunction = vertexProgram, FragmentFunction = fragmentProgram, VertexDescriptor = vertexDescriptor, DepthAttachmentPixelFormat = mtkView.DepthStencilPixelFormat, StencilAttachmentPixelFormat = mtkView.DepthStencilPixelFormat }; pipelineStateDescriptor.ColorAttachments[0].PixelFormat = mtkView.ColorPixelFormat; pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error); if (pipelineState == null) { Console.WriteLine("Failed to created pipeline state, error {0}", error); } var depthStateDesc = new MTLDepthStencilDescriptor { DepthCompareFunction = MTLCompareFunction.Less, DepthWriteEnabled = true }; depthState = device.CreateDepthStencilState(depthStateDesc); NSImage image = NSImage.ImageNamed("Fighter_Diffuse.jpg"); MTKTextureLoader mTKTextureLoader = new MTKTextureLoader(device); this.texture = mTKTextureLoader.FromCGImage(image.CGImage, new MTKTextureLoaderOptions(), out error); MTLSamplerDescriptor samplerDescriptor = new MTLSamplerDescriptor() { MinFilter = MTLSamplerMinMagFilter.Linear, MagFilter = MTLSamplerMinMagFilter.Linear, SAddressMode = MTLSamplerAddressMode.ClampToEdge, TAddressMode = MTLSamplerAddressMode.ClampToEdge, }; this.sampler = device.CreateSamplerState(samplerDescriptor); }
public override void ViewDidLoad() { base.ViewDidLoad(); // Set the view to use the default device device = MTLDevice.SystemDefault; if (device == null) { Console.WriteLine("Metal is not supported on this device"); View = new NSView(View.Frame); } // Create a new command queue commandQueue = device.CreateCommandQueue(); // Load all the shader files with a metal file extension in the project defaultLibrary = device.CreateDefaultLibrary(); // Setup view mtkView = (MTKView)View; mtkView.Delegate = this; mtkView.Device = device; mtkView.SampleCount = 1; mtkView.DepthStencilPixelFormat = MTLPixelFormat.Depth32Float_Stencil8; mtkView.ColorPixelFormat = MTLPixelFormat.BGRA8Unorm; mtkView.PreferredFramesPerSecond = 60; mtkView.ClearColor = new MTLClearColor(0.5f, 0.5f, 0.5f, 1.0f); // Load the vertex program into the library IMTLFunction vertexProgram = defaultLibrary.CreateFunction("cube_vertex"); // Load the fragment program into the library IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("cube_fragment"); // Create a vertex descriptor from the MTKMesh MTLVertexDescriptor vertexDescriptor = new MTLVertexDescriptor(); vertexDescriptor.Attributes[0].Format = MTLVertexFormat.Float4; vertexDescriptor.Attributes[0].BufferIndex = 0; vertexDescriptor.Attributes[0].Offset = 0; vertexDescriptor.Attributes[1].Format = MTLVertexFormat.Float4; vertexDescriptor.Attributes[1].BufferIndex = 0; vertexDescriptor.Attributes[1].Offset = 4 * sizeof(float); vertexDescriptor.Attributes[2].Format = MTLVertexFormat.Float2; vertexDescriptor.Attributes[2].BufferIndex = 0; vertexDescriptor.Attributes[2].Offset = 8 * sizeof(float); vertexDescriptor.Layouts[0].Stride = 10 * sizeof(float); vertexDescriptor.Layouts[0].StepRate = 1; vertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex; vertexBuffer = device.CreateBuffer(vertexData, MTLResourceOptions.CpuCacheModeDefault);// (MTLResourceOptions)0); this.clock = new System.Diagnostics.Stopwatch(); clock.Start(); this.view = CreateLookAt(new Vector3(0, 0, 5), new Vector3(0, 0, 0), Vector3.UnitY); var aspect = (float)(View.Bounds.Size.Width / View.Bounds.Size.Height); proj = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, aspect, 0.1f, 100); this.constantBuffer1 = device.CreateBuffer((uint)Marshal.SizeOf(this.param), MTLResourceOptions.CpuCacheModeDefault); this.constantBuffer2 = device.CreateBuffer((uint)Marshal.SizeOf(this.param), MTLResourceOptions.CpuCacheModeDefault); // Create a reusable pipeline state var pipelineStateDescriptor = new MTLRenderPipelineDescriptor { SampleCount = mtkView.SampleCount, VertexFunction = vertexProgram, FragmentFunction = fragmentProgram, VertexDescriptor = vertexDescriptor, DepthAttachmentPixelFormat = mtkView.DepthStencilPixelFormat, StencilAttachmentPixelFormat = mtkView.DepthStencilPixelFormat, }; MTLRenderPipelineColorAttachmentDescriptor renderBufferAttachment = pipelineStateDescriptor.ColorAttachments[0]; renderBufferAttachment.PixelFormat = mtkView.ColorPixelFormat; NSError error; pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error); if (pipelineState == null) { Console.WriteLine("Failed to created pipeline state, error {0}", error); } var depthStencilState1Description = new MTLDepthStencilDescriptor { DepthCompareFunction = MTLCompareFunction.Less, DepthWriteEnabled = true, FrontFaceStencil = new MTLStencilDescriptor() { WriteMask = 0xff, StencilCompareFunction = MTLCompareFunction.Always, DepthStencilPassOperation = MTLStencilOperation.IncrementClamp, } }; depthStencilState1 = device.CreateDepthStencilState(depthStencilState1Description); var depthStencilState2Description = new MTLDepthStencilDescriptor { DepthCompareFunction = MTLCompareFunction.Less, DepthWriteEnabled = true, FrontFaceStencil = new MTLStencilDescriptor() { ReadMask = 0xff, WriteMask = 0x0, StencilCompareFunction = MTLCompareFunction.NotEqual, } }; depthStencilState2 = device.CreateDepthStencilState(depthStencilState2Description); // Texture NSImage image = NSImage.ImageNamed("crate.png"); MTKTextureLoader mTKTextureLoader = new MTKTextureLoader(device); this.texture = mTKTextureLoader.FromCGImage(image.CGImage, new MTKTextureLoaderOptions(), out error); MTLSamplerDescriptor samplerDescriptor = new MTLSamplerDescriptor() { MinFilter = MTLSamplerMinMagFilter.Linear, MagFilter = MTLSamplerMinMagFilter.Linear, SAddressMode = MTLSamplerAddressMode.Repeat, TAddressMode = MTLSamplerAddressMode.Repeat, }; this.sampler = device.CreateSamplerState(samplerDescriptor); }
void LoadAssets() { // Load the fragment program into the library. IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("fragmentLight"); // Load the vertex program into the library. IMTLFunction vertexProgram = defaultLibrary.CreateFunction("vertexLight"); /* * Create a vertex descriptor for our Metal pipeline. Specifies the layout * of vertices the pipeline should expect. */ var mtlVertexDescriptor = new MTLVertexDescriptor(); // Positions. mtlVertexDescriptor.Attributes [(int)VertexAttributes.Position].Format = MTLVertexFormat.Float3; mtlVertexDescriptor.Attributes [(int)VertexAttributes.Position].Offset = 0; mtlVertexDescriptor.Attributes [(int)VertexAttributes.Position].BufferIndex = (nuint)(int)BufferIndex.MeshVertexBuffer; // Normals. mtlVertexDescriptor.Attributes[(int)VertexAttributes.Normal].Format = MTLVertexFormat.Float3; mtlVertexDescriptor.Attributes[(int)VertexAttributes.Normal].Offset = 12; mtlVertexDescriptor.Attributes[(int)VertexAttributes.Normal].BufferIndex = (nuint)(int)BufferIndex.MeshVertexBuffer; // Texture coordinates. mtlVertexDescriptor.Attributes[(int)VertexAttributes.Texcoord].Format = MTLVertexFormat.Half2; mtlVertexDescriptor.Attributes[(int)VertexAttributes.Texcoord].Offset = 24; mtlVertexDescriptor.Attributes[(int)VertexAttributes.Texcoord].BufferIndex = (nuint)(int)BufferIndex.MeshVertexBuffer; // Single interleaved buffer. mtlVertexDescriptor.Layouts[(int)BufferIndex.MeshVertexBuffer].Stride = 28; mtlVertexDescriptor.Layouts[(int)BufferIndex.MeshVertexBuffer].StepRate = 1; mtlVertexDescriptor.Layouts[(int)BufferIndex.MeshVertexBuffer].StepFunction = MTLVertexStepFunction.PerVertex; // Create a reusable pipeline state var pipelineStateDescriptor = new MTLRenderPipelineDescriptor { Label = "MyPipeline", SampleCount = view.SampleCount, VertexFunction = vertexProgram, FragmentFunction = fragmentProgram, VertexDescriptor = mtlVertexDescriptor }; pipelineStateDescriptor.ColorAttachments [0].PixelFormat = view.ColorPixelFormat; pipelineStateDescriptor.DepthAttachmentPixelFormat = view.DepthStencilPixelFormat; pipelineStateDescriptor.StencilAttachmentPixelFormat = view.DepthStencilPixelFormat; NSError error; pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error); if (pipelineState == null) { Console.WriteLine("Failed to created pipeline state, error {0}", error.LocalizedDescription); } var depthStateDesc = new MTLDepthStencilDescriptor { DepthCompareFunction = MTLCompareFunction.Less, DepthWriteEnabled = true, }; depthState = device.CreateDepthStencilState(depthStateDesc); /* * From our Metal vertex descriptor, create a Model I/O vertex descriptor we'll * load our asset with. This specifies the layout of vertices Model I/O should * format loaded meshes with. */ var mdlVertexDescriptor = MDLVertexDescriptor.FromMetal(mtlVertexDescriptor); mdlVertexDescriptor.Attributes.GetItem <MDLVertexAttribute> ((int)VertexAttributes.Position).Name = MDLVertexAttributes.Position; mdlVertexDescriptor.Attributes.GetItem <MDLVertexAttribute> ((int)VertexAttributes.Normal).Name = MDLVertexAttributes.Normal; mdlVertexDescriptor.Attributes.GetItem <MDLVertexAttribute> ((int)VertexAttributes.Texcoord).Name = MDLVertexAttributes.TextureCoordinate; var bufferAllocator = new MTKMeshBufferAllocator(device); NSUrl assetUrl = NSBundle.MainBundle.GetUrlForResource("Data/Assets/realship/realship.obj", string.Empty); if (assetUrl == null) { Console.WriteLine("Could not find asset."); } /* * Load Model I/O Asset with mdlVertexDescriptor, specifying vertex layout and * bufferAllocator enabling ModelIO to load vertex and index buffers directory * into Metal GPU memory. */ var asset = new MDLAsset(assetUrl, mdlVertexDescriptor, bufferAllocator); // Create MetalKit meshes. MDLMesh[] mdlMeshes; NSError mtkError; var mtkMeshes = MTKMesh.FromAsset(asset, device, out mdlMeshes, out mtkError); if (mtkMeshes == null) { Console.WriteLine("Failed to create mesh, error {0}", error.LocalizedDescription); return; } // Create our array of App-Specific mesh wrapper objects. meshes = new List <MetalKitEssentialsMesh> (); for (int i = 0; i < mtkMeshes.Length; i++) { var mtkMesh = mtkMeshes [i]; var mdlMesh = mdlMeshes [(nuint)i]; var mesh = new MetalKitEssentialsMesh(mtkMesh, mdlMesh, device); meshes.Add(mesh); } for (int i = 0; i < maxInflightBuffers; i++) { frameUniformBuffers [i] = device.CreateBuffer((nuint)Marshal.SizeOf <FrameUniforms> (), MTLResourceOptions.CpuCacheModeDefault); } }
public MetalKitEssentialsSubmesh(MTKSubmesh mtkSubmesh, MDLSubmesh mdlSubmesh, IMTLDevice device) { materialUniforms = device.CreateBuffer((nuint)Marshal.SizeOf <MaterialUniforms> (), MTLResourceOptions.CpuCacheModeDefault); var uniforms = Marshal.PtrToStructure <MaterialUniforms> (materialUniforms.Contents); submesh = mtkSubmesh; for (nuint i = 0; i < mdlSubmesh.Material.Count; i++) { MDLMaterialProperty property = ObjectAtIndexedSubscript(mdlSubmesh.Material, i); if (property == null) { continue; } if (property.Name == "baseColorMap") { if (property.Type != MDLMaterialPropertyType.String) { continue; } var textureURL = new NSUrl(string.Format("file://{0}", property.StringValue)); var textureLoader = new MTKTextureLoader(device); NSError error; diffuseTexture = textureLoader.FromUrl(textureURL, null, out error); if (diffuseTexture == null) { throw new Exception(string.Format("Diffuse texture load: {0}", error.LocalizedDescription)); } } else if (property.Name == "specularColor") { if (property.Type == MDLMaterialPropertyType.Float4) { uniforms.specularColor = property.Float4Value; } else if (property.Type == MDLMaterialPropertyType.Float3) { uniforms.specularColor = new Vector4(property.Float3Value); } uniforms.specularColor.W = 1f; } else if (property.Name == "emission") { if (property.Type == MDLMaterialPropertyType.Float4) { uniforms.emissiveColor = property.Float4Value; } else if (property.Type == MDLMaterialPropertyType.Float3) { uniforms.emissiveColor = new Vector4(property.Float3Value); } uniforms.emissiveColor.W = 1f; } } Marshal.StructureToPtr(uniforms, materialUniforms.Contents, true); }
public override void ViewDidLoad() { base.ViewDidLoad(); // Set the view to use the default device device = MTLDevice.SystemDefault; if (device == null) { Console.WriteLine("Metal is not supported on this device"); View = new NSView(View.Frame); } // Create a new command queue commandQueue = device.CreateCommandQueue(); // Load all the shader files with a metal file extension in the project defaultLibrary = device.CreateDefaultLibrary(); // Setup view view = (MTKView)View; view.Delegate = this; view.Device = device; view.SampleCount = 1; view.DepthStencilPixelFormat = MTLPixelFormat.Depth32Float_Stencil8; view.ColorPixelFormat = MTLPixelFormat.BGRA8Unorm; view.PreferredFramesPerSecond = 60; view.ClearColor = new MTLClearColor(0.5f, 0.5f, 0.5f, 1.0f); // Load the vertex program into the library IMTLFunction vertexProgram = defaultLibrary.CreateFunction("quad_vertex"); // Load the fragment program into the library IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("quad_fragment"); // Create a vertex descriptor from the MTKMesh MTLVertexDescriptor vertexDescriptor = new MTLVertexDescriptor(); vertexDescriptor.Attributes[0].Format = MTLVertexFormat.Float4; vertexDescriptor.Attributes[0].BufferIndex = 0; vertexDescriptor.Attributes[0].Offset = 0; vertexDescriptor.Attributes[1].Format = MTLVertexFormat.Float2; vertexDescriptor.Attributes[1].BufferIndex = 0; vertexDescriptor.Attributes[1].Offset = 4 * sizeof(float); vertexDescriptor.Layouts[0].Stride = 6 * sizeof(float); vertexDescriptor.Layouts[0].StepRate = 1; vertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex; this.vertexBuffer = device.CreateBuffer(vertexData, MTLResourceOptions.CpuCacheModeDefault);// (MTLResourceOptions)0); this.mipmapping = 0; this.constantBuffer = device.CreateBuffer(sizeof(float), MTLResourceOptions.CpuCacheModeDefault); SetConstantBuffer(this.mipmapping, constantBuffer); // Create a reusable pipeline state var pipelineStateDescriptor = new MTLRenderPipelineDescriptor { SampleCount = view.SampleCount, VertexFunction = vertexProgram, FragmentFunction = fragmentProgram, VertexDescriptor = vertexDescriptor, DepthAttachmentPixelFormat = view.DepthStencilPixelFormat, StencilAttachmentPixelFormat = view.DepthStencilPixelFormat }; pipelineStateDescriptor.ColorAttachments[0].PixelFormat = view.ColorPixelFormat; NSError error; pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error); if (pipelineState == null) { Console.WriteLine("Failed to created pipeline state, error {0}", error); } var depthStateDesc = new MTLDepthStencilDescriptor { DepthCompareFunction = MTLCompareFunction.Less, DepthWriteEnabled = true }; depthState = device.CreateDepthStencilState(depthStateDesc); // Texture KTX NSUrl url = NSBundle.MainBundle.GetUrlForResource("crate", "ktx"); MTKTextureLoader mTKTextureLoader = new MTKTextureLoader(device); this.texture = mTKTextureLoader.FromUrl(url, new MTKTextureLoaderOptions(), out error); Console.WriteLine("Failed to created pipeline state, error {0}", error); MTLSamplerDescriptor samplerDescriptor = new MTLSamplerDescriptor() { MinFilter = MTLSamplerMinMagFilter.Linear, MagFilter = MTLSamplerMinMagFilter.Linear, MipFilter = MTLSamplerMipFilter.Linear, SAddressMode = MTLSamplerAddressMode.ClampToEdge, TAddressMode = MTLSamplerAddressMode.ClampToEdge, }; this.sampler = device.CreateSamplerState(samplerDescriptor); this.clock = new System.Diagnostics.Stopwatch(); this.clock.Start(); this.time = 0; }
public ClothSimMetalNode(IMTLDevice device, uint width, uint height) { var vector3Size = System.Runtime.InteropServices.Marshal.SizeOf <OpenTK.NVector3>(); var vertices = new List <SCNVector3>(); var normals = new List <SCNVector3>(); var uvs = new List <OpenTK.Vector2>(); var indices = new List <byte>(); for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { var p = new SCNVector3(x, 0, y); vertices.Add(p); normals.Add(SCNVector3.UnitY); uvs.Add(new OpenTK.Vector2(p.X / width, p.Z / height)); } } for (var y = 0; y < (height - 1); y++) { for (var x = 0; x < (width - 1); x++) { // make 2 triangles from the 4 vertices of a quad var i0 = (byte)(y * width + x); var i1 = (byte)(i0 + 1); var i2 = (byte)(i0 + width); var i3 = (byte)(i2 + 1); // triangle 1 indices.Add(i0); indices.Add(i2); indices.Add(i3); // triangle 2 indices.Add(i0); indices.Add(i3); indices.Add(i1); } } var vertexBuffer1 = device.CreateBuffer(vertices.ToArray(), MTLResourceOptions.CpuCacheModeWriteCombined); var vertexBuffer2 = device.CreateBuffer((nuint)(vertices.Count * vector3Size), MTLResourceOptions.CpuCacheModeWriteCombined); var vertexSource = SCNGeometrySource.FromMetalBuffer(vertexBuffer1, MTLVertexFormat.Float3, SCNGeometrySourceSemantics.Vertex, vertices.Count, 0, vector3Size); var normalBuffer = device.CreateBuffer(normals.ToArray(), MTLResourceOptions.CpuCacheModeWriteCombined); var normalWorkBuffer = device.CreateBuffer((nuint)(normals.Count * vector3Size), MTLResourceOptions.CpuCacheModeWriteCombined); var normalSource = SCNGeometrySource.FromMetalBuffer(normalBuffer, MTLVertexFormat.Float3, SCNGeometrySourceSemantics.Normal, normals.Count, 0, vector3Size); var uvBuffer = device.CreateBuffer(uvs.ToArray(), MTLResourceOptions.CpuCacheModeWriteCombined); var uvSource = SCNGeometrySource.FromMetalBuffer(uvBuffer, MTLVertexFormat.Float2, SCNGeometrySourceSemantics.Texcoord, uvs.Count, 0, OpenTK.Vector2.SizeInBytes); var data = NSData.FromArray(indices.ToArray()); var indexElement = SCNGeometryElement.FromData(data, SCNGeometryPrimitiveType.Triangles, 1178, 4); var geometry = SCNGeometry.Create(new SCNGeometrySource[] { vertexSource, normalSource, uvSource }, new SCNGeometryElement[] { indexElement }); // velocity buffers var velocityBuffer1 = device.CreateBuffer((nuint)(vertices.Count * vector3Size), MTLResourceOptions.CpuCacheModeWriteCombined); var velocityBuffer2 = device.CreateBuffer((nuint)(vertices.Count * vector3Size), MTLResourceOptions.CpuCacheModeWriteCombined); this.Geometry = geometry; this.VertexCount = vertices.Count; this.Vb1 = vertexBuffer1; this.Vb2 = vertexBuffer2; this.NormalBuffer = normalBuffer; this.NormalWorkBuffer = normalWorkBuffer; this.VelocityBuffers = new List <IMTLBuffer> { velocityBuffer1, velocityBuffer2 }; }