Skip to content
Snippets Groups Projects
Commit 22c45e78 authored by Alexander Rose's avatar Alexander Rose
Browse files

improved renderer and postprocessing params

parent 768ec108
No related branches found
No related tags found
No related merge requests found
/**
* Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
......@@ -17,6 +17,7 @@ import { ParamDefinition as PD } from '../../mol-util/param-definition';
import { RenderTarget } from '../../mol-gl/webgl/render-target';
import { DrawPass } from './draw';
import { Camera } from '../../mol-canvas3d/camera';
import { produce } from 'immer';
import quad_vert from '../../mol-gl/shader/quad.vert'
import postprocessing_frag from '../../mol-gl/shader/postprocessing.frag'
......@@ -47,14 +48,21 @@ const PostprocessingSchema = {
}
export const PostprocessingParams = {
occlusionEnable: PD.Boolean(false),
occlusionKernelSize: PD.Numeric(4, { min: 1, max: 32, step: 1 }),
occlusionBias: PD.Numeric(0.5, { min: 0, max: 1, step: 0.01 }),
occlusionRadius: PD.Numeric(32, { min: 0, max: 256, step: 1 }),
outlineEnable: PD.Boolean(false),
outlineScale: PD.Numeric(1, { min: 0, max: 10, step: 1 }),
outlineThreshold: PD.Numeric(0.8, { min: 0, max: 1, step: 0.01 }),
occlusion: PD.MappedStatic('off', {
on: PD.Group({
kernelSize: PD.Numeric(4, { min: 1, max: 32, step: 1 }),
bias: PD.Numeric(0.5, { min: 0, max: 1, step: 0.01 }),
radius: PD.Numeric(64, { min: 0, max: 256, step: 1 }),
}),
off: PD.Group({})
}, { cycle: true, description: 'Darken occluded crevices with the ambient occlusion effect' }),
outline: PD.MappedStatic('off', {
on: PD.Group({
scale: PD.Numeric(1, { min: 0, max: 10, step: 1 }),
threshold: PD.Numeric(0.8, { min: 0, max: 1, step: 0.01 }),
}),
off: PD.Group({})
}, { cycle: true, description: 'Draw outline around 3D objects' })
}
export type PostprocessingProps = PD.Values<typeof PostprocessingParams>
......@@ -75,14 +83,14 @@ function getPostprocessingRenderable(ctx: WebGLContext, colorTexture: Texture, d
uFogFar: ValueCell.create(10000),
uFogColor: ValueCell.create(Vec3.create(1, 1, 1)),
dOcclusionEnable: ValueCell.create(p.occlusionEnable),
dOcclusionKernelSize: ValueCell.create(p.occlusionKernelSize),
uOcclusionBias: ValueCell.create(p.occlusionBias),
uOcclusionRadius: ValueCell.create(p.occlusionRadius),
dOcclusionEnable: ValueCell.create(p.occlusion.name === 'on'),
dOcclusionKernelSize: ValueCell.create(p.occlusion.name === 'on' ? p.occlusion.params.kernelSize : 4),
uOcclusionBias: ValueCell.create(p.occlusion.name === 'on' ? p.occlusion.params.bias : 0.5),
uOcclusionRadius: ValueCell.create(p.occlusion.name === 'on' ? p.occlusion.params.radius : 64),
dOutlineEnable: ValueCell.create(p.outlineEnable),
uOutlineScale: ValueCell.create(p.outlineScale * ctx.pixelRatio),
uOutlineThreshold: ValueCell.create(p.outlineThreshold),
dOutlineEnable: ValueCell.create(p.outline.name === 'on'),
uOutlineScale: ValueCell.create((p.outline.name === 'on' ? p.outline.params.scale : 1) * ctx.pixelRatio),
uOutlineThreshold: ValueCell.create(p.outline.name === 'on' ? p.outline.params.threshold : 0.8),
dPackedDepth: ValueCell.create(packedDepth),
}
......@@ -108,7 +116,7 @@ export class PostprocessingPass {
}
get enabled() {
return this.props.occlusionEnable || this.props.outlineEnable
return this.props.occlusion.name === 'on' || this.props.outline.name === 'on'
}
setSize(width: number, height: number) {
......@@ -117,35 +125,28 @@ export class PostprocessingPass {
}
setProps(props: Partial<PostprocessingProps>) {
if (props.occlusionEnable !== undefined) {
this.props.occlusionEnable = props.occlusionEnable
ValueCell.update(this.renderable.values.dOcclusionEnable, props.occlusionEnable)
this.props = produce(this.props, p => {
if (props.occlusion !== undefined) {
p.occlusion.name = props.occlusion.name
ValueCell.updateIfChanged(this.renderable.values.dOcclusionEnable, props.occlusion.name === 'on')
if (props.occlusion.name === 'on') {
p.occlusion.params = { ...props.occlusion.params }
ValueCell.updateIfChanged(this.renderable.values.dOcclusionKernelSize, props.occlusion.params.kernelSize)
ValueCell.updateIfChanged(this.renderable.values.uOcclusionBias, props.occlusion.params.bias)
ValueCell.updateIfChanged(this.renderable.values.uOcclusionRadius, props.occlusion.params.radius)
}
if (props.occlusionKernelSize !== undefined) {
this.props.occlusionKernelSize = props.occlusionKernelSize
ValueCell.update(this.renderable.values.dOcclusionKernelSize, props.occlusionKernelSize)
}
if (props.occlusionBias !== undefined) {
this.props.occlusionBias = props.occlusionBias
ValueCell.update(this.renderable.values.uOcclusionBias, props.occlusionBias)
}
if (props.occlusionRadius !== undefined) {
this.props.occlusionRadius = props.occlusionRadius
ValueCell.update(this.renderable.values.uOcclusionRadius, props.occlusionRadius)
}
if (props.outlineEnable !== undefined) {
this.props.outlineEnable = props.outlineEnable
ValueCell.update(this.renderable.values.dOutlineEnable, props.outlineEnable)
}
if (props.outlineScale !== undefined) {
this.props.outlineScale = props.outlineScale
ValueCell.update(this.renderable.values.uOutlineScale, props.outlineScale * this.webgl.pixelRatio)
if (props.outline !== undefined) {
p.outline.name = props.outline.name
ValueCell.updateIfChanged(this.renderable.values.dOutlineEnable, props.outline.name === 'on')
if (props.outline.name === 'on') {
p.outline.params = { ...props.outline.params }
ValueCell.updateIfChanged(this.renderable.values.uOutlineScale, props.outline.params.scale)
ValueCell.updateIfChanged(this.renderable.values.uOutlineThreshold, props.outline.params.threshold)
}
if (props.outlineThreshold !== undefined) {
this.props.outlineThreshold = props.outlineThreshold
ValueCell.update(this.renderable.values.uOutlineThreshold, props.outlineThreshold)
}
})
this.renderable.update()
}
......
/**
* Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
......@@ -55,22 +55,63 @@ export const RendererParams = {
interiorColorFlag: PD.Boolean(true, { label: 'Use Interior Color' }),
interiorColor: PD.Color(Color.fromNormalizedRgb(0.3, 0.3, 0.3)),
highlightColor: PD.Color(Color.fromNormalizedRgb(1.0, 0.4, 0.6)),
selectColor: PD.Color(Color.fromNormalizedRgb(0.2, 1.0, 0.1)),
style: PD.MappedStatic('matte', {
custom: PD.Group({
lightIntensity: PD.Numeric(0.6, { min: 0.0, max: 1.0, step: 0.01 }),
ambientIntensity: PD.Numeric(0.4, { min: 0.0, max: 1.0, step: 0.01 }),
metalness: PD.Numeric(0.0, { min: 0.0, max: 1.0, step: 0.01 }),
roughness: PD.Numeric(1.0, { min: 0.0, max: 1.0, step: 0.01 }),
reflectivity: PD.Numeric(0.5, { min: 0.0, max: 1.0, step: 0.01 }),
highlightColor: PD.Color(Color.fromNormalizedRgb(1.0, 0.4, 0.6)),
selectColor: PD.Color(Color.fromNormalizedRgb(0.2, 1.0, 0.1)),
}, { isExpanded: true }),
flat: PD.Group({}),
matte: PD.Group({}),
glossy: PD.Group({}),
metallic: PD.Group({}),
plastic: PD.Group({}),
}, { label: 'Render Style', description: 'Style in which the 3D scene is rendered' }),
}
export type RendererProps = PD.Values<typeof RendererParams>
function getStyle(props: RendererProps['style']) {
switch (props.name) {
case 'custom':
return props.params
case 'flat':
return {
lightIntensity: 0, ambientIntensity: 1,
metalness: 0, roughness: 0.4, reflectivity: 0.5
}
case 'matte':
return {
lightIntensity: 0.6, ambientIntensity: 0.4,
metalness: 0, roughness: 1, reflectivity: 0.5
}
case 'glossy':
return {
lightIntensity: 0.6, ambientIntensity: 0.4,
metalness: 0, roughness: 0.4, reflectivity: 0.5
}
case 'metallic':
return {
lightIntensity: 0.6, ambientIntensity: 0.4,
metalness: 0.4, roughness: 0.6, reflectivity: 0.5
}
case 'plastic':
return {
lightIntensity: 0.6, ambientIntensity: 0.4,
metalness: 0, roughness: 0.2, reflectivity: 0.5
}
}
}
namespace Renderer {
export function create(ctx: WebGLContext, props: Partial<RendererProps> = {}): Renderer {
const { gl, state, stats } = ctx
const p = deepClone({ ...PD.getDefaultValues(RendererParams), ...props })
const style = getStyle(p.style)
const viewport = Viewport()
const bgColor = Color.toVec3Normalized(Vec3(), p.backgroundColor)
......@@ -112,12 +153,12 @@ namespace Renderer {
uTransparentBackground: ValueCell.create(0),
// the following are general 'material' uniforms
uLightIntensity: ValueCell.create(p.lightIntensity),
uAmbientIntensity: ValueCell.create(p.ambientIntensity),
uLightIntensity: ValueCell.create(style.lightIntensity),
uAmbientIntensity: ValueCell.create(style.ambientIntensity),
uMetalness: ValueCell.create(p.metalness),
uRoughness: ValueCell.create(p.roughness),
uReflectivity: ValueCell.create(p.reflectivity),
uMetalness: ValueCell.create(style.metalness),
uRoughness: ValueCell.create(style.roughness),
uReflectivity: ValueCell.create(style.reflectivity),
uPickingAlphaThreshold: ValueCell.create(p.pickingAlphaThreshold),
......@@ -276,28 +317,6 @@ namespace Renderer {
ValueCell.update(globalUniforms.uInteriorColor, Color.toVec3Normalized(globalUniforms.uInteriorColor.ref.value, p.interiorColor))
}
if (props.lightIntensity !== undefined && props.lightIntensity !== p.lightIntensity) {
p.lightIntensity = props.lightIntensity
ValueCell.update(globalUniforms.uLightIntensity, p.lightIntensity)
}
if (props.ambientIntensity !== undefined && props.ambientIntensity !== p.ambientIntensity) {
p.ambientIntensity = props.ambientIntensity
ValueCell.update(globalUniforms.uAmbientIntensity, p.ambientIntensity)
}
if (props.metalness !== undefined && props.metalness !== p.metalness) {
p.metalness = props.metalness
ValueCell.update(globalUniforms.uMetalness, p.metalness)
}
if (props.roughness !== undefined && props.roughness !== p.roughness) {
p.roughness = props.roughness
ValueCell.update(globalUniforms.uRoughness, p.roughness)
}
if (props.reflectivity !== undefined && props.reflectivity !== p.reflectivity) {
p.reflectivity = props.reflectivity
ValueCell.update(globalUniforms.uReflectivity, p.reflectivity)
}
if (props.highlightColor !== undefined && props.highlightColor !== p.highlightColor) {
p.highlightColor = props.highlightColor
ValueCell.update(globalUniforms.uHighlightColor, Color.toVec3Normalized(globalUniforms.uHighlightColor.ref.value, p.highlightColor))
......@@ -306,6 +325,16 @@ namespace Renderer {
p.selectColor = props.selectColor
ValueCell.update(globalUniforms.uSelectColor, Color.toVec3Normalized(globalUniforms.uSelectColor.ref.value, p.selectColor))
}
if (props.style !== undefined) {
p.style = props.style
Object.assign(style, getStyle(props.style))
ValueCell.updateIfChanged(globalUniforms.uLightIntensity, style.lightIntensity)
ValueCell.updateIfChanged(globalUniforms.uAmbientIntensity, style.ambientIntensity)
ValueCell.updateIfChanged(globalUniforms.uMetalness, style.metalness)
ValueCell.updateIfChanged(globalUniforms.uRoughness, style.roughness)
ValueCell.updateIfChanged(globalUniforms.uReflectivity, style.reflectivity)
}
},
setViewport: (x: number, y: number, width: number, height: number) => {
gl.viewport(x, y, width, height)
......
/**
* Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author David Sehnal <david.sehnal@gmail.com>
......@@ -38,9 +38,9 @@ const SimpleSettingsParams = {
'transparent': PD.EmptyGroup(),
'opaque': PD.Group({ color: PD.Color(Color(0xFCFBF9), { description: 'Custom background color' }) }, { isFlat: true })
}, { description: 'Background of the 3D canvas' }),
renderStyle: PD.Select('glossy', PD.arrayToOptions(['flat', 'matte', 'glossy', 'metallic']), { description: 'Style in which the 3D scene is rendered' }),
occlusion: PD.Boolean(false, { description: 'Darken occluded crevices with the ambient occlusion effect' }),
outline: PD.Boolean(false, { description: 'Draw outline around 3D objects' }),
renderStyle: Canvas3DParams.renderer.params.style,
occlusion: Canvas3DParams.postprocessing.params.occlusion,
outline: Canvas3DParams.postprocessing.params.outline,
fog: PD.Boolean(false, { description: 'Show fog in the distance' }),
clipFar: PD.Boolean(true, { description: 'Clip scene in the distance' }),
};
......@@ -60,21 +60,6 @@ const SimpleSettingsMapping = ParamMapping({
const { canvas } = props;
const renderer = canvas.renderer;
let renderStyle: SimpleSettingsParams['renderStyle']['defaultValue'] = 'custom' as any;
if (renderer) {
if (renderer.lightIntensity === 0 && renderer.ambientIntensity === 1 && renderer.roughness === 0.4 && renderer.metalness === 0) {
renderStyle = 'flat'
} else if (renderer.lightIntensity === 0.6 && renderer.ambientIntensity === 0.4) {
if (renderer.roughness === 1 && renderer.metalness === 0) {
renderStyle = 'matte'
} else if (renderer.roughness === 0.4 && renderer.metalness === 0) {
renderStyle = 'glossy'
} else if (renderer.roughness === 0.6 && renderer.metalness === 0.4) {
renderStyle = 'metallic'
}
}
}
return {
layout: props.layout,
spin: !!canvas.trackball.spin,
......@@ -82,9 +67,9 @@ const SimpleSettingsMapping = ParamMapping({
background: (renderer.backgroundColor === ColorNames.white && canvas.transparentBackground)
? { name: 'transparent', params: { } }
: { name: 'opaque', params: { color: renderer.backgroundColor } },
renderStyle,
occlusion: canvas.postprocessing.occlusionEnable,
outline: canvas.postprocessing.outlineEnable,
renderStyle: renderer.style,
occlusion: canvas.postprocessing.occlusion,
outline: canvas.postprocessing.outline,
fog: ctx.canvas3d ? canvas.cameraFog > 1 : false,
clipFar: canvas.cameraClipFar
};
......@@ -95,18 +80,9 @@ const SimpleSettingsMapping = ParamMapping({
canvas.cameraMode = s.camera;
canvas.transparentBackground = s.background.name === 'transparent';
canvas.renderer.backgroundColor = s.background.name === 'transparent' ? ColorNames.white : s.background.params.color;
switch (s.renderStyle) {
case 'flat': Object.assign(canvas.renderer, { lightIntensity: 0, ambientIntensity: 1, roughness: 0.4, metalness: 0 }); break;
case 'matte': Object.assign(canvas.renderer, { lightIntensity: 0.6, ambientIntensity: 0.4, roughness: 1, metalness: 0 }); break;
case 'glossy': Object.assign(canvas.renderer, { lightIntensity: 0.6, ambientIntensity: 0.4, roughness: 0.4, metalness: 0 }); break;
case 'metallic': Object.assign(canvas.renderer, { lightIntensity: 0.6, ambientIntensity: 0.4, roughness: 0.6, metalness: 0.4 }); break;
}
canvas.postprocessing.occlusionEnable = s.occlusion;
if (s.occlusion) {
canvas.postprocessing.occlusionBias = 0.5;
canvas.postprocessing.occlusionRadius = 64;
}
canvas.postprocessing.outlineEnable = s.outline;
canvas.renderer.style = s.renderStyle
canvas.postprocessing.occlusion = s.occlusion;
canvas.postprocessing.outline = s.outline;
canvas.cameraFog = s.fog ? 50 : 0;
canvas.cameraClipFar = s.clipFar;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment