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);
        }
		void LoadAssets ()
		{
			var textureLoader = new MTKTextureLoader (metalView.Device);
			NSUrl url = NSBundle.MainBundle.GetUrlForResource ("AnimalImage", "png");

			NSError error;
			sourceTexture = textureLoader.FromUrl (url, null, out error);
		}
Пример #3
0
        void LoadAssets()
        {
            var   textureLoader = new MTKTextureLoader(metalView.Device);
            NSUrl url           = NSBundle.MainBundle.GetUrlForResource("AnimalImage", "png");

            NSError error;

            sourceTexture = textureLoader.FromUrl(url, null, out error);
        }
        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
            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 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);
        }