| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 |
- /** (超级采样抗锯齿)
- *这是一种“暴力”但效果最好的方法。(性能最差)
- 它将场景渲染到一个比屏幕大得多的分辨率上,然后再降采样到屏幕大小,从而获得极其平滑的边缘
- * Supersample Anti-Aliasing Render Pass
- *
- * @author bhouston / http://clara.io/
- *
- * This manual approach to SSAA re-renders the scene ones for each sample with camera jitter and accumulates the results.
- *
- * References: https://en.wikipedia.org/wiki/Supersampling
- *
- */
-
- import * as THREE from "../../../../libs/three.js/build/three.module.js";
- import {Pass, ShaderPass} from './ShaderPass'
- import CopyShader from './CopyShader'
- //较为原始的一种抗锯齿 (超级采样抗锯齿)
- let SSAARenderPass = function ( clearColor, clearAlpha ) {
- Pass.call( this );
- //this.scene //= scene;
- //this.camera = camera;
- this.sampleLevel = 4; // specified as n, where the number of samples is 2^n, so sampleLevel = 4, is 2^4 samples, 16.
- this.unbiased = true;
- // as we need to clear the buffer in this pass, clearColor must be set to something, defaults to black.
- this.clearColor = ( clearColor !== undefined ) ? clearColor : 0x000000;
- this.clearAlpha = ( clearAlpha !== undefined ) ? clearAlpha : 0;
-
- this.renderUniforms = {
- bgTex : {value:null},
- outlineTex : {value:null},
- opacity : {value:1},
- }
-
- this.renderMat = new THREE.ShaderMaterial({
- uniforms: this.renderUniforms,
- vertexShader: CopyShader.vertexShader,
- /* fragmentShader: CopyShader.fragmentShader, */
- fragmentShader: `
- uniform sampler2D bgTex;
- uniform sampler2D outlineTex;
- uniform float opacity;
- varying vec2 vUv;
- void main() {
- vec4 color1 = texture2D( bgTex, vUv );
- vec4 color2 = texture2D( outlineTex, vUv );
- gl_FragColor = opacity * mix(color1, color2, color2.a) ;
-
-
- }
- `,
- premultipliedAlpha: true,
- blending: THREE.AdditiveBlending,
- depthTest: false,
- depthWrite: false,
- transparent: true
- })
-
-
- this.renderMat2 = new THREE.ShaderMaterial({
- uniforms: THREE.UniformsUtils.clone(CopyShader.uniforms) ,
- vertexShader: CopyShader.vertexShader,
- fragmentShader:`uniform float opacity;
- uniform sampler2D tDiffuse;
- varying vec2 vUv;
- void main() {
-
- vec4 texel = texture2D( tDiffuse, vUv );
-
- if(texel.r == 0.0 && texel.g == 0.0 && texel.b == 0.0){
- discard;
- }else{
- gl_FragColor = opacity * texel;
- }
- }
- ` ,
-
-
- depthTest: false,
- depthWrite: false,
- transparent: true
- })
-
-
-
-
-
-
- ////////////////////
- /* this.renderMat.blendSrc = THREE.OneFactor //即将写入缓冲区的颜色。
- this.renderMat.blendDst = THREE.OneFactor //缓冲区已经存在的颜色
- this.renderMat.blendEquation = THREE.AddEquation;
- this.renderMat.blendEquationAlpha = THREE.AddEquation;
- this.renderMat.blendDstAlpha = THREE.SrcAlphaFactor
- this.renderMat.blendSrcAlpha = THREE.SrcAlphaFactor */
- this.camera2 = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
- this.scene2 = new THREE.Scene();
- this.quad2 = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), this.renderMat/* this.copyMaterial */ );
- this.quad2.frustumCulled = false; // Avoid getting clipped
- this.scene2.add( this.quad2 );
- this.copyPass = new ShaderPass( CopyShader );
- this.copyPass.renderToScreen = true
- };
- SSAARenderPass.prototype = Object.assign( Object.create( Pass.prototype ), {
- constructor: SSAARenderPass,
- dispose: function () {
- if ( this.sampleRenderTarget ) {
- this.sampleRenderTarget.dispose();
- this.sampleRenderTarget = null;
- }
- },
- setSize: function ( width, height ) {
- if ( this.sampleRenderTarget ) this.sampleRenderTarget.setSize( width, height );
- this.childPass && this.childPass.setSize(width, height)
-
- },
- addPass: function (pass){
- this.childPass = pass;
- },
- render: function (scene, camera, viewports, renderer, writeBuffer, readBuffer, maskActive, renderFun ) {
- if(this.useCopy ){
- scene = this.copyPass.scene; camera = this.copyPass.camera;
- }
- if ( ! this.sampleRenderTarget ) {
- this.sampleRenderTarget = new THREE.WebGLRenderTarget( readBuffer.width, readBuffer.height, { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat } );
- this.sampleRenderTarget.texture.name = "SSAARenderPass.sample";
- }
- var jitterOffsets = SSAARenderPass.JitterVectors[ Math.max( 0, Math.min( this.sampleLevel, 5 ) ) ];
- var autoClear = renderer.autoClear;
- renderer.autoClear = false;
- var oldClearColor = renderer.getClearColor(new THREE.Color).getHex();
- var oldClearAlpha = renderer.getClearAlpha();
- renderer.setClearColor( this.clearColor, this.clearAlpha );
-
- var baseSampleWeight = 1.0 / jitterOffsets.length;
- var roundingRange = 1 / 32;
- //this.copyUniforms[ "tDiffuse" ].value = this.sampleRenderTarget.texture;
-
- let oldTarget = renderer.getRenderTarget();
-
- if(oldTarget){
- if(oldTarget.scissorTest){
- var width = oldTarget.scissor.w, height = oldTarget.scissor.z
- }else{
- var width = oldTarget.width, height = oldTarget.height;
- }
- }else{
- var width = readBuffer.width, height = readBuffer.height;
- }
-
- // render the scene multiple times, each slightly jitter offset from the last and accumulate the results.
-
- let opa = 0
- for ( var i = 0; i < jitterOffsets.length; i ++ ) {
- var jitterOffset = jitterOffsets[ i ];
- if ( camera.setViewOffset ) {
- camera.setViewOffset( width, height,
- jitterOffset[ 0 ] * 0.0625 , jitterOffset[ 1 ] * 0.0625 , // 0.0625 = 1 / 16
- width, height );
- }
- var sampleWeight = baseSampleWeight;
- if ( this.unbiased ) {//更柔和
- var uniformCenteredDistribution = ( - 0.5 + ( i + 0.5 ) / jitterOffsets.length );
- sampleWeight += roundingRange * uniformCenteredDistribution;
- }
-
- renderer.setRenderTarget(this.sampleRenderTarget)
- renderer.clear()
- if(this.useCopy){
- this.copyPass.render(scene,camera, null,renderer, writeBuffer, readBuffer )
- }else{
- if(renderFun){
- renderFun({target : this.sampleRenderTarget})
- }else{
- renderer.render( scene, camera );
- }
- }
- renderer.setRenderTarget(oldTarget)
-
- //---------------------
- //获取outline tex
- let hasOutline = this.childPass && this.childPass.render(scene, camera, renderer, writeBuffer, readBuffer, null, renderFun )
-
-
- //合成到该材质
- this.renderUniforms[ "bgTex" ].value = this.sampleRenderTarget.texture;
- this.renderUniforms[ "outlineTex" ].value = hasOutline ? readBuffer.texture : null
- this.renderUniforms[ "opacity" ].value = sampleWeight;
-
-
-
- /* console.log('sampleWeight', sampleWeight)
- opa += sampleWeight */
-
- if(!this.renderToScreen){
- renderer.setRenderTarget(writeBuffer)
- }
- if(i === 0 ){
- renderer.setClearColor( 0x000000, 0 ); //叠加前颜色必须0
- renderer.clear()
- }
- renderer.render( this.scene2, this.camera2); // , this.renderToScreen ? null : writeBuffer, ( i === 0 )
- if(!this.renderToScreen){
- renderer.setRenderTarget(oldTarget)
- }
- //if(i==2)break;
- }
- //console.log('sum:',opa)
- if ( camera.clearViewOffset )camera.clearViewOffset();
- //renderer.setRenderTarget(readBuffer)
- //renderer.setClearColor( 0x000000, 0 );
- //renderer.clear()
- /* this.quad2.material = this.renderMat2
- this.renderMat2.uniforms.tDiffuse.value = writeBuffer.texture;
- renderer.render( this.scene2, this.camera2);
- this.quad2.material = this.renderMat */
- //renderer.setRenderTarget(oldTarget)
-
-
-
- renderer.autoClear = autoClear;
- renderer.setClearColor( oldClearColor, oldClearAlpha );
-
-
-
-
- /* 试了好几次,测量线的透明度还是还原不了。 clearAlpha十分影响结果。
- 因为绘制测量线需要背景透明。 或许可以先全部绘制完后,再 copyshader中 抗锯齿?
-
-
- 另外会有黑边。
- */
- }
- } );
- // These jitter vectors are specified in integers because it is easier.
- // I am assuming a [-8,8) integer grid, but it needs to be mapped onto [-0.5,0.5)
- // before being used, thus these integers need to be scaled by 1/16.
- //
- // Sample patterns reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476218%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
- SSAARenderPass.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 ]
- ]
- ];
- //锯齿效果见 https://threejs.org/examples/?q=ssaa#webgl_postprocessing_ssaa
- export default SSAARenderPass
|