diff --git a/examples/files.js b/examples/files.js index 0efe36dd30ac76..254e265b9377e5 100644 --- a/examples/files.js +++ b/examples/files.js @@ -135,6 +135,7 @@ var files = { "webgl_materials_texture_manualmipmap", "webgl_materials_texture_pvrtc", "webgl_materials_texture_tga", + "webgl_materials_transparency", "webgl_materials_variations_basic", "webgl_materials_variations_lambert", "webgl_materials_variations_phong", diff --git a/examples/webgl_materials_transparency.html b/examples/webgl_materials_transparency.html new file mode 100644 index 00000000000000..3080bfddfe32e5 --- /dev/null +++ b/examples/webgl_materials_transparency.html @@ -0,0 +1,246 @@ + + + + threejs webgl - materials + + + + + + +
+
threejs - Transparency with Non-Premultipled Alpha (left) versus Premultiplied Alpha (right) with RGBA8 Buffers by Ben Houston.
+ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Three.js b/src/Three.js index 1c91569900d61e..794301c2ac244a 100644 --- a/src/Three.js +++ b/src/Three.js @@ -156,6 +156,7 @@ THREE.AdditiveBlending = 2; THREE.SubtractiveBlending = 3; THREE.MultiplyBlending = 4; THREE.CustomBlending = 5; +THREE.PremultipliedAlphaBlending = 6; // custom blending equations // (numbers start from 100 not to clash with other diff --git a/src/renderers/shaders/ShaderChunk/premultiplied_alpha_fragment.glsl b/src/renderers/shaders/ShaderChunk/premultiplied_alpha_fragment.glsl new file mode 100644 index 00000000000000..555fec0651b46e --- /dev/null +++ b/src/renderers/shaders/ShaderChunk/premultiplied_alpha_fragment.glsl @@ -0,0 +1,6 @@ +#ifdef PREMULTIPLIED_ALPHA + + // Get get normal blending with premultipled, use with CustomBlending, OneFactor, OneMinusSrcAlphaFactor, AddEquation. + gl_FragColor.rgb *= gl_FragColor.a; + +#endif diff --git a/src/renderers/shaders/ShaderLib/linedashed_frag.glsl b/src/renderers/shaders/ShaderLib/linedashed_frag.glsl index b155e8633413b7..36550f5629e52b 100644 --- a/src/renderers/shaders/ShaderLib/linedashed_frag.glsl +++ b/src/renderers/shaders/ShaderLib/linedashed_frag.glsl @@ -30,5 +30,6 @@ void main() { gl_FragColor = linearToOutputTexel( vec4( outgoingLight, diffuseColor.a ) ); #include + #include } diff --git a/src/renderers/shaders/ShaderLib/meshbasic_frag.glsl b/src/renderers/shaders/ShaderLib/meshbasic_frag.glsl index 08cf1d3965ba81..1f48124a2a39dc 100644 --- a/src/renderers/shaders/ShaderLib/meshbasic_frag.glsl +++ b/src/renderers/shaders/ShaderLib/meshbasic_frag.glsl @@ -45,5 +45,6 @@ void main() { gl_FragColor = linearToOutputTexel( vec4( outgoingLight, diffuseColor.a ) ); #include + #include } diff --git a/src/renderers/shaders/ShaderLib/meshlambert_frag.glsl b/src/renderers/shaders/ShaderLib/meshlambert_frag.glsl index 648b42aa39ebd9..65ac4fbf585c82 100644 --- a/src/renderers/shaders/ShaderLib/meshlambert_frag.glsl +++ b/src/renderers/shaders/ShaderLib/meshlambert_frag.glsl @@ -72,5 +72,6 @@ void main() { gl_FragColor = linearToOutputTexel( vec4( outgoingLight, diffuseColor.a ) ); #include + #include } diff --git a/src/renderers/shaders/ShaderLib/meshphong_frag.glsl b/src/renderers/shaders/ShaderLib/meshphong_frag.glsl index f9f91e83aef99a..5bdf2a0658facc 100644 --- a/src/renderers/shaders/ShaderLib/meshphong_frag.glsl +++ b/src/renderers/shaders/ShaderLib/meshphong_frag.glsl @@ -56,5 +56,6 @@ void main() { gl_FragColor = linearToOutputTexel( vec4( outgoingLight, diffuseColor.a ) ); #include + #include } diff --git a/src/renderers/shaders/ShaderLib/meshstandard_frag.glsl b/src/renderers/shaders/ShaderLib/meshstandard_frag.glsl index f658bcfa65647d..385488c742b48e 100644 --- a/src/renderers/shaders/ShaderLib/meshstandard_frag.glsl +++ b/src/renderers/shaders/ShaderLib/meshstandard_frag.glsl @@ -68,5 +68,6 @@ void main() { gl_FragColor = linearToOutputTexel( vec4( outgoingLight, diffuseColor.a ) ); #include + #include } diff --git a/src/renderers/shaders/ShaderLib/points_frag.glsl b/src/renderers/shaders/ShaderLib/points_frag.glsl index 2dbdcadb0060d2..8eae45c6664b43 100644 --- a/src/renderers/shaders/ShaderLib/points_frag.glsl +++ b/src/renderers/shaders/ShaderLib/points_frag.glsl @@ -23,5 +23,6 @@ void main() { gl_FragColor = linearToOutputTexel( vec4( outgoingLight, diffuseColor.a ) ); #include + #include } diff --git a/src/renderers/webgl/WebGLProgram.js b/src/renderers/webgl/WebGLProgram.js index 86a75919e9827a..b9380eea566ca7 100644 --- a/src/renderers/webgl/WebGLProgram.js +++ b/src/renderers/webgl/WebGLProgram.js @@ -491,6 +491,8 @@ THREE.WebGLProgram = ( function () { parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', parameters.pointLightShadows > 0 ? '#define POINT_LIGHT_SHADOWS' : '', + parameters.premultipliedAlpha ? "#define PREMULTIPLIED_ALPHA" : '', + parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', parameters.logarithmicDepthBuffer && renderer.extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '', diff --git a/src/renderers/webgl/WebGLPrograms.js b/src/renderers/webgl/WebGLPrograms.js index 453a6d8f1937e2..3d1929b9d88451 100644 --- a/src/renderers/webgl/WebGLPrograms.js +++ b/src/renderers/webgl/WebGLPrograms.js @@ -21,7 +21,7 @@ THREE.WebGLPrograms = function ( renderer, capabilities ) { "alphaMap", "combine", "vertexColors", "fog", "useFog", "fogExp", "flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning", "maxBones", "useVertexTexture", "morphTargets", "morphNormals", - "maxMorphTargets", "maxMorphNormals", + "maxMorphTargets", "maxMorphNormals", "premultipliedAlpha", "numDirLights", "numPointLights", "numSpotLights", "numHemiLights", "shadowMapEnabled", "pointLightShadows", "shadowMapType", @@ -175,6 +175,7 @@ THREE.WebGLPrograms = function ( renderer, capabilities ) { shadowMapEnabled: renderer.shadowMap.enabled && object.receiveShadow && lights.shadows.length > 0, shadowMapType: renderer.shadowMap.type, + premultipliedAlpha: ( material.blending === THREE.PremultipliedAlphaBlending ), alphaTest: material.alphaTest, doubleSided: material.side === THREE.DoubleSide, flipSided: material.side === THREE.BackSide diff --git a/src/renderers/webgl/WebGLState.js b/src/renderers/webgl/WebGLState.js index 2b0d45488db272..9e12af02b174f2 100644 --- a/src/renderers/webgl/WebGLState.js +++ b/src/renderers/webgl/WebGLState.js @@ -230,6 +230,11 @@ THREE.WebGLState = function ( gl, extensions, paramThreeToGL ) { gl.blendEquation( gl.FUNC_ADD ); gl.blendFunc( gl.ZERO, gl.SRC_COLOR ); + } else if( blending === THREE.PremultipliedAlphaBlending ) { + + gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); + gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); + } else { gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); diff --git a/utils/build/includes/common.json b/utils/build/includes/common.json index 5db2a709ec81eb..6e9c4648d0636a 100644 --- a/utils/build/includes/common.json +++ b/utils/build/includes/common.json @@ -132,7 +132,7 @@ "src/renderers/shaders/ShaderChunk/color_pars_vertex.glsl", "src/renderers/shaders/ShaderChunk/color_vertex.glsl", "src/renderers/shaders/ShaderChunk/common.glsl", - "src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl", + "src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl", "src/renderers/shaders/ShaderChunk/defaultnormal_vertex.glsl", "src/renderers/shaders/ShaderChunk/displacementmap_vertex.glsl", "src/renderers/shaders/ShaderChunk/displacementmap_pars_vertex.glsl", @@ -171,6 +171,7 @@ "src/renderers/shaders/ShaderChunk/morphtarget_vertex.glsl", "src/renderers/shaders/ShaderChunk/normal_fragment.glsl", "src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl", + "src/renderers/shaders/ShaderChunk/premultiplied_alpha_fragment.glsl", "src/renderers/shaders/ShaderChunk/project_vertex.glsl", "src/renderers/shaders/ShaderChunk/roughnessmap_fragment.glsl", "src/renderers/shaders/ShaderChunk/roughnessmap_pars_fragment.glsl",