[SUB] Rotating a texture in a pixel shader

Posted By: Steempipe

[SUB] Rotating a texture in a pixel shader - 01/16/16 05:22

An example of rotating a texture 0-360 degrees in a pixelshader.

Just playing around mainly, but planning to use it to some extent in a different shader.

Maybe it will be useful to somebody.

Texture Rotation in Pixelshader



Code:
BMAP* tex = "stone.tga";

MATERIAL* mtlEffect = 


{

skin1 = tex;
	
effect = " 

//-------------------------------------
// non-tweakables
//-------------------------------------
float4x4 	matWorldViewProj;


//-------------------------------------
// tweakables
//-------------------------------------
float vecSkill1; // pass angle in degrees

//-------------------------------------
// textures
//-------------------------------------

texture mtlSkin1;
sampler sTex = sampler_state
{
   Texture = <mtlSkin1>;
   MinFilter = Linear;
   MagFilter = Linear;
   MipFilter = Linear;   
   AddressU  = wrap;  
   AddressV  = wrap;  
};


//-------------------------------------
// structs 
//-------------------------------------
struct VS_INPUT
{
    float4 Position		: 	POSITION;
    float2 TexCoord0 	: 	TEXCOORD0;
};

struct VS_OUTPUT
{
    float4 PosWorld		: POSITION;    
    float2 TexCoord0		: TEXCOORD0;    
   
};

// ----------------------------------------------------------------
//  vertexshader 
// ----------------------------------------------------------------
VS_OUTPUT vs_main( VS_INPUT In ) 
{
    VS_OUTPUT Out;

    float4 Position = mul(In.Position,  matWorldViewProj);
    Out.PosWorld = Position;
    Out.TexCoord0 =  In.TexCoord0.xy;
        
    return Out;
}



// ----------------------------------------------------------------
//  pixelshader 
// ----------------------------------------------------------------
float4 ps_main(VS_OUTPUT In) : COLOR
{
    
    float s = sin(radians(vecSkill1.x)); // input in degrees
    float c = cos(radians(vecSkill1.x));
    
    float2x2 rotMatrix = float2x2(c,-s,s,c);
    
    float2 rotated_tex = In.TexCoord0 -=0.5;
    rotated_tex = mul(In.TexCoord0.xy ,rotMatrix);
    rotated_tex += 0.5;
       
    float4 oTexture = tex2D(sTex, rotated_tex * 2 ); 
       
    return oTexture;
   
}


// ----------------------------------------------------------------
//  Technique
// ----------------------------------------------------------------
Technique tech1 
{
    Pass One
      {
      	vertexshader = compile vs_2_0 vs_main();
         pixelshader = compile ps_2_0 ps_main();
      }

     
}


";

}

action mtl_texrot () {
	
	my.material = mtlEffect;
   
}

Posted By: txesmi

Re: [SUB] Rotating a texture in a pixel shader - 01/16/16 09:27

Thanks!

but should the rotation matrix be calculated in the CPU only once?
Posted By: Steempipe

Re: [SUB] Rotating a texture in a pixel shader - 01/16/16 12:31

That's a good suggestion, txesmi. Thanks for pointing it out.
Posted By: 20BN

Re: [SUB] Rotating a texture in a pixel shader - 01/17/16 13:04

@ Steempipe
Thanks!
It's very very useful!
Can u update uv moving, and scale?
Posted By: Steempipe

Re: [SUB] Rotating a texture in a pixel shader - 01/17/16 15:18

Originally Posted By: txesmi
Thanks!

but should the rotation matrix be calculated in the CPU only once?


I believe that I have implemented your suggestion (in version 2 below) by doing the calculation in a material_init event. Thanks for the suggestion as it has helped me learn a lot more about the engine and coding!

Version 2 - Rotating a Texture in a Shader

Quote:

