2016-09-05 7 views
1

마우스를 사용하여 카메라 위치를 제어하려면 compute function으로 계산합니다.Shaders.metal은 마우스의 y 값만 가져옵니다.

import MetalKit 

public class MetalView: MTKView, NSWindowDelegate { 

    var queue: MTLCommandQueue! = nil 
    var cps: MTLComputePipelineState! = nil 

    var timer: Float = 0 
    var timerBuffer: MTLBuffer! 

    var mouseBuffer: MTLBuffer! 
    var pos: NSPoint! 

    required public init(coder: NSCoder) { 
     super.init(coder: coder) 
     self.framebufferOnly = false 
     device = MTLCreateSystemDefaultDevice() 
     registerShaders() 
    } 


    override public func drawRect(dirtyRect: NSRect) { 
     super.drawRect(dirtyRect) 
     if let drawable = currentDrawable { 
      let command_buffer = queue.commandBuffer() 
      let command_encoder = command_buffer.computeCommandEncoder() 
      command_encoder.setComputePipelineState(cps) 
      command_encoder.setTexture(drawable.texture, atIndex: 0) 
      command_encoder.setBuffer(timerBuffer, offset: 0, atIndex: 1) 
      command_encoder.setBuffer(mouseBuffer, offset: 0, atIndex: 2) 
      update() 
      let threadGroupCount = MTLSizeMake(8, 8, 1) 
      let threadGroups = MTLSizeMake(drawable.texture.width/threadGroupCount.width, drawable.texture.height/threadGroupCount.height, 1) 
      command_encoder.dispatchThreadgroups(threadGroups, threadsPerThreadgroup: threadGroupCount) 
      command_encoder.endEncoding() 
      command_buffer.presentDrawable(drawable) 
      command_buffer.commit() 
     } 
    } 

    func registerShaders() { 
     queue = device!.newCommandQueue() 
     do { 
      let library = device!.newDefaultLibrary()! 
      let kernel = library.newFunctionWithName("compute")! 
      timerBuffer = device!.newBufferWithLength(sizeof(Float), options: []) 
      mouseBuffer = device!.newBufferWithLength(sizeof(NSPoint), options: []) 
      cps = try device!.newComputePipelineStateWithFunction(kernel) 
     } catch let e { 
      Swift.print("\(e)") 
     } 
    } 

    func update() { 
     timer += 0.01 
     var bufferPointer = timerBuffer.contents() 
     memcpy(bufferPointer, &timer, sizeof(Float)) 
     bufferPointer = mouseBuffer.contents() 
     memcpy(bufferPointer, &pos, sizeof(NSPoint)) 
    } 

    override public func mouseDragged(event: NSEvent) { 
     pos = convertPointToLayer(convertPoint(event.locationInWindow, fromView: nil)) 
     let scale = layer!.contentsScale 
     pos.x *= scale 
     pos.y *= scale 
     debugPrint("Hello",pos.x,pos.y) 
    } 
} 

내 쉐이더 코드 :

kernel void compute(texture2d<float, access::write> output [[texture(0)]], 
        constant float &timer [[buffer(1)]], 
        constant float2 &mouse [[buffer(2)]], 
        uint2 gid [[thread_position_in_grid]]) 
{ 
    int width = output.get_width(); 
    int height = output.get_height(); 
    float2 uv = float2(gid)/float2(width, height); 
    uv = uv * 2.0 - 1.0; 
    // scale proportionately. 
    if(width > height) uv.x *= float(width)/float(height); 
    if(width < height) uv.y *= float(height)/float(width); 


    float2 mpos = mouse * 2.0 - 1.0; 

    float3 cameraPosition = float3(mpos.x,mpos.y, -10.0);///<-- mouse position to set camera position 

... 

} 

어쨌든 나는 단지 mpos.y 가치를 내 view 코드입니다. mpos.xcompute 기능으로 전송되지 않는 것 같습니다. 이 문제를 어떻게 해결할 수 있습니까?

+0

쉐이더에 mpos.x 값이 없다는 증거를 더 많이 제공 할 수 있습니까? – Marius

+0

나는'float3 (mpos.x, 0.0, -10.0)'과'float3 (0.0, mpos.x, -10.0)'과 같이'float3 cameraPosition = float3 (mpos.x, mpos.y, -10.0))''mpos.x'가 작동 하는지를보기 위해서입니다. – sooon

답변

1

NSPoint의 필드는 CGFloat입니다. 문제는 64 비트의 경우 CGFloatDouble이 아니라 Float으로 정의되어 있다고 생각합니다. 금속의 float은 스위프트의 Float에 해당하며 Double이 아닙니다. 아마도 float2은 2 개의 Swift Float에 해당합니다. 버퍼 레이아웃이 잘못되었습니다. 두 FloatNSPoint이 아닌 mouseBuffer으로 복사하십시오.

+0

'nspoint'를'float2'로 변환하는 법? – sooon

+0

'nspoint'를'float2'로 변환하는 방법을 모르겠습니다. 그래서 대신 2 개의 float을 사용하여 2 개의 마우스 버퍼 (x와 y)에 넣습니다. 그런 다음 작동합니다. – sooon