Skip to content

什么是跨IB渲染?

部分游戏中,身体和衣服使用了不同的Shader进行渲染,使用不同渲染的部分一般不在同一个IB中,导致材质和光照效果不同,在部分情况下,如果我们想让某个部分使用另一个部分的光照和材质Shader进行渲染,就需要用到跨IB渲染技术。

这个名字是我自己随便起的,没有英文对应的技术名词。

实现方法

首先把最终的Mod的ini先贴过来,方便随时参考:


;MARK:Constants----------------------------------------------------------
[Constants]
global $active0
global $active1
global $active2
global persist $swapkey0 = 0
global persist $swapkey1 = 1

;MARK:Present----------------------------------------------------------
[Present]
post $active0 = 0
post $active1 = 0
post $active2 = 0

;MARK:Key----------------------------------------------------------
[KeySwap_0]
condition = $active0 == 1
key = f7
type = cycle
$swapkey0 = 0,1,


;MARK:Key----------------------------------------------------------
[KeySwap_1]
condition = $active0 == 1
key = f8
type = cycle
$swapkey1 = 0,1,


;MARK:TextureOverrideVertexLimitRaise----------------------------------------------------------
[TextureOverride_6b3c1103_丝袜_VertexLimitRaise]
hash = 0ba52f8d
override_byte_stride = 40
override_vertex_count = 1025
uav_byte_stride = 4


;MARK:TextureOverrideVertexLimitRaise----------------------------------------------------------
[TextureOverride_81d8e71a_衣服_VertexLimitRaise]
hash = 1f516443
override_byte_stride = 40
override_vertex_count = 36397
uav_byte_stride = 4


;MARK:TextureOverrideVertexLimitRaise----------------------------------------------------------
[TextureOverride_298dc3b2_腿和脖子_VertexLimitRaise]
hash = 175c6c67
override_byte_stride = 40
override_vertex_count = 1051
uav_byte_stride = 4


;MARK:TextureOverrideVB----------------------------------------------------------
; 6b3c1103 ----------------------------
[TextureOverride_VB_6b3c1103_丝袜_Position]
hash = 9ca19154
cs-cb0 = Resource_6b3c1103_VertexLimit
cs-t0 = Resource6b3c1103Position
cs-t1 = Resource6b3c1103Blend
handling = skip
dispatch = 18,1,1
$active0 = 1

[TextureOverride_VB_6b3c1103_丝袜_Texcoord]
hash = 62585f16
vb1 = Resource6b3c1103Texcoord

[TextureOverride_VB_6b3c1103_丝袜_Blend]
hash = 13c142be


;MARK:TextureOverrideVB----------------------------------------------------------
; 81d8e71a ----------------------------
[TextureOverride_VB_81d8e71a_衣服_Position]
hash = 07f702b9
cs-cb0 = Resource_81d8e71a_VertexLimit
cs-t0 = Resource81d8e71aPosition
cs-t1 = Resource81d8e71aBlend
handling = skip
dispatch = 570,1,1
$active1 = 1

[TextureOverride_VB_81d8e71a_衣服_Texcoord]
hash = d4615e17
vb1 = Resource81d8e71aTexcoord

[TextureOverride_VB_81d8e71a_衣服_Blend]
hash = c123de45


;MARK:TextureOverrideVB----------------------------------------------------------
; 298dc3b2 ----------------------------
[TextureOverride_VB_298dc3b2_腿和脖子_Position]
hash = e3ca0283
cs-cb0 = Resource_298dc3b2_VertexLimit
cs-t0 = Resource298dc3b2Position
cs-t1 = Resource298dc3b2Blend
handling = skip
dispatch = 18,1,1
$active2 = 1

[TextureOverride_VB_298dc3b2_腿和脖子_Texcoord]
hash = c3af7d47
vb1 = Resource298dc3b2Texcoord

[TextureOverride_VB_298dc3b2_腿和脖子_Blend]
hash = 60cc2063