//=============================================================================
// Texture Coord Rotation
//=============================================================================
//
// Eric (Steempipe) Hendrickson-Lambert
// needs: 3DGS C/P DirectX 9 vs/ps_2_0
//
// 1/15/16 version 1
// 1/17/16 version 2
// changed code to calculate/initialize rotation matrix outside of
// shader in material event. recomendation by "txesmi"
//=============================================================================


BMAP* tex = "stone.tga";


function mtlEffect_init()

{

// example of using 4x4 matrix to rotate a texture in a shader
//

// tweakables to control how our texture is translated
var tex_rotation_in_degrees = 45; // 0-360 degrees in CW rotation.

// initialize our rotation matrix
float rotation_matrix[16] =
{ 1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 };



// apply necessary maths to our matrix
rotation_matrix[0] = cosv(tex_rotation_in_degrees);
rotation_matrix[1] = -sinv(tex_rotation_in_degrees);
rotation_matrix[4] = sinv(tex_rotation_in_degrees);
rotation_matrix[5] = cosv(tex_rotation_in_degrees);

mat_effect1 = rotation_matrix; // assign our matrix to a pointer for the shader

}

MATERIAL* mtlEffect =


{

event = mtlEffect_init; // set up the texture rotation matrix for the shader

skin1 = tex;

effect = "

//-------------------------------------
// non-tweakables
//-------------------------------------
float4x4 matWorldViewProj;
float4x4 matEffect1;


//-------------------------------------
// tweakables
//-------------------------------------
// rotation degree variable located in mtlEffect_init function

//-------------------------------------
// textures
//-------------------------------------

texture mtlSkin1;
sampler sTex = sampler_state
{
Texture = <mtlSkin1>;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
AddressU = wrap;
AddressV = wrap;
};


//-------------------------------------
// structs
//-------------------------------------
struct VS_INPUT
{
float4 Position : POSITION;
float2 TexCoord0 : TEXCOORD0;
};

struct VS_OUTPUT
{
float4 PosWorld : POSITION;
float2 TexCoord0 : TEXCOORD0;

};

// ----------------------------------------------------------------
// vertexshader
// ----------------------------------------------------------------
VS_OUTPUT vs_main( VS_INPUT In )
{
VS_OUTPUT Out;

float4 Position = mul(In.Position, matWorldViewProj);
Out.PosWorld = Position;
Out.TexCoord0 = In.TexCoord0.xy;

return Out;
}



// ----------------------------------------------------------------
// pixelshader
// ----------------------------------------------------------------
float4 ps_main(VS_OUTPUT In) : COLOR
{


// translate texture origin to the center
float2 rotated_tex = In.TexCoord0 -=0.5;

// rotate
rotated_tex = mul(In.TexCoord0.xy ,matEffect1);

// translate texture back to 0..1 range
rotated_tex += 0.5;

float4 oTexture = tex2D(sTex, rotated_tex * 2);

return oTexture;

}


// ----------------------------------------------------------------
// Technique
// ----------------------------------------------------------------
Technique tech1
{
Pass One
{
vertexshader = compile vs_2_0 vs_main();
pixelshader = compile ps_2_0 ps_main();
}


}


";

}

action mtl_texrot () {

my.material = mtlEffect;

}
Posted By: Steempipe

Re: [SUB] Rotating a texture in a pixel shader - 01/17/16 15:19

Originally Posted By: 20BN
@ Steempipe
Thanks!
It's very very useful!
Can u update uv moving, and scale?


@20BN

EDIT:
Version 3 - Texture rotation/scaling/shifting

Here's a version for you that allows variables for scaling the texture and shifting the texture based on time.
1). I've moved the tweakables into the "action" so that they are in one place.
2). I've moved the texture UV translations into the vertex shader, must be a more efficient place(?)
3). Put an example of how to use one TEXCOORD to pass the rotated UV's and also the un-rotated UV's to the pixel shader and then lerped between the two for an example.
4). The slider, fi; in the executable demo, adds a divisor to the shifting time_step.

