2D金属渲染,旋转和长宽比

时间:2018-09-11 13:52:30

标签: metal metalkit

我已经深入学习Metal,对一般的渲染世界知识很少,所以请原谅潜在的新手问题。

我有以下内容:

  1. 用户定义的任意大小的目标纹理。
  2. 从用户提供的图像派生的纹理。
  3. 用户0.0 ... 1.0提供的刻度,平移和旋转

我想在纹理上标记图像。我有90%的人在工作,但我当然会被矩阵绊倒。我正在执行以下操作:

  1. 计算缩放矩阵以使图像纹理以适当的宽高比适合目标纹理。
  2. 调整比例矩阵以考虑到用户提供的其他比例。
  3. 根据用户提供的值计算平移和旋转矩阵。
  4. 应用缩放,旋转和平移矩阵以通过顶点着色器将图章“放置”。
  5. 渲染!

当然,如果目标纹理为正方形,则效果很好,但如果不是,则旋转会导致图像倾斜。我知道为什么会发生这种情况,只是不了解可以解决此问题的适当矩阵,或者如果我做的完全错误。


渲染代码:

let renderPassDescriptor = MTLRenderPassDescriptor()
renderPassDescriptor.colorAttachments[0].texture = drawable.texture
renderPassDescriptor.colorAttachments[0].loadAction = .clear
renderPassDescriptor.colorAttachments[0].clearColor = clearColor
renderPassDescriptor.colorAttachments[0].storeAction = .store

let commandBuffer = commandQueue.makeCommandBuffer()!
let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor)!

let vertices: [AspectVertex] = [
    AspectVertex(position: float2(-1.0,  1.0), texturePosition: float2(0.0, 0.0)),
    AspectVertex(position: float2( 1.0,  1.0), texturePosition: float2(1.0, 0.0)),
    AspectVertex(position: float2(-1.0, -1.0), texturePosition: float2(0.0, 1.0)),
    AspectVertex(position: float2( 1.0, -1.0), texturePosition: float2(1.0, 1.0))
]

let vertexBuffer = metalDevice.makeBuffer(bytes: vertices, length: MemoryLayout<AspectVertex>.size * vertices.count, options: [])!

let availableSize = sceneSize * userScale

let delta = availableSize / imageSize
let factor = delta.min()!

let scaledSize = imageSize * factor
let normalizedSize = scaledSize / sceneSize

var vertexUniform = AspectVertexUniform(
    rotation: float4x4.zRotation(by: Float.pi * rotation),
    scaling: float4x4.scale(by: normalizedSize.x, y: normalizedSize.y, z: 1.0),
)

let vertexUniformBuffer = metalDevice.makeBuffer(bytes: &vertexUniform, length: MemoryLayout<AspectVertexUniform>.size, options: [])!

encoder.setRenderPipelineState(pipelineState)
encoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0)
encoder.setVertexBuffer(vertexUniformBuffer, offset: 0, index: 1)
encoder.setFragmentTexture(texture, index: 0)
encoder.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: 4)

renderEncoder.endEncoding()

commandBuffer.present(drawable)
commandBuffer.commit()

顶点着色器:(目前暂不翻译)

vertex AspectVertexOut aspect_vertex(const device AspectVertexIn* vertices [[ buffer(0) ]],
                                     const device AspectVertexUniform& uniform [[ buffer(1) ]],
                                     unsigned int vid [[ vertex_id ]])
{
    AspectVertexIn vertexIn = vertices[vid];

    AspectVertexOut vertexOut;
    vertexOut.position = uniform.rotationMatrix * uniform.scalingMatrix * float4(vertexIn.position, 0.0, 1.0);
    vertexOut.texturePosition = vertexIn.texturePosition;

    return vertexOut;
}

0 个答案:

没有答案