Swift+Metal Emitter로

8181 단어 SwiftMetaliOS

Swift+Metal Emitter로


스위프트+메탈의 발사체(입자 발생기) 샘플입니다.
어떤 GN 드라이버입니다.
화염과 연기도 같은 구조로 재현할 수 있다.
완성형↓

표현 기교


1. α 블렌드를 활성화합니다.
2. depth stencil에 쓰기를 금지합니다.
3. 메탈의 포인트를 사용하여 그립니다.

코드


1. 알파 블렌드


반투명(투명)을 활성화하려면 α 블렌드를 활성화합니다.
결과 색상 = source BlendFactor* 드로잉 색상(BlendOperation) d e stination 알파 BlendFactor* 원래 색상
이번에는 간단한 덧셈 합성으로 설정했다.
MetalEzRender.swift
        renderPipelineDescriptor.colorAttachments[0].isBlendingEnabled = true
        renderPipelineDescriptor.colorAttachments[0].rgbBlendOperation = .add
        renderPipelineDescriptor.colorAttachments[0].alphaBlendOperation = .add
        renderPipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = .one
        renderPipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = .one
        renderPipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = .one
        renderPipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = .one

2. depth stencil에 쓰기를 금지합니다.


일반적으로 depth stencil에 기록됩니다.
그러나 효과를 표시할 때는 쓰기를 금지하는 것이 좋다.
쓰기와 금지의 결과는 다음과 같다.
기록된 경우↓

쓰기 금지상태↓

쓰기를 하면 뒤에 있는 객체가 표시되지 않으므로 투명해도 뒤에 그려지지 않습니다.
그러나 depth stencil은 깊이 정보를 쓰지 않기 때문에 멀리서 그려야 합니다.
MetalEz.swift
        //depth stencilに書き込むとき
        let depthDescriptor = MTLDepthStencilDescriptor()
        depthDescriptor.depthCompareFunction = .less
        depthDescriptor.isDepthWriteEnabled = true
        depthStencilState = device.makeDepthStencilState(descriptor: depthDescriptor)

        //depth stencilに書き込まないとき
        let depthDescriptorForBlending = MTLDepthStencilDescriptor()
        depthDescriptorForBlending.depthCompareFunction = .less
        depthDescriptorForBlending.isDepthWriteEnabled = false
        depthStencilStateForBlending = device.makeDepthStencilState(descriptor: depthDescriptorForBlending)

3. 메탈의 포인트를 사용하여 그립니다.


OpenGL의 경우 정사각형을 그리려면 두 개의 삼각형이 필요하며, 메탈은 포인트로 정사각형을 그릴 수 있다.
데이터를 삭감할 수 있다.
MetalEzRender.swift
    func draw(vaertex: MTLBuffer, frameUniformBuffer: MTLBuffer, texure: MTLTexture, count: Int) {
        mtlEz.mtlRenderCommandEncoder.setVertexBuffer(vaertex, offset: 0, index: 0)
        mtlEz.mtlRenderCommandEncoder.setVertexBuffer(frameUniformBuffer, offset: 0, index: 1)
        mtlEz.mtlRenderCommandEncoder.setFragmentTexture(texure, index: 0)
        mtlEz.mtlRenderCommandEncoder.drawPrimitives(type: .point, vertexStart: 0, vertexCount: count, instanceCount: 1)
    }

좋은 웹페이지 즐겨찾기