我对ThreeJS和GLSL都是新手。我试图在另一个片段着色器中重用一个片段着色器的输出,并在下一帧的同一着色器中使用相同的输出。换句话说,着色器的输出取决于前一帧中同一着色器的输出。我试图使用WebGLRenderTarget来实现这一点。
下面是我的代码:
import * as THREE from "three"
var camera, camera_2, fireShader, mainShader, renderer, scene, scene_2
const width = 1200
const height = 720
const texture = new THREE.TextureLoader().load('./images/00_map.png')
var fire = new THREE.TextureLoader().load('./images/fire_01.png')
const fireLayer = new THREE.WebGLRenderTarget(width, height)
const uniforms = {
iTime: { value: 0 },
iResolution: { value: new THREE.Vector3(width, height, 1) },
iTexture: { value: texture},
iFire: { value: fire }
}
const now = new Date()
async function init() {
const stage = document.getElementById('stage')
renderer = new THREE.WebGLRenderer({antialias: true})
scene = new THREE.Scene()
camera = new THREE.OrthographicCamera(width / -2, width / 2, height / 2, height / -2, 0.1, 20)
camera.position.z = 5
renderer.setSize(width, height)
stage.appendChild(renderer.domElement)
mainShader = await (await fetch('shaders/frag.glsl')).text()
const geometry = new THREE.PlaneGeometry(width, height)
const material = new THREE.ShaderMaterial({
uniforms,
fragmentShader: mainShader
})
material.needsUpdate = true
const plane = new THREE.Mesh(geometry, material)
scene.add(plane)
}
async function init_2 () {
scene_2 = new THREE.Scene()
camera_2 = new THREE.OrthographicCamera(width / -2, width / 2, height / 2, height / -2, 0.1, 20)
camera_2.position.z = 5
fireShader = await (await fetch('shaders/fire.glsl')).text()
const geometry = new THREE.PlaneGeometry(width, height)
const material = new THREE.ShaderMaterial({
uniforms,
fragmentShader: fireShader
})
material.needsUpdate = true
const plane = new THREE.Mesh(geometry, material)
scene_2.add(plane)
}
function render() {
uniforms.iTime.value = (new Date() - now) * .001
renderer.setRenderTarget(fireLayer)
renderer.render(scene_2, camera_2)
if (scene.children[0])
scene.children[0].material.uniforms.iFire.value = fireLayer.texture
renderer.setRenderTarget(null)
renderer.render(scene, camera)
}
function animate() {
render()
requestAnimationFrame(animate)
}
init()
init_2()
animate()
字符串
更新纹理如上图所示,即scene.children[0].material.uniforms.iFire.value = fireLayer.texture
导致非法反馈错误。当我尝试使用{...fireLayer.texture}
更新纹理时,什么都没有显示。我怀疑这是因为这样复制并没有复制图像。
如何正确复制片段着色器的输出并在生成它的同一着色器中使用它?
1条答案
按热度按时间rjjhvcjd1#
如果你尝试读写同一张图片,你会得到未定义的结果和一个非法的反馈错误。你必须使用
FramebufferTexture
。将着色器的输出复制到帧缓冲区纹理中,并将此纹理用作下一帧的输入:个字符