-
Notifications
You must be signed in to change notification settings - Fork 46
Open
Description
Hi,
currently I try to migrate this post process to work with pmdrs/postprocessing. Unfortunately I failed.
I would really appreciate if someone could help me with this.
import { Color, HalfFloatType, NearestFilter, RGBAFormat, Uniform, Vector2, Vector4, WebGLRenderTarget } from "three"
import { Effect } from 'postprocessing'
import { getSurfaceIdMaterial } from "./FindSurfaces"
export default class OutlineEffect extends Effect {
constructor(resolution, scene, camera) {
super('OutlineEffect', fragmentShader, {
uniforms: new Map([
["surfaceBuffer", new Uniform(null)],
['outlineColor', new Uniform(new Color(1, 0, 0))],
['multiplierParameters', new Uniform(new Vector2(.9, 20))],
['screenSize', new Uniform(new Vector4(resolution.x, resolution.y, 1 / resolution.x, 1 / resolution.y))]
])
})
this.resolution = new Vector2(resolution.x, resolution.y)
this.scene = scene
this.camera = camera
this.surfaceBuffer = new WebGLRenderTarget(this.resolution.x, this.resolution.y)
this.surfaceBuffer.texture.format = RGBAFormat
this.surfaceBuffer.texture.type = HalfFloatType
this.surfaceBuffer.texture.minFilter = NearestFilter
this.surfaceBuffer.texture.magFilter = NearestFilter
this.surfaceBuffer.texture.generateMipmaps = false
this.surfaceBuffer.stencilBuffer = false
this.uniforms.get("surfaceBuffer").value = this.surfaceBuffer.texture
this.surfaceIdOverrideMaterial = getSurfaceIdMaterial()
}
update(renderer, inputBuffer, deltaTime) {
// Turn off writing to the depth buffer because we need to read from it in the subsequent passes.
const depthBufferValue = writeBuffer.depthBuffer
writeBuffer.depthBuffer = false
// 1. Re-render the scene to capture all suface IDs in a texture.
renderer.setRenderTarget(this.surfaceBuffer)
const overrideMaterialValue = this.scene.overrideMaterial
this.scene.overrideMaterial = this.surfaceIdOverrideMaterial
renderer.render(this.scene, this.camera)
this.scene.overrideMaterial = overrideMaterialValue
// 2. Draw the outlines using the depth texture and normal texture and combine it with the scene color
if (this.renderToScreen) {
// If this is the last effect, then renderToScreen is true.
// So we should render to the screen by setting target null
// Otherwise, just render into the writeBuffer that the next effect will use as its read buffer.
renderer.setRenderTarget(null)
this.fsQuad.render(renderer)
} else {
renderer.setRenderTarget(writeBuffer)
this.fsQuad.render(renderer)
}
// Reset the depthBuffer value so we continue writing to it in the next render.
writeBuffer.depthBuffer = depthBufferValue
}
updateMaxSurfaceId(maxSurfaceId) {
this.surfaceIdOverrideMaterial.uniforms.maxSurfaceId.value = maxSurfaceId
}
setSize(width, height) {
this.resolution.set(width, height)
this.surfaceBuffer.setSize(width, height)
this.uniforms.get('screenSize').value.set(this.resolution.x, this.resolution.y, 1 / this.resolution.x, 1 / this.resolution.y)
}
}
const fragmentShader = `
uniform sampler2D surfaceBuffer;
uniform vec4 screenSize;
uniform vec3 outlineColor;
uniform vec2 multiplierParameters;
float readDepth (sampler2D depthSampler, vec2 coord) {
float fragCoordZ = texture2D(depthSampler, coord).x;
float viewZ = perspectiveDepthToViewZ(fragCoordZ, cameraNear, cameraFar);
return viewZToOrthographicDepth(viewZ, cameraNear, cameraFar);
}
float getLinearDepth(vec3 pos) {
return -(viewMatrix * vec4(pos, 1.0)).z;
}
float getLinearScreenDepth(sampler2D map) {
vec2 vUv = gl_FragCoord.xy * screenSize.zw;
return readDepth(map, vUv);
}
float getPixelDepth(int x, int y, vec2 uv) {
return readDepth(depthBuffer, uv + screenSize.zw * vec2(x, y));
}
vec3 getSurfaceValue(int x, int y, vec2 uv) {
vec3 val = texture2D(surfaceBuffer, uv + screenSize.zw * vec2(x, y)).rgb;
return val;
}
float saturateValue(float num) {
return clamp(num, 0.0, 1.0);
}
float getSufaceIdDiff(vec3 surfaceValue, vec2 uv) {
float surfaceIdDiff = 0.0;
surfaceIdDiff += distance(surfaceValue, getSurfaceValue(1, 0, uv));
surfaceIdDiff += distance(surfaceValue, getSurfaceValue(0, 1, uv));
surfaceIdDiff += distance(surfaceValue, getSurfaceValue(0, 1, uv));
surfaceIdDiff += distance(surfaceValue, getSurfaceValue(0, -1, uv));
surfaceIdDiff += distance(surfaceValue, getSurfaceValue(1, 1, uv));
surfaceIdDiff += distance(surfaceValue, getSurfaceValue(1, -1, uv));
surfaceIdDiff += distance(surfaceValue, getSurfaceValue(-1, 1, uv));
surfaceIdDiff += distance(surfaceValue, getSurfaceValue(-1, -1, uv));
return surfaceIdDiff;
}
void mainImage(const in vec4 inputColor, const in vec2 uv, out vec4 outputColor) {
float depth = getPixelDepth(0, 0, uv);
vec3 surfaceValue = getSurfaceValue(0, 0, uv);
// Get the difference between depth of neighboring pixels and current
float depthDiff = 0.0;
depthDiff += abs(depth - getPixelDepth(1, 0, uv));
depthDiff += abs(depth - getPixelDepth(-1, 0, uv));
depthDiff += abs(depth - getPixelDepth(0, 1, uv));
depthDiff += abs(depth - getPixelDepth(0, -1, uv));
// Get the difference between surface values of neighboring pixels and current
float surfaceValueDiff = getSufaceIdDiff(surfaceValue, uv);
// Apply multiplier & bias to each
float depthBias = multiplierParameters.x;
float depthMultiplier = multiplierParameters.y;
depthDiff = depthDiff * depthMultiplier;
depthDiff = saturateValue(depthDiff);
depthDiff = pow(depthDiff, depthBias);
if (surfaceValueDiff != 0.0) surfaceValueDiff = 1.0;
float outline = saturateValue(surfaceValueDiff + depthDiff);
// Combine outline with scene color
vec4 outlineColor = vec4(outlineColor, 1.0);
outputColor = vec4(mix(inputColor, outlineColor, outline));
}`
Metadata
Metadata
Assignees
Labels
No labels