Browse Source

Material: Add alphaToCoverage.

Mugen87 4 years ago
parent
commit
7fdf7b78fc

+ 6 - 0
docs/api/en/materials/Material.html

@@ -36,6 +36,12 @@
 		Default is *0*.
 		</p>
 
+		<h3>[property:Float alphaToCoverage]</h3>
+		<p>
+		Enables alpha to coverage. Can only be used with MSAA-enabled contexts (meaning when the renderer was created with *antialias* parameter set to *true*).
+		Default is *false*.
+		</p>
+
 		<h3>[property:Integer blendDst]</h3>
 		<p>
 		Blending destination. Default is [page:CustomBlendingEquation OneMinusSrcAlphaFactor].

+ 6 - 0
docs/api/zh/materials/Material.html

@@ -28,6 +28,12 @@
 <p>设置运行alphaTest时要使用的alpha值。如果不透明度低于此值,则不会渲染材质。默认值为*0*。
 </p>
 
+<h3>[property:Float alphaToCoverage]</h3>
+<p>
+Enables alpha to coverage. Can only be used with MSAA-enabled contexts (meaning when the renderer was created with *antialias* parameter set to *true*).
+Default is *false*.
+</p>
+
 <h3>[property:Integer blendDst]</h3>
 <p> 混合目标。默认值为[page:CustomBlendingEquation OneMinusSrcAlphaFactor]。
 	目标因子所有可能的取值请参阅[page:CustomBlendingEquation constants]。

BIN
examples/screenshots/webgl_materials_wireframe.jpg


+ 28 - 25
examples/webgl_materials_wireframe.html

@@ -13,8 +13,8 @@
 
 		<script type="x-shader/x-vertex" id="vertexShader">
 
