swift – 在顶点着色器之前将计算/内核函数应用于顶点缓冲区
发布时间:2020-12-14 04:55:13 所属栏目:百科 来源:网络整理
导读:我想使用计算着色器来修改我的顶点,然后将它们传递给顶点着色器.我找不到任何这样的例子或解释,除了它似乎在这里提到: Metal emulate geometry shaders using compute shaders.这对我没有帮助,因为它没有解释它的CPU部分. 我已经看过许多在计算着色器中读取
我想使用计算着色器来修改我的顶点,然后将它们传递给顶点着色器.我找不到任何这样的例子或解释,除了它似乎在这里提到:
Metal emulate geometry shaders using compute shaders.这对我没有帮助,因为它没有解释它的CPU部分.
我已经看过许多在计算着色器中读取和写入纹理缓冲区的示例,但我需要读取和修改顶点缓冲区,其中包含带法线的自定义顶点结构,并由MDLMesh创建.我将永远感谢一些示例代码! 背景 我真正想要实现的是能够修改GPU上的顶点法线.另一种选择是,如果我可以从顶点着色器访问整个三角形,就像在链接的答案中一样.出于某种原因,我只能使用stage_in属性访问单个顶点.在这种特殊情况下,使用整个缓冲区对我来说不起作用,这可能与使用Model I / O和MDLMesh提供的网格有关.当我手动创建顶点时,我能够访问顶点缓冲区数组.话虽如此,使用该解决方案,我将不得不为每个三角形计算新的顶点法线向量三次,这似乎是浪费,并且无论如何我希望能够将计算着色器应用于顶点缓冲区! 解决方法
感谢Ken Thomases的评论,我设法找到了解决方案.他让我意识到这很简单:
我正在使用如下所示的顶点结构: // Metal side struct Vertex { float4 position; float4 normal; float4 color; }; // Swift side struct Vertex { var position: float4 var normal: float4 var color: float4 } 在我通常创建顶点缓冲区,索引缓冲区和渲染管道状态的设置期间,我现在还创建一个计算管道状态: // Vertex buffer let dataSize = vertexData.count*MemoryLayout<Vertex>.stride vertexBuffer = device.makeBuffer(bytes: vertexData,length: dataSize,options: [])! // Index buffer indexCount = indices.count let indexSize = indexCount*MemoryLayout<UInt16>.stride indexBuffer = device.makeBuffer(bytes: indices,length: indexSize,options: [])! // Compute pipeline state let adjustmentFunction = library.makeFunction(name: "adjustment_func")! cps = try! device.makeComputePipelineState(function: adjustmentFunction) // Render pipeline state let rpld = MTLRenderPipelineDescriptor() rpld.vertexFunction = library.makeFunction(name: "vertex_func") rpld.fragmentFunction = library.makeFunction(name: "fragment_func") rpld.colorAttachments[0].pixelFormat = .bgra8Unorm rps = try! device.makeRenderPipelineState(descriptor: rpld) commandQueue = device.makeCommandQueue()! 然后我的渲染函数如下所示: let black = MTLClearColor(red: 0,green: 0,blue: 0,alpha: 1) rpd.colorAttachments[0].texture = drawable.texture rpd.colorAttachments[0].clearColor = black rpd.colorAttachments[0].loadAction = .clear let commandBuffer = commandQueue.makeCommandBuffer()! let computeCommandEncoder = commandBuffer.makeComputeCommandEncoder()! computeCommandEncoder.setComputePipelineState(cps) computeCommandEncoder.setBuffer(vertexBuffer,offset: 0,index: 0) computeCommandEncoder.dispatchThreadgroups(MTLSize(width: meshSize*meshSize,height: 1,depth: 1),threadsPerThreadgroup: MTLSize(width: 4,depth: 1)) computeCommandEncoder.endEncoding() let renderCommandEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: rpd)! renderCommandEncoder.setRenderPipelineState(rps) renderCommandEncoder.setFrontFacing(.counterClockwise) renderCommandEncoder.setCullMode(.back) updateUniforms(aspect: Float(size.width/size.height)) renderCommandEncoder.setVertexBuffer(vertexBuffer,index: 0) renderCommandEncoder.setVertexBuffer(uniformBuffer,index: 1) renderCommandEncoder.setFragmentBuffer(uniformBuffer,index: 1) renderCommandEncoder.drawIndexedPrimitives(type: .triangle,indexCount: indexCount,indexType: .uint16,indexBuffer: indexBuffer,indexBufferOffset: 0) renderCommandEncoder.endEncoding() commandBuffer.present(drawable) commandBuffer.commit() 最后我的计算着色器看起来像这样: kernel void adjustment_func(const device Vertex *vertices [[buffer(0)]],uint2 gid [[thread_position_in_grid]]) { vertices[gid.x].position = function(pos.xyz); } 这是我的顶点函数的签名: vertex VertexOut vertex_func(const device Vertex *vertices [[buffer(0)]],uint i [[vertex_id]],constant Uniforms &uniforms [[buffer(1)]]) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |