Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MRT Support #16390

Merged
merged 28 commits into from May 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
8f86b94
MRT Support
takahirox May 5, 2019
819e592
Add MRT example
takahirox May 5, 2019
4f33c7d
Rename AttachnemtsNum to NumAttachments
takahirox May 6, 2019
eb738e9
Reflect the review comments to webgl2_mrt.html
takahirox May 6, 2019
5e05c19
Define texture parameter via WebGLMultiRenderTarget constructor in MR…
takahirox Jul 24, 2019
d181c43
Minor clean up
takahirox Jul 24, 2019
8e9d833
Fix setupFrameBufferTextre(). Use texture.format/type instead of rend…
takahirox Jul 24, 2019
ed0bc50
Use module in MRT example
takahirox Jul 24, 2019
3b35050
Merge remote-tracking branch 'upstream/dev' into MRTSupport
takahirox Jan 23, 2020
326519a
Merge remote-tracking branch 'upstream/dev' into MRTSupport
takahirox Jun 10, 2020
a51b488
Replace var with let or const
takahirox Jun 10, 2020
884061d
Merge remote-tracking branch 'upstream/dev' into MRTSupport
takahirox Aug 4, 2020
a41a97a
Replace ShaderMaterial with RawShaderMaterial for MRT example
takahirox Aug 4, 2020
6baa4de
Fix formatting
takahirox Aug 14, 2020
b4600bf
Fix for lint
takahirox Aug 14, 2020
ac9e83c
Add MRT example screenshot
takahirox Aug 23, 2020
ce10c80
Merge remote-tracking branch 'upstream/dev' into MRTSupport
takahirox Nov 13, 2020
8496847
Merge remote-tracking branch 'upstream/dev' into MRTSupport
takahirox Mar 26, 2021
8f09add
Merge branch 'dev' into MRTSupport
takahirox Apr 4, 2021
3cb1164
Reflect the review comments for WebGLMultiRenderTarget
takahirox Apr 7, 2021
76dc98b
Merge branch 'MRTSupport' of https://github.com/takahirox/three.js in…
takahirox Apr 7, 2021
5e3456a
Rename .textures to .texture in WebGLMultiRenderTarget
takahirox Apr 9, 2021
c507d9e
WebGLMultiRenderTarget: Remove setCount()
takahirox Apr 21, 2021
c82e721
WebGLMultiRenderTarget: Method chain
takahirox Apr 21, 2021
424dc59
WebGLMultiRenderTarget: More proper setTexture() and copy()
takahirox Apr 21, 2021
517c20e
WebGLCapabilities: Use extensions.has() instead of .get()
takahirox Apr 21, 2021
bfe4017
WebGLMultiRenderTarget: Remove setTexture()
takahirox Apr 22, 2021
28e8041
Rename WebGLMultiRenderTarget to WebGLMultipleRenderTargets
takahirox Apr 22, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/files.json
Expand Up @@ -309,6 +309,7 @@
"webgl2_materials_texture2darray",
"webgl2_materials_texture3d",
"webgl2_materials_texture3d_partialupdate",
"webgl2_mrt",
"webgl2_multisampled_renderbuffers",
"webgl2_rendertarget_texture2darray",
"webgl2_volume_cloud",
Expand Down
Binary file added examples/screenshots/webgl2_mrt.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
277 changes: 277 additions & 0 deletions examples/webgl2_mrt.html
@@ -0,0 +1,277 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - Multiple Render Targets</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #000;
color: #fff;
margin: 0px;
overflow: hidden;
}
#info {
color: #fff;
position: absolute;
top: 10px;
width: 100%;
text-align: center;
display:block;
}
#info a, .button { color: #f00; font-weight: bold; text-decoration: underline; cursor: pointer }
</style>

<!-- 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.rgb = mix( diffuse, normal, step( 0.5, vUv.x ) );
pc_FragColor.a = 1.0;

}
</script>

</head>
<body>
<div id="info">
<a href="http://threejs.org" target="_blank">threejs</a> - WebGL - Multiple Render Targets<br/>
Renders geometry into a G-Buffer.<br/>
Visualized here is the color and normal data from the G-Buffer.<br/>
Created by <a href="http://twitter.com/mattdesl" target="_blank">@mattdesl</a>.
</div>

<script type="module">

import * as THREE from '../build/three.module.js';

import { WEBGL } from './jsm/WebGL.js';
import { OrbitControls } from './jsm/controls/OrbitControls.js';

let container;
let camera, scene, renderer, controls;
let renderTarget;
let postScene, postCamera;

