Search code examples
iosobjective-cmetalmetalkit

how to use MTLSamplerState instead of declaring a sampler in my fragment shader code?


I have the shader below where I define a sampler (constexpr sampler textureSampler (mag_filter::linear,min_filter::linear);).

    using namespace metal;

    struct ProjectedVertex {
      'float4 position [[position]];
      'float2 textureCoord;
    };

    fragment float4 fragmentShader(const ProjectedVertex in [[stage_in]],
                                   const texture2d<float> colorTexture [[texture(0)]],
                                   constant float4 &opacity [[buffer(1)]]){

      constexpr sampler textureSampler (mag_filter::linear,min_filter::linear);
      const float4 colorSample = colorTexture.sample(textureSampler, in.textureCoord);
      return colorSample*opacity[0];

    }

Now I would like to avoid to hardly define this sampler inside my shader code. I found MTLSamplerState But I don't know how to use it


Solution

  • To create a sampler, first create a MTLSamplerDescriptor object and configure the descriptor’s properties. Then call the newSamplerStateWithDescriptor: method on the MTLDevice object that will use this sampler. After you create the sampler, you can release the descriptor or reconfigure its properties to create other samplers.

    // Create default sampler state
    MTLSamplerDescriptor *samplerDesc = [MTLSamplerDescriptor new];
    samplerDesc.rAddressMode = MTLSamplerAddressModeRepeat;
    samplerDesc.sAddressMode = MTLSamplerAddressModeRepeat;
    samplerDesc.tAddressMode = MTLSamplerAddressModeRepeat;
    samplerDesc.minFilter = MTLSamplerMinMagFilterLinear;
    samplerDesc.magFilter = MTLSamplerMinMagFilterLinear;
    samplerDesc.mipFilter = MTLSamplerMipFilterNotMipmapped;
    id<MTLSamplerState> ss = [device newSamplerStateWithDescriptor:samplerDesc];
    

    Sets a sampler state for the fragment function:

        id<MTLRenderCommandEncoder> encoder = [commandBuffer renderCommandEncoderWithDescriptor: passDescriptor];
         ...
        [encoder setFragmentSamplerState: ss atIndex:0];
    

    Accessing from the shader:

    fragment float4 albedoMainFragment(ImageColor in [[stage_in]],
                                    texture2d<float> diffuseTexture [[texture(0)]],
                                    sampler smp [[sampler(0)]]) {
    
        float4 color = diffuseTexture.sample(smp, in.texCoord);
        return color;
    }