Ver Fonte

added automatic mipmap generation, fixed cube texture / mipmaps on directx

ncannasse há 8 anos atrás
pai
commit
96e1520324
6 ficheiros alterados com 68 adições e 10 exclusões
  1. 20 7
      h3d/impl/DirectXDriver.hx
  2. 4 0
      h3d/impl/Driver.hx
  3. 9 1
      h3d/impl/GlDriver.hx
  4. 4 0
      h3d/mat/Data.hx
  5. 14 0
      h3d/mat/Texture.hx
  6. 17 2
      samples/CubeTexture.hx

+ 20 - 7
h3d/impl/DirectXDriver.hx

@@ -259,7 +259,10 @@ class DirectXDriver extends h3d.impl.Driver {
 
 	override function allocTexture(t:h3d.mat.Texture):Texture {
 
-		var mips = 1; // todo
+		var mips = 1;
+		if( t.flags.has(MipMapped) ) {
+			while( t.width >= 1 << mips || t.height >= 1 << mips ) mips++;
+		}
 
 		var rt = t.flags.has(Target);
 		var isCube = t.flags.has(Cube);
@@ -270,11 +273,16 @@ class DirectXDriver extends h3d.impl.Driver {
 		desc.format = getTextureFormat(t);
 		desc.usage = Default;
 		desc.bind = ShaderResource;
+		desc.mipLevels = mips;
 		if( rt )
 			desc.bind |= RenderTarget;
 		if( isCube ) {
 			desc.arraySize = 6;
-			desc.misc = TextureCube;
+			desc.misc |= TextureCube;
+		}
+		if( t.flags.has(MipMapped) && !t.flags.has(ManualMipMapGen) ) {
+			desc.bind |= RenderTarget;
+			desc.misc |= GenerateMips;
 		}
 		var tex = Driver.createTexture2d(desc);
 		if( tex == null )
@@ -307,6 +315,10 @@ class DirectXDriver extends h3d.impl.Driver {
 		i.res.release();
 	}
 
+	override function generateMipMaps(texture:h3d.mat.Texture) {
+		Driver.generateMips(texture.t.view);
+	}
+
 	function updateBuffer( res : dx.Resource, bytes : hl.Bytes, startByte : Int, bytesCount : Int ) {
 		box.left = startByte;
 		box.top = 0;
@@ -342,6 +354,7 @@ class DirectXDriver extends h3d.impl.Driver {
 
 	override function uploadTexturePixels(t:h3d.mat.Texture, pixels:hxd.Pixels, mipLevel:Int, side:Int) {
 		pixels.convert(RGBA);
+		if( mipLevel >= t.t.mips ) throw "Mip level outside texture range : " + mipLevel + " (max = " + (t.t.mips - 1) + ")";
 		t.t.res.updateSubresource(mipLevel + side * t.t.mips, null, pixels.bytes, pixels.width << 2, 0);
 		updateResCount++;
 	}
@@ -701,11 +714,11 @@ class DirectXDriver extends h3d.impl.Driver {
 				t.lastFrame = frame;
 
 				var view = t.t.view;
-				if( view == state.resources[i] ) continue;
-
-				state.resources[i] = view;
-				max = i;
-				if( start < 0 ) start = i;
+				if( view != state.resources[i] ) {
+					state.resources[i] = view;
+					max = i;
+					if( start < 0 ) start = i;
+				}
 
 				var bits = @:privateAccess t.bits;
 				if( bits != state.samplerBits[i] ) {

+ 4 - 0
h3d/impl/Driver.hx

@@ -118,6 +118,10 @@ class Driver {
 		#end
 	}
 
+	public function generateMipMaps( texture : h3d.mat.Texture ) {
+		throw "Mipmaps auto generation is not supported on this platform";
+	}
+
 	public function getNativeShaderCode( shader : hxsl.RuntimeShader ) : String {
 		return null;
 	}

+ 9 - 1
h3d/impl/GlDriver.hx

@@ -431,7 +431,8 @@ class GlDriver extends Driver {
 			if( cull == 0 )
 				gl.disable(GL.CULL_FACE);
 			else {
-				if( Pass.getCulling(curMatBits) == 0 ) gl.enable(GL.CULL_FACE);
+				if( curMatBits < 0 || Pass.getCulling(curMatBits) == 0 )
+					gl.enable(GL.CULL_FACE);
 				gl.cullFace(FACES[cull]);
 			}
 		}
@@ -746,6 +747,13 @@ class GlDriver extends Driver {
 		gl.deleteBuffer(v.b);
 	}
 
+	override function generateMipMaps( t : h3d.mat.Texture ) {
+		var bind = t.flags.has(Cube) ? GL.TEXTURE_CUBE_MAP : GL.TEXTURE_2D;
+		gl.bindTexture(bind, t.t.t);
+		gl.generateMipmap(bind);
+		gl.bindTexture(bind, null);
+	}
+
 	override function uploadTextureBitmap( t : h3d.mat.Texture, bmp : hxd.BitmapData, mipLevel : Int, side : Int ) {
 	#if (nme || hlsdl || psgl || openfl || lime)
 		var pixels = bmp.getPixels();

+ 4 - 0
h3d/mat/Data.hx

@@ -84,6 +84,10 @@ enum TextureFlags {
 		Activates Mip Mapping for this texture. Might not be available for target textures.
 	**/
 	MipMapped;
+	/**
+		By default, textures created with MipMapped will have their mipmaps generated when you upload the mipmap level 0. This flag disables this and manually upload mipmaps instead.
+	**/
+	ManualMipMapGen;
 	/**
 		This is a not power of two texture. Automatically set when having width or height being not power of two.
 	**/

+ 14 - 0
h3d/mat/Texture.hx

@@ -191,16 +191,30 @@ class Texture {
 		p.dispose();
 	}
 
+	inline function checkSize(width, height, mip) {
+		if( width != this.width >> mip || height != this.height >> mip )
+			throw "Invalid upload size : " + width + "x" + height + " should be " + (this.width >> mip) + "x" + (this.height >> mip);
+	}
+
+	function checkMipMapGen(mipLevel,side) {
+		if( mipLevel == 0 && flags.has(MipMapped) && !flags.has(ManualMipMapGen) && (!flags.has(Cube) || side == 5) )
+			mem.driver.generateMipMaps(this);
+	}
+
 	public function uploadBitmap( bmp : hxd.BitmapData, mipLevel = 0, side = 0 ) {
 		alloc();
+		checkSize(bmp.width, bmp.height, mipLevel);
 		mem.driver.uploadTextureBitmap(this, bmp, mipLevel, side);
 		flags.set(WasCleared);
+		checkMipMapGen(mipLevel, side);
 	}
 
 	public function uploadPixels( pixels : hxd.Pixels, mipLevel = 0, side = 0 ) {
 		alloc();
+		checkSize(pixels.width, pixels.height, mipLevel);
 		mem.driver.uploadTexturePixels(this, pixels, mipLevel, side);
 		flags.set(WasCleared);
+		checkMipMapGen(mipLevel, side);
 	}
 
 	public function dispose() {

+ 17 - 2
samples/CubeTexture.hx

@@ -1,14 +1,19 @@
 class CubeTexture extends hxd.App {
 
+	var skyTexture : h3d.mat.Texture;
+
 	override function init() {
 
-		var skyTexture = new h3d.mat.Texture(128, 128, [Cube]);
+		skyTexture = new h3d.mat.Texture(128, 128, [Cube, MipMapped]);
 		var bmp = hxd.Pixels.alloc(skyTexture.width, skyTexture.height, h3d.mat.Texture.nativeFormat);
 		var faceColors = [0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0x00FFFF, 0xFF00FF];
 		for( i in 0...6 ) {
-			bmp.clear(faceColors[i]);
+			for( x in 0...128 )
+				for( y in 0...128 )
+					bmp.setPixel(x,y, (x + y) & 1 == 0 ? faceColors[i] : (faceColors[i]>>1)&0x7F7F7F);
 			skyTexture.uploadPixels(bmp, 0, i);
 		}
+		skyTexture.mipMap = Linear;
 
 		var sky = new h3d.prim.Sphere(30, 128, 128);
 		sky.addNormals();
@@ -35,6 +40,16 @@ class CubeTexture extends hxd.App {
 
 	}
 
+	override function update(dt:Float) {
+		if( hxd.Key.isPressed("M".code) ) {
+			skyTexture.mipMap = switch( skyTexture.mipMap ) {
+			case None: Nearest;
+			case Nearest: Linear;
+			case Linear: None;
+			}
+		}
+	}
+
 	static function main() {
 		new CubeTexture();
 	}