Jump to content

Refraction/Distortion?


LoLJester

Recommended Posts

You have to consider that from a gameplay standpoint all of those solutions are not good, since when the "cloaked" player is visible in some way, he is visible and if he is not visible good, it encourages people cheating, through graphics settings.

Best method may be to just make the player invisible when cloaked and occasionally add particle effects, like smoke, so it helps indicating that there is a cloaked player, but he is not physically visible.

Link to comment
Share on other sites

Let me share my try at this subject.

What I did is to use a PostFX to copy the backbuffer before the TransparentObj RenderBin into a NamedTexture and use that NamedTexture as a texture sampler for a Custom Material. That Custom material just distorted a bit so it's not really refraction.


If you have a custom RenderBin for those cloacking objects you should change the renderBin for the PostFX to that one.


Note that the use of $backbuffer can cause issues if you use various viewports like with VR.


----------------------------------------------

First we create the PostFX (and exec it somewhere):

 

singleton ShaderData( PreTranspCopy_Shader )
{   
  DXVertexShaderFile 	= "shaders/common/postFx/postFxV.hlsl";
  DXPixelShaderFile 	= "shaders/common/postFx/passthruP.hlsl";

  OGLVertexShaderFile  = "shaders/common/postFx/gl/postFxV.glsl";
  OGLPixelShaderFile   = "shaders/common/postFx/gl/passthruP.glsl";

  samplerNames[0] = "$inputTex";

  pixVersion = 2.0;
};

singleton GFXStateBlockData( PreTranspCopy_stateblock )
{
  zDefined = true;
  zEnable = false;
  zWriteEnable = false;

  samplersDefined = true;
  samplerStates[0] = SamplerClampPoint;
};

singleton PostEffect( PreTranspCopy )
{
  // This PostEffect is used by 'AL_FormatToken' directly. It is never added to
  // the PostEffectManager. Do not call enable() on it.
  isEnabled = true;
  renderTime = "PFXBeforeBin";
  renderBin = "ObjTranslucentBin";      

  shader = PreTranspCopy_Shader;
  stateBlock = PreTranspCopy_stateblock;

  texture[0] = "$backbuffer";
  target = "#PreRenderTranslucent";
};

 

Then the material. For this example I'll just create a new material in the material.cs of the soldier so I can skin it directly.

I don't have access to a computer with glsl compability so those are up to you.

Add this at the end of that material.cs:

 

singleton ShaderData( predatorTextureShader )
{
  DXVertexShaderFile = "shaders/common/z_predatorV.hlsl";
  DXPixelShaderFile 	= "shaders/common/z_predatorP.hlsl";
  samplerNames[0] = "$diffuseMap";
  pixVersion =2.0;
};

singleton CustomMaterial(Mat_Predator_Soldier_Main : Mat_Soldier_Main)
{
  mapTo = "Predator_Soldier_Main";
  translucent = true;
  shader = predatorTextureShader;
  sampler["diffuseMap"] = "#PreRenderTranslucent";
};

 

You may want to use a different CustomMaterial for each object so the woobly effect is not sincronized:


singleton CustomMaterial(Mat_Predator2_Soldier_Main : Mat_Predator_Soldier_Main) {};

singleton CustomMaterial(Mat_Predator3_Soldier_Main : Mat_Predator_Soldier_Main) {};

...


Finally I added the two shader (hlsl) files at shaders/common.

(Remember they must be plain ANSI files.)


----------z_predatorV.hlsl---------

struct VertToPixOut
{
  float4 hpos       : POSITION;
  float4 screen        : TEXCOORD1;
};

struct VertToPixIn
{
  float4 hpos       : POSITION;
};

uniform float4x4 modelview;

VertToPixOut main( VertToPixIn In)
{
  VertToPixOut Out;
  Out.hpos = mul( modelview, In.hpos);

  Out.screen = Out.hpos;

  return Out;
}

 

--------------z_predatorP.hlsl-----------

The distortion effect is in here.

You should, of course, use another function for the distortion. This one is just a basic example.

struct datainput {
  float4 screenCoord : TEXCOORD1;
};

//diffuseMap is defined in the CustomMaterial and its ShaderData
uniform sampler2D diffuseMap        : register(S0);

//accumTime is an engine variable. It's kind of the time of the material.
//Use it to move things in time
uniform float     accumTime;

