|
[SUB] Rotating a texture in a pixel shader
#457383
01/16/16 05:22
01/16/16 05:22
|
Joined: Dec 2003
Posts: 1,097 Maryland, USA
Steempipe
OP
Serious User
|
OP
Serious User
Joined: Dec 2003
Posts: 1,097
Maryland, USA
|
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
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;
}
|
|
|
Re: [SUB] Rotating a texture in a pixel shader
[Re: txesmi]
#457412
01/17/16 15:18
01/17/16 15:18
|
Joined: Dec 2003
Posts: 1,097 Maryland, USA
Steempipe
OP
Serious User
|
OP
Serious User
Joined: Dec 2003
Posts: 1,097
Maryland, USA
|
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 //============================================================================= // 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; }
|
|
|
Re: [SUB] Rotating a texture in a pixel shader
[Re: 20BN]
#457413
01/17/16 15:19
01/17/16 15:19
|
Joined: Dec 2003
Posts: 1,097 Maryland, USA
Steempipe
OP
Serious User
|
OP
Serious User
Joined: Dec 2003
Posts: 1,097
Maryland, USA
|
@ 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.
// 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!!
Last edited by Steempipe; 01/17/16 20:05. Reason: changes as requested
|
|
|
Re: [SUB] Rotating a texture in a pixel shader
[Re: Steempipe]
#457496
01/19/16 21:11
01/19/16 21:11
|
Joined: Dec 2003
Posts: 1,097 Maryland, USA
Steempipe
OP
Serious User
|
OP
Serious User
Joined: Dec 2003
Posts: 1,097
Maryland, USA
|
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.
|
|
|
Re: [SUB] Rotating a texture in a pixel shader
[Re: Steempipe]
#457514
01/20/16 15:31
01/20/16 15:31
|
Joined: Feb 2003
Posts: 146 RP China
20BN
Member
|
Member
Joined: Feb 2003
Posts: 146
RP China
|
@ 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!
|
|
|
Re: [SUB] Rotating a texture in a pixel shader
[Re: 20BN]
#457553
01/22/16 08:57
01/22/16 08:57
|
Joined: Dec 2003
Posts: 1,097 Maryland, USA
Steempipe
OP
Serious User
|
OP
Serious User
Joined: Dec 2003
Posts: 1,097
Maryland, USA
|
@ 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
|
|
|
Re: [SUB] Rotating a texture in a pixel shader
[Re: Steempipe]
#457983
02/10/16 20:24
02/10/16 20:24
|
Joined: Dec 2003
Posts: 1,097 Maryland, USA
Steempipe
OP
Serious User
|
OP
Serious User
Joined: Dec 2003
Posts: 1,097
Maryland, USA
|
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!
Last edited by Steempipe; 02/10/16 20:24.
|
|
|
|