使用 ThreeJS 从片段着色器读取生成的纹理时出现问题

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

我正在尝试使用 Three.WebGLRenderTarget 生成纹理,然后在下一阶段的片段着色器中访问它。

这个想法是运行第一阶段一次以生成复杂且昂贵的 SDF 地图,然后根据需要在后续阶段中访问它。

目前,如果我将其直接发送到屏幕,我可以生成测试纹理,但当我将其发送到纹理并尝试读取它时,我只会得到黑屏。

我猜这很简单,感谢任何帮助。

测试代码:

import * as Three from 'three'

const renderer = new Three.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)


const buffer = new Three.WebGLRenderTarget(window.innerWidth, window.innerHeight, {
    minFilter: Three.LinearFilter,
    magFilter: Three.LinearFilter,
    stencilBuffer: false,
    depthBuffer: false,
    type: Three.UnsignedByteType
});
buffer.texture.needsUpdate = false;

const camera = new Three.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
)
camera.position.set(0, 0, 1000);

//Buffer scene
const bufferScene = new Three.Scene()

const bufferQuad = new Three.Mesh(
    new Three.PlaneGeometry(2, 2),
    new Three.ShaderMaterial({
        uniforms: {
            u_resolution: { value: new Three.Vector2(window.innerWidth, window.innerHeight) }
        },
        blending: Three.NoBlending,
        vertexShader: vertShader,
        fragmentShader: bufferShader,
        depthWrite: false,
        depthTest: false,
    })
);

bufferScene.add(bufferQuad);


//Screen Scene
const screenScene = new Three.Scene()

const screenQuad = new Three.Mesh(
    new Three.PlaneGeometry(2, 2),
    new Three.ShaderMaterial({
        uniforms: {
            buffer: { value: buffer.texture }
        },
        blending: Three.NoBlending,
        vertexShader: vertShader,
        fragmentShader: screenShader,
        depthWrite: false,
        depthTest: false,

    })
);

screenScene.add(screenQuad);


window.addEventListener('resize', onWindowResize, false)

function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix()
    renderer.setSize(window.innerWidth, window.innerHeight)
    render(screenScene)
}

function loop() {
    requestAnimationFrame(loop)
    render(screenScene)
}

function render(scene) {
    renderer.render(scene, camera)
}

function main() {
    render(bufferScene);
    loop();
}

main()

还有着色器

const vertShader = `
varying vec2 vUv;

void main(){
    
    vUv=position.xy*.5+.5;
    gl_Position=vec4(position.xy,1.,1.);
}`;

const bufferShader = `
precision highp float;

uniform vec2 u_resolution;

void main(){
    vec2 uv=gl_FragCoord.xy/u_resolution.xy;
    gl_FragColor=vec4(uv,0.,1.);
}`;

const screenShader = `
precision highp float;

uniform sampler2D buffer;
varying vec2 vUv;

void main(){
    
    vec4 texel=texture2D(buffer,vUv);
    gl_FragColor=texel;
}`;
javascript three.js glsl webgl
1个回答
1
投票

看来您在渲染器中设置了渲染目标。尝试像这样重写你的

main()
函数:

function main() {
    renderer.setRenderTarget(buffer);
    render(bufferScene);
    renderer.setRenderTarget(null);
    loop();
}

完整代码:

const vertShader = `
varying vec2 vUv;

void main(){
    
    vUv=position.xy*.5+.5;
    gl_Position=vec4(position.xy,1.,1.);
}`;

const bufferShader = `
precision highp float;

uniform vec2 u_resolution;

void main(){
    vec2 uv=gl_FragCoord.xy/u_resolution.xy;
    gl_FragColor=vec4(uv,0.,1.);
}`;

const screenShader = `
precision highp float;

uniform sampler2D buffer;
varying vec2 vUv;

void main(){
    
    vec4 texel=texture2D(buffer,vUv);
    gl_FragColor=texel;
}`;

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)


const buffer = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight, {
  minFilter: THREE.LinearFilter,
  magFilter: THREE.LinearFilter,
  stencilBuffer: false,
  depthBuffer: false,
  type: THREE.UnsignedByteType
});
buffer.texture.needsUpdate = false;

const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
)
camera.position.set(0, 0, 1000);

//Buffer scene
const bufferScene = new THREE.Scene()

const bufferQuad = new THREE.Mesh(
  new THREE.PlaneGeometry(2, 2),
  new THREE.ShaderMaterial({
    uniforms: {
      u_resolution: {
        value: new THREE.Vector2(window.innerWidth, window.innerHeight)
      }
    },
    blending: THREE.NoBlending,
    vertexShader: vertShader,
    fragmentShader: bufferShader,
    depthWrite: false,
    depthTest: false,
  })
);

bufferScene.add(bufferQuad);


//Screen Scene
const screenScene = new THREE.Scene()

const screenQuad = new THREE.Mesh(
  new THREE.PlaneGeometry(2, 2),
  new THREE.ShaderMaterial({
    uniforms: {
      buffer: {
        value: buffer.texture
      }
    },
    blending: THREE.NoBlending,
    vertexShader: vertShader,
    fragmentShader: screenShader,
    depthWrite: false,
    depthTest: false,

  })
);

screenScene.add(screenQuad);


window.addEventListener('resize', onWindowResize, false)

function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()
  renderer.setSize(window.innerWidth, window.innerHeight)
  render(screenScene)
}

function loop() {
  requestAnimationFrame(loop)
  render(screenScene)
}

function render(scene) {
  renderer.render(scene, camera)
}

function main() {
  renderer.setRenderTarget(buffer);
  render(bufferScene);
  renderer.setRenderTarget(null);
  loop();
}

main()
body {
      margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script>

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