'use strict'
// ******************************** 离屏渲染 - 开始 ********************************
const OffscreenStart = new class {
/** 开始渲染离屏画面 */
render() {
const gl = GL
// 启用离屏纹理并擦除画布
gl.enableOffscreen(true)
gl.clearColor(0, 0, 0, 0)
gl.clear(gl.COLOR_BUFFER_BIT)
}
}
// ******************************** 离屏渲染 - 结束 ********************************
const OffscreenEnd = new class {
/** 结束渲染离屏画面 */
render() {
const gl = GL
// 禁用离屏纹理并复制纹理像素到画布中
gl.enableOffscreen(false)
gl.blend = 'copy'
// 如果用blitFramebuffer在抗锯齿模式下会报错
const program = gl.imageProgram.use()
const vertices = gl.arrays[0].float32
vertices[0] = -1
vertices[1] = 1
vertices[2] = 0
vertices[3] = 0
vertices[4] = -1
vertices[5] = -1
vertices[6] = 0
vertices[7] = 1
vertices[8] = 1
vertices[9] = -1
vertices[10] = 1
vertices[11] = 1
vertices[12] = 1
vertices[13] = 1
vertices[14] = 1
vertices[15] = 0
gl.bindVertexArray(program.vao.a110)
gl.vertexAttrib1f(program.a_Opacity, 1)
gl.uniformMatrix3fv(program.u_Matrix, false, gl.matrix.reset())
gl.uniform1i(program.u_LightMode, 0)
gl.uniform1i(program.u_ColorMode, 0)
gl.uniform4f(program.u_Tint, 0, 0, 0, 0)
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STREAM_DRAW, 0, 16)
gl.bindTexture(gl.TEXTURE_2D, gl.offscreen.current.base.glTexture)
gl.drawArrays(gl.TRIANGLE_FAN, 0, 4)
}
}
// ******************************** 染色器对象 ********************************
const Tinter = new class {
// 色调数组
tint = [0, 0, 0, 0]
/** 更新场景色调 */
update() {
const {tint} = this
if (tint[0] === 0 &&
tint[1] === 0 &&
tint[2] === 0 &&
tint[3] === 0) {
Scene.filters.delete('tint')
} else {
Scene.filters.set('tint', this)
}
}
/** 重置色调 */
reset() {
if (this.transition) {
this.transition.remove()
delete this.transition
}
this.tint[0] = 0
this.tint[1] = 0
this.tint[2] = 0
this.tint[3] = 0
Scene.filters.delete('tint')
}
/** 渲染场景色调 */
render() {
const gl = GL
// 切换离屏纹理
gl.switchOffscreen()
gl.blend = 'copy'
// 复制染色后的画面到当前的离屏纹理
gl.drawImage(gl.offscreen.last, 0, 0, gl.width, gl.height, this.tint)
}
/**
* 设置场景色调: 红[-255, 255] 绿[-255, 255] 蓝[-255, 255] 灰[0, 255]
* @param {Array<number>} tint 色调数组
* @param {string} easingId 过渡曲线ID
* @param {number} duration 持续时间(毫秒)
*/
set(tint, easingId, duration) {
// 如果上一次的色调过渡未结束,移除
if (this.transition) {
this.transition.remove()
delete this.transition
}
if (duration > 0) {
// 设置场景滤镜模块:色调渲染器
Scene.filters.set('tint', this)
const start = Array.from(this.tint)
const end = tint
const easing = Easing.get(easingId)
// 创建色调过渡计时器
this.transition = new Timer({
duration: duration,
update: timer => {
const tint = this.tint
const time = easing.map(timer.elapsed / duration)
tint[0] = Math.clamp(start[0] * (1 - time) + end[0] * time, -255, 255)
tint[1] = Math.clamp(start[1] * (1 - time) + end[1] * time, -255, 255)
tint[2] = Math.clamp(start[2] * (1 - time) + end[2] * time, -255, 255)
tint[3] = Math.clamp(start[3] * (1 - time) + end[3] * time, 0, 255)
},
callback: () => {
delete this.transition
// 检查是否需要删除渲染器
this.update()
},
}).add()
} else {
// 直接设置色调
this.tint[0] = tint[0]
this.tint[1] = tint[1]
this.tint[2] = tint[2]
this.tint[3] = tint[3]
this.update()
}
}
}