UNPKG

playcanvas

Version:

PlayCanvas WebGL game engine

72 lines (69 loc) 3.73 kB
import { SHADERLANGUAGE_GLSL, SHADERLANGUAGE_WGSL, SEMANTIC_POSITION } from '../../platform/graphics/constants.js'; import { RenderPassShaderQuad } from '../../scene/graphics/render-pass-shader-quad.js'; import { ShaderUtils } from '../../scene/shader-lib/shader-utils.js'; import glslDownsamplePS from '../../scene/shader-lib/glsl/chunks/render-pass/frag/downsample.js'; import wgslDownsamplePS from '../../scene/shader-lib/wgsl/chunks/render-pass/frag/downsample.js'; import { ShaderChunks } from '../../scene/shader-lib/shader-chunks.js'; /** * @import { GraphicsDevice } from '../../platform/graphics/graphics-device.js' * @import { Texture } from '../../platform/graphics/texture.js' */ /** * Render pass implementation of a down-sample filter. * * @category Graphics * @ignore */ class RenderPassDownsample extends RenderPassShaderQuad { /** * @param {GraphicsDevice} device - The graphics device. * @param {Texture} sourceTexture - The source texture to downsample. * @param {object} [options] - The options for the render pass. * @param {boolean} [options.boxFilter] - Whether to use a box filter for downsampling. * @param {Texture|null} [options.premultiplyTexture] - The texture to premultiply the source texture * with. Only supported when boxFilter is true. * @param {string} [options.premultiplySrcChannel] - The source channel to premultiply. * @param {boolean} [options.removeInvalid] - Whether to remove invalid pixels from the output. */ constructor(device, sourceTexture, options = {}){ super(device); this.sourceTexture = sourceTexture; this.premultiplyTexture = options.premultiplyTexture; // register shader chunks ShaderChunks.get(device, SHADERLANGUAGE_GLSL).set('downsamplePS', glslDownsamplePS); ShaderChunks.get(device, SHADERLANGUAGE_WGSL).set('downsamplePS', wgslDownsamplePS); const boxFilter = options.boxFilter ?? false; const key = `${boxFilter ? 'Box' : ''}-${options.premultiplyTexture ? 'Premultiply' : ''}-${options.premultiplySrcChannel ?? ''}-${options.removeInvalid ? 'RemoveInvalid' : ''}`; const defines = new Map(); if (boxFilter) defines.set('BOXFILTER', ''); if (options.premultiplyTexture) defines.set('PREMULTIPLY', ''); if (options.removeInvalid) defines.set('REMOVE_INVALID', ''); defines.set('{PREMULTIPLY_SRC_CHANNEL}', options.premultiplySrcChannel ?? 'x'); this.shader = ShaderUtils.createShader(device, { uniqueName: `DownSampleShader:${key}`, attributes: { aPosition: SEMANTIC_POSITION }, vertexChunk: 'quadVS', fragmentChunk: 'downsamplePS', fragmentDefines: defines }); this.sourceTextureId = device.scope.resolve('sourceTexture'); this.premultiplyTextureId = device.scope.resolve('premultiplyTexture'); this.sourceInvResolutionId = device.scope.resolve('sourceInvResolution'); this.sourceInvResolutionValue = new Float32Array(2); } setSourceTexture(value) { this._sourceTexture = value; // change resize source this.options.resizeSource = value; } execute() { this.sourceTextureId.setValue(this.sourceTexture); if (this.premultiplyTexture) { this.premultiplyTextureId.setValue(this.premultiplyTexture); } this.sourceInvResolutionValue[0] = 1.0 / this.sourceTexture.width; this.sourceInvResolutionValue[1] = 1.0 / this.sourceTexture.height; this.sourceInvResolutionId.setValue(this.sourceInvResolutionValue); super.execute(); } } export { RenderPassDownsample };