#include "CurveWorld.fx"

float4x4 gWorld : WORLD;
float4x4 gWorldViewProj : WORLDVIEWPROJECTION;
float4x4 gViewInverse : VIEWINVERSE;

Texture2D gTexture;
float4 gColor;
float gHeight = 1;
float gIntensity = .3f;
float gHeightChange = 0.3f;

struct VS_INPUT
{
    float3 pos : POSITION;
    float2 texCoord : TEXCOORD;
};

struct VS_OUTPUT
{
    float4 pos : SV_POSITION;
    float2 texCoord : TEXCOORD;
};

DepthStencilState EnableDepth
{
    DepthEnable = TRUE;
    DepthWriteMask = ALL;
};

RasterizerState BackCulling
{
    CullMode = FRONT;
};

BlendState EnableBlending
{
    BlendEnable[0] = FALSE;
};

SamplerState samLinear
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap; // or Mirror or Clamp or Border
    AddressV = Wrap; // or Mirror or Clamp or Border
};

float3 BulgeOut(float3 position)
{
    float heightNorm = abs(position.y / (gHeight / 2.f));
    position.xz *= 1 + (1 - heightNorm * heightNorm) * gIntensity;
    position.y *= 1 - gHeightChange * gIntensity;
    return position;
}

VS_OUTPUT VS(VS_INPUT input)
{
    VS_OUTPUT output;
    
    output.pos = CurveWorld(BulgeOut(input.pos), gViewInverse, gWorld, gWorldViewProj);
    output.texCoord = input.texCoord;
    return output;
}

float4 PS(VS_OUTPUT input) : SV_TARGET
{
    float4 tex = gTexture.Sample(samLinear, input.texCoord);
    return float4(tex.rgb * gColor.rgb, 1);
}

technique11 Default
{
    pass P0
    {
        SetRasterizerState(BackCulling);
        SetDepthStencilState(EnableDepth, 0);

        SetVertexShader(CompileShader(vs_4_0, VS()));
        SetGeometryShader(NULL);
        SetPixelShader(CompileShader(ps_4_0, PS()));
    }
}