Can't make horizontal and vertical blur render together

I’m trying to implement contact shadows based on this example. I managed to create a render target (shadowRenderTarget) where the base of the contact shadow appears. Now I’d like to blur it like in the example. I have another render target (blurRenderTarget) to achieve this.

When I do the horizontal blur it seems working:

blurPlaneMesh.material = horizontalBlurMaterial;
blurPlaneMesh.material.uniforms.tDiffuse.value = shadowRenderTarget.texture;
horizontalBlurMaterial.uniforms.h.value = amount * 1 / 256;
renderer.setRenderTarget (blurRenderTarget);
renderer.render (blurPlaneMesh, shadowCamera);

The blurred shadow appears on the blurPlaneMesh. But when I try to do the vertical blur targeting the original render target it becomes completely white.

blurPlaneMesh.material = verticalBlurMaterial;
blurPlaneMesh.material.uniforms.tDiffuse.value = blurRenderTarget.texture;
verticalBlurMaterial.uniforms.v.value = amount * 1 / 256;
renderer.setRenderTarget (shadowRenderTarget);
renderer.render (blurPlaneMesh, shadowCamera);

I have no idea what I’m doing wrong. Here is a JSFiddle with my result. If you comment out the blurring part at the end you can see that it seems working fine without the blurring.

i struggled a lot with that example, it’s very cryptic, maybe it helps to compare notes with this one. it’s a slightly improved implementation, it looks better and can handle color falloff.

import { HorizontalBlurShader, VerticalBlurShader } from 'three-stdlib'

const smooth = true
const renderer = ...
const scene = ...
const blur = 1
const color = "black"
const resolution = 512
const width = 10
const height = 10

const renderTarget = new THREE.WebGLRenderTarget(resolution, resolution)
const renderTargetBlur = new THREE.WebGLRenderTarget(resolution, resolution)
renderTargetBlur.texture.generateMipmaps = renderTarget.texture.generateMipmaps = false
const planeGeometry = new THREE.PlaneGeometry(width, height).rotateX(Math.PI / 2)
const blurPlane = new THREE.Mesh(planeGeometry)
const depthMaterial = new THREE.MeshDepthMaterial()
depthMaterial.depthTest = depthMaterial.depthWrite = false
depthMaterial.onBeforeCompile = (shader) => {
  shader.uniforms = {
    ...shader.uniforms,
    ucolor: { value: new THREE.Color(color) },
  }
  shader.fragmentShader = shader.fragmentShader.replace(
    `void main() {`, //
    `uniform vec3 ucolor;
     void main() {
    `
  )
  shader.fragmentShader = shader.fragmentShader.replace(
    'vec4( vec3( 1.0 - fragCoordZ ), opacity );',
    // Colorize the shadow, multiply by the falloff so that the center can remain darker
    'vec4( ucolor * fragCoordZ * 2.0, ( 1.0 - fragCoordZ ) * 1.0 );'
  )
}

const horizontalBlurMaterial = new THREE.ShaderMaterial(HorizontalBlurShader)
const verticalBlurMaterial = new THREE.ShaderMaterial(VerticalBlurShader)
verticalBlurMaterial.depthTest = horizontalBlurMaterial.depthTest = false

const blurShadows = (blur) => {
  blurPlane.visible = true

  blurPlane.material = horizontalBlurMaterial
  horizontalBlurMaterial.uniforms.tDiffuse.value = renderTarget.texture
  horizontalBlurMaterial.uniforms.h.value = (blur * 1) / 256

  renderer.setRenderTarget(renderTargetBlur)
  renderer.render(blurPlane, shadowCamera.current)

  blurPlane.material = verticalBlurMaterial
  verticalBlurMaterial.uniforms.tDiffuse.value = renderTargetBlur.texture
  verticalBlurMaterial.uniforms.v.value = (blur * 1) / 256

  renderer.setRenderTarget(renderTarget)
  renderer.render(blurPlane, shadowCamera.current)

  blurPlane.visible = false
}

function renderloop() {
  const initialBackground = scene.background
  scene.background = null
  const initialOverrideMaterial = scene.overrideMaterial
  scene.overrideMaterial = depthMaterial
  renderer.setRenderTarget(renderTarget)
  renderer.render(scene, shadowCamera.current)
  scene.overrideMaterial = initialOverrideMaterial

  blurShadows(blur)
  if (smooth) blurShadows(blur * 0.4)

  renderer.setRenderTarget(null)
  scene.background = initialBackground

you would need the following structure, i’ll leave this in jsx because you most likely have that already, the rotations are necessary.

<group rotation-x={Math.PI / 2} {...props} ref={ref as any}>
  <mesh renderOrder={renderOrder} geometry={planeGeometry} scale={[1, -1, 1]} rotation={[-Math.PI / 2, 0, 0]}>
    <meshBasicMaterial
      map={renderTarget.texture}
      map-encoding={gl.outputEncoding}
      transparent
      opacity={opacity}
      depthWrite={depthWrite}
    />
  </mesh>
  <orthographicCamera ref={shadowCamera} args={[-width / 2, width / 2, height / 2, -height / 2, 0, far]} />
</group>

Thanks for the link! Finally I managed to solve the situation, something was off with my camera so I ended up using a completely separate camera for blurring, and now it seems working.