Jump to content
  • Advertisement
Sign in to follow this  
BattleCollie

Storing motion vectors in 8 bit RGBAs

This topic is 3166 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

WARNING: I'm really new to HLSL so this is going to look hacky. So I was reading the Killzone 2 document about deferred rendering and notice they're storing screen space motion vectors inside a 8 bit R and G. I'm curious about any details of how they're doing this because it seems no matter how I set it up it looks... well.. wrong. Can anyone shed some light on if there's some trick I'm missing on storing the motion vectors? Also I'm computing the space in the pixel shader because it seemed that when I did it in the vertex shader the interpolation of motion seemed really off. I've already confirmed that gWorldViewProj and gPrevWorldViewProj are correct so I'm not sure where I've gone wrong. Someone mentioned something in a post about leaving the coordinates in eye space and dividing by w in the pixel shader but my attempts at that pretty much had the same results. Tips? Scoldings?
Quote:
/////////////////////////////////////////////// // SAS Parameters /////////////////////////////////////////////// #ifdef DEBUG_SHADER #ifndef SASSCRIPT #define SASSCRIPT float Script : STANDARDSGLOBAL < string UIWidget = "none"; string ScriptClass = "scene"; string ScriptOrder = "standard"; string ScriptOutput = "color"; string Script = "Technique=Technique?gbuffer_normalmap;"; > = 0.8; #endif #endif //////////////////////////////////////////////// // Includes //////////////////////////////////////////////// #include "shared.fx" //////////////////////////////////////////////// // FXComposer Debug Variables //////////////////////////////////////////////// #ifdef DEBUG_SHADER Texture2D gBaseTexture; Texture2D gNormalTexture; Texture2D gSpecularTexture; #endif //////////////////////////////////////////////// // Input/Output Declarations //////////////////////////////////////////////// struct mrtvs_out { float4 position : SV_POSITION0; float2 texcoord : TEXCOORD0; float3 normal : TEXCOORD1; float3 tangent : TEXCOORD2; float3 bitangent : TEXCOORD3; float2 depth : TEXCOORD4; }; struct mrtps_out { float4 gbuffer0 : SV_Target0; float4 gbuffer1 : SV_Target1; float4 gbuffer2 : SV_Target2; float4 gbuffer3 : SV_Target3; }; //////////////////////////////////////////////// // Gbuffer Shaders /////////////////////////////////////////////// mrtvs_out mrtVS(float4 position : POSITION, float3 normal : NORMAL, float3 tangent : TANGENT, float3 bitangent : BINORMAL, float2 texcoord : TEXCOORD0 ) { mrtvs_out OUT; // Projected position OUT.position = mul(position, gWorldViewProj); // Normal in world space OUT.normal = normalize(mul(normal, gWorld)); // Tangents in world space OUT.tangent = normalize(mul(tangent, gWorld)); OUT.bitangent = normalize(mul(bitangent, gWorld)); // Texture coordinates OUT.texcoord = texcoord; // Depth OUT.depth.xy = OUT.position.zw; return OUT; } mrtps_out mrtPS(mrtvs_out IN) : SV_Target { mrtps_out OUT; // GBUFFER0: | DiffuseR | DiffuseG | DiffuseB | Stencil | // GBUFFER1: | NormalX | NormalY | NormalZ | SpecularPower | // GBUFFER2: | MotionX | MotionY | | SpecularIntensity | // GBUFFER3: | UNUSED | // Color texture (TEXTURE0) ///////////////////////////////////////// #ifdef DEBUG_SHADER OUT.gbuffer0 = gBaseTexture.Sample(samLinear, IN.texcoord); if(OUT.gbuffer0.a == 0.0) #endif OUT.gbuffer0 = gTexture0.Sample(samLinear, IN.texcoord); // Stencil OUT.gbuffer0.a = 1.0; // Normal texture (TEXTURE1) /////////////////////////////////////// float4 normmap; #ifdef DEBUG_SHADER normmap = gNormalTexture.Sample(samLinear, IN.texcoord); if(normmap.a == 0.0) #endif normmap = gTexture1.Sample(samLinear, IN.texcoord); // TBN matrix. Calculated in here because then tangents, // bitangent, and normal are interpolated by PS then. float3x3 tbnm = float3x3(IN.tangent, IN.bitangent, IN.normal); // Convert from 0 to 1 image space to -1 to 1 normal space. float3 p = (2 * normmap.rgb - 1); // Flip Y. Why? Seems to look right. p.y = -p.y; // Transform normal map into world space and store OUT.gbuffer1.xyz = 0.5f * (mul(p, tbnm) + 1.0f); // specular power OUT.gbuffer1.w = log2(gMatfPower) / 10.5; // (TEXTURE2) /////////////////////////////////////////////////////// float4 specular; #ifdef DEBUG_SHADER specular = gSpecularTexture.Sample(samLinear, IN.texcoord); if(specular.a == 0.0) #endif specular = gTexture2.Sample(samLinear, IN.texcoord); OUT.gbuffer2.a = specular.r; // Reconstruct world space position from depth. // Has to be done in here to get it per pixel for // previous position. float2 texcoord = float2(IN.position.x * gAspect.x, IN.position.y * gAspect.y); float depth = IN.depth.x/IN.depth.y; float4 position; position.x = texcoord.x * 2.0f - 1.0f; position.y = -(texcoord.y * 2.0f - 1.0f); position.z = depth; position.w = 1.0f; position = mul(position, gWorldViewProjI); //position /= position.w; // Find previous position float4 cposition = mul(position, gWorldViewProj); cposition /= cposition.w; float4 pposition = mul(position, gPrevWorldViewProj); pposition /= pposition.w; // Find velocity float2 velocity = (cposition - pposition); // Have to multiply by some blur factor to // actually see anything happen? WTF. // velocity *= 200; // Move from [-1, 1] to [0, 2] to [0, 1] OUT.gbuffer2.rg = (velocity + 1.0f) * 0.5f; // (TEXTURE3) /////////////////////////////////////////////////////// OUT.gbuffer3 = float4(0.0, 0.0, 1.0, 0.0); return OUT; } /////////////////////////////////////////////// // Techniques /////////////////////////////////////////////// technique10 gbuffer_normalmap { pass P0 { SetVertexShader(CompileShader(vs_4_0, mrtVS())); SetGeometryShader(NULL ); SetPixelShader(CompileShader(ps_4_0, mrtPS())); SetBlendState(DisableBlend, float4(0.0f, 0.0f, 0.0f, 0.0f), 0xFFFFFFFF); } }

