mirror of
https://bitbucket.org/CPMADevs/cnq3
synced 2025-02-16 17:01:08 +00:00
added motion blur and freeze frame commands
- fixed crash due to missing blue noise texture - added motion vector viz - renamed TextureFormat entries
This commit is contained in:
parent
c592ef22d6
commit
838c9a6485
39 changed files with 1707 additions and 134 deletions
|
@ -103,10 +103,21 @@ add: Cinematic Rendering Pipeline CVars
|
||||||
0 - disabled
|
0 - disabled
|
||||||
1 - 1/4 pixel count, 9 samples total
|
1 - 1/4 pixel count, 9 samples total
|
||||||
2 - 1/16 pixel count, 25 samples total
|
2 - 1/16 pixel count, 25 samples total
|
||||||
|
motion blur:
|
||||||
|
crp_mblur <0 to 3> (default: 0) sets the motion blur mode
|
||||||
|
0 - disabled
|
||||||
|
1 - camera blur only
|
||||||
|
2 - object blur only
|
||||||
|
3 - camera and object blur
|
||||||
|
crp_mblur_exposure <0.0 to 1.0> (default: 0.5) is the exposure time in percentage of frame time
|
||||||
miscellaneous:
|
miscellaneous:
|
||||||
crp_drawNormals <0|1> (default: 0) draws vertex normals as colorized wireframe lines
|
crp_drawNormals <0|1> (default: 0) draws vertex normals as colorized wireframe lines
|
||||||
crp_updateRTAS <0|1> (default: 1) enables raytracing acceleration structure builds every frame
|
crp_updateRTAS <0|1> (default: 1) enables raytracing acceleration structure builds every frame
|
||||||
|
|
||||||
|
add: Cinematic Rendering Pipeline commands
|
||||||
|
cin_freezeFrame freezes the rendered frame (minus ImGUI and tone map) and G-Buffer for inspection
|
||||||
|
cin_freezeFrameMB freezes the rendered frame (minus ImGUI, tone map and motion blur)
|
||||||
|
|
||||||
fix: allocating enough memory for 4K screenshots and video captures
|
fix: allocating enough memory for 4K screenshots and video captures
|
||||||
|
|
||||||
fix: the new demo player now drops zombie snapshots and snapshots from before a server time rewind
|
fix: the new demo player now drops zombie snapshots and snapshots from before a server time rewind
|
||||||
|
|
|
@ -361,6 +361,7 @@ static qbool CL_CG_GetValue( char* value, int valueSize, const char* key )
|
||||||
{ "trap_CNQ3_NK_Upload", CG_EXT_NK_UPLOAD },
|
{ "trap_CNQ3_NK_Upload", CG_EXT_NK_UPLOAD },
|
||||||
{ "trap_CNQ3_NK_Draw", CG_EXT_NK_DRAW },
|
{ "trap_CNQ3_NK_Draw", CG_EXT_NK_DRAW },
|
||||||
{ "trap_CNQ3_SetCharEvents", CG_EXT_SETCHAREVENTS },
|
{ "trap_CNQ3_SetCharEvents", CG_EXT_SETCHAREVENTS },
|
||||||
|
{ "trap_CNQ3_R_AddRefEntityToScene", CG_EXT_CNQ3_R_ADDREFENTITYTOSCENE },
|
||||||
// commands
|
// commands
|
||||||
{ "screenshotnc", 1 },
|
{ "screenshotnc", 1 },
|
||||||
{ "screenshotncJPEG", 1 },
|
{ "screenshotncJPEG", 1 },
|
||||||
|
@ -525,7 +526,7 @@ static intptr_t CL_CgameSystemCalls( intptr_t *args )
|
||||||
re.ClearScene();
|
re.ClearScene();
|
||||||
return 0;
|
return 0;
|
||||||
case CG_R_ADDREFENTITYTOSCENE:
|
case CG_R_ADDREFENTITYTOSCENE:
|
||||||
re.AddRefEntityToScene( VMA(1), qfalse );
|
re.AddRefEntityToScene( VMA(1), REV_ORIGINAL );
|
||||||
return 0;
|
return 0;
|
||||||
case CG_R_ADDPOLYTOSCENE:
|
case CG_R_ADDPOLYTOSCENE:
|
||||||
re.AddPolyToScene( args[1], args[2], VMA(3), 1 );
|
re.AddPolyToScene( args[1], args[2], VMA(3), 1 );
|
||||||
|
@ -648,7 +649,7 @@ static intptr_t CL_CgameSystemCalls( intptr_t *args )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case CG_EXT_R_ADDREFENTITYTOSCENE2:
|
case CG_EXT_R_ADDREFENTITYTOSCENE2:
|
||||||
re.AddRefEntityToScene( VMA(1), qtrue );
|
re.AddRefEntityToScene( VMA(1), REV_INTSHADERTIME );
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case CG_EXT_R_FORCEFIXEDDLIGHTS:
|
case CG_EXT_R_FORCEFIXEDDLIGHTS:
|
||||||
|
@ -728,6 +729,10 @@ static intptr_t CL_CgameSystemCalls( intptr_t *args )
|
||||||
cls.cgameCharEvents = (qbool)args[1];
|
cls.cgameCharEvents = (qbool)args[1];
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
case CG_EXT_CNQ3_R_ADDREFENTITYTOSCENE:
|
||||||
|
re.AddRefEntityToScene( VMA(1), REV_MOTIONBLUR );
|
||||||
|
return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Com_Error( ERR_DROP, "Bad cgame system trap: %i", args[0] );
|
Com_Error( ERR_DROP, "Bad cgame system trap: %i", args[0] );
|
||||||
}
|
}
|
||||||
|
|
|
@ -885,7 +885,7 @@ static intptr_t CL_UISystemCalls( intptr_t* args )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case UI_R_ADDREFENTITYTOSCENE:
|
case UI_R_ADDREFENTITYTOSCENE:
|
||||||
re.AddRefEntityToScene( VMA(1), qfalse );
|
re.AddRefEntityToScene( VMA(1), REV_ORIGINAL );
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case UI_R_ADDPOLYTOSCENE:
|
case UI_R_ADDPOLYTOSCENE:
|
||||||
|
@ -1127,7 +1127,7 @@ static intptr_t CL_UISystemCalls( intptr_t* args )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case UI_EXT_R_ADDREFENTITYTOSCENE2:
|
case UI_EXT_R_ADDREFENTITYTOSCENE2:
|
||||||
re.AddRefEntityToScene( VMA(1), qtrue );
|
re.AddRefEntityToScene( VMA(1), REV_INTSHADERTIME );
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case UI_EXT_CVAR_SETRANGE:
|
case UI_EXT_CVAR_SETRANGE:
|
||||||
|
|
|
@ -206,7 +206,8 @@ typedef enum {
|
||||||
CG_EXT_NK_CREATEFONTATLAS,
|
CG_EXT_NK_CREATEFONTATLAS,
|
||||||
CG_EXT_NK_UPLOAD,
|
CG_EXT_NK_UPLOAD,
|
||||||
CG_EXT_NK_DRAW,
|
CG_EXT_NK_DRAW,
|
||||||
CG_EXT_SETCHAREVENTS
|
CG_EXT_SETCHAREVENTS,
|
||||||
|
CG_EXT_CNQ3_R_ADDREFENTITYTOSCENE
|
||||||
} cgameImport_t;
|
} cgameImport_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -40,8 +40,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
// animation without needing to know the frame count
|
// animation without needing to know the frame count
|
||||||
|
|
||||||
// refdef flags
|
// refdef flags
|
||||||
#define RDF_NOWORLDMODEL 1 // used for player configuration screen
|
#define RDF_NOWORLDMODEL 1 // used for player configuration screen
|
||||||
#define RDF_HYPERSPACE 4 // teleportation effect
|
#define RDF_HYPERSPACE 4 // teleportation effect
|
||||||
|
#define RDF_CNQ3_TELEPORTED 8 // the camera teleported since the last submitted scene
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
vec3_t xyz;
|
vec3_t xyz;
|
||||||
|
@ -79,7 +80,7 @@ typedef struct {
|
||||||
float shadowPlane; // projection shadows go here, stencils go slightly lower
|
float shadowPlane; // projection shadows go here, stencils go slightly lower
|
||||||
|
|
||||||
vec3_t axis[3]; // rotation vectors
|
vec3_t axis[3]; // rotation vectors
|
||||||
qbool nonNormalizedAxes; // axis are not normalized, i.e. they have scale
|
qbool nonNormalizedAxes; // axis are not normalized, i.e. they have scale
|
||||||
float origin[3]; // also used as MODEL_BEAM's "from"
|
float origin[3]; // also used as MODEL_BEAM's "from"
|
||||||
int frame; // also used as MODEL_BEAM's diameter
|
int frame; // also used as MODEL_BEAM's diameter
|
||||||
|
|
||||||
|
@ -97,15 +98,64 @@ typedef struct {
|
||||||
byte shaderRGBA[4]; // colors used by rgbgen entity shaders
|
byte shaderRGBA[4]; // colors used by rgbgen entity shaders
|
||||||
float shaderTexCoord[2]; // texture coordinates used by tcMod entity modifiers
|
float shaderTexCoord[2]; // texture coordinates used by tcMod entity modifiers
|
||||||
union {
|
union {
|
||||||
float fShaderTime; // subtracted from refdef time to control effect start times
|
float fShaderTime; // subtracted from refdef time to control effect start times
|
||||||
int iShaderTime; // qvm float have 23bit mantissa. After 8388607ms (02:20) we lost data.
|
int iShaderTime; // qvm float have 23bit mantissa. After 8388607ms (02:20) we lost data.
|
||||||
} shaderTime;
|
} shaderTime;
|
||||||
|
|
||||||
// extra sprite information
|
// extra sprite information
|
||||||
float radius;
|
float radius;
|
||||||
float rotation;
|
float rotation;
|
||||||
|
} refEntityBase_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
refEntityType_t reType;
|
||||||
|
int renderfx;
|
||||||
|
|
||||||
|
qhandle_t hModel; // opaque type outside refresh
|
||||||
|
|
||||||
|
// most recent data
|
||||||
|
vec3_t lightingOrigin; // so multi-part models can be lit identically (RF_LIGHTING_ORIGIN)
|
||||||
|
float shadowPlane; // projection shadows go here, stencils go slightly lower
|
||||||
|
|
||||||
|
vec3_t axis[3]; // rotation vectors
|
||||||
|
qbool nonNormalizedAxes; // axis are not normalized, i.e. they have scale
|
||||||
|
float origin[3]; // also used as MODEL_BEAM's "from"
|
||||||
|
int frame; // also used as MODEL_BEAM's diameter
|
||||||
|
|
||||||
|
// previous data for frame interpolation
|
||||||
|
float oldorigin[3]; // also used as MODEL_BEAM's "to"
|
||||||
|
int oldframe;
|
||||||
|
float backlerp; // 0.0 = current, 1.0 = old
|
||||||
|
|
||||||
|
// texturing
|
||||||
|
int skinNum; // inline skin index
|
||||||
|
qhandle_t customSkin; // NULL for default skin
|
||||||
|
qhandle_t customShader; // use one image for the entire thing
|
||||||
|
|
||||||
|
// misc
|
||||||
|
byte shaderRGBA[4]; // colors used by rgbgen entity shaders
|
||||||
|
float shaderTexCoord[2]; // texture coordinates used by tcMod entity modifiers
|
||||||
|
union {
|
||||||
|
float fShaderTime; // subtracted from refdef time to control effect start times
|
||||||
|
int iShaderTime; // qvm float have 23bit mantissa. After 8388607ms (02:20) we lost data.
|
||||||
|
} shaderTime;
|
||||||
|
|
||||||
|
// extra sprite information
|
||||||
|
float radius;
|
||||||
|
float rotation;
|
||||||
|
|
||||||
|
// CNQ3 extensions
|
||||||
|
int uniqueId; // for tracking refresh entities across frames, 0 is untracked
|
||||||
|
float motionBlurScale; // 1.0f by default but can tweak for e.g. first-person weapon
|
||||||
} refEntity_t;
|
} refEntity_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
REV_ORIGINAL,
|
||||||
|
REV_INTSHADERTIME,
|
||||||
|
REV_MOTIONBLUR,
|
||||||
|
REV_LATEST = REV_MOTIONBLUR
|
||||||
|
} refEntityVersion_t;
|
||||||
|
|
||||||
|
|
||||||
#define MAX_RENDER_STRINGS 8
|
#define MAX_RENDER_STRINGS 8
|
||||||
#define MAX_RENDER_STRING_LENGTH 32
|
#define MAX_RENDER_STRING_LENGTH 32
|
||||||
|
|
|
@ -138,10 +138,10 @@ struct DOFCombineRC
|
||||||
|
|
||||||
void GatherDepthOfField::Init()
|
void GatherDepthOfField::Init()
|
||||||
{
|
{
|
||||||
const TextureFormat::Id renderTargetFormat = TextureFormat::RGBA64_Float;
|
const TextureFormat::Id renderTargetFormat = TextureFormat::R16G16B16A16_Float;
|
||||||
|
|
||||||
tileWidth = (uint32_t)(glConfig.vidWidth + 15) / 16;
|
tileTextureWidth = (uint32_t)(glConfig.vidWidth + 15) / 16;
|
||||||
tileHeight = (uint32_t)(glConfig.vidHeight + 15) / 16;
|
tileTextureHeight = (uint32_t)(glConfig.vidHeight + 15) / 16;
|
||||||
|
|
||||||
{
|
{
|
||||||
ComputePipelineDesc desc("DOF split");
|
ComputePipelineDesc desc("DOF split");
|
||||||
|
@ -223,8 +223,8 @@ void GatherDepthOfField::Init()
|
||||||
desc.name = "DOF far field CoC";
|
desc.name = "DOF far field CoC";
|
||||||
farCocTexture = CreateTexture(desc);
|
farCocTexture = CreateTexture(desc);
|
||||||
|
|
||||||
desc.width = tileWidth;
|
desc.width = tileTextureWidth;
|
||||||
desc.height = tileHeight;
|
desc.height = tileTextureHeight;
|
||||||
desc.name = "DOF near field CoC tile #1";
|
desc.name = "DOF near field CoC tile #1";
|
||||||
nearCocTileTexture = CreateTexture(desc);
|
nearCocTileTexture = CreateTexture(desc);
|
||||||
desc.name = "DOF near field CoC tile #2";
|
desc.name = "DOF near field CoC tile #2";
|
||||||
|
@ -334,7 +334,7 @@ void GatherDepthOfField::DrawNearCocTileGen()
|
||||||
|
|
||||||
CmdBindPipeline(nearCocTileGenPipeline);
|
CmdBindPipeline(nearCocTileGenPipeline);
|
||||||
CmdSetComputeRootConstants(0, sizeof(rc), &rc);
|
CmdSetComputeRootConstants(0, sizeof(rc), &rc);
|
||||||
CmdDispatch((tileWidth + 7) / 8, (tileHeight + 7) / 8, 1);
|
CmdDispatch((tileTextureWidth + 7) / 8, (tileTextureHeight + 7) / 8, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GatherDepthOfField::DrawNearCocTileMax()
|
void GatherDepthOfField::DrawNearCocTileMax()
|
||||||
|
@ -353,7 +353,7 @@ void GatherDepthOfField::DrawNearCocTileMax()
|
||||||
|
|
||||||
CmdBindPipeline(nearCocTileMaxPipeline);
|
CmdBindPipeline(nearCocTileMaxPipeline);
|
||||||
CmdSetComputeRootConstants(0, sizeof(rc), &rc);
|
CmdSetComputeRootConstants(0, sizeof(rc), &rc);
|
||||||
CmdDispatch((tileWidth + 7) / 8, (tileHeight + 7) / 8, 1);
|
CmdDispatch((tileTextureWidth + 7) / 8, (tileTextureHeight + 7) / 8, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GatherDepthOfField::DrawBlur()
|
void GatherDepthOfField::DrawBlur()
|
||||||
|
|
|
@ -27,6 +27,7 @@ along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
||||||
#include "compshaders/crp/gbufferviz_depth.h"
|
#include "compshaders/crp/gbufferviz_depth.h"
|
||||||
#include "compshaders/crp/gbufferviz_normal.h"
|
#include "compshaders/crp/gbufferviz_normal.h"
|
||||||
#include "compshaders/crp/gbufferviz_position.h"
|
#include "compshaders/crp/gbufferviz_position.h"
|
||||||
|
#include "compshaders/crp/gbufferviz_motion.h"
|
||||||
|
|
||||||
|
|
||||||
#pragma pack(push, 4)
|
#pragma pack(push, 4)
|
||||||
|
@ -50,6 +51,11 @@ struct DecodePositionRC
|
||||||
uint32_t coloredDelta;
|
uint32_t coloredDelta;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MotionVectorRC
|
||||||
|
{
|
||||||
|
uint32_t textureIndex;
|
||||||
|
};
|
||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
|
||||||
|
@ -87,6 +93,17 @@ void GBufferViz::Init()
|
||||||
desc.AddRenderTarget(0, crp.renderTargetFormat);
|
desc.AddRenderTarget(0, crp.renderTargetFormat);
|
||||||
decodeShadingPositionPipeline = CreateGraphicsPipeline(desc);
|
decodeShadingPositionPipeline = CreateGraphicsPipeline(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
GraphicsPipelineDesc desc("G-Buffer Motion");
|
||||||
|
desc.shortLifeTime = true;
|
||||||
|
desc.vertexShader = ShaderByteCode(g_fullscreen_vs);
|
||||||
|
desc.pixelShader = ShaderByteCode(g_gbufferviz_motion_ps);
|
||||||
|
desc.depthStencil.DisableDepth();
|
||||||
|
desc.rasterizer.cullMode = CT_TWO_SIDED;
|
||||||
|
desc.AddRenderTarget(0, crp.renderTargetFormat);
|
||||||
|
motionVectorPipeline = CreateGraphicsPipeline(desc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBufferViz::DrawGUI()
|
void GBufferViz::DrawGUI()
|
||||||
|
@ -166,14 +183,47 @@ void GBufferViz::DrawGUI()
|
||||||
CmdSetGraphicsRootConstants(0, sizeof(rc), &rc);
|
CmdSetGraphicsRootConstants(0, sizeof(rc), &rc);
|
||||||
CmdDraw(3, 0);
|
CmdDraw(3, 0);
|
||||||
}
|
}
|
||||||
|
else if(textureIndex == GBufferTexture::MotionVectorRaw ||
|
||||||
|
textureIndex == GBufferTexture::MotionVectorMB)
|
||||||
|
{
|
||||||
|
srp.renderMode = RenderMode::None;
|
||||||
|
|
||||||
|
const HTexture texture =
|
||||||
|
textureIndex == GBufferTexture::MotionVectorRaw ?
|
||||||
|
crp.motionVectorTexture :
|
||||||
|
crp.motionVectorMBTexture;
|
||||||
|
|
||||||
|
SCOPED_RENDER_PASS("Debug Motion", 1.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
CmdSetViewportAndScissor(0, 0, glConfig.vidWidth, glConfig.vidHeight);
|
||||||
|
|
||||||
|
CmdBeginBarrier();
|
||||||
|
CmdTextureBarrier(texture, ResourceStates::PixelShaderAccessBit);
|
||||||
|
CmdTextureBarrier(renderTarget, ResourceStates::RenderTargetBit);
|
||||||
|
CmdEndBarrier();
|
||||||
|
|
||||||
|
MotionVectorRC rc = {};
|
||||||
|
rc.textureIndex = GetTextureIndexSRV(texture);
|
||||||
|
|
||||||
|
CmdBindRenderTargets(1, &renderTarget, NULL);
|
||||||
|
CmdBindPipeline(motionVectorPipeline);
|
||||||
|
CmdSetGraphicsRootConstants(0, sizeof(rc), &rc);
|
||||||
|
CmdDraw(3, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if(ImGui::Begin("G-Buffer", &windowActive, ImGuiWindowFlags_AlwaysAutoResize))
|
if(ImGui::Begin("G-Buffer", &windowActive, ImGuiWindowFlags_AlwaysAutoResize))
|
||||||
{
|
{
|
||||||
|
ImGui::Checkbox("Full-res", &fullResolution);
|
||||||
|
ImGui::SameLine();
|
||||||
ImGui::RadioButton("Depth", &textureIndex, GBufferTexture::Depth);
|
ImGui::RadioButton("Depth", &textureIndex, GBufferTexture::Depth);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::RadioButton("Normal", &textureIndex, GBufferTexture::Normal);
|
ImGui::RadioButton("Normal", &textureIndex, GBufferTexture::Normal);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::RadioButton("Light", &textureIndex, GBufferTexture::Light);
|
ImGui::RadioButton("Light", &textureIndex, GBufferTexture::Light);
|
||||||
|
|
||||||
|
ImGui::RadioButton("Motion Raw", &textureIndex, GBufferTexture::MotionVectorRaw);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::RadioButton("Motion MB", &textureIndex, GBufferTexture::MotionVectorMB);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::RadioButton("Shading Position Delta", &textureIndex, GBufferTexture::ShadingPositionDelta);
|
ImGui::RadioButton("Shading Position Delta", &textureIndex, GBufferTexture::ShadingPositionDelta);
|
||||||
if(textureIndex == GBufferTexture::ShadingPositionDelta)
|
if(textureIndex == GBufferTexture::ShadingPositionDelta)
|
||||||
|
@ -182,7 +232,13 @@ void GBufferViz::DrawGUI()
|
||||||
ImGui::Checkbox("Per-axis delta", &coloredPositionDelta);
|
ImGui::Checkbox("Per-axis delta", &coloredPositionDelta);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ImVec2 resolution = ImVec2(glConfig.vidWidth / 2, glConfig.vidHeight / 2);
|
ImVec2 resolution = ImVec2(glConfig.vidWidth, glConfig.vidHeight);
|
||||||
|
if(!fullResolution)
|
||||||
|
{
|
||||||
|
resolution.x /= 2;
|
||||||
|
resolution.y /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
HTexture texture;
|
HTexture texture;
|
||||||
switch(textureIndex)
|
switch(textureIndex)
|
||||||
{
|
{
|
||||||
|
@ -190,6 +246,8 @@ void GBufferViz::DrawGUI()
|
||||||
case GBufferTexture::Normal: texture = renderTarget; break;
|
case GBufferTexture::Normal: texture = renderTarget; break;
|
||||||
case GBufferTexture::Light: texture = crp.lightTexture; break;
|
case GBufferTexture::Light: texture = crp.lightTexture; break;
|
||||||
case GBufferTexture::ShadingPositionDelta: texture = renderTarget; break;
|
case GBufferTexture::ShadingPositionDelta: texture = renderTarget; break;
|
||||||
|
case GBufferTexture::MotionVectorRaw: texture = renderTarget; break;
|
||||||
|
case GBufferTexture::MotionVectorMB: texture = renderTarget; break;
|
||||||
default: Q_assert(!"Invalid G-Buffer texture index"); texture = crp.lightTexture; break;
|
default: Q_assert(!"Invalid G-Buffer texture index"); texture = crp.lightTexture; break;
|
||||||
}
|
}
|
||||||
ImGui::Image((ImTextureID)GetTextureIndexSRV(texture), resolution);
|
ImGui::Image((ImTextureID)GetTextureIndexSRV(texture), resolution);
|
||||||
|
|
|
@ -40,6 +40,8 @@ extern cvar_t* crp_accumDof_focusDist;
|
||||||
extern cvar_t* crp_accumDof_radius;
|
extern cvar_t* crp_accumDof_radius;
|
||||||
extern cvar_t* crp_accumDof_samples;
|
extern cvar_t* crp_accumDof_samples;
|
||||||
extern cvar_t* crp_accumDof_preview;
|
extern cvar_t* crp_accumDof_preview;
|
||||||
|
extern cvar_t* crp_mblur;
|
||||||
|
extern cvar_t* crp_mblur_exposure;
|
||||||
extern cvar_t* crp_drawNormals;
|
extern cvar_t* crp_drawNormals;
|
||||||
extern cvar_t* crp_updateRTAS;
|
extern cvar_t* crp_updateRTAS;
|
||||||
extern cvar_t* crp_debug0;
|
extern cvar_t* crp_debug0;
|
||||||
|
@ -58,6 +60,15 @@ struct DOFMethod
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MotionBlurModes
|
||||||
|
{
|
||||||
|
enum Flags
|
||||||
|
{
|
||||||
|
CameraBit = 1 << 0,
|
||||||
|
ObjectBit = 1 << 1
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
struct Tessellator
|
struct Tessellator
|
||||||
{
|
{
|
||||||
enum Id
|
enum Id
|
||||||
|
@ -111,6 +122,10 @@ private:
|
||||||
|
|
||||||
bool batchOldDepthHack;
|
bool batchOldDepthHack;
|
||||||
bool batchDepthHack;
|
bool batchDepthHack;
|
||||||
|
int batchEntityId;
|
||||||
|
float batchMotionScale;
|
||||||
|
|
||||||
|
HPipeline skyboxMotionPipeline;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WorldOpaque
|
struct WorldOpaque
|
||||||
|
@ -237,8 +252,30 @@ private:
|
||||||
HTexture nearCocTileTexture;
|
HTexture nearCocTileTexture;
|
||||||
HTexture nearCocTileTexture2;
|
HTexture nearCocTileTexture2;
|
||||||
HTexture farCocTexture;
|
HTexture farCocTexture;
|
||||||
uint32_t tileWidth;
|
uint32_t tileTextureWidth;
|
||||||
uint32_t tileHeight;
|
uint32_t tileTextureHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MotionBlur
|
||||||
|
{
|
||||||
|
void Init();
|
||||||
|
void Draw();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void DrawPack();
|
||||||
|
void DrawTileGen();
|
||||||
|
void DrawTileMax();
|
||||||
|
void DrawBlur();
|
||||||
|
|
||||||
|
HPipeline packPipeline;
|
||||||
|
HPipeline tileGenPipeline;
|
||||||
|
HPipeline tileMaxPipeline;
|
||||||
|
HPipeline blurPipeline;
|
||||||
|
HTexture tileTexture;
|
||||||
|
HTexture tileTexture2;
|
||||||
|
HTexture packedTexture;
|
||||||
|
uint32_t tileTextureWidth;
|
||||||
|
uint32_t tileTextureHeight;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Magnifier
|
struct Magnifier
|
||||||
|
@ -266,6 +303,8 @@ private:
|
||||||
Normal,
|
Normal,
|
||||||
Light,
|
Light,
|
||||||
ShadingPositionDelta,
|
ShadingPositionDelta,
|
||||||
|
MotionVectorRaw,
|
||||||
|
MotionVectorMB,
|
||||||
Count
|
Count
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -273,9 +312,11 @@ private:
|
||||||
HPipeline linearizeDepthPipeline;
|
HPipeline linearizeDepthPipeline;
|
||||||
HPipeline decodeNormalsPipeline;
|
HPipeline decodeNormalsPipeline;
|
||||||
HPipeline decodeShadingPositionPipeline;
|
HPipeline decodeShadingPositionPipeline;
|
||||||
|
HPipeline motionVectorPipeline;
|
||||||
bool windowActive = false;
|
bool windowActive = false;
|
||||||
int textureIndex = 0;
|
int textureIndex = 0;
|
||||||
bool coloredPositionDelta = false;
|
bool coloredPositionDelta = false;
|
||||||
|
bool fullResolution = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DynamicLights
|
struct DynamicLights
|
||||||
|
@ -405,6 +446,18 @@ struct GeoBuffers
|
||||||
uint32_t vertexBufferStrides[BaseBufferId::Count + StageBufferId::Count];
|
uint32_t vertexBufferStrides[BaseBufferId::Count + StageBufferId::Count];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FreezeFrame
|
||||||
|
{
|
||||||
|
enum Id
|
||||||
|
{
|
||||||
|
Inactive,
|
||||||
|
Pending,
|
||||||
|
Active,
|
||||||
|
PendingBeforeMB,
|
||||||
|
ActiveBeforeMB
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
struct CRP : IRenderPipeline
|
struct CRP : IRenderPipeline
|
||||||
{
|
{
|
||||||
void Init() override;
|
void Init() override;
|
||||||
|
@ -445,7 +498,8 @@ struct CRP : IRenderPipeline
|
||||||
HTexture readbackRenderTarget;
|
HTexture readbackRenderTarget;
|
||||||
HTexture depthTexture;
|
HTexture depthTexture;
|
||||||
HTexture normalTexture;
|
HTexture normalTexture;
|
||||||
HTexture motionVectorTexture;
|
HTexture motionVectorTexture; // raw, for TAA/denoisers/etc
|
||||||
|
HTexture motionVectorMBTexture; // mangled, for motion blur only
|
||||||
HTexture noisyLightTexture;
|
HTexture noisyLightTexture;
|
||||||
HTexture lightTexture;
|
HTexture lightTexture;
|
||||||
HTexture shadingPositionTexture;
|
HTexture shadingPositionTexture;
|
||||||
|
@ -456,6 +510,8 @@ struct CRP : IRenderPipeline
|
||||||
HSampler samplers[BASE_SAMPLER_COUNT]; // all base samplers
|
HSampler samplers[BASE_SAMPLER_COUNT]; // all base samplers
|
||||||
uint32_t samplerIndices[BASE_SAMPLER_COUNT]; // descriptor heap indices
|
uint32_t samplerIndices[BASE_SAMPLER_COUNT]; // descriptor heap indices
|
||||||
HTexture blueNoise2D;
|
HTexture blueNoise2D;
|
||||||
|
FreezeFrame::Id freezeFrame;
|
||||||
|
HTexture frozenTexture;
|
||||||
|
|
||||||
// blit
|
// blit
|
||||||
HPipeline blitPipelineLDR;
|
HPipeline blitPipelineLDR;
|
||||||
|
@ -486,6 +542,7 @@ struct CRP : IRenderPipeline
|
||||||
ToneMap toneMap;
|
ToneMap toneMap;
|
||||||
GatherDepthOfField gatherDof;
|
GatherDepthOfField gatherDof;
|
||||||
AccumDepthOfField accumDof;
|
AccumDepthOfField accumDof;
|
||||||
|
MotionBlur motionBlur;
|
||||||
Fog fog;
|
Fog fog;
|
||||||
Magnifier magnifier;
|
Magnifier magnifier;
|
||||||
DynamicLights dynamicLights;
|
DynamicLights dynamicLights;
|
||||||
|
|
|
@ -64,6 +64,8 @@ cvar_t* crp_accumDof_focusDist;
|
||||||
cvar_t* crp_accumDof_radius;
|
cvar_t* crp_accumDof_radius;
|
||||||
cvar_t* crp_accumDof_samples;
|
cvar_t* crp_accumDof_samples;
|
||||||
cvar_t* crp_accumDof_preview;
|
cvar_t* crp_accumDof_preview;
|
||||||
|
cvar_t* crp_mblur;
|
||||||
|
cvar_t* crp_mblur_exposure;
|
||||||
cvar_t* crp_drawNormals;
|
cvar_t* crp_drawNormals;
|
||||||
cvar_t* crp_updateRTAS;
|
cvar_t* crp_updateRTAS;
|
||||||
cvar_t* crp_debug0;
|
cvar_t* crp_debug0;
|
||||||
|
@ -150,6 +152,25 @@ static const cvarTableItem_t crp_cvars[] =
|
||||||
&crp_gatherDof_brightness, "crp_gatherDof_brightness", "2", CVAR_ARCHIVE, CVART_FLOAT, "0", "8", "blur brightness weight",
|
&crp_gatherDof_brightness, "crp_gatherDof_brightness", "2", CVAR_ARCHIVE, CVART_FLOAT, "0", "8", "blur brightness weight",
|
||||||
"Gather DoF bokeh brightness", CVARCAT_GRAPHICS, "Blur brightness weight", ""
|
"Gather DoF bokeh brightness", CVARCAT_GRAPHICS, "Blur brightness weight", ""
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
&crp_mblur, "crp_mblur", "0", CVAR_ARCHIVE, CVART_INTEGER, "0", "3",
|
||||||
|
"motion blur mode\n"
|
||||||
|
S_COLOR_VAL " 0 " S_COLOR_HELP "= Disabled\n"
|
||||||
|
S_COLOR_VAL " 1 " S_COLOR_HELP "= Camera only\n"
|
||||||
|
S_COLOR_VAL " 2 " S_COLOR_HELP "= Object only\n"
|
||||||
|
S_COLOR_VAL " 3 " S_COLOR_HELP "= Camera + Object",
|
||||||
|
"Motion blur mode", CVARCAT_GRAPHICS, "", "",
|
||||||
|
CVAR_GUI_VALUE("0", "Disabled", "")
|
||||||
|
CVAR_GUI_VALUE("1", "Camera only", "")
|
||||||
|
CVAR_GUI_VALUE("2", "Object only", "")
|
||||||
|
CVAR_GUI_VALUE("3", "Camera + Object", "")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&crp_mblur_exposure, "crp_mblur_exposure", "0.5", CVAR_ARCHIVE, CVART_FLOAT, "0", "1",
|
||||||
|
"motion blur scale\n"
|
||||||
|
"This is the exposure time in percentage of frame time.",
|
||||||
|
"Motion blur exposure", CVARCAT_GRAPHICS, "Exposure time in percentage of frame time", ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
&crp_drawNormals, "crp_drawNormals", "0", CVAR_TEMP, CVART_BOOL, NULL, NULL, "draws vertex normals",
|
&crp_drawNormals, "crp_drawNormals", "0", CVAR_TEMP, CVART_BOOL, NULL, NULL, "draws vertex normals",
|
||||||
"Draw vertex normals", CVARCAT_GRAPHICS | CVARCAT_DEBUGGING, "", ""
|
"Draw vertex normals", CVARCAT_GRAPHICS | CVARCAT_DEBUGGING, "", ""
|
||||||
|
@ -179,6 +200,52 @@ static const cvarTableItem_t crp_cvars[] =
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void FreezeFrame_f();
|
||||||
|
static void FreezeFrameMB_f();
|
||||||
|
|
||||||
|
static const cmdTableItem_t crp_cmds[] =
|
||||||
|
{
|
||||||
|
{ "cin_freezeFrame", FreezeFrame_f, NULL, "toggles freeze frame mode" },
|
||||||
|
{ "cin_freezeFrameMB", FreezeFrameMB_f, NULL, "toggles freeze frame mode for MB" }
|
||||||
|
};
|
||||||
|
|
||||||
|
static void FreezeFrame_f()
|
||||||
|
{
|
||||||
|
if(crp.freezeFrame == FreezeFrame::Active ||
|
||||||
|
crp.freezeFrame == FreezeFrame::ActiveBeforeMB)
|
||||||
|
{
|
||||||
|
crp.freezeFrame = FreezeFrame::Inactive;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
crp.freezeFrame = FreezeFrame::Pending;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FreezeFrameMB_f()
|
||||||
|
{
|
||||||
|
if(crp.freezeFrame == FreezeFrame::Active ||
|
||||||
|
crp.freezeFrame == FreezeFrame::ActiveBeforeMB)
|
||||||
|
{
|
||||||
|
crp.freezeFrame = FreezeFrame::Inactive;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
crp.freezeFrame = FreezeFrame::PendingBeforeMB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static HTexture LoadTexture(const char* name, int flags, textureWrap_t glWrapClampMode, const image_t* onFail = tr.defaultImage)
|
||||||
|
{
|
||||||
|
image_t* const image = R_FindImageFile(name, flags, glWrapClampMode);
|
||||||
|
if(image == NULL)
|
||||||
|
{
|
||||||
|
return onFail->texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
return image->texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PSOCache::Init(Entry* entries_, uint32_t maxEntryCount_)
|
void PSOCache::Init(Entry* entries_, uint32_t maxEntryCount_)
|
||||||
{
|
{
|
||||||
|
@ -215,12 +282,8 @@ int PSOCache::AddPipeline(const GraphicsPipelineDesc& desc, const char* name)
|
||||||
|
|
||||||
void CRP::Init()
|
void CRP::Init()
|
||||||
{
|
{
|
||||||
static bool veryFirstInit = true;
|
ri.Cvar_RegisterTable(crp_cvars, ARRAY_LEN(crp_cvars));
|
||||||
if(veryFirstInit)
|
ri.Cmd_RegisterTable(crp_cmds, ARRAY_LEN(crp_cmds));
|
||||||
{
|
|
||||||
ri.Cvar_RegisterTable(crp_cvars, ARRAY_LEN(crp_cvars));
|
|
||||||
veryFirstInit = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
InitDesc initDesc;
|
InitDesc initDesc;
|
||||||
initDesc.directDescriptorHeapIndexing = true;
|
initDesc.directDescriptorHeapIndexing = true;
|
||||||
|
@ -262,13 +325,12 @@ void CRP::Init()
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
renderTargetFormat = TextureFormat::RGBA64_Float;
|
renderTargetFormat = TextureFormat::R16G16B16A16_Float;
|
||||||
|
|
||||||
TextureDesc desc("render target #1", glConfig.vidWidth, glConfig.vidHeight);
|
TextureDesc desc("render target #1", glConfig.vidWidth, glConfig.vidHeight);
|
||||||
desc.initialState = ResourceStates::RenderTargetBit;
|
desc.initialState = ResourceStates::RenderTargetBit;
|
||||||
desc.allowedState = ResourceStates::RenderTargetBit | ResourceStates::PixelShaderAccessBit;
|
desc.allowedState = ResourceStates::RenderTargetBit | ResourceStates::PixelShaderAccessBit | ResourceStates::ComputeShaderAccessBit;
|
||||||
Vector4Clear(desc.clearColor);
|
desc.SetClearColor(vec4_zero);
|
||||||
desc.usePreferredClearValue = true;
|
|
||||||
desc.committedResource = true;
|
desc.committedResource = true;
|
||||||
desc.format = renderTargetFormat;
|
desc.format = renderTargetFormat;
|
||||||
desc.shortLifeTime = true;
|
desc.shortLifeTime = true;
|
||||||
|
@ -279,6 +341,17 @@ void CRP::Init()
|
||||||
renderTarget = renderTargets[0];
|
renderTarget = renderTargets[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
TextureDesc desc("frozen frame", glConfig.vidWidth, glConfig.vidHeight);
|
||||||
|
desc.initialState = ResourceStates::RenderTargetBit;
|
||||||
|
desc.allowedState = ResourceStates::RenderTargetBit | ResourceStates::PixelShaderAccessBit | ResourceStates::ComputeShaderAccessBit;
|
||||||
|
desc.format = renderTargetFormat;
|
||||||
|
desc.shortLifeTime = true;
|
||||||
|
frozenTexture = RHI::CreateTexture(desc);
|
||||||
|
|
||||||
|
freezeFrame = FreezeFrame::Inactive;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
TextureDesc desc("readback render target", glConfig.vidWidth, glConfig.vidHeight);
|
TextureDesc desc("readback render target", glConfig.vidWidth, glConfig.vidHeight);
|
||||||
desc.initialState = ResourceStates::RenderTargetBit;
|
desc.initialState = ResourceStates::RenderTargetBit;
|
||||||
|
@ -286,7 +359,7 @@ void CRP::Init()
|
||||||
Vector4Clear(desc.clearColor);
|
Vector4Clear(desc.clearColor);
|
||||||
desc.usePreferredClearValue = true;
|
desc.usePreferredClearValue = true;
|
||||||
desc.committedResource = true;
|
desc.committedResource = true;
|
||||||
desc.format = TextureFormat::RGBA32_UNorm;
|
desc.format = TextureFormat::R8G8B8A8_UNorm;
|
||||||
desc.shortLifeTime = true;
|
desc.shortLifeTime = true;
|
||||||
readbackRenderTarget = RHI::CreateTexture(desc);
|
readbackRenderTarget = RHI::CreateTexture(desc);
|
||||||
}
|
}
|
||||||
|
@ -360,29 +433,40 @@ void CRP::Init()
|
||||||
desc.shortLifeTime = true;
|
desc.shortLifeTime = true;
|
||||||
desc.initialState = ResourceStates::RenderTargetBit;
|
desc.initialState = ResourceStates::RenderTargetBit;
|
||||||
desc.allowedState = ResourceStates::RenderTargetBit | ResourceStates::PixelShaderAccessBit | ResourceStates::ComputeShaderAccessBit;
|
desc.allowedState = ResourceStates::RenderTargetBit | ResourceStates::PixelShaderAccessBit | ResourceStates::ComputeShaderAccessBit;
|
||||||
desc.format = TextureFormat::RG32_SNorm;
|
desc.format = TextureFormat::R16G16_SNorm;
|
||||||
desc.SetClearColor(vec4_zero);
|
desc.SetClearColor(vec4_zero);
|
||||||
normalTexture = RHI::CreateTexture(desc);
|
normalTexture = RHI::CreateTexture(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
TextureDesc desc("GBuffer motion vectors", glConfig.vidWidth, glConfig.vidHeight);
|
TextureDesc desc("GBuffer raw motion vectors", glConfig.vidWidth, glConfig.vidHeight);
|
||||||
desc.committedResource = true;
|
desc.committedResource = true;
|
||||||
desc.shortLifeTime = true;
|
desc.shortLifeTime = true;
|
||||||
desc.initialState = ResourceStates::RenderTargetBit;
|
desc.initialState = ResourceStates::RenderTargetBit;
|
||||||
desc.allowedState = ResourceStates::RenderTargetBit | ResourceStates::PixelShaderAccessBit | ResourceStates::ComputeShaderAccessBit;
|
desc.allowedState = ResourceStates::RenderTargetBit | ResourceStates::PixelShaderAccessBit | ResourceStates::ComputeShaderAccessBit;
|
||||||
desc.format = TextureFormat::RG32_Float;
|
desc.format = TextureFormat::R16G16_Float;
|
||||||
desc.SetClearColor(vec4_zero);
|
desc.SetClearColor(vec4_zero);
|
||||||
motionVectorTexture = RHI::CreateTexture(desc);
|
motionVectorTexture = RHI::CreateTexture(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
TextureDesc desc("GBuffer MB motion vectors", glConfig.vidWidth, glConfig.vidHeight);
|
||||||
|
desc.committedResource = true;
|
||||||
|
desc.shortLifeTime = true;
|
||||||
|
desc.initialState = ResourceStates::RenderTargetBit;
|
||||||
|
desc.allowedState = ResourceStates::RenderTargetBit | ResourceStates::PixelShaderAccessBit | ResourceStates::ComputeShaderAccessBit;
|
||||||
|
desc.format = TextureFormat::R16G16_Float;
|
||||||
|
desc.SetClearColor(vec4_zero);
|
||||||
|
motionVectorMBTexture = RHI::CreateTexture(desc);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
TextureDesc desc("GBuffer direct light", glConfig.vidWidth, glConfig.vidHeight);
|
TextureDesc desc("GBuffer direct light", glConfig.vidWidth, glConfig.vidHeight);
|
||||||
desc.committedResource = true;
|
desc.committedResource = true;
|
||||||
desc.shortLifeTime = true;
|
desc.shortLifeTime = true;
|
||||||
desc.initialState = ResourceStates::RenderTargetBit;
|
desc.initialState = ResourceStates::RenderTargetBit;
|
||||||
desc.allowedState = ResourceStates::RenderTargetBit | ResourceStates::PixelShaderAccessBit | ResourceStates::ComputeShaderAccessBit;
|
desc.allowedState = ResourceStates::RenderTargetBit | ResourceStates::PixelShaderAccessBit | ResourceStates::ComputeShaderAccessBit;
|
||||||
desc.format = TextureFormat::RGBA64_Float;
|
desc.format = TextureFormat::R16G16B16A16_Float;
|
||||||
desc.SetClearColor(colorBlack);
|
desc.SetClearColor(colorBlack);
|
||||||
lightTexture = RHI::CreateTexture(desc);
|
lightTexture = RHI::CreateTexture(desc);
|
||||||
desc.name = "GBuffer raw direct light";
|
desc.name = "GBuffer raw direct light";
|
||||||
|
@ -395,7 +479,7 @@ void CRP::Init()
|
||||||
desc.shortLifeTime = true;
|
desc.shortLifeTime = true;
|
||||||
desc.initialState = ResourceStates::RenderTargetBit;
|
desc.initialState = ResourceStates::RenderTargetBit;
|
||||||
desc.allowedState = ResourceStates::RenderTargetBit | ResourceStates::PixelShaderAccessBit | ResourceStates::ComputeShaderAccessBit;
|
desc.allowedState = ResourceStates::RenderTargetBit | ResourceStates::PixelShaderAccessBit | ResourceStates::ComputeShaderAccessBit;
|
||||||
desc.format = TextureFormat::RGBA128_Float;
|
desc.format = TextureFormat::R32G32B32A32_Float;
|
||||||
desc.SetClearColor(vec4_zero);
|
desc.SetClearColor(vec4_zero);
|
||||||
shadingPositionTexture = RHI::CreateTexture(desc);
|
shadingPositionTexture = RHI::CreateTexture(desc);
|
||||||
}
|
}
|
||||||
|
@ -407,10 +491,10 @@ void CRP::Init()
|
||||||
desc.pixelShader = ShaderByteCode(g_blit_ps);
|
desc.pixelShader = ShaderByteCode(g_blit_ps);
|
||||||
desc.depthStencil.DisableDepth();
|
desc.depthStencil.DisableDepth();
|
||||||
desc.rasterizer.cullMode = CT_TWO_SIDED;
|
desc.rasterizer.cullMode = CT_TWO_SIDED;
|
||||||
desc.AddRenderTarget(0, TextureFormat::RGBA32_UNorm);
|
desc.AddRenderTarget(0, TextureFormat::R8G8B8A8_UNorm);
|
||||||
blitPipelineLDR = CreateGraphicsPipeline(desc);
|
blitPipelineLDR = CreateGraphicsPipeline(desc);
|
||||||
desc.name = "blit HDR";
|
desc.name = "blit HDR";
|
||||||
desc.renderTargets[0].format = TextureFormat::RGBA64_Float;
|
desc.renderTargets[0].format = TextureFormat::R16G16B16A16_Float;
|
||||||
blitPipelineHDR = CreateGraphicsPipeline(desc);
|
blitPipelineHDR = CreateGraphicsPipeline(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,6 +527,7 @@ void CRP::Init()
|
||||||
toneMap.Init();
|
toneMap.Init();
|
||||||
gatherDof.Init();
|
gatherDof.Init();
|
||||||
accumDof.Init();
|
accumDof.Init();
|
||||||
|
motionBlur.Init();
|
||||||
fog.Init();
|
fog.Init();
|
||||||
magnifier.Init();
|
magnifier.Init();
|
||||||
dynamicLights.Init();
|
dynamicLights.Init();
|
||||||
|
@ -455,7 +540,7 @@ void CRP::Init()
|
||||||
void CRP::LoadResources()
|
void CRP::LoadResources()
|
||||||
{
|
{
|
||||||
const int flags = IMG_NOPICMIP | IMG_NOMIPMAP | IMG_NOIMANIP | IMG_NOAF;
|
const int flags = IMG_NOPICMIP | IMG_NOMIPMAP | IMG_NOIMANIP | IMG_NOAF;
|
||||||
blueNoise2D = R_FindImageFile("textures/stbn_2d.tga", flags, TW_REPEAT)->texture;
|
blueNoise2D = LoadTexture("textures/stbn_2d.tga", flags, TW_REPEAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRP::ShutDown(bool fullShutDown)
|
void CRP::ShutDown(bool fullShutDown)
|
||||||
|
@ -495,6 +580,22 @@ void CRP::BeginFrame()
|
||||||
|
|
||||||
void CRP::EndFrame()
|
void CRP::EndFrame()
|
||||||
{
|
{
|
||||||
|
if(freezeFrame == FreezeFrame::Pending)
|
||||||
|
{
|
||||||
|
crp.SwapRenderTargets();
|
||||||
|
CmdBeginBarrier();
|
||||||
|
CmdTextureBarrier(GetReadRenderTarget(), ResourceStates::PixelShaderAccessBit);
|
||||||
|
CmdTextureBarrier(frozenTexture, ResourceStates::RenderTargetBit);
|
||||||
|
CmdEndBarrier();
|
||||||
|
Blit(frozenTexture, GetReadRenderTarget(), "Blit Frozen Frame", true, vec2_one, vec2_zero);
|
||||||
|
CmdBeginBarrier();
|
||||||
|
CmdTextureBarrier(frozenTexture, ResourceStates::PixelShaderAccessBit);
|
||||||
|
CmdEndBarrier();
|
||||||
|
srp.EndFrame();
|
||||||
|
freezeFrame = FreezeFrame::Active;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
srp.DrawGUI();
|
srp.DrawGUI();
|
||||||
gbufferViz.DrawGUI();
|
gbufferViz.DrawGUI();
|
||||||
magnifier.DrawGUI();
|
magnifier.DrawGUI();
|
||||||
|
@ -605,7 +706,21 @@ void CRP::ProcessShader(shader_t& shader)
|
||||||
|
|
||||||
void CRP::ExecuteRenderCommands(const byte* data, bool /*readbackRequested*/)
|
void CRP::ExecuteRenderCommands(const byte* data, bool /*readbackRequested*/)
|
||||||
{
|
{
|
||||||
// @NOTE: the CRP always blits the final result to the readback texture
|
// @NOTE: readbackRequested is unused because
|
||||||
|
// the CRP always blits the final result to the readback texture
|
||||||
|
|
||||||
|
if(freezeFrame == FreezeFrame::Active ||
|
||||||
|
freezeFrame == FreezeFrame::ActiveBeforeMB)
|
||||||
|
{
|
||||||
|
BeginFrame();
|
||||||
|
Blit(GetWriteRenderTarget(), frozenTexture, "Blit Frozen Frame", true, vec2_one, vec2_zero);
|
||||||
|
if(freezeFrame == FreezeFrame::ActiveBeforeMB)
|
||||||
|
{
|
||||||
|
motionBlur.Draw();
|
||||||
|
}
|
||||||
|
EndFrame();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
|
@ -768,6 +883,21 @@ void CRP::DrawSceneView(const drawSceneViewCommand_t& cmd)
|
||||||
transpResolve.Draw(cmd);
|
transpResolve.Draw(cmd);
|
||||||
CmdSetViewportAndScissor(vp.viewportX, vp.viewportY, vp.viewportWidth, vp.viewportHeight);
|
CmdSetViewportAndScissor(vp.viewportX, vp.viewportY, vp.viewportWidth, vp.viewportHeight);
|
||||||
gatherDof.Draw();
|
gatherDof.Draw();
|
||||||
|
if(freezeFrame == FreezeFrame::PendingBeforeMB &&
|
||||||
|
IsViewportFullscreen(backEnd.viewParms))
|
||||||
|
{
|
||||||
|
crp.SwapRenderTargets();
|
||||||
|
CmdBeginBarrier();
|
||||||
|
CmdTextureBarrier(GetReadRenderTarget(), ResourceStates::PixelShaderAccessBit);
|
||||||
|
CmdTextureBarrier(frozenTexture, ResourceStates::RenderTargetBit);
|
||||||
|
CmdEndBarrier();
|
||||||
|
Blit(frozenTexture, GetReadRenderTarget(), "Blit Frozen Frame", true, vec2_one, vec2_zero);
|
||||||
|
CmdBeginBarrier();
|
||||||
|
CmdTextureBarrier(frozenTexture, ResourceStates::PixelShaderAccessBit);
|
||||||
|
CmdEndBarrier();
|
||||||
|
freezeFrame = FreezeFrame::ActiveBeforeMB;
|
||||||
|
}
|
||||||
|
motionBlur.Draw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -796,6 +926,11 @@ void CRP::UploadSceneViewData()
|
||||||
R_InvMatrix(dest.projectionMatrix, dest.invProjectionMatrix);
|
R_InvMatrix(dest.projectionMatrix, dest.invProjectionMatrix);
|
||||||
memcpy(dest.viewMatrix, vp.world.modelMatrix, sizeof(dest.viewMatrix));
|
memcpy(dest.viewMatrix, vp.world.modelMatrix, sizeof(dest.viewMatrix));
|
||||||
R_InvMatrix(dest.viewMatrix, dest.invViewMatrix);
|
R_InvMatrix(dest.viewMatrix, dest.invViewMatrix);
|
||||||
|
|
||||||
|
memcpy(dest.prevViewProjMatrix, tr.prevViewProjMatrix, sizeof(dest.prevViewProjMatrix));
|
||||||
|
memcpy(dest.prevViewMatrix, tr.prevViewMatrix, sizeof(dest.prevViewMatrix));
|
||||||
|
memcpy(dest.prevProjectionMatrix, tr.prevProjMatrix, sizeof(dest.prevProjectionMatrix));
|
||||||
|
|
||||||
RB_CreateClipPlane(dest.clipPlane);
|
RB_CreateClipPlane(dest.clipPlane);
|
||||||
#if defined(_DEBUG)
|
#if defined(_DEBUG)
|
||||||
dest.debug[0] = crp_debug0->value;
|
dest.debug[0] = crp_debug0->value;
|
||||||
|
@ -814,10 +949,15 @@ void CRP::UploadSceneViewData()
|
||||||
dest.depthTextureIndex = GetTextureIndexSRV(depthTexture);
|
dest.depthTextureIndex = GetTextureIndexSRV(depthTexture);
|
||||||
dest.normalTextureIndex = GetTextureIndexSRV(normalTexture);
|
dest.normalTextureIndex = GetTextureIndexSRV(normalTexture);
|
||||||
dest.shadingPositionTextureIndex = GetTextureIndexSRV(shadingPositionTexture);
|
dest.shadingPositionTextureIndex = GetTextureIndexSRV(shadingPositionTexture);
|
||||||
|
dest.motionVectorTextureIndex = GetTextureIndexSRV(motionVectorTexture);
|
||||||
|
dest.motionVectorMBTextureIndex = GetTextureIndexSRV(motionVectorMBTexture);
|
||||||
dest.lightTextureIndex = GetTextureIndexSRV(lightTexture);
|
dest.lightTextureIndex = GetTextureIndexSRV(lightTexture);
|
||||||
dest.tlasBufferIndex = IsNullHandle(tlasBuffer) ? 0 : GetBufferIndexSRV(tlasBuffer);
|
dest.tlasBufferIndex = IsNullHandle(tlasBuffer) ? 0 : GetBufferIndexSRV(tlasBuffer);
|
||||||
dest.tlasInstanceBufferIndex = IsNullHandle(tlasInstanceBuffer) ? 0 : GetBufferIndexSRV(tlasInstanceBuffer);
|
dest.tlasInstanceBufferIndex = IsNullHandle(tlasInstanceBuffer) ? 0 : GetBufferIndexSRV(tlasInstanceBuffer);
|
||||||
dest.lightCount = refdef.num_dlights;
|
dest.lightCount = refdef.num_dlights;
|
||||||
|
RB_LinearDepthConstants(&dest.linearDepthA, &dest.linearDepthB);
|
||||||
|
dest.zNear = vp.zNear;
|
||||||
|
dest.zFar = vp.zFar;
|
||||||
|
|
||||||
for(int i = 0; i < refdef.num_dlights; i++)
|
for(int i = 0; i < refdef.num_dlights; i++)
|
||||||
{
|
{
|
||||||
|
|
227
code/renderer/crp_motion_blur.cpp
Normal file
227
code/renderer/crp_motion_blur.cpp
Normal file
|
@ -0,0 +1,227 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 2024 Gian 'myT' Schellenbaum
|
||||||
|
|
||||||
|
This file is part of Challenge Quake 3 (CNQ3).
|
||||||
|
|
||||||
|
Challenge Quake 3 is free software; you can redistribute it
|
||||||
|
and/or modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
Challenge Quake 3 is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
// Cinematic Rendering Pipeline - scatter-as-gather motion blur
|
||||||
|
|
||||||
|
|
||||||
|
#include "crp_local.h"
|
||||||
|
#include "compshaders/crp/fullscreen.h"
|
||||||
|
#include "compshaders/crp/mblur_pack.h"
|
||||||
|
#include "compshaders/crp/mblur_tile_gen.h"
|
||||||
|
#include "compshaders/crp/mblur_tile_max.h"
|
||||||
|
#include "compshaders/crp/mblur_blur.h"
|
||||||
|
|
||||||
|
|
||||||
|
#pragma pack(push, 4)
|
||||||
|
|
||||||
|
struct MBPackRC
|
||||||
|
{
|
||||||
|
float motionScale;
|
||||||
|
float maxRadiusPx;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MBTileGenRC
|
||||||
|
{
|
||||||
|
uint32_t inputTextureIndex;
|
||||||
|
uint32_t outputTextureIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MBTileMaxRC
|
||||||
|
{
|
||||||
|
uint32_t inputTextureIndex;
|
||||||
|
uint32_t outputTextureIndex;
|
||||||
|
uint32_t samplerIndex; // point/clamp
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MBBlurRC
|
||||||
|
{
|
||||||
|
uint32_t colorTextureIndex;
|
||||||
|
uint32_t tileTextureIndex;
|
||||||
|
uint32_t packedTextureIndex;
|
||||||
|
uint32_t blueNoiseTextureIndex;
|
||||||
|
uint32_t pointSamplerIndex; // clamp
|
||||||
|
uint32_t linearSamplerIndex; // clamp
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
|
||||||
|
void MotionBlur::Init()
|
||||||
|
{
|
||||||
|
tileTextureWidth = (uint32_t)(glConfig.vidWidth + 15) / 16;
|
||||||
|
tileTextureHeight = (uint32_t)(glConfig.vidHeight + 15) / 16;
|
||||||
|
|
||||||
|
{
|
||||||
|
GraphicsPipelineDesc desc("MBlur velocity/depth packing");
|
||||||
|
desc.shortLifeTime = true;
|
||||||
|
desc.vertexShader = ShaderByteCode(g_fullscreen_vs);
|
||||||
|
desc.pixelShader = ShaderByteCode(g_pack_ps);
|
||||||
|
desc.depthStencil.DisableDepth();
|
||||||
|
desc.rasterizer.cullMode = CT_TWO_SIDED;
|
||||||
|
desc.AddRenderTarget(0, TextureFormat::R32G32_UInt);
|
||||||
|
packPipeline = CreateGraphicsPipeline(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ComputePipelineDesc desc("MBlur tile generation");
|
||||||
|
desc.shortLifeTime = true;
|
||||||
|
desc.shader = ShaderByteCode(g_tile_gen_cs);
|
||||||
|
tileGenPipeline = CreateComputePipeline(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ComputePipelineDesc desc("MBlur tile dilation");
|
||||||
|
desc.shortLifeTime = true;
|
||||||
|
desc.shader = ShaderByteCode(g_tile_max_cs);
|
||||||
|
tileMaxPipeline = CreateComputePipeline(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
GraphicsPipelineDesc desc("MBlur reconstruction filter");
|
||||||
|
desc.shortLifeTime = true;
|
||||||
|
desc.vertexShader = ShaderByteCode(g_fullscreen_vs);
|
||||||
|
desc.pixelShader = ShaderByteCode(g_blur_ps);
|
||||||
|
desc.depthStencil.DisableDepth();
|
||||||
|
desc.rasterizer.cullMode = CT_TWO_SIDED;
|
||||||
|
desc.AddRenderTarget(0, crp.renderTargetFormat);
|
||||||
|
blurPipeline = CreateGraphicsPipeline(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
TextureDesc desc("MBlur velocity tile #1", tileTextureWidth, tileTextureHeight);
|
||||||
|
desc.shortLifeTime = true;
|
||||||
|
desc.committedResource = true;
|
||||||
|
desc.initialState = ResourceStates::UnorderedAccessBit;
|
||||||
|
desc.allowedState = ResourceStates::UnorderedAccessBit | ResourceStates::ComputeShaderAccessBit | ResourceStates::PixelShaderAccessBit;
|
||||||
|
desc.format = TextureFormat::R16G16_Float;
|
||||||
|
tileTexture = CreateTexture(desc);
|
||||||
|
desc.name = "MBlur velocity tile #2";
|
||||||
|
tileTexture2 = CreateTexture(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
TextureDesc desc("MBlur packed velocity/depth", glConfig.vidWidth, glConfig.vidHeight);
|
||||||
|
desc.shortLifeTime = true;
|
||||||
|
desc.committedResource = true;
|
||||||
|
desc.initialState = ResourceStates::RenderTargetBit;
|
||||||
|
desc.allowedState = ResourceStates::RenderTargetBit | ResourceStates::ComputeShaderAccessBit | ResourceStates::PixelShaderAccessBit;
|
||||||
|
desc.format = TextureFormat::R32G32_UInt;
|
||||||
|
packedTexture = CreateTexture(desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MotionBlur::Draw()
|
||||||
|
{
|
||||||
|
if(crp_mblur->integer == 0 ||
|
||||||
|
(backEnd.refdef.rdflags & RDF_CNQ3_TELEPORTED) != 0 ||
|
||||||
|
!IsViewportFullscreen(backEnd.viewParms))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawPack();
|
||||||
|
DrawTileGen();
|
||||||
|
DrawTileMax();
|
||||||
|
DrawBlur();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MotionBlur::DrawPack()
|
||||||
|
{
|
||||||
|
SCOPED_RENDER_PASS("MBlur Pack", 0.125f, 0.125f, 0.25f);
|
||||||
|
|
||||||
|
CmdBeginBarrier();
|
||||||
|
CmdTextureBarrier(crp.motionVectorMBTexture, ResourceStates::PixelShaderAccessBit);
|
||||||
|
CmdTextureBarrier(crp.depthTexture, ResourceStates::PixelShaderAccessBit);
|
||||||
|
CmdTextureBarrier(packedTexture, ResourceStates::RenderTargetBit);
|
||||||
|
CmdEndBarrier();
|
||||||
|
|
||||||
|
MBPackRC rc = {};
|
||||||
|
rc.motionScale = crp_mblur_exposure->value;
|
||||||
|
rc.maxRadiusPx = min(glConfig.vidHeight / 25.0f, 30.0f);
|
||||||
|
|
||||||
|
CmdBindRenderTargets(1, &packedTexture, NULL);
|
||||||
|
CmdBindPipeline(packPipeline);
|
||||||
|
CmdSetGraphicsRootConstants(0, sizeof(rc), &rc);
|
||||||
|
CmdDraw(3, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MotionBlur::DrawTileGen()
|
||||||
|
{
|
||||||
|
SCOPED_RENDER_PASS("MBlur Tile Gen", 0.125f, 0.125f, 0.25f);
|
||||||
|
|
||||||
|
CmdBeginBarrier();
|
||||||
|
CmdTextureBarrier(packedTexture, ResourceStates::ComputeShaderAccessBit);
|
||||||
|
CmdTextureBarrier(tileTexture, ResourceStates::UnorderedAccessBit);
|
||||||
|
CmdEndBarrier();
|
||||||
|
|
||||||
|
MBTileGenRC rc = {};
|
||||||
|
rc.inputTextureIndex = GetTextureIndexSRV(packedTexture);
|
||||||
|
rc.outputTextureIndex = GetTextureIndexUAV(tileTexture, 0);
|
||||||
|
|
||||||
|
CmdBindPipeline(tileGenPipeline);
|
||||||
|
CmdSetComputeRootConstants(0, sizeof(rc), &rc);
|
||||||
|
CmdDispatch((tileTextureWidth + 7) / 8, (tileTextureHeight + 7) / 8, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MotionBlur::DrawTileMax()
|
||||||
|
{
|
||||||
|
SCOPED_RENDER_PASS("MBlur Tile Max", 0.125f, 0.125f, 0.25f);
|
||||||
|
|
||||||
|
CmdBeginBarrier();
|
||||||
|
CmdTextureBarrier(tileTexture, ResourceStates::ComputeShaderAccessBit);
|
||||||
|
CmdTextureBarrier(tileTexture2, ResourceStates::UnorderedAccessBit);
|
||||||
|
CmdEndBarrier();
|
||||||
|
|
||||||
|
MBTileMaxRC rc = {};
|
||||||
|
rc.inputTextureIndex = GetTextureIndexSRV(tileTexture);
|
||||||
|
rc.outputTextureIndex = GetTextureIndexUAV(tileTexture2, 0);
|
||||||
|
rc.samplerIndex = GetSamplerIndex(TW_CLAMP_TO_EDGE, TextureFilter::Point);
|
||||||
|
|
||||||
|
CmdBindPipeline(tileMaxPipeline);
|
||||||
|
CmdSetComputeRootConstants(0, sizeof(rc), &rc);
|
||||||
|
CmdDispatch((tileTextureWidth + 7) / 8, (tileTextureHeight + 7) / 8, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MotionBlur::DrawBlur()
|
||||||
|
{
|
||||||
|
SCOPED_RENDER_PASS("MBlur Blur", 0.125f, 0.125f, 0.25f);
|
||||||
|
|
||||||
|
crp.SwapRenderTargets();
|
||||||
|
|
||||||
|
CmdBeginBarrier();
|
||||||
|
CmdTextureBarrier(crp.GetReadRenderTarget(), ResourceStates::PixelShaderAccessBit);
|
||||||
|
CmdTextureBarrier(tileTexture2, ResourceStates::PixelShaderAccessBit);
|
||||||
|
CmdTextureBarrier(packedTexture, ResourceStates::PixelShaderAccessBit);
|
||||||
|
CmdTextureBarrier(crp.renderTarget, ResourceStates::RenderTargetBit);
|
||||||
|
CmdEndBarrier();
|
||||||
|
|
||||||
|
MBBlurRC rc = {};
|
||||||
|
rc.colorTextureIndex = GetTextureIndexSRV(crp.GetReadRenderTarget());
|
||||||
|
rc.tileTextureIndex = GetTextureIndexSRV(tileTexture2);
|
||||||
|
rc.packedTextureIndex = GetTextureIndexSRV(packedTexture);
|
||||||
|
rc.blueNoiseTextureIndex = GetTextureIndexSRV(crp.blueNoise2D);
|
||||||
|
rc.pointSamplerIndex = GetSamplerIndex(TW_CLAMP_TO_EDGE, TextureFilter::Point);
|
||||||
|
rc.linearSamplerIndex = GetSamplerIndex(TW_CLAMP_TO_EDGE, TextureFilter::Linear);
|
||||||
|
|
||||||
|
CmdBindRenderTargets(1, &crp.renderTarget, NULL);
|
||||||
|
CmdBindPipeline(blurPipeline);
|
||||||
|
CmdSetGraphicsRootConstants(0, sizeof(rc), &rc);
|
||||||
|
CmdDraw(3, 0);
|
||||||
|
}
|
|
@ -23,6 +23,8 @@ along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include "crp_local.h"
|
#include "crp_local.h"
|
||||||
#include "compshaders/crp/prepass.h"
|
#include "compshaders/crp/prepass.h"
|
||||||
|
#include "compshaders/crp/fullscreen.h"
|
||||||
|
#include "compshaders/crp/skybox_motion.h"
|
||||||
|
|
||||||
|
|
||||||
#pragma pack(push, 4)
|
#pragma pack(push, 4)
|
||||||
|
@ -30,17 +32,128 @@ struct PrepassRC
|
||||||
{
|
{
|
||||||
float modelViewMatrix[16];
|
float modelViewMatrix[16];
|
||||||
float modelMatrix[16];
|
float modelMatrix[16];
|
||||||
float normalMatrix[16];
|
float prevModelMatrix[16];
|
||||||
|
float normalMatrix[9];
|
||||||
|
float motionBlurScale;
|
||||||
uint32_t textureIndex;
|
uint32_t textureIndex;
|
||||||
uint32_t samplerIndex;
|
uint32_t samplerIndex;
|
||||||
uint32_t alphaTest;
|
uint32_t alphaTest;
|
||||||
|
uint32_t motionBlurMode;
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
|
||||||
|
struct EntityData
|
||||||
|
{
|
||||||
|
float modelMatrix[16];
|
||||||
|
int uniqueId;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EntityTracker
|
||||||
|
{
|
||||||
|
void BeginFrame()
|
||||||
|
{
|
||||||
|
Q_assert(!begun);
|
||||||
|
Q_assert(!enabled);
|
||||||
|
|
||||||
|
const viewParms_t& vp = backEnd.viewParms;
|
||||||
|
enabled = IsViewportFullscreen(vp) && !vp.isPortal;
|
||||||
|
begun = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EndFrame()
|
||||||
|
{
|
||||||
|
Q_assert(begun);
|
||||||
|
|
||||||
|
begun = false;
|
||||||
|
if(enabled)
|
||||||
|
{
|
||||||
|
enabled = false;
|
||||||
|
EntityArray* prevEntsCopy = prevEnts;
|
||||||
|
prevEnts = currEnts;
|
||||||
|
currEnts = prevEntsCopy;
|
||||||
|
currEnts->Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompareEntity(float* prevModelMatrix, int uniqueId, const float* modelMatrix)
|
||||||
|
{
|
||||||
|
Q_assert(begun);
|
||||||
|
|
||||||
|
if(!enabled || uniqueId == 0)
|
||||||
|
{
|
||||||
|
memcpy(prevModelMatrix, modelMatrix, 16 * sizeof(float));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityData* prevEnt = NULL;
|
||||||
|
for(uint32_t i = 0, end = prevEnts->count; i < end; i++)
|
||||||
|
{
|
||||||
|
EntityData& ent = (*prevEnts)[i];
|
||||||
|
if(ent.uniqueId == uniqueId)
|
||||||
|
{
|
||||||
|
prevEnt = &ent;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(prevEnt != NULL)
|
||||||
|
{
|
||||||
|
memcpy(prevModelMatrix, prevEnt->modelMatrix, 16 * sizeof(float));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(prevModelMatrix, modelMatrix, 16 * sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityData* currEnt = NULL;
|
||||||
|
for(uint32_t i = 0, end = currEnts->count; i < end; i++)
|
||||||
|
{
|
||||||
|
EntityData& ent = (*currEnts)[i];
|
||||||
|
if(ent.uniqueId == uniqueId)
|
||||||
|
{
|
||||||
|
currEnt = &ent;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(currEnt != NULL)
|
||||||
|
{
|
||||||
|
memcpy(currEnt->modelMatrix, modelMatrix, 16 * sizeof(float));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EntityData ent;
|
||||||
|
memcpy(ent.modelMatrix, modelMatrix, 16 * sizeof(float));
|
||||||
|
ent.uniqueId = uniqueId;
|
||||||
|
currEnts->Add(ent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef RHI::StaticUnorderedArray<EntityData, 16384> EntityArray;
|
||||||
|
EntityArray entities[2];
|
||||||
|
EntityArray* currEnts = &entities[0];
|
||||||
|
EntityArray* prevEnts = &entities[1];
|
||||||
|
bool enabled;
|
||||||
|
bool begun;
|
||||||
|
};
|
||||||
|
|
||||||
|
static EntityTracker et;
|
||||||
|
|
||||||
|
|
||||||
void Prepass::Init()
|
void Prepass::Init()
|
||||||
{
|
{
|
||||||
psoCache.Init(psoCacheEntries, ARRAY_LEN(psoCacheEntries));
|
psoCache.Init(psoCacheEntries, ARRAY_LEN(psoCacheEntries));
|
||||||
|
|
||||||
|
{
|
||||||
|
GraphicsPipelineDesc desc("Skybox Motion Vectors");
|
||||||
|
desc.shortLifeTime = true;
|
||||||
|
desc.vertexShader.Set(g_fullscreen_vs);
|
||||||
|
desc.pixelShader.Set(g_skybox_motion_ps);
|
||||||
|
desc.depthStencil.DisableDepth();
|
||||||
|
desc.rasterizer.cullMode = CT_TWO_SIDED;
|
||||||
|
desc.AddRenderTarget(0, TextureFormat::R16G16_Float);
|
||||||
|
skyboxMotionPipeline = CreateGraphicsPipeline(desc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Prepass::Draw(const drawSceneViewCommand_t& cmd)
|
void Prepass::Draw(const drawSceneViewCommand_t& cmd)
|
||||||
|
@ -57,6 +170,8 @@ void Prepass::Draw(const drawSceneViewCommand_t& cmd)
|
||||||
backEnd.refdef = cmd.refdef;
|
backEnd.refdef = cmd.refdef;
|
||||||
backEnd.viewParms = cmd.viewParms;
|
backEnd.viewParms = cmd.viewParms;
|
||||||
|
|
||||||
|
et.BeginFrame();
|
||||||
|
|
||||||
CmdSetViewportAndScissor(backEnd.viewParms);
|
CmdSetViewportAndScissor(backEnd.viewParms);
|
||||||
batchOldDepthHack = false;
|
batchOldDepthHack = false;
|
||||||
batchDepthHack = false;
|
batchDepthHack = false;
|
||||||
|
@ -65,18 +180,44 @@ void Prepass::Draw(const drawSceneViewCommand_t& cmd)
|
||||||
CmdTextureBarrier(crp.depthTexture, ResourceStates::DepthWriteBit);
|
CmdTextureBarrier(crp.depthTexture, ResourceStates::DepthWriteBit);
|
||||||
CmdTextureBarrier(crp.normalTexture, ResourceStates::RenderTargetBit);
|
CmdTextureBarrier(crp.normalTexture, ResourceStates::RenderTargetBit);
|
||||||
CmdTextureBarrier(crp.motionVectorTexture, ResourceStates::RenderTargetBit);
|
CmdTextureBarrier(crp.motionVectorTexture, ResourceStates::RenderTargetBit);
|
||||||
|
CmdTextureBarrier(crp.motionVectorMBTexture, ResourceStates::RenderTargetBit);
|
||||||
CmdTextureBarrier(crp.shadingPositionTexture, ResourceStates::RenderTargetBit);
|
CmdTextureBarrier(crp.shadingPositionTexture, ResourceStates::RenderTargetBit);
|
||||||
CmdEndBarrier();
|
CmdEndBarrier();
|
||||||
|
|
||||||
CmdClearDepthStencilTarget(crp.depthTexture, true, 0.0f);
|
CmdClearDepthStencilTarget(crp.depthTexture, true, 0.0f);
|
||||||
CmdClearColorTarget(crp.normalTexture, vec4_zero, NULL);
|
CmdClearColorTarget(crp.normalTexture, vec4_zero, NULL);
|
||||||
CmdClearColorTarget(crp.motionVectorTexture, vec4_zero, NULL);
|
|
||||||
CmdClearColorTarget(crp.shadingPositionTexture, vec4_zero, NULL);
|
CmdClearColorTarget(crp.shadingPositionTexture, vec4_zero, NULL);
|
||||||
|
|
||||||
|
// clear the motion vectors with skybox values
|
||||||
|
CmdBeginDebugLabel("Skybox Motion Vectors");
|
||||||
|
{
|
||||||
|
CmdBindRenderTargets(1, &crp.motionVectorTexture, NULL);
|
||||||
|
CmdBindPipeline(skyboxMotionPipeline);
|
||||||
|
CmdDraw(3, 0);
|
||||||
|
|
||||||
|
if(crp_mblur->integer & MotionBlurModes::CameraBit)
|
||||||
|
{
|
||||||
|
CmdBindRenderTargets(1, &crp.motionVectorMBTexture, NULL);
|
||||||
|
CmdBindPipeline(skyboxMotionPipeline);
|
||||||
|
CmdDraw(3, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CmdClearColorTarget(crp.motionVectorMBTexture, vec4_zero, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CmdEndDebugLabel();
|
||||||
|
|
||||||
GeoBuffers& db = crp.dynBuffers[GetFrameIndex()];
|
GeoBuffers& db = crp.dynBuffers[GetFrameIndex()];
|
||||||
db.BeginUpload();
|
db.BeginUpload();
|
||||||
|
|
||||||
const HTexture renderTargets[] = { crp.normalTexture, crp.motionVectorTexture, crp.shadingPositionTexture };
|
const HTexture renderTargets[] =
|
||||||
|
{
|
||||||
|
crp.normalTexture,
|
||||||
|
crp.motionVectorTexture,
|
||||||
|
crp.motionVectorMBTexture,
|
||||||
|
crp.shadingPositionTexture
|
||||||
|
};
|
||||||
CmdBindRenderTargets(ARRAY_LEN(renderTargets), renderTargets, &crp.depthTexture);
|
CmdBindRenderTargets(ARRAY_LEN(renderTargets), renderTargets, &crp.depthTexture);
|
||||||
CmdBindVertexBuffers(ARRAY_LEN(db.vertexBuffers), db.vertexBuffers, db.vertexBufferStrides, NULL);
|
CmdBindVertexBuffers(ARRAY_LEN(db.vertexBuffers), db.vertexBuffers, db.vertexBufferStrides, NULL);
|
||||||
CmdBindIndexBuffer(db.indexBuffer.buffer, IndexType::UInt32, 0);
|
CmdBindIndexBuffer(db.indexBuffer.buffer, IndexType::UInt32, 0);
|
||||||
|
@ -88,6 +229,7 @@ void Prepass::Draw(const drawSceneViewCommand_t& cmd)
|
||||||
const shader_t* shader = NULL;
|
const shader_t* shader = NULL;
|
||||||
const shader_t* oldShader = NULL;
|
const shader_t* oldShader = NULL;
|
||||||
int oldEntityNum = -1;
|
int oldEntityNum = -1;
|
||||||
|
batchEntityId = -1;
|
||||||
backEnd.currentEntity = &tr.worldEntity;
|
backEnd.currentEntity = &tr.worldEntity;
|
||||||
|
|
||||||
tess.numVertexes = 0;
|
tess.numVertexes = 0;
|
||||||
|
@ -109,13 +251,16 @@ void Prepass::Draw(const drawSceneViewCommand_t& cmd)
|
||||||
|
|
||||||
const bool shaderChanged = shader != oldShader;
|
const bool shaderChanged = shader != oldShader;
|
||||||
const bool entityChanged = entityNum != oldEntityNum;
|
const bool entityChanged = entityNum != oldEntityNum;
|
||||||
if(shaderChanged || entityChanged)
|
const bool idChanged = drawSurf->uniqueEntityId != batchEntityId;
|
||||||
|
if(shaderChanged || entityChanged || idChanged)
|
||||||
{
|
{
|
||||||
oldShader = shader;
|
oldShader = shader;
|
||||||
oldEntityNum = entityNum;
|
oldEntityNum = entityNum;
|
||||||
EndBatch();
|
EndBatch();
|
||||||
BeginBatch(shader);
|
BeginBatch(shader);
|
||||||
tess.greyscale = drawSurf->greyscale;
|
tess.greyscale = drawSurf->greyscale;
|
||||||
|
batchEntityId = drawSurf->uniqueEntityId;
|
||||||
|
batchMotionScale = drawSurf->motionBlurScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(entityChanged)
|
if(entityChanged)
|
||||||
|
@ -136,6 +281,8 @@ void Prepass::Draw(const drawSceneViewCommand_t& cmd)
|
||||||
CmdSetViewportAndScissor(backEnd.viewParms);
|
CmdSetViewportAndScissor(backEnd.viewParms);
|
||||||
batchOldDepthHack = false;
|
batchOldDepthHack = false;
|
||||||
batchDepthHack = false;
|
batchDepthHack = false;
|
||||||
|
|
||||||
|
et.EndFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Prepass::ProcessShader(shader_t& shader)
|
void Prepass::ProcessShader(shader_t& shader)
|
||||||
|
@ -181,9 +328,10 @@ void Prepass::ProcessShader(shader_t& shader)
|
||||||
desc.rasterizer.cullMode = shader.cullType;
|
desc.rasterizer.cullMode = shader.cullType;
|
||||||
desc.rasterizer.polygonOffset = shader.polygonOffset != 0;
|
desc.rasterizer.polygonOffset = shader.polygonOffset != 0;
|
||||||
desc.rasterizer.clampDepth = clampDepth;
|
desc.rasterizer.clampDepth = clampDepth;
|
||||||
desc.AddRenderTarget(0, TextureFormat::RG32_SNorm);
|
desc.AddRenderTarget(0, TextureFormat::R16G16_SNorm);
|
||||||
desc.AddRenderTarget(0, TextureFormat::RG32_Float);
|
desc.AddRenderTarget(0, TextureFormat::R16G16_Float);
|
||||||
desc.AddRenderTarget(0, TextureFormat::RGBA128_Float);
|
desc.AddRenderTarget(0, TextureFormat::R16G16_Float);
|
||||||
|
desc.AddRenderTarget(0, TextureFormat::R32G32B32A32_Float);
|
||||||
|
|
||||||
pipeline_t& p = shader.prepassPipeline;
|
pipeline_t& p = shader.prepassPipeline;
|
||||||
p.firstStage = 0;
|
p.firstStage = 0;
|
||||||
|
@ -219,6 +367,7 @@ void Prepass::EndBatch()
|
||||||
{
|
{
|
||||||
PrepassRC rc = {};
|
PrepassRC rc = {};
|
||||||
float tempMatrix[16];
|
float tempMatrix[16];
|
||||||
|
float normalMatrix[16];
|
||||||
|
|
||||||
const int vertexCount = tess.numVertexes;
|
const int vertexCount = tess.numVertexes;
|
||||||
const int indexCount = tess.numIndexes;
|
const int indexCount = tess.numIndexes;
|
||||||
|
@ -265,13 +414,26 @@ void Prepass::EndBatch()
|
||||||
const uint32_t alphaTest = AlphaTestShaderConstFromStateBits(stage->stateBits);
|
const uint32_t alphaTest = AlphaTestShaderConstFromStateBits(stage->stateBits);
|
||||||
Q_assert(sampIdx < ARRAY_LEN(crp.samplers));
|
Q_assert(sampIdx < ARRAY_LEN(crp.samplers));
|
||||||
|
|
||||||
|
R_InvMatrix(backEnd.modelMatrix, tempMatrix);
|
||||||
|
R_TransposeMatrix(tempMatrix, normalMatrix);
|
||||||
|
|
||||||
memcpy(rc.modelViewMatrix, backEnd.orient.modelMatrix, sizeof(rc.modelViewMatrix));
|
memcpy(rc.modelViewMatrix, backEnd.orient.modelMatrix, sizeof(rc.modelViewMatrix));
|
||||||
memcpy(rc.modelMatrix, backEnd.modelMatrix, sizeof(rc.modelMatrix));
|
memcpy(rc.modelMatrix, backEnd.modelMatrix, sizeof(rc.modelMatrix));
|
||||||
R_InvMatrix(backEnd.modelMatrix, tempMatrix);
|
et.CompareEntity(rc.prevModelMatrix, batchEntityId, backEnd.modelMatrix);
|
||||||
R_TransposeMatrix(tempMatrix, rc.normalMatrix);
|
rc.normalMatrix[0] = normalMatrix[ 0];
|
||||||
|
rc.normalMatrix[1] = normalMatrix[ 1];
|
||||||
|
rc.normalMatrix[2] = normalMatrix[ 2];
|
||||||
|
rc.normalMatrix[3] = normalMatrix[ 4];
|
||||||
|
rc.normalMatrix[4] = normalMatrix[ 5];
|
||||||
|
rc.normalMatrix[5] = normalMatrix[ 6];
|
||||||
|
rc.normalMatrix[6] = normalMatrix[ 8];
|
||||||
|
rc.normalMatrix[7] = normalMatrix[ 9];
|
||||||
|
rc.normalMatrix[8] = normalMatrix[10];
|
||||||
|
rc.motionBlurScale = batchMotionScale;
|
||||||
rc.textureIndex = texIdx;
|
rc.textureIndex = texIdx;
|
||||||
rc.samplerIndex = sampIdx;
|
rc.samplerIndex = sampIdx;
|
||||||
rc.alphaTest = alphaTest;
|
rc.alphaTest = alphaTest;
|
||||||
|
rc.motionBlurMode = crp_mblur->integer;
|
||||||
CmdSetGraphicsRootConstants(0, sizeof(rc), &rc);
|
CmdSetGraphicsRootConstants(0, sizeof(rc), &rc);
|
||||||
|
|
||||||
db.DrawStage(vertexCount, indexCount);
|
db.DrawStage(vertexCount, indexCount);
|
||||||
|
|
|
@ -172,11 +172,11 @@ void GRP::Init()
|
||||||
renderTargetFormat = TextureFormat::R10G10B10A2_UNorm;
|
renderTargetFormat = TextureFormat::R10G10B10A2_UNorm;
|
||||||
break;
|
break;
|
||||||
case RTCF_R16G16B16A16:
|
case RTCF_R16G16B16A16:
|
||||||
renderTargetFormat = TextureFormat::RGBA64_UNorm;
|
renderTargetFormat = TextureFormat::R16G16B16A16_UNorm;
|
||||||
break;
|
break;
|
||||||
case RTCF_R8G8B8A8:
|
case RTCF_R8G8B8A8:
|
||||||
default:
|
default:
|
||||||
renderTargetFormat = TextureFormat::RGBA32_UNorm;
|
renderTargetFormat = TextureFormat::R8G8B8A8_UNorm;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,7 +198,7 @@ void GRP::Init()
|
||||||
Vector4Clear(desc.clearColor);
|
Vector4Clear(desc.clearColor);
|
||||||
desc.usePreferredClearValue = true;
|
desc.usePreferredClearValue = true;
|
||||||
desc.committedResource = true;
|
desc.committedResource = true;
|
||||||
desc.format = TextureFormat::RGBA32_UNorm;
|
desc.format = TextureFormat::R8G8B8A8_UNorm;
|
||||||
desc.shortLifeTime = true;
|
desc.shortLifeTime = true;
|
||||||
readbackRenderTarget = RHI::CreateTexture(desc);
|
readbackRenderTarget = RHI::CreateTexture(desc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,9 +58,9 @@ void PostProcess::Init()
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureFormat::Id rtFormats[RTCF_COUNT] = {};
|
TextureFormat::Id rtFormats[RTCF_COUNT] = {};
|
||||||
rtFormats[RTCF_R8G8B8A8] = TextureFormat::RGBA32_UNorm;
|
rtFormats[RTCF_R8G8B8A8] = TextureFormat::R8G8B8A8_UNorm;
|
||||||
rtFormats[RTCF_R10G10B10A2] = TextureFormat::R10G10B10A2_UNorm;
|
rtFormats[RTCF_R10G10B10A2] = TextureFormat::R10G10B10A2_UNorm;
|
||||||
rtFormats[RTCF_R16G16B16A16] = TextureFormat::RGBA64_UNorm;
|
rtFormats[RTCF_R16G16B16A16] = TextureFormat::R16G16B16A16_UNorm;
|
||||||
for(int i = 0; i < RTCF_COUNT; ++i)
|
for(int i = 0; i < RTCF_COUNT; ++i)
|
||||||
{
|
{
|
||||||
Q_assert((int)rtFormats[i] > 0 && (int)rtFormats[i] < TextureFormat::Count);
|
Q_assert((int)rtFormats[i] > 0 && (int)rtFormats[i] < TextureFormat::Count);
|
||||||
|
@ -91,7 +91,7 @@ void PostProcess::Init()
|
||||||
desc.pixelShader = ShaderByteCode(g_post_ps);
|
desc.pixelShader = ShaderByteCode(g_post_ps);
|
||||||
desc.depthStencil.DisableDepth();
|
desc.depthStencil.DisableDepth();
|
||||||
desc.rasterizer.cullMode = CT_TWO_SIDED;
|
desc.rasterizer.cullMode = CT_TWO_SIDED;
|
||||||
desc.AddRenderTarget(0, TextureFormat::RGBA32_UNorm);
|
desc.AddRenderTarget(0, TextureFormat::R8G8B8A8_UNorm);
|
||||||
toneMapPipeline = CreateGraphicsPipeline(desc);
|
toneMapPipeline = CreateGraphicsPipeline(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -134,7 +134,7 @@ void SMAA::Update()
|
||||||
desc.initialState = ResourceStates::PixelShaderAccessBit;
|
desc.initialState = ResourceStates::PixelShaderAccessBit;
|
||||||
desc.allowedState = ResourceStates::PixelShaderAccessBit;
|
desc.allowedState = ResourceStates::PixelShaderAccessBit;
|
||||||
desc.committedResource = true;
|
desc.committedResource = true;
|
||||||
desc.format = TextureFormat::RG16_UNorm;
|
desc.format = TextureFormat::R8G8_UNorm;
|
||||||
areaTexture = CreateTexture(desc);
|
areaTexture = CreateTexture(desc);
|
||||||
|
|
||||||
MappedTexture texture;
|
MappedTexture texture;
|
||||||
|
@ -208,7 +208,7 @@ void SMAA::Update()
|
||||||
Vector4Clear(desc.clearColor);
|
Vector4Clear(desc.clearColor);
|
||||||
desc.usePreferredClearValue = true;
|
desc.usePreferredClearValue = true;
|
||||||
desc.committedResource = true;
|
desc.committedResource = true;
|
||||||
desc.format = TextureFormat::RG16_UNorm;
|
desc.format = TextureFormat::R8G8_UNorm;
|
||||||
edgeTexture = CreateTexture(desc);
|
edgeTexture = CreateTexture(desc);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -218,7 +218,7 @@ void SMAA::Update()
|
||||||
Vector4Clear(desc.clearColor);
|
Vector4Clear(desc.clearColor);
|
||||||
desc.usePreferredClearValue = true;
|
desc.usePreferredClearValue = true;
|
||||||
desc.committedResource = true;
|
desc.committedResource = true;
|
||||||
desc.format = TextureFormat::RGBA32_UNorm;
|
desc.format = TextureFormat::R8G8B8A8_UNorm;
|
||||||
blendTexture = CreateTexture(desc);
|
blendTexture = CreateTexture(desc);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -226,7 +226,7 @@ void SMAA::Update()
|
||||||
desc.initialState = ResourceStates::RenderTargetBit;
|
desc.initialState = ResourceStates::RenderTargetBit;
|
||||||
desc.allowedState = ResourceStates::RenderTargetBit | ResourceStates::PixelShaderAccessBit;
|
desc.allowedState = ResourceStates::RenderTargetBit | ResourceStates::PixelShaderAccessBit;
|
||||||
desc.committedResource = true;
|
desc.committedResource = true;
|
||||||
desc.format = TextureFormat::RGBA32_UNorm;
|
desc.format = TextureFormat::R8G8B8A8_UNorm;
|
||||||
inputTexture = CreateTexture(desc);
|
inputTexture = CreateTexture(desc);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -234,7 +234,7 @@ void SMAA::Update()
|
||||||
desc.initialState = ResourceStates::RenderTargetBit;
|
desc.initialState = ResourceStates::RenderTargetBit;
|
||||||
desc.allowedState = ResourceStates::RenderTargetBit | ResourceStates::PixelShaderAccessBit;
|
desc.allowedState = ResourceStates::RenderTargetBit | ResourceStates::PixelShaderAccessBit;
|
||||||
desc.committedResource = true;
|
desc.committedResource = true;
|
||||||
desc.format = TextureFormat::RGBA32_UNorm;
|
desc.format = TextureFormat::R8G8B8A8_UNorm;
|
||||||
outputTexture = CreateTexture(desc);
|
outputTexture = CreateTexture(desc);
|
||||||
|
|
||||||
grp.post.SetInverseToneMapInput(outputTexture);
|
grp.post.SetInverseToneMapInput(outputTexture);
|
||||||
|
@ -281,7 +281,7 @@ void SMAA::Update()
|
||||||
desc.depthStencil.frontFace.passOp = StencilOp::Replace;
|
desc.depthStencil.frontFace.passOp = StencilOp::Replace;
|
||||||
desc.depthStencil.backFace.passOp = StencilOp::Replace;
|
desc.depthStencil.backFace.passOp = StencilOp::Replace;
|
||||||
desc.rasterizer.cullMode = CT_TWO_SIDED;
|
desc.rasterizer.cullMode = CT_TWO_SIDED;
|
||||||
desc.AddRenderTarget(0, TextureFormat::RG16_UNorm);
|
desc.AddRenderTarget(0, TextureFormat::R8G8_UNorm);
|
||||||
firstPassPipeline = CreateGraphicsPipeline(desc);
|
firstPassPipeline = CreateGraphicsPipeline(desc);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -295,7 +295,7 @@ void SMAA::Update()
|
||||||
desc.depthStencil.frontFace.comparison = ComparisonFunction::Equal;
|
desc.depthStencil.frontFace.comparison = ComparisonFunction::Equal;
|
||||||
desc.depthStencil.backFace.comparison = ComparisonFunction::Equal;
|
desc.depthStencil.backFace.comparison = ComparisonFunction::Equal;
|
||||||
desc.rasterizer.cullMode = CT_TWO_SIDED;
|
desc.rasterizer.cullMode = CT_TWO_SIDED;
|
||||||
desc.AddRenderTarget(0, TextureFormat::RGBA32_UNorm);
|
desc.AddRenderTarget(0, TextureFormat::R8G8B8A8_UNorm);
|
||||||
secondPassPipeline = CreateGraphicsPipeline(desc);
|
secondPassPipeline = CreateGraphicsPipeline(desc);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -304,7 +304,7 @@ void SMAA::Update()
|
||||||
desc.pixelShader = GetShaderByteCode(2, true);
|
desc.pixelShader = GetShaderByteCode(2, true);
|
||||||
desc.depthStencil.DisableDepth();
|
desc.depthStencil.DisableDepth();
|
||||||
desc.rasterizer.cullMode = CT_TWO_SIDED;
|
desc.rasterizer.cullMode = CT_TWO_SIDED;
|
||||||
desc.AddRenderTarget(0, TextureFormat::RGBA32_UNorm);
|
desc.AddRenderTarget(0, TextureFormat::R8G8B8A8_UNorm);
|
||||||
thirdPassPipeline = CreateGraphicsPipeline(desc);
|
thirdPassPipeline = CreateGraphicsPipeline(desc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -877,16 +877,22 @@ namespace RHI
|
||||||
{
|
{
|
||||||
switch(format)
|
switch(format)
|
||||||
{
|
{
|
||||||
case TextureFormat::RGBA128_Float:
|
case TextureFormat::R32G32B32A32_Float:
|
||||||
return 16;
|
return 16;
|
||||||
case TextureFormat::RGBA64_Float:
|
case TextureFormat::R16G16B16A16_UNorm:
|
||||||
|
case TextureFormat::R16G16B16A16_Float:
|
||||||
|
case TextureFormat::R32G32_Float:
|
||||||
|
case TextureFormat::R32G32_UInt:
|
||||||
return 8;
|
return 8;
|
||||||
case TextureFormat::RGBA32_UNorm:
|
case TextureFormat::R8G8B8A8_UNorm:
|
||||||
case TextureFormat::Depth32_Float:
|
case TextureFormat::Depth32_Float:
|
||||||
case TextureFormat::Depth24_Stencil8:
|
case TextureFormat::Depth24_Stencil8:
|
||||||
case TextureFormat::R10G10B10A2_UNorm:
|
case TextureFormat::R10G10B10A2_UNorm:
|
||||||
|
case TextureFormat::R32_UInt:
|
||||||
|
case TextureFormat::R16G16_SNorm:
|
||||||
|
case TextureFormat::R16G16_Float:
|
||||||
return 4;
|
return 4;
|
||||||
case TextureFormat::RG16_UNorm:
|
case TextureFormat::R8G8_UNorm:
|
||||||
return 2;
|
return 2;
|
||||||
case TextureFormat::R8_UNorm:
|
case TextureFormat::R8_UNorm:
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1260,7 +1266,7 @@ namespace RHI
|
||||||
D3D(readbackCommandList->Reset(readbackCommandAllocator, NULL));
|
D3D(readbackCommandList->Reset(readbackCommandAllocator, NULL));
|
||||||
|
|
||||||
Texture& texture = rhi.textures.Get(htexture);
|
Texture& texture = rhi.textures.Get(htexture);
|
||||||
Q_assert(texture.desc.format == TextureFormat::RGBA32_UNorm);
|
Q_assert(texture.desc.format == TextureFormat::R8G8B8A8_UNorm);
|
||||||
const D3D12_RESOURCE_DESC textureDesc = texture.texture->GetDesc();
|
const D3D12_RESOURCE_DESC textureDesc = texture.texture->GetDesc();
|
||||||
D3D12_PLACED_SUBRESOURCE_FOOTPRINT layout;
|
D3D12_PLACED_SUBRESOURCE_FOOTPRINT layout;
|
||||||
rhi.device->GetCopyableFootprints(&textureDesc, 0, 1, 0, &layout, NULL, NULL, NULL);
|
rhi.device->GetCopyableFootprints(&textureDesc, 0, 1, 0, &layout, NULL, NULL, NULL);
|
||||||
|
@ -1804,18 +1810,20 @@ namespace RHI
|
||||||
{
|
{
|
||||||
switch(format)
|
switch(format)
|
||||||
{
|
{
|
||||||
case TextureFormat::RGBA32_UNorm: return DXGI_FORMAT_R8G8B8A8_UNORM;
|
case TextureFormat::R8G8B8A8_UNorm: return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
case TextureFormat::RGBA64_UNorm: return DXGI_FORMAT_R16G16B16A16_UNORM;
|
case TextureFormat::R16G16B16A16_UNorm: return DXGI_FORMAT_R16G16B16A16_UNORM;
|
||||||
case TextureFormat::RGBA64_Float: return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
case TextureFormat::R32G32_Float: return DXGI_FORMAT_R32G32_FLOAT;
|
||||||
case TextureFormat::RGBA128_Float: return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
case TextureFormat::R16G16B16A16_Float: return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||||
|
case TextureFormat::R32G32B32A32_Float: return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||||
case TextureFormat::Depth32_Float: return DXGI_FORMAT_D32_FLOAT;
|
case TextureFormat::Depth32_Float: return DXGI_FORMAT_D32_FLOAT;
|
||||||
case TextureFormat::Depth24_Stencil8: return DXGI_FORMAT_D24_UNORM_S8_UINT;
|
case TextureFormat::Depth24_Stencil8: return DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||||
case TextureFormat::RG16_UNorm: return DXGI_FORMAT_R8G8_UNORM;
|
case TextureFormat::R8G8_UNorm: return DXGI_FORMAT_R8G8_UNORM;
|
||||||
case TextureFormat::R8_UNorm: return DXGI_FORMAT_R8_UNORM;
|
case TextureFormat::R8_UNorm: return DXGI_FORMAT_R8_UNORM;
|
||||||
case TextureFormat::R10G10B10A2_UNorm: return DXGI_FORMAT_R10G10B10A2_UNORM;
|
case TextureFormat::R10G10B10A2_UNorm: return DXGI_FORMAT_R10G10B10A2_UNORM;
|
||||||
case TextureFormat::R32_UInt: return DXGI_FORMAT_R32_UINT;
|
case TextureFormat::R32_UInt: return DXGI_FORMAT_R32_UINT;
|
||||||
case TextureFormat::RG32_SNorm: return DXGI_FORMAT_R16G16_SNORM;
|
case TextureFormat::R32G32_UInt: return DXGI_FORMAT_R32G32_UINT;
|
||||||
case TextureFormat::RG32_Float: return DXGI_FORMAT_R16G16_FLOAT;
|
case TextureFormat::R16G16_SNorm: return DXGI_FORMAT_R16G16_SNORM;
|
||||||
|
case TextureFormat::R16G16_Float: return DXGI_FORMAT_R16G16_FLOAT;
|
||||||
default: Q_assert(!"Unsupported texture format"); return DXGI_FORMAT_R8G8B8A8_UNORM;
|
default: Q_assert(!"Unsupported texture format"); return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2258,7 +2266,7 @@ namespace RHI
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
TextureDesc desc("null RW", 1, 1);
|
TextureDesc desc("null RW", 1, 1);
|
||||||
desc.format = TextureFormat::RGBA32_UNorm;
|
desc.format = TextureFormat::R8G8B8A8_UNorm;
|
||||||
desc.initialState = ResourceStates::UnorderedAccessBit;
|
desc.initialState = ResourceStates::UnorderedAccessBit;
|
||||||
desc.allowedState = ResourceStates::UnorderedAccessBit | ResourceStates::PixelShaderAccessBit;
|
desc.allowedState = ResourceStates::UnorderedAccessBit | ResourceStates::PixelShaderAccessBit;
|
||||||
rhi.nullRWTexture = CreateTexture(desc);
|
rhi.nullRWTexture = CreateTexture(desc);
|
||||||
|
|
|
@ -162,18 +162,20 @@ namespace RHI
|
||||||
enum Id
|
enum Id
|
||||||
{
|
{
|
||||||
Invalid,
|
Invalid,
|
||||||
RGBA32_UNorm,
|
R8G8B8A8_UNorm,
|
||||||
RGBA64_UNorm,
|
R16G16B16A16_UNorm,
|
||||||
RGBA64_Float,
|
R32G32_Float,
|
||||||
RGBA128_Float,
|
R16G16B16A16_Float,
|
||||||
|
R32G32B32A32_Float,
|
||||||
Depth32_Float,
|
Depth32_Float,
|
||||||
RG16_UNorm,
|
R8G8_UNorm,
|
||||||
R8_UNorm,
|
R8_UNorm,
|
||||||
Depth24_Stencil8,
|
Depth24_Stencil8,
|
||||||
R10G10B10A2_UNorm,
|
R10G10B10A2_UNorm,
|
||||||
R32_UInt,
|
R32_UInt,
|
||||||
RG32_SNorm,
|
R32G32_UInt,
|
||||||
RG32_Float,
|
R16G16_SNorm,
|
||||||
|
R16G16_Float,
|
||||||
Count
|
Count
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -430,7 +432,7 @@ namespace RHI
|
||||||
struct RenderTarget
|
struct RenderTarget
|
||||||
{
|
{
|
||||||
uint32_t q3BlendMode = GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
|
uint32_t q3BlendMode = GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
|
||||||
TextureFormat::Id format = TextureFormat::RGBA32_UNorm;
|
TextureFormat::Id format = TextureFormat::R8G8B8A8_UNorm;
|
||||||
}
|
}
|
||||||
renderTargets[MaxRenderTargets];
|
renderTargets[MaxRenderTargets];
|
||||||
uint32_t renderTargetCount = 0;
|
uint32_t renderTargetCount = 0;
|
||||||
|
@ -501,7 +503,7 @@ namespace RHI
|
||||||
sampleCount = 1;
|
sampleCount = 1;
|
||||||
initialState = ResourceStates::PixelShaderAccessBit;
|
initialState = ResourceStates::PixelShaderAccessBit;
|
||||||
allowedState = ResourceStates::PixelShaderAccessBit;
|
allowedState = ResourceStates::PixelShaderAccessBit;
|
||||||
format = TextureFormat::RGBA32_UNorm;
|
format = TextureFormat::R8G8B8A8_UNorm;
|
||||||
committedResource = false;
|
committedResource = false;
|
||||||
usePreferredClearValue = false;
|
usePreferredClearValue = false;
|
||||||
}
|
}
|
||||||
|
@ -514,7 +516,7 @@ namespace RHI
|
||||||
uint32_t sampleCount = 1;
|
uint32_t sampleCount = 1;
|
||||||
ResourceStates::Flags initialState = ResourceStates::PixelShaderAccessBit;
|
ResourceStates::Flags initialState = ResourceStates::PixelShaderAccessBit;
|
||||||
ResourceStates::Flags allowedState = ResourceStates::PixelShaderAccessBit;
|
ResourceStates::Flags allowedState = ResourceStates::PixelShaderAccessBit;
|
||||||
TextureFormat::Id format = TextureFormat::RGBA32_UNorm;
|
TextureFormat::Id format = TextureFormat::R8G8B8A8_UNorm;
|
||||||
bool committedResource = false;
|
bool committedResource = false;
|
||||||
bool usePreferredClearValue = false; // for render targets and depth/stencil buffers
|
bool usePreferredClearValue = false; // for render targets and depth/stencil buffers
|
||||||
float clearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
float clearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||||
|
|
|
@ -290,6 +290,21 @@ bool IsValueInRange(T p, T min, T max)
|
||||||
return all(p >= min) && all(p <= max);
|
return all(p >= min) && all(p <= max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsValue01(float2 p)
|
||||||
|
{
|
||||||
|
return IsValueInRange(p, float2(0, 0), float2(1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsValue01(float3 p)
|
||||||
|
{
|
||||||
|
return IsValueInRange(p, float3(0, 0, 0), float3(1, 1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsValue01(float4 p)
|
||||||
|
{
|
||||||
|
return IsValueInRange(p, float4(0, 0, 0, 0), float4(1, 1, 1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
uint2 GetTextureSize(Texture2D<T> texture0)
|
uint2 GetTextureSize(Texture2D<T> texture0)
|
||||||
{
|
{
|
||||||
|
@ -299,6 +314,15 @@ uint2 GetTextureSize(Texture2D<T> texture0)
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
uint2 GetTextureSize(RWTexture2D<T> texture0)
|
||||||
|
{
|
||||||
|
uint2 size;
|
||||||
|
texture0.GetDimensions(size.x, size.y);
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
// by Sakib Saikia, https://sakibsaikia.github.io/graphics/2022/01/04/Nan-Checks-In-HLSL.html
|
// by Sakib Saikia, https://sakibsaikia.github.io/graphics/2022/01/04/Nan-Checks-In-HLSL.html
|
||||||
bool IsNan(float x)
|
bool IsNan(float x)
|
||||||
{
|
{
|
||||||
|
@ -316,3 +340,59 @@ float AnimateBlueNoise(float blueNoise, uint frameIndex)
|
||||||
{
|
{
|
||||||
return frac(blueNoise + float(frameIndex % 32) * 0.61803399);
|
return frac(blueNoise + float(frameIndex % 32) * 0.61803399);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float2 NDCToTC(float2 ndc)
|
||||||
|
{
|
||||||
|
float2 tc = ndc * float2(0.5, -0.5) + 0.5;
|
||||||
|
|
||||||
|
return tc;
|
||||||
|
}
|
||||||
|
|
||||||
|
float2 TCToNDC(float2 tc)
|
||||||
|
{
|
||||||
|
float2 ndc = (2.0 * tc - 1.0) * float2(1, -1);
|
||||||
|
|
||||||
|
return ndc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the longest vector
|
||||||
|
float2 vmax(float2 a, float2 b)
|
||||||
|
{
|
||||||
|
float2 result = dot(a, a) > dot(b, b) ? a : b;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint PackHalf2(float2 input)
|
||||||
|
{
|
||||||
|
uint2 d = f32tof16(input);
|
||||||
|
uint result = d.x | (d.y << 16u);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float2 UnpackHalf2(uint input)
|
||||||
|
{
|
||||||
|
uint2 d = uint2(input & 0xFFFFu, input >> 16u);
|
||||||
|
float2 result = f16tof32(d);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float2 CartesianToPolar(float2 cartesian)
|
||||||
|
{
|
||||||
|
float radius = length(cartesian);
|
||||||
|
float angle = atan2(cartesian.y, cartesian.x);
|
||||||
|
float2 polar = float2(radius, angle);
|
||||||
|
|
||||||
|
return polar;
|
||||||
|
}
|
||||||
|
|
||||||
|
float2 PolarToCartesian(float2 polar)
|
||||||
|
{
|
||||||
|
float sinAngle, cosAngle;
|
||||||
|
sincos(polar.y, sinAngle, cosAngle);
|
||||||
|
float2 cartesian = polar.x * float2(cosAngle, sinAngle);
|
||||||
|
|
||||||
|
return cartesian;
|
||||||
|
}
|
||||||
|
|
44
code/renderer/shaders/crp/gbufferviz_motion.hlsl
Normal file
44
code/renderer/shaders/crp/gbufferviz_motion.hlsl
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 2024 Gian 'myT' Schellenbaum
|
||||||
|
|
||||||
|
This file is part of Challenge Quake 3 (CNQ3).
|
||||||
|
|
||||||
|
Challenge Quake 3 is free software; you can redistribute it
|
||||||
|
and/or modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
Challenge Quake 3 is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
// colorizes motion vectors for debugging
|
||||||
|
|
||||||
|
|
||||||
|
#include "common.hlsli"
|
||||||
|
#include "fullscreen.hlsli"
|
||||||
|
|
||||||
|
|
||||||
|
cbuffer RootConstants
|
||||||
|
{
|
||||||
|
uint textureIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
float4 ps(VOut input) : SV_Target
|
||||||
|
{
|
||||||
|
Texture2D<float2> motionTexture = ResourceDescriptorHeap[textureIndex];
|
||||||
|
float2 size = float2(GetTextureSize(motionTexture));
|
||||||
|
float scale = size.y / size.x; // correct for aspect ratio
|
||||||
|
uint3 tc = uint3(input.position.xy, 0);
|
||||||
|
float2 raw = motionTexture.Load(tc);
|
||||||
|
float2 display = abs(raw) * 50.0 * scale;
|
||||||
|
float4 result = float4(display, 0, 1);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
336
code/renderer/shaders/crp/mblur_blur.hlsl
Normal file
336
code/renderer/shaders/crp/mblur_blur.hlsl
Normal file
|
@ -0,0 +1,336 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 2024 Gian 'myT' Schellenbaum
|
||||||
|
|
||||||
|
This file is part of Challenge Quake 3 (CNQ3).
|
||||||
|
|
||||||
|
Challenge Quake 3 is free software; you can redistribute it
|
||||||
|
and/or modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
Challenge Quake 3 is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
// motion blur reconstruction filter
|
||||||
|
|
||||||
|
|
||||||
|
#include "common.hlsli"
|
||||||
|
#include "fullscreen.hlsli"
|
||||||
|
#include "scene_view.h.hlsli"
|
||||||
|
|
||||||
|
|
||||||
|
cbuffer RootConstants : register(b0)
|
||||||
|
{
|
||||||
|
uint colorTextureIndex;
|
||||||
|
uint tileTextureIndex;
|
||||||
|
uint packedTextureIndex;
|
||||||
|
uint blueNoiseTextureIndex;
|
||||||
|
uint pointSamplerIndex; // clamp
|
||||||
|
uint linearSamplerIndex; // clamp
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
Summary:
|
||||||
|
- sampling N times in a line along fragment's direction
|
||||||
|
- sampling N times in a line along neighborhood's strongest direction
|
||||||
|
- bilinearly interpolating neighborhood tiles in polar coordinates with clamped velocity
|
||||||
|
- jittering the lines' center points with blue noise
|
||||||
|
- binary classification of samples based on depth and distance/velocity
|
||||||
|
- weighting samples based on direction similarity
|
||||||
|
- background reconstruction using mirrored samples
|
||||||
|
|
||||||
|
References:
|
||||||
|
- "A Reconstruction Filter for Plausible Motion Blur" by McGuire et al.
|
||||||
|
- "Next-Generation Post-Processing in Call of Duty Advanced Warfare" by Jorge Jimenez
|
||||||
|
*/
|
||||||
|
|
||||||
|
void ProcessSample(
|
||||||
|
inout float4 fgAccum, inout float4 bgAccum, inout float alpha, inout float center,
|
||||||
|
float Zs, float Zc, float Vsl, float Vcl, float distTC, float3 C0s, float3 C1s, float W0d)
|
||||||
|
{
|
||||||
|
const float DepthThreshold = 0.28; // 10mm assuming 56u == 2m
|
||||||
|
|
||||||
|
if(Zs - DepthThreshold < Zc && Vsl >= distTC)
|
||||||
|
{
|
||||||
|
fgAccum += float4(C0s, 1) * W0d;
|
||||||
|
bgAccum += float4(C1s, 1);
|
||||||
|
alpha += 1.0;
|
||||||
|
}
|
||||||
|
else if(Zs >= Zc && Vcl >= distTC)
|
||||||
|
{
|
||||||
|
bgAccum += float4(C0s, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
center += 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 ps(VOut input) : SV_Target
|
||||||
|
{
|
||||||
|
SceneView scene = GetSceneView();
|
||||||
|
SamplerState pointSampler = SamplerDescriptorHeap[pointSamplerIndex];
|
||||||
|
SamplerState linearSampler = SamplerDescriptorHeap[linearSamplerIndex];
|
||||||
|
Texture2D colorTexture = ResourceDescriptorHeap[colorTextureIndex];
|
||||||
|
Texture2D<float2> tileTexture = ResourceDescriptorHeap[tileTextureIndex];
|
||||||
|
Texture2D<uint2> packedTexture = ResourceDescriptorHeap[packedTextureIndex];
|
||||||
|
Texture2D blueNoiseTexture = ResourceDescriptorHeap[blueNoiseTextureIndex];
|
||||||
|
float2 fullResSize = float2(GetTextureSize(colorTexture));
|
||||||
|
float2 tileSize = float2(GetTextureSize(tileTexture));
|
||||||
|
uint2 blueNoiseSize = GetTextureSize(blueNoiseTexture);
|
||||||
|
|
||||||
|
float2 tileTC = input.texCoords;
|
||||||
|
float2 Vnraw = tileTexture.SampleLevel(pointSampler, tileTC, 0);
|
||||||
|
float2 tileWeights = frac(tileTC * tileSize + 0.5);
|
||||||
|
float4 Vnx = tileTexture.GatherRed(pointSampler, tileTC);
|
||||||
|
float4 Vny = tileTexture.GatherGreen(pointSampler, tileTC);
|
||||||
|
float2 Vnpa[4];
|
||||||
|
float Vnw[4];
|
||||||
|
for(int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
float2 Vni = float2(Vnx[i], Vny[i]);
|
||||||
|
if(length(Vni * fullResSize) < 2.0)
|
||||||
|
{
|
||||||
|
Vni = Vnraw; // ignore tiles with small vectors
|
||||||
|
}
|
||||||
|
Vnpa[i] = CartesianToPolar(Vni);
|
||||||
|
}
|
||||||
|
Vnw[0] = (1.0 - tileWeights.x) * tileWeights.y; // (-,+)
|
||||||
|
Vnw[1] = tileWeights.x * tileWeights.y; // (+,+)
|
||||||
|
Vnw[2] = tileWeights.x * (1.0 - tileWeights.y); // (+,-)
|
||||||
|
Vnw[3] = (1.0 - tileWeights.x) * (1.0 - tileWeights.y); // (-,-)
|
||||||
|
float2 Vnp = Vnw[0] * Vnpa[0] + Vnw[1] * Vnpa[1] + Vnw[2] * Vnpa[2] + Vnw[3] * Vnpa[3];
|
||||||
|
Vnp.x = max(Vnp.x, length(Vnraw)); // make sure the lerp won't yield a smaller vector
|
||||||
|
float2 Vn = PolarToCartesian(Vnp);
|
||||||
|
float2 Vnn = normalize(Vn);
|
||||||
|
float3 color = colorTexture.SampleLevel(pointSampler, input.texCoords, 0).rgb;
|
||||||
|
uint2 packedFrag = packedTexture.Load(uint3(input.texCoords * fullResSize, 0));
|
||||||
|
float2 Vc = UnpackHalf2(packedFrag.x);
|
||||||
|
float Vcl = length(Vc);
|
||||||
|
float2 Vcn = Vc / Vcl;
|
||||||
|
float Zc = asfloat(packedFrag.y) * scene.zFar;
|
||||||
|
float lengthPx = length(Vn * fullResSize);
|
||||||
|
if(lengthPx < 0.5)
|
||||||
|
{
|
||||||
|
return float4(color, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(length(Vc * fullResSize) <= 4.0)
|
||||||
|
{
|
||||||
|
Vc = Vn;
|
||||||
|
Vcn = Vnn;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint2 blueNoisePx = (input.texCoords * fullResSize) % blueNoiseSize;
|
||||||
|
float2 blueNoise = blueNoiseTexture.Load(uint3(blueNoisePx, 0)).xy;
|
||||||
|
float tcJitter = blueNoise.x;
|
||||||
|
uint sampleCount = min(2 * uint(ceil(lengthPx)), 64);
|
||||||
|
float2 tcStepN = 0.5 * Vn / float2(sampleCount - 1, sampleCount - 1);
|
||||||
|
float2 tcStepC = 0.5 * Vc / float2(sampleCount - 1, sampleCount - 1);
|
||||||
|
float4 fgAccum = float4(0, 0, 0, 0);
|
||||||
|
float4 bgAccum = float4(0, 0, 0, 0);
|
||||||
|
float alpha = 0.0; // foreground (1) / background (0) lerp
|
||||||
|
float center = 0.0; // center (1) / background (0) lerp
|
||||||
|
uint realSampleCount = 0;
|
||||||
|
|
||||||
|
if(length(Vc * fullResSize) >= 1.0)
|
||||||
|
{
|
||||||
|
fgAccum += float4(color, 1);
|
||||||
|
alpha += 1.0;
|
||||||
|
}
|
||||||
|
bgAccum += float4(color, 1);
|
||||||
|
|
||||||
|
uint totalSampleCount = sampleCount * 2;
|
||||||
|
for(uint i = 1; i < totalSampleCount; i++)
|
||||||
|
{
|
||||||
|
float lineStep = float(i / 2);
|
||||||
|
float i0 = tcJitter + lineStep;
|
||||||
|
float i1 = tcJitter - lineStep;
|
||||||
|
float2 tcStep, dirn;
|
||||||
|
[flatten]
|
||||||
|
if(i % 2 == 0)
|
||||||
|
{
|
||||||
|
tcStep = tcStepN;
|
||||||
|
dirn = Vnn;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tcStep = tcStepC;
|
||||||
|
dirn = Vcn;
|
||||||
|
}
|
||||||
|
float2 TC0 = input.texCoords + i0 * tcStep;
|
||||||
|
float2 TC1 = input.texCoords + i1 * tcStep;
|
||||||
|
|
||||||
|
[branch]
|
||||||
|
if(!IsValue01(TC0) || !IsValue01(TC1))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint2 packedSample0 = packedTexture.Load(uint3(TC0 * fullResSize, 0));
|
||||||
|
float2 V0s = UnpackHalf2(packedSample0.x);
|
||||||
|
float V0sl = length(V0s);
|
||||||
|
float2 V0sn = V0s / V0sl;
|
||||||
|
float Z0s = asfloat(packedSample0.y) * scene.zFar;
|
||||||
|
float3 C0s = colorTexture.SampleLevel(pointSampler, TC0, 0).rgb;
|
||||||
|
float distTC0 = distance(TC0, input.texCoords);
|
||||||
|
float W0d = max(dot(V0sn, dirn), 0.0);
|
||||||
|
|
||||||
|
uint2 packedSample1 = packedTexture.Load(uint3(TC1 * fullResSize, 0));
|
||||||
|
float2 V1s = UnpackHalf2(packedSample1.x);
|
||||||
|
float V1sl = length(V1s);
|
||||||
|
float2 V1sn = V1s / V1sl;
|
||||||
|
float Z1s = asfloat(packedSample1.y) * scene.zFar;
|
||||||
|
float3 C1s = colorTexture.SampleLevel(pointSampler, TC1, 0).rgb;
|
||||||
|
float distTC1 = distance(TC1, input.texCoords);
|
||||||
|
float W1d = max(dot(V1sn, dirn), 0.0);
|
||||||
|
|
||||||
|
ProcessSample(fgAccum, bgAccum, alpha, center, Z0s, Zc, V0sl, Vcl, distTC0, C0s, C1s, W0d);
|
||||||
|
ProcessSample(fgAccum, bgAccum, alpha, center, Z1s, Zc, V1sl, Vcl, distTC1, C1s, C0s, W1d);
|
||||||
|
|
||||||
|
realSampleCount += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fgAccum.w <= 0.0 || bgAccum.w <= 0.0)
|
||||||
|
{
|
||||||
|
return float4(color, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fgAccum.rgb /= fgAccum.w;
|
||||||
|
bgAccum.rgb /= bgAccum.w;
|
||||||
|
alpha /= float(realSampleCount);
|
||||||
|
center /= float(realSampleCount);
|
||||||
|
float3 bg = center * color + (1.0 - center) * bgAccum.rgb;
|
||||||
|
float3 blended = alpha * fgAccum.rgb + (1.0 - alpha) * bg;
|
||||||
|
|
||||||
|
return float4(blended, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/*
|
||||||
|
Summary:
|
||||||
|
- sampling N times in a line along fragment's direction
|
||||||
|
- sampling N times in a line along neighborhood's strongest direction
|
||||||
|
- jittering neighborhood tiles to trade banding for blue noise
|
||||||
|
- jittering the lines' center points with blue noise
|
||||||
|
- weighting samples based on depth, distance and direction similarity
|
||||||
|
|
||||||
|
References:
|
||||||
|
- "A Reconstruction Filter for Plausible Motion Blur" by McGuire et al.
|
||||||
|
- "A Fast and Stable Feature-Aware Motion Blur Filter" by Guertin et al.
|
||||||
|
*/
|
||||||
|
|
||||||
|
float Cone(float distSamples, float velocityLength)
|
||||||
|
{
|
||||||
|
float result = saturate(1.0 - distSamples / velocityLength);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Cylinder(float distSamples, float velocityLength)
|
||||||
|
{
|
||||||
|
float l = velocityLength;
|
||||||
|
float result = 1.0 - smoothstep(0.95 * l, 1.05 * l, distSamples);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float SoftDepthFalloff(float zA, float zB)
|
||||||
|
{
|
||||||
|
float result = saturate(1.0 - (zB - zA) / max(zB, zA));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 ps(VOut input) : SV_Target
|
||||||
|
{
|
||||||
|
SceneView scene = GetSceneView();
|
||||||
|
SamplerState pointSampler = SamplerDescriptorHeap[pointSamplerIndex];
|
||||||
|
SamplerState linearSampler = SamplerDescriptorHeap[linearSamplerIndex];
|
||||||
|
Texture2D colorTexture = ResourceDescriptorHeap[colorTextureIndex];
|
||||||
|
Texture2D<float2> tileTexture = ResourceDescriptorHeap[tileTextureIndex];
|
||||||
|
Texture2D<uint2> packedTexture = ResourceDescriptorHeap[packedTextureIndex];
|
||||||
|
Texture2D blueNoiseTexture = ResourceDescriptorHeap[blueNoiseTextureIndex];
|
||||||
|
float2 fullResSize = float2(GetTextureSize(colorTexture));
|
||||||
|
float2 tileSize = float2(GetTextureSize(tileTexture));
|
||||||
|
uint2 blueNoiseSize = GetTextureSize(blueNoiseTexture);
|
||||||
|
|
||||||
|
uint2 blueNoisePx = (input.texCoords * fullResSize) % blueNoiseSize;
|
||||||
|
float2 blueNoise = blueNoiseTexture.Load(uint3(blueNoisePx, 0)).xy;
|
||||||
|
float2 tileJitterTC = 0.25 * (blueNoise * 2.0 - 1.0) / tileSize;
|
||||||
|
float2 tileTC = input.texCoords + tileJitterTC;
|
||||||
|
float2 Vn = tileTexture.SampleLevel(pointSampler, tileTC, 0);
|
||||||
|
float2 Vnn = normalize(Vn);
|
||||||
|
float3 color = colorTexture.SampleLevel(pointSampler, input.texCoords, 0).rgb;
|
||||||
|
uint2 packedFrag = packedTexture.Load(uint3(input.texCoords * fullResSize, 0));
|
||||||
|
float2 Vc = UnpackHalf2(packedFrag.x);
|
||||||
|
float Vcl = length(Vc);
|
||||||
|
float2 Vcn = Vc / Vcl;
|
||||||
|
float Zc = asfloat(packedFrag.y) * scene.zFar;
|
||||||
|
float lengthPx = length(Vn * fullResSize);
|
||||||
|
if(lengthPx < 0.5)
|
||||||
|
{
|
||||||
|
return float4(color, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint sampleCount = min(4 * uint(ceil(lengthPx)), 64); // per line
|
||||||
|
float2 tcStepN = 2.0 * Vn / float2(sampleCount - 1, sampleCount - 1);
|
||||||
|
float2 tcStepC = 2.0 * Vc / float2(sampleCount - 1, sampleCount - 1);
|
||||||
|
float3 colorAccum = color;
|
||||||
|
float weightAccum = 1.0;
|
||||||
|
uint sampleCountTotal = sampleCount * 2; // across all lines
|
||||||
|
for(uint i = 0; i < sampleCount; i++)
|
||||||
|
{
|
||||||
|
float step = float(i / 2);
|
||||||
|
|
||||||
|
float2 tc;
|
||||||
|
float2 dirn;
|
||||||
|
[flatten]
|
||||||
|
if(sampleCount % 2 == 0)
|
||||||
|
{
|
||||||
|
tc = input.texCoords - 0.5 * Vn + (blueNoise.x + step) * tcStepN;
|
||||||
|
dirn = Vnn;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tc = input.texCoords - 0.5 * Vc + (blueNoise.y + step) * tcStepC;
|
||||||
|
dirn = Vcn;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!IsValue01(tc))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint2 packedSample = packedTexture.Load(uint3(tc * fullResSize, 0));
|
||||||
|
float2 Vs = UnpackHalf2(packedSample.x);
|
||||||
|
float Vsl = length(Vs);
|
||||||
|
float2 Vsn = Vs / Vsl;
|
||||||
|
float Zs = asfloat(packedSample.y) * scene.zFar;
|
||||||
|
float3 colorSample = colorTexture.SampleLevel(pointSampler, tc, 0).rgb;
|
||||||
|
float fg = SoftDepthFalloff(Zc, Zs);
|
||||||
|
float bg = SoftDepthFalloff(Zs, Zc);
|
||||||
|
float distTC = distance(tc, input.texCoords);
|
||||||
|
float fgWeight = fg * Cone(distTC, Vsl) * max(0, dot(dirn, Vsn));
|
||||||
|
float bgWeight = bg * Cone(distTC, Vcl) * max(0, dot(dirn, Vcn));
|
||||||
|
float overlapWeight = 2.0 * Cylinder(distTC, Vsl) * Cylinder(distTC, Vcl);
|
||||||
|
float weight = fgWeight + bgWeight + overlapWeight;
|
||||||
|
colorAccum += colorSample * weight;
|
||||||
|
weightAccum += weight;
|
||||||
|
}
|
||||||
|
float4 result = float4(colorAccum /= weightAccum, 1.0);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
57
code/renderer/shaders/crp/mblur_pack.hlsl
Normal file
57
code/renderer/shaders/crp/mblur_pack.hlsl
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 2024 Gian 'myT' Schellenbaum
|
||||||
|
|
||||||
|
This file is part of Challenge Quake 3 (CNQ3).
|
||||||
|
|
||||||
|
Challenge Quake 3 is free software; you can redistribute it
|
||||||
|
and/or modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
Challenge Quake 3 is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
// motion blur packing of scaled velocities and linear depth into a full-screen texture
|
||||||
|
|
||||||
|
|
||||||
|
#include "common.hlsli"
|
||||||
|
#include "fullscreen.hlsli"
|
||||||
|
#include "scene_view.h.hlsli"
|
||||||
|
|
||||||
|
|
||||||
|
cbuffer RootConstants
|
||||||
|
{
|
||||||
|
float motionScale;
|
||||||
|
float maxRadiusPx;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint2 ps(VOut input) : SV_Target
|
||||||
|
{
|
||||||
|
SceneView scene = GetSceneView();
|
||||||
|
|
||||||
|
Texture2D<float> depthTexture = ResourceDescriptorHeap[scene.depthTextureIndex];
|
||||||
|
float2 textureSize = float2(GetTextureSize(depthTexture));
|
||||||
|
uint3 tc = uint3(input.texCoords * textureSize, 0);
|
||||||
|
float depthZW = depthTexture.Load(tc);
|
||||||
|
float linearDepth01 = scene.LinearDepth(depthZW) / scene.zFar;
|
||||||
|
|
||||||
|
Texture2D<float2> motionTexture = ResourceDescriptorHeap[scene.motionVectorMBTextureIndex];
|
||||||
|
float2 motionTC = motionTexture.Load(tc) * motionScale;
|
||||||
|
float2 motionPx = motionTC * textureSize;
|
||||||
|
float motionLengthPx = length(motionPx);
|
||||||
|
if(motionLengthPx > maxRadiusPx)
|
||||||
|
{
|
||||||
|
motionTC *= maxRadiusPx / motionLengthPx;
|
||||||
|
}
|
||||||
|
uint motionPacked = PackHalf2(motionTC);
|
||||||
|
uint2 result = uint2(motionPacked, asuint(linearDepth01));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
62
code/renderer/shaders/crp/mblur_tile_gen.hlsl
Normal file
62
code/renderer/shaders/crp/mblur_tile_gen.hlsl
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 2024 Gian 'myT' Schellenbaum
|
||||||
|
|
||||||
|
This file is part of Challenge Quake 3 (CNQ3).
|
||||||
|
|
||||||
|
Challenge Quake 3 is free software; you can redistribute it
|
||||||
|
and/or modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
Challenge Quake 3 is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
// motion blur velocity tile generation
|
||||||
|
|
||||||
|
|
||||||
|
#include "common.hlsli"
|
||||||
|
|
||||||
|
|
||||||
|
cbuffer RootConstants : register(b0)
|
||||||
|
{
|
||||||
|
uint inputTextureIndex;
|
||||||
|
uint outputTextureIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
[numthreads(8, 8, 1)]
|
||||||
|
void cs(uint3 dtid : SV_DispatchThreadID, uint3 gid : SV_GroupID, uint3 gtid : SV_GroupThreadID)
|
||||||
|
{
|
||||||
|
uint2 tcOut = dtid.xy;
|
||||||
|
RWTexture2D<float2> outputTexture = ResourceDescriptorHeap[outputTextureIndex];
|
||||||
|
if(any(tcOut >= GetTextureSize(outputTexture)))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture2D<uint2> inputTexture = ResourceDescriptorHeap[inputTextureIndex];
|
||||||
|
|
||||||
|
// This loop can read out of bounds in the inputTexture.
|
||||||
|
// Each full-res pixel has a corresponding tile pixel, but the reverse isn't always true.
|
||||||
|
// Texture.Load is specced to return 0 on OOB accesses.
|
||||||
|
// Since we max() the values, zeroes have no effect on the final result.
|
||||||
|
uint2 tcInCorner = tcOut * uint2(16, 16);
|
||||||
|
float2 maxVelocity = float2(0, 0);
|
||||||
|
for(uint y = 0; y < 16; y++)
|
||||||
|
{
|
||||||
|
for(uint x = 0; x < 16; x++)
|
||||||
|
{
|
||||||
|
uint2 tcIn = tcInCorner + uint2(x, y);
|
||||||
|
float2 velocity = UnpackHalf2(inputTexture.Load(uint3(tcIn, 0)).x);
|
||||||
|
maxVelocity = vmax(maxVelocity, velocity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outputTexture[tcOut] = maxVelocity;
|
||||||
|
}
|
62
code/renderer/shaders/crp/mblur_tile_max.hlsl
Normal file
62
code/renderer/shaders/crp/mblur_tile_max.hlsl
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 2024 Gian 'myT' Schellenbaum
|
||||||
|
|
||||||
|
This file is part of Challenge Quake 3 (CNQ3).
|
||||||
|
|
||||||
|
Challenge Quake 3 is free software; you can redistribute it
|
||||||
|
and/or modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
Challenge Quake 3 is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
// motion blur velocity tile dilation
|
||||||
|
|
||||||
|
|
||||||
|
#include "common.hlsli"
|
||||||
|
|
||||||
|
|
||||||
|
cbuffer RootConstants : register(b0)
|
||||||
|
{
|
||||||
|
uint inputTextureIndex;
|
||||||
|
uint outputTextureIndex;
|
||||||
|
uint samplerIndex; // point/clamp
|
||||||
|
};
|
||||||
|
|
||||||
|
[numthreads(8, 8, 1)]
|
||||||
|
void cs(uint3 dtid : SV_DispatchThreadID)
|
||||||
|
{
|
||||||
|
uint2 tc = dtid.xy;
|
||||||
|
RWTexture2D<float2> outputTexture = ResourceDescriptorHeap[outputTextureIndex];
|
||||||
|
uint2 textureSize = GetTextureSize(outputTexture);
|
||||||
|
if(any(tc >= textureSize))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture2D<float2> inputTexture = ResourceDescriptorHeap[inputTextureIndex];
|
||||||
|
SamplerState samplerState = SamplerDescriptorHeap[samplerIndex];
|
||||||
|
|
||||||
|
float2 tcShifted = float2(tc) + float2(0.5, 0.5);
|
||||||
|
float2 pixelSize = float2(1, 1) / float2(textureSize);
|
||||||
|
float2 maxVelocity = float2(0, 0);
|
||||||
|
for(int y = -1; y <= 1; y++)
|
||||||
|
{
|
||||||
|
for(int x = -1; x <= 1; x++)
|
||||||
|
{
|
||||||
|
float2 tc01 = (tcShifted + float2(x, y)) * pixelSize;
|
||||||
|
float2 velocity = inputTexture.SampleLevel(samplerState, tc01, 0);
|
||||||
|
maxVelocity = vmax(maxVelocity, velocity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outputTexture[tc] = maxVelocity;
|
||||||
|
}
|
|
@ -30,10 +30,21 @@ cbuffer RootConstants
|
||||||
{
|
{
|
||||||
matrix modelViewMatrix;
|
matrix modelViewMatrix;
|
||||||
matrix modelMatrix;
|
matrix modelMatrix;
|
||||||
matrix normalMatrix;
|
matrix prevModelMatrix;
|
||||||
|
float normalMatrix0;
|
||||||
|
float normalMatrix1;
|
||||||
|
float normalMatrix2;
|
||||||
|
float normalMatrix3;
|
||||||
|
float normalMatrix4;
|
||||||
|
float normalMatrix5;
|
||||||
|
float normalMatrix6;
|
||||||
|
float normalMatrix7;
|
||||||
|
float normalMatrix8;
|
||||||
|
float motionBlurScale;
|
||||||
uint textureIndex;
|
uint textureIndex;
|
||||||
uint samplerIndex;
|
uint samplerIndex;
|
||||||
uint alphaTest;
|
uint alphaTest;
|
||||||
|
uint motionBlurMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VIn
|
struct VIn
|
||||||
|
@ -47,8 +58,11 @@ struct VIn
|
||||||
struct VOut
|
struct VOut
|
||||||
{
|
{
|
||||||
float4 position : SV_Position;
|
float4 position : SV_Position;
|
||||||
nointerpolation float3 normalWS : NORMAL;
|
float4 currPosition : CURRPOSITION;
|
||||||
nointerpolation float3 positionWS : POSITION;
|
float4 prevPosition : PREVPOSITION;
|
||||||
|
float4 prevPositionMB : PREVPOSITIONMB;
|
||||||
|
nointerpolation float3 normalWS : NORMALWS;
|
||||||
|
nointerpolation float3 positionWS : POSITIONWS;
|
||||||
float2 texCoords : TEXCOORD0;
|
float2 texCoords : TEXCOORD0;
|
||||||
float4 color : COLOR0;
|
float4 color : COLOR0;
|
||||||
float clipDist : SV_ClipDistance0;
|
float clipDist : SV_ClipDistance0;
|
||||||
|
@ -57,13 +71,40 @@ struct VOut
|
||||||
VOut vs(VIn input)
|
VOut vs(VIn input)
|
||||||
{
|
{
|
||||||
SceneView scene = GetSceneView();
|
SceneView scene = GetSceneView();
|
||||||
matrix projectionMatrix = scene.projectionMatrix;
|
float4 positionOS = float4(input.position, 1);
|
||||||
float4 positionVS = mul(modelViewMatrix, float4(input.position.xyz, 1));
|
float4 positionWS = mul(modelMatrix, positionOS);
|
||||||
|
float4 positionVS = mul(modelViewMatrix, float4(input.position, 1));
|
||||||
|
float4 prevPositionWS = mul(prevModelMatrix, positionOS);
|
||||||
|
float3x3 normalMatrix = float3x3(
|
||||||
|
normalMatrix0, normalMatrix3, normalMatrix6,
|
||||||
|
normalMatrix1, normalMatrix4, normalMatrix7,
|
||||||
|
normalMatrix2, normalMatrix5, normalMatrix8);
|
||||||
|
float4 currPosition = mul(scene.projectionMatrix, positionVS);
|
||||||
|
float4 prevPosition = mul(scene.prevViewProjMatrix, prevPositionWS);
|
||||||
|
float4 prevPositionMB;
|
||||||
|
if(motionBlurMode == 1)
|
||||||
|
{
|
||||||
|
// camera only, ignore previous model matrix
|
||||||
|
prevPositionMB = mul(scene.prevViewProjMatrix, positionWS);
|
||||||
|
}
|
||||||
|
else if(motionBlurMode == 2)
|
||||||
|
{
|
||||||
|
// object only, ignore previous view & projection matrices
|
||||||
|
prevPositionMB = mul(scene.projectionMatrix, mul(scene.viewMatrix, prevPositionWS));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// both combined
|
||||||
|
prevPositionMB = prevPosition;
|
||||||
|
}
|
||||||
|
|
||||||
VOut output;
|
VOut output;
|
||||||
output.position = mul(projectionMatrix, positionVS);
|
output.position = currPosition;
|
||||||
output.normalWS = mul(normalMatrix, float4(input.normal, 0)).xyz;
|
output.currPosition = currPosition;
|
||||||
output.positionWS = mul(modelMatrix, float4(input.position, 1)).xyz;
|
output.prevPosition = prevPosition;
|
||||||
|
output.prevPositionMB = prevPositionMB;
|
||||||
|
output.normalWS = mul(normalMatrix, input.normal);
|
||||||
|
output.positionWS = positionWS.xyz;
|
||||||
output.texCoords = input.texCoords;
|
output.texCoords = input.texCoords;
|
||||||
output.color = input.color;
|
output.color = input.color;
|
||||||
output.clipDist = dot(positionVS, scene.clipPlane);
|
output.clipDist = dot(positionVS, scene.clipPlane);
|
||||||
|
@ -75,24 +116,10 @@ struct POut
|
||||||
{
|
{
|
||||||
float2 normal : SV_Target0;
|
float2 normal : SV_Target0;
|
||||||
float2 motionVector : SV_Target1;
|
float2 motionVector : SV_Target1;
|
||||||
float4 shadingPosition : SV_Target2;
|
float2 motionVectorMB : SV_Target2;
|
||||||
|
float4 shadingPosition : SV_Target3;
|
||||||
};
|
};
|
||||||
|
|
||||||
float3 FixNormal(float3 vertexNormal, float3 faceNormal)
|
|
||||||
{
|
|
||||||
if(length(vertexNormal) < 0.5)
|
|
||||||
{
|
|
||||||
return faceNormal;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(dot(vertexNormal, faceNormal) < 0.0)
|
|
||||||
{
|
|
||||||
return -vertexNormal;
|
|
||||||
}
|
|
||||||
|
|
||||||
return vertexNormal;
|
|
||||||
}
|
|
||||||
|
|
||||||
POut ps(VOut input, float3 barycentrics : SV_Barycentrics)
|
POut ps(VOut input, float3 barycentrics : SV_Barycentrics)
|
||||||
{
|
{
|
||||||
if(alphaTest != ATEST_NONE)
|
if(alphaTest != ATEST_NONE)
|
||||||
|
@ -125,9 +152,14 @@ POut ps(VOut input, float3 barycentrics : SV_Barycentrics)
|
||||||
float dist = saturate(distance(shadingPosition, position));
|
float dist = saturate(distance(shadingPosition, position));
|
||||||
float positionDelta = asfloat(PackColor(float4(dist3, dist)));
|
float positionDelta = asfloat(PackColor(float4(dist3, dist)));
|
||||||
|
|
||||||
|
float2 currPosTC = NDCToTC(input.currPosition.xy / input.currPosition.w);
|
||||||
|
float2 prevPosTC = NDCToTC(input.prevPosition.xy / input.prevPosition.w);
|
||||||
|
float2 prevPosMBTC = NDCToTC(input.prevPositionMB.xy / input.prevPositionMB.w);
|
||||||
|
|
||||||
POut output;
|
POut output;
|
||||||
output.normal = OctEncode(normalize(normal));
|
output.normal = OctEncode(normalize(normal));
|
||||||
output.motionVector = float2(0, 0); // @TODO:
|
output.motionVector = currPosTC - prevPosTC;
|
||||||
|
output.motionVectorMB = (currPosTC - prevPosMBTC) * motionBlurScale;
|
||||||
output.shadingPosition = float4(shadingPosition, positionDelta);
|
output.shadingPosition = float4(shadingPosition, positionDelta);
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
|
|
|
@ -45,6 +45,9 @@ struct SceneView
|
||||||
matrix invProjectionMatrix;
|
matrix invProjectionMatrix;
|
||||||
matrix viewMatrix;
|
matrix viewMatrix;
|
||||||
matrix invViewMatrix;
|
matrix invViewMatrix;
|
||||||
|
matrix prevViewProjMatrix;
|
||||||
|
matrix prevViewMatrix;
|
||||||
|
matrix prevProjectionMatrix;
|
||||||
float4 clipPlane;
|
float4 clipPlane;
|
||||||
float4 debug;
|
float4 debug;
|
||||||
uint sceneViewIndex;
|
uint sceneViewIndex;
|
||||||
|
@ -52,11 +55,24 @@ struct SceneView
|
||||||
uint depthTextureIndex;
|
uint depthTextureIndex;
|
||||||
uint normalTextureIndex;
|
uint normalTextureIndex;
|
||||||
uint shadingPositionTextureIndex;
|
uint shadingPositionTextureIndex;
|
||||||
|
uint motionVectorTextureIndex;
|
||||||
|
uint motionVectorMBTextureIndex;
|
||||||
uint lightTextureIndex;
|
uint lightTextureIndex;
|
||||||
uint tlasBufferIndex;
|
uint tlasBufferIndex;
|
||||||
uint tlasInstanceBufferIndex;
|
uint tlasInstanceBufferIndex;
|
||||||
uint lightCount;
|
uint lightCount;
|
||||||
|
float linearDepthA;
|
||||||
|
float linearDepthB;
|
||||||
|
float zNear;
|
||||||
|
float zFar;
|
||||||
DynamicLight lights[SCENE_VIEW_MAX_LIGHTS];
|
DynamicLight lights[SCENE_VIEW_MAX_LIGHTS];
|
||||||
|
|
||||||
|
#if !defined(__cplusplus)
|
||||||
|
float LinearDepth(float zwDepth)
|
||||||
|
{
|
||||||
|
return linearDepthB / (zwDepth - linearDepthA);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
|
|
48
code/renderer/shaders/crp/skybox_motion.hlsl
Normal file
48
code/renderer/shaders/crp/skybox_motion.hlsl
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 2024 Gian 'myT' Schellenbaum
|
||||||
|
|
||||||
|
This file is part of Challenge Quake 3 (CNQ3).
|
||||||
|
|
||||||
|
Challenge Quake 3 is free software; you can redistribute it
|
||||||
|
and/or modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
Challenge Quake 3 is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
// outputs motion vectors for objects infinitely far away
|
||||||
|
|
||||||
|
|
||||||
|
#include "common.hlsli"
|
||||||
|
#include "fullscreen.hlsli"
|
||||||
|
#include "scene_view.h.hlsli"
|
||||||
|
|
||||||
|
|
||||||
|
float2 ps(VOut input) : SV_Target
|
||||||
|
{
|
||||||
|
SceneView scene = GetSceneView();
|
||||||
|
|
||||||
|
// we need the position to match for perfect translation invariance
|
||||||
|
matrix prevViewMatrix = scene.prevViewMatrix;
|
||||||
|
prevViewMatrix[0][3] = scene.viewMatrix[0][3];
|
||||||
|
prevViewMatrix[1][3] = scene.viewMatrix[1][3];
|
||||||
|
prevViewMatrix[2][3] = scene.viewMatrix[2][3];
|
||||||
|
|
||||||
|
float2 currNDC = TCToNDC(input.texCoords.xy);
|
||||||
|
float4 currPointNDC = float4(currNDC, 0, 1);
|
||||||
|
float4 pointWSw = mul(scene.invViewMatrix, mul(scene.invProjectionMatrix, currPointNDC));
|
||||||
|
float4 pointWS = pointWSw / pointWSw.w;
|
||||||
|
float4 prevPointNDC = mul(scene.prevProjectionMatrix, mul(prevViewMatrix, pointWS));
|
||||||
|
float2 prevNDC = prevPointNDC.xy / prevPointNDC.w;
|
||||||
|
float2 motionTC = NDCToTC(currNDC) - NDCToTC(prevNDC);
|
||||||
|
|
||||||
|
return motionTC;
|
||||||
|
}
|
|
@ -76,11 +76,6 @@ float GetBitAsFloat(uint bits, uint bitIndex)
|
||||||
return (bits & (1u << bitIndex)) ? 1.0 : 0.0;
|
return (bits & (1u << bitIndex)) ? 1.0 : 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
float2 UnpackHalf2(uint data)
|
|
||||||
{
|
|
||||||
return float2(f16tof32(data), f16tof32(data >> 16));
|
|
||||||
}
|
|
||||||
|
|
||||||
float4 DepthFadeFragmentColor(float4 color, OIT_Fragment fragment, float storedDepthZW)
|
float4 DepthFadeFragmentColor(float4 color, OIT_Fragment fragment, float storedDepthZW)
|
||||||
{
|
{
|
||||||
if(((fragment.depthFadeScaleBias >> 8) & 1) == 0)
|
if(((fragment.depthFadeScaleBias >> 8) & 1) == 0)
|
||||||
|
|
|
@ -72,7 +72,7 @@ void MipMapGenerator::Init(bool ddhi_, const ShaderByteCode& g2l, const ShaderBy
|
||||||
for(int t = 0; t < 2; ++t)
|
for(int t = 0; t < 2; ++t)
|
||||||
{
|
{
|
||||||
TextureDesc desc(va("mip-map generation #%d", t + 1), MAX_TEXTURE_SIZE, MAX_TEXTURE_SIZE);
|
TextureDesc desc(va("mip-map generation #%d", t + 1), MAX_TEXTURE_SIZE, MAX_TEXTURE_SIZE);
|
||||||
desc.format = TextureFormat::RGBA64_Float;
|
desc.format = TextureFormat::R16G16B16A16_Float;
|
||||||
desc.initialState = ResourceStates::UnorderedAccessBit;
|
desc.initialState = ResourceStates::UnorderedAccessBit;
|
||||||
desc.allowedState = ResourceStates::UnorderedAccessBit | ResourceStates::ComputeShaderAccessBit;
|
desc.allowedState = ResourceStates::UnorderedAccessBit | ResourceStates::ComputeShaderAccessBit;
|
||||||
textures[MipSlice::Float16_0 + t] = CreateTexture(desc);
|
textures[MipSlice::Float16_0 + t] = CreateTexture(desc);
|
||||||
|
|
|
@ -222,6 +222,24 @@ void R_AddDrawSurfCmd( drawSurf_t* drawSurfs, int numDrawSurfs, int numTranspSur
|
||||||
cmd->shouldClearColor = shouldClearColor;
|
cmd->shouldClearColor = shouldClearColor;
|
||||||
cmd->shouldDrawScene = shouldDrawScene;
|
cmd->shouldDrawScene = shouldDrawScene;
|
||||||
Vector4Copy( clearColor, cmd->clearColor );
|
Vector4Copy( clearColor, cmd->clearColor );
|
||||||
|
|
||||||
|
// full-screen non-portal view?
|
||||||
|
if(!tr.viewParms.isPortal &&
|
||||||
|
tr.viewParms.viewportX == 0 &&
|
||||||
|
tr.viewParms.viewportY == 0 &&
|
||||||
|
tr.viewParms.viewportWidth == glConfig.vidWidth &&
|
||||||
|
tr.viewParms.viewportHeight == glConfig.vidHeight)
|
||||||
|
{
|
||||||
|
// combined view-projection matrices
|
||||||
|
memcpy(tr.prevViewProjMatrix, tr.currViewProjMatrix, sizeof(tr.prevViewProjMatrix));
|
||||||
|
R_MultMatrix(tr.viewParms.world.modelMatrix, tr.viewParms.projectionMatrix, tr.currViewProjMatrix);
|
||||||
|
|
||||||
|
// separate view and projection matrices
|
||||||
|
memcpy(tr.prevViewMatrix, tr.currViewMatrix, sizeof(tr.prevViewMatrix));
|
||||||
|
memcpy(tr.prevProjMatrix, tr.currProjMatrix, sizeof(tr.prevProjMatrix));
|
||||||
|
memcpy(tr.currViewMatrix, tr.viewParms.world.modelMatrix, sizeof(tr.currViewMatrix));
|
||||||
|
memcpy(tr.currProjMatrix, tr.viewParms.projectionMatrix, sizeof(tr.currProjMatrix));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -534,6 +534,8 @@ struct drawSurf_t {
|
||||||
int zppFirstIndex;
|
int zppFirstIndex;
|
||||||
int zppIndexCount;
|
int zppIndexCount;
|
||||||
float radiusOverZ;
|
float radiusOverZ;
|
||||||
|
int uniqueEntityId;
|
||||||
|
float motionBlurScale;
|
||||||
};
|
};
|
||||||
|
|
||||||
void R_TessellateSurface( const surfaceType_t* surfType );
|
void R_TessellateSurface( const surfaceType_t* surfType );
|
||||||
|
@ -1007,11 +1009,21 @@ typedef struct {
|
||||||
qbool shaderParseFailed;
|
qbool shaderParseFailed;
|
||||||
int shaderParseNumWarnings;
|
int shaderParseNumWarnings;
|
||||||
|
|
||||||
|
// raytracing support
|
||||||
rtSurf_t rtSurfs[MAX_DRAWSURFS];
|
rtSurf_t rtSurfs[MAX_DRAWSURFS];
|
||||||
int numRTSurfs;
|
int numRTSurfs;
|
||||||
int sceneCounterRT;
|
int sceneCounterRT;
|
||||||
trRefdef_t rtRefdef;
|
trRefdef_t rtRefdef;
|
||||||
|
|
||||||
|
// from current and last frame's non-portal full-screen scene view
|
||||||
|
// needed for motion vectors
|
||||||
|
float currViewProjMatrix[16];
|
||||||
|
float prevViewProjMatrix[16];
|
||||||
|
float currViewMatrix[16];
|
||||||
|
float prevViewMatrix[16];
|
||||||
|
float currProjMatrix[16];
|
||||||
|
float prevProjMatrix[16];
|
||||||
|
|
||||||
} trGlobals_t;
|
} trGlobals_t;
|
||||||
|
|
||||||
extern backEndState_t backEnd;
|
extern backEndState_t backEnd;
|
||||||
|
@ -1141,7 +1153,7 @@ void R_AddMD3Surfaces( trRefEntity_t *e );
|
||||||
|
|
||||||
void R_AddPolygonSurfaces();
|
void R_AddPolygonSurfaces();
|
||||||
|
|
||||||
void R_AddDrawSurf( const surfaceType_t* surface, const shader_t* shader, int staticGeoChunk = 0, int zppFirstIndex = 0, int zppIndexCount = 0, float radiusOverZ = 666.0f );
|
void R_AddDrawSurf( const surfaceType_t* surface, const shader_t* shader, int uniqueEntityId, float mblurScale, int staticGeoChunk = 0, int zppFirstIndex = 0, int zppIndexCount = 0, float radiusOverZ = 666.0f );
|
||||||
void R_AddLitSurf( const surfaceType_t* surface, const shader_t* shader, int staticGeoChunk );
|
void R_AddLitSurf( const surfaceType_t* surface, const shader_t* shader, int staticGeoChunk );
|
||||||
void R_AddRTSurf( const surfaceType_t* surface, const shader_t* shader );
|
void R_AddRTSurf( const surfaceType_t* surface, const shader_t* shader );
|
||||||
uint64_t R_ComposeSort( int entityNum, const shader_t* shader, int staticGeoChunk );
|
uint64_t R_ComposeSort( int entityNum, const shader_t* shader, int staticGeoChunk );
|
||||||
|
@ -1411,7 +1423,7 @@ SCENE GENERATION
|
||||||
void R_ClearFrame();
|
void R_ClearFrame();
|
||||||
|
|
||||||
void RE_ClearScene();
|
void RE_ClearScene();
|
||||||
void RE_AddRefEntityToScene( const refEntity_t *ent, qbool intShaderTime );
|
void RE_AddRefEntityToScene( const refEntity_t *ent, refEntityVersion_t version );
|
||||||
void RE_AddPolyToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts, int num );
|
void RE_AddPolyToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts, int num );
|
||||||
void RE_AddLightToScene( const vec3_t org, float radius, float r, float g, float b );
|
void RE_AddLightToScene( const vec3_t org, float radius, float r, float g, float b );
|
||||||
void RE_RenderScene( const refdef_t *fd, int us );
|
void RE_RenderScene( const refdef_t *fd, int us );
|
||||||
|
|
|
@ -1280,7 +1280,7 @@ static float SurfGreyscaleAmount( const shader_t* shader )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void R_AddDrawSurf( const surfaceType_t* surface, const shader_t* shader, int staticGeoChunk, int zppFirstIndex, int zppIndexCount, float radiusOverZ )
|
void R_AddDrawSurf( const surfaceType_t* surface, const shader_t* shader, int uniqueEntityId, float mblurScale, int staticGeoChunk, int zppFirstIndex, int zppIndexCount, float radiusOverZ )
|
||||||
{
|
{
|
||||||
if (tr.refdef.numDrawSurfs >= MAX_DRAWSURFS)
|
if (tr.refdef.numDrawSurfs >= MAX_DRAWSURFS)
|
||||||
return;
|
return;
|
||||||
|
@ -1295,6 +1295,8 @@ void R_AddDrawSurf( const surfaceType_t* surface, const shader_t* shader, int st
|
||||||
drawSurf->zppFirstIndex = zppFirstIndex;
|
drawSurf->zppFirstIndex = zppFirstIndex;
|
||||||
drawSurf->zppIndexCount = zppIndexCount;
|
drawSurf->zppIndexCount = zppIndexCount;
|
||||||
drawSurf->radiusOverZ = radiusOverZ;
|
drawSurf->radiusOverZ = radiusOverZ;
|
||||||
|
drawSurf->uniqueEntityId = uniqueEntityId;
|
||||||
|
drawSurf->motionBlurScale = mblurScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1644,7 +1646,7 @@ static void R_AddEntitySurfaces()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
shader = R_GetShaderByHandle( ent->e.customShader );
|
shader = R_GetShaderByHandle( ent->e.customShader );
|
||||||
R_AddDrawSurf( &entitySurface, shader );
|
R_AddDrawSurf( &entitySurface, shader, ent->e.uniqueId, ent->e.motionBlurScale );
|
||||||
R_AddRTSurf( &entitySurface, shader ); // @TODO: billboards need to be procedural geometry
|
R_AddRTSurf( &entitySurface, shader ); // @TODO: billboards need to be procedural geometry
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1654,7 +1656,7 @@ static void R_AddEntitySurfaces()
|
||||||
|
|
||||||
tr.currentModel = R_GetModelByHandle( ent->e.hModel );
|
tr.currentModel = R_GetModelByHandle( ent->e.hModel );
|
||||||
if (!tr.currentModel) {
|
if (!tr.currentModel) {
|
||||||
R_AddDrawSurf( &entitySurface, tr.defaultShader );
|
R_AddDrawSurf( &entitySurface, tr.defaultShader, ent->e.uniqueId, ent->e.motionBlurScale );
|
||||||
} else {
|
} else {
|
||||||
switch ( tr.currentModel->type ) {
|
switch ( tr.currentModel->type ) {
|
||||||
case MOD_MD3:
|
case MOD_MD3:
|
||||||
|
@ -1669,7 +1671,7 @@ static void R_AddEntitySurfaces()
|
||||||
case MOD_BAD: // null model axis
|
case MOD_BAD: // null model axis
|
||||||
if ( (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal)
|
if ( (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal)
|
||||||
break;
|
break;
|
||||||
R_AddDrawSurf( &entitySurface, tr.defaultShader );
|
R_AddDrawSurf( &entitySurface, tr.defaultShader, ent->e.uniqueId, ent->e.motionBlurScale );
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ri.Error( ERR_DROP, "R_AddEntitySurfaces: Bad modeltype" );
|
ri.Error( ERR_DROP, "R_AddEntitySurfaces: Bad modeltype" );
|
||||||
|
|
|
@ -287,7 +287,7 @@ void R_AddMD3Surfaces( trRefEntity_t* ent )
|
||||||
// don't add third_person objects if not viewing through a portal
|
// don't add third_person objects if not viewing through a portal
|
||||||
if ( !personalModel ) {
|
if ( !personalModel ) {
|
||||||
if( !culled )
|
if( !culled )
|
||||||
R_AddDrawSurf( (const surfaceType_t*)surface, shader );
|
R_AddDrawSurf( (const surfaceType_t*)surface, shader, ent->e.uniqueId, ent->e.motionBlurScale );
|
||||||
R_AddRTSurf( (const surfaceType_t*)surface, shader );
|
R_AddRTSurf( (const surfaceType_t*)surface, shader );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -128,7 +128,7 @@ typedef struct {
|
||||||
// a scene is built up by calls to R_ClearScene and the various R_Add functions.
|
// a scene is built up by calls to R_ClearScene and the various R_Add functions.
|
||||||
// Nothing is drawn until R_RenderScene is called.
|
// Nothing is drawn until R_RenderScene is called.
|
||||||
void (*ClearScene)();
|
void (*ClearScene)();
|
||||||
void (*AddRefEntityToScene)( const refEntity_t *re, qbool intShaderTime );
|
void (*AddRefEntityToScene)( const refEntity_t *re, refEntityVersion_t version );
|
||||||
void (*AddPolyToScene)( qhandle_t hShader, int numVerts, const polyVert_t *verts, int num );
|
void (*AddPolyToScene)( qhandle_t hShader, int numVerts, const polyVert_t *verts, int num );
|
||||||
qbool (*LightForPoint)( const vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir );
|
qbool (*LightForPoint)( const vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir );
|
||||||
void (*AddLightToScene)( const vec3_t org, float radius, float r, float g, float b );
|
void (*AddLightToScene)( const vec3_t org, float radius, float r, float g, float b );
|
||||||
|
|
|
@ -83,7 +83,7 @@ void R_AddPolygonSurfaces()
|
||||||
|
|
||||||
const srfPoly_t* poly = tr.refdef.polys;
|
const srfPoly_t* poly = tr.refdef.polys;
|
||||||
for (int i = 0; i < tr.refdef.numPolys; ++i, ++poly) {
|
for (int i = 0; i < tr.refdef.numPolys; ++i, ++poly) {
|
||||||
R_AddDrawSurf( (const surfaceType_t*)poly, R_GetShaderByHandle( poly->hShader ) );
|
R_AddDrawSurf( (const surfaceType_t*)poly, R_GetShaderByHandle( poly->hShader ), 0, 1.0f );
|
||||||
// @TODO: polygons are sometimes used to replace sprites (e.g. CPMA rocket smoke),
|
// @TODO: polygons are sometimes used to replace sprites (e.g. CPMA rocket smoke),
|
||||||
// they should be procedural geometry
|
// they should be procedural geometry
|
||||||
R_AddRTSurf( (const surfaceType_t*)poly, R_GetShaderByHandle( poly->hShader ) );
|
R_AddRTSurf( (const surfaceType_t*)poly, R_GetShaderByHandle( poly->hShader ) );
|
||||||
|
@ -154,7 +154,7 @@ void RE_AddPolyToScene( qhandle_t hShader, int numVerts, const polyVert_t* verts
|
||||||
///////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
void RE_AddRefEntityToScene( const refEntity_t* ent, qbool intShaderTime )
|
void RE_AddRefEntityToScene( const refEntity_t* ent, refEntityVersion_t version )
|
||||||
{
|
{
|
||||||
if ( !tr.registered ) {
|
if ( !tr.registered ) {
|
||||||
return;
|
return;
|
||||||
|
@ -169,9 +169,15 @@ void RE_AddRefEntityToScene( const refEntity_t* ent, qbool intShaderTime )
|
||||||
}
|
}
|
||||||
|
|
||||||
trRefEntity_t* const trEnt = &backEndData->entities[r_numentities];
|
trRefEntity_t* const trEnt = &backEndData->entities[r_numentities];
|
||||||
trEnt->e = *ent;
|
if ( version == REV_LATEST ) {
|
||||||
|
trEnt->e = *ent;
|
||||||
|
} else {
|
||||||
|
memcpy( &trEnt->e, ent, sizeof( refEntityBase_t ) );
|
||||||
|
trEnt->e.uniqueId = 0;
|
||||||
|
trEnt->e.motionBlurScale = 1.0f;
|
||||||
|
}
|
||||||
trEnt->lightingCalculated = qfalse;
|
trEnt->lightingCalculated = qfalse;
|
||||||
trEnt->intShaderTime = intShaderTime;
|
trEnt->intShaderTime = version >= REV_INTSHADERTIME;
|
||||||
r_numentities++;
|
r_numentities++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -183,7 +183,7 @@ static qbool R_LightCullSurface( const surfaceType_t* surface, const dlight_t* d
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void R_AddWorldSurface( msurface_t* surf )
|
static void R_AddWorldSurface( msurface_t* surf, int uniqueId, float mblurScale )
|
||||||
{
|
{
|
||||||
if ( surf->vcBSP == tr.viewCount )
|
if ( surf->vcBSP == tr.viewCount )
|
||||||
return; // already checked during this BSP walk
|
return; // already checked during this BSP walk
|
||||||
|
@ -210,7 +210,7 @@ static void R_AddWorldSurface( msurface_t* surf )
|
||||||
radiusOverZ = triangles->radius / max( dist, 0.001f );
|
radiusOverZ = triangles->radius / max( dist, 0.001f );
|
||||||
}
|
}
|
||||||
|
|
||||||
R_AddDrawSurf( surf->data, surf->shader, surf->staticGeoChunk, surf->zppFirstIndex, surf->zppIndexCount, radiusOverZ );
|
R_AddDrawSurf( surf->data, surf->shader, uniqueId, mblurScale, surf->staticGeoChunk, surf->zppFirstIndex, surf->zppIndexCount, radiusOverZ );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -319,7 +319,7 @@ static void R_RecursiveWorldNode( mnode_t *node, int planeBits )
|
||||||
while (c--) {
|
while (c--) {
|
||||||
// the surface may have already been added if it spans multiple leafs
|
// the surface may have already been added if it spans multiple leafs
|
||||||
msurface_t* surf = *mark;
|
msurface_t* surf = *mark;
|
||||||
R_AddWorldSurface( surf );
|
R_AddWorldSurface( surf, 0, 1.0f );
|
||||||
mark++;
|
mark++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,7 +451,7 @@ void R_AddBrushModelSurfaces( const trRefEntity_t* re )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for ( int s = 0; s < bmodel->numSurfaces; ++s ) {
|
for ( int s = 0; s < bmodel->numSurfaces; ++s ) {
|
||||||
R_AddWorldSurface( bmodel->firstSurface + s );
|
R_AddWorldSurface( bmodel->firstSurface + s, re->e.uniqueId, re->e.motionBlurScale );
|
||||||
}
|
}
|
||||||
|
|
||||||
R_TransformDlights( tr.refdef.num_dlights, tr.refdef.dlights, &tr.orient );
|
R_TransformDlights( tr.refdef.num_dlights, tr.refdef.dlights, &tr.orient );
|
||||||
|
|
|
@ -413,7 +413,13 @@ void ProcessCRP()
|
||||||
CompilePixelShader("gbufferviz_depth.h", "gbufferviz_depth.hlsl", "gbufferviz_depth");
|
CompilePixelShader("gbufferviz_depth.h", "gbufferviz_depth.hlsl", "gbufferviz_depth");
|
||||||
CompilePixelShader("gbufferviz_normal.h", "gbufferviz_normal.hlsl", "gbufferviz_normal");
|
CompilePixelShader("gbufferviz_normal.h", "gbufferviz_normal.hlsl", "gbufferviz_normal");
|
||||||
CompilePixelShader("gbufferviz_position.h", "gbufferviz_position.hlsl", "gbufferviz_position");
|
CompilePixelShader("gbufferviz_position.h", "gbufferviz_position.hlsl", "gbufferviz_position");
|
||||||
|
CompilePixelShader("gbufferviz_motion.h", "gbufferviz_motion.hlsl", "gbufferviz_motion");
|
||||||
CompileGraphics("wireframe_normals.h", "wireframe_normals.hlsl", "wireframe_normals");
|
CompileGraphics("wireframe_normals.h", "wireframe_normals.hlsl", "wireframe_normals");
|
||||||
|
CompilePixelShader("skybox_motion.h", "skybox_motion.hlsl", "skybox_motion");
|
||||||
|
CompileCompute("mblur_tile_gen.h", "mblur_tile_gen.hlsl", "tile_gen");
|
||||||
|
CompileCompute("mblur_tile_max.h", "mblur_tile_max.hlsl", "tile_max");
|
||||||
|
CompilePixelShader("mblur_blur.h", "mblur_blur.hlsl", "blur");
|
||||||
|
CompilePixelShader("mblur_pack.h", "mblur_pack.hlsl", "pack");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int /*argc*/, const char** argv)
|
int main(int /*argc*/, const char** argv)
|
||||||
|
|
|
@ -135,6 +135,7 @@
|
||||||
<ClCompile Include="..\..\code\renderer\crp_geometry.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_geometry.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_magnifier.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_magnifier.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_main.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_main.cpp" />
|
||||||
|
<ClCompile Include="..\..\code\renderer\crp_motion_blur.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_opaque.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_opaque.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_prepass.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_prepass.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_raytracing.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_raytracing.cpp" />
|
||||||
|
@ -231,6 +232,9 @@
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\gbufferviz_depth.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\gbufferviz_depth.hlsl">
|
||||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\gbufferviz_motion.hlsl">
|
||||||
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
|
</FxCompile>
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\gbufferviz_normal.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\gbufferviz_normal.hlsl">
|
||||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
@ -243,6 +247,18 @@
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\magnifier.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\magnifier.hlsl">
|
||||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\mblur_blur.hlsl">
|
||||||
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\mblur_pack.hlsl">
|
||||||
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\mblur_tile_gen.hlsl">
|
||||||
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\mblur_tile_max.hlsl">
|
||||||
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
|
</FxCompile>
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\mip_1.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\mip_1.hlsl">
|
||||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
@ -261,6 +277,9 @@
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\prepass.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\prepass.hlsl">
|
||||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\skybox_motion.hlsl">
|
||||||
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
|
</FxCompile>
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\tone_map.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\tone_map.hlsl">
|
||||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
<ClCompile Include="..\..\code\renderer\crp_geometry.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_geometry.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_magnifier.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_magnifier.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_main.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_main.cpp" />
|
||||||
|
<ClCompile Include="..\..\code\renderer\crp_motion_blur.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_opaque.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_opaque.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_prepass.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_prepass.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_raytracing.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_raytracing.cpp" />
|
||||||
|
@ -135,6 +136,9 @@
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\gbufferviz_depth.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\gbufferviz_depth.hlsl">
|
||||||
<Filter>shaders\crp</Filter>
|
<Filter>shaders\crp</Filter>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\gbufferviz_motion.hlsl">
|
||||||
|
<Filter>shaders\crp</Filter>
|
||||||
|
</FxCompile>
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\gbufferviz_normal.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\gbufferviz_normal.hlsl">
|
||||||
<Filter>shaders\crp</Filter>
|
<Filter>shaders\crp</Filter>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
@ -147,6 +151,18 @@
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\magnifier.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\magnifier.hlsl">
|
||||||
<Filter>shaders\crp</Filter>
|
<Filter>shaders\crp</Filter>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\mblur_blur.hlsl">
|
||||||
|
<Filter>shaders\crp</Filter>
|
||||||
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\mblur_pack.hlsl">
|
||||||
|
<Filter>shaders\crp</Filter>
|
||||||
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\mblur_tile_gen.hlsl">
|
||||||
|
<Filter>shaders\crp</Filter>
|
||||||
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\mblur_tile_max.hlsl">
|
||||||
|
<Filter>shaders\crp</Filter>
|
||||||
|
</FxCompile>
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\mip_1.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\mip_1.hlsl">
|
||||||
<Filter>shaders\crp</Filter>
|
<Filter>shaders\crp</Filter>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
@ -165,6 +181,9 @@
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\prepass.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\prepass.hlsl">
|
||||||
<Filter>shaders\crp</Filter>
|
<Filter>shaders\crp</Filter>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\skybox_motion.hlsl">
|
||||||
|
<Filter>shaders\crp</Filter>
|
||||||
|
</FxCompile>
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\tone_map.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\tone_map.hlsl">
|
||||||
<Filter>shaders\crp</Filter>
|
<Filter>shaders\crp</Filter>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
|
|
@ -137,6 +137,7 @@
|
||||||
<ClCompile Include="..\..\code\renderer\crp_geometry.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_geometry.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_magnifier.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_magnifier.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_main.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_main.cpp" />
|
||||||
|
<ClCompile Include="..\..\code\renderer\crp_motion_blur.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_opaque.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_opaque.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_prepass.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_prepass.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_raytracing.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_raytracing.cpp" />
|
||||||
|
@ -233,6 +234,9 @@
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\gbufferviz_depth.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\gbufferviz_depth.hlsl">
|
||||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\gbufferviz_motion.hlsl">
|
||||||
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
|
</FxCompile>
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\gbufferviz_normal.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\gbufferviz_normal.hlsl">
|
||||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
@ -245,6 +249,18 @@
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\magnifier.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\magnifier.hlsl">
|
||||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\mblur_blur.hlsl">
|
||||||
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\mblur_pack.hlsl">
|
||||||
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\mblur_tile_gen.hlsl">
|
||||||
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\mblur_tile_max.hlsl">
|
||||||
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
|
</FxCompile>
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\mip_1.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\mip_1.hlsl">
|
||||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
@ -263,6 +279,9 @@
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\prepass.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\prepass.hlsl">
|
||||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\skybox_motion.hlsl">
|
||||||
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
|
</FxCompile>
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\tone_map.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\tone_map.hlsl">
|
||||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
<ClCompile Include="..\..\code\renderer\crp_geometry.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_geometry.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_magnifier.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_magnifier.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_main.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_main.cpp" />
|
||||||
|
<ClCompile Include="..\..\code\renderer\crp_motion_blur.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_opaque.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_opaque.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_prepass.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_prepass.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_raytracing.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_raytracing.cpp" />
|
||||||
|
@ -135,6 +136,9 @@
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\gbufferviz_depth.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\gbufferviz_depth.hlsl">
|
||||||
<Filter>shaders\crp</Filter>
|
<Filter>shaders\crp</Filter>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\gbufferviz_motion.hlsl">
|
||||||
|
<Filter>shaders\crp</Filter>
|
||||||
|
</FxCompile>
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\gbufferviz_normal.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\gbufferviz_normal.hlsl">
|
||||||
<Filter>shaders\crp</Filter>
|
<Filter>shaders\crp</Filter>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
@ -147,6 +151,18 @@
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\magnifier.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\magnifier.hlsl">
|
||||||
<Filter>shaders\crp</Filter>
|
<Filter>shaders\crp</Filter>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\mblur_blur.hlsl">
|
||||||
|
<Filter>shaders\crp</Filter>
|
||||||
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\mblur_pack.hlsl">
|
||||||
|
<Filter>shaders\crp</Filter>
|
||||||
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\mblur_tile_gen.hlsl">
|
||||||
|
<Filter>shaders\crp</Filter>
|
||||||
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\mblur_tile_max.hlsl">
|
||||||
|
<Filter>shaders\crp</Filter>
|
||||||
|
</FxCompile>
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\mip_1.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\mip_1.hlsl">
|
||||||
<Filter>shaders\crp</Filter>
|
<Filter>shaders\crp</Filter>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
@ -165,6 +181,9 @@
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\prepass.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\prepass.hlsl">
|
||||||
<Filter>shaders\crp</Filter>
|
<Filter>shaders\crp</Filter>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\skybox_motion.hlsl">
|
||||||
|
<Filter>shaders\crp</Filter>
|
||||||
|
</FxCompile>
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\tone_map.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\tone_map.hlsl">
|
||||||
<Filter>shaders\crp</Filter>
|
<Filter>shaders\crp</Filter>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
|
Loading…
Reference in a new issue