-
-
Notifications
You must be signed in to change notification settings - Fork 35.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
WebGLMultipleRenderTargets: Add multisampling support. (#24001)
* setUsage does not update attributes after the buffer is created * check is not necessary in the buffer creation * clean code * prevent unnecessary double buffer update * fix lint * [WebGLMultipleRenderTarget] Support Multisampling [WebGLMultipleRenderTarget] Support Multisampling clean bufferattributes code clean bufferattributes code * removed unused code * added build for tests * pupeeter screenshot * better example * resets the active FBO back to the multisampled FBO after blitting. * lint * use mask instead of COLOR_BUFFER_BIT * Update webgl2_multiple_rendertargets_multisampled.html * wip fix safari * removed use of temporary buffers and fix safari and ios example * fix lint * fix pupeeter example? * prevent unecessary fbo creation for non-mrt * fix * fix puppeeter rendering black screenshot * remove build * Update webgl2_multiple_rendertargets_multisampled.html Create `DepthTexture` without parameters. * remove unecessary framebuffer render and texture instructions * example: usage of stencil buffer instead of depth texture Co-authored-by: Michael Herzog <[email protected]>
- Loading branch information
1 parent
0ccddfd
commit 714a21b
Showing
5 changed files
with
463 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
337 changes: 337 additions & 0 deletions
337
examples/webgl2_multiple_rendertargets_multisampled.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,337 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<title>three.js webgl - Multiple Render Targets MultiSampled</title> | ||
<meta charset="utf-8"> | ||
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> | ||
<link type="text/css" rel="stylesheet" href="main.css"> | ||
|
||
<!-- Write to G-Buffer --> | ||
<script id="gbuffer-vert" type="x-shader/x-vertex"> | ||
in vec3 position; | ||
in vec3 normal; | ||
in vec2 uv; | ||
|
||
out vec3 vNormal; | ||
out vec2 vUv; | ||
|
||
uniform mat4 modelViewMatrix; | ||
uniform mat4 projectionMatrix; | ||
uniform mat3 normalMatrix; | ||
|
||
void main() { | ||
|
||
vUv = uv; | ||
|
||
// get smooth normals | ||
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 ); | ||
|
||
vec3 transformedNormal = normalMatrix * normal; | ||
vNormal = normalize( transformedNormal ); | ||
|
||
gl_Position = projectionMatrix * mvPosition; | ||
|
||
} | ||
</script> | ||
<script id="gbuffer-frag" type="x-shader/x-fragment"> | ||
precision highp float; | ||
precision highp int; | ||
|
||
layout(location = 0) out vec4 gColor; | ||
layout(location = 1) out vec4 gNormal; | ||
|
||
uniform sampler2D tDiffuse; | ||
uniform vec2 repeat; | ||
|
||
in vec3 vNormal; | ||
in vec2 vUv; | ||
|
||
void main() { | ||
|
||
// write color to G-Buffer | ||
gColor = texture( tDiffuse, vUv * repeat ); | ||
|
||
// write normals to G-Buffer | ||
gNormal = vec4( normalize( vNormal ), 0.0 ); | ||
|
||
} | ||
</script> | ||
|
||
<!-- Read G-Buffer and render to screen --> | ||
<script id="render-vert" type="x-shader/x-vertex"> | ||
in vec3 position; | ||
in vec2 uv; | ||
|
||
out vec2 vUv; | ||
|
||
uniform mat4 modelViewMatrix; | ||
uniform mat4 projectionMatrix; | ||
|
||
void main() { | ||
|
||
vUv = uv; | ||
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); | ||
|
||
} | ||
</script> | ||
<script id="render-frag" type="x-shader/x-fragment"> | ||
precision highp float; | ||
precision highp int; | ||
|
||
layout(location = 0) out vec4 pc_FragColor; | ||
|
||
in vec2 vUv; | ||
|
||
uniform sampler2D tDiffuse; | ||
uniform sampler2D tNormal; | ||
|
||
void main() { | ||
|
||
vec3 diffuse = texture( tDiffuse, vUv ).rgb; | ||
vec3 normal = texture( tNormal, vUv ).rgb; | ||
|
||
pc_FragColor = vec4(vec3(0.), 1.); | ||
pc_FragColor.rgb += mix( diffuse, normal, step( 0.5, vUv.x ) ); | ||
|
||
} | ||
</script> | ||
|
||
</head> | ||
<body> | ||
<div id="info"> | ||
<a href="http://threejs.org" target="_blank">threejs</a> - WebGL - Multiple Render Targets Multisampled<br/> | ||
Created by <a href="http://twitter.com/onirenaud" target="_blank">@onirenaud</a> with the help of <a href="http://twitter.com/Cody_J_Bennett" target="_blank">@Cody_J_Bennett</a>. | ||
</div> | ||
<div id="container"> | ||
</div> | ||
<!-- Import maps polyfill --> | ||
<!-- Remove this when import maps will be widely supported --> | ||
<script async src="https://unpkg.com/[email protected]/dist/es-module-shims.js"></script> | ||
|
||
<script type="importmap"> | ||
{ | ||
"imports": { | ||
"three": "../build/three.module.js" | ||
} | ||
} | ||
</script> | ||
|
||
<script type="module"> | ||
|
||
import * as THREE from 'three'; | ||
|
||
import WebGL from './jsm/capabilities/WebGL.js'; | ||
import { OrbitControls } from './jsm/controls/OrbitControls.js'; | ||
import { GUI } from './jsm/libs/lil-gui.module.min.js'; | ||
import Stats from './jsm/libs/stats.module.js'; | ||
|
||
let camera, scene, renderer, controls, container, group; | ||
let renderTarget; | ||
let postScene, postCamera; | ||
let stats; | ||
|
||
const clock = new THREE.Clock(); | ||
// Create a multi render target with Float buffers | ||
const gui = new GUI(); | ||
|
||
const effectController = { | ||
msaa: true | ||
}; | ||
|
||
init(); | ||
gui.add( effectController, 'msaa', true ).onChange( () => { | ||
|
||
renderTarget.samples = effectController.msaa ? 4 : 0; | ||
render(); | ||
|
||
} ); | ||
|
||
function init() { | ||
|
||
container = document.getElementById( 'container' ); | ||
|
||
if ( WebGL.isWebGL2Available() === false ) { | ||
|
||
document.body.appendChild( WebGL.getWebGL2ErrorMessage() ); | ||
return; | ||
|
||
} | ||
|
||
renderer = new THREE.WebGLRenderer(); | ||
renderer.setPixelRatio( 1 ); | ||
renderer.setSize( window.innerWidth, window.innerHeight ); | ||
container.appendChild( renderer.domElement ); | ||
|
||
stats = new Stats(); | ||
stats.domElement.style.position = 'absolute'; | ||
stats.domElement.style.top = '0px'; | ||
container.appendChild( stats.domElement ); | ||
|
||
|
||
renderTarget = new THREE.WebGLMultipleRenderTargets( | ||
window.innerWidth, | ||
window.innerHeight, | ||
2, | ||
{ | ||
samples: effectController.msaa ? 4 : 0, | ||
depthBuffer: true, | ||
stencilBuffer: true, | ||
} | ||
); | ||
|
||
for ( let i = 0, il = renderTarget.texture.length; i < il; i ++ ) { | ||
|
||
renderTarget.texture[ i ].minFilter = THREE.NearestFilter; | ||
renderTarget.texture[ i ].magFilter = THREE.NearestFilter; | ||
|
||
} | ||
// Name our G-Buffer attachments for debugging | ||
|
||
renderTarget.texture[ 0 ].name = 'diffuse'; | ||
renderTarget.texture[ 1 ].name = 'normal'; | ||
|
||
// Scene setup | ||
|
||
scene = new THREE.Scene(); | ||
scene.fog = new THREE.Fog( 0xa0a0a0, 500, 2000 ); | ||
|
||
const groundMat = new THREE.MeshBasicMaterial( { color: 0xffffff, transparent: true } ); | ||
groundMat.onBeforeCompile = function ( shader ) { | ||
|
||
shader.fragmentShader = ` | ||
layout(location = 1) out vec4 gOther; | ||
${shader.fragmentShader} | ||
`; | ||
shader.fragmentShader = shader.fragmentShader.replace( | ||
'#include <fog_fragment>', | ||
` | ||
#include <fog_fragment> | ||
gOther = gl_FragColor; | ||
` | ||
); | ||
|
||
}; | ||
|
||
const ground = new THREE.Mesh( new THREE.PlaneGeometry( 10000, 10000 ), groundMat ); | ||
ground.position.y = - 100; | ||
ground.rotation.x = - Math.PI / 2; | ||
scene.add( ground ); | ||
scene.background = new THREE.Color( 0xa0a0a0 ); | ||
|
||
container = document.getElementById( 'container' ); | ||
|
||
camera = new THREE.PerspectiveCamera( 45, container.offsetWidth / container.offsetHeight, 1, 2000 ); | ||
camera.position.z = 500; | ||
|
||
const diffuse = new THREE.TextureLoader().load( | ||
|
||
'textures/brick_diffuse.jpg' | ||
|
||
); | ||
|
||
diffuse.wrapS = diffuse.wrapT = THREE.RepeatWrapping; | ||
|
||
group = new THREE.Group(); | ||
|
||
const geometry = new THREE.TorusKnotGeometry( 10, 3.3, 12, 32 ); | ||
|
||
for ( let i = 0; i < 10; i ++ ) { | ||
|
||
const material = new THREE.RawShaderMaterial( { | ||
vertexShader: document.querySelector( '#gbuffer-vert' ).textContent.trim(), | ||
fragmentShader: document.querySelector( '#gbuffer-frag' ).textContent.trim(), | ||
uniforms: { | ||
tDiffuse: { value: diffuse }, | ||
repeat: { value: new THREE.Vector2( 5, 0.5 ) } | ||
}, | ||
wireframe: i % 2 === 0, | ||
glslVersion: THREE.GLSL3 | ||
} ); | ||
|
||
const mesh = new THREE.Mesh( geometry, material ); | ||
mesh.position.x = ( i / 10 ) * 600 - 300; | ||
mesh.position.y = ( i / 10 ) * 200 - 100; | ||
mesh.position.z = Math.random() * 600 - 300; | ||
mesh.rotation.x = Math.random(); | ||
mesh.rotation.z = Math.random(); | ||
mesh.scale.setScalar( Math.random() * 5 + 5 ); | ||
group.add( mesh ); | ||
|
||
|
||
} | ||
|
||
scene.add( group ); | ||
// PostProcessing setup | ||
|
||
postScene = new THREE.Scene(); | ||
postCamera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); | ||
|
||
postScene.add( new THREE.Mesh( | ||
new THREE.PlaneGeometry( 2, 2 ), | ||
new THREE.RawShaderMaterial( { | ||
vertexShader: document.querySelector( '#render-vert' ).textContent.trim(), | ||
fragmentShader: document.querySelector( '#render-frag' ).textContent.trim(), | ||
uniforms: { | ||
tDiffuse: { value: renderTarget.texture[ 0 ] }, | ||
tNormal: { value: renderTarget.texture[ 1 ] }, | ||
}, | ||
glslVersion: THREE.GLSL3 | ||
} ) | ||
) ); | ||
|
||
// Controls | ||
|
||
controls = new OrbitControls( camera, renderer.domElement ); | ||
controls.addEventListener( 'change', render ); | ||
controls.enableZoom = false; | ||
controls.screenSpacePanning = true; | ||
|
||
|
||
window.addEventListener( 'resize', onWindowResize ); | ||
|
||
animate(); | ||
|
||
} | ||
|
||
function onWindowResize() { | ||
|
||
camera.aspect = window.innerWidth / window.innerHeight; | ||
camera.updateProjectionMatrix(); | ||
|
||
renderer.setSize( window.innerWidth, window.innerHeight ); | ||
|
||
renderTarget.setSize( window.innerWidth, window.innerHeight ); | ||
|
||
render(); | ||
|
||
} | ||
|
||
function render() { | ||
|
||
// render scene into target | ||
renderer.setRenderTarget( renderTarget ); | ||
renderer.render( scene, camera ); | ||
|
||
// render post FX | ||
renderer.setRenderTarget( null ); | ||
renderer.render( postScene, postCamera ); | ||
|
||
} | ||
|
||
function animate() { | ||
|
||
requestAnimationFrame( animate ); | ||
|
||
controls.update(); | ||
|
||
group.rotation.y += clock.getDelta() * 0.1; | ||
|
||
stats.update(); | ||
render(); | ||
|
||
} | ||
|
||
</script> | ||
|
||
</body> | ||
</html> |
Oops, something went wrong.