/* * TSDGLBloomEffect.js * Keynote HTML Player * * Created by Tungwei Cheng * Copyright (c) 2018 Apple Inc. All rights reserved. */ var kShaderUniformBloomAmount = "BloomAmount"; var kShaderUniformBlurTexture = "BlurTexture"; var TSDGLBloomEffect = Class.create({ initialize: function(gl) { this.gl = gl; }, initWithEffectSize: function(effectSize, blurScale) { this._effectSize = effectSize; // blurScale must be >= 1.0 this._blurBufferSize = CGSizeMake(Math.max(16, Math.ceil(effectSize.width / blurScale)), Math.max(16, Math.ceil(effectSize.height / blurScale)));; this.p_setupShaders(); this.p_setupBuffers(); }, p_setupShaders: function() { var gl = this.gl; var _blurBufferSize = this._blurBufferSize; var blurTextureSize = WebGraphics.makePoint(1.0 / _blurBufferSize.width, 1.0 / _blurBufferSize.height); var blurTransform = WebGraphics.makeOrthoMatrix4(0, _blurBufferSize.width, 0, _blurBufferSize.height, -1, +1); // shader 1: horizontal blur shader var _blurHorizontalShader = this._blurHorizontalShader = new TSDGLShader(gl); _blurHorizontalShader.initWithDefaultHorizontalBlurShader(); _blurHorizontalShader.setMat4WithTransform3D(blurTransform, kTSDGLShaderUniformMVPMatrix); _blurHorizontalShader.setPoint2D(blurTextureSize, kTSDGLShaderUniformTextureSize); // shader 2: vertical blur shader var _blurVerticalShader = this._blurVerticalShader = new TSDGLShader(gl); _blurVerticalShader.initWithDefaultVerticalBlurShader(); _blurVerticalShader.setMat4WithTransform3D(blurTransform, kTSDGLShaderUniformMVPMatrix); _blurVerticalShader.setPoint2D(blurTextureSize, kTSDGLShaderUniformTextureSize); // shader 3: transfer shader var _fboTransferShader = this._fboTransferShader = new TSDGLShader(gl); _fboTransferShader.initWithDefaultTextureShader(); _fboTransferShader.setMat4WithTransform3D(blurTransform, kTSDGLShaderUniformMVPMatrix); // shader 4: bloom effect shader var _bloomShader = this._bloomShader = new TSDGLShader(gl); _bloomShader.initWithShaderFileNames("bloom", "bloom"); _bloomShader.setGLint(0, kTSDGLShaderUniformTexture); _bloomShader.setGLint(1, kShaderUniformBlurTexture); }, p_setupBuffers: function() { var gl = this.gl; var _effectSize = this._effectSize; var _blurBufferSize = this._blurBufferSize; var meshSize = CGSizeMake(2, 2); var effectRect = CGRectMake(0, 0, _effectSize.width, _effectSize.height); var blurBufferRect = CGRectMake(0, 0, _blurBufferSize.width, _blurBufferSize.height); // buffer 1: bloom effect var _dataBuffer = this._dataBuffer = new TSDGLDataBuffer(gl); _dataBuffer.initWithVertexRect(effectRect, TSDRectUnit, meshSize, false, false); // buffer 2: blur buffer var _blurDataBuffer = this._blurDataBuffer = new TSDGLDataBuffer(gl); _blurDataBuffer.initWithVertexRect(blurBufferRect, CGRectZero, meshSize, true, false); // buffer 3: transfer buffer var _blurTransferDataBuffer = this._blurTransferDataBuffer = new TSDGLDataBuffer(gl); _blurTransferDataBuffer.initWithVertexRect(blurBufferRect, TSDRectUnit, meshSize, false, false); // initialize color framebuffer with one texture for storing incoming rendering this._colorFramebuffer = new TSDGLFrameBuffer(gl, _effectSize, 1); // initialize blur framebuffer with two textures for blurring operations this._blurFramebuffer = new TSDGLFrameBuffer(gl, _blurBufferSize, 2); }, bindFramebuffer: function() { this._colorFramebuffer.bindFramebuffer(); }, unbindFramebufferAndBindGLFramebuffer: function(previousFramebuffer) { this._colorFramebuffer.unbindFramebufferAndBindGLFramebuffer(previousFramebuffer); }, p_blurColorBufferWithPreviousFramebuffer: function(previousFramebuffer) { var gl = this.gl; var _blurFramebuffer = this._blurFramebuffer; var _blurBufferSize = this._blurBufferSize; _blurFramebuffer.bindFramebuffer(); gl.clear(gl.COLOR_BUFFER_BIT); gl.viewport(0, 0, _blurBufferSize.width, _blurBufferSize.height); // Step 1: Transfer color to blur buffer gl.bindTexture(gl.TEXTURE_2D, this._colorFramebuffer.currentGLTexture()); this._blurTransferDataBuffer.drawWithShader(this._fboTransferShader, true); // Step 2: Blur horizontally var blurTexture = _blurFramebuffer.currentGLTexture(); _blurFramebuffer.setCurrentTextureToNext(); gl.clear(gl.COLOR_BUFFER_BIT); gl.bindTexture(gl.TEXTURE_2D, blurTexture); this._blurDataBuffer.drawWithShader(this._blurHorizontalShader, true); // Step 3: Blur Vertically gl.bindTexture(gl.TEXTURE_2D, null); blurTexture = _blurFramebuffer.currentGLTexture(); _blurFramebuffer.setCurrentTextureToNext(); gl.clear(gl.COLOR_BUFFER_BIT); gl.bindTexture(gl.TEXTURE_2D, blurTexture); this._blurDataBuffer.drawWithShader(this._blurVerticalShader, true); _blurFramebuffer.unbindFramebufferAndBindGLFramebuffer(previousFramebuffer); gl.bindTexture(gl.TEXTURE_2D, null); }, drawBloomEffectWithMVPMatrix: function(MVPMatrix, bloomAmount, currentGLFramebuffer) { var gl = this.gl; var _effectSize = this._effectSize; var oldViewportRect = gl.getParameter(gl.VIEWPORT); // Blur color buffer into blur FBO this.p_blurColorBufferWithPreviousFramebuffer(currentGLFramebuffer); // change viewport back to effect size gl.viewport(0, 0, _effectSize.width, _effectSize.height); // Draw Bloom gl.activeTexture(gl.TEXTURE1); gl.bindTexture(gl.TEXTURE_2D, this._blurFramebuffer.currentGLTexture()); gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, this._colorFramebuffer.currentGLTexture()); var _bloomShader = this._bloomShader; _bloomShader.setMat4WithTransform3D(MVPMatrix, kTSDGLShaderUniformMVPMatrix); _bloomShader.setGLFloat(bloomAmount, kShaderUniformBloomAmount); this._dataBuffer.drawWithShader(_bloomShader, true); gl.activeTexture(gl.TEXTURE1); gl.bindTexture(gl.TEXTURE_2D, null); gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, null); // change viewport back to original size gl.viewport(oldViewportRect[0], oldViewportRect[1], oldViewportRect[2], oldViewportRect[3]); } });