Skip to content

Commit b7636e4

Browse files
[REMIX-3048] supporting outwards displacement with POM
1 parent 8e0992a commit b7636e4

34 files changed

+358
-171
lines changed

RtxOptions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@ Tables below enumerate all the options and their defaults set by RTX Remix. Note
647647
|rtx.terrainBaker.material.bakeReplacementMaterials|bool|True|Enables baking of replacement materials when they are present\.|
648648
|rtx.terrainBaker.material.bakeSecondaryPBRTextures|bool|True|Enables baking of secondary textures in replacement materials when they are present\.<br>Secondary textures are all PBR textures except for albedoOpacity\. So that includes normal, roughness, etc\.|
649649
|rtx.terrainBaker.material.maxResolutionToUseForReplacementMaterials|int|8192|Max resolution to use for preprocessing and baking of input replacement material textures other than color opacity which is used as is\.<br>Applies only to a case when a preprocessing compute shader is used to support baking of secondary PBR materials\.<br>Replacement materials need to be preprocessed prior to baking them and limitting the max resolution allows to balance the quality vs performance cost\.|
650-
|rtx.terrainBaker.material.properties.displaceInFactor|float|1|The max depth the baked terrain can support will be larger than the max depth <br>of any incoming draw call, which results in a loss of detail\. When this is <br>too low, the displacement will lack detail\. When it is too high, the lowest <br>parts of the POM will flatten out\.|
650+
|rtx.terrainBaker.material.properties.displaceInFactor|float|1|The max depth and height the baked terrain can support will be larger than the max <br>of any incoming draw call, which results in a loss of detail\. When this is <br>too low, the displacement will lack detail\. When it is too high, the lowest <br>and highest parts of the POM will flatten out\. This affects both displaceIn <br>and displaceOut, despite the name\.|
651651
|rtx.terrainBaker.material.properties.emissiveColorConstant|float3|0, 0, 0|Emissive color constant\. Should be a color in sRGB colorspace with gamma encoding\.|
652652
|rtx.terrainBaker.material.properties.emissiveIntensity|float|0|Emissive intensity\.|
653653
|rtx.terrainBaker.material.properties.enableEmission|bool|False|A flag to determine if emission is enabled\.|

documentation/RemixApiChangelog.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
## Remix API Changelog
2+
3+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
4+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
5+
6+
## [0.4.2]
7+
8+
### Added
9+
- MaterialInfoOpaqueEXT.displaceOut
10+
11+
### Changed
12+
- renamed MaterialInfoOpaqueEXT.heightTextureStrength to MaterialInfoOpaqueEXT.displaceIn
13+
14+
### Fixed
15+
16+
### Removed

documentation/TerrainSystem.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,8 @@ Caveats/limitations:
2020
- Using too high resolution replacement textures can have noticeable performance impact. Adjust [rtx.terrainBaker.material.maxResolutionToUseForReplacementMaterials](../RtxOptions.md) to balance quality vs performance cost of baking replacement textures.
2121
- Terrain baking is not free. It has a computational and memory cost. You can parametrize its properties to suit your needs and memory limitations. In the future there may be a more adaptive mechanism to fit in-game scenario and resource availability. Tune following settings to adjust resolution and memory overhead of the Terrain System [rtx.terrainBaker.cascadeMap.*](../RtxOptions.md) and [rtx.terrainBaker.material.maxResolutionToUseForReplacementMaterials](../RtxOptions.md).
2222
- Programmable shaders with Shader Model 2.0+ utilize a preprocessing compute pass to support baking of secondary PBR textures. This is an expensive operation both performance and memory wise. Draw calls using fixed function pipeline and programmable pipelines with Shader Model 1.0 instead rely on shader injection. This shader injection functionality is controlled via [rtx.terrainBaker.material.replacementSupportInPS_programmableShaders](../RtxOptions.md) and [rtx.terrainBaker.material.replacementSupportInPS_fixedFunction](../RtxOptions.md) that needs to be set prior to launching the game on modification. Both of these are enabled by default. While these options should work they are still in experimental stage. If you observe any crashes or quality issues which get fixed by disabling the two options then file github issues for them.
23-
- Differences between the UV tiling size of the incoming terrain draw calls and the baked terrain map can cause precision loss in baked heightmaps. Specifically, the baked heightmap's max displacement distance may be significantly larger (or smaller) than the actual max displacement distance of any of the incoming draw calls, resulting in a loss of detail. [rtx.terrainBaker.material.properties.displaceInFactor](../RtxOptions.md) can be used to fix that by shrinking the baked heightmap's max displacement. When it is too low, the displacement will lack detail. When it is too high, the lowest parts of the POM will flatten out. The `Calculate Scene's Optimal Displace In Factor` button in the terrain material properties panel can be used to automatically calculate the highest safe value for a given scene. `rtx.conf` creators should use that button in representative sample of a game's levels, and then set `displaceInFactor` to the lowest observed value.
23+
- Differences between the UV tiling size of the incoming terrain draw calls and the baked terrain map can cause precision loss in baked heightmaps. Specifically, the baked heightmap's max displacement distance may be significantly larger (or smaller) than the actual max displacement distance of any of the incoming draw calls, resulting in a loss of detail. [rtx.terrainBaker.material.properties.displaceInFactor](../RtxOptions.md) can be used to fix that by shrinking the baked heightmap's max displacement. When it is too low, the displacement will lack detail. When it is too high, the lowest and highest parts of the POM will flatten out. The `Calculate Scene's Optimal Displacement Factor` button in the terrain material properties panel can be used to automatically calculate the highest safe value for a given scene. `rtx.conf` creators should use that button in representative sample of a game's levels, and then set `displaceInFactor` to the lowest observed value.
2424

