Would it possible to get the example code on wiki updated to show:
* current headers
* macOS Metal instead of OpenGL
? As someone who is struggling to get the Metal renderer to work, having a good example to work off of would be extremely helpful.
Thanks.
* current headers
* macOS Metal instead of OpenGL
? As someone who is struggling to get the Metal renderer to work, having a good example to work off of would be extremely helpful.
Thanks.
Inviato yesterday @ 9:49 pm
Here is the reference:
VdjVideoEngineMetal = 5
Inviato 19 hours ago
Inside OnDraw, the device is a MTLRenderCommandEncoder:
The texture you can get from vdj is a MTLTexture
To draw something, you'd also need some shaders. For just putting some texture on the screen, you could use vdj's however.
This is how the NDI plugin currently does it:
id<MTLRenderCommandEncoder> commandEncoder;
void *commandEncoderPtr = nullptr;
if (GetDevice(VdjVideoEngineMetal, (void**)&commandEncoderPtr)!=S_OK)
return S_FALSE;
commandEncoder = (__bridge id<MTLRenderCommandEncoder>)(commandEncoderPtr);
The texture you can get from vdj is a MTLTexture
id<MTLTexture> texture;
void *texturePtr = nullptr;
TVertex* vertices = nullptr;
if (GetTexture(VdjVideoEngineMetal, (void**)&texturePtr, &vertices)!=S_OK)
return S_FALSE;
texture = (__bridge id<MTLTexture>)(texturePtr);
To draw something, you'd also need some shaders. For just putting some texture on the screen, you could use vdj's however.
This is how the NDI plugin currently does it:
struct VIn_Texture
{
simd_float2 position;
simd_float2 texCoord;
simd_float4 color;
};
void CReceiveNDI::bitblt(void *texture)
{
float alpha = 1.f;
int srcX=0, srcY=0, srcWidth=curTextureW, srcHeight=curTextureH, dstX=0, dstY=0, dstWidth=width, dstHeight=height;
initImageSize(&srcX, &srcY, &srcWidth, &srcHeight, curTextureAR, 0, width, height, &dstX, &dstY, &dstWidth, &dstHeight);
if (!texture)
return;
if (width<=0 || height<=0 || srcWidth<=0 || srcHeight<=0)
return;
id<MTLTexture> localTexture = (__bridge id<MTLTexture>)texture;
VIn_Texture v[4];
v[0].color = {1.f, 1.f, 1.f, alpha};
v[0].texCoord = {srcX/(float)[localTexture width], srcY/(float)[localTexture height]};
v[0].position = {(float)dstX, (float)dstY};
v[1].color = v[0].color;
v[1].texCoord = {(srcX+srcWidth) / (float)[localTexture width], srcY / (float)[localTexture height]};
v[1].position = {(float)(dstX+dstWidth), (float)dstY};
v[3].color = v[0].color;
v[3].texCoord = {(srcX+srcWidth) / (float)[localTexture width], (srcY+srcHeight) / (float)[localTexture height]};
v[3].position = {(float)(dstX+dstWidth), (float)(dstY+dstHeight)};
v[2].color = v[0].color;
v[2].texCoord = {srcX / (float)[localTexture width], (srcY+srcHeight) / (float)[localTexture height]};
v[2].position = {(float)dstX, (float)(dstY+dstHeight)};
id<MTLRenderCommandEncoder> commandEncoder;
void *commandEncoderPtr = nullptr;
if (GetDevice(VdjVideoEngineMetal, (void**)&commandEncoderPtr)!=S_OK)
return;
commandEncoder = (__bridge id<MTLRenderCommandEncoder>)(commandEncoderPtr);
if (!pipelineTexture)
{
MTLRenderPipelineDescriptor *pipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
if (!shadersLib)
{
//Note: this currently uses the shaders from vdj
//it would be better to use your own shaders and include them in the plugin
id<MTLLibrary> newShadersLib = [[commandEncoder device] newDefaultLibrary];
if (!newShadersLib)
return;
shadersLib = (void*)CFBridgingRetain(newShadersLib);
}
pipelineDescriptor.label = @"Texture Pipeline";
pipelineDescriptor.vertexFunction = [(__bridge id<MTLLibrary>)shadersLib newFunctionWithName:@"renderVertexTexture"];
pipelineDescriptor.fragmentFunction = [(__bridge id<MTLLibrary>)shadersLib newFunctionWithName:@"renderFragmentTexture"];
pipelineDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
pipelineDescriptor.colorAttachments[0].blendingEnabled = YES;
pipelineDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
pipelineDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;
pipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;
pipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorSourceAlpha;
pipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
pipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
pipelineDescriptor.depthAttachmentPixelFormat = MTLPixelFormatInvalid;
NSError *error = nil;
id<MTLRenderPipelineState> newPipelineTexture = [[commandEncoder device] newRenderPipelineStateWithDescriptor:pipelineDescriptor error:&error];
if (!newPipelineTexture)
return;
pipelineTexture = (void*)CFBridgingRetain(newPipelineTexture);
}
id<MTLRenderPipelineState> localPipelineTexture = (__bridge id<MTLRenderPipelineState>)pipelineTexture;
static constexpr int nbVertices = 4;
[commandEncoder setVertexBytes:v length:nbVertices*sizeof(VIn_Texture) atIndex:0];
[commandEncoder setFrontFacingWinding:MTLWindingClockwise];
[commandEncoder setCullMode:MTLCullModeNone];
[commandEncoder setRenderPipelineState:localPipelineTexture];
[commandEncoder setFragmentTexture:localTexture atIndex:0];
[commandEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:nbVertices];
}
Inviato 18 hours ago