Share this post


Link to post
Share on other sites
Advertisement
Neeeevermind... What has two thumbs and dumb as a brick. Me. I thought we'd met.

I guess motion blur isn't going to show much velocity between frames when you're running at 1500 FPS. I did a little cleaning on the code though which seems nicer than what I was doing previously.

Quote:

///////////////////////////////////////////////
// SAS Parameters
///////////////////////////////////////////////
#ifdef DEBUG_SHADER
#ifndef SASSCRIPT
#define SASSCRIPT

float Script : STANDARDSGLOBAL <
string UIWidget = "none";
string ScriptClass = "scene";
string ScriptOrder = "standard";
string ScriptOutput = "color";
string Script = "Technique=Technique?gbuffer_normalmap;";
> = 0.8;

#endif
#endif

////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////
#include "shared.fx"

////////////////////////////////////////////////
// FXComposer Debug Variables
////////////////////////////////////////////////
#ifdef DEBUG_SHADER
Texture2D gBaseTexture;
Texture2D gNormalTexture;
Texture2D gSpecularTexture;
#endif

////////////////////////////////////////////////
// Input/Output Declarations
////////////////////////////////////////////////
struct mrtvs_out {
float4 position : SV_POSITION0;
float2 texcoord : TEXCOORD0;
float3 normal : TEXCOORD1;
float3 tangent : TEXCOORD2;
float3 bitangent : TEXCOORD3;
float4 cpos : HPOS0;
float4 ppos : HPOS1;
};

