Browse Source

Implement RenderManager.clearColor, add support for blending and transparent in RenderManager.blit, Add generic return type in RenderTargetManager.getTempTarget

master
Palash Bansal 3 years ago
parent
commit
f595dd7ddb
No account linked to committer's email address
3 changed files with 139 additions and 32 deletions
  1. 104
    26
      src/rendering/RenderManager.ts
  2. 31
    2
      src/rendering/RenderTarget.ts
  3. 4
    4
      src/rendering/RenderTargetManager.ts

+ 104
- 26
src/rendering/RenderManager.ts View File

@@ -1,7 +1,11 @@
import {
Blending,
Color,
HalfFloatType,
IUniform,
NoBlending,
NoColorSpace,
NormalBlending,
NoToneMapping,
PCFShadowMap,
ShaderMaterial,
@@ -296,6 +300,13 @@ export class RenderManager extends RenderTargetManager<IRenderManagerEvent, IRen
return string
}

renderTargetToBuffer(target: WebGLRenderTarget): Uint8Array|Uint16Array {
const buffer = target.texture.type === HalfFloatType ?
new Uint16Array(target.width * target.height * 4) :
new Uint8Array(target.width * target.height * 4)
this._renderer.readRenderTargetPixels(target, 0, 0, target.width, target.height, buffer)
return buffer
}

// endregion

