Skip to content

Commit

Permalink
Material: Add "material.alphaHash" transparency mode (#24271)
Browse files Browse the repository at this point in the history
* Material: Add .alphaHash and .alphaHashScale

Material.alphaHash: Add example

Clean up.

Update builds

Examples: Clean up alpha hash params

Fix background color changes, add GammaCorrectionShader

TAARenderPass: Initialize .accumulateIndex

Alpha Hash: Initialize sampleLevel=0 in example

Avoids flashing from TAARenderPass

Clean up alpha hash example.

Lint

Update builds

Add screenshot

* Material: Move alphahash to separate shader chunks.

* Material: Remove alphaHashScale

* Clean up

* Clean up

* Clean up

* Clean up
  • Loading branch information
donmccurdy authored Jun 12, 2023
1 parent c1c3625 commit 77ba743
Show file tree
Hide file tree
Showing 20 changed files with 121 additions and 0 deletions.
1 change: 1 addition & 0 deletions examples/jsm/postprocessing/TAARenderPass.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class TAARenderPass extends SSAARenderPass {

this.sampleLevel = 0;
this.accumulate = false;
this.accumulateIndex = - 1;

}

Expand Down
1 change: 1 addition & 0 deletions src/loaders/MaterialLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ class MaterialLoader extends Loader {
if ( json.opacity !== undefined ) material.opacity = json.opacity;
if ( json.transparent !== undefined ) material.transparent = json.transparent;
if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest;
if ( json.alphaHash !== undefined ) material.alphaHash = json.alphaHash;
if ( json.depthTest !== undefined ) material.depthTest = json.depthTest;
if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite;
if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite;
Expand Down
3 changes: 3 additions & 0 deletions src/materials/Material.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class Material extends EventDispatcher {

this.opacity = 1;
this.transparent = false;
this.alphaHash = false;

this.blendSrc = SrcAlphaFactor;
this.blendDst = OneMinusSrcAlphaFactor;
Expand Down Expand Up @@ -353,6 +354,7 @@ class Material extends EventDispatcher {
if ( this.dithering === true ) data.dithering = true;

if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
if ( this.alphaHash === true ) data.alphaHash = this.alphaHash;
if ( this.alphaToCoverage === true ) data.alphaToCoverage = this.alphaToCoverage;
if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha;
if ( this.forceSinglePass === true ) data.forceSinglePass = this.forceSinglePass;
Expand Down Expand Up @@ -474,6 +476,7 @@ class Material extends EventDispatcher {
this.dithering = source.dithering;

this.alphaTest = source.alphaTest;
this.alphaHash = source.alphaHash;
this.alphaToCoverage = source.alphaToCoverage;
this.premultipliedAlpha = source.premultipliedAlpha;
this.forceSinglePass = source.forceSinglePass;
Expand Down
4 changes: 4 additions & 0 deletions src/renderers/shaders/ShaderChunk.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import alphahash_fragment from './ShaderChunk/alphahash_fragment.glsl.js';
import alphahash_pars_fragment from './ShaderChunk/alphahash_pars_fragment.glsl.js';
import alphamap_fragment from './ShaderChunk/alphamap_fragment.glsl.js';
import alphamap_pars_fragment from './ShaderChunk/alphamap_pars_fragment.glsl.js';
import alphatest_fragment from './ShaderChunk/alphatest_fragment.glsl.js';
Expand Down Expand Up @@ -121,6 +123,8 @@ import * as shadow from './ShaderLib/shadow.glsl.js';
import * as sprite from './ShaderLib/sprite.glsl.js';

export const ShaderChunk = {
alphahash_fragment: alphahash_fragment,
alphahash_pars_fragment: alphahash_pars_fragment,
alphamap_fragment: alphamap_fragment,
alphamap_pars_fragment: alphamap_pars_fragment,
alphatest_fragment: alphatest_fragment,
Expand Down
7 changes: 7 additions & 0 deletions src/renderers/shaders/ShaderChunk/alphahash_fragment.glsl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default /* glsl */`
#ifdef USE_ALPHAHASH
if ( diffuseColor.a < getAlphaHashThreshold( vPosition ) ) discard;
#endif
`;
68 changes: 68 additions & 0 deletions src/renderers/shaders/ShaderChunk/alphahash_pars_fragment.glsl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
export default /* glsl */`
#ifdef USE_ALPHAHASH
/**
* See: https://casual-effects.com/research/Wyman2017Hashed/index.html
*/
const float ALPHA_HASH_SCALE = 0.05; // Derived from trials only, and may be changed.
float hash2D( vec2 value ) {
return fract( 1.0e4 * sin( 17.0 * value.x + 0.1 * value.y ) * ( 0.1 + abs( sin( 13.0 * value.y + value.x ) ) ) );
}
float hash3D( vec3 value ) {
return hash2D( vec2( hash2D( value.xy ), value.z ) );
}
float getAlphaHashThreshold( vec3 position ) {
// Find the discretized derivatives of our coordinates
float maxDeriv = max(
length( dFdx( position.xyz ) ),
length( dFdy( position.xyz ) )
);
float pixScale = 1.0 / ( ALPHA_HASH_SCALE * maxDeriv );
// Find two nearest log-discretized noise scales
vec2 pixScales = vec2(
exp2( floor( log2( pixScale ) ) ),
exp2( ceil( log2( pixScale ) ) )
);
// Compute alpha thresholds at our two noise scales
vec2 alpha = vec2(
hash3D( floor( pixScales.x * position.xyz ) ),
hash3D( floor( pixScales.y * position.xyz ) )
);
// Factor to interpolate lerp with
float lerpFactor = fract( log2( pixScale ) );
// Interpolate alpha threshold from noise at two scales
float x = ( 1.0 - lerpFactor ) * alpha.x + lerpFactor * alpha.y;
// Pass into CDF to compute uniformly distrib threshold
float a = min( lerpFactor, 1.0 - lerpFactor );
vec3 cases = vec3(
x * x / ( 2.0 * a * ( 1.0 - a ) ),
( x - 0.5 * a ) / ( 1.0 - a ),
1.0 - ( ( 1.0 - x ) * ( 1.0 - x ) / ( 2.0 * a * ( 1.0 - a ) ) )
);
// Find our final, uniformly distributed alpha threshold (ατ)
float threshold = ( x < ( 1.0 - a ) )
? ( ( x < a ) ? cases.x : cases.y )
: cases.z;
// Avoids ατ == 0. Could also do ατ =1-ατ
return clamp( threshold , 1.0e-6, 1.0 );
}
#endif
`;
6 changes: 6 additions & 0 deletions src/renderers/shaders/ShaderChunk/begin_vertex.glsl.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
export default /* glsl */`
vec3 transformed = vec3( position );
#ifdef USE_ALPHAHASH
vPosition = vec3( position );
#endif
`;
6 changes: 6 additions & 0 deletions src/renderers/shaders/ShaderChunk/common.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ struct GeometricContext {
#endif
};
#ifdef USE_ALPHAHASH
varying vec3 vPosition;
#endif
vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
Expand Down
2 changes: 2 additions & 0 deletions src/renderers/shaders/ShaderLib/depth.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export const fragment = /* glsl */`
#include <map_pars_fragment>
#include <alphamap_pars_fragment>
#include <alphatest_pars_fragment>
#include <alphahash_pars_fragment>
#include <logdepthbuf_pars_fragment>
#include <clipping_planes_pars_fragment>
Expand All @@ -72,6 +73,7 @@ void main() {
#include <map_fragment>
#include <alphamap_fragment>
#include <alphatest_fragment>
#include <alphahash_fragment>
#include <logdepthbuf_fragment>
Expand Down
2 changes: 2 additions & 0 deletions src/renderers/shaders/ShaderLib/distanceRGBA.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ varying vec3 vWorldPosition;
#include <map_pars_fragment>
#include <alphamap_pars_fragment>
#include <alphatest_pars_fragment>
#include <alphahash_pars_fragment>
#include <clipping_planes_pars_fragment>
void main () {
Expand All @@ -62,6 +63,7 @@ void main () {
#include <map_fragment>
#include <alphamap_fragment>
#include <alphatest_fragment>
#include <alphahash_fragment>
float dist = length( vWorldPosition - referencePosition );
dist = ( dist - nearDistance ) / ( farDistance - nearDistance );
Expand Down
2 changes: 2 additions & 0 deletions src/renderers/shaders/ShaderLib/meshbasic.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ uniform float opacity;
#include <map_pars_fragment>
#include <alphamap_pars_fragment>
#include <alphatest_pars_fragment>
#include <alphahash_pars_fragment>
#include <aomap_pars_fragment>
#include <lightmap_pars_fragment>
#include <envmap_common_pars_fragment>
Expand All @@ -76,6 +77,7 @@ void main() {
#include <color_fragment>
#include <alphamap_fragment>
#include <alphatest_fragment>
#include <alphahash_fragment>
#include <specularmap_fragment>
ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );
Expand Down
2 changes: 2 additions & 0 deletions src/renderers/shaders/ShaderLib/meshlambert.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ uniform float opacity;
#include <map_pars_fragment>
#include <alphamap_pars_fragment>
#include <alphatest_pars_fragment>
#include <alphahash_pars_fragment>
#include <aomap_pars_fragment>
#include <lightmap_pars_fragment>
#include <emissivemap_pars_fragment>
Expand Down Expand Up @@ -92,6 +93,7 @@ void main() {
#include <color_fragment>
#include <alphamap_fragment>
#include <alphatest_fragment>
#include <alphahash_fragment>
#include <specularmap_fragment>
#include <normal_fragment_begin>
#include <normal_fragment_maps>
Expand Down
2 changes: 2 additions & 0 deletions src/renderers/shaders/ShaderLib/meshmatcap.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ varying vec3 vViewPosition;
#include <map_pars_fragment>
#include <alphamap_pars_fragment>
#include <alphatest_pars_fragment>
#include <alphahash_pars_fragment>
#include <fog_pars_fragment>
#include <normal_pars_fragment>
#include <bumpmap_pars_fragment>
Expand All @@ -76,6 +77,7 @@ void main() {
#include <color_fragment>
#include <alphamap_fragment>
#include <alphatest_fragment>
#include <alphahash_fragment>
#include <normal_fragment_begin>
#include <normal_fragment_maps>
Expand Down
2 changes: 2 additions & 0 deletions src/renderers/shaders/ShaderLib/meshphong.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ uniform float opacity;
#include <map_pars_fragment>
#include <alphamap_pars_fragment>
#include <alphatest_pars_fragment>
#include <alphahash_pars_fragment>
#include <aomap_pars_fragment>
#include <lightmap_pars_fragment>
#include <emissivemap_pars_fragment>
Expand Down Expand Up @@ -94,6 +95,7 @@ void main() {
#include <color_fragment>
#include <alphamap_fragment>
#include <alphatest_fragment>
#include <alphahash_fragment>
#include <specularmap_fragment>
#include <normal_fragment_begin>
#include <normal_fragment_maps>
Expand Down
2 changes: 2 additions & 0 deletions src/renderers/shaders/ShaderLib/meshphysical.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ varying vec3 vViewPosition;
#include <map_pars_fragment>
#include <alphamap_pars_fragment>
#include <alphatest_pars_fragment>
#include <alphahash_pars_fragment>
#include <aomap_pars_fragment>
#include <lightmap_pars_fragment>
#include <emissivemap_pars_fragment>
Expand Down Expand Up @@ -165,6 +166,7 @@ void main() {
#include <color_fragment>
#include <alphamap_fragment>
#include <alphatest_fragment>
#include <alphahash_fragment>
#include <roughnessmap_fragment>
#include <metalnessmap_fragment>
#include <normal_fragment_begin>
Expand Down
2 changes: 2 additions & 0 deletions src/renderers/shaders/ShaderLib/meshtoon.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ uniform float opacity;
#include <map_pars_fragment>
#include <alphamap_pars_fragment>
#include <alphatest_pars_fragment>
#include <alphahash_pars_fragment>
#include <aomap_pars_fragment>
#include <lightmap_pars_fragment>
#include <emissivemap_pars_fragment>
Expand Down Expand Up @@ -88,6 +89,7 @@ void main() {
#include <color_fragment>
#include <alphamap_fragment>
#include <alphatest_fragment>
#include <alphahash_fragment>
#include <normal_fragment_begin>
#include <normal_fragment_maps>
#include <emissivemap_fragment>
Expand Down
2 changes: 2 additions & 0 deletions src/renderers/shaders/ShaderLib/points.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ uniform float opacity;
#include <color_pars_fragment>
#include <map_particle_pars_fragment>
#include <alphatest_pars_fragment>
#include <alphahash_pars_fragment>
#include <fog_pars_fragment>
#include <logdepthbuf_pars_fragment>
#include <clipping_planes_pars_fragment>
Expand All @@ -71,6 +72,7 @@ void main() {
#include <map_particle_fragment>
#include <color_fragment>
#include <alphatest_fragment>
#include <alphahash_fragment>
outgoingLight = diffuseColor.rgb;
Expand Down
2 changes: 2 additions & 0 deletions src/renderers/shaders/ShaderLib/sprite.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ uniform float opacity;
#include <map_pars_fragment>
#include <alphamap_pars_fragment>
#include <alphatest_pars_fragment>
#include <alphahash_pars_fragment>
#include <fog_pars_fragment>
#include <logdepthbuf_pars_fragment>
#include <clipping_planes_pars_fragment>
Expand All @@ -67,6 +68,7 @@ void main() {
#include <map_fragment>
#include <alphamap_fragment>
#include <alphatest_fragment>
#include <alphahash_fragment>
outgoingLight = diffuseColor.rgb;
Expand Down
2 changes: 2 additions & 0 deletions src/renderers/webgl/WebGLProgram.js
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
parameters.alphaHash ? '#define USE_ALPHAHASH' : '',

parameters.transmission ? '#define USE_TRANSMISSION' : '',
parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
Expand Down Expand Up @@ -730,6 +731,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {

parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
parameters.alphaTest ? '#define USE_ALPHATEST' : '',
parameters.alphaHash ? '#define USE_ALPHAHASH' : '',

parameters.sheen ? '#define USE_SHEEN' : '',
parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '',
Expand Down
3 changes: 3 additions & 0 deletions src/renderers/webgl/WebGLPrograms.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities

const HAS_ALPHATEST = material.alphaTest > 0;

const HAS_ALPHAHASH = !! material.alphaHash;

const HAS_EXTENSIONS = !! material.extensions;

const HAS_ATTRIBUTE_UV1 = !! geometry.attributes.uv1;
Expand Down Expand Up @@ -232,6 +234,7 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities

alphaMap: HAS_ALPHAMAP,
alphaTest: HAS_ALPHATEST,
alphaHash: HAS_ALPHAHASH,

combine: material.combine,

Expand Down

0 comments on commit 77ba743

Please sign in to comment.