diff --git a/docs/user-manual/graphics/advanced-rendering/dual-source-blending.md b/docs/user-manual/graphics/advanced-rendering/dual-source-blending.md new file mode 100644 index 00000000000..10286877b9d --- /dev/null +++ b/docs/user-manual/graphics/advanced-rendering/dual-source-blending.md @@ -0,0 +1,94 @@ +--- +title: Dual-Source Blending +description: Use two fragment shader outputs in one blend operation on WebGL 2 and WebGPU. +--- + +Dual-source blending allows a fragment shader to produce two colors for a single color attachment. The first color is the value being blended, while the second color can be selected as a blend factor. This supports effects such as subpixel text antialiasing and advanced compositing that cannot be expressed using a single fragment output. + +## Platform Support + +Dual-source blending is an optional capability on both graphics backends: + +- **WebGPU** uses the `dual-source-blending` device feature and WGSL language extension. +- **WebGL 2** uses the `WEBGL_blend_func_extended` extension. + +PlayCanvas exposes both through the same capability flag: + +```javascript +const device = app.graphicsDevice; + +if (!device.supportsDualSourceBlending) { + // Use a fallback material or rendering path. +} +``` + +The engine also defines `CAPS_DUAL_SOURCE_BLENDING` when the capability is available. On WebGPU, the engine adds `enable dual_source_blending;` to fragment shader variants that use the feature. + +## Blend Factors + +The secondary fragment output can be referenced using four blend factors: + +| Blend factor | Description | +|--------------|-------------| +| `BLENDMODE_SRC1_COLOR` | Secondary source color | +| `BLENDMODE_ONE_MINUS_SRC1_COLOR` | One minus the secondary source color | +| `BLENDMODE_SRC1_ALPHA` | Secondary source alpha | +| `BLENDMODE_ONE_MINUS_SRC1_ALPHA` | One minus the secondary source alpha | + +Only use these constants when `device.supportsDualSourceBlending` is true. + +## StandardMaterial + +Dual-source blending is enabled automatically when a material's [`BlendState`](https://api.playcanvas.com/engine/classes/BlendState.html) uses one of the secondary source factors. There is no separate material setting. See [Transparency](/user-manual/graphics/transparency) for how blend state fits together with the other transparency options. + +First, override the `outputPS` chunk to write the primary and secondary fragment outputs. Supply both GLSL and WGSL versions when supporting both graphics backends: + +```javascript +const material = new pc.StandardMaterial(); +material.useLighting = false; +material.useTonemap = false; + +material.getShaderChunks(pc.SHADERLANGUAGE_GLSL).set('outputPS', ` + gl_FragColor = vec4(0.45, 0.02, 0.02, 0.0); + pcFragColorSecondary = vec4(0.0, 0.85, 0.18, 1.0); +`); + +material.getShaderChunks(pc.SHADERLANGUAGE_WGSL).set('outputPS', ` + output.color = vec4f(0.45, 0.02, 0.02, 0.0); + output.colorSecondary = vec4f(0.0, 0.85, 0.18, 1.0); +`); +``` + +Then configure the blend state. This example calculates `source0 + destination * source1` for RGB: + +```javascript +material.blendState = new pc.BlendState( + true, + pc.BLENDEQUATION_ADD, + pc.BLENDMODE_ONE, + pc.BLENDMODE_SRC1_COLOR, + pc.BLENDEQUATION_ADD, + pc.BLENDMODE_ZERO, + pc.BLENDMODE_ONE +); + +material.update(); +``` + +Here, `gl_FragColor` / `output.color` is `source0`, and `pcFragColorSecondary` / `output.colorSecondary` is `source1`. The secondary value participates in blending but is not written to a separate color attachment. + +## ShaderMaterial + +[`ShaderMaterial`](https://api.playcanvas.com/engine/classes/ShaderMaterial.html) uses the same BlendState-driven behavior. Write both outputs in the fragment shader and assign a blend state containing a secondary source factor. The engine automatically generates the dual-source shader variant for that material. + +When creating shader definitions directly using `ShaderDefinitionUtils.createDefinition`, pass `useDualSourceBlending: true`. This low-level option is not needed for StandardMaterial or ShaderMaterial. + +## Restrictions + +- The render target must have exactly one color attachment. Dual-source blending cannot be combined with [Multiple Render Targets](/user-manual/graphics/advanced-rendering/multiple-render-targets). +- Support is device-dependent, so always check `device.supportsDualSourceBlending` before assigning a secondary source blend factor. +- Dual-source blending is selected independently for each material and draw call. Other materials in the same render pass do not need dual-source outputs. + +## Example + +The [Dual-Source Blending example](https://playcanvas.com/examples/#/test/dual-source-blending) renders a black-and-white checkerboard, then draws a dual-source blended quad over it. Black cells receive only the red primary output, while white cells also contribute the green secondary output. diff --git a/docs/user-manual/graphics/advanced-rendering/index.md b/docs/user-manual/graphics/advanced-rendering/index.md index 310d9837528..39de3f61660 100644 --- a/docs/user-manual/graphics/advanced-rendering/index.md +++ b/docs/user-manual/graphics/advanced-rendering/index.md @@ -1,4 +1,4 @@ --- title: Advanced Rendering -description: Section index for batching, instancing, multi-draw, indirect drawing, and multiple render targets in PlayCanvas. +description: Section index for batching, instancing, multi-draw, indirect drawing, multiple render targets, and dual-source blending in PlayCanvas. --- diff --git a/docs/user-manual/graphics/advanced-rendering/multiple-render-targets.md b/docs/user-manual/graphics/advanced-rendering/multiple-render-targets.md index 57f58be8717..2abcba1cd92 100644 --- a/docs/user-manual/graphics/advanced-rendering/multiple-render-targets.md +++ b/docs/user-manual/graphics/advanced-rendering/multiple-render-targets.md @@ -12,6 +12,7 @@ Multiple render targets have the following restrictions: - All color attachments of a multiple render target must have the same width and height. - All color attachments are cleared to the same value, specified using [`CameraComponent.clearColor`](https://api.playcanvas.com/engine/classes/CameraComponent.html#clearcolor). - All color attachments use the same write mask and alpha blend mode, as specified using [`BlendState`](https://api.playcanvas.com/engine/classes/BlendState.html). +- [Dual-source blending](/user-manual/graphics/advanced-rendering/dual-source-blending) cannot be used with MRT because it requires exactly one color attachment. ## How to use MRT diff --git a/docs/user-manual/graphics/shaders/glsl-specifics.md b/docs/user-manual/graphics/shaders/glsl-specifics.md index 2c03110c1c3..eb4ed1de1f9 100644 --- a/docs/user-manual/graphics/shaders/glsl-specifics.md +++ b/docs/user-manual/graphics/shaders/glsl-specifics.md @@ -94,3 +94,9 @@ varying vec2 uv0; The `in`/`out` syntax (introduced in GLSL 3.3+) is not supported. ::: + +### Dual-Source Fragment Outputs + +When a material's blend state uses a secondary source factor, write the primary color to `gl_FragColor` and the secondary blend value to `pcFragColorSecondary`. On WebGL 2, the engine enables `GL_EXT_blend_func_extended` and declares both outputs automatically. + +See [Dual-Source Blending](/user-manual/graphics/advanced-rendering/dual-source-blending) for capability detection, cross-platform shader code, and BlendState configuration. diff --git a/docs/user-manual/graphics/shaders/wgsl-capabilities.md b/docs/user-manual/graphics/shaders/wgsl-capabilities.md index f304b51483f..116d53aea51 100644 --- a/docs/user-manual/graphics/shaders/wgsl-capabilities.md +++ b/docs/user-manual/graphics/shaders/wgsl-capabilities.md @@ -61,6 +61,11 @@ At device creation, the engine reads `navigator.gpu.wgslLanguageFeatures` and ad - **Preprocessor define:** `CAPS_PRIMITIVE_INDEX` - **Shader stages:** fragment - **Details:** Simplified API exposes `primitiveIndex` on `FragmentInput` and the global `pcPrimitiveIndex` when the device supports the feature +- **`device.supportsDualSourceBlending`** + - **Engine injects:** `enable dual_source_blending;` for fragment shader variants whose blend state uses a secondary source factor + - **Preprocessor define:** `CAPS_DUAL_SOURCE_BLENDING` + - **Shader stages:** fragment + - **Details:** Provides a second fragment output for use as a blend factor; see [Dual-Source Blending](/user-manual/graphics/advanced-rendering/dual-source-blending) - **`device.supportsSubgroups`** - **Engine injects:** `enable subgroups;` - **Preprocessor define:** `CAPS_SUBGROUPS` diff --git a/docs/user-manual/graphics/shaders/wgsl-vertex-fragment-shaders.md b/docs/user-manual/graphics/shaders/wgsl-vertex-fragment-shaders.md index 57c7ef59f26..51e515eac72 100644 --- a/docs/user-manual/graphics/shaders/wgsl-vertex-fragment-shaders.md +++ b/docs/user-manual/graphics/shaders/wgsl-vertex-fragment-shaders.md @@ -133,6 +133,12 @@ Example: } ``` +#### Dual-Source Outputs + +When a material's blend state uses a secondary source factor, write the primary color to `output.color` and the secondary blend value to `output.colorSecondary`. The engine generates both outputs at location 0 with the appropriate `@blend_src` attributes and enables the required WGSL extension. + +Dual-source blending requires exactly one color attachment. See [Dual-Source Blending](/user-manual/graphics/advanced-rendering/dual-source-blending) for capability detection and BlendState configuration. + :::note Support for rendering to integer textures (output format other than `vec4f`) is not available yet, and will be added in the future. diff --git a/docs/user-manual/graphics/transparency.md b/docs/user-manual/graphics/transparency.md new file mode 100644 index 00000000000..0ebbc953976 --- /dev/null +++ b/docs/user-manual/graphics/transparency.md @@ -0,0 +1,132 @@ +--- +title: Transparency +description: "Compare the ways PlayCanvas renders transparent surfaces: alpha blending, alpha test, opacity dithering and alpha to coverage, and when to use each." +--- + +PlayCanvas offers several ways to render a surface that is not fully opaque. They differ in cost, in how much they depend on draw order, and in the kind of artifacts they produce, so the right choice depends on what you are rendering. + +All of them are driven by the material's opacity, which comes from [`StandardMaterial#opacity`](https://api.playcanvas.com/engine/classes/StandardMaterial.html#opacity), an [`opacityMap`](https://api.playcanvas.com/engine/classes/StandardMaterial.html#opacitymap), or vertex colors. + +## Alpha Blending + +Setting [`blendType`](https://api.playcanvas.com/engine/classes/Material.html#blendtype) to a blending mode such as `BLEND_NORMAL` mixes the surface with whatever is already in the frame buffer. + +```javascript +material.blendType = pc.BLEND_NORMAL; +material.opacity = 0.5; +material.update(); +``` + +This gives the smoothest result and supports any opacity value, but it is order dependent. Blended geometry is drawn in the transparent pass, after opaque geometry, and is sorted back to front per layer according to [`Layer#transparentSortMode`](https://api.playcanvas.com/engine/classes/Layer.html#transparentsortmode). Sorting happens per mesh instance, so it cannot resolve a single mesh that overlaps itself - a common source of artifacts on foliage, hair and glass. Blended materials also normally disable depth writes, so they do not occlude each other. + +### Blend State + +`blendType` is a convenient shorthand for a handful of common configurations. For full control, assign a [`BlendState`](https://api.playcanvas.com/engine/classes/BlendState.html) to [`Material#blendState`](https://api.playcanvas.com/engine/classes/Material.html#blendstate), which specifies the blend equation and the source and destination factors for color and alpha independently, along with a per-channel color write mask. Assigning a blend state overwrites anything previously set through `blendType`. + +```javascript +// equivalent to BLEND_NORMAL, written out in full +material.blendState = new pc.BlendState( + true, + pc.BLENDEQUATION_ADD, pc.BLENDMODE_SRC_ALPHA, pc.BLENDMODE_ONE_MINUS_SRC_ALPHA +); +material.update(); +``` + +Several ready-made states are available as constants - `BlendState.NOBLEND`, `BlendState.ALPHABLEND`, `BlendState.ADDBLEND` and `BlendState.NOWRITE`. For best performance, create the blend states you need up front and assign them as required, rather than modifying a state after creation. + +Note that the getter returns a read-only view, so the setter must be used to change blending - this is what keeps the material's transparency and sorting state in sync: + +```javascript +const state = material.blendState.clone(); +state.setColorWrite(true, true, true, false); +material.blendState = state; +material.update(); +``` + +#### Per-attachment blending + +By default a blend state applies to every color attachment of the render target. When rendering to [Multiple Render Targets](/user-manual/graphics/advanced-rendering/multiple-render-targets), individual attachments can be given their own blend state and write mask using [`BlendState#setAttachment`](https://api.playcanvas.com/engine/classes/BlendState.html#setattachment), for attachment indices 1 to 7. Attachment 0 is configured through the other properties of the class, and any attachment without an independent state follows attachment 0. + +```javascript +// attachment 1 keeps the blending of attachment 0, but writes no channels +const state = material.blendState.clone(); +const noWrite = state.clone(); +noWrite.setColorWrite(false, false, false, false); +state.setAttachment(1, noWrite); +material.blendState = state; +material.update(); +``` + +This requires [`GraphicsDevice#supportsIndependentBlending`](https://api.playcanvas.com/engine/classes/GraphicsDevice.html#supportsindependentblending). On devices without support, the state of attachment 0 is used for all attachments. + +Using one of the secondary source blend factors in a blend state additionally enables [Dual-Source Blending](/user-manual/graphics/advanced-rendering/dual-source-blending), which lets a fragment shader output a second color used as a blend factor. + +## Alpha Test + +[`alphaTest`](https://api.playcanvas.com/engine/classes/Material.html#alphatest) discards any fragment whose opacity falls below a threshold. + +```javascript +material.alphaTest = 0.5; +material.update(); +``` + +The result is binary - a fragment is either fully opaque or gone - so there is nothing to sort and the material stays in the opaque pass, writing depth normally. That makes it cheap and completely order independent, at the cost of hard, aliased cutout edges. It is the usual choice for dense foliage and other cutouts where partial opacity is not needed. + +## Opacity Dithering + +[`opacityDither`](https://api.playcanvas.com/engine/classes/StandardMaterial.html#opacitydither) converts opacity into a screen-space dither pattern, discarding a proportion of fragments instead of blending them. + +```javascript +material.blendType = pc.BLEND_NONE; +material.opacity = 0.5; +material.opacityDither = pc.DITHER_BAYER8; +material.update(); +``` + +Available patterns are `DITHER_BAYER2`, `DITHER_BAYER4`, `DITHER_BAYER8`, `DITHER_BAYER16`, `DITHER_BLUENOISE` and `DITHER_IGNNOISE`. Like alpha test this is order independent and stays in the opaque pass, but it supports continuous opacity. The trade-off is visible noise, which resolves into smooth transparency when combined with temporal antialiasing or a high output resolution. [`opacityShadowDither`](https://api.playcanvas.com/engine/classes/StandardMaterial.html#opacityshadowdither) applies the same technique to the shadow the object casts. + +## Alpha To Coverage + +[`alphaToCoverage`](https://api.playcanvas.com/engine/classes/Material.html#alphatocoverage) uses the fragment's alpha to build an MSAA sample coverage mask. Instead of blending, the hardware keeps a proportion of the multi-sample coverage matching the alpha value. + +```javascript +material.blendType = pc.BLEND_NONE; +material.opacity = 0.5; +material.alphaToCoverage = true; +material.update(); +``` + +Blending does not need to be enabled - the alpha is consumed by the coverage mask, much like alpha test. The material stays in the opaque pass and writes depth, which makes the result order independent. + +Quality is bounded by the sample count of the render target. With 4x MSAA, opacity is quantized to 0%, 25%, 50%, 75% and 100%, which is why alpha to coverage works well for softening the sharp edges of an alpha cutout, but is a poor choice for large areas of even semi-transparency, where the quantization is obvious. + +### Requirements + +Alpha to coverage requires a multi-sampled render target and is **silently ignored** when rendering into a single-sampled one. Nothing is logged in release builds and no error is raised - the surface simply renders as fully opaque. If you enable the flag and see no change, check that antialiasing is actually on: + +```javascript +const device = await pc.createGraphicsDevice(canvas, { + deviceTypes: [deviceType], + antialias: true +}); +``` + +On WebGPU there is an additional requirement: the first color attachment of the render target must use a blendable format that has an alpha channel. This matters in practice because [`CameraFrame`](https://api.playcanvas.com/engine/classes/CameraFrame.html) prefers `PIXELFORMAT_111110F` for its HDR render target, and that format has no alpha channel. Alpha to coverage is therefore ignored for geometry rendered through `CameraFrame` with its default formats, and a warning is logged in debug builds. Requesting a format with an alpha channel resolves it: + +```javascript +cameraFrame.rendering.renderFormats = [pc.PIXELFORMAT_RGBA16F]; +cameraFrame.update(); +``` + +WebGL has no equivalent restriction, as it uses the alpha the shader outputs regardless of whether the render target stores an alpha channel. Alpha to coverage therefore still applies on WebGL with formats such as `PIXELFORMAT_111110F`, which is a deliberate difference between the two backends rather than a bug. + +## Choosing an Approach + +| Technique | Opacity | Order dependent | Pass | Main drawback | +|-----------|---------|-----------------|------|---------------| +| Alpha blending | Continuous | Yes | Transparent | Sorting artifacts, no self-sorting | +| Alpha test | Binary | No | Opaque | Hard, aliased edges | +| Opacity dithering | Continuous | No | Opaque | Visible noise without TAA | +| Alpha to coverage | Quantized to sample count | No | Opaque | Needs MSAA, coarse steps | + +As a rough guide, use alpha blending for glass and other genuinely see-through surfaces where quality matters more than ordering; alpha test for dense cutouts; opacity dithering for fades and level-of-detail transitions, especially when temporal antialiasing is already enabled; and alpha to coverage to soften cutout edges when MSAA is already being paid for. diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/advanced-rendering/dual-source-blending.md b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/advanced-rendering/dual-source-blending.md new file mode 100644 index 00000000000..e897b3eb97c --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/advanced-rendering/dual-source-blending.md @@ -0,0 +1,94 @@ +--- +title: デュアルソースブレンディング +description: WebGL 2 と WebGPU で、1 回のブレンド処理に 2 つのフラグメントシェーダー出力を使用します。 +--- + +デュアルソースブレンディングを使用すると、フラグメントシェーダーは 1 つのカラーアタッチメントに対して 2 つのカラーを出力できます。1 つ目のカラーはブレンドされる値で、2 つ目のカラーはブレンド係数として選択できます。これにより、サブピクセルテキストアンチエイリアスや、単一のフラグメント出力では表現できない高度な合成処理を実装できます。 + +## プラットフォームサポート + +デュアルソースブレンディングは、どちらのグラフィックスバックエンドでもオプション機能です。 + +- **WebGPU** は `dual-source-blending` デバイス機能と WGSL 言語拡張を使用します。 +- **WebGL 2** は `WEBGL_blend_func_extended` 拡張を使用します。 + +PlayCanvas は両方を同じケイパビリティフラグで公開します。 + +```javascript +const device = app.graphicsDevice; + +if (!device.supportsDualSourceBlending) { + // フォールバック用のマテリアルまたはレンダリングパスを使用します。 +} +``` + +この機能が利用できる場合、エンジンは `CAPS_DUAL_SOURCE_BLENDING` も定義します。WebGPU では、この機能を使用するフラグメントシェーダーバリアントに `enable dual_source_blending;` を追加します。 + +## ブレンド係数 + +2 つ目のフラグメント出力は、次の 4 つのブレンド係数で参照できます。 + +| ブレンド係数 | 説明 | +|--------------|------| +| `BLENDMODE_SRC1_COLOR` | 2 つ目のソースカラー | +| `BLENDMODE_ONE_MINUS_SRC1_COLOR` | 1 から 2 つ目のソースカラーを引いた値 | +| `BLENDMODE_SRC1_ALPHA` | 2 つ目のソースアルファ | +| `BLENDMODE_ONE_MINUS_SRC1_ALPHA` | 1 から 2 つ目のソースアルファを引いた値 | + +これらの定数は、`device.supportsDualSourceBlending` が true の場合にのみ使用してください。 + +## StandardMaterial + +マテリアルの [`BlendState`](https://api.playcanvas.com/engine/classes/BlendState.html) が 2 つ目のソースを参照する係数を使用すると、デュアルソースブレンディングは自動的に有効になります。マテリアルに個別の設定はありません。ブレンドステートが他の透明度オプションとどのように関係するかについては、[透明度](/user-manual/graphics/transparency) を参照してください。 + +最初に、`outputPS` チャンクをオーバーライドして、1 つ目と 2 つ目のフラグメント出力を書き込みます。両方のグラフィックスバックエンドをサポートする場合は、GLSL 版と WGSL 版の両方を指定します。 + +```javascript +const material = new pc.StandardMaterial(); +material.useLighting = false; +material.useTonemap = false; + +material.getShaderChunks(pc.SHADERLANGUAGE_GLSL).set('outputPS', ` + gl_FragColor = vec4(0.45, 0.02, 0.02, 0.0); + pcFragColorSecondary = vec4(0.0, 0.85, 0.18, 1.0); +`); + +material.getShaderChunks(pc.SHADERLANGUAGE_WGSL).set('outputPS', ` + output.color = vec4f(0.45, 0.02, 0.02, 0.0); + output.colorSecondary = vec4f(0.0, 0.85, 0.18, 1.0); +`); +``` + +次に、ブレンドステートを設定します。この例では、RGB に対して `source0 + destination * source1` を計算します。 + +```javascript +material.blendState = new pc.BlendState( + true, + pc.BLENDEQUATION_ADD, + pc.BLENDMODE_ONE, + pc.BLENDMODE_SRC1_COLOR, + pc.BLENDEQUATION_ADD, + pc.BLENDMODE_ZERO, + pc.BLENDMODE_ONE +); + +material.update(); +``` + +ここで、`gl_FragColor` / `output.color` が `source0`、`pcFragColorSecondary` / `output.colorSecondary` が `source1` です。2 つ目の値はブレンド処理に使用されますが、別のカラーアタッチメントには書き込まれません。 + +## ShaderMaterial + +[`ShaderMaterial`](https://api.playcanvas.com/engine/classes/ShaderMaterial.html) も同じ BlendState ベースの動作を使用します。フラグメントシェーダーで両方の出力を書き込み、2 つ目のソースを参照する係数を含むブレンドステートを割り当てます。エンジンは、そのマテリアル用のデュアルソースシェーダーバリアントを自動的に生成します。 + +`ShaderDefinitionUtils.createDefinition` を直接使用してシェーダー定義を作成する場合は、`useDualSourceBlending: true` を渡します。この低レベルオプションは、StandardMaterial または ShaderMaterial では必要ありません。 + +## 制限事項 + +- レンダーターゲットにはカラーアタッチメントが 1 つだけ必要です。デュアルソースブレンディングを [マルチレンダーターゲット](/user-manual/graphics/advanced-rendering/multiple-render-targets) と組み合わせることはできません。 +- サポート状況はデバイスによって異なるため、2 つ目のソースを参照するブレンド係数を割り当てる前に、必ず `device.supportsDualSourceBlending` を確認してください。 +- デュアルソースブレンディングは、マテリアルおよびドローコールごとに個別に選択されます。同じレンダーパス内の他のマテリアルにデュアルソース出力は必要ありません。 + +## 例 + +[デュアルソースブレンディングの例](https://playcanvas.com/examples/#/test/dual-source-blending)では、白黒のチェッカーボードをレンダリングし、その上にデュアルソースブレンディングを使用する四角形を描画します。黒いセルには赤い 1 つ目の出力のみが適用され、白いセルには緑の 2 つ目の出力も加算されます。 diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/advanced-rendering/index.md b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/advanced-rendering/index.md index 639fc207169..f9da3c5122d 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/advanced-rendering/index.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/advanced-rendering/index.md @@ -1,4 +1,4 @@ --- title: 高度なレンダリング -description: PlayCanvasにおけるバッチング、インスタンシング、マルチドロー、間接描画、複数レンダーターゲットのセクションインデックスです。 +description: PlayCanvasにおけるバッチング、インスタンシング、マルチドロー、間接描画、複数レンダーターゲット、デュアルソースブレンディングのセクションインデックスです。 --- diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/advanced-rendering/multiple-render-targets.md b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/advanced-rendering/multiple-render-targets.md index 82a9566ebc7..6f01afdccdb 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/advanced-rendering/multiple-render-targets.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/advanced-rendering/multiple-render-targets.md @@ -12,6 +12,7 @@ MRTは、PlayCanvasが動作するすべてのデバイス(WebGL2およびWebG - 複数のレンダーターゲットのすべてのカラーアタッチメントは、同じ幅と高さを持ちます。 - すべてのカラーアタッチメントは、[`CameraComponent.clearColor`](https://api.playcanvas.com/engine/classes/CameraComponent.html#clearcolor)を使用して指定された同じ値にクリアされます。 - すべてのカラーアタッチメントは、[`BlendState`](https://api.playcanvas.com/engine/classes/BlendState.html)を使用して指定された同じ書き込みマスクとアルファブレンドモードを使用します。 +- [デュアルソースブレンディング](/user-manual/graphics/advanced-rendering/dual-source-blending)にはカラーアタッチメントが 1 つだけ必要なため、MRT と組み合わせることはできません。 ## MRTの使用方法 diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/shaders/glsl-specifics.md b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/shaders/glsl-specifics.md index 9701f2d9722..749e5d494a7 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/shaders/glsl-specifics.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/shaders/glsl-specifics.md @@ -52,3 +52,9 @@ varying vec2 uv0; `in`/`out` 構文 (GLSL 3.3+ で導入) はサポートされていません。 ::: + +### デュアルソースフラグメント出力 + +マテリアルのブレンドステートが 2 つ目のソースを参照する係数を使用する場合、1 つ目のカラーを `gl_FragColor` に、2 つ目のブレンド値を `pcFragColorSecondary` に書き込みます。WebGL 2 では、エンジンが `GL_EXT_blend_func_extended` を有効にし、両方の出力を自動的に宣言します。 + +ケイパビリティの検出、クロスプラットフォームのシェーダーコード、BlendState の設定については、[デュアルソースブレンディング](/user-manual/graphics/advanced-rendering/dual-source-blending) を参照してください。 diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/shaders/wgsl-capabilities.md b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/shaders/wgsl-capabilities.md index 5386b9ece82..55f74eaa727 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/shaders/wgsl-capabilities.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/shaders/wgsl-capabilities.md @@ -61,6 +61,11 @@ output.color = vec4f(vec3f(result), 1.0); - **プリプロセッサ定義:** `CAPS_PRIMITIVE_INDEX` - **シェーダー段階:** フラグメント - **説明:** 簡略 API では、対応端末向けに `FragmentInput` の `primitiveIndex` およびグローバル `pcPrimitiveIndex` +- **`device.supportsDualSourceBlending`** + - **エンジンが注入:** ブレンドステートが 2 つ目のソースを参照する係数を使用するフラグメントシェーダーバリアントに `enable dual_source_blending;` + - **プリプロセッサ定義:** `CAPS_DUAL_SOURCE_BLENDING` + - **シェーダー段階:** フラグメント + - **説明:** ブレンド係数として使用できる 2 つ目のフラグメント出力を提供します。詳細は [デュアルソースブレンディング](/user-manual/graphics/advanced-rendering/dual-source-blending) を参照してください - **`device.supportsSubgroups`** - **エンジンが注入:** `enable subgroups;` - **プリプロセッサ定義:** `CAPS_SUBGROUPS` diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/shaders/wgsl-vertex-fragment-shaders.md b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/shaders/wgsl-vertex-fragment-shaders.md index da23fcc8bb3..81b4a1ae543 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/shaders/wgsl-vertex-fragment-shaders.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/shaders/wgsl-vertex-fragment-shaders.md @@ -133,6 +133,12 @@ fragDepth: @builtin(frag_depth) } ``` +#### デュアルソース出力 + +マテリアルのブレンドステートが 2 つ目のソースを参照する係数を使用する場合、1 つ目のカラーを `output.color` に、2 つ目のブレンド値を `output.colorSecondary` に書き込みます。エンジンは、適切な `@blend_src` 属性を使用してロケーション 0 に両方の出力を生成し、必要な WGSL 拡張を有効にします。 + +デュアルソースブレンディングには、カラーアタッチメントが 1 つだけ必要です。ケイパビリティの検出と BlendState の設定については、[デュアルソースブレンディング](/user-manual/graphics/advanced-rendering/dual-source-blending) を参照してください。 + :::note 整数テクスチャへのレンダリング(`vec4f`以外の出力フォーマット)のサポートはまだ利用できませんが、将来追加される予定です。 diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/transparency.md b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/transparency.md new file mode 100644 index 00000000000..e1ef57afc43 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/graphics/transparency.md @@ -0,0 +1,132 @@ +--- +title: 透明度 +description: "PlayCanvasで透明なサーフェスをレンダリングする方法(アルファブレンディング、アルファテスト、不透明度のディザリング、アルファトゥカバレッジ)を比較し、それぞれの使いどころを説明します。" +--- + +PlayCanvasには、完全に不透明ではないサーフェスをレンダリングする方法がいくつかあります。それぞれコスト、描画順への依存度、発生するアーティファクトの種類が異なるため、何をレンダリングするかによって適切な選択が変わります。 + +いずれの方法も、マテリアルの不透明度によって制御されます。不透明度は[`StandardMaterial#opacity`](https://api.playcanvas.com/engine/classes/StandardMaterial.html#opacity)、[`opacityMap`](https://api.playcanvas.com/engine/classes/StandardMaterial.html#opacitymap)、または頂点カラーから取得されます。 + +## アルファブレンディング + +[`blendType`](https://api.playcanvas.com/engine/classes/Material.html#blendtype)に`BLEND_NORMAL`などのブレンドモードを設定すると、サーフェスはフレームバッファに既に存在する内容と混合されます。 + +```javascript +material.blendType = pc.BLEND_NORMAL; +material.opacity = 0.5; +material.update(); +``` + +これは最も滑らかな結果が得られ、任意の不透明度の値をサポートしますが、描画順に依存します。ブレンドされるジオメトリは不透明なジオメトリの後の透明パスで描画され、[`Layer#transparentSortMode`](https://api.playcanvas.com/engine/classes/Layer.html#transparentsortmode)に従ってレイヤーごとに奥から手前へソートされます。ソートはメッシュインスタンス単位で行われるため、自身と重なる単一のメッシュを正しく解決することはできません。これは、植生、髪、ガラスでアーティファクトが発生する一般的な原因です。また、ブレンドされるマテリアルは通常デプス書き込みを無効にするため、互いを遮蔽しません。 + +### ブレンドステート + +`blendType`は、よく使われるいくつかの設定に対する便利な短縮形です。完全に制御するには、[`BlendState`](https://api.playcanvas.com/engine/classes/BlendState.html)を[`Material#blendState`](https://api.playcanvas.com/engine/classes/Material.html#blendstate)に割り当てます。BlendStateでは、ブレンド式と、カラーおよびアルファのソース係数とデスティネーション係数をそれぞれ個別に指定でき、さらにチャンネルごとのカラー書き込みマスクも指定できます。ブレンドステートを割り当てると、`blendType`で以前に設定した内容は上書きされます。 + +```javascript +// BLEND_NORMAL と同等の設定を明示的に記述したもの +material.blendState = new pc.BlendState( + true, + pc.BLENDEQUATION_ADD, pc.BLENDMODE_SRC_ALPHA, pc.BLENDMODE_ONE_MINUS_SRC_ALPHA +); +material.update(); +``` + +よく使われるステートは定数として用意されています(`BlendState.NOBLEND`、`BlendState.ALPHABLEND`、`BlendState.ADDBLEND`、`BlendState.NOWRITE`)。パフォーマンスを最大限に高めるには、作成後にステートを変更するのではなく、必要なブレンドステートを事前に作成して必要に応じて割り当ててください。 + +なお、ゲッターは読み取り専用のビューを返すため、ブレンディングを変更するにはセッターを使用する必要があります。これにより、マテリアルの透明度とソートの状態が同期されます。 + +```javascript +const state = material.blendState.clone(); +state.setColorWrite(true, true, true, false); +material.blendState = state; +material.update(); +``` + +#### カラーアタッチメントごとのブレンディング + +ブレンドステートは、デフォルトではレンダーターゲットのすべてのカラーアタッチメントに適用されます。[複数のレンダーターゲット](/user-manual/graphics/advanced-rendering/multiple-render-targets)にレンダリングする場合、[`BlendState#setAttachment`](https://api.playcanvas.com/engine/classes/BlendState.html#setattachment)を使用して、インデックス1から7のアタッチメントに個別のブレンドステートと書き込みマスクを設定できます。アタッチメント0はクラスの他のプロパティで設定し、個別のステートが設定されていないアタッチメントはアタッチメント0に従います。 + +```javascript +// アタッチメント1はアタッチメント0のブレンディングを維持しますが、どのチャンネルも書き込みません +const state = material.blendState.clone(); +const noWrite = state.clone(); +noWrite.setColorWrite(false, false, false, false); +state.setAttachment(1, noWrite); +material.blendState = state; +material.update(); +``` + +これには[`GraphicsDevice#supportsIndependentBlending`](https://api.playcanvas.com/engine/classes/GraphicsDevice.html#supportsindependentblending)が必要です。サポートされていないデバイスでは、アタッチメント0のステートがすべてのアタッチメントに使用されます。 + +ブレンドステートで2つ目のソースを参照する係数を使用すると、[デュアルソースブレンディング](/user-manual/graphics/advanced-rendering/dual-source-blending)も有効になります。これにより、フラグメントシェーダーがブレンド係数として使用される2つ目のカラーを出力できます。 + +## アルファテスト + +[`alphaTest`](https://api.playcanvas.com/engine/classes/Material.html#alphatest)は、不透明度がしきい値を下回るフラグメントを破棄します。 + +```javascript +material.alphaTest = 0.5; +material.update(); +``` + +結果は二値になります。つまりフラグメントは完全に不透明か、破棄されるかのどちらかです。そのためソートが不要で、マテリアルは不透明パスに留まり、通常どおりデプスに書き込みます。これにより低コストで描画順に完全に依存しなくなりますが、切り抜きのエッジは硬くエイリアスが目立ちます。部分的な不透明度が不要な、密度の高い植生などの切り抜き表現で通常選ばれる方法です。 + +## 不透明度のディザリング + +[`opacityDither`](https://api.playcanvas.com/engine/classes/StandardMaterial.html#opacitydither)は、不透明度をブレンドする代わりに、一定の割合のフラグメントを破棄するスクリーンスペースのディザパターンに変換します。 + +```javascript +material.blendType = pc.BLEND_NONE; +material.opacity = 0.5; +material.opacityDither = pc.DITHER_BAYER8; +material.update(); +``` + +使用できるパターンは`DITHER_BAYER2`、`DITHER_BAYER4`、`DITHER_BAYER8`、`DITHER_BAYER16`、`DITHER_BLUENOISE`、`DITHER_IGNNOISE`です。アルファテストと同様に描画順に依存せず不透明パスに留まりますが、連続的な不透明度をサポートします。その代償としてノイズが見えますが、テンポラルアンチエイリアシングや高い出力解像度と組み合わせることで滑らかな透明表現に解消されます。[`opacityShadowDither`](https://api.playcanvas.com/engine/classes/StandardMaterial.html#opacityshadowdither)は、オブジェクトが落とすシャドウに同じ手法を適用します。 + +## アルファトゥカバレッジ + +[`alphaToCoverage`](https://api.playcanvas.com/engine/classes/Material.html#alphatocoverage)は、フラグメントのアルファ値を使用してMSAAのサンプルカバレッジマスクを構築します。ブレンドの代わりに、ハードウェアがアルファ値に応じた割合のマルチサンプルカバレッジを保持します。 + +```javascript +material.blendType = pc.BLEND_NONE; +material.opacity = 0.5; +material.alphaToCoverage = true; +material.update(); +``` + +ブレンドを有効にする必要はありません。アルファテストと同様に、アルファ値はカバレッジマスクによって消費されます。マテリアルは不透明パスに留まりデプスに書き込むため、結果は描画順に依存しません。 + +品質はレンダーターゲットのサンプル数によって制限されます。4x MSAAの場合、不透明度は0%、25%、50%、75%、100%に量子化されます。そのため、アルファトゥカバレッジはアルファによる切り抜きの硬いエッジを滑らかにするのには適していますが、量子化が目立つ広い面積の半透明表現には適していません。 + +### 要件 + +アルファトゥカバレッジにはマルチサンプルのレンダーターゲットが必要で、シングルサンプルのレンダーターゲットにレンダリングする場合は**何も通知されずに無視されます**。リリースビルドではログも出力されず、エラーも発生せず、サーフェスは単に完全に不透明としてレンダリングされます。このフラグを有効にしても変化が見られない場合は、アンチエイリアシングが実際に有効になっているか確認してください。 + +```javascript +const device = await pc.createGraphicsDevice(canvas, { + deviceTypes: [deviceType], + antialias: true +}); +``` + +WebGPUではさらに要件があります。レンダーターゲットの最初のカラーアタッチメントが、アルファチャンネルを持つブレンド可能なフォーマットを使用している必要があります。これは実際に問題になります。[`CameraFrame`](https://api.playcanvas.com/engine/classes/CameraFrame.html)はHDRレンダーターゲットに`PIXELFORMAT_111110F`を優先しますが、このフォーマットにはアルファチャンネルがありません。そのため、デフォルトのフォーマットの`CameraFrame`を通してレンダリングされるジオメトリではアルファトゥカバレッジは無視され、デバッグビルドでは警告が出力されます。アルファチャンネルを持つフォーマットを要求すれば解決します。 + +```javascript +cameraFrame.rendering.renderFormats = [pc.PIXELFORMAT_RGBA16F]; +cameraFrame.update(); +``` + +WebGLには同等の制限はありません。レンダーターゲットがアルファチャンネルを格納しているかどうかに関係なく、シェーダーが出力したアルファ値を使用するためです。そのためWebGLでは`PIXELFORMAT_111110F`のようなフォーマットでもアルファトゥカバレッジが適用されます。これは2つのバックエンド間の意図的な違いであり、バグではありません。 + +## 手法の選択 + +| 手法 | 不透明度 | 描画順への依存 | パス | 主な欠点 | +|------|----------|----------------|------|----------| +| アルファブレンディング | 連続的 | あり | 透明 | ソートのアーティファクト、自己ソート不可 | +| アルファテスト | 二値 | なし | 不透明 | 硬くエイリアスの目立つエッジ | +| 不透明度のディザリング | 連続的 | なし | 不透明 | TAAがない場合にノイズが見える | +| アルファトゥカバレッジ | サンプル数に量子化 | なし | 不透明 | MSAAが必要、段階が粗い | + +大まかな指針としては、ガラスなど実際に透けて見えるサーフェスで描画順よりも品質が重要な場合はアルファブレンディング、密度の高い切り抜きにはアルファテスト、フェードやLODの遷移(特にテンポラルアンチエイリアシングが既に有効な場合)には不透明度のディザリング、MSAAのコストを既に支払っている場合に切り抜きのエッジを滑らかにするにはアルファトゥカバレッジを使用してください。 diff --git a/sidebars.js b/sidebars.js index dcb58fe65cb..47b29f146db 100644 --- a/sidebars.js +++ b/sidebars.js @@ -800,6 +800,7 @@ const sidebars = { 'user-manual/graphics/physical-rendering/image-based-lighting', ], }, + 'user-manual/graphics/transparency', { type: 'category', label: 'Linear Workflow', @@ -883,6 +884,7 @@ const sidebars = { 'user-manual/graphics/advanced-rendering/hardware-instancing', 'user-manual/graphics/advanced-rendering/multi-draw', 'user-manual/graphics/advanced-rendering/multiple-render-targets', + 'user-manual/graphics/advanced-rendering/dual-source-blending', 'user-manual/graphics/advanced-rendering/indirect-drawing', 'user-manual/graphics/advanced-rendering/html-in-canvas', ],