MetalDeferredLighting/AAPLUtilities.h

/*
 Copyright (C) 2014 Apple Inc. All Rights Reserved.
 See LICENSE.txt for this sample’s licensing information
 
 Abstract:
 
      Utilities for AAPLDeferredLighting
      
 */
 
#ifndef __AAPL_UTILITIES_H__
#define __AAPL_UTILITIES_H__
 
#import <simd/simd.h>
 
using namespace simd;
 
struct ImageInfo
{
    uint     width;
    uint     height;
    uint     bitsPerPixel;
    bool     hasAlpha;
    void     *bitmapData;
};
 
// Pipeline Error Handling ******************************************************************
static void CheckPipelineError(id<MTLRenderPipelineState> pipeline, NSError *error)
{
    if (pipeline == nil)
    {
        NSLog(@"Failed to create pipeline. error is %@", [error description]);
        assert(0);
    }
}
 
//Shader Loading ***************************************************************
static id<MTLFunction> _newFunctionFromLibrary(id<MTLLibrary> library, NSString *name)
{
    id<MTLFunction> func = [library newFunctionWithName: name];
    if (!func)
    {
        NSLog(@"failed to find function %@ in the library", name);
        assert(0);
    }
    return func;
}
/////////////////////////////////////////////////////
// Misc Utitility functions
namespace Utilities
{
    const float PI = 3.14159265359f;
    
    float DegreesToRadians(float degree)
    {
        return (degree * PI / 180.0f);
    }
    
    const float inscribe = 0.755761314076171f;    // sqrtf(3.0) / 12.0 * (3.0 + sqrtf(5.0))
    const float circumscribe = 0.951056516295154; // 0.25 * sqrtf(10.0 + 2.0 * sqrtf(5.0))
    
    static float randomFloat(float min, float max)
    {
        double mix = (double)random() / RAND_MAX;
        return min + (max - min) * mix;
    }
    
    static float4 randomColor(void)
    {
        float4 color = {randomFloat(0.0, 1.0), randomFloat(0.0, 1.0), randomFloat(0.0, 1.0), 0.0f};
        
        return normalize(color);
    }
}
/////////////////////////////////////////////////////////
// Texture loading and conversion
static void RGB8ImageToRGBA8(ImageInfo *tex_info)
{
    
    assert(tex_info != NULL);
    assert(tex_info->bitsPerPixel == 24);
    
    NSUInteger stride = tex_info->width * 4;
    void *newPixels = malloc(stride * tex_info->height);
    
    uint32_t *dstPixel = static_cast<uint32_t *>(newPixels);
    uint8_t r, g, b, a;
    a = 255;
    
    NSUInteger sourceStride = tex_info->width * tex_info->bitsPerPixel / 8;
    
    for (int j = 0; j < tex_info->height; j++)
    {
        for (int i = 0; i < sourceStride; i += 3)
        {
            uint8_t *srcPixel = (uint8_t *)(tex_info->bitmapData) + i + (sourceStride * j);
            r = *srcPixel;
            srcPixel++;
            g = *srcPixel;
            srcPixel++;
            b = *srcPixel;
            srcPixel++;
            
            *dstPixel = (static_cast<uint32_t>(a) << 24 | static_cast<uint32_t>(b) << 16 | static_cast<uint32_t>(g) << 8 | static_cast<uint32_t>(r));
            dstPixel++;
            
        }
    }
    
    free(tex_info->bitmapData);
    tex_info->bitmapData = static_cast<unsigned char *>(newPixels);
    tex_info->hasAlpha = true;
    tex_info->bitsPerPixel = 32;
}
 
static void CreateImageInfo(const char *name, ImageInfo &tex_info)
{
    tex_info.bitmapData = NULL;
    
    UIImage* baseImage = [UIImage imageWithContentsOfFile: [NSString stringWithUTF8String: name]];
    CGImageRef image = baseImage.CGImage;
    
    if (!image)
    {
        return;
    }
    
    tex_info.width = (uint)CGImageGetWidth(image);
    tex_info.height = (uint)CGImageGetHeight(image);
    tex_info.bitsPerPixel = (uint)CGImageGetBitsPerPixel(image);
    tex_info.hasAlpha = CGImageGetAlphaInfo(image) != kCGImageAlphaNone;
    uint sizeInBytes = tex_info.width * tex_info.height * tex_info.bitsPerPixel / 8;
    uint bytesPerRow = tex_info.width * tex_info.bitsPerPixel / 8;
    
    tex_info.bitmapData = malloc(sizeInBytes);
    CGContextRef context = CGBitmapContextCreate(tex_info.bitmapData, tex_info.width, tex_info.height, 8, bytesPerRow, CGImageGetColorSpace(image), CGImageGetBitmapInfo(image));
    
    CGContextDrawImage(context, CGRectMake(0, 0, tex_info.width, tex_info.height), image);
    
    CGContextRelease(context);
    
}
 
#endif