Game Development Community

Example of a "Refract" Shader...

by Jack Stone · in Torque 3D Professional · 07/14/2012 (5:39 pm) · 4 replies

Hello,

I have been spending some time looking at Shaders recently, and I am currently trying to produce a "predator" style cloaking shader. Based on my research, this would be accomplished with a refraction effect.

I can see several references to refraction in the code, such as in the water shader, but never by itself, and it's proving difficult to isolate just the parts I need. The closest I have come is the following code (fragment) in a pixel shader, taken mostly from waterBasicP.hlsl:

float3 bumpNorm = tex2D( bumpMap, IN.texCoord ) * 2.0 - 1.0;
float4 distortPos = IN.hpos2;
distortPos.xy += bumpNorm.xy  * 2;   

 float4 refractColor = hdrDecode( tex2Dproj( refractMap, distortPos ) );   
OUT.col = refractColor;
   return OUT;

This produces something like what I want, but I still get strange colours appearing at certain viewing angles, and I have no idea where they are coming from.

All of the examples I can find online seem to use an intrinsic function, refract(), but I haven't had much luck with this either.

Does anyone know where I can find a very basic 4 or 5 line refract example I could play around with?

Thanks.

#1
07/14/2012 (7:44 pm)
I hope someone has an answer to this as well. I was wanting to use a shader like this for hot objects like a candles or fire, and desert areas.
#2
07/15/2012 (6:48 am)
For every texel calculate your vertex screen space coords, then sample your normal map vectors,generate some little shift and re-sample from backbuff,this would produce the "predator effect".
I believe your code should look like this:

float shift = 0.01;
float2 refract = tex2D(normalMap,IN.uv0);
refract = ((refract * 2.0) - 1.0) * shift;
float4 diffuse = tex2D( backBuff, screen_space_coords + refract);

You don't need to generate a refraction vector since you're using a normal map for that and you would bake the refraction mapping there.
#3
07/16/2012 (6:53 am)
Thanks Ivan, that's a big help!

I'm not sure if I am implementing this correctly though, my pixel shader looks like this:

#include "torque.hlsl"    

#define IN_HLSL
#include "shdrConsts.h"


//-----------------------------------------------------------------------------
// Structures                                                                  
//-----------------------------------------------------------------------------
struct ConnectData
{
   float2 texCoord        : TEXCOORD0;

};


struct Fragout
{
   float4 col : COLOR0;
};


//-----------------------------------------------------------------------------
// Main                                                                        
//-----------------------------------------------------------------------------
Fragout main( ConnectData IN,

uniform sampler      refractBuff : register( S0 ),
uniform sampler      normalMap : register( S1 )
)
{
   Fragout OUT;

float shift = 0.01;  
    float2 refract = tex2D(normalMap,IN.texCoord);  
    refract = ((refract * 2.0) - 1.0) * shift;  
    float4 diffuse = tex2D( refractBuff, IN.texCoord + refract);  
    
    OUT.col = diffuse;
    
   return OUT;
   
}

What exactly are the "screen_space_coords" that I use?

I am just seeing a plain white texture at the moment...
#4
07/17/2012 (1:16 am)
In your vertex shader,after transformation, pass float3 ScreenPosition as varying:
ScreenPosition = out_Position.xyw;

In your pixel shader:
float2 sspos = ScreenPosition.xy / ScreenPosition.z;

Then sample using pos:
float4 diffuse = tex2D( backBuff, sspos + refract);