;MARK:TextureOverrideIB----------------------------------------------------------
[TextureOverride_IB_6b3c1103_丝袜_Component1]
hash = 6b3c1103
match_first_index = 0
checktextureoverride = vb1
handling = skip
ib = Resource_6b3c1103_Component1
if $swapkey0 == 1
  ; [mesh:6b3c1103-1-丝袜.001] [vertex_count:1025]
  drawindexed = 5517,0,0
endif


[Resource_VB0]
[Resource_VB1]
;MARK:TextureOverrideIB----------------------------------------------------------
[TextureOverride_IB_81d8e71a_衣服_Component1]
hash = 81d8e71a
match_first_index = 0
checktextureoverride = vb1
handling = skip
ib = Resource_81d8e71a_Component1
if $swapkey1 == 1
  ; [mesh:81d8e71a-1-水印] [vertex_count:27152]
  drawindexed = 38829,0,0
endif

; [mesh:81d8e71a-1-衣服.001] [vertex_count:6687]
drawindexed = 31557,38829,0

Resource_VB0 = ref vb0
Resource_VB1 = ref vb1

;MARK:TextureOverrideIB----------------------------------------------------------
[TextureOverride_IB_298dc3b2_腿和脖子_Component1]
hash = 298dc3b2
match_first_index = 0
checktextureoverride = vb1
handling = skip
ib = Resource_298dc3b2_Component1
ps-t8 = Resource_298dc3b2_1_d4b0a178_Slot_DiffuseMap
; [mesh:298dc3b2-1-腿和脖子.001] [vertex_count:1051]
drawindexed = 5517,0,0

ib = Resource_81d8e71a_Component1
vb0 = Resource_VB0
vb1 = Resource_VB1
; [mesh:81d8e71a-1-身体跨IB] [vertex_count:2558]
drawindexed = 13836,70386,0


;MARK:ResourceBuffer----------------------------------------------------------
[Resource_6b3c1103_VertexLimit]
type = Buffer
format = R32G32B32A32_UINT
data = 1025 0 0 0


;MARK:ResourceBuffer----------------------------------------------------------
[Resource6b3c1103Position]
type = ByteAddressBuffer
stride = 40
filename = Buffer/6b3c1103-Position.buf

[Resource6b3c1103Texcoord]
type = Buffer
stride = 8
filename = Buffer/6b3c1103-Texcoord.buf

[Resource6b3c1103Blend]
type = ByteAddressBuffer
stride = 32
filename = Buffer/6b3c1103-Blend.buf

[Resource_6b3c1103_Component1]
type = Buffer
format = DXGI_FORMAT_R32_UINT
filename = Buffer/6b3c1103-Component1.buf


;MARK:ResourceBuffer----------------------------------------------------------
[Resource_81d8e71a_VertexLimit]
type = Buffer
format = R32G32B32A32_UINT
data = 36397 0 0 0


;MARK:ResourceBuffer----------------------------------------------------------
[Resource81d8e71aPosition]
type = ByteAddressBuffer
stride = 40
filename = Buffer/81d8e71a-Position.buf

[Resource81d8e71aTexcoord]
type = Buffer
stride = 8
filename = Buffer/81d8e71a-Texcoord.buf

[Resource81d8e71aBlend]
type = ByteAddressBuffer
stride = 32
filename = Buffer/81d8e71a-Blend.buf

[Resource_81d8e71a_Component1]
type = Buffer
format = DXGI_FORMAT_R32_UINT
filename = Buffer/81d8e71a-Component1.buf


;MARK:ResourceBuffer----------------------------------------------------------
[Resource_298dc3b2_VertexLimit]
type = Buffer
format = R32G32B32A32_UINT
data = 1051 0 0 0


;MARK:ResourceBuffer----------------------------------------------------------
[Resource298dc3b2Position]
type = ByteAddressBuffer
stride = 40
filename = Buffer/298dc3b2-Position.buf

