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",