微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

金属碎片着色器-如何根据可通过绘图功能调整的均匀度为每个像素分配颜色?

如何解决金属碎片着色器-如何根据可通过绘图功能调整的均匀度为每个像素分配颜色?

我有一个MTKView,它正在渲染一个具有一定大小的多维数据集,以便它的一个面可以填满整个屏幕。

我正在将包含随机Float的结构变量(称为统一变量)传递给片段着色器,我想根据float的值为屏幕上的每个像素着色不同的颜色。

现在,它会根据Float的值将整个四边形变成红色或蓝色,这在绘制函数中是随机的。

我认为我的设置是错误的,因为在任何一帧我都只能访问一个随机浮点数,并且在该帧期间所有像素都将被上色(我将没有一组随机浮点数来确定像素颜色)。但是,我认为我可以简单地向struct变量中添加更多变量来克服此问题。

主要问题是通过片段功能访问单个像素...如果它甚至性能足以确定屏幕上每个像素的颜色。

import UIKit
import MetalKit

class ViewController: UIViewController,MTKViewDelegate {
     
     var Metaldevice: MTLDevice!
     var Metalview: MTKView!
     var Metallibrary: MTLLibrary!
     var Metalqueue: MTLCommandQueue!
     var Metalpipelinestate: MTLRenderPipelinestate!
     var Metalmesh: MTKMesh!
     
     var theuniforms = Uniforms(color: 1)
     
     struct Uniforms {
          var color = Float(1)
     }
     
     override var prefeRSStatusBarHidden: Bool { return true }
     override var prefersHomeIndicatorAutoHidden: Bool { return true }
     override func viewDidLoad() {
          super.viewDidLoad()

          self.view.backgroundColor = .black
          
          self.Metaldevice = MTLCreateSystemDefaultDevice()
          self.Metalview = MTKView()
          self.Metalview.frame = UIScreen.main.bounds
          self.Metalview.clearColor = MTLClearColor(red: 0,green: 0,blue: 0,alpha: 1)
          self.Metalview.delegate = self
          self.Metalview.device = self.Metaldevice
          self.view.addSubview(self.Metalview)
          
          self.Metallibrary = self.Metaldevice.makeDefaultLibrary()
          self.Metalqueue = self.Metaldevice.makeCommandQueue()
          self.Metalmesh = self.returncube()
          
          let vfunc = self.Metallibrary.makeFunction(name: "vertex_main")
          let ffunc = self.Metallibrary.makeFunction(name: "fragment_main")
          let descriptor = MTLRenderPipelineDescriptor()
          descriptor.colorAttachments[0].pixelFormat = .bgra8Unorm
          descriptor.vertexFunction = vfunc
          descriptor.fragmentFunction = ffunc
          descriptor.vertexDescriptor = MTKMetalVertexDescriptorFromModelIO(self.Metalmesh.vertexDescriptor)
          
          self.Metalpipelinestate = try! self.Metaldevice.makeRenderPipelinestate(descriptor: descriptor)
          

     }


     func returncube() -> MTKMesh {
          let allocator = MTKMeshBufferAllocator(device: self.Metaldevice)
          let model = MDLMesh(BoxWithExtent: [2,2,2],segments: [1,1,1],inwardnormals: false,geometryType: .triangles,allocator: allocator)
          let mesh = try! MTKMesh(mesh: model,device: self.Metaldevice)
          return mesh
     }
     
     func draw(in view: MTKView) {
          let descriptor = self.Metalview.currentRenderPassDescriptor
          let buffer = self.Metalqueue.makeCommandBuffer()
          let encoder = buffer?.makeRenderCommandEncoder(descriptor: descriptor!)
          encoder?.setRenderPipelinestate(self.Metalpipelinestate)
          
          self.theuniforms.color = Float.random(in: 1.0...2.0)
          
          encoder?.setVertexBytes(&theuniforms,length: MemoryLayout<Uniforms>.stride,index: 1)
          encoder?.setVertexBuffer(self.Metalmesh.vertexBuffers[0].buffer,offset: 0,index: 0)
          for mesh in self.Metalmesh.submeshes {
               encoder?.drawIndexedPrimitives(type: .triangle,indexCount: mesh.indexCount,indexType: mesh.indexType,indexBuffer: mesh.indexBuffer.buffer,indexBufferOffset: mesh.indexBuffer.offset)
          }
          
          encoder?.endEncoding()
          let drawable = self.Metalview.currentDrawable
          buffer?.present(drawable!)
          buffer?.commit()
          
     }
     
     func mtkView(_ view: MTKView,drawableSizeWillChange size: CGSize) {
          
     }
}


这是着色器代码

#include <Metal_stdlib>
using namespace Metal;
#include <simd/simd.h>

struct VertexIn {
     float4 position [[attribute(0)]];
};

struct Uniforms {
     float color;
};

struct VertexOut {
     float4 position [[position]];
     Uniforms uniforms;
};

vertex VertexOut vertex_main(const VertexIn in [[stage_in]],constant Uniforms &uniforms [[buffer(1)]]
                          )
{
     VertexOut out;
     out.position = in.position;
     out.uniforms = uniforms;
     return out;
}

fragment float4 fragment_main( VertexOut in [[stage_in]])
{
     
     float4 color;
     
     if (in.uniforms.color > 1.5){ color = float4(1,1); }
     else { color = float4(0,1); }
     return color;
}

解决方法

首先,您不应该使用制服来更改使CPU过载的每个像素的颜色,但这是GPU任务,因此您应该在着色器内部使用某些功能。而且,如果您希望制服相应地更改片段的颜色,则必须将其传递到片段函数Sub Test4() Dim rowDB As Long Dim wsDB As Worksheet Set wsDB = ActiveSheet rowDB = WorksheetFunction.Match("30.06.2020",wsDB.Range("C7:C366")) Debug.Print rowDB End Sub 中,并在片段函数中调用它。如果我说对了,您会在立方体上想要类似白噪声的东西,因此这里是着色器:

setFragmentBytes(&theuniforms,length: MemoryLayout<Uniforms>.stride,index: 1)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。