2525
Future considerations / not supported (yet):
2626
- Material constants per input terrain replacement material.
27-
- Supporting Quadtree POM with baked heightmaps.
2827
- Orthogonal surfaces (i.e. walls with floor) and separate multi-layer surfaces (i.e. baked road on a bridge over another baked road below). For these cases you can use the decal system. The benefit of the terrain system to the decal system is that the terrain baking exactly replicates original game's blending while the decal system only approximates the original blending. On the other hand, decal system supports blending in any direction and the input decal textures are sampled at the desired resolution at the time of ray hits the surface while the terrain system resamples original textures to a shared terrain texture. This can result in a of loss of image fidelity depending on the parametrization of the terrain system (see [rtx.terrainBaker.*](../RtxOptions.md)).

packman-external.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<package name="rtx-remix-nv_usd" version="5" />
1616
</dependency>
1717
<dependency name="omni_core_materials" linkPath="external/omni_core_materials">
18-
<package name="rtx-remix-omni_core_materials" version="13" />
18+
<package name="rtx-remix-omni_core_materials" version="15" />
1919
</dependency>
2020
<dependency name="reflex" linkPath="external/reflex">
2121
<package name="rtx-remix-reflex" version="1" />

public/include/remix/remix.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,13 +275,14 @@ namespace remix {
275275
thinFilmThickness_value = 200.f;
276276
alphaIsThinFilmThickness = false;
277277
heightTexture = {};
278-
heightTextureStrength = 0.0f;
278+
displaceIn = 0.0f;
279279
useDrawCallAlphaState = true;
280280
blendType_hasvalue = false;
281281
blendType_value = 0;
282282
invertedBlend = false;
283283
alphaTestType = 7;
284284
alphaReferenceValue = 0;
285+
displaceOut = 0.0f;
285286
static_assert(sizeof remixapi_MaterialInfoOpaqueEXT == 112);
286287
}
287288

public/include/remix/remix_c.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@
2626
#include <stdint.h>
2727
#include <windows.h>
2828

29+
#ifndef REMIX_ALLOW_X86
2930
#if _WIN64 != 1
3031
#error Remix API requires 64-bit for the ray tracing features.
3132
#endif
33+
#endif
3234

3335

3436
// __stdcall convention
@@ -52,7 +54,7 @@
5254

5355
#define REMIXAPI_VERSION_MAJOR 0
5456
#define REMIXAPI_VERSION_MINOR 4
55-
#define REMIXAPI_VERSION_PATCH 1
57+
#define REMIXAPI_VERSION_PATCH 2
5658

5759

5860
// External
@@ -194,14 +196,15 @@ extern "C" {
194196
float thinFilmThickness_value;
195197
remixapi_Bool alphaIsThinFilmThickness;
196198
remixapi_Path heightTexture;
197-
float heightTextureStrength;
199+
float displaceIn;
198200
// If true, InstanceInfoBlendEXT is used as a source for alpha state
199201
remixapi_Bool useDrawCallAlphaState;
200202
remixapi_Bool blendType_hasvalue;
201203
int blendType_value;
202204
remixapi_Bool invertedBlend;
203205
int alphaTestType;
204206
uint8_t alphaReferenceValue;
207+
float displaceOut;
205208
} remixapi_MaterialInfoOpaqueEXT;
206209