float4 main( datainput IN ) : COLOR0
{
  //texture to screen
  float2 screenpos = 0.5+IN.screenCoord.xy/2*float2(1,-1)/IN.screenCoord.w;

  //wooble effect example
  float2 repeat = (1 - 1/200) - abs(sin(accumTime*3)/200);
  screenpos = screenpos * repeat;


  float4 colour_exit = tex2D( diffuseMap, screenpos);

  //here you can modify colourexit if needed

  return colour_exit;
} 

 


After these changes just do


%player.setSkinName("Predator")

(%player.setSkinName("Predator2"), etc)


Change %player with the ID of the soldier to re-skin like (LocalClientConnection.player).setSkinName("Predator")

Link to comment
Share on other sites

  • 2 months later...

After much searching for shadows in customMaterials and shaders ... turns out I should have been looking for customMaterials in shadows ... :roll:


lighting/shadowMap/shadowMatHook.cpp

 

void ShadowMaterialHook::init( BaseMatInstance *inMat )
{
//...
   // Do instancing in shadows if we can.
   if ( inFeatures.hasFeature( MFT_UseInstancing ) )
      features.addFeature( MFT_UseInstancing );
 
   Material *shadowMat = (Material*)inMat->getMaterial();
   if ( dynamic_cast( shadowMat ) )
   {
      // This is a custom material... who knows what it really does, but
      // if it wasn't already filtered out of the shadow render then just
      // give it some default depth out material.
      //shadowMat = MATMGR->getMaterialDefinitionByName( "AL_DefaultShadowMaterial" );//<<<<<<<<<
   }
 
   // By default we want to disable some states
   // that the material might enable for us.
//...

 

So ends up being a standard Torque concept of "who knows what the hell this for, let's just do something with it" :lol:

Link to comment
Share on other sites

On @JeffR advice I added:

mCastShadows = true;//yorks in (to customMaterialDefinition.cpp)

bool mCastShadows;//yorks in (to customMaterialDefinition.h)

virtual bool castsShadows() const { return mCastShadows; }//yorks in (to customMaterialDefinition.h)


Okay, so what's happening now is this:

 

// This is a custom material... who knows what it really does, but

// if it wasn't already filtered out of the shadow render then just

// give it some default depth out material.

 

So now translucent gets filtered out and no shadows appear, and non-translucent customMaterials cast shadows - regardless of what castShadows=bool setting the texture material actually has.


A more useful addition would be to get the status of castShadows and then force "shadowMat = MATMGR->getMaterialDefinitionByName( "AL_DefaultShadowMaterial" );" whether translucent or not. Though I'm not sure how to do that ... :|

Link to comment
Share on other sites

Let me share my try at this subject.

What I did is to use a PostFX to copy the backbuffer before the TransparentObj RenderBin into a NamedTexture and use that NamedTexture as a texture sampler for a Custom Material. That Custom material just distorted a bit so it's not really refraction.

should be able to also snag https://github.com/GarageGames/Torque3D/blob/development/Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs#L85

which will let you grab

https://github.com/GarageGames/Torque3D/blob/development/Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl#L33

+ https://github.com/GarageGames/Torque3D/blob/development/Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl#L216-L218

for the variables to use to determine which way to 'bend' the texture lookup if you're not using translucency itself.


edit: a shadergen result file with normals calcs to pull from

//*****************************************************************************
// Torque -- HLSL procedural shader
//*****************************************************************************

// Dependencies:
#include "shaders/common/torque.hlsl"

// Features:
// Vert Position
// Render Target Output = 0.0, output mask b
// Base Texture
// Diffuse Color
// Deferred Shading: Specular Map
// Deferred Shading: Mat Info Flags
// Bumpmap [Deferred]
// Reflect Cube
// Eye Space Depth (Out)
// Visibility
// GBuffer Conditioner
// BC5nm
// Deferred Material

struct VertData
{
  float3 position        : POSITION;
  float tangentW        : TEXCOORD3;
  float3 normal          : NORMAL;
  float3 T               : TANGENT;
  float2 texCoord        : TEXCOORD0;
};


struct ConnectData
{
  float4 hpos            : SV_Position;
  float2 out_texCoord    : TEXCOORD0;
  float3x3 outViewToTangent : TEXCOORD1;
  float3 reflectVec      : TEXCOORD4;
  float4 wsEyeVec        : TEXCOORD5;
};


//-----------------------------------------------------------------------------
// Main
//-----------------------------------------------------------------------------
ConnectData main( VertData IN,
                 uniform float4x4 modelview       : register(C0),
                 uniform float4x4 viewToObj       : register(C4),
                 uniform float4x4 objTrans        : register(C8),
                 uniform float3   eyePosWorld     : register(C12)
)
{
  ConnectData OUT;

  // Vert Position
  OUT.hpos = mul(modelview, float4(IN.position.xyz,1));

  // Render Target Output = 0.0, output mask b

  // Base Texture
  OUT.out_texCoord = (float2)IN.texCoord;

  // Diffuse Color

  // Deferred Shading: Specular Map

  // Deferred Shading: Mat Info Flags

  // Bumpmap [Deferred]
  float3x3 objToTangentSpace;
  objToTangentSpace[0] = IN.T;
  objToTangentSpace[1] = cross( IN.T, normalize(IN.normal) ) * IN.tangentW;
  objToTangentSpace[2] = normalize(IN.normal);
  float3x3 viewToTangent = mul( objToTangentSpace, (float3x3)viewToObj );
  OUT.outViewToTangent = viewToTangent;

  // Reflect Cube
  float3 cubeVertPos = mul(objTrans, float4(IN.position,1)).xyz;
  float3 cubeNormal = ( mul( (objTrans),  float4(IN.normal, 0) ) ).xyz;
  cubeNormal = bool(length(cubeNormal)) ? normalize(cubeNormal) : cubeNormal;
  float3 eyeToVert = cubeVertPos - eyePosWorld;
  OUT.reflectVec = reflect(eyeToVert, cubeNormal);

  // Eye Space Depth (Out)
  float3 depthPos = mul( objTrans, float4( IN.position.xyz, 1 ) ).xyz;
  OUT.wsEyeVec = float4( depthPos.xyz - eyePosWorld, 1 );

  // Visibility

  // GBuffer Conditioner

  // BC5nm

  // Deferred Material

  return OUT;
}

//*****************************************************************************
// Torque -- HLSL procedural shader
//*****************************************************************************

// Dependencies:
#include "shaders/common/torque.hlsl"

// Features:
// Vert Position
// Render Target Output = 0.0, output mask b
// Base Texture
// Diffuse Color
// Deferred Shading: Specular Map
// Deferred Shading: Mat Info Flags
// Bumpmap [Deferred]
// Reflect Cube
// Eye Space Depth (Out)
// Visibility
// GBuffer Conditioner
// BC5nm
// Deferred Material

struct ConnectData
{
  float4 vpos            : SV_Position;
  float2 texCoord        : TEXCOORD0;
  float3x3 viewToTangent   : TEXCOORD1;
  float3 reflectVec      : TEXCOORD4;
  float4 wsEyeVec        : TEXCOORD5;
};


struct Fragout
{
  float4 col : SV_Target0;
  float4 col1 : SV_Target1;
  float4 col2 : SV_Target2;
  float4 col3 : SV_Target3;
};


//-----------------------------------------------------------------------------
// Main
//-----------------------------------------------------------------------------
Fragout main( ConnectData IN,
             uniform SamplerState diffuseMap      : register(S0),
             uniform Texture2D diffuseMapTex   : register(T0),
             uniform float4    diffuseMaterialColor : register(C0),
             uniform SamplerState specularMap     : register(S1),
             uniform Texture2D specularMapTex  : register(T1),
             uniform float     matInfoFlags    : register(C1),
             uniform SamplerState bumpMap         : register(S2),
             uniform Texture2D bumpMapTex      : register(T2),
             uniform SamplerState cubeMap         : register(S3),
             uniform TextureCube cubeMapTex      : register(T3),
             uniform float     cubeMips        : register(C2),
             uniform float3    vEye            : register(C4),
             uniform float4    oneOverFarplane : register(C5),
             uniform float     visibility      : register(C3)
)
{
  Fragout OUT;

  // Vert Position

  // Render Target Output = 0.0, output mask b
  OUT.col3 = 0.00001;

  // Base Texture
  float4 diffuseColor = diffuseMapTex.Sample(diffuseMap, IN.texCoord);
  OUT.col1 = diffuseColor;

  // Diffuse Color
  OUT.col1 *= diffuseMaterialColor;

  // Deferred Shading: Specular Map
  float smoothness =    specularMapTex.Sample(specularMap, IN.texCoord).r;
  float metalness =    specularMapTex.Sample(specularMap, IN.texCoord).b;
  float4 specularColor =    specularMapTex.Sample(specularMap, IN.texCoord).ggga;
  OUT.col2.bga = float3(smoothness,specularColor.g,metalness);

  // Deferred Shading: Mat Info Flags
  OUT.col2.r = matInfoFlags;

  // Bumpmap [Deferred]
  float4 bumpNormal = float4( bumpMapTex.Sample(bumpMap, IN.texCoord).rg * 2.0 - 1.0, 0.0, 0.0 ); // bc5nm
  bumpNormal.z = sqrt( 1.0 - dot( bumpNormal.xy, bumpNormal.xy ) ); // bc5nm
  half3 gbNormal = (half3)mul( bumpNormal.xyz, IN.viewToTangent );

  // Reflect Cube
  OUT.col3 = cubeMapTex.SampleLevel( cubeMap, float3(IN.reflectVec).rgb, min((1.0 - smoothness)*cubeMips + 1.0, cubeMips));

  // Eye Space Depth (Out)
#ifndef CUBE_SHADOW_MAP
  float eyeSpaceDepth = dot(vEye, (IN.wsEyeVec.xyz / IN.wsEyeVec.w));
#else
  float eyeSpaceDepth = length( IN.wsEyeVec.xyz / IN.wsEyeVec.w ) * oneOverFarplane.x;
#endif

  // Visibility
  fizzle( IN.vpos.xy, visibility );

  // GBuffer Conditioner
  float4 normal_depth = float4(normalize(gbNormal), eyeSpaceDepth);

  // output buffer format: GFXFormatR16G16B16A16F
  // g-buffer conditioner: float4(normal.X, normal.Y, depth Hi, depth Lo)
  float4 _gbConditionedOutput = float4(sqrt(half(2.0/(1.0 - normal_depth.y))) * half2(normal_depth.xz), 0.0, normal_depth.a);

  // Encode depth into hi/lo
  float2 _tempDepth = frac(normal_depth.a * float2(1.0, 65535.0));
  _gbConditionedOutput.zw = _tempDepth.xy - _tempDepth.yy * float2(1.0/65535.0, 0.0);

  OUT.col = _gbConditionedOutput;

  // BC5nm

  // Deferred Material


  return OUT;
}

Link to comment
Share on other sites

  • 2 weeks later...

Righty, had a bit of a look at shaders hlsl code ... and it's gibberish to me :roll: but having said that I still managed to get some cool improvements! :mrgreen:


RDZRU7PpILQ


Two types of distortion material in the video, the first has translucency the second doesn not - hence the shadow, and also this creates more distortion for reasons ...


Bascially I added a swirly distort effect to screenpos x and y using y and x and some offsets.


So the Pixel shader now looks like this:

 

struct datainput 
{
   float4 screenCoord : TEXCOORD1;
};
 
//diffuseMap is defined in the CustomMaterial and its ShaderData
uniform sampler2D diffuseMap        : register(S0);
 
//accumTime is an engine variable. It's kind of the time of the material.
//Use it to move things in time
uniform float     accumTime;
 
float4 main( datainput IN ) : COLOR0
{
 
   //texture to screen
   float2 screenpos = 0.5+IN.screenCoord.xy/2*float2(1,-1)/IN.screenCoord.w;
 
   	float2 wobble;
	float speed = 0.03;
	float magnify = 1.0;
 
	wobble.y = magnify + sin(IN.screenCoord.x + accumTime) * speed;
    wobble.x = magnify + sin(IN.screenCoord.y + accumTime) * speed;
 
	//yorks abs seems to give more rotation but splits it into visible cells
    //wobble.y = magnify + abs(sin(IN.screenCoord.x + accumTime) * speed);
    //wobble.x = magnify + abs(sin(IN.screenCoord.y + accumTime) * speed);
 
	screenpos = screenpos * wobble;
 
    float4 colour_exit = tex2D(diffuseMap, screenpos);
 
   return colour_exit;
}

 

Initially I did abs(sin like the original wobble script but it dissected the area into noticeable cells which then rotated against each other. Dropping abs gives a more integrated flow.


And the Vertex Shader has a very minor change to increase the distortion somewhat:

 

struct VertToPixOut
{
   float4 hpos       : POSITION;
   float4 screen        : TEXCOORD1;
};
 
struct VertToPixIn
{
   float4 hpos       : POSITION;
};
 
uniform float4x4 modelview;
 
VertToPixOut main( VertToPixIn In)
{
   VertToPixOut Out;
   Out.hpos = mul( modelview, In.hpos);
 
   //Out.screen = Out.hpos;
   Out.screen = Out.hpos * 1.5;//yorks bump it up a bit but not too much
 
   return Out;
}

 

I'd still like a couple of extra things ... though I'm not entirely sure what ... perhaps make the material slightly darker like introduce a color float of 0.9 or something. Really I'm trying for the old Doom pink demons which had invisible types but you could still see them if if you were looking. Having said that I haven't tested this with an enemy attack on the player so not sure how well it'd currently show up attacking/following in game.

Link to comment
Share on other sites

Those textures are looking really amazing.


I'm not sure you'll experience this but let me share some issues I had while playing with these kind of transparencies:


a) Using #prepass works only for Advance Lightning. But that's fine as very few users have the kind of ancient computers* that can't handle it.

b) Be careful with the limits of the screen. For me the texture wraps around so in these limits a wobble can show the texture of the other side of the screen. It's more noticeable if there is a huge contrast of colours between both sides.