Code:
// Texture Coord Rotation
//=============================================================================
// 
// Eric (Steempipe) Hendrickson-Lambert
// needs: 3DGS C/P   DirectX 9 vs/ps_2_0
//
// 1/15/16  version 1
// 1/17/16  version 2 
//             changed code to calculate/initialize rotation matrix outside of
//				   shader in material event.  recomendation by "txesmi"
// 1/17/16  version 3
//					1). added texture scaling and shifting example.
//					2). moved all texture rotation/scaling/shifting operations to 
//					    vertex shader.
//					3). an example of trick using (1) texCoord to pass 2 sets of UV's and use 
//					    those 2 sets of UV's in pixelshader.
//					4). put tweakable scaling and shifting vars in the action to be in one place.
//					5). pan_slider controls shifting speed				
//=============================================================================


BMAP* tex = "stone.tga";
var tex_rotation_in_degrees; // var for degrees rotation

function mtlEffect_init()

{

   // example of using 4x4 matrix to rotate a texture in a shader
   // 
   
   // tweakables to control how our texture is translated
   //var tex_rotation_in_degrees = 45;  // 0-360 degrees in CW rotation.
  
     // initialize variables in our rotation matrix
   float rotation_matrix[16] =
		{ 1.0, 0.0, 0.0, 0.0,
		  0.0, 1.0,	0.0, 0.0,
		  0.0, 0.0, 1.0, 0.0,
		  0.0, 0.0, 0.0, 1.0 };
		  
	
	// apply necessary maths to our matrix
	rotation_matrix[0] = cosv(tex_rotation_in_degrees);
	rotation_matrix[1] = -sinv(tex_rotation_in_degrees);
	rotation_matrix[4] = sinv(tex_rotation_in_degrees);
	rotation_matrix[5] = cosv(tex_rotation_in_degrees);
	
	mat_effect1 = rotation_matrix; // assign our matrix to a pointer for the shader
	
}

MATERIAL* mtlEffect = 


{

event = mtlEffect_init;  // set up the texture rotation matrix for the shader

skin1 = tex;
	
effect = " 

//-------------------------------------
// non-tweakables
//-------------------------------------
float4x4 	matWorldViewProj;
float4x4 	matEffect1; // rotation matrix 
float4 		vecSkill41; // texture scaling in x, scrolling time in y


//-------------------------------------
// tweakables
//-------------------------------------
//  rotation degree variable located in mtlEffect_init function

//-------------------------------------
// textures
//-------------------------------------

texture mtlSkin1;
sampler sTex = sampler_state
{
   Texture = <mtlSkin1>;
   MinFilter = Linear;
   MagFilter = Linear;
   MipFilter = Linear;   
   AddressU  = wrap;  
   AddressV  = wrap;  
};


//-------------------------------------
// structs 
//-------------------------------------
struct VS_INPUT
{
    float4 Position		: 	POSITION;
    float2 TexCoord0 	: 	TEXCOORD0;
};

struct VS_OUTPUT
{
    float4 PosWorld		: POSITION;    
    float4 TexCoord0		: TEXCOORD0;    
   
};

// ----------------------------------------------------------------
//  vertexshader 
// ----------------------------------------------------------------
VS_OUTPUT vs_main( VS_INPUT In ) 
{
    VS_OUTPUT Out;

    float4 Position = mul(In.Position,  matWorldViewProj);
    Out.PosWorld = Position; 
    
    //==========Texture Translations=============================
    // translate texture origin to the center    
    float2 rotated_tex = In.TexCoord0 -=0.5;
    
    // rotate
    rotated_tex = mul(In.TexCoord0.xy  ,matEffect1); 
    
    // translate texture back to 0..1 range
    rotated_tex += 0.5;
    
    // do scaling and shift after the rotation operation
    
    // scale/tile factor for our texture
    rotated_tex *= vecSkill41.x;
    
    // shift the texture coordinates
    // adjust as needed by choosing which xy component to influence
    // and by either +/- sign.
    rotated_tex.y += vecSkill41.y;
    //===========================================================
       
    Out.TexCoord0.xy = rotated_tex.xy; // pass rotated texture coords to pixel shader
    
    // a trick to get the most use out of one texture coordinate
    Out.TexCoord0.zw = In.TexCoord0.xy;// pass unrotated texture coords thru
       
    return Out;
}



// ----------------------------------------------------------------
//  pixelshader 
// ----------------------------------------------------------------
float4 ps_main(VS_OUTPUT In) : COLOR
{
             
    float4 oTex1 = tex2D(sTex,In.TexCoord0.zw); // unrotated (is that a word?) tex
    
    float4 oTex2 = tex2D(sTex, In.TexCoord0.xy); // rotated tex 
    
    // assemble our final output color
    // in this case we lerp the rotated tex with an unroted version
    // just an example for experimenting
    float4 finalcolor = lerp (oTex1, oTex2, 0.7);
    
    return finalcolor;
}


// ----------------------------------------------------------------
//  Technique
// ----------------------------------------------------------------
Technique tech1 
{
    Pass One
      {
      	vertexshader = compile vs_2_0 vs_main();
         pixelshader = compile ps_2_0 ps_main();
      }

     
}


";

}

