//
// Asura_D3D_VS_Tools_Modules.cpp
//
// Created by RJF - 01 October 2004
//
// Copyright (C) 2004 Rebellion, All Rights Reserved.
//

#include "Core/Asura.h"

// These are tools-only shaders
// They will fail to compile if we are not building ASURA_TOOLS
#if defined ASURA_TOOLS

// This file's header.
#include "Rendering/Asura_Direct3D_Shaders.h"

// Vertex Declarator
// (for D3DGenericVertex structure)

static Direct3D_VertexElement auVSD[] =
{
	{	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()
};


const char* const szVS_TOOLS_MODULE_CODE =

// Tools module shader
// Single-pass rendering with no fog
// Expected constants:
//   c0-3 : ViewProj matrix
//   c11  : U Offset , V Offset , 0 , 0 (for texture anim)

"vs.1.1 \n"
"dcl_position0	v0 \n"
"dcl_color0		v1 \n"
"dcl_texcoord0	v2 \n"
"dcl_texcoord1	v3 \n"

// Do the position
"m4x4 oPos, v0, c0 \n"

// Diffuse
"mov oD0, v1 \n"

// Texcoords
"add oT0, v2, c11 \n"
"mov oT1, v3 \n"
"add oT2, v2, c11 \n"
"add oT3, v2, c11 \n";

// Register the shader with Asura

const Asura_Direct3D_VertexShader xVS_TOOLS_MODULE_SHADER(ASURA_D3D_VS_TOOLS_MODULE, szVS_TOOLS_MODULE_CODE, auVSD);

const char* const szVS_TOOLS_MODULE_LINEARFOG_CODE =

// Tools module shader
// Single-pass rendering with no fog
// Expected constants:
//   c0-3 : ViewProj matrix
//	 c4	  : Fog scaling values (x,y), min/max (z,w)
//   c11  : U Offset , V Offset , 0 , 0 (for texture anim)

"vs.1.1 \n"
"dcl_position0	v0 \n"
"dcl_color0		v1 \n"
"dcl_texcoord0	v2 \n"
"dcl_texcoord1	v3 \n"

// Do the position
"m4x4 r0, v0, c0 \n"
"mov oPos, r0 \n"

// Fog
"mad r0.x, r0.w, c4.x, c4.y \n"
"max r0.x, r0.x, c4.z \n"
"min oFog, r0.x, c4.w \n"

// Diffuse
"mov oD0, v1 \n"

// Texcoords
"add oT0, v2, c11 \n"
"mov oT1, v3 \n"
"add oT2, v2, c11 \n"
"add oT3, v2, c11 \n";

// Register the shader with Asura

const Asura_Direct3D_VertexShader xVS_TOOLS_MODULE_LINEARFOG_SHADER(ASURA_D3D_VS_TOOLS_MODULE_LINEARFOG, szVS_TOOLS_MODULE_LINEARFOG_CODE, auVSD);


const char* const szVS_TOOLS_MODULE_GRAPHFOG_CODE =

// Tools module shader
// Single-pass rendering with no fog
// Expected constants:
//  c0-c3: ViewProj matrix
//  c5:    Fog values scaling values (x,y) spline control point position (z), 1.0f (w)
//  c6:    Scaling values to map full-range value to first-part-of-spline
//  c7:    Scaling values to map full-range value to second-part-of-spline
//  c8:    Fog abcv1 vector for points between the near plane and centerpoint
//  c9:    Fog abcv1 vector for points between centerpoint and far plane
//  c10:    0.0f, 1.0f
//  c11  : U Offset , V Offset , 0 , 0 (for texture anim)


"vs.1.1 \n"
"dcl_position0	v0 \n"
"dcl_color0		v1 \n"
"dcl_texcoord0	v2 \n"
"dcl_texcoord1	v3 \n"

// Do the position
"m4x4 r0, v0, c0 \n"
"mov oPos, r0 \n"

// Fog
// our distance from the camera (in metres) is in r12.w (oPos.w)
// c5.x: 1 / (fardistance - neardistance)
// c5.y: (-neardistance / (fardistance - neardistance))
"mad r1.z, r0.w, c5.x, c5.y \n"
"min r1.z, r1.z, c10.y \n"
"max r1.z, r1.z, c10.x \n"
// so r1.z is now in the [0..1] range, 1 being farthest and 0 being nearest.
// decide which part of the spline we're in
// a 0.0 in r1.x means we want c+0, a 1.0 means we want c+1
"sge r0.x, r1.z, c5.z \n"
"mov a0.x, r0.x \n"
// rescale r1.z for this part of the spline
"mad r1.z, r1.z, c[6+a0.x].x, c[6+a0.x].y \n"
// we want to build (r1.z^3, r1.z^2, r1.z, 1) for easy calc
"mov r1.w, c5.w \n"
"mul r1.y, r1.z, r1.z \n"
"mul r1.x, r1.y, r1.z \n"
// dp4 to generate the output value
"dp4 oFog, r1, c[8+a0.x] \n"

// Diffuse
"mov oD0, v1 \n"

// Texcoords
"add oT0, v2, c11 \n"
"mov oT1, v3 \n"
"add oT2, v2, c11 \n"
"add oT3, v2, c11 \n";

// Register the shader with Asura

const Asura_Direct3D_VertexShader xVS_TOOLS_MODULE_GRAPHFOG_SHADER(ASURA_D3D_VS_TOOLS_MODULE_GRAPHFOG, szVS_TOOLS_MODULE_GRAPHFOG_CODE, auVSD);

const char* const szVS_TOOLS_MODULE_REFLECTIVE_CODE =

// Tools module shader
// Single-pass rendering with no fog
// Expected constants:
//   c0-3 : ViewProj matrix
//   c4-7 : Proj matrix
//   c8-11: Refl matrix

"vs.1.1 \n"
"dcl_position0	v0 \n"
"dcl_normal0	v1 \n"
"dcl_color0		v2 \n"
"dcl_texcoord0	v3 \n"

// Do the position
"m4x4 oPos, v0, c0 \n"

// Diffuse
"mov oD0, v2 \n"

// Texcoords
"mov oT0, v3 \n"

// Refl
"dp4 r0.x, v0, c4	\n"
"dp4 r0.y, v0, c5	\n"
"dp4 r0.z, v0, c6	\n"
// normalise view position
"dp3 r1.x, r0, r0	\n"
"rsq r1.x, r1.x		\n"
"mul r0.xyz, r0.xyz, r1.x \n"

// transform + normalise normal as well
"dp3 r1.x, v1, c4	\n"
"dp3 r1.y, v1, c5	\n"
"dp3 r1.z, v1, c6	\n"

"dp3 r2.x, r1, r1	\n"
"rsq r2.x, r2.x		\n"
"mul r1.xyz, r1.xyz, r2.x \n"

// reflection vector is D - 2(D.N)N
"dp3 r2.x, r0, r1	\n" // D.N
"add r2.x, r2.x, r2.x \n" // 2(D.N)
"mul r2.xyz, r2.xxx, r1.xyz \n" // 2(D.N)N
"sub r2.xyz, r0.xyz, r2.xyz \n" // D - 2(D.N)N

"mov r2.w, c10.x \n"

// push through texture matrix
"dp4 oT1.x, r2, c8 \n"
"dp4 oT1.y, r2, c9 \n"
;

// Register the shader with Asura

const Asura_Direct3D_VertexShader xVS_TOOLS_MODULE_REFLECTIVE_SHADER(ASURA_D3D_VS_TOOLS_MODULE_REFLECTIVE, szVS_TOOLS_MODULE_REFLECTIVE_CODE, auVSD);


//tools collision mesh shader
static Direct3D_VertexElement g_ax_CMeshZOffset_Vertex_Decl[] = 
{
	{0,  0,  D3DDECLTYPE_FLOAT3,	D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,	0},
	{0,  12, D3DDECLTYPE_D3DCOLOR,	D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,		0},
	{0,  16, D3DDECLTYPE_FLOAT2,	D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,	0},
	D3DDECL_END()
};


// Expected constants:
//     c0    obj->screen matrix
//     c1            "
//     c2            "
//     c3            "
//     c4    z offset
//     c5    object space cam pos xyz
static const char* szVS_TOOLS_CMESH_ZOFFSET =
{
    " vs.1.1                      \n "
	
	" dcl_position	v0 \n"
	" dcl_color		v1 \n"
	" dcl_texcoord0	v2 \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 ||

    " mul r1.xyz, c4.xyz, r1.xyz  \n " // r1.{xyz} = offset / || to_cam ||

    " 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, v1                 \n "
	"mov oT0, v2 \n"
};

// Declare the shader.
static Asura_Direct3D_VertexShader xVS_TOOLS_CMESH_ZOFFSET( ASURA_D3D_VS_TOOLS_CMESH_ZOFFSET, szVS_TOOLS_CMESH_ZOFFSET, g_ax_CMeshZOffset_Vertex_Decl );



#endif // defined ASURA_TOOLS
