@@ -13,14 +13,12 @@ import {
1313 Color ,
1414 ColorRepresentation ,
1515 Group ,
16- Material ,
1716 Mesh ,
1817 MeshBasicMaterial ,
1918 MeshDepthMaterial ,
2019 OrthographicCamera ,
2120 PlaneGeometry ,
2221 ShaderMaterial ,
23- Texture ,
2422 WebGLRenderTarget ,
2523} from 'three' ;
2624import { HorizontalBlurShader , VerticalBlurShader } from 'three-stdlib' ;
@@ -119,24 +117,20 @@ export class NgtsContactShadows {
119117 private color = pick ( this . options , 'color' ) ;
120118 private near = pick ( this . options , 'near' ) ;
121119 private far = pick ( this . options , 'far' ) ;
122-
123- private shadowsOptions = computed ( ( ) => {
124- const [ width , height , resolution , color ] = [
125- this . scaledWidth ( ) ,
126- this . scaledHeight ( ) ,
127- this . resolution ( ) ,
128- this . color ( ) ,
129- ] ;
130- const renderTarget = new WebGLRenderTarget ( resolution , resolution ) ;
131- const renderTargetBlur = new WebGLRenderTarget ( resolution , resolution ) ;
132- renderTargetBlur . texture . generateMipmaps = renderTarget . texture . generateMipmaps = false ;
133-
134- const planeGeometry = new PlaneGeometry ( width , height ) . rotateX ( Math . PI / 2 ) ;
135- const blurPlane = new Mesh ( planeGeometry ) ;
136- const depthMaterial = new MeshDepthMaterial ( ) ;
137- depthMaterial . depthTest = depthMaterial . depthWrite = false ;
138- depthMaterial . onBeforeCompile = ( shader ) => {
139- shader . uniforms = { ...shader . uniforms , ucolor : { value : new Color ( color ) } } ;
120+ private smooth = pick ( this . options , 'smooth' ) ;
121+ private frames = pick ( this . options , 'frames' ) ;
122+ private blur = pick ( this . options , 'blur' ) ;
123+
124+ private renderTarget = computed ( ( ) => this . createRenderTarget ( this . resolution ( ) ) ) ;
125+ private renderTargetBlur = computed ( ( ) => this . createRenderTarget ( this . resolution ( ) ) ) ;
126+ planeGeometry = computed ( ( ) => new PlaneGeometry ( this . scaledWidth ( ) , this . scaledHeight ( ) ) . rotateX ( Math . PI / 2 ) ) ;
127+ private blurPlane = computed ( ( ) => new Mesh ( this . planeGeometry ( ) ) ) ;
128+ private depthMaterial = computed ( ( ) => {
129+ const color = new Color ( this . color ( ) ) ;
130+ const material = new MeshDepthMaterial ( ) ;
131+ material . depthTest = material . depthWrite = false ;
132+ material . onBeforeCompile = ( shader ) => {
133+ shader . uniforms = { ...shader . uniforms , ucolor : { value : color } } ;
140134 shader . fragmentShader = shader . fragmentShader . replace (
141135 `void main() {` , //
142136 `uniform vec3 ucolor;
@@ -149,86 +143,107 @@ export class NgtsContactShadows {
149143 'vec4( ucolor * fragCoordZ * 2.0, ( 1.0 - fragCoordZ ) * 1.0 );' ,
150144 ) ;
151145 } ;
152-
153- const horizontalBlurMaterial = new ShaderMaterial ( HorizontalBlurShader ) ;
154- const verticalBlurMaterial = new ShaderMaterial ( VerticalBlurShader ) ;
155- verticalBlurMaterial . depthTest = horizontalBlurMaterial . depthTest = false ;
156-
157- return {
158- renderTarget,
159- planeGeometry,
160- depthMaterial,
161- blurPlane,
162- horizontalBlurMaterial,
163- verticalBlurMaterial,
164- renderTargetBlur,
165- } ;
146+ return material ;
166147 } ) ;
167148
149+ private horizontalBlurMaterial = new ShaderMaterial ( { ...HorizontalBlurShader , depthTest : false } ) ;
150+ private verticalBlurMaterial = new ShaderMaterial ( { ...VerticalBlurShader , depthTest : false } ) ;
151+
168152 renderOrder = pick ( this . options , 'renderOrder' ) ;
169153 opacity = pick ( this . options , 'opacity' ) ;
170154 depthWrite = pick ( this . options , 'depthWrite' ) ;
171- planeGeometry = computed ( ( ) => this . shadowsOptions ( ) . planeGeometry ) ;
172- texture = computed ( ( ) => this . shadowsOptions ( ) . renderTarget . texture ) ;
155+ texture = pick ( this . renderTarget , 'texture' ) ;
173156 cameraArgs = computed ( ( ) => {
174157 const [ width , height , near , far ] = [ this . scaledWidth ( ) , this . scaledHeight ( ) , this . near ( ) , this . far ( ) ] ;
175158 return [ - width / 2 , width / 2 , height / 2 , - height / 2 , near , far ] ;
176159 } ) ;
177160
161+ constructor ( ) {
162+ extend ( { Group, Mesh, MeshBasicMaterial, OrthographicCamera } ) ;
163+
164+ let count = 0 ;
165+ injectBeforeRender ( ( ) => {
166+ const shadowsCamera = this . shadowsCameraRef ( ) ?. nativeElement ;
167+ if ( ! shadowsCamera ) return ;
168+
169+ const frames = this . frames ( ) ;
170+ if ( frames === Infinity || count < frames ) {
171+ this . renderShadows ( ) ;
172+ count ++ ;
173+ }
174+ } ) ;
175+ }
176+
177+ private renderShadows ( ) {
178+ const shadowsCamera = this . shadowsCameraRef ( ) ?. nativeElement ;
179+ if ( ! shadowsCamera ) return ;
180+
181+ const [ blur , smooth , gl , scene , contactShadows , depthMaterial , renderTarget ] = [
182+ this . blur ( ) ,
183+ this . smooth ( ) ,
184+ this . gl ( ) ,
185+ this . scene ( ) ,
186+ this . contactShadowsRef ( ) . nativeElement ,
187+ this . depthMaterial ( ) ,
188+ this . renderTarget ( ) ,
189+ ] ;
190+
191+ const initialBackground = scene . background ;
192+ const initialOverrideMaterial = scene . overrideMaterial ;
193+ const initialClearAlpha = gl . getClearAlpha ( ) ;
194+
195+ contactShadows . visible = false ;
196+ scene . background = null ;
197+ scene . overrideMaterial = depthMaterial ;
198+ gl . setClearAlpha ( 0 ) ;
199+
200+ // render to the render target to get the depths
201+ gl . setRenderTarget ( renderTarget ) ;
202+ gl . render ( scene , shadowsCamera ) ;
203+
204+ this . blurShadows ( blur ) ;
205+ if ( smooth ) this . blurShadows ( blur * 0.4 ) ;
206+
207+ // reset
208+ gl . setRenderTarget ( null ) ;
209+
210+ contactShadows . visible = true ;
211+ scene . overrideMaterial = initialOverrideMaterial ;
212+ scene . background = initialBackground ;
213+ gl . setClearAlpha ( initialClearAlpha ) ;
214+ }
215+
178216 private blurShadows ( blur : number ) {
179- const { renderTarget, renderTargetBlur, blurPlane, horizontalBlurMaterial, verticalBlurMaterial } =
180- this . shadowsOptions ( ) ;
181217 const shadowsCamera = this . shadowsCameraRef ( ) ?. nativeElement ;
182218 if ( ! shadowsCamera ) return ;
183219
220+ const [ blurPlane , horizontalBlurMaterial , verticalBlurMaterial , renderTargetBlur , renderTarget , gl ] = [
221+ this . blurPlane ( ) ,
222+ this . horizontalBlurMaterial ,
223+ this . verticalBlurMaterial ,
224+ this . renderTargetBlur ( ) ,
225+ this . renderTarget ( ) ,
226+ this . gl ( ) ,
227+ ] ;
228+
184229 blurPlane . visible = true ;
185230 blurPlane . material = horizontalBlurMaterial ;
186231 horizontalBlurMaterial . uniforms [ 'tDiffuse' ] . value = renderTarget . texture ;
187232 horizontalBlurMaterial . uniforms [ 'h' ] . value = blur / 256 ;
188- this . gl ( ) . setRenderTarget ( renderTargetBlur ) ;
189- this . gl ( ) . render ( blurPlane , shadowsCamera ) ;
233+ gl . setRenderTarget ( renderTargetBlur ) ;
234+ gl . render ( blurPlane , shadowsCamera ) ;
190235
191236 blurPlane . material = verticalBlurMaterial ;
192237 verticalBlurMaterial . uniforms [ 'tDiffuse' ] . value = renderTargetBlur . texture ;
193238 verticalBlurMaterial . uniforms [ 'v' ] . value = blur / 256 ;
194- this . gl ( ) . setRenderTarget ( renderTarget ) ;
195- this . gl ( ) . render ( blurPlane , shadowsCamera ) ;
239+ gl . setRenderTarget ( renderTarget ) ;
240+ gl . render ( blurPlane , shadowsCamera ) ;
196241 blurPlane . visible = false ;
197242 }
198243
199- constructor ( ) {
200- extend ( { Group, Mesh, MeshBasicMaterial, OrthographicCamera } ) ;
201-
202- let count = 0 ;
203- let initialBackground : Color | Texture | null ;
204- let initialOverrideMaterial : Material | null ;
205-
206- injectBeforeRender ( ( ) => {
207- const shadowsCamera = this . shadowsCameraRef ( ) ?. nativeElement ;
208- if ( ! shadowsCamera ) return ;
209- const [ { frames, blur, smooth } , gl , scene , contactShadows , { depthMaterial, renderTarget } ] = [
210- this . options ( ) ,
211- this . gl ( ) ,
212- this . scene ( ) ,
213- this . contactShadowsRef ( ) . nativeElement ,
214- this . shadowsOptions ( ) ,
215- ] ;
216- if ( frames === Infinity || count < frames * frames ) {
217- count ++ ;
218- initialBackground = scene . background ;
219- initialOverrideMaterial = scene . overrideMaterial ;
220- contactShadows . visible = false ;
221- scene . background = null ;
222- scene . overrideMaterial = depthMaterial ;
223- gl . setRenderTarget ( renderTarget ) ;
224- gl . render ( scene , shadowsCamera ) ;
225- this . blurShadows ( blur ) ;
226- if ( smooth ) this . blurShadows ( blur * 0.4 ) ;
227- gl . setRenderTarget ( null ) ;
228- contactShadows . visible = true ;
229- scene . overrideMaterial = initialOverrideMaterial ;
230- scene . background = initialBackground ;
231- }
232- } ) ;
244+ private createRenderTarget ( resolution : number ) {
245+ const renderTarget = new WebGLRenderTarget ( resolution , resolution ) ;
246+ renderTarget . texture . generateMipmaps = false ;
247+ return renderTarget ;
233248 }
234249}
0 commit comments