init();

function init() {

if ( WEBGL.isWebGL2Available() === false ) {

document.body.appendChild( WEBGL.getWebGL2ErrorMessage() );
return;

}

container = document.createElement( 'div' );
takahirox marked this conversation as resolved.
Show resolved Hide resolved
document.body.appendChild( container );

const canvas = document.createElement( 'canvas' );
const context = canvas.getContext( 'webgl2' );

renderer = new THREE.WebGLRenderer( {
canvas: canvas,
context: context
} );

renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );

// Create a multi render target with Float buffers

renderTarget = new THREE.WebGLMultipleRenderTargets(
window.innerWidth * window.devicePixelRatio,
window.innerHeight * window.devicePixelRatio,
2
);

for ( let i = 0, il = renderTarget.texture.length; i < il; i ++ ) {

renderTarget.texture[ i ].minFilter = THREE.NearestFilter;
renderTarget.texture[ i ].magFilter = THREE.NearestFilter;
renderTarget.texture[ i ].type = THREE.FloatType;

}

// Name our G-Buffer attachments for debugging

renderTarget.texture[ 0 ].name = 'diffuse';
renderTarget.texture[ 1 ].name = 'normal';

// Scene setup

scene = new THREE.Scene();

camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10 );
camera.position.z = 4;

const diffuse = new THREE.TextureLoader().load(

'textures/brick_diffuse.jpg',

function () {

// ready to render
render();

}

);

diffuse.wrapS = diffuse.wrapT = THREE.RepeatWrapping;

scene.add( new THREE.Mesh(
new THREE.TorusKnotGeometry( 1, 0.3, 128, 64 ),
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 ) }
},
glslVersion: THREE.GLSL3
} )
) );

// 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, false );

}

function onWindowResize() {

camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();

renderer.setSize( window.innerWidth, window.innerHeight );

const dpr = renderer.getPixelRatio();
renderTarget.setSize( window.innerWidth * dpr, window.innerHeight * dpr );

render();

}

function render() {

// render scene into target
renderer.setRenderTarget( renderTarget );
renderer.render( scene, camera );

// render post FX
renderer.setRenderTarget( null );
renderer.render( postScene, postCamera );

}

</script>

</body>
</html>
1 change: 1 addition & 0 deletions src/Three.js
@@ -1,5 +1,6 @@
import { REVISION } from './constants.js';

export { WebGLMultipleRenderTargets } from './renderers/WebGLMultipleRenderTargets.js';
export { WebGLMultisampleRenderTarget } from './renderers/WebGLMultisampleRenderTarget.js';
export { WebGLCubeRenderTarget } from './renderers/WebGLCubeRenderTarget.js';
export { WebGLRenderTarget } from './renderers/WebGLRenderTarget.js';
Expand Down
79 changes: 79 additions & 0 deletions src/renderers/WebGLMultipleRenderTargets.js
@@ -0,0 +1,79 @@
import { WebGLRenderTarget } from './WebGLRenderTarget.js';

class WebGLMultipleRenderTargets extends WebGLRenderTarget {

constructor( width, height, count ) {

super( width, height );

const texture = this.texture;

this.texture = [];

for ( let i = 0; i < count; i ++ ) {

this.texture[ i ] = texture.clone();

}

}

setSize( width, height, depth = 1 ) {

if ( this.width !== width || this.height !== height || this.depth !== depth ) {

this.width = width;
this.height = height;
this.depth = depth;

for ( let i = 0, il = this.texture.length; i < il; i ++ ) {

this.texture[ i ].image.width = width;
this.texture[ i ].image.height = height;
this.texture[ i ].image.depth = depth;

}

this.dispose();

}

this.viewport.set( 0, 0, width, height );
this.scissor.set( 0, 0, width, height );

return this;

}

copy( source ) {

this.dispose();

this.width = source.width;
this.height = source.height;
this.depth = source.depth;

this.viewport.set( 0, 0, this.width, this.height );
this.scissor.set( 0, 0, this.width, this.height );

this.depthBuffer = source.depthBuffer;
this.stencilBuffer = source.stencilBuffer;
this.depthTexture = source.depthTexture;

this.texture.length = 0;

for ( let i = 0, il = source.texture.length; i < il; i ++ ) {

this.texture[ i ] = source.texture[ i ].clone();

}

return this;

}

}

WebGLMultipleRenderTargets.prototype.isWebGLMultipleRenderTargets = true;

export { WebGLMultipleRenderTargets };