//////////////////////////////////////////////////////////////////////////////
//
// Asura_D3D_VS_MeshHighlight.cpp
//
// Copyright (c) 2002 Rebellion. All rights reserved.
//
// Description:
//
//     Vertex shaders for rendering a highlighted Asura mesh, with optional
//     vertex offsets (towards the camera, to avoid z fighting.)
//
// History:
//
//     (MP  - 17.10.2002) - Created.
//
//////////////////////////////////////////////////////////////////////////////

// I N C L U D E S ///////////////////////////////////////////////////////////

#include "Core/Asura.h"
#include "Rendering/Asura_Direct3D_Shaders.h"
#include "Rendering/Asura_PlatformRenderMesh.h"

// G L O B A L S /////////////////////////////////////////////////////////////

static Direct3D_VertexElement g_ax_Vertex_Decl[] = 
{
	{0,  0,  D3DDECLTYPE_FLOAT3,	D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,	0},
	{0,  12, D3DDECLTYPE_FLOAT3,	D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,		0},
	{0,  24, D3DDECLTYPE_D3DCOLOR,	D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,		0},
	{0,  28, D3DDECLTYPE_FLOAT2,	D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,	0},
	{0,  36, D3DDECLTYPE_FLOAT2,	D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,	1},
	D3DDECL_END()
};


// Expected constants:
//     c0    obj->screen matrix
//     c1            "
//     c2            "
//     c3            "
//     c4    colour
static const char* g_szCode =
{
    " vs.1.1            \n"
	
	" dcl_position	v0 \n"

    // Transform to screen space and write to output position register.
    " m4x4 oPos, v0, c0 \n"

    // Copy colour to output colour register.
    " mov oD0, c4       \n"
};

// Expected constants:
//     c0    obj->screen matrix
//     c1            "
//     c2            "
//     c3            "
//     c4    colour
//     c5    object space cam pos xyz
#if ASURA_PC_OFFSET_MESH_HIGHLIGHT_ACCORDING_TO_CAM_DIST
// Constants setup by code:
//     c6    { offset min,     offset min,     offset min,     don't care }
//     c7    { offset range,   offset range,   offset range,   don't care }
//     c8    { cam dist min,   cam dist min,   cam dist min,   don't care }
//     c9    { cam dist range, cam dist range, cam dist range, don't care }
//     c10   1 / c9
//     c11   0
#else
//     c6    { offset, offset, offset, don't care }
#endif
static const char* g_szCodeWithOffset =
{
    " vs.1.1                      \n "
	
	" dcl_position	v0 \n"
	" dcl_normal	v1 \n"
	" dcl_color		v2 \n"
	" dcl_texcoord0	v3 \n"
	" dcl_texcoord1	v4 \n"
    // Offset.
    " mov r0.w,   v0.w            \n "
    " sub r0.xyz, c5.xyz, v0.xyz  \n " // r0 = to_cam
    " dp3 r1.xyz, r0.xyz, r0.xyz  \n " // r1.{xyz} = to_cam . to_cam
    " rsq r1.xyz, r1.x          \n " // r1.{xyz} = 1 / || to_cam ||
#if ASURA_PC_OFFSET_MESH_HIGHLIGHT_ACCORDING_TO_CAM_DIST
    " rcp r2.xyz, r1.x          \n " // r2.{xyz} = || to_cam ||
    " sub r2.xyz, r2.xyz, c8.xyz  \n " // r2.{xyz} = || to_cam || - cam_dist_min
    " max r2.xyz, r2.xyz, c11.xyz \n " // r2.{xyz} = max( 0, r2.{xyz} )
    " min r2.xyz, r2.xyz, c9.xyz  \n " // r2.{xyz} = min( r2.{xyz}, cam_dist_range )
    " mul r2.xyz, r2.xyz, c10.xyz \n " // r2.{xyz} = r2.{xyz} / cam_dist_range
    " mul r2.xyz, r2.xyz, c7.xyz  \n " // r2.{xyz} = r2.{xyz} * offset_range
    " add r2.xyz, r2.xyz, c6.xyz  \n " // r2.{xyz} = r2.{xyz} + offset_min
    " mul r1.xyz, r2.xyz, r1.xyz  \n " // r1.{xyz} = r2.{xyz} / || to_cam || = calculated_offset / || to_cam ||
#else
    " mul r1.xyz, c6.xyz, r1.xyz  \n " // r1.{xyz} = offset / || to_cam ||
#endif
    " mul r0.xyz, r0.xyz, r1.xyz  \n " // r0 = offset * norm( to_cam )
    " add r0.xyz, r0.xyz, v0.xyz  \n " // r0 = vertex_pos + offset * norm( to_cam )


    // Transform to screen space and write to output position register.
    " m4x4 oPos, r0, c0           \n "

    // Copy colour to output colour register.
    " mov oD0, c4                 \n "
};

// Declare the shader.
static Asura_Direct3D_VertexShader g_xShader( ASURA_D3D_VS_MESHHIGHLIGHT, g_szCode, g_ax_Vertex_Decl );
static Asura_Direct3D_VertexShader g_xShaderWithOffset( ASURA_D3D_VS_MESHHIGHLIGHT_WITHOFFSET, g_szCodeWithOffset, g_ax_Vertex_Decl );
