React-三纤维高斯模糊

问题描述 投票:0回答:1

我正在尝试向场景添加高斯模糊。我正在使用这个 GLSL 着色器:

uniform sampler2D tDiffuse;
uniform int uKernel;
uniform float uSigma;
uniform vec2 uDirection;
uniform float uStrength;
uniform float uDirectionalResolution;
varying vec2 v_Uv;

float gaussianPdf(in float x,in float sigma){
  return(.39894/sigma)*exp(-.5*x*x/(sigma*sigma));
}

float parabola(float x,float k){
  return pow(4.*x*(1.-x),k);
}

void main(){
  float weightSum=gaussianPdf(0.,uSigma);
  vec4 t=texture2D(tDiffuse,v_Uv);
  vec3 diffuseSum=t.rgb*weightSum;
  float invSize=1./uDirectionalResolution;
  
  float focus=distance(vec2(.5),v_Uv);
  focus=smoothstep(0.,.7,focus);
  
  for(int i=1;i<uKernel;i++){
    float x=float(i);
    float w=gaussianPdf(x,uSigma);
    
    vec2 offset=uDirection*invSize*x*uStrength*focus;
    vec4 sample1=texture2D(tDiffuse,v_Uv+offset);
    vec4 sample2=texture2D(tDiffuse,v_Uv-offset);
    diffuseSum+=(sample1.rgb+sample2.rgb)*w;
    weightSum+=2.*w;
  }
  
  gl_FragColor=vec4(diffuseSum/weightSum,1.);
}

当您提供图像作为 tDiffuse 纹理时,它适用于图像,但我试图将其添加为后处理效果。我尝试获取相机的 renderTarget 并将该纹理作为 tDiffuse 传递,但这在计算上太昂贵了:(
这是反应代码:

import vert from "./vertex.glsl"
import frag from "./fragment.glsl"

function BlurShader() {
    const { gl, size, scene, camera } = useThree();
    const uniforms = useMemo(() => ({
        time: { value: 0.0 },
        uKernel: { value: 13 },
        uSigma: { value: 3 },
        tDiffuse: { value: null },
        uStrength: { value: 1 },
        uDirection: { value: new THREE.Vector2(1, 1) },
        uDirectionalResolution: { value: 512 },
    }), [])
    return (
        <>

        </>
    )
}


export default function Test() {
    return (
        <div className='h-full w-full absolute'>
            <Canvas camera={{ fov: 75, near: 0.01, far: 50, position: [0, 0, 1] }}>
                <color attach="background" args={["black"]} />
                <OrbitControls />
                <Particles />
                <BlurShader />
            </Canvas>
        </div>
    )
}

有没有一种方法可以在不执行相机 renderTarget 的情况下实现此目的?或者有其他更有效的方法吗?

three.js glsl react-three-fiber react-three-drei
1个回答
0
投票

我采用了简单的方法,使用react- Three / drei中的“useFBO”创建了我想要的效果

function BlurShader() {
const FBOTarget = useFBO(1024, 1024, { stencilBuffer: false, minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter });
const materialRef = useRef();
const uniforms = useMemo(() => ({
    time: { value: 0.0 },
    uKernel: { value: 13 },
    uSigma: { value: 6 },
    tDiffuse: { value: null },
    uStrength: { value: 2.5 },
    uDirection: { value: new THREE.Vector2(1, 1) },
    uDirectionalResolution: { value: 512 },
    resolution: { value: new THREE.Vector2(1024, 1024) },
}), [])
useFrame((state) => {
    state.gl.setRenderTarget(FBOTarget);
    state.gl.render(state.scene, state.camera);
    state.gl.setRenderTarget(null);
    materialRef.current.uniforms.tDiffuse.value = FBOTarget.texture;
})
return (
    <>
        <mesh position={[0, 0, 0.2]}>
            <planeGeometry args={[2, 1]} />
            <shaderMaterial
                ref={materialRef}
                fragmentShader={frag}
                vertexShader={vert}
                uniforms={uniforms}
            />
        </mesh>
        <Box args={[0.2, 0.2, 0.2]} position={[0.5, 0.2, 0]} >
            <meshBasicMaterial color={"green"} />
        </Box>
        <Box args={[0.2, 0.2, 0.2]} position={[0.1, 0, -0.1]} >
            <meshBasicMaterial color={"yellow"} />
        </Box>
        <Box args={[0.2, 0.2, 0.2]} position={[-0.7, 0.2, 0]} >
            <meshBasicMaterial color={"red"} />
        </Box>
        <Box args={[0.2, 0.2, 0.2]} position={[-0.4, -0.3, -0.3]} >
            <meshBasicMaterial color={"blue"} />
        </Box>
    </>
)}

结果如下:Blur

但我仍然不知道如何将其应用到相机而不是飞机上。 也许将其渲染到屏幕外,然后再次渲染到相机,或者使用effectComposer?

© www.soinside.com 2019 - 2024. All rights reserved.