1
1
import { Engine } from "../Engine" ;
2
- import { BlendFactor , BlendOperation , CullMode , Shader , ShaderPass , ShaderProperty } from "../shader" ;
2
+ import { BlendFactor , BlendOperation , CullMode , Shader , ShaderProperty } from "../shader" ;
3
3
import { RenderQueueType } from "../shader/enums/RenderQueueType" ;
4
4
import { ShaderMacro } from "../shader/ShaderMacro" ;
5
5
import { RenderState } from "../shader/state/RenderState" ;
@@ -8,6 +8,9 @@ import { RenderFace } from "./enums/RenderFace";
8
8
import { Material } from "./Material" ;
9
9
10
10
export class BaseMaterial extends Material {
11
+ /** @internal */
12
+ static _shadowCasterRenderQueueProp = ShaderProperty . getByName ( "material_ShadowCasterRenderQueue" ) ;
13
+
11
14
protected static _baseTextureMacro : ShaderMacro = ShaderMacro . getByName ( "MATERIAL_HAS_BASETEXTURE" ) ;
12
15
protected static _normalTextureMacro : ShaderMacro = ShaderMacro . getByName ( "MATERIAL_HAS_NORMALTEXTURE" ) ;
13
16
protected static _emissiveTextureMacro : ShaderMacro = ShaderMacro . getByName ( "MATERIAL_HAS_EMISSIVETEXTURE" ) ;
@@ -27,8 +30,6 @@ export class BaseMaterial extends Material {
27
30
private _renderFace : RenderFace = RenderFace . Front ;
28
31
private _isTransparent : boolean = false ;
29
32
private _blendMode : BlendMode = BlendMode . Normal ;
30
- private _shadowPass : ShaderPass ;
31
- private _shadowPassIndex : number ;
32
33
33
34
/**
34
35
* Shader used by the material.
@@ -62,21 +63,33 @@ export class BaseMaterial extends Material {
62
63
} else {
63
64
renderStates . length = maxPassCount ;
64
65
}
65
-
66
- this . _refreshShadowPassInfo ( ) ;
67
66
}
68
67
69
68
/**
70
- * Whethor transparent of first shader pass render state.
69
+ * Whether transparent of first shader pass render state.
71
70
*/
72
71
get isTransparent ( ) : boolean {
73
72
return this . _isTransparent ;
74
73
}
75
74
76
75
set isTransparent ( value : boolean ) {
77
76
if ( value !== this . _isTransparent ) {
78
- this . _isTransparent = value ;
79
77
this . setIsTransparent ( 0 , value ) ;
78
+
79
+ const { shaderData } = this ;
80
+ if ( value ) {
81
+ // Use alpha test queue to simulate transparent shadow
82
+ shaderData . setFloat ( BaseMaterial . _shadowCasterRenderQueueProp , RenderQueueType . AlphaTest ) ;
83
+ } else {
84
+ const alphaCutoff = shaderData . getFloat ( BaseMaterial . _alphaCutoffProp ) ;
85
+ if ( alphaCutoff ) {
86
+ shaderData . setFloat ( BaseMaterial . _shadowCasterRenderQueueProp , RenderQueueType . AlphaTest ) ;
87
+ } else {
88
+ shaderData . setFloat ( BaseMaterial . _shadowCasterRenderQueueProp , RenderQueueType . Opaque ) ;
89
+ }
90
+ }
91
+
92
+ this . _isTransparent = value ;
80
93
}
81
94
}
82
95
@@ -90,8 +103,8 @@ export class BaseMaterial extends Material {
90
103
91
104
set blendMode ( value : BlendMode ) {
92
105
if ( value !== this . _blendMode ) {
93
- this . _blendMode = value ;
94
106
this . setBlendMode ( 0 , value ) ;
107
+ this . _blendMode = value ;
95
108
}
96
109
}
97
110
@@ -110,8 +123,14 @@ export class BaseMaterial extends Material {
110
123
if ( shaderData . getFloat ( BaseMaterial . _alphaCutoffProp ) !== value ) {
111
124
if ( value ) {
112
125
shaderData . enableMacro ( BaseMaterial . _alphaCutoffMacro ) ;
126
+ shaderData . setFloat ( BaseMaterial . _shadowCasterRenderQueueProp , RenderQueueType . AlphaTest ) ;
113
127
} else {
114
128
shaderData . disableMacro ( BaseMaterial . _alphaCutoffMacro ) ;
129
+ if ( this . _isTransparent ) {
130
+ shaderData . setFloat ( BaseMaterial . _shadowCasterRenderQueueProp , RenderQueueType . AlphaTest ) ;
131
+ } else {
132
+ shaderData . setFloat ( BaseMaterial . _shadowCasterRenderQueueProp , RenderQueueType . Opaque ) ;
133
+ }
115
134
}
116
135
117
136
const { renderStates } = this ;
@@ -127,10 +146,7 @@ export class BaseMaterial extends Material {
127
146
: RenderQueueType . Opaque ;
128
147
}
129
148
}
130
-
131
149
shaderData . setFloat ( BaseMaterial . _alphaCutoffProp , value ) ;
132
-
133
- this . _setShadowPassRenderQueueType ( ) ;
134
150
}
135
151
}
136
152
@@ -155,7 +171,10 @@ export class BaseMaterial extends Material {
155
171
*/
156
172
constructor ( engine : Engine , shader : Shader ) {
157
173
super ( engine , shader ) ;
158
- this . shaderData . setFloat ( BaseMaterial . _alphaCutoffProp , 0 ) ;
174
+
175
+ const { shaderData } = this ;
176
+ shaderData . setFloat ( BaseMaterial . _alphaCutoffProp , 0 ) ;
177
+ shaderData . setFloat ( BaseMaterial . _shadowCasterRenderQueueProp , RenderQueueType . Opaque ) ;
159
178
}
160
179
161
180
/**
@@ -169,22 +188,22 @@ export class BaseMaterial extends Material {
169
188
throw "Pass should less than pass count." ;
170
189
}
171
190
const renderState = renderStates [ passIndex ] ;
191
+ const { shaderData } = this ;
172
192
173
193
if ( isTransparent ) {
174
194
renderState . blendState . targetBlendState . enabled = true ;
175
195
renderState . depthState . writeEnabled = false ;
176
196
renderState . renderQueueType = RenderQueueType . Transparent ;
177
- this . shaderData . enableMacro ( BaseMaterial . _transparentMacro ) ;
197
+ shaderData . enableMacro ( BaseMaterial . _transparentMacro ) ;
178
198
} else {
179
199
renderState . blendState . targetBlendState . enabled = false ;
180
200
renderState . depthState . writeEnabled = true ;
181
- renderState . renderQueueType = this . shaderData . getFloat ( BaseMaterial . _alphaCutoffProp )
201
+
202
+ renderState . renderQueueType = shaderData . getFloat ( BaseMaterial . _alphaCutoffProp )
182
203
? RenderQueueType . AlphaTest
183
204
: RenderQueueType . Opaque ;
184
- this . shaderData . disableMacro ( BaseMaterial . _transparentMacro ) ;
205
+ shaderData . disableMacro ( BaseMaterial . _transparentMacro ) ;
185
206
}
186
-
187
- this . _setShadowPassRenderQueueType ( ) ;
188
207
}
189
208
190
209
/**
@@ -260,31 +279,4 @@ export class BaseMaterial extends Material {
260
279
target . _isTransparent = this . _isTransparent ;
261
280
target . _blendMode = this . _blendMode ;
262
281
}
263
-
264
- private _refreshShadowPassInfo ( ) : void {
265
- const passes = this . shader . subShaders [ 0 ] . passes ;
266
- const length = passes . length ;
267
- this . _shadowPass = null ;
268
- this . _shadowPassIndex = null ;
269
-
270
- for ( let i = 0 ; i < length ; i ++ ) {
271
- const pass = passes [ i ] ;
272
- if ( pass . name === "ShadowCaster" ) {
273
- this . _shadowPass = pass ;
274
- this . _shadowPassIndex = i ;
275
- }
276
- }
277
- }
278
-
279
- private _setShadowPassRenderQueueType ( ) : void {
280
- const shadowPass = this . _shadowPass ;
281
-
282
- if ( shadowPass ) {
283
- const alphaCutoff = this . shaderData . getFloat ( BaseMaterial . _alphaCutoffProp ) ;
284
- const renderState = shadowPass . _renderState ?? this . renderStates [ this . _shadowPassIndex ] ;
285
-
286
- renderState . renderQueueType =
287
- alphaCutoff || this . _isTransparent ? RenderQueueType . AlphaTest : RenderQueueType . Opaque ;
288
- }
289
- }
290
282
}
0 commit comments