struct mrtps_out {
float4 gbuffer0 : SV_Target0;
float4 gbuffer1 : SV_Target1;
float4 gbuffer2 : SV_Target2;
float4 gbuffer3 : SV_Target3;
};

////////////////////////////////////////////////
// Gbuffer Shaders
///////////////////////////////////////////////
mrtvs_out mrtVS(float4 position : POSITION,
float3 normal : NORMAL,
float3 tangent : TANGENT,
float3 bitangent : BINORMAL,
float2 texcoord : TEXCOORD0
)
{
mrtvs_out OUT;

// Projected position
OUT.position = mul(position, gWorldViewProj);

// Normal in world space
OUT.normal = normalize(mul(normal, gWorld));

// Tangents in world space
OUT.tangent = normalize(mul(tangent, gWorld));
OUT.bitangent = normalize(mul(bitangent, gWorld));

// Texture coordinates
OUT.texcoord = texcoord;

// Screen space positions;
OUT.cpos = OUT.position;
OUT.ppos = mul(position, gPrevWorldViewProj);

return OUT;
}

mrtps_out mrtPS(mrtvs_out IN) : SV_Target
{
mrtps_out OUT;

// GBUFFER0: | DiffuseR | DiffuseG | DiffuseB | Stencil |
// GBUFFER1: | NormalX | NormalY | NormalZ | SpecularPower |
// GBUFFER2: | MotionX | MotionY | | SpecularIntensity |
// GBUFFER3: | UNUSED |

// Color texture (TEXTURE0) /////////////////////////////////////////
#ifdef DEBUG_SHADER
OUT.gbuffer0 = gBaseTexture.Sample(samLinear, IN.texcoord);
if(OUT.gbuffer0.a == 0.0)
#endif
OUT.gbuffer0 = gTexture0.Sample(samLinear, IN.texcoord);

// Stencil
OUT.gbuffer0.a = 1.0;

// Normal texture (TEXTURE1) ///////////////////////////////////////
float4 normmap;
#ifdef DEBUG_SHADER
normmap = gNormalTexture.Sample(samLinear, IN.texcoord);
if(normmap.a == 0.0)
#endif
normmap = gTexture1.Sample(samLinear, IN.texcoord);

// TBN matrix. Calculated in here because then tangents,
// bitangent, and normal are interpolated by PS then.
float3x3 tbnm = float3x3(IN.tangent, IN.bitangent, IN.normal);

// Convert from 0 to 1 image space to -1 to 1 normal space.
float3 p = (2 * normmap.rgb - 1);

// Flip Y. Why? Seems to look right.
p.y = -p.y;

// Transform normal map into world space and store
OUT.gbuffer1.xyz = 0.5f * (mul(p, tbnm) + 1.0f);

// specular power
OUT.gbuffer1.w = log2(gMatfPower) / 10.5;

// (TEXTURE2) ///////////////////////////////////////////////////////
float4 specular;
#ifdef DEBUG_SHADER
specular = gSpecularTexture.Sample(samLinear, IN.texcoord);
if(specular.a == 0.0)
#endif

specular = gTexture2.Sample(samLinear, IN.texcoord);
OUT.gbuffer2.a = specular.r;

// Velocity
float4 cpos = IN.cpos / IN.cpos.w;
float4 ppos = IN.ppos / IN.ppos.w;
float2 velocity = (cpos - ppos) / 2.0f;
// Move from [-1, 1] to [0, 2] to [0, 1]
OUT.gbuffer2.rg = (velocity + 1.0f) * 0.5f;

// (TEXTURE3) ///////////////////////////////////////////////////////
//OUT.gbuffer3 = float4(0.0, 0.0, 1.0, 0.0);

return OUT;
}

///////////////////////////////////////////////
// Techniques
///////////////////////////////////////////////
technique10 gbuffer_normalmap
{
pass P0
{
SetVertexShader(CompileShader(vs_4_0, mrtVS()));
SetGeometryShader(NULL );
SetPixelShader(CompileShader(ps_4_0, mrtPS()));
SetBlendState(DisableBlend, float4(0.0f, 0.0f, 0.0f, 0.0f), 0xFFFFFFFF);
}
}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!