Browse Source

basic stencil buffer interface

Mugen87 9 years ago
parent
commit
1d0e1243ce
2 changed files with 217 additions and 37 deletions
  1. 20 0
      src/Three.js
  2. 197 37
      src/renderers/webgl/WebGLState.js

+ 20 - 0
src/Three.js

@@ -275,6 +275,26 @@ THREE.GreaterEqualDepth = 5;
 THREE.GreaterDepth = 6;
 THREE.NotEqualDepth = 7;
 
+// stencil functions
+
+THREE.NeverStencil = 0;
+THREE.AlwaysStencil = 1;
+THREE.LessStencil = 2;
+THREE.LessEqualStencil = 3;
+THREE.EqualStencil = 4;
+THREE.GreaterEqualStencil = 5;
+THREE.GreaterStencil = 6;
+THREE.NotEqualStencil = 7;
+
+// stencil operations
+
+THREE.KeepStencil = 0;
+THREE.ReplaceStencil = 1;
+THREE.IncrStencil = 2;
+THREE.DecrStencil = 3;
+THREE.InvertStencil = 4;
+THREE.IncrWrapStencil = 5;
+THREE.DecrWrapStencil = 6;
 
 // TEXTURE CONSTANTS
 

+ 197 - 37
src/renderers/webgl/WebGLState.js