@@ -307,6 +318,9 @@ export class RenderManager extends RenderTargetManager<IRenderManagerEvent, IRen
get totalFrameCount(): number {
return this._totalFrameCount
}
resetTotalFrameCount(): void {
this._totalFrameCount = 0
}
set pipeline(value: IPassID[]) {
this._pipeline = value
if (this.autoBuildPipeline) {
@@ -383,25 +397,50 @@ export class RenderManager extends RenderTargetManager<IRenderManagerEvent, IRen
// / TODO



blit(destination: IRenderTarget|undefined|null, {source, viewport, material, clear = true, respectColorSpace = false}: {source?: Texture, viewport?: Vector4, material?: ShaderMaterial, clear?: boolean, respectColorSpace?: boolean} = {}): void {
/**
*
* @param destination - destination target, or screen if undefined or null
* @param source - source Texture
* @param viewport - viewport and scissor
* @param material - override material
* @param clear - clear before blit
* @param respectColorSpace - does color space conversion when reading and writing to the target
* @param blending - Note - Set to NormalBlending if transparent is set to false
* @param transparent
*/
blit(destination: IRenderTarget|undefined|null, {source, viewport, material, clear = true, respectColorSpace = false, blending = NoBlending, transparent = true}: {source?: Texture, viewport?: Vector4, material?: ShaderMaterial, clear?: boolean, respectColorSpace?: boolean, blending?: Blending, transparent?: boolean} = {}): void {
const copyPass = !respectColorSpace ? this._composer.copyPass : this._composer.copyPass2
const {renderToScreen, material: oldMaterial, uniforms: oldUniforms, clear: oldClear} = copyPass
if (material) {
copyPass.material = material
}
const oldViewport = this._renderer.getViewport(new Vector4())
const oldScissor = this._renderer.getScissor(new Vector4())
const oldScissorTest = this._renderer.getScissorTest()
const oldTransparent = copyPass.material.transparent
const oldViewport = !destination ? this._renderer.getViewport(new Vector4()) : destination.viewport.clone()
const oldScissor = !destination ? this._renderer.getScissor(new Vector4()) : destination.scissor.clone()
const oldScissorTest = !destination ? this._renderer.getScissorTest() : destination.scissorTest
const oldAutoClear = this._renderer.autoClear
const oldTarget = this._renderer.getRenderTarget()
if (viewport) this._renderer.setViewport(viewport)
if (viewport) this._renderer.setScissor(viewport)
if (viewport) this._renderer.setScissorTest(true)
const oldBlending = copyPass.material.blending

if (viewport) {
if (!destination) {
this._renderer.setViewport(viewport)
this._renderer.setScissor(viewport)
this._renderer.setScissorTest(true)
} else {
destination.viewport.copy(viewport)
destination.scissor.copy(viewport)
destination.scissorTest = true
}
}
this._renderer.autoClear = false
copyPass.material.blending = !transparent ? NormalBlending : blending
copyPass.uniforms = copyPass.material.uniforms
copyPass.renderToScreen = false
copyPass.clear = clear
copyPass.material.transparent = transparent
copyPass.material.needsUpdate = true

this._renderer.renderWithModes({
sceneRender: true,
opaqueRender: true,
@@ -416,28 +455,67 @@ export class RenderManager extends RenderTargetManager<IRenderManagerEvent, IRen
copyPass.clear = oldClear
copyPass.material = oldMaterial
copyPass.uniforms = oldUniforms
copyPass.material.blending = oldBlending
copyPass.material.transparent = oldTransparent
this._renderer.autoClear = oldAutoClear
if (viewport) this._renderer.setViewport(oldViewport)
if (viewport) this._renderer.setScissor(oldScissor)
if (viewport) this._renderer.setScissorTest(oldScissorTest)
if (viewport) {
if (!destination) {
this._renderer.setViewport(oldViewport)
this._renderer.setScissor(oldScissor)
this._renderer.setScissorTest(oldScissorTest)
} else {
destination.viewport.copy(oldViewport)
destination.scissor.copy(oldScissor)
destination.scissorTest = oldScissorTest
}
}
this._renderer.setRenderTarget(oldTarget) // todo: active cubeface etc
}

// clearColor({r, g, b, a, target, depth = true, stencil = true}:
// {r?: number, g?: number, b?: number, a?: number, target?: IRenderTarget, depth?: boolean, stencil?: boolean}): void {
// const color = this._renderer.getClearColor(new Color())
// const alpha = this._renderer.getClearAlpha()
// this._renderer.setClearAlpha(a ?? alpha)
// this._renderer.setClearColor(new Color(r ?? color.r, g ?? color.g, b ?? color.b))
// const lastTarget = this._renderer.getRenderTarget()
// const activeCubeFace = this._renderer.getActiveCubeFace()
// const activeMipLevel = this._renderer.getActiveMipmapLevel()
// this._renderer.setRenderTarget((target as WebGLRenderTarget) ?? null)
// this._renderer.clear(true, depth, stencil)
// this._renderer.setRenderTarget(lastTarget, activeCubeFace, activeMipLevel)
// this._renderer.setClearColor(color)
// this._renderer.setClearAlpha(alpha)
// }
clearColor({r, g, b, a, target, depth = true, stencil = true, viewport}:
{r?: number, g?: number, b?: number, a?: number, target?: IRenderTarget, depth?: boolean, stencil?: boolean, viewport?: Vector4}): void {
const color = this._renderer.getClearColor(new Color())
const alpha = this._renderer.getClearAlpha()
this._renderer.setClearAlpha(a ?? alpha)
this._renderer.setClearColor(new Color(r ?? color.r, g ?? color.g, b ?? color.b))
const lastTarget = this._renderer.getRenderTarget()
const activeCubeFace = this._renderer.getActiveCubeFace()
const activeMipLevel = this._renderer.getActiveMipmapLevel()

const oldViewport = !target ? this._renderer.getViewport(new Vector4()) : target.viewport.clone()
const oldScissor = !target ? this._renderer.getScissor(new Vector4()) : target.scissor.clone()
const oldScissorTest = !target ? this._renderer.getScissorTest() : target.scissorTest
if (viewport) {
if (!target) {
this._renderer.setViewport(viewport)
this._renderer.setScissor(viewport)
this._renderer.setScissorTest(true)
} else {
target.viewport.copy(viewport)
target.scissor.copy(viewport)
target.scissorTest = true
}
}

this._renderer.setRenderTarget((target as WebGLRenderTarget) ?? null)
this._renderer.clear(true, depth, stencil)

if (viewport) {
if (!target) {
this._renderer.setViewport(oldViewport)
this._renderer.setScissor(oldScissor)
this._renderer.setScissorTest(oldScissorTest)
} else {
target.viewport.copy(oldViewport)
target.scissor.copy(oldScissor)
target.scissorTest = oldScissorTest
}
}

this._renderer.setRenderTarget(lastTarget, activeCubeFace, activeMipLevel)
this._renderer.setClearColor(color)
this._renderer.setClearAlpha(alpha)
}


/**

+ 31
- 2
src/rendering/RenderTarget.ts View File

@@ -6,6 +6,8 @@ import {
Texture,
TextureDataType,
} from 'three'
import {Vector4} from 'three/src/math/Vector4'
import {DepthTexture} from 'three/src/textures/DepthTexture'

export interface IRenderTarget extends EventDispatcher {
texture: Texture | Texture[]
@@ -15,7 +17,34 @@ export interface IRenderTarget extends EventDispatcher {
clone(trackTarget?: boolean): this
setSize(width: number, height: number, depth?: number): void;
dispose(): void;
samples: number

scissor: Vector4;
/**
* @default false
*/
scissorTest: boolean;
viewport: Vector4;

/**
* @default true
*/
depthBuffer: boolean;

/**
* @default true
*/
stencilBuffer: boolean;

/**
* @default null
*/
depthTexture: DepthTexture;
/**
* Defines the count of MSAA samples. Can only be used with WebGL 2. Default is **0**.
* @default 0
*/
samples: number;

}

export interface CreateRenderTargetOptions {
@@ -35,5 +64,5 @@ export interface CreateRenderTargetOptions {

export function createRenderTargetKey(op: CreateRenderTargetOptions = {}): string {
// colorSpace is in key because of ext_sRGB
return [op.sizeMultiplier, op.samples, op.colorSpace, op.type, op.format, op.depthBuffer, op.depthTexture, op.size?.width, op.size?.height].join(';')
return [op.sizeMultiplier, op.samples, op.colorSpace, op.type, op.format, op.depthBuffer, op.depthTexture, op.textureCount, op.size?.width, op.size?.height].join(';')
}

+ 4
- 4
src/rendering/RenderTargetManager.ts View File

@@ -87,12 +87,12 @@ export abstract class RenderTargetManager<E extends BaseEvent = BaseEvent, ET ex
target.dispose()
}

getTempTarget(op: CreateRenderTargetOptions = {}): IRenderTarget {
getTempTarget<T extends IRenderTarget = IRenderTarget>(op: CreateRenderTargetOptions = {}): T {
const key = createRenderTargetKey(op)
let target: IRenderTarget | undefined
if (this._releasedTempTargets[key]?.length) target = this._releasedTempTargets[key].pop()
let target: T | undefined
if (this._releasedTempTargets[key]?.length) target = this._releasedTempTargets[key].pop() as T
if (!target) {
target = this.createTarget(op)
target = this.createTarget<T>(op)
this._processNewTempTarget(target, key)
} else {
this._setTargetOptions(target, op)

Loading…
Cancel
Save