action mtl_texrot () {
	

	my.material = mtlEffect;
	
	// texture 0-360 degrees in CW rotation.
	// used in mtlEffect_init
	tex_rotation_in_degrees = 100;  
	
	// pass scaling/tiling factor to shader vecSkill41.x
	my.skill41 = floatv(2); 
	
	//  adjust scrolling rate via slider
	var tmp =20;
	var time_smooth = 0.666;
	
	// the var fac_speed_adj is from <panel_func.h> via the slider
	while(1){
	tmp+=  time_step/fac_speed_adj;
	my.skill42 = floatv(tmp); // pass scrolling time to shader vecSkill41.y
	wait(1);}		
	   
}



Have fun!!
Posted By: Steempipe

Re: [SUB] Rotating a texture in a pixel shader - 01/19/16 21:11

FYI: I've learned that when applying normalmapping to a rotated texture, it is required to multiply the normalmap coords with the INVERSE of the rotated matrix to get correct lighting.
As shown here.
Interesting.

Posted By: 20BN

Re: [SUB] Rotating a texture in a pixel shader - 01/20/16 15:31

@ Steempipe
Thanks your code!

I wrote very basic lite-c MDL7 SKIN# effects system. It's play sequence textures (ex: fire_4x4.png = 16 frame pictures) on effect model, support TexturePacker and XML data. But the FPS is very low in my game (testing 10+ entity), this is a big problem. But in UNITY easily use shader editor support sequence textures, mesh vertex alpha, uv moving, texture scale, RGB color blend etc.

I'm shader noob, but I hope some like shader can be achieved in 3DGS.
(need your help free or non free support)

Thanks again!
Posted By: Steempipe

Re: [SUB] Rotating a texture in a pixel shader - 01/22/16 08:57

Originally Posted By: 20BN
@ Steempipe
Thanks your code!

I wrote very basic lite-c MDL7 SKIN# effects system. It's play sequence textures (ex: fire_4x4.png = 16 frame pictures) on effect model, support TexturePacker and XML data. But the FPS is very low in my game (testing 10+ entity), this is a big problem. But in UNITY easily use shader editor support sequence textures, mesh vertex alpha, uv moving, texture scale, RGB color blend etc.

I'm shader noob, but I hope some like shader can be achieved in 3DGS.
(need your help free or non free support)

Thanks again!


Glad you can use it... Sent you a PM
Posted By: Steempipe

Re: [SUB] Rotating a texture in a pixel shader - 02/10/16 20:24

Here's the complete project for rotating and adding a normalmap to the rotated texture.

Matrix Texture Rotation and Normalmapping

Key points:
1). If you rotate a texture, you _must_ apply normal mapping to the inverse of that rotation to get true NdotL.
2). Project utilizes the engines matEffect.

Have fun!
© 2024 lite-C Forums