【发布时间】:2019-10-12 00:16:25
【问题描述】:
我正在使用此调用从缓冲区渲染点片段:
renderEncoder.drawPrimitives(type: .point,
vertexStart: 0,
vertexCount: 1,
instanceCount: emitter.currentParticles)
emitter.currentParticles 是缓冲区中的粒子总数。是否可以以某种方式仅绘制缓冲区的一部分?
我试过这个,但它绘制了缓冲区的前半部分:
renderEncoder.drawPrimitives(type: .point,
vertexStart: emitter.currentParticles / 2,
vertexCount: 1,
instanceCount: emitter.currentParticles / 2)
其实vertexStart似乎没有任何作用。我似乎可以将它设置为任何值,它仍然从 0 开始。
编辑:
管道配置:
private func buildParticlePipelineStates() {
do {
guard let library = Renderer.device.makeDefaultLibrary(),
let function = library.makeFunction(name: "compute") else { return }
// particle update pipeline state
particlesPipelineState = try Renderer.device.makeComputePipelineState(function: function)
// render pipeline state
let vertexFunction = library.makeFunction(name: "vertex_particle")
let fragmentFunction = library.makeFunction(name: "fragment_particle")
let descriptor = MTLRenderPipelineDescriptor()
descriptor.vertexFunction = vertexFunction
descriptor.fragmentFunction = fragmentFunction
descriptor.colorAttachments[0].pixelFormat = renderPixelFormat
descriptor.colorAttachments[0].isBlendingEnabled = true
descriptor.colorAttachments[0].rgbBlendOperation = .add
descriptor.colorAttachments[0].alphaBlendOperation = .add
descriptor.colorAttachments[0].sourceRGBBlendFactor = .sourceAlpha
descriptor.colorAttachments[0].sourceAlphaBlendFactor = .sourceAlpha
descriptor.colorAttachments[0].destinationRGBBlendFactor = .oneMinusSourceAlpha
descriptor.colorAttachments[0].destinationAlphaBlendFactor = .oneMinusSourceAlpha
renderPipelineState = try
Renderer.device.makeRenderPipelineState(descriptor: descriptor)
renderPipelineState = try Renderer.device.makeRenderPipelineState(descriptor: descriptor)
} catch let error {
print(error.localizedDescription)
}
}
顶点着色器:
struct VertexOut {
float4 position [[ position ]];
float point_size [[ point_size ]];
float4 color;
};
vertex VertexOut vertex_particle(constant float2 &size [[buffer(0)]],
device Particle *particles [[buffer(1)]],
constant float2 &emitterPosition [[ buffer(2) ]],
uint instance [[instance_id]])
{
VertexOut out;
float2 position = particles[instance].position + emitterPosition;
out.position.xy = position.xy / size * 2.0 - 1.0;
out.position.z = 0;
out.position.w = 1;
out.point_size = particles[instance].size * particles[instance].scale;
out.color = particles[instance].color;
return out;
}
fragment float4 fragment_particle(VertexOut in [[ stage_in ]],
texture2d<float> particleTexture [[ texture(0) ]],
float2 point [[ point_coord ]]) {
constexpr sampler default_sampler;
float4 color = particleTexture.sample(default_sampler, point);
if ((color.a < 0.01) || (in.color.a < 0.01)) {
discard_fragment();
}
color = float4(in.color.xyz, 0.2 * color.a * in.color.a);
return color;
}
【问题讨论】:
-
您使用实例计数而不是顶点计数来表示要渲染的点数是什么?
-
这就是他们在我使用的 Metal by Tutorials 一书中的示例中设置它的方式。那么,我应该将 instaceCount 设置为 1,并将 vertexCount 设置为要渲染的粒子数吗?要么?是否可以绘制缓冲区的范围?
-
实例化是一种特殊的、有点先进的技术。如果你不熟悉它,你可能还不应该使用它。所以,是的,您通常应该使用 vertexCount 作为要渲染的粒子数。您可以将 instanceCount 指定为 1 或仅使用不带 instanceCount 参数的方法。综上所述,是否使用实例化对顶点描述符(如果您正在使用它)和顶点着色器都有影响。这些可能需要调整,但我不能告诉你如何调整,因为你没有展示它们。
-
看来它必须设置为使用实例化,因为我尝试按照您的建议进行更改,但它不起作用。如果更多代码会有所帮助,请告诉我您想看到什么。知道为什么 vertexStart 似乎没有效果吗?
-
显示你是如何配置管道描述符的,特别是它的顶点描述符,如果你正在使用它。另外,显示顶点着色器。
标签: ios rendering metal mtlbuffer