Introduction to basic knowledge of metal, the first Metal By Example series: http://metalbyexample.com/ . Related articles of the blogger mainly give typical problems encountered in engineering practice and solutions.
Source code of this section: https://github.com/sjy234sjy234/Learn-Metal/tree/master/MetalPoint . Metal graphics rendering engine is built-in to support the drawing of points with adjustable size, and the drawing is a square point. First, metal's drawPrimitives method supports 5 mtlprimitivetypes in total:
typedef NS_ENUM(NSUInteger, MTLPrimitiveType) { MTLPrimitiveTypePoint = 0, MTLPrimitiveTypeLine = 1, MTLPrimitiveTypeLineStrip = 2, MTLPrimitiveTypeTriangle = 3, MTLPrimitiveTypeTriangleStrip = 4, } NS_ENUM_AVAILABLE(10_11, 8_0);
First, the definition of Vertex supporting color is given in Objective-C:
typedef struct { vector_float4 position; vector_float4 color; } Vertex;
The cache allocation of the points to be drawn is given in the PointRenderer class:
//buffer definition @property (nonatomic, strong) id<MTLBuffer> pointVertexBuffer; //buffer setup - (void)buildResources { static const Vertex pointVertices[] = { { .position = { -0.5, -0.5, 0, 1 }, .color = { 1, 0, 0, 1 } }, { .position = { -0.5, 0.5, 0, 1 }, .color = { 0, 1, 0, 1 } }, { .position = { 0.5, -0.5, 0, 1 }, .color = { 0, 0, 1, 1 } }, { .position = { 0.5, 0.5, 0, 1 }, .color = { 0, 1, 0, 1 } } }; _pointVertexBuffer = [_metalContext.device newBufferWithBytes:pointVertices length:sizeof(pointVertices) options:MTLResourceOptionCPUCacheModeDefault]; }
Finally, in the draw function, call the drawPrimitives function to draw MTLPrimitiveTypePoint.
[commandEncoder drawPrimitives: MTLPrimitiveTypePoint vertexStart: 0 vertexCount: 4];
The size of the control point is carried out in the shader. The following is the code in the shader file of point.metal, which realizes the setting of the size and color of the point:
#include <metal_stdlib> using namespace metal; struct Vertex { float4 position [[position]]; float4 color; }; struct PVertex{ float4 position [[position]]; float4 color; float size[[point_size]]; }; vertex PVertex point_vertex_main(device Vertex *vertices [[buffer(0)]], uint vid [[vertex_id]]) { PVertex outVertex; outVertex.position = vertices[vid].position; outVertex.color = vertices[vid].color; outVertex.size = 30; return outVertex; } fragment float4 point_fragment_main(PVertex inVertex [[stage_in]]) { return inVertex.color; }
The key is that PVertex, a variable passed from vertex main to fragment main, has a declaration built-in variable float size [[point] size], which can be adjusted by modifying the value of size.