Problem to port gl sl shader to hlsl

Started by
3 comments, last by rohezal 10 years, 7 months ago

Hi guys,

I am doing a mod for a game. I can only change the shaders.

It is a billboard cloud (a quad which rotates with the camera and changes it's it texture depending on the viewing angle of the user). If you are at the front you see the dragon face front. If you are 90° degree to the left, the quad rotates and you see the dragonface fromt the left. I am doing this with one mega texture (8K*2K texel). It consists of 16*4 = 64 (512x512 pixel) images next to each other. It works ok smile.png.

It allready works in GL SL (open gl). I just move the UV coordinates to display a different part of texture (which is just one of the 512x512 images). When it just were 1x64 images the mapping would be easing 360° degree, so each the image to display would ucoord = ucoord/64 + (int)(angle/64) or something. Now I have 2D mapping and try to get from sin and cos the the degree. It works. Then map it a 16x4 image "array". It works.

But when I try to map it to direct x hlsl it fails. I don't know why. Maybe you have an idea.

If you want to try it:

Grid Shader (starts with //own code it is a mod like I said):

http://pastebin.de/35908

Rotation only Shader (works):

http://pastebin.de/35909

The open gl gl sl shader (works):

http://pastebin.de/35910

Advertisement

Maybe the convertion betwen sin and cos to a 360 angle is problematic. Does someone know a good formular to calculate a 360 degree angle from a sin and cos?

Usually trigonometric functions want the argument in radians, not degrees. This holds for both GLSL and HLSL (and every math library I have come across so far).

Formulas.

I have only shader access to not a functions for me. I am doing the math myself and it works in open gl:

I have no good way to debug I just increase the Y axis with the angle to check it. It grows constantly so I don't think there is the problem

.


	//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

I want to get the index of the image (like an element from an 1D array int data[64];).

There are 64 images. In 1D it would be: int imageId = int(angle /64);

In 2D the idea is ( the array is array[4][16]):


int oneDimension = int(angle /64); //angles to image indexes
int imageIdX = oneDimension % 16; //x coord or index of the image.
int imageIdY = int(oneDimension/ 16); //y coord or index of the image.

This works in open gl but not in direct x.

I realy just want to calculate the angle from a sinus and cosinus and the split it in X and Y indexes of a 2D array. Maybe you have a radiant way to do it, but I am bad in radiants.

Here is the working open gl code to make indexX und indexY from the angle:



#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	v_vImageId = floor(angle * NUMBER_OF_ROWS / DEGREE_SIZE_OF_IMAGE);
	v_vImageId =  float ( mod( int(v_vImageId) , int(NUMBER_OF_IMAGES) ) );

	gl_TexCoord[0]   = gl_MultiTexCoord0;
	//use min because the angle is negative

	gl_TexCoord[0].x = (gl_TexCoord[0].x/NUMBER_OF_IMAGES) + max(0,(v_vImageId))/NUMBER_OF_IMAGES;
	gl_TexCoord[0].y = (gl_TexCoord[0].y / NUMBER_OF_ROWS) + (NUMBER_OF_ROWS-1)/NUMBER_OF_ROWS  - (1/NUMBER_OF_ROWS) * floor(angle*NUMBER_OF_ROWS/360);

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);
    }
    */

}

This topic is closed to new replies.

Advertisement