프로그래밍 방식으로 생성되는 이미지가 있으며이 이미지를 컴퓨팅 쉐이더에 텍스처로 보내려고합니다. 이 이미지를 생성하는 방법은 각각의 RGBA 구성 요소를 UInt8
값으로 계산하고이를 UInt32
으로 결합하여 이미지의 버퍼에 저장하는 것입니다. 나는 다음과 같은 코드 조각이 작업을 수행 : RGBA32
가 이동하고 UInt32
가치 창출을하는 작은 구조체이다UInt8 구성 요소 유형의 텍스처를 Metal 컴퓨팅 쉐이더에 전달
guard let cgContext = CGContext(data: nil,
width: width,
height: height,
bitsPerComponent: 8,
bytesPerRow: 0,
space: CGColorSpaceCreateDeviceRGB(),
bitmapInfo: RGBA32.bitmapInfo) else {
print("Unable to create CGContext")
return
}
guard let buffer = cgContext.data else {
print("Unable to create textures")
return
}
let pixelBuffer = buffer.bindMemory(to: RGBA32.self, capacity: width * height)
let heightFloat = Float(height)
let widthFloat = Float(width)
for i in 0 ..< height {
let latitude = Float(i + 1)/heightFloat
for j in 0 ..< width {
let longitude = Float(j + 1)/widthFloat
let x = UInt8(((sin(longitude * Float.pi * 2) * cos(latitude * Float.pi) + 1)/2) * 255)
let y = UInt8(((sin(longitude * Float.pi * 2) * sin(latitude * Float.pi) + 1)/2) * 255)
let z = UInt8(((cos(latitude * Float.pi) + 1)/2) * 255)
let offset = width * i + j
pixelBuffer[offset] = RGBA32(red: x, green: y, blue: z, alpha: 255)
}
}
let coordinateConversionImage = cgContext.makeImage()
. 이 이미지는 UIImage
으로 변환하여 내 사진 라이브러리에 저장할 수 있으므로 문제가 없습니다.
이 이미지를 컴퓨팅 쉐이더에 텍스처로 보내려고 할 때 문제가 발생합니다. 다음은 내 쉐이더 코드 :
kernel void updateEnvironmentMap(texture2d<uint, access::read> currentFrameTexture [[texture(0)]],
texture2d<uint, access::read> coordinateConversionTexture [[texture(1)]],
texture2d<uint, access::write> environmentMap [[texture(2)]]
uint2 gid [[thread_position_in_grid]])
{
const uint4 pixel = {255, 127, 63, 255};
environmentMap.write(pixel, gid);
}
이 코드의 문제는 내 텍스처의 종류가 32 비트 인 uint
이고, 나는 32 비트 픽셀에게 난에서와 동일한 방식으로 생성 할 것입니다 CPU, 4 개의 8 비트 값 추가. 그러나, 내가 함께 추가 할 수있는 byte
유형이 없으므로 uint32
을 만들었 기 때문에 Metal에서는 그렇게 할 수 없습니다. 그래서 제 질문은, 2D 텍스처를 처리하고 금속 계산 쉐이더에서 32 비트 픽셀을 설정하는 올바른 방법은 무엇입니까?
보너스 질문 : 입력 텍스처 유형으로 texture2d<float, access::read>
인 예제 쉐이더 코드를 보았습니다. 나는 그것이 0.0과 1.0 사이의 값을 나타내는 것으로 가정하고 있지만, 0과 255 사이의 값을 가진 unsigned int에는 어떤 장점이 있습니까?
편집 : 셰이더의 출력 텍스처 environmentMap
은 입력 텍스처와 동일한 속성 (너비, 높이, pixelFormat 등)을 가지고 있습니다. 이것이 반 직관적이라고 생각하는 이유는 uint4
을 픽셀로 설정한다는 것입니다. 즉, 4 개의 32 비트 값으로 구성되는 반면, 각 픽셀은 32 비트이어야합니다. 이 현재 코드에서 {255, 127, 63, 255}
은 {2550, 127, 63, 255}
과 정확히 동일한 결과를 가지므로 출력 텍스쳐에 쓰여지기 전에 어떻게 든 값이 0-255 사이에 고정됩니다. 그러나 이것은 극도로 반 직관적입니다.
워렌 덕분에 많은 일이 해결되었습니다. 또한, 이것에 대해 더 많은 정보를 원한다면 Metal Shading Language Specification의 Chapter 7.7 Texture Addressing and Conversion Rules를 참고하십시오. – halileohalilei