فهرست منبع

added JS MRT support

Nicolas Cannasse 9 سال پیش
والد
کامیت
9c14765713
2فایلهای تغییر یافته به همراه72 افزوده شده و 15 حذف شده
  1. 38 3
      h3d/impl/GlDriver.hx
  2. 34 12
      hxsl/GlslOut.hx

+ 38 - 3
h3d/impl/GlDriver.hx

@@ -72,6 +72,7 @@ class GlDriver extends Driver {
 
 	#if js
 	var canvas : js.html.CanvasElement;
+	var mrtExt : { function drawBuffersWEBGL( colors : Array<Int> ) : Void; }
 	public var gl : js.html.webgl.RenderingContext;
 	#elseif cpp
 	var fixMult : Bool;
@@ -87,6 +88,7 @@ class GlDriver extends Driver {
 	var bufferWidth : Int;
 	var bufferHeight : Int;
 	var curTarget : h3d.mat.Texture;
+	var numTargets : Int;
 
 	public function new() {
 		#if (nme || openfl || lime)
@@ -719,7 +721,19 @@ class GlDriver extends Driver {
 		}
 	}
 
+	inline function unbindTargets() {
+		if( curTarget != null && numTargets > 1 ) {
+			while( numTargets > 1 )
+				gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0 + (--numTargets), GL.TEXTURE_2D, null, 0);
+			#if js
+			if( mrtExt != null )
+				mrtExt.drawBuffersWEBGL([GL.COLOR_ATTACHMENT0]);
+			#end
+		}
+	}
+
 	override function setRenderTarget( tex : h3d.mat.Texture ) {
+		unbindTargets();
 		curTarget = tex;
 		if( tex == null ) {
 			gl.bindFramebuffer(GL.FRAMEBUFFER, null);
@@ -733,8 +747,29 @@ class GlDriver extends Driver {
 		gl.viewport(0, 0, tex.width, tex.height);
 	}
 
-	override public function setRenderTargets( textures : Array<h3d.mat.Texture> )  {
-		throw "TODO";
+	override function setRenderTargets( textures : Array<h3d.mat.Texture> ) {
+		unbindTargets();
+		if( textures.length < 2 ) {
+			setRenderTarget(textures[0]);
+			return;
+		}
+		curTarget = textures[0];
+		numTargets = textures.length;
+		for( tex in textures ) {
+			if( tex.t == null )
+				tex.alloc();
+			if( tex == curTarget ) {
+				gl.bindFramebuffer(GL.FRAMEBUFFER, curTarget.t.fb);
+				gl.viewport(0, 0, tex.width, tex.height);
+			} else {
+				gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0 + textures.indexOf(tex), GL.TEXTURE_2D, tex.t.t, 0);
+			}
+			tex.lastFrame = frame;
+		}
+		#if js
+		if( mrtExt != null )
+			mrtExt.drawBuffersWEBGL([for( i in 0...textures.length ) GL.COLOR_ATTACHMENT0 + i]);
+		#end
 	}
 
 	override function init( onCreate : Bool -> Void, forceSoftware = false ) {
@@ -763,7 +798,7 @@ class GlDriver extends Driver {
 		case FloatTextures:
 			gl.getExtension('OES_texture_float') != null && gl.getExtension('OES_texture_float_linear') != null;
 		case MultipleRenderTargets:
-			gl.getExtension('WEBGL_draw_buffers') != null;
+			mrtExt != null || (mrtExt = gl.getExtension('WEBGL_draw_buffers')) != null;
 		#end
 		case PerTargetDepthBuffer:
 			true;

+ 34 - 12
hxsl/GlslOut.hx

@@ -34,6 +34,7 @@ class GlslOut {
 	var decls : Array<String>;
 	var isVertex : Bool;
 	var allNames : Map<String, Int>;
+	var outIndexes : Map<Int, Int>;
 	public var varNames : Map<Int,String>;
 	public var flipY : Bool;
 
@@ -54,7 +55,10 @@ class GlslOut {
 	function decl( s : String ) {
 		for( d in decls )
 			if( d == s ) return;
-		decls.push(s);
+		if( s.charCodeAt(0) == '#'.code )
+			decls.unshift(s);
+		else
+			decls.push(s);
 	}
 
 	function addType( t : Type ) {
@@ -372,8 +376,13 @@ class GlslOut {
 	}
 
 	function varName( v : TVar ) {
-		if( v.kind == Output )
-			return isVertex ? "gl_Position" : "gl_FragColor";
+		if( v.kind == Output ) {
+			if( isVertex )
+				return "gl_Position";
+			if( outIndexes == null )
+				return "gl_FragColor";
+			return 'gl_FragData[${outIndexes.get(v.id)}]';
+		}
 		var n = varNames.get(v.id);
 		if( n != null )
 			return n;
@@ -398,19 +407,14 @@ class GlslOut {
 		buf = new StringBuf();
 		exprValues = [];
 
-		//#if GL_ES_VERSION_2_0  would be the test to use at compilation time, but would require a GL context to call glGetString (GL_SHADING_LANGUAGE_VERSION)
-		//#ifdef GL_ES is to test in the shader itself but #version  muse be declared first
-		#if((cpp && mobile)||js)
-		decls.push("#version 100");
-		#else
-		decls.push("#version 130");
-		#end
-		decls.push("precision mediump float;");
+		decl("precision mediump float;");
 
 		if( s.funs.length != 1 ) throw "assert";
 		var f = s.funs[0];
 		isVertex = f.kind == Vertex;
 
+		var outIndex = 0;
+		outIndexes = new Map();
 		for( v in s.vars ) {
 			switch( v.kind ) {
 			case Param, Global:
@@ -419,7 +423,11 @@ class GlslOut {
 				add("attribute ");
 			case Var:
 				add("varying ");
-			case Function, Output: continue;
+			case Output:
+				outIndexes.set(v.id, outIndex++);
+				continue;
+			case Function:
+				continue;
 			case Local:
 			}
 			if( v.qualifiers != null )
@@ -438,6 +446,11 @@ class GlslOut {
 		}
 		add("\n");
 
+		if( outIndex < 2 )
+			outIndexes = null;
+		else if( !isVertex )
+			decl("#extension GL_EXT_draw_buffers : enable");
+
 		var tmp = buf;
 		buf = new StringBuf();
 		add("void main(void) {\n");
@@ -465,6 +478,15 @@ class GlslOut {
 			add(e);
 			add("\n\n");
 		}
+
+		//#if GL_ES_VERSION_2_0  would be the test to use at compilation time, but would require a GL context to call glGetString (GL_SHADING_LANGUAGE_VERSION)
+		//#ifdef GL_ES is to test in the shader itself but #version  muse be declared first
+		#if((cpp && mobile)||js)
+		decl("#version 100");
+		#else
+		decl("#version 130");
+		#end
+
 		decls.push(buf.toString());
 		buf = null;
 		return decls.join("\n");