http://i.imgur.com/yzXE5lm.png




*just me, probably.

Link to comment
Share on other sites

@irei1as I tested this in basic lighting too and it seems to work fine - though as you say BL is pretty redundant these days.

I did notice screen-wrapping as well when adding it to a static object and moving it to the edge of the screen - but only on the "Y axis" (?), so 0 0 0 in worldspace. Horizontal seems okay for some reason ... :|


Not sure what to do about that though - though thankfully it's not going to affect what I want it for too much as it might help the player see invisible enemies when they approach.


One more thing I'd like to do, is to add a colour shade/tint/darken to it but don't know. I noticed you commented about modifying colour_exit:

//here you can modify colourexit if needed
 
   return colour_exit;

 

I tried adding an rgba to colour_exit before the return and got the colouring - but lost all the transparency and wobble :(


Any hints for how I should be doing this? :?:

Link to comment
Share on other sites

Aha! Was doing it wrong - probably still doing it wrong but at least I have a result.


C3XE3BYXAAAVMss.jpg


To pixel shader:

//...
    float4 colour_exit = tex2D(diffuseMap, screenpos);
 
	//here you can modify colourexit if needed
   	float4 color;//new color value
 
	//positive = more white, negative = more black
	color = float4(-0.1, -0.1, -0.1, 1.0);//rgba
 
	colour_exit = colour_exit.rgba + color;//add color to colour_exit rgba
 
	return colour_exit;
}

 

