ソースを参照

flip y before uploading textures in native GL

Nicolas Cannasse 10 年 前
コミット
c817efa4b4
6 ファイル変更54 行追加8 行削除
  1. 5 1
      h3d/impl/GlDriver.hx
  2. 14 0
      h3d/mat/Texture.hx
  3. 1 0
      hxd/BitmapData.hx
  4. 21 0
      hxd/Pixels.hx
  5. 13 5
      hxd/res/Image.hx
  6. 0 2
      hxsl/GlslOut.hx

+ 5 - 1
h3d/impl/GlDriver.hx

@@ -445,7 +445,10 @@ class GlDriver extends Driver {
 		var img = bmp.toNative();
 		gl.bindTexture(GL.TEXTURE_2D, t.t.t);
 		#if hxsdl
-		gl.texImage2D(GL.TEXTURE_2D, mipLevel, GL.RGBA, bmp.width, bmp.height, 0, GL.RGBA, GL.UNSIGNED_BYTE, img.pixels.toData());
+		var pixels = bmp.getPixels();
+		pixels.setFlip(true);
+		gl.texImage2D(GL.TEXTURE_2D, mipLevel, GL.RGBA, bmp.width, bmp.height, 0, GL.RGBA, GL.UNSIGNED_BYTE, pixels.bytes.getData());
+		pixels.dispose();
 		#else
 		gl.texImage2D(GL.TEXTURE_2D, mipLevel, GL.RGBA, GL.RGBA, GL.UNSIGNED_BYTE, img.getImageData(0, 0, bmp.width, bmp.height));
 		#end
@@ -458,6 +461,7 @@ class GlDriver extends Driver {
 		gl.bindTexture(GL.TEXTURE_2D, t.t.t);
 		pixels.convert(RGBA);
 		#if hxsdl
+		pixels.setFlip(true);
 		gl.texImage2D(GL.TEXTURE_2D, mipLevel, GL.RGBA, t.width, t.height, 0, GL.RGBA, GL.UNSIGNED_BYTE, pixels.bytes.getData());
 		#else
 		var pixels = new Uint8Array(pixels.bytes.getData());

+ 14 - 0
h3d/mat/Texture.hx

@@ -6,6 +6,20 @@ class Texture {
 
 	static var UID = 0;
 
+	/**
+		The preferred native format that the Driver will process faster.
+	**/
+	public static var nativeFormat(default,never) : hxd.PixelFormat =
+		#if flash
+			BGRA;
+		#else
+			RGBA; // OpenGL
+		#end
+	/**
+		Tells if the Driver requires y-flipping the texture pixels before uploading.
+	**/
+	public static inline var nativeFlip = #if hxsdl true #else false #end;
+
 	var t : h3d.impl.Driver.Texture;
 	var mem : h3d.impl.MemoryManager;
 	#if debug

+ 1 - 0
hxd/BitmapData.hx

@@ -355,6 +355,7 @@ class BitmapData {
 	}
 
 	public function setPixels( pixels : Pixels ) {
+		pixels.setFlip(false);
 		#if flash
 		var bytes = pixels.bytes.getData();
 		bytes.position = 0;

+ 21 - 0
hxd/Pixels.hx

@@ -3,6 +3,7 @@ package hxd;
 enum Flags {
 	ReadOnly;
 	AlphaPremultiplied;
+	FlipY;
 }
 
 class Pixels {
@@ -55,6 +56,24 @@ class Pixels {
 		flags.unset(ReadOnly);
 	}
 
+	public function setFlip( b : Bool ) {
+		#if js if( b == null ) b = false; #end
+		if( flags.has(FlipY) == b ) return;
+		if( flags.has(ReadOnly) ) copyInner();
+		if( b ) flags.set(FlipY) else flags.unset(FlipY);
+		var stride = width * bytesPerPixel(format);
+		for( y in 0...height >> 1 ) {
+			var p1 = y * stride;
+			var p2 = (height - 1 - y) * stride;
+			for( x in 0...stride ) {
+				var a = bytes.get(p1);
+				var b = bytes.get(p2);
+				bytes.set(p1++, b);
+				bytes.set(p2++, a);
+			}
+		}
+	}
+
 	@:noDebug
 	public function convert( target : PixelFormat ) {
 		if( format == target )
@@ -109,6 +128,7 @@ class Pixels {
 	}
 
 	public function getPixel(x, y) : Int {
+		if( flags.has(FlipY) ) y = height - 1 - y;
 		var p = ((x + y * width) << 2) + offset;
 		switch(format) {
 		case BGRA:
@@ -121,6 +141,7 @@ class Pixels {
 	}
 
 	public function setPixel(x, y, color) : Void {
+		if( flags.has(FlipY) ) y = height - 1 - y;
 		var p = ((x + y * width) << 2) + offset;
 		var a = color >>> 24;
 		var r = (color >> 16) & 0xFF;

+ 13 - 5
hxd/res/Image.hx

@@ -65,19 +65,27 @@ class Image extends Resource {
 		return inf;
 	}
 
-	public function getPixels() {
+	public function getPixels( ?fmt : PixelFormat, ?flipY : Bool ) {
 		getSize();
+		var pixels : hxd.Pixels;
 		if( inf.isPNG ) {
 			var png = new format.png.Reader(new haxe.io.BytesInput(entry.getBytes()));
 			png.checkCRC = false;
-			var pixels = Pixels.alloc(inf.width, inf.height, BGRA);
+			pixels = Pixels.alloc(inf.width, inf.height, BGRA);
+			#if( format >= "3.1.3" )
+			format.png.Tools.extract32(png.read(), pixels.bytes, flipY);
+			if( flipY ) pixels.flags.set(FlipY);
+			#else
 			format.png.Tools.extract32(png.read(), pixels.bytes);
-			return pixels;
+			#end
 		} else {
 			var bytes = entry.getBytes();
 			var p = NanoJpeg.decode(bytes);
-			return new Pixels(p.width,p.height,p.pixels, BGRA);
+			pixels = new Pixels(p.width,p.height,p.pixels, BGRA);
 		}
+		if( fmt != null ) pixels.convert(fmt);
+		if( flipY != null ) pixels.setFlip(flipY);
+		return pixels;
 	}
 
 	public function toBitmap() : hxd.BitmapData {
@@ -104,7 +112,7 @@ class Image extends Resource {
 			function load() {
 				// immediately loading the PNG is faster than going through loadBitmap
 				tex.alloc();
-				var pixels = getPixels();
+				var pixels = getPixels(h3d.mat.Texture.nativeFormat, h3d.mat.Texture.nativeFlip);
 				if( pixels.width != tex.width || pixels.height != tex.height )
 					pixels.makeSquare();
 				tex.uploadPixels(pixels);

+ 0 - 2
hxsl/GlslOut.hx

@@ -37,9 +37,7 @@ class GlslOut {
 	public function new() {
 		varNames = new Map();
 		allNames = new Map();
-		#if js
 		flipY = true;
-		#end
 	}
 
 	inline function add( v : Dynamic ) {