-			attribute vec3 center;
-			varying vec3 vCenter;
+			in vec3 center;
+			out vec3 vCenter;
 
 			void main() {
 
@@ -28,25 +28,26 @@
 
 		<script type="x-shader/x-fragment" id="fragmentShader">
 
-			uniform float widthFactor;
+			uniform float thickness;
 
-			varying vec3 vCenter;
+			in vec3 vCenter;
+			out vec4 outColor;
 
-			float edgeFactorTri() {
+			float aastep( float threshold, float dist ) {
 
-				vec3 d = fwidth( vCenter.xyz );
-
-				vec3 a3 = smoothstep( vec3( 0.0 ), d * widthFactor, vCenter.xyz );
-
-				return min( min( a3.x, a3.y ), a3.z );
+				float afwidth = fwidth( dist ) * 0.5;
+				return smoothstep( threshold - afwidth, threshold + afwidth, dist );
 
 			}
 
 			void main() {
 
-				if ( edgeFactorTri() > 0.99 ) discard;
+				float d = min( min( vCenter.x, vCenter.y ), vCenter.z );
 
-				gl_FragColor = gl_FrontFacing ? vec4( 0.9, 0.9, 1.0, 1.0 ) : vec4( 0.4, 0.4, 0.5, 1.0 );
+				float edge = 1.0 - aastep( thickness, d );
+
+				outColor.rgb = gl_FrontFacing ? vec3( 0.9, 0.9, 1.0 ) : vec3( 0.4, 0.4, 0.5 );
+				outColor.a = edge;
 
 			}
 
@@ -56,13 +57,15 @@
 
 			import * as THREE from '../build/three.module.js';
 
+			import { OrbitControls } from './jsm/controls/OrbitControls.js';
+
 			import { GUI } from './jsm/libs/dat.gui.module.js';
 
 			const API = {
-				widthFactor: 1
+				thickness: 0.01
 			};
 
-			let renderer, scene, camera, mesh1, mesh2;
+			let renderer, scene, camera, mesh2;
 
 			init();
 
@@ -78,6 +81,10 @@
 				camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 500 );
 				camera.position.z = 150;
 
+				const controls = new OrbitControls( camera, renderer.domElement );
+				controls.enablePan = false;
+				controls.enableZoom = false;
+
 				new THREE.BufferGeometryLoader().load( 'models/json/WaltHeadLo_buffergeometry.json', function ( geometry ) {
 
 					// on the left
@@ -89,26 +96,26 @@
 
 					} );
 
-					mesh1 = new THREE.Mesh( geometry, material1 );
+					const mesh1 = new THREE.Mesh( geometry, material1 );
 					mesh1.position.set( - 40, 0, 0 );
 
 					scene.add( mesh1 );
 
 					// on the right
 
-					const uniforms = { 'widthFactor': { value: API.widthFactor } };
+					const uniforms = { 'thickness': { value: API.thickness } };
 
 					const material2 = new THREE.ShaderMaterial( {
 
 						uniforms: uniforms,
 						vertexShader: document.getElementById( 'vertexShader' ).textContent,
 						fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
-						side: THREE.DoubleSide
+						side: THREE.DoubleSide,
+						glslVersion: THREE.GLSL3,
+						alphaToCoverage: true // only works when WebGLRenderer's "antialias" is set to "true"
 
 					} );
 
-					material2.extensions.derivatives = true;
-
 					geometry.deleteAttribute( 'normal' );
 					geometry.deleteAttribute( 'uv' );
 
@@ -129,9 +136,9 @@
 
 				const gui = new GUI();
 
-				gui.add( API, 'widthFactor', 0.4, 4 ).onChange( function () {
+				gui.add( API, 'thickness', 0.01, 0.1 ).onChange( function () {
 
-					mesh2.material.uniforms.widthFactor.value = API.widthFactor;
+					mesh2.material.uniforms.thickness.value = API.thickness;
 
 				} );
 
@@ -177,10 +184,6 @@
 
 				requestAnimationFrame( animate );
 
-				mesh1.rotation.y += 0.01;
-
-				mesh2.rotation.y += 0.01;
-
 				renderer.render( scene, camera );
 
 			}

+ 3 - 0
src/loaders/MaterialLoader.js

@@ -122,6 +122,9 @@ class MaterialLoader extends Loader {
 		if ( json.morphNormals !== undefined ) material.morphNormals = json.morphNormals;
 		if ( json.dithering !== undefined ) material.dithering = json.dithering;
 
+		if ( json.alphaToCoverage !== undefined ) material.alphaToCoverage = json.alphaToCoverage;
+		if ( json.premultipliedAlpha !== undefined ) material.premultipliedAlpha = json.premultipliedAlpha;
+
 		if ( json.vertexTangents !== undefined ) material.vertexTangents = json.vertexTangents;
 
 		if ( json.visible !== undefined ) material.visible = json.visible;

+ 3 - 0
src/materials/Material.js

@@ -59,6 +59,7 @@ function Material() {
 	this.dithering = false;
 
 	this.alphaTest = 0;
+	this.alphaToCoverage = false;
 	this.premultipliedAlpha = false;
 
 	this.visible = true;
@@ -298,6 +299,7 @@ Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 		if ( this.dithering === true ) data.dithering = true;
 
 		if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
+		if ( this.alphaToCoverage === true ) data.alphaToCoverage = this.alphaToCoverage;
 		if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha;
 
 		if ( this.wireframe === true ) data.wireframe = this.wireframe;
@@ -421,6 +423,7 @@ Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 		this.dithering = source.dithering;
 
 		this.alphaTest = source.alphaTest;
+		this.alphaToCoverage = source.alphaToCoverage;
 		this.premultipliedAlpha = source.premultipliedAlpha;
 
 		this.visible = source.visible;

+ 5 - 0
src/renderers/webgl/WebGLState.js

@@ -642,6 +642,10 @@ function WebGLState( gl, extensions, capabilities ) {
 
 		setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
 
+		material.alphaToCoverage === true
+			? enable( gl.SAMPLE_ALPHA_TO_COVERAGE )
+			: disable( gl.SAMPLE_ALPHA_TO_COVERAGE );
+
 	}
 
 	//
@@ -885,6 +889,7 @@ function WebGLState( gl, extensions, capabilities ) {
 		gl.disable( gl.POLYGON_OFFSET_FILL );
 		gl.disable( gl.SCISSOR_TEST );
 		gl.disable( gl.STENCIL_TEST );
+		gl.disable( gl.SAMPLE_ALPHA_TO_COVERAGE );
 
 		gl.blendEquation( gl.FUNC_ADD );
 		gl.blendFunc( gl.ONE, gl.ZERO );

+ 2 - 1
utils/build/rollup.config.js

@@ -152,7 +152,8 @@ function glconstants() {
 		UNPACK_SKIP_IMAGES: 32877,
 		MAX_SAMPLES: 36183,
 		READ_FRAMEBUFFER: 36008,
-		DRAW_FRAMEBUFFER: 36009
+		DRAW_FRAMEBUFFER: 36009,
+		SAMPLE_ALPHA_TO_COVERAGE: 32926
 	};
 
 	return {