There's probably a better way of doing use this using diffuseColor or something but I'm not sure how that works ...

Link to comment
Share on other sites

Hang on, maybe lerp is the better bet here:

 

//...
    float4 colour_exit = tex2D(diffuseMap, screenpos);
 
	//here you can modify colourexit if needed
   	float4 color;
 
	color = float4(0.2, 0.2, 0.2, 1.0);//0.2 is dark
 
	colour_exit = lerp(colour_exit, color, 0.3);//1.0 would be solid matt colour so 0.3 gives color and transparency
 
	return colour_exit;
}

 

Code looks less hacky at least ...


C3XNTBIWEAQ6wGt.jpg

Link to comment
Share on other sites

I'm still having problems using #prepass to get any results in my old computer.

But it just may be that it doesn't work in the old code I'm using and it's fixed in the new versions.

An example of how to use it will be helpful so I can be sure where I'm wrong. Thanks.



Changing colours is a bit complex. Let me share a few experiments of how I modified colour_exit:


Plain black and white with a colour multiplication:

(...)
float bn_base = (colour_exit.x + colour_exit.y + colour_exit.z) / 3.0;

//red example, change rgb values as needed
float3 mult_colour = float3(1.0, 0.0, 0.0);

colour_exit = float4(mult_colour.x * bn_base, mult_colour.y * bn_base, mult_colour.y * bn_base, colour_exit.a);
return colour_exit;
}

 

The same but with luminance black and white:

(...)
float bn_base = (0.2126 * colour_exit.x + 0.7152 * colour_exit.y + 0.0722 * colour_exit.z);

//red example, change rgb values as needed
float3 mult_colour = float3(1.0, 0.0, 0.0);

colour_exit = float4(mult_colour.x * bn_base, mult_colour.y * bn_base, mult_colour.y * bn_base, colour_exit.a);
return colour_exit;
}

 

Sepia tone (copy/paste from somewhere):

(...)
float3 sepia;
sepia.r = dot(colour_exit.rgb, float3(0.393, 0.769, 0.189));
sepia.g = dot(colour_exit.rgb, float3(0.349, 0.686, 0.168));   
sepia.b = dot(colour_exit.rgb, float3(0.272, 0.534, 0.131));
colour_exit = float4(sepia.xyz, colour_exit.a);
return colour_exit;
}

 

Direct light multiply:

(...)
//[0,1] range for darker and over 1 to make them more white.
//Note: return clamps the colour
float light_value = 0.5;

colour_exit = float4(colour_exit.xyz * light_value, colour_exit.a);
return colour_exit;
}

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...