1 | ( function () {
|
2 |
|
3 | |
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 | class SSAARenderPass extends THREE.Pass {
|
14 |
|
15 | constructor( scene, camera, clearColor, clearAlpha ) {
|
16 |
|
17 | super();
|
18 | this.scene = scene;
|
19 | this.camera = camera;
|
20 | this.sampleLevel = 4;
|
21 |
|
22 | this.unbiased = true;
|
23 |
|
24 | this.clearColor = clearColor !== undefined ? clearColor : 0x000000;
|
25 | this.clearAlpha = clearAlpha !== undefined ? clearAlpha : 0;
|
26 | this._oldClearColor = new THREE.Color();
|
27 | if ( THREE.CopyShader === undefined ) console.error( 'THREE.SSAARenderPass relies on THREE.CopyShader' );
|
28 | const copyShader = THREE.CopyShader;
|
29 | this.copyUniforms = THREE.UniformsUtils.clone( copyShader.uniforms );
|
30 | this.copyMaterial = new THREE.ShaderMaterial( {
|
31 | uniforms: this.copyUniforms,
|
32 | vertexShader: copyShader.vertexShader,
|
33 | fragmentShader: copyShader.fragmentShader,
|
34 | premultipliedAlpha: true,
|
35 | transparent: true,
|
36 | blending: THREE.AdditiveBlending,
|
37 | depthTest: false,
|
38 | depthWrite: false
|
39 | } );
|
40 | this.fsQuad = new THREE.FullScreenQuad( this.copyMaterial );
|
41 |
|
42 | }
|
43 |
|
44 | dispose() {
|
45 |
|
46 | if ( this.sampleRenderTarget ) {
|
47 |
|
48 | this.sampleRenderTarget.dispose();
|
49 | this.sampleRenderTarget = null;
|
50 |
|
51 | }
|
52 |
|
53 | }
|
54 |
|
55 | setSize( width, height ) {
|
56 |
|
57 | if ( this.sampleRenderTarget ) this.sampleRenderTarget.setSize( width, height );
|
58 |
|
59 | }
|
60 |
|
61 | render( renderer, writeBuffer, readBuffer ) {
|
62 |
|
63 | if ( ! this.sampleRenderTarget ) {
|
64 |
|
65 | this.sampleRenderTarget = new THREE.WebGLRenderTarget( readBuffer.width, readBuffer.height, {
|
66 | minFilter: THREE.LinearFilter,
|
67 | magFilter: THREE.LinearFilter,
|
68 | format: THREE.RGBAFormat
|
69 | } );
|
70 | this.sampleRenderTarget.texture.name = 'SSAARenderPass.sample';
|
71 |
|
72 | }
|
73 |
|
74 | const jitterOffsets = _JitterVectors[ Math.max( 0, Math.min( this.sampleLevel, 5 ) ) ];
|
75 |
|
76 | const autoClear = renderer.autoClear;
|
77 | renderer.autoClear = false;
|
78 | renderer.getClearColor( this._oldClearColor );
|
79 | const oldClearAlpha = renderer.getClearAlpha();
|
80 | const baseSampleWeight = 1.0 / jitterOffsets.length;
|
81 | const roundingRange = 1 / 32;
|
82 | this.copyUniforms[ 'tDiffuse' ].value = this.sampleRenderTarget.texture;
|
83 | const viewOffset = {
|
84 | fullWidth: readBuffer.width,
|
85 | fullHeight: readBuffer.height,
|
86 | offsetX: 0,
|
87 | offsetY: 0,
|
88 | width: readBuffer.width,
|
89 | height: readBuffer.height
|
90 | };
|
91 | const originalViewOffset = Object.assign( {}, this.camera.view );
|
92 | if ( originalViewOffset.enabled ) Object.assign( viewOffset, originalViewOffset );
|
93 |
|
94 | for ( let i = 0; i < jitterOffsets.length; i ++ ) {
|
95 |
|
96 | const jitterOffset = jitterOffsets[ i ];
|
97 |
|
98 | if ( this.camera.setViewOffset ) {
|
99 |
|
100 | this.camera.setViewOffset( viewOffset.fullWidth, viewOffset.fullHeight, viewOffset.offsetX + jitterOffset[ 0 ] * 0.0625, viewOffset.offsetY + jitterOffset[ 1 ] * 0.0625,
|
101 | viewOffset.width, viewOffset.height );
|
102 |
|
103 | }
|
104 |
|
105 | let sampleWeight = baseSampleWeight;
|
106 |
|
107 | if ( this.unbiased ) {
|
108 |
|
109 |
|
110 |
|
111 |
|
112 | const uniformCenteredDistribution = - 0.5 + ( i + 0.5 ) / jitterOffsets.length;
|
113 | sampleWeight += roundingRange * uniformCenteredDistribution;
|
114 |
|
115 | }
|
116 |
|
117 | this.copyUniforms[ 'opacity' ].value = sampleWeight;
|
118 | renderer.setClearColor( this.clearColor, this.clearAlpha );
|
119 | renderer.setRenderTarget( this.sampleRenderTarget );
|
120 | renderer.clear();
|
121 | renderer.render( this.scene, this.camera );
|
122 | renderer.setRenderTarget( this.renderToScreen ? null : writeBuffer );
|
123 |
|
124 | if ( i === 0 ) {
|
125 |
|
126 | renderer.setClearColor( 0x000000, 0.0 );
|
127 | renderer.clear();
|
128 |
|
129 | }
|
130 |
|
131 | this.fsQuad.render( renderer );
|
132 |
|
133 | }
|
134 |
|
135 | if ( this.camera.setViewOffset && originalViewOffset.enabled ) {
|
136 |
|
137 | this.camera.setViewOffset( originalViewOffset.fullWidth, originalViewOffset.fullHeight, originalViewOffset.offsetX, originalViewOffset.offsetY, originalViewOffset.width, originalViewOffset.height );
|
138 |
|
139 | } else if ( this.camera.clearViewOffset ) {
|
140 |
|
141 | this.camera.clearViewOffset();
|
142 |
|
143 | }
|
144 |
|
145 | renderer.autoClear = autoClear;
|
146 | renderer.setClearColor( this._oldClearColor, oldClearAlpha );
|
147 |
|
148 | }
|
149 |
|
150 | }
|
151 |
|
152 |
|
153 |
|
154 |
|
155 |
|
156 |
|
157 | const _JitterVectors = [[[ 0, 0 ]], [[ 4, 4 ], [ - 4, - 4 ]], [[ - 2, - 6 ], [ 6, - 2 ], [ - 6, 2 ], [ 2, 6 ]], [[ 1, - 3 ], [ - 1, 3 ], [ 5, 1 ], [ - 3, - 5 ], [ - 5, 5 ], [ - 7, - 1 ], [ 3, 7 ], [ 7, - 7 ]], [[ 1, 1 ], [ - 1, - 3 ], [ - 3, 2 ], [ 4, - 1 ], [ - 5, - 2 ], [ 2, 5 ], [ 5, 3 ], [ 3, - 5 ], [ - 2, 6 ], [ 0, - 7 ], [ - 4, - 6 ], [ - 6, 4 ], [ - 8, 0 ], [ 7, - 4 ], [ 6, 7 ], [ - 7, - 8 ]], [[ - 4, - 7 ], [ - 7, - 5 ], [ - 3, - 5 ], [ - 5, - 4 ], [ - 1, - 4 ], [ - 2, - 2 ], [ - 6, - 1 ], [ - 4, 0 ], [ - 7, 1 ], [ - 1, 2 ], [ - 6, 3 ], [ - 3, 3 ], [ - 7, 6 ], [ - 3, 6 ], [ - 5, 7 ], [ - 1, 7 ], [ 5, - 7 ], [ 1, - 6 ], [ 6, - 5 ], [ 4, - 4 ], [ 2, - 3 ], [ 7, - 2 ], [ 1, - 1 ], [ 4, - 1 ], [ 2, 1 ], [ 6, 2 ], [ 0, 4 ], [ 4, 4 ], [ 2, 5 ], [ 7, 5 ], [ 5, 6 ], [ 3, 7 ]]];
|
158 |
|
159 | THREE.SSAARenderPass = SSAARenderPass;
|
160 |
|
161 | } )();
|