| @uiFolderContainer('Custom Tint Extension') | @uiFolderContainer('Custom Tint Extension') | ||||
| export class CustomScreenPassExtensionPlugin extends AScreenPassExtensionPlugin { | export class CustomScreenPassExtensionPlugin extends AScreenPassExtensionPlugin { | ||||
| static readonly PluginType = 'Vignette' | |||||
| static readonly PluginType = 'CustomScreenPassExtensionPlugin' | |||||
| readonly extraUniforms = { | readonly extraUniforms = { | ||||
| intensity: {value: 1}, | intensity: {value: 1}, | ||||
| }) | }) | ||||
| async function init() { | async function init() { | ||||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||||
| await viewer.load('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||||
| autoCenter: true, | |||||
| autoScale: true, | |||||
| }) | |||||
| await Promise.all([ | |||||
| viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr'), | |||||
| viewer.load('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||||
| autoCenter: true, | |||||
| autoScale: true, | |||||
| })]) | |||||
| // Add the color to the UI | // Add the color to the UI | ||||
| const ui = viewer.addPluginSync(TweakpaneUiPlugin, true) | const ui = viewer.addPluginSync(TweakpaneUiPlugin, true) | ||||
| ui.setupPluginUi(CustomScreenPassExtensionPlugin) | |||||
| ui.setupPluginUi(CustomScreenPassExtensionPlugin, {expanded: true}) | |||||
| } | } | ||||
| async function init() { | async function init() { | ||||
| viewer.scene.backgroundColor.set(0) | viewer.scene.backgroundColor.set(0) | ||||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||||
| await viewer.load('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||||
| await Promise.all([ | |||||
| viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr'), | |||||
| viewer.load('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||||
| autoCenter: true, | autoCenter: true, | ||||
| autoScale: true, | autoScale: true, | ||||
| }) | |||||
| })]) | |||||
| // Add the color to the UI | // Add the color to the UI | ||||
| const ui = viewer.addPluginSync(TweakpaneUiPlugin, true) | const ui = viewer.addPluginSync(TweakpaneUiPlugin, true) |
| async function init() { | async function init() { | ||||
| viewer.scene.backgroundColor.set(0) | viewer.scene.backgroundColor.set(0) | ||||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||||
| await viewer.load('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||||
| autoCenter: true, | |||||
| autoScale: true, | |||||
| }) | |||||
| await Promise.all([ | |||||
| viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr'), | |||||
| viewer.load('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||||
| autoCenter: true, | |||||
| autoScale: true, | |||||
| })]) | |||||
| // Add the color to the UI | // Add the color to the UI | ||||
| const ui = viewer.addPluginSync(TweakpaneUiPlugin, true) | const ui = viewer.addPluginSync(TweakpaneUiPlugin, true) |
| async function init() { | async function init() { | ||||
| viewer.scene.backgroundColor.set(0) | viewer.scene.backgroundColor.set(0) | ||||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||||
| await viewer.load('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||||
| autoCenter: true, | |||||
| autoScale: true, | |||||
| }) | |||||
| await Promise.all([ | |||||
| viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr'), | |||||
| viewer.load('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||||
| autoCenter: true, | |||||
| autoScale: true, | |||||
| })]) | |||||
| } | } | ||||
| _testStart() | _testStart() |
| ## What you need | ## What you need | ||||
| - A 3D Model (GLTF, GLB, OBJ, FBX, etc). Optionally, the model, scene, and plugins can be configured, compressed and exported using the [Threepipe Editor](https://editor.threepipe.org) or [Tweakpane Editor](https://threepipe.org/examples/tweakpane-editor/). A sample is used in examples below. | |||||
| - A 3D Model (GLTF, GLB, OBJ, FBX, etc). Optionally, the model, scene, and plugins can be configured, compressed and exported using the [Threepipe Editor](https://editor.threepipe.org) or [Tweakpane Editor](https://threepipe.org/examples/tweakpane-editor/). Here is a sample model with configured settings - [classic-watch.glb](https://asset-samples.threepipe.org/demos/classic-watch.glb) | |||||
| - A modern browser that supports [WebGL2](https://caniuse.com/webgl2) and [WebAssembly](https://caniuse.com/webassembly) (for some plugins). | - A modern browser that supports [WebGL2](https://caniuse.com/webgl2) and [WebAssembly](https://caniuse.com/webassembly) (for some plugins). | ||||
| - Node.js (for local development). Node 18+ is recommended. | |||||
| - Node.js (optional, only for local development). Node 18+ is recommended. | |||||
| - An existing project or willingness to start a new one | - An existing project or willingness to start a new one | ||||
| - Basic knowledge of JavaScript/TypeScript | - Basic knowledge of JavaScript/TypeScript | ||||
| # Screen Pass - Extensions and Shaders | # Screen Pass - Extensions and Shaders | ||||
| The Screen Pass is the final rendering stage in Threepipe that outputs the rendered scene to the screen or a render target. It provides multiple ways to customize the final image through custom shaders, material extensions, and shader snippets. | |||||
| The `ScreenPass` is the final rendering stage in Threepipe that outputs the rendered scene to the screen or a render target. It provides multiple ways to customize the final image through custom shaders, material extensions, and shader snippets. | |||||
| ## Overview | ## Overview | ||||
| Check out the [ScreenPass.glsl](https://github.com/repalash/threepipe/blob/master/src/postprocessing/ScreenPass.glsl) for the default fragment shader code used in the screen pass. | Check out the [ScreenPass.glsl](https://github.com/repalash/threepipe/blob/master/src/postprocessing/ScreenPass.glsl) for the default fragment shader code used in the screen pass. | ||||
| Let's explore how to customize the screen pass using different methods to achieve a color tint effect as an example. | |||||
| <iframe src="https://threepipe.org/examples/screen-pass-extension-plugin/" style="width:100%;min-height:600px;border:none;" loading="lazy" title="Screen Pass Extension Example"></iframe> | |||||
| ## Basic Screen Shader | ## Basic Screen Shader | ||||
| The simplest way to customize the screen pass is by providing a shader snippet as a string: | The simplest way to customize the screen pass is by providing a shader snippet as a string: | ||||
| ## Screen Pass Material Extensions | ## Screen Pass Material Extensions | ||||
| Material extensions provide the most flexible way to modify the screen pass. They allow you to: | Material extensions provide the most flexible way to modify the screen pass. They allow you to: | ||||
| - Add custom uniforms | |||||
| - Inject shader code | |||||
| - Add defines | |||||
| - Add custom uniforms, defines | |||||
| - Inject/modify shader code | |||||
| - Hook into render events | - Hook into render events | ||||
| ```typescript | ```typescript |
| ## Step 1: Setting Up the Basic Structure | ## Step 1: Setting Up the Basic Structure | ||||
| First, import the necessary modules from threepipe: | |||||
| First, let's create a new project or install `threepipe`, `@threepipe/plugin-tweakpane`(into existing project) and import the necessary modules in your project: | |||||
| ```bash | |||||
| # If you are starting a new project, use the following command to create a new threepipe project | |||||
| npm create threepipe@latest | |||||
| # If you are adding to an existing project, install threepipe and the Tweakpane UI plugin | |||||
| npm install threepipe @threepipe/plugin-tweakpane | |||||
| ``` | |||||
| Import the required modules in your JavaScript or TypeScript file: | |||||
| ```typescript | ```typescript | ||||
| import { | import { | ||||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | ||||
| ``` | ``` | ||||
| ::: tip | |||||
| Checkout the [Quickstart section](./../guide/getting-started#quickstart) for more details on how to set up a basic threepipe project. | |||||
| ::: | |||||
| ## Step 2: Define ShaderToy Uniforms | ## Step 2: Define ShaderToy Uniforms | ||||
| ShaderToy shaders expect specific uniforms. Create these to match the ShaderToy specification: | ShaderToy shaders expect specific uniforms. Create these to match the ShaderToy specification: |