Преглед изворни кода

Add camera shader helpers, support for custom shader snippet in ExtendedCopyPass and RenderTargetPreviewPlugin, some doc comments in IPass.

master
Palash Bansal пре 2 година
родитељ
комит
5e8faf2be3
No account linked to committer's email address

+ 5
- 0
src/core/camera/PerspectiveCamera2.ts Прегледај датотеку

@@ -410,6 +410,11 @@ export class PerspectiveCamera2 extends PerspectiveCamera implements ICamera {

// for shader prop updater
private _positionWorld = new Vector3()

/**
* See also cameraHelpers.glsl
* @param material
*/
updateShaderProperties(material: {defines: Record<string, string | number | undefined>; uniforms: {[p: string]: IUniform}}): this {
material.uniforms.cameraPositionWorld?.value?.copy(this._positionWorld)
material.uniforms.cameraNearFar?.value?.set(this.near, this.far)

+ 18
- 3
src/plugins/ui/RenderTargetPreviewPlugin.ts Прегледај датотеку

@@ -1,11 +1,12 @@
import {AViewerPluginSync, ThreeViewer} from '../../viewer'
import {IRenderTarget} from '../../rendering'
import {createDiv, createStyles, getOrCall, onChange, ValOrArr, ValOrFunc} from 'ts-browser-helpers'
import {SRGBColorSpace, Vector4, WebGLRenderTarget} from 'three'
import {ShaderMaterial, SRGBColorSpace, Vector4, WebGLRenderTarget} from 'three'
import styles from './RenderTargetPreviewPlugin.css?inline'
import {CustomContextMenu} from '../../utils'
import {uiFolderContainer, uiToggle} from 'uiconfig.js'
import {ITexture} from '../../core'
import {ExtendedCopyPass} from '../../postprocessing'

export interface RenderTargetBlock {
target: ValOrFunc<IRenderTarget|{texture?: ValOrArr<ITexture>}|undefined>
@@ -14,6 +15,7 @@ export interface RenderTargetBlock {
transparent: boolean
originalColorSpace: boolean
div: HTMLDivElement
material?: ShaderMaterial // see ExtendedCopyPass
}
@uiFolderContainer('Render Target Preview Plugin')
export class RenderTargetPreviewPlugin<TEvent extends string> extends AViewerPluginSync<TEvent> {
@@ -76,15 +78,27 @@ export class RenderTargetPreviewPlugin<TEvent extends string> extends AViewerPlu
clear: !targetBlock.transparent,
respectColorSpace: !targetBlock.originalColorSpace,
viewport: new Vector4(rect.x, rect.y, rect.width, rect.height),
material: targetBlock.material,
})
this._viewer.renderManager.webglRenderer.outputColorSpace = outputColorSpace
}
}

