Challenge: Draw with metal-cpp
June 8, 2022
Metal is the foundation for accelerated graphics and compute power on Apple platforms — and if you’re familiar with C++, now’s the perfect time to explore its incredible power. For this challenge, we're inviting you to try out metal-cpp and render your own triangle, sphere, or even a mesh in Xcode.
We also welcome you to visit the Graphics & Games Study Hall during the day to collaborate on this challenge! Ask questions, connect with other developers, and share your creations.
Study Hall: Draw with metal-cpp
View nowBegin the challenge
Before you begin, you’ll want to watch “Program Metal in C++ with metal-cpp” and download the LearnMetalCPP project, which contains a series of C++ samples.
Program Metal in C++ with metal-cpp
Watch nowDownload the LearnMetalCPP project
Open the project in Xcode, and choose 00-window.cpp as your base code. To render your image, you’ll need to set up a few things within your project.
First, create a MTL::RenderPipelineState
object with a MTL::RenderPipelineDescriptor
. To do this, you’ll need to create a function, like buildShaders()
. In the code snippet below, we’ve provided the shader code needed to render a single triangle.
void Renderer::buildShaders()
{
using NS::StringEncoding::UTF8StringEncoding;
const char* shaderSrc = R"(
#include <metal_stdlib>
using namespace metal;
struct AAPLVertex
{
float3 position;
half3 color;
};
// Welcome to modify the mesh as you want
constant AAPLVertex triangles[] = {
{ float3{ -0.8f, 0.8f, 0.0f }, half3{ 1.0, 0.3f, 0.2f } },
{ float3{ 0.0f, -0.8f, 0.0f }, half3{ 0.8f, 1.0, 0.0f } },
{ float3{ +0.8f, 0.8f, 0.0f }, half3{ 0.8f, 0.0f, 1.0 } }
};
struct v2f
{
float4 position [[position]];
half3 color;
};
v2f vertex vertexMain( uint vertexId [[vertex_id]])
{
v2f o;
o.position = float4( triangles[ vertexId ].position, 1.0 );
o.color = half3 ( triangles[ vertexId ].color );
return o;
}
half4 fragment fragmentMain( v2f in [[stage_in]] )
{
return half4( in.color, 1.0 );
}
)";
// TODO: Create a MTL::RenderPipelineDescriptor
// TODO: Allocate a MTL::RenderPipelineState object
}
Then, extend the Renderer::draw( MTK::View* pView)
function by setting a MTL::RenderPipelineState
and inserting draw calls.
void Renderer::draw( MTK::View* pView )
{
...
// TODO: Set MTL::RenderPipelineState
// TODO: Draw a single triangle or more!
...
}
After that:
- Create the
MTL::RenderPipelineDescriptor
object and set up some properties. - Create the
MTL::RenderPipelineState
object. - Tip: Be careful with object lifecycles.
Ready to share your metal-cpp art with the community? Show us what you’ve made on Twitter with the hashtag #WWDC22Challenges, or share your work in the Graphics & Games Study Hall. And if you'd like to discuss metal-cpp and other Graphics & Games topics, join the team at events all throughout the week at WWDC22.