@@ -27,6 +27,14 @@ THREE.WebGLState = function ( gl, extensions, paramThreeToGL ) {
 
 	var currentColorWrite = null;
 
+	var currentStencilWrite = null;
+	var currentStencilFunc = null;
+	var currentStencilRef = null;
+	var currentStencilMask = null;
+	var currentStencilFail  = null;
+	var currentStencilZFail = null;
+	var currentStencilZPass = null;
+
 	var currentFlipSided = null;
 
 	var currentLineWidth = null;
@@ -263,59 +271,51 @@ THREE.WebGLState = function ( gl, extensions, paramThreeToGL ) {
 
 		if ( currentDepthFunc !== depthFunc ) {
 
-			if ( depthFunc ) {
-
-				switch ( depthFunc ) {
-
-					case THREE.NeverDepth:
+			switch ( depthFunc ) {
 
-						gl.depthFunc( gl.NEVER );
-						break;
+				case THREE.NeverDepth:
 
-					case THREE.AlwaysDepth:
+					gl.depthFunc( gl.NEVER );
+					break;
 
-						gl.depthFunc( gl.ALWAYS );
-						break;
+				case THREE.AlwaysDepth:
 
-					case THREE.LessDepth:
+					gl.depthFunc( gl.ALWAYS );
+					break;
 
-						gl.depthFunc( gl.LESS );
-						break;
+				case THREE.LessDepth:
 
-					case THREE.LessEqualDepth:
+					gl.depthFunc( gl.LESS );
+					break;
 
-						gl.depthFunc( gl.LEQUAL );
-						break;
+				case THREE.LessEqualDepth:
 
-					case THREE.EqualDepth:
+					gl.depthFunc( gl.LEQUAL );
+					break;
 
-						gl.depthFunc( gl.EQUAL );
-						break;
+				case THREE.EqualDepth:
 
-					case THREE.GreaterEqualDepth:
+					gl.depthFunc( gl.EQUAL );
+					break;
 
-						gl.depthFunc( gl.GEQUAL );
-						break;
+				case THREE.GreaterEqualDepth:
 
-					case THREE.GreaterDepth:
+					gl.depthFunc( gl.GEQUAL );
+					break;
 
-						gl.depthFunc( gl.GREATER );
-						break;
+				case THREE.GreaterDepth:
 
-					case THREE.NotEqualDepth:
+					gl.depthFunc( gl.GREATER );
+					break;
 
-						gl.depthFunc( gl.NOTEQUAL );
-						break;
+				case THREE.NotEqualDepth:
 
-					default:
+					gl.depthFunc( gl.NOTEQUAL );
+					break;
 
-						gl.depthFunc( gl.LEQUAL );
+				default:
 
-				}
-
-			} else {
-
-				gl.depthFunc( gl.LEQUAL );
+					console.error( 'THREE.WebGLState: Invalid depth function: %s', depthFunc );
 
 			}
 
@@ -361,6 +361,115 @@ THREE.WebGLState = function ( gl, extensions, paramThreeToGL ) {
 
 	};
 
+	this.setStencilFunc = function ( stencilFunc, stencilRef, stencilMask ) {
+
+	  if( currentStencilFunc !== stencilFunc ||
+	      currentStencilRef  !== stencilRef  ||
+	      currentStencilMask !== stencilMask ) {
+
+      switch ( stencilFunc ) {
+
+        case THREE.NeverStencil:
+
+          gl.stencilFunc( gl.NEVER,  stencilRef, stencilMask );
+          break;
+
+        case THREE.AlwaysStencil:
+
+          gl.stencilFunc( gl.ALWAYS,  stencilRef, stencilMask );
+          break;
+
+        case THREE.LessStencil:
+
+          gl.stencilFunc( gl.LESS,  stencilRef, stencilMask );
+          break;
+
+        case THREE.LessEqualStencil:
+
+          gl.stencilFunc( gl.LEQUAL,  stencilRef, stencilMask );
+          break;
+
+        case THREE.EqualStencil:
+
+          gl.stencilFunc( gl.EQUAL,  stencilRef, stencilMask );
+          break;
+
+        case THREE.GreaterEqualStencil:
+
+          gl.stencilFunc( gl.GEQUAL,  stencilRef, stencilMask );
+          break;
+
+        case THREE.GreaterStencil:
+
+          gl.stencilFunc( gl.GREATER,  stencilRef, stencilMask );
+          break;
+
+        case THREE.NotEqualStencil:
+
+          gl.stencilFunc( gl.NOTEQUAL,  stencilRef, stencilMask );
+          break;
+
+        default:
+
+          console.error( 'THREE.WebGLState: Invalid stencil function: %s', stencilFunc );
+
+      }
+
+	    currentStencilFunc = stencilFunc;
+	    currentStencilRef  = stencilRef;
+	    currentStencilMask = stencilMask;
+
+	  }
+
+	};
+
+	this.setStencilOp = function ( stencilFail, stencilZFail, stencilZPass ) {
+
+	  var fail, zFail, zPass;
+
+	  if( currentStencilFail  !== stencilFail   ||
+	      currentStencilZFail !== stencilZFail  ||
+	      currentStencilZPass !== stencilZPass ) {
+
+	    fail  = getStencilOp( stencilFail );
+	    zFail = getStencilOp( stencilZFail );
+	    zPass = getStencilOp( stencilZPass )
+
+	    gl.stencilOp( fail,  zFail, zPass );
+
+	    currentStencilFail  = stencilFail;
+	    currentStencilZFail = stencilZFail;
+	    currentStencilZPass = stencilZPass;
+
+	  }
+
+	};
+
+	this.setStencilTest = function ( stencilTest ) {
+
+	  if ( stencilTest ) {
+
+	    this.enable( gl.STENCIL_TEST );
+
+	  } else {
+
+	    this.disable( gl.STENCIL_TEST );
+
+	  }
+
+	};
+
+	this.setStencilWrite = function ( stencilWrite ) {
+
+	  if ( currentStencilWrite !== stencilWrite ) {
+
+	    gl.stencilMask( stencilWrite );
+	    currentStencilWrite = stencilWrite;
+
+	  }
+
+	};
+
 	this.setFlipSided = function ( flipSided ) {
 
 		if ( currentFlipSided !== flipSided ) {
@@ -509,8 +618,6 @@ THREE.WebGLState = function ( gl, extensions, paramThreeToGL ) {
 
 	};
 
-	//
-
 	this.reset = function () {
 
 		for ( var i = 0; i < enabledAttributes.length; i ++ ) {
@@ -537,4 +644,57 @@ THREE.WebGLState = function ( gl, extensions, paramThreeToGL ) {
 
 	};
 
+	// private
+
+	function getStencilOp( stencilOp ){
+
+		var op;
+
+		switch ( stencilOp ) {
+
+			case THREE.KeepStencil:
+
+				op = gl.KEEP;
+				break;
+
+			case THREE.ReplaceStencil:
+
+				op = gl.REPLACE;
+				break;
+
+			case THREE.IncrStencil:
+
+				op = gl.INCR;
+				break;
+
+			case THREE.DecrStencil:
+
+				op = gl.DECR;
+				break;
+
+			case THREE.InvertStencil:
+
+				op = gl.INVERT;
+				break;
+
+			case THREE.IncrWrapStencil:
+
+				op = gl.INCR_WRAP;
+				break;
+
+			case THREE.DecrWrapStencil:
+
+				op = gl.DECR_WRAP;
+				break;
+
+			default:
+
+				console.error( 'THREE.WebGLState: Invalid stencil operation: %s', stencilOp );
+
+		}
+
+		return op;
+
+	}
+
 };