// -*- coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-

/*
 * Copyright (c) 2025, Awe Morris. All rights reserved.
 */

//
// Apple Metal Shader
//

const char *gameShader =
        "#include <metal_stdlib>                                                                \n"
        "#include <metal_common>                                                                \n"
        "#include <simd/simd.h>                                                                 \n"
        "                                                                                       \n"
        "using namespace metal;                                                                 \n"
        "                                                                                       \n"
        "enum GameVertexInputIndex {                                                            \n"
        "    GameVertexInputIndexVertices = 0,                                                  \n"
        "};                                                                                     \n"
        "                                                                                       \n"
        "enum {                                                                                 \n"
        "    GameTextureIndexColor = 0,                                                         \n"
        "    GameTextureIndexRule = 1,                                                          \n"
        "};                                                                                     \n"
        "                                                                                       \n"
        "struct GameVertex {                                                                    \n"
        "    vector_float2 xy;                                                                  \n"
        "    vector_float2 uv;                                                                  \n"
        "    float alpha;                                                                       \n"
        "    float padding;  // This is absolutely needed for 64-bit alignments                 \n"
        "};                                                                                     \n"
        "                                                                                       \n"
        "// Vertex shader outputs and fragment shader inputs                                    \n"
        "struct RasterizerData {                                                                \n"
        "    float4 position [[position]];                                                      \n"
        "    float2 textureCoordinate;                                                          \n"
        "    float alpha;                                                                       \n"
        "};                                                                                     \n"
        "                                                                                       \n"
        "vertex RasterizerData                                                                  \n"
        "vertexShader(uint vertexID [[vertex_id]],                                              \n"
        "             constant GameVertex *vertexArray [[buffer(GameVertexInputIndexVertices)]])\n"
        "{                                                                                      \n"
        "    RasterizerData out;                                                                \n"
        "    out.position = vector_float4(vertexArray[vertexID].xy, 0, 1);                      \n"
        "    out.textureCoordinate = vertexArray[vertexID].uv;                                  \n"
        "    out.alpha = vertexArray[vertexID].alpha;                                           \n"
        "    return out;                                                                        \n"
        "}                                                                                      \n"
        "                                                                                       \n"
        "fragment float4                                                                        \n"
        "fragmentNormalShader(RasterizerData in [[stage_in]],                                   \n"
        "                     texture2d<half> colorTexture [[texture(GameTextureIndexColor)]])  \n"
        "{                                                                                      \n"
        "    constexpr sampler textureSampler(mag_filter::linear, min_filter::linear);          \n"
        "    const half4 colorSample = colorTexture.sample(textureSampler, in.textureCoordinate);  \n"
        "    return float4(colorSample.r, colorSample.g, colorSample.b, colorSample.a * in.alpha); \n"
        "}                                                                                      \n"
        "                                                                                       \n"
        "fragment float4                                                                        \n"
        "fragmentCopyShader(RasterizerData in [[stage_in]],                                     \n"
        "                   texture2d<half> colorTexture [[texture(GameTextureIndexColor)]])    \n"
        "{                                                                                      \n"
        "    constexpr sampler textureSampler(mag_filter::linear, min_filter::linear);          \n"
        "    half4 colorSample = colorTexture.sample(textureSampler, in.textureCoordinate);     \n"
        "    colorSample.a = 1.0;                                                               \n"
        "    return float4(colorSample);                                                        \n"
        "}                                                                                      \n"
        "                                                                                       \n"
        "fragment float4                                                                        \n"
        "fragmentDimShader(RasterizerData in [[stage_in]],                                      \n"
        "                  texture2d<half> colorTexture [[texture(GameTextureIndexColor)]])     \n"
        "{                                                                                      \n"
        "    constexpr sampler textureSampler (mag_filter::linear, min_filter::linear);         \n"
        "    half4 colorSample = colorTexture.sample(textureSampler, in.textureCoordinate);     \n"
        "    colorSample.rgb *= 0.5;                                                            \n"
        "    return float4(colorSample);                                                        \n"
        "}                                                                                      \n"
        "                                                                                       \n"
        "fragment float4                                                                        \n"
        "fragmentRuleShader(RasterizerData in [[stage_in]],                                     \n"
        "                   texture2d<half> colorTexture [[texture(GameTextureIndexColor)]],    \n"
        "                   texture2d<half> ruleTexture [[texture(GameTextureIndexRule)]])      \n"
        "{                                                                                      \n"
        "    constexpr sampler textureSampler (mag_filter::linear, min_filter::linear);         \n"
        "    half4 colorSample = colorTexture.sample(textureSampler, in.textureCoordinate);     \n"
        "    const half4 ruleSample = ruleTexture.sample(textureSampler, in.textureCoordinate); \n"
        "    colorSample.a = 1.0 - step(in.alpha, (float)ruleSample.b);                         \n"
        "    return float4(colorSample.r, colorSample.g, colorSample.b, colorSample.a);         \n"
        "}                                                                                      \n"
        "                                                                                       \n"
        "fragment float4                                                                        \n"
        "fragmentMeltShader(RasterizerData in [[stage_in]],                                     \n"
        "                   texture2d<half> colorTexture [[texture(GameTextureIndexColor)]],    \n"
        "                   texture2d<half> ruleTexture [[texture(GameTextureIndexRule)]])      \n"
        "{                                                                                      \n"
        "    constexpr sampler textureSampler (mag_filter::linear, min_filter::linear);         \n"
        "    half4 colorSample = colorTexture.sample(textureSampler, in.textureCoordinate);     \n"
        "    const half4 ruleSample = ruleTexture.sample(textureSampler, in.textureCoordinate); \n"
        "    colorSample.a = clamp((1.0 - ruleSample.b) + (in.alpha * 2.0 - 1.0), 0.0, 1.0);    \n"
        "    return float4(colorSample);                                                        \n"
        "}                                                                                      \n";