[Resource298dc3b2Texcoord]
type = Buffer
stride = 8
filename = Buffer/298dc3b2-Texcoord.buf

[Resource298dc3b2Blend]
type = ByteAddressBuffer
stride = 32
filename = Buffer/298dc3b2-Blend.buf

[Resource_298dc3b2_Component1]
type = Buffer
format = DXGI_FORMAT_R32_UINT
filename = Buffer/298dc3b2-Component1.buf


;MARK:ResourceTexture----------------------------------------------------------
[Resource_298dc3b2_1_d4b0a178_Slot_DiffuseMap]
filename = Texture/298dc3b2_1_d4b0a178_Slot_DiffuseMap.dds


;MARK:VertexShaderCheck----------------------------------------------------------
[ShaderOverride_a3c5c0c308ddeb69]
hash = a3c5c0c308ddeb69
if $costume_mods
  checktextureoverride = ib
endif

[ShaderOverride_e0f9ed199a2a5226]
hash = e0f9ed199a2a5226
if $costume_mods
  checktextureoverride = ib
endif

[ShaderOverride_98d23592a35efad9]
hash = 98d23592a35efad9
if $costume_mods
  checktextureoverride = ib
endif

[ShaderOverride_1757673cfe604ebe]
hash = 1757673cfe604ebe
if $costume_mods
  checktextureoverride = ib
endif

[ShaderOverride_2030c989673a6153]
hash = 2030c989673a6153
if $costume_mods
  checktextureoverride = ib
endif

[ShaderOverride_50bca0018babfea7]
hash = 50bca0018babfea7
if $costume_mods
  checktextureoverride = ib
endif

[ShaderOverride_3a66ac7f1cda3dd7]
hash = 3a66ac7f1cda3dd7
if $costume_mods
  checktextureoverride = ib
endif

[ShaderOverride_b57c0b15f73f5439]
hash = b57c0b15f73f5439
if $costume_mods
  checktextureoverride = ib
endif

[ShaderOverride_e81384063af12b94]
hash = e81384063af12b94
if $costume_mods
  checktextureoverride = ib
endif


;sha256=180ab2c539fc9db7795401fdf5af7c4fb102d09b97ce65a7c809e8ebaa681718

这里有很多内容是用不到的,我们去掉部分无效内容,只关注核心的几行。




[TextureOverride_VB_6b3c1103_丝袜_Texcoord]
hash = 62585f16
vb1 = Resource6b3c1103Texcoord



[TextureOverride_VB_81d8e71a_衣服_Texcoord]
hash = d4615e17
vb1 = Resource81d8e71aTexcoord


[TextureOverride_VB_298dc3b2_腿和脖子_Texcoord]
hash = c3af7d47
vb1 = Resource298dc3b2Texcoord


;MARK:TextureOverrideIB----------------------------------------------------------
[TextureOverride_IB_6b3c1103_丝袜_Component1]
hash = 6b3c1103
match_first_index = 0
checktextureoverride = vb1
handling = skip
ib = Resource_6b3c1103_Component1
if $swapkey0 == 1
  ; [mesh:6b3c1103-1-丝袜.001] [vertex_count:1025]
  drawindexed = 5517,0,0
endif


[Resource_VB0]
[Resource_VB1]
;MARK:TextureOverrideIB----------------------------------------------------------
[TextureOverride_IB_81d8e71a_衣服_Component1]
hash = 81d8e71a
match_first_index = 0
checktextureoverride = vb1
handling = skip
ib = Resource_81d8e71a_Component1
if $swapkey1 == 1
  ; [mesh:81d8e71a-1-水印] [vertex_count:27152]
  drawindexed = 38829,0,0
endif

; [mesh:81d8e71a-1-衣服.001] [vertex_count:6687]
drawindexed = 31557,38829,0

Resource_VB0 = ref vb0
Resource_VB1 = ref vb1

