Here is the solution, including the coordinate transformation from open gl to directx (which is tricky with 16x4 subimages in the texture, it is normaly flipped without the conversion)
// (C)2006 S2 Games
// mesh_shadowed.vsh modified by rohezal
//
// Default mesh vertex shader with shadowmap support
//=============================================================================
//=============================================================================
// Headers
//=============================================================================
#include "../common/common.h"
#include "../common/fog.h"
//=============================================================================
// Global variables
//=============================================================================
float4x4 mWorldViewProj; // World * View * Projection transformation
float4x4 mWorldView; // World * View
float3x3 mWorldViewRotate; // World rotation for normals
float4 vSunPositionView;
float3 vAmbient;
float3 vSunColor;
float3 vSunColorSpec;
float fGlossiness;
#if (SHADOWS == 1)
#ifdef SHADOW_SPLIT_PROJECTION
float4x4 mLightWorldViewProjTexSplit[4]; // Light's World * View * Projection * Tex
#else
float4x4 mLightWorldViewProjTex; // Light's World * View * Projection * Tex
#endif
#endif
float4 vColor;
#if (NUM_BONES > 0)
float4x3 vBones[NUM_BONES];
#endif
#ifdef CLOUDS
float4x4 mCloudProj;
#endif
#if (FOG_OF_WAR == 1)
float4x4 mFowProj;
#endif
//=============================================================================
// Vertex shader output structure
//=============================================================================
#define OBJECT_SIZE 100 //ugly hack but hey S2upid at work
#define OBJECT_HALFSIZE OBJECT_SIZE/2 //ugly hack but hey S2upid at work
#define DEGREE_TO_RADIANS 0.017453f //constant for transforming degrees in radians
#define NUMBER_OF_IMAGES 16.0f //number of images in texture, per row!!!
#define DEGREE_SIZE_OF_IMAGE (360/NUMBER_OF_IMAGES) //if there a cirle of images, how many degrees of 360 has on single image. 16 images = 22.5
#define NUMBER_OF_ROWS 4.0f //if there a cirle of images, how many degrees of 360 has on single image. 16 images = 22.5
struct VS_OUTPUT
{
float4 Position : POSITION;
float4 Color0 : COLOR0;
float2 Texcoord0 : TEXCOORDX;
#include "../common/inc_texcoord.h"
#if (LIGHTING_QUALITY == 0 || FALLOFF_QUALITY == 0)
float3 PositionView : TEXCOORDX;
#include "../common/inc_texcoord.h"
#endif
#if (LIGHTING_QUALITY == 0)
float3 Normal : TEXCOORDX;
#include "../common/inc_texcoord.h"
float3 Tangent : TEXCOORDX;
#include "../common/inc_texcoord.h"
float3 Binormal : TEXCOORDX;
#include "../common/inc_texcoord.h"
#elif (LIGHTING_QUALITY == 1)
float3 HalfAngle : TEXCOORDX;
#include "../common/inc_texcoord.h"
float3 SunLight : TEXCOORDX;
#include "../common/inc_texcoord.h"
#elif (LIGHTING_QUALITY == 2)
float3 DiffLight : TEXCOORDX;
#include "../common/inc_texcoord.h"
float3 SpecLight : TEXCOORDX;
#include "../common/inc_texcoord.h"
#elif (LIGHTING_QUALITY == 3)
float3 DiffLight : TEXCOORDX;
#include "../common/inc_texcoord.h"
#endif
#if (SHADOWS == 1)
#ifdef SHADOW_SPLIT_PROJECTION
float4 TexcoordLight0 : TEXCOORDX;
#include "../common/inc_texcoord.h"
float4 TexcoordLight1 : TEXCOORDX;
#include "../common/inc_texcoord.h"
float4 TexcoordLight2 : TEXCOORDX;
#include "../common/inc_texcoord.h"
float4 TexcoordLight3 : TEXCOORDX;
#include "../common/inc_texcoord.h"
#else
float4 TexcoordLight : TEXCOORDX; // Texcoord in light texture space
#include "../common/inc_texcoord.h"
#endif
#endif
#ifdef CLOUDS
float4 TexcoordClouds : TEXCOORDX;
#include "../common/inc_texcoord.h"
#endif
#if ((FOG_QUALITY == 1 && FOG_TYPE != 0) || (FALLOFF_QUALITY == 1 && (FOG_TYPE != 0 || SHADOWS == 1)) || FOG_OF_WAR == 1)
float4 Last : TEXCOORDX;
#include "../common/inc_texcoord.h"
#endif
};
//=============================================================================
// Vertex shader input structure
//=============================================================================
struct VS_INPUT
{
float3 Position : POSITION;
float3 Normal : NORMAL;
float2 Texcoord0 : TEXCOORD0;
float3 Tangent : TEXCOORD1;
#if (NUM_BONES > 0)
int4 BoneIndex : TEXCOORD_BONEINDEX;
float4 BoneWeight : TEXCOORD_BONEWEIGHT;
#endif
};
//=============================================================================
// Vertex Shader
//=============================================================================
VS_OUTPUT VS( VS_INPUT In )
{
VS_OUTPUT Out;
#if ((FOG_QUALITY == 1 && FOG_TYPE != 0) || (FALLOFF_QUALITY == 1 && (FOG_TYPE != 0 || SHADOWS == 1)) || FOG_OF_WAR == 1)
Out.Last = 0;
#endif
float3 vInNormal = (In.Normal / 255.0f) * 2.0f - 1.0f;
float3 vInTangent = (In.Tangent / 255.0f) * 2.0f - 1.0f;
#if (NUM_BONES > 0)
float3 vPosition = 0.0f;
float3 vNormal = 0.0f;
float3 vTangent = 0.0f;
//
// GPU Skinning
// Blend bone matrix transforms for this bone
//
int4 vBlendIndex = In.BoneIndex;
float4 vBoneWeight = In.BoneWeight / 255.0f;
float4x3 mBlend = 0.0f;
for (int i = 0; i < NUM_BONE_WEIGHTS; ++i)
mBlend += vBones[vBlendIndex[i]] * vBoneWeight[i];
float3x3 mAxis = float3x3(mBlend[0], mBlend[1], mBlend[2]);
float3 vPos = mBlend[3];
vPosition = mul(In.Position, mAxis) + vPos;
vNormal = mul(vInNormal, mAxis);
vTangent = mul(vInTangent, mAxis);
vNormal = normalize(vNormal);
vTangent = normalize(vTangent);
#else
float3 vPosition = In.Position;
float3 vNormal = vInNormal;
float3 vTangent = vInTangent;
#endif
float3 vPositionView = mul(float4(vPosition, 1.0f), mWorldView).xyz;
//own code
float3 objectNormal = mul(vNormal, mWorldViewRotate);
float3 camVector = float3(0.0f,0.0f,-1.0f);
float3 camVector2 = -normalize(vPositionView);
//get the INVERSE angel. calculate the angle between object and camera and go in the opposite angle
//cos and sin can only go from -1 to 1, so 180 = -180 and he can decide
float cosAngle = dot(objectNormal,camVector2);
//the sin is always positive, since it is the area of a parallelo gram. check if the quad face left or right from the cam (-1)
float sinAngle = sin(acos(cosAngle)) * (objectNormal.x / max(abs(objectNormal.x), 0.001f));
//float4x4 rotMatrixZ = float4x4(1.0f,0.0f,0.0f,0.0f, 0.0f,1.0f,0.0f,0.0f, 0.0f,0.0f,1.0f,0.0f, 0.0f,0.0f,0.0f,1.0f);
float4x4 rotMatrixZ = float4x4(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 );
rotMatrixZ[0][0] = 1.0f;
rotMatrixZ[1][1] = 1.0f;
rotMatrixZ[2][2] = 1.0f;
rotMatrixZ[3][3] = 1.0f;
rotMatrixZ[0][0] = -cosAngle;
rotMatrixZ[1][0] = -sinAngle;
rotMatrixZ[0][1] = sinAngle;
rotMatrixZ[1][1] = -cosAngle;
//Out.Position = mul(mWorldViewProj, mul(rotMatrixZ,float4(In.Position, 1.0f)));
Out.Position = mul(mul(float4(In.Position, 1.0f),rotMatrixZ),mWorldViewProj);
//do it again for the texture
cosAngle = dot(objectNormal,camVector);
sinAngle = sin(acos(cosAngle)) * (objectNormal.x / max(abs(objectNormal.x), 0.001f));
//grid code
//cos - 1 ... ups builded a cirle from -180 to 180... wtf this was not by purpose lol. 0 -> -180 -> +180 ->0
//float angle = (cosAngle - 1) * 90 * (sinAngle/abs(sinAngle)) + min(0,sinAngle/abs(sinAngle)) * 180;
//transform the creative solution *LOOOL* to a normal angle from 0 to 360 degree.
//angle = -angle*(sinAngle/abs(sinAngle)) * max(sinAngle/abs(sinAngle),0) + 180 + abs(sinAngle)*180;
// 0 - 180 //180 + i*180 where i = 0 to 1
//fucked up but works. for normal people: first line 0 - 90, second 90 - 180, third 180-270, fourth 270 - 360
//if sin > 0 and cos > 0 then first line, if sin > 0 and cos < 0 then second line + 90 and so on.
float angle = sinAngle * 90 * max(sinAngle/abs(sinAngle),0) * max(cosAngle/abs(cosAngle),0) //sin pos cos pos
+ min (cosAngle/abs(cosAngle),0) * (cosAngle/abs(cosAngle)) * max(0,sinAngle/abs(sinAngle)) * (90 + 90 * abs(cosAngle)) //cos neg sin pos
+ min (cosAngle/abs(cosAngle),0) * (cosAngle/abs(cosAngle)) * min (sinAngle/abs(sinAngle),0) * (sinAngle/abs(sinAngle)) * (180 + 90 * abs(sinAngle)) //cos neg sin neg
+ max(0,cosAngle/abs(cosAngle)) * min (sinAngle/abs(sinAngle),0) * (sinAngle/abs(sinAngle)) * (270 + 90 * abs(cosAngle)); //cos neg sin pos
float v_vImageId = floor(angle * NUMBER_OF_ROWS / DEGREE_SIZE_OF_IMAGE);
//v_vImageId = float ( mod( int(v_vImageId) , int(NUMBER_OF_IMAGES) ) );
//no mod this sux
v_vImageId = v_vImageId - NUMBER_OF_IMAGES * floor(v_vImageId/NUMBER_OF_IMAGES);
//float v_vImageId = int(((angle - 90 * floor(angle/90)) / DEGREE_SIZE_OF_IMAGE));
//no mod fuuuu MS
/*
float v_vImageId = int(angle / DEGREE_SIZE_OF_IMAGE);
v_vImageId = v_vImageId - NUMBER_OF_ROWS * floor(v_vImageId/NUMBER_OF_ROWS);
*/
Out.Texcoord0 = In.Texcoord0;
float convert = In.Texcoord0.y - (1-In.Texcoord0.y);
Out.Texcoord0.y = 1- In.Texcoord0.y;
//use min because the angle is negative
Out.Texcoord0.x = (Out.Texcoord0.x/NUMBER_OF_IMAGES) + max(0,(v_vImageId))/NUMBER_OF_IMAGES;
//Out.Texcoord0.x = (Out.Texcoord0.x/NUMBER_OF_IMAGES) + int(angle/DEGREE_SIZE_OF_IMAGE)/NUMBER_OF_IMAGES;
//Out.Texcoord0.x = (Out.Texcoord0.x/16.0f)+ v_vImageId/16.0f;
//Out.Texcoord0.y = 1-Out.Texcoord0.y;//translate from open gl to directx
Out.Texcoord0.y = (Out.Texcoord0.y / NUMBER_OF_ROWS) + (NUMBER_OF_ROWS-1)/NUMBER_OF_ROWS - (1/NUMBER_OF_ROWS) * floor(angle*NUMBER_OF_ROWS/360);
//translate to directx coords
Out.Texcoord0.y = Out.Texcoord0.y+convert*1.0f/NUMBER_OF_ROWS;
//Out.Texcoord0.y = (Out.Texcoord0.y / 4) + testy;
//Out.Position[1] = Out.Position[1] + Out.Position[1]*(angle/100);
//END OWN CODE
//Out.Position = mul(float4(vPosition, 1.0f), mWorldViewProj);
Out.Color0 = vColor;
//Out.Texcoord0 = In.Texcoord0;
#if (LIGHTING_QUALITY == 0 || FALLOFF_QUALITY == 0)
Out.PositionView = vPositionView;
#endif
#if (FALLOFF_QUALITY == 1 && (FOG_TYPE != 0 || SHADOWS == 1))
Out.Last.z = length(vPositionView);
#endif
#if (LIGHTING_QUALITY == 0)
Out.Normal = mul(vNormal, mWorldViewRotate);
Out.Tangent = mul(vTangent, mWorldViewRotate);
Out.Binormal = cross(Out.Tangent, Out.Normal);
#elif (LIGHTING_QUALITY == 1)
float3 vCamDirection = -normalize(vPositionView);
float3 vLight = vSunPositionView.xyz;
float3 vWVNormal = mul(vNormal, mWorldViewRotate);
float3 vWVTangent = mul(vTangent, mWorldViewRotate);
float3 vWVBinormal = cross(vWVTangent, vWVNormal);
float3x3 mRotate = transpose(float3x3(vWVTangent, vWVBinormal, vWVNormal));
Out.SunLight = mul(vLight, mRotate);
Out.HalfAngle = mul(normalize(vLight + vCamDirection), mRotate);
#elif (LIGHTING_QUALITY == 2)
float3 vCamDirection = -normalize(vPositionView);
float3 vLight = vSunPositionView.xyz;
float3 vHalfAngle = normalize(vLight + vCamDirection);
float3 vWVNormal = mul(vNormal, mWorldViewRotate);
float fDiffuse = saturate(dot(vWVNormal, vLight));
float fSpecular = saturate(step(0.0f, fDiffuse) * (pow(dot(vWVNormal, vHalfAngle), fGlossiness)));
Out.DiffLight = vSunColor * fDiffuse;
Out.SpecLight = vSunColorSpec * fSpecular;
#elif (LIGHTING_QUALITY == 3)
float3 vLight = vSunPositionView.xyz;
float3 vWVNormal = mul(vNormal, mWorldViewRotate);
float fDiffuse = saturate(dot(vWVNormal, vLight));
Out.DiffLight = vSunColor * fDiffuse;
#endif
#if (SHADOWS == 1)
#ifdef SHADOW_SPLIT_PROJECTION
Out.TexcoordLight0 = mul(float4(vPosition, 1.0f), mLightWorldViewProjTexSplit[0]);
Out.TexcoordLight1 = mul(float4(vPosition, 1.0f), mLightWorldViewProjTexSplit[1]);
Out.TexcoordLight2 = mul(float4(vPosition, 1.0f), mLightWorldViewProjTexSplit[2]);
Out.TexcoordLight3 = mul(float4(vPosition, 1.0f), mLightWorldViewProjTexSplit[3]);
#else
Out.TexcoordLight = mul(float4(vPosition, 1.0f), mLightWorldViewProjTex);
#endif
#endif
#ifdef CLOUDS
Out.TexcoordClouds = mul(float4(vPosition, 1.0f), mCloudProj);
#endif
#if (FOG_QUALITY == 1 && FOG_TYPE != 0)
Out.Last.w = Fog(vPositionView);
#endif
#if (FOG_OF_WAR == 1)
Out.Last.xy = mul(float4(vPosition, 1.0f), mFowProj).xy;
#endif
return Out;
//outsourced own code
/*
float test = (angle-2*floor(angle/90));
test = int(test/90);
test = test/2;
*/
/*
float test = angle / 360*64;
test = float(int(test));
test = test -16*floor(test/16);
test = test/16;
*/
/*
float test = max((angle - 91 *floor (angle/91)),0);
//test = test * (max(0, test-5.6)/(test-5.6));
//test = int(int (test) / max(int(90/16),1) ) ;
test = int(floor(test / 5.625));
test = test/16;
*/
/*
float test = float(int(angle));
test = max((test - 91 *floor (test/91)),0);
test = floor(test / 5.625);
test = floor(test*10 / 16);
test = test/10;
*/
/*
float testy = angle;
testy = int(testy/181);
testy = testy/2;
*/
/*
float test = min(angle,90.0f);
test = max(test,0.0f);
float adder = 0.0f;
if(test < 5.63f*8)
{
adder = 2.0f / 16.0f;
}
if(test > 5.63f*8)
{
adder = 8.0f/16.0f;
}
*/
/*
if(test > 5.63f && test < 11.26f )
{
adder = (1.0f/16.0f);
}
if(test > 11.26f && test < 17.00f )
{
adder = (2.0f/16.0f);
}
*/
}