207210
// Valid only if remixapi_MaterialInfo contains remixapi_MaterialInfoOpaqueEXT in pNext chain

src/d3d9/d3d9_device.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6665,7 +6665,9 @@ namespace dxvk {
66656665
data->Stages[i].BumpEnvLScale = bit::cast<float>(m_state.textureStages[i][DXVK_TSS_BUMPENVLSCALE]);
66666666
data->Stages[i].BumpEnvLOffset = bit::cast<float>(m_state.textureStages[i][DXVK_TSS_BUMPENVLOFFSET]);
66676667
// NV-DXVK start: support height map scaling in terrain baking
6668+
data->Stages[i].texturePreOffset = 0.f;
66686669
data->Stages[i].textureScale = 1.f;
6670+
data->Stages[i].texturePostOffset = 0.f;
66696671
// NV-DXVK end
66706672
}
66716673
}
@@ -7392,7 +7394,9 @@ namespace dxvk {
73927394

73937395
auto& rs = m_state.renderStates;
73947396
DecodeD3DCOLOR((D3DCOLOR) rs[D3DRS_TEXTUREFACTOR], data->textureFactor.data);
7397+
data->texturePreOffset = 0.f;
73957398
data->textureScale = 1.f;
7399+
data->texturePostOffset = 0.f;
73967400

73977401
EmitCs([
73987402
cBuffer = m_psFixedFunction,

src/d3d9/d3d9_fixed_function.cpp

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,8 @@ namespace dxvk {
391391

392392
// NV-DXVK start: support height map scaling in terrain baking
393393
float_t,
394+
float_t,
395+
float_t,
394396
// NV-DXVK end
395397
};
396398

@@ -422,12 +424,18 @@ namespace dxvk {
422424
offset += sizeof(float);
423425

424426
// NV-DXVK start: support height map scaling in terrain baking
427+
spvModule.memberDecorateOffset(structType, stage * D3D9SharedPSStages_Count + D3D9SharedPSStages_TexturePreOffset, offset);
428+
offset += sizeof(float);
429+
425430
spvModule.memberDecorateOffset(structType, stage * D3D9SharedPSStages_Count + D3D9SharedPSStages_TextureScale, offset);
426431
offset += sizeof(float);
427-
// NV-DXVK end
428432

429-
// Padding...
433+
spvModule.memberDecorateOffset(structType, stage * D3D9SharedPSStages_Count + D3D9SharedPSStages_TexturePostOffset, offset);
430434
offset += sizeof(float);
435+
436+
// Padding
437+
offset += 3 * sizeof(float);
438+
// NV-DXVK end
431439
}
432440

433441
uint32_t sharedState = spvModule.newVar(
@@ -540,7 +548,9 @@ namespace dxvk {
540548

541549
enum D3D9FFPSMembers {
542550
TextureFactor = 0,
543-
TextureScale = 1,
551+
TexturePreOffset = 1,
552+
TextureScale = 2,
553+
TexturePostOffset = 3,
544554

545555
MemberCount
546556
};
@@ -551,7 +561,9 @@ namespace dxvk {
551561

552562
struct {
553563
uint32_t textureFactor;
564+
uint32_t texturePreOffset;
554565
uint32_t textureScale;
566+
uint32_t texturePostOffset;
555567
} constants;
556568

557569
struct {
@@ -1693,7 +1705,9 @@ namespace dxvk {
16931705
uint32_t textureValue,
16941706
uint32_t texcoord,
16951707
uint32_t texcoordType,
1708+
std::function<uint32_t()> loadTexturePreOffsetFnc,
16961709
std::function<uint32_t()> loadTextureScaleFnc,
1710+
std::function<uint32_t()> loadTexturePostOffsetFnc,
16971711
std::function<uint32_t()> loadAlbedoOpacityFnc,
16981712
std::function<void(uint32_t vec4value)> storeVec4ValueToRegisterFnc,
16991713
std::function<uint32_t()> loadVec4ValueFromRegisterFnc) {
@@ -1759,11 +1773,17 @@ namespace dxvk {
17591773
// Divide textureScale by the max input uv delta.
17601774
uint32_t textureScale = spvModule.opFDiv(floatType, loadTextureScaleFnc(), maxDelta);
17611775

1762-
// Scale the texture components towards 1 instead of towards 0 by doing:
1763-
// new value = 1 - (textureScale * (1 - value))
1764-
textureValue = spvModule.opFSub(vec4Type, spvModule.constvec4f32(1.0f, 1.0f, 1.0f, 1.0f), textureValue);
1776+
// The height values need to scale relative to a neutral value (which is different in the input image and the output map).
1777+
// First, subtract the neutral value from the pixel color:
1778+
uint32_t texturePreOffset4 = spvModule.opVectorTimesScalar(vec4Type, spvModule.constvec4f32(1.0f, 1.0f, 1.0f, 1.0f), loadTexturePreOffsetFnc());
1779+
textureValue = spvModule.opFAdd(vec4Type, texturePreOffset4, textureValue);
1780+
1781+
// Second, apply all of the scale operations:
17651782
textureValue = spvModule.opVectorTimesScalar(vec4Type, textureValue, textureScale);
1766-
textureValue = spvModule.opFSub(vec4Type, spvModule.constvec4f32(1.0f, 1.0f, 1.0f, 1.0f), textureValue);
1783+
1784+
// Third, add the output neutral value:
1785+
uint32_t texturePostOffset4 = spvModule.opVectorTimesScalar(vec4Type, spvModule.constvec4f32(1.0f, 1.0f, 1.0f, 1.0f), loadTexturePostOffsetFnc());
1786+
textureValue = spvModule.opFAdd(vec4Type, texturePostOffset4, textureValue);
17671787

17681788
// The new texture value needs to be stored before branching out, and reloaded after
17691789
storeVec4ValueToRegisterFnc(textureValue);
@@ -1994,15 +2014,27 @@ namespace dxvk {
19942014
auto loadVec4ValueFromRegisterFnc = [&]() -> uint32_t {
19952015
return m_module.opLoad(vec4Type, registerStorage);
19962016
};
2017+
auto loadTexturePreOffsetFnc = [&]() -> uint32_t {
2018+
uint32_t texturePreOffsetOffset = m_module.constu32(D3D9SharedPSStages_Count * kTerrainBakerSecondaryTextureStage + D3D9SharedPSStages_TexturePreOffset);
2019+
uint32_t texturePreOffsetPtr = m_module.opAccessChain(m_module.defPointerType(m_floatType, spv::StorageClassUniform),
2020+
m_ps.sharedState, 1, &texturePreOffsetOffset);
2021+
return m_module.opLoad(m_floatType, texturePreOffsetPtr);
2022+
};
19972023
auto loadTextureScaleFnc = [&]() -> uint32_t {
19982024
uint32_t textureScaleOffset = m_module.constu32(D3D9SharedPSStages_Count * kTerrainBakerSecondaryTextureStage + D3D9SharedPSStages_TextureScale);
19992025
uint32_t textureScalePtr = m_module.opAccessChain(m_module.defPointerType(m_floatType, spv::StorageClassUniform),
20002026
m_ps.sharedState, 1, &textureScaleOffset);
20012027
return m_module.opLoad(m_floatType, textureScalePtr);
20022028
};
2029+
auto loadTexturePostOffsetFnc = [&]() -> uint32_t {
2030+
uint32_t texturePostOffsetOffset = m_module.constu32(D3D9SharedPSStages_Count * kTerrainBakerSecondaryTextureStage + D3D9SharedPSStages_TexturePostOffset);
2031+
uint32_t texturePostOffsetPtr = m_module.opAccessChain(m_module.defPointerType(m_floatType, spv::StorageClassUniform),
2032+
m_ps.sharedState, 1, &texturePostOffsetOffset);
2033+
return m_module.opLoad(m_floatType, texturePostOffsetPtr);
2034+
};
20032035

20042036

2005-
return postprocessTextureReadForTerrainBaking(m_module, textureValue, texcoord, texcoord_t, loadTextureScaleFnc, loadAlbedoOpacityFnc, storeVec4ValueToRegisterFnc, loadVec4ValueFromRegisterFnc);
2037+
return postprocessTextureReadForTerrainBaking(m_module, textureValue, texcoord, texcoord_t, loadTexturePreOffsetFnc, loadTextureScaleFnc, loadTexturePostOffsetFnc, loadAlbedoOpacityFnc, storeVec4ValueToRegisterFnc, loadVec4ValueFromRegisterFnc);
20062038
};
20072039

20082040
texture = postprocessColorOutputTextureRead(texture);
@@ -2376,8 +2408,10 @@ namespace dxvk {
23762408

23772409
// Constant Buffer for PS.
23782410
std::array<uint32_t, uint32_t(D3D9FFPSMembers::MemberCount)> members = {
2379-
m_vec4Type, // Texture Factor
2380-
m_floatType // Texture Scale
2411+
m_vec4Type, // TextureFactor
2412+
m_floatType, // TexturePreOffset
2413+
m_floatType, // TextureScale
2414+
m_floatType // TexturePostOffset
23812415
};
23822416

23832417
const uint32_t structType =
@@ -2389,12 +2423,20 @@ namespace dxvk {
23892423
m_module.memberDecorateOffset(structType, D3D9FFPSMembers::TextureFactor, offset);
23902424
offset += sizeof(Vector4);
23912425

2426+
m_module.memberDecorateOffset(structType, D3D9FFPSMembers::TexturePreOffset, offset);
2427+
offset += sizeof(float);
2428+
23922429
m_module.memberDecorateOffset(structType, D3D9FFPSMembers::TextureScale, offset);
23932430
offset += sizeof(float);
2431+
2432+
m_module.memberDecorateOffset(structType, D3D9FFPSMembers::TexturePostOffset, offset);
2433+
offset += sizeof(float);
23942434

23952435
m_module.setDebugName(structType, "D3D9FixedFunctionPS");
23962436
m_module.setDebugMemberName (structType, D3D9FFPSMembers::TextureFactor, "TextureFactor");
2437+
m_module.setDebugMemberName (structType, D3D9FFPSMembers::TexturePreOffset, "TexturePreOffset");
23972438
m_module.setDebugMemberName (structType, D3D9FFPSMembers::TextureScale, "TextureScale");
2439+
m_module.setDebugMemberName (structType, D3D9FFPSMembers::TexturePostOffset, "TexturePostOffset");
23982440

23992441
m_ps.constantBuffer = m_module.newVar(
24002442
m_module.defPointerType(structType, spv::StorageClassUniform),
@@ -2426,7 +2468,9 @@ namespace dxvk {
24262468
};
24272469

24282470
m_ps.constants.textureFactor = LoadConstant(m_vec4Type, uint32_t(D3D9FFPSMembers::TextureFactor));
2471+
m_ps.constants.texturePreOffset = LoadConstant(m_floatType, uint32_t(D3D9FFPSMembers::TexturePreOffset));
24292472
m_ps.constants.textureScale = LoadConstant(m_floatType, uint32_t(D3D9FFPSMembers::TextureScale));
2473+
m_ps.constants.texturePostOffset = LoadConstant(m_floatType, uint32_t(D3D9FFPSMembers::TexturePostOffset));
24302474

24312475
// Samplers
24322476
for (uint32_t i = 0; i < caps::TextureStageCount; i++) {

src/d3d9/d3d9_fixed_function.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,9 @@ namespace dxvk {
260260
uint32_t textureValue,
261261
uint32_t texcoord,
262262
uint32_t texcoordType,
263+
std::function<uint32_t()> loadTexturePreOffsetFnc,
263264
std::function<uint32_t()> loadTextureScaleFnc,
265+
std::function<uint32_t()> loadTexturePostOffsetFnc,
264266
std::function<uint32_t()> loadAlbedoOpacityFnc,
265267
std::function<void(uint32_t vec4value)> storeVec4ValueToRegisterFnc,
266268
std::function<uint32_t()> loadVec4ValueFromRegisterFnc);

src/d3d9/d3d9_state.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,11 @@ namespace dxvk {
168168

169169
struct D3D9FixedFunctionPS {
170170
Vector4 textureFactor;
171+
// NV-DXVK start: support height map scaling in terrain baking
172+
float texturePreOffset;
171173
float textureScale;
174+
float texturePostOffset;
175+
// NV-DXVK end
172176
};
173177

174178
enum D3D9SharedPSStages {
@@ -178,7 +182,9 @@ namespace dxvk {
178182
D3D9SharedPSStages_BumpEnvLScale,
179183
D3D9SharedPSStages_BumpEnvLOffset,
180184
// NV-DXVK start: support height map scaling in terrain baking
185+
D3D9SharedPSStages_TexturePreOffset,
181186
D3D9SharedPSStages_TextureScale,
187+
D3D9SharedPSStages_TexturePostOffset,
182188
// NV-DXVK end
183189
D3D9SharedPSStages_Count,
184190
};
@@ -190,8 +196,10 @@ namespace dxvk {
190196
float BumpEnvLScale;
191197
float BumpEnvLOffset;
192198
// NV-DXVK start: support height map scaling in terrain baking
199+
float texturePreOffset;
193200
float textureScale;
194-
float Padding;
201+
float texturePostOffset;
202+
float padding[3];
195203
// NV-DXVK end
196204
} Stages[8];
197205
};

0 commit comments

Comments
 (0)