Exemplo n.º 1
0
        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);
            }
        }
		void LoadAssets ()
		{
			IMTLFunction fragmentProgram = defaultLibrary.CreateFunction ("fragmentLight");
			IMTLFunction vertexProgram = defaultLibrary.CreateFunction ("vertexLight");

			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);
			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.");

			// Create MetalKit meshes.
			MTKMesh[] mtkMeshes;
			NSArray mdlMeshes;
			NSError mtkError;

			var asset = new MDLAsset (assetUrl, mdlVertexDescriptor, bufferAllocator);

			mtkMeshes = MTKMesh.FromAsset (asset, device, out mdlMeshes, out mtkError);

			if (mtkMeshes == null) {
				Console.WriteLine ("Failed to create mesh, error {0}", error.LocalizedDescription);
				return;
			}

			meshes = new List<MetalKitEssentialsMesh> ();

			for (int i = 0; i < mtkMeshes.Length; i++) {
				var mtkMesh = mtkMeshes [i];
				var mdlMesh = mdlMeshes.GetItem<MDLMesh> ((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);
		}