;MARK:TextureOverrideIB----------------------------------------------------------
[TextureOverride_IB_298dc3b2_腿和脖子_Component1]
hash = 298dc3b2
match_first_index = 0
checktextureoverride = vb1
handling = skip
ib = Resource_298dc3b2_Component1
ps-t8 = Resource_298dc3b2_1_d4b0a178_Slot_DiffuseMap
; [mesh:298dc3b2-1-腿和脖子.001] [vertex_count:1051]
drawindexed = 5517,0,0

ib = Resource_81d8e71a_Component1
vb0 = Resource_VB0
vb1 = Resource_VB1
; [mesh:81d8e71a-1-身体跨IB] [vertex_count:2558]
drawindexed = 13836,70386,0

首先我们知道

TextureOverride_IB_81d8e71a_衣服_Component1

它是复制一部分衣服的部分

TextureOverride_IB_298dc3b2_腿和脖子_Component1

它负责身体的部分

那么如果要实现跨IB渲染,我们就需要在身体的部分,把我们用衣服部分传递权重制作的身体模型给渲染出来。

所以首先,我们会在衣服的部分备份vb0和vb1:

[Resource_VB0]
[Resource_VB1]
;MARK:TextureOverrideIB----------------------------------------------------------
[TextureOverride_IB_81d8e71a_衣服_Component1]
hash = 81d8e71a
match_first_index = 0
checktextureoverride = vb1
handling = skip
ib = Resource_81d8e71a_Component1
if $swapkey1 == 1
  ; [mesh:81d8e71a-1-水印] [vertex_count:27152]
  drawindexed = 38829,0,0
endif

; [mesh:81d8e71a-1-衣服.001] [vertex_count:6687]
drawindexed = 31557,38829,0

Resource_VB0 = ref vb0
Resource_VB1 = ref vb1

这里的

[Resource_VB0]
[Resource_VB1]

就是声明资源 这里的

Resource_VB0 = ref vb0
Resource_VB1 = ref vb1

就是备份资源

备份完成资源后,要在身体的部分DrawIndexed出来,在DrawIndexed之前,需要替换IB、VB0、VB1,如下:

;MARK:TextureOverrideIB----------------------------------------------------------
[TextureOverride_IB_298dc3b2_腿和脖子_Component1]
hash = 298dc3b2
match_first_index = 0
checktextureoverride = vb1
handling = skip
ib = Resource_298dc3b2_Component1
ps-t8 = Resource_298dc3b2_1_d4b0a178_Slot_DiffuseMap
; [mesh:298dc3b2-1-腿和脖子.001] [vertex_count:1051]
drawindexed = 5517,0,0

ib = Resource_81d8e71a_Component1
vb0 = Resource_VB0
vb1 = Resource_VB1
; [mesh:81d8e71a-1-身体跨IB] [vertex_count:2558]
drawindexed = 13836,70386,0

这里的代码是我们额外加上的,加在身体部分正常drawindexed完成之后:

ib = Resource_81d8e71a_Component1
vb0 = Resource_VB0
vb1 = Resource_VB1
; [mesh:81d8e71a-1-身体跨IB] [vertex_count:2558]
drawindexed = 13836,70386,0

这里的

; [mesh:81d8e71a-1-身体跨IB] [vertex_count:2558]
drawindexed = 13836,70386,0

就是原本正常生成完Mod后,是在衣服部分drawindexed的,我们挪过来了。

到这里跨IB渲染就完成了,我们成功的把身体模型用衣服的权重来传递,并且在衣服的部位上生成Mod,最后使用跨IB渲染技术,在身体部位绘制,以达到衣服部位生成的mod使用身体材质渲染的效果。

每个游戏的跨IB方法,都要随机应变,甚至每种shader的跨IB方法都不一样,没有完全相同的方法适用于所有场景,理解其核心原理就好。

比如有些是在VB0的替换部分draw完成后copy So0的,比如有些除了copy vb0之外,还需要copy cs-t0等等来修正坐标系,具体Mod具体分析即可,如果不懂的话,首选方案还是找别人做好的跨IB渲染Mod来参考原理。