addTarget(target: RenderTargetBlock['target'], name: string, transparent = false, originalColorSpace = false, visible = true): this {
/**
*
* @param target - render target or a function that returns a render target
* @param name - name of the target
* @param transparent - if true, the target will be rendered with transparency
* @param originalColorSpace - if true, the target will be rendered in its original color space
* @param visible - initial visibility
* @param material - snippet for {@link ExtendedCopyPass} or a custom {@link ExtendedShaderMaterial} or three.js ShaderMaterial. Example to read just the red channel `(s)=>s + ' = vec4(' + s + '.r);'`
*/
addTarget(target: RenderTargetBlock['target'], name: string, transparent = false, originalColorSpace = false, visible = true, material?: ValOrFunc<string, [string]> | ShaderMaterial): this {
if (!target) return this
const div = document.createElement('div')
const targetDef = {target, name, transparent, div, originalColorSpace, visible}
const targetDef: RenderTargetBlock = {target, name, transparent, div, originalColorSpace, visible}
if (material) targetDef.material = (material as ShaderMaterial)?.isMaterial ? material as ShaderMaterial : new ExtendedCopyPass(material as any).material

div.classList.add('RenderTargetPreviewPluginTarget')
if (!targetDef.visible) div.classList.add('RenderTargetPreviewPluginCollapsed')
const header = document.createElement('div')
@@ -136,6 +150,7 @@ export class RenderTargetPreviewPlugin<TEvent extends string> extends AViewerPlu
if (!canvas) return this
const blob = this._viewer.renderManager.exportRenderTarget(target as WebGLRenderTarget)
const url = URL.createObjectURL(blob)
// todo use file transfer or viewer downloadBlob
const link = document.createElement('a')
document.body.appendChild(link)
link.style.display = 'none'

+ 7
- 4
src/postprocessing/ExtendedCopyPass.ts Прегледај датотеку

@@ -1,10 +1,10 @@
import {UniformsUtils} from 'three'
import {CopyShader} from 'three/examples/jsm/shaders/CopyShader.js'
import {glsl} from 'ts-browser-helpers'
import {getOrCall, glsl, ValOrFunc} from 'ts-browser-helpers'
import {ExtendedShaderPass} from './ExtendedShaderPass'

export class ExtendedCopyPass extends ExtendedShaderPass {
constructor() {
constructor(snippet?: ValOrFunc<string, [string]>, respectColorSpace = true) {
super({
uniforms: UniformsUtils.clone(CopyShader.uniforms),
vertexShader: CopyShader.vertexShader,
@@ -13,13 +13,16 @@ export class ExtendedCopyPass extends ExtendedShaderPass {
#include <alphatest_pars_fragment>
varying vec2 vUv;
void main() {
vec4 diffuseColor = tDiffuseTexelToLinear(texture2D(tDiffuse, vUv)) * opacity;
${respectColorSpace ?
'vec4 diffuseColor = tDiffuseTexelToLinear(texture2D(tDiffuse, vUv)) * opacity;' :
'vec4 diffuseColor = texture2D(tDiffuse, vUv) * opacity;'}
#include <alphatest_fragment>
${snippet ? getOrCall(snippet, 'diffuseColor') : ''}
#ifdef OPAQUE
diffuseColor.a = 1.0;
#endif
gl_FragColor = diffuseColor;
#include <encodings_fragment>
${respectColorSpace ? '#include <encodings_fragment>' : ''}
}
`,
}, 'tDiffuse')

+ 5
- 0
src/postprocessing/ExtendedShaderPass.ts Прегледај датотеку

@@ -33,6 +33,10 @@ export class ExtendedShaderPass extends ShaderPass implements IPass {
})
}

/**
* to be called from beforeRender or onObjectRender or similar.
* @param updater
*/
updateShaderProperties(updater?: (IShaderPropertiesUpdater|undefined) | (IShaderPropertiesUpdater|undefined)[]) {
if (!updater) return
if (!Array.isArray(updater)) updater = [updater]
@@ -47,6 +51,7 @@ export class ExtendedShaderPass extends ShaderPass implements IPass {
}

setDirty() {
this.material.needsUpdate = true // do this when material defines etc are changed
this.onDirty.forEach(v=>v())
}


+ 16
- 2
src/postprocessing/Pass.ts Прегледај датотеку

@@ -1,7 +1,7 @@
import {IDisposable, ValOrFunc} from 'ts-browser-helpers'
import {IUniform} from 'three'
import {Pass} from 'three/examples/jsm/postprocessing/Pass.js'
import {IShaderPropertiesUpdater, MaterialExtension} from '../materials'
import {MaterialExtension} from '../materials'
import {ICamera, IRenderManager, IScene} from '../core'

export type IPassID = 'render' | 'screen' | string
@@ -9,13 +9,27 @@ export type IPassID = 'render' | 'screen' | string
export interface IPass<Tid extends IPassID = IPassID> extends Pass, IDisposable {
uniforms?: {[name: string]: IUniform}

updateShaderProperties?: (updater?: (IShaderPropertiesUpdater|undefined) | (IShaderPropertiesUpdater|undefined)[])=>void
// todo?
// updateShaderProperties?: (updater?: (IShaderPropertiesUpdater|undefined) | (IShaderPropertiesUpdater|undefined)[])=>void

materialExtension?: MaterialExtension

/**
* Checked by {@link RenderManager} to determine whether to render this frame. A frame is rendered if any pass is dirty.
* This can be set by the plugin/pass to indicate when to continue rendering. See {@link ProgressivePlugin}.
* This is different from {@link setDirty} which is implementation specific to the pass/plugin. It generally calls onDirty and set the viewer dirty.
*/
dirty?: ValOrFunc<boolean> // isDirty (optional)

/**
* Set the pass as dirty. This is implementation specific to the pass/plugin. It generally calls all {@link onDirty} and set the viewer dirty.
*/
setDirty?(): void
onDirty?: (()=>void)[];

/**
* Unique id for the pass. Used to determine the order of passes in the pipeline.
*/
passId?: Tid;
}


+ 3
- 1
src/utils/shaders.ts Прегледај датотеку

@@ -1,7 +1,9 @@
import simpleCameraHelpers from './shaders/simpleCameraHelpers.glsl'
import cameraHelpers from './shaders/cameraHelpers.glsl'
import randomHelpers from './shaders/randomHelpers.glsl'
import defaultVertex from './shaders/defaultVertex.glsl'
import voronoiNoise from './shaders/voronoiNoise.glsl'

export const shaderUtils = {
simpleCameraHelpers, randomHelpers, voronoiNoise,
simpleCameraHelpers, cameraHelpers, randomHelpers, defaultVertex, voronoiNoise,
}

+ 51
- 0
src/utils/shaders/cameraHelpers.glsl Прегледај датотеку

@@ -0,0 +1,51 @@
#ifndef BASIC_CAMERA_HELPERS
#define BASIC_CAMERA_HELPERS

// See also PerspectiveCamera2
uniform mat4 projection;
uniform vec2 cameraNearFar;
uniform vec3 cameraPositionWorld;

#ifndef THREE_PACKING_INCLUDED
#define THREE_PACKING_INCLUDED
#include <packing>
#endif

float linstep(float edge0, float edge1, float value) {
return clamp((value-edge0)/(edge1-edge0), 0.0, 1.0);
}

float depthToViewZ(const in float depth){
return (depth > 0.999) ? -cameraNearFar.y * 1000.0 : -mix(cameraNearFar.x, cameraNearFar.y, depth);
}
float viewZToDepth(const in float viewZ){
return linstep(-cameraNearFar.x, -cameraNearFar.y, viewZ);
}

vec4 viewToScreen3(const in vec3 pos) {
vec4 projected = projection * vec4(pos, 1.0);
projected.z = pos.z;
// w is -viewZ
projected.w = 1./projected.w;
projected.xyz *= projected.w;
projected.xy = 0.5 + 0.5 * projected.xy;
return projected;
}

vec3 screenToView(const in vec2 uv, const in float viewZ) {
vec2 uv_ = 2. * uv - 1.;
float xe = -(uv_.x + projection[2][0]) * viewZ / projection[0][0];
float ye = -(uv_.y + projection[2][1]) * viewZ / projection[1][1];
return vec3(xe, ye, viewZ);
}

float viewZFromNDCZ(const in float depth) {
#if PERSPECTIVE_CAMERA == 1
return perspectiveDepthToViewZ(depth, cameraNearFar.x, cameraNearFar.y);
#else
return orthographicDepthToViewZ(depth, cameraNearFar.x, cameraNearFar.y);
#endif
}


#endif

+ 6
- 0
src/utils/shaders/simpleCameraHelpers.glsl Прегледај датотеку

@@ -7,4 +7,10 @@ vec3 viewToScreen(const in vec3 pos) {
vec4 projected = projectionMatrix * vec4(pos, 1.0);
return vec3(0.5 + 0.5 * projected.xy / projected.w, projected.w);
}
vec3 screenToView(const in vec2 uv, const in float viewZ) {
vec2 uv_ = 2. * uv - 1.;
float xe = -(uv_.x + projectionMatrix[2][0]) * viewZ / projectionMatrix[0][0];
float ye = -(uv_.y + projectionMatrix[2][1]) * viewZ / projectionMatrix[1][1];
return vec3(xe, ye, viewZ);
}
#endif

Loading…
Откажи
Сачувај