Exemple #1
0
        public void Draw(MTKView view)
        {
            // Create a new command buffer for each renderpass to the current drawable
            IMTLCommandBuffer commandBuffer = commandQueue.CommandBuffer();

            // Call the view's completion handler which is required by the view since it will signal its semaphore and set up the next buffer
            var drawable = view.CurrentDrawable;

            // Obtain a renderPassDescriptor generated from the view's drawable textures
            MTLRenderPassDescriptor renderPassDescriptor = view.CurrentRenderPassDescriptor;

            // If we have a valid drawable, begin the commands to render into it
            if (renderPassDescriptor != null)
            {
                // Create a render command encoder so we can render into something
                IMTLRenderCommandEncoder renderEncoder = commandBuffer.CreateRenderCommandEncoder(renderPassDescriptor);

                // First Draw
                var time          = clock.ElapsedMilliseconds / 1000.0f;
                var viewProj      = Matrix4.Mult(this.view, this.proj);
                var worldViewProj = Matrix4.CreateRotationX(time) * Matrix4.CreateRotationY(time * 2) * Matrix4.CreateRotationZ(time * .7f) * viewProj;

                param.WorldViewProjection = Matrix4.Transpose(worldViewProj);
                param.IsTextured          = true;
                SetConstantBuffer(this.param, this.constantBuffer1);

                // Set context state
                renderEncoder.SetRenderPipelineState(pipelineState);
                renderEncoder.SetFrontFacingWinding(MTLWinding.Clockwise);
                renderEncoder.SetCullMode(MTLCullMode.None);

                renderEncoder.SetStencilReferenceValue(0);
                renderEncoder.SetDepthStencilState(depthStencilState1);

                renderEncoder.SetVertexBuffer(vertexBuffer, 0, 0);
                renderEncoder.SetFragmentTexture(this.texture, 0);
                renderEncoder.SetFragmentSamplerState(this.sampler, 0);
                renderEncoder.SetVertexBuffer(constantBuffer1, (nuint)Marshal.SizeOf(this.param), 1);
                renderEncoder.SetFragmentBuffer(constantBuffer1, (nuint)Marshal.SizeOf(this.param), 1);

                // Tell the render context we want to draw our primitives
                renderEncoder.DrawPrimitives(MTLPrimitiveType.Triangle, 0, (nuint)vertexData.Length);


                // Second Draw

                // Set constant buffer
                param.IsTextured          = false;
                worldViewProj             = Matrix4.CreateRotationX(time) * Matrix4.CreateRotationY(time * 2) * Matrix4.CreateRotationZ(time * .7f) * Matrix4.Scale(1.04f) * viewProj;
                param.WorldViewProjection = Matrix4.Transpose(worldViewProj);
                SetConstantBuffer(this.param, constantBuffer2);

                renderEncoder.SetStencilReferenceValue(1);
                renderEncoder.SetDepthStencilState(depthStencilState2);

                renderEncoder.SetVertexBuffer(constantBuffer2, (nuint)Marshal.SizeOf(this.param), 1);
                renderEncoder.SetFragmentBuffer(constantBuffer2, (nuint)Marshal.SizeOf(this.param), 1);

                // Tell the render context we want to draw our primitives
                renderEncoder.DrawPrimitives(MTLPrimitiveType.Triangle, 0, (nuint)vertexData.Length);

                // We're done encoding commands
                renderEncoder.EndEncoding();

                // Schedule a present once the framebuffer is complete using the current drawable
                commandBuffer.PresentDrawable(drawable);
            }

            // Finalize rendering here & push the command buffer to the GPU
            commandBuffer.Commit();
        }