티스토리 뷰

iOS/Metal

Metal: Texturing and Sampling

0zerohyun 2022. 1. 7. 16:34

Texture 매핑

var depthTexture: MTLTexture! = nil
let depthTextureDescriptor =
    MTLTextureDescriptor.texture2DDescriptor(
        pixelFormat: .depth32Float,
        width: Int(layerSize.width),
        height: Int(layerSize.height),
        mipmapped: false)
depthTexture = device.makeTexture(descriptor: depthTextureDescriptor)

Texel : Texture의 조각

 

 

Mipmapping

MTLBitCommandEncoder

func generateMipmaps(for texture: MTLTexture)

 

Sampling

Sampler : 좌표계, addressing mode, filtering 등 reading texture와 관련된 렌더 상태를 캡슐화한 객체

Address Modes

음의 좌표를 갖고 있거나 texture의 측정값이 1을 넘을 때 등의 상황에 사용

MTLSamplerAddressMode

  • clampToEdge
  • mirrorClampToEdge
  • repeat
  • mirrorRepeat
  • clampToZero
  • clampToBorderColor

Filters Modes

linear

nearest

 

Anisotropy

 

 

Sampler States

MTLSamplerState

var diffuseTexture: MTLTexture! = nil
var samplerState: MTLSamplerState! = nil

let samplerDescriptor = MTLSamplerDescriptor()
samplerDescriptor.minFilter = .nearest
samplerDescriptor.magFilter = .linear
samplerState = device.makeSamplerState(descriptor: samplerDescriptor)

commandEncoder.setFragmentTexture(diffuseTexture, at: 0)
commandEncoder.setFragmentSamplerState(samplerState, at: 0)

※ GPU를 사용하지 않고 Shader function안에서 sampler를 만들 수도 있다.

 

 

Texture와 Sampler를 Graphic Function에 전달

Texture 생성

func textureForImage(_ image:UIImage, device:MTLDevice) -> MTLTexture? {
    let imageRef = image.cgImage!

    let width = imageRef.width
    let height = imageRef.height
    let colorSpace = CGColorSpaceCreateDeviceRGB()

    let rawData = calloc(height * width * 4,
        MemoryLayout<UInt8>.size)

    let bytesPerPixel = 4
    let bytesPerRow = bytesPerPixel * width
    let bitsPerComponent = 8

    // Core Graphics
    let options = CGImageAlphaInfo.premultipliedLast.rawValue |
        CGBitmapInfo.byteOrder32Big.rawValue

    let context = CGContext(data: rawData,
                            width: width,
                            height: height,
                            bitsPerComponent: bitsPerComponent,
                            bytesPerRow: bytesPerRow,
                            space: colorSpace,
                            bitmapInfo: options)

    context?.draw(imageRef, in: CGRect(x: 0,
        y: 0,
        width: CGFloat(width),
        height: CGFloat(height)))

    // MTLTextureDescriptor
    let textureDescriptor =
    MTLTextureDescriptor.texture2DDescriptor(
        pixelFormat: .rgba8Unorm,
        width: Int(width),
        height: Int(height),
        mipmapped: true)
    let texture = device.makeTexture(descriptor: textureDescriptor)

    let region = MTLRegionMake2D(0, 0, Int(width), Int(height))

    texture.replace(region: region,
                    mipmapLevel: 0,
                    slice: 0,
                    withBytes: rawData!,
                    bytesPerRow: bytesPerRow,
                    bytesPerImage: bytesPerRow * height)

    free(rawData)

    return texture
}

diffuseTexture = self.textureForImage(UIImage(named: "bluemarble")!, device: device)

 

Metal Texture Functions

struct TexturedInVertex
{
    packed_float4 position [[attribute(0)]];
    packed_float4 normal [[attribute(1)]];
    packed_float2 texCoords [[attribute(2)]];
};

struct TexturedColoredOutVertex
{
    float4 position [[position]];
    float3 normal;
    float2 texCoords;
};

struct Uniforms
{
    float4x4 projectionMatrix;
    float4x4 modelViewMatrix;
};

 

vertex TexturedColoredOutVertex vertex_sampler(
    device TexturedInVertex *vert [[buffer(0)]],
    constant Uniforms &uniforms [[buffer(1)]],
    uint vid [[vertex_id]])
{
    float4x4 MV = uniforms.modelViewMatrix;
    float3x3 normalMatrix(MV[0].xyz, MV[1].xyz, MV[2].xyz);
    float4 modelNormal = vert[vid].normal;
    
    TexturedColoredOutVertex outVertex;
    outVertex.position = uniforms.projectionMatrix *
        uniforms.modelViewMatrix * float4(vert[vid].position);
    outVertex.normal = normalMatrix * modelNormal.xyz;
    outVertex.texCoords = vert[vid].texCoords;
    
    return outVertex;
}

fragment half4 fragment_sampler(
    TexturedColoredOutVertex vert  [[stage_in]],
    texture2d<float, access::sample> diffuseTexture [[texture(0)]],
    sampler samplr [[sampler(0)]])
{
    float4 diffuseColor = diffuseTexture.sample(samplr, vert.texCoords);
    return half4(diffuseColor.r, diffuseColor.g, diffuseColor.b, 1);
}

'iOS > Metal' 카테고리의 다른 글

Metal 좌표계  (0) 2022.01.26
Metal: Metal Resources  (0) 2022.01.07
Metal: MetalKit  (0) 2022.01.07
Metal: Shader  (0) 2022.01.07
Metal: MTLTexture to CIImage 변경 시 rgb값 그대로 가져오기  (0) 2022.01.06
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함