我正在尝试使用 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;
}`;
看来您在渲染器中设置了渲染目标。尝试像这样重写你的
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>