소스 검색

remove flip of GL textures at upload/fetch: instead use screenToUv/uvToScreen for uv/screen coordinates transform.

ncannasse 7 년 전
부모
커밋
21a117354b
15개의 변경된 파일53개의 추가작업 그리고 91개의 파일을 삭제
  1. 1 1
      h3d/impl/DirectXDriver.hx
  2. 4 0
      h3d/impl/Driver.hx
  3. 2 8
      h3d/impl/GlDriver.hx
  4. 1 10
      h3d/mat/Texture.hx
  5. 5 4
      h3d/prim/Plane2D.hx
  6. 2 2
      h3d/shader/BaseMesh.hx
  7. 1 2
      h3d/shader/Blur.hx
  8. 1 1
      h3d/shader/SAO.hx
  9. 2 17
      h3d/shader/Shadow.hx
  10. 1 2
      h3d/shader/VolumeDecal.hx
  11. 1 1
      hxd/res/Image.hx
  12. 3 1
      hxsl/Ast.hx
  13. 11 7
      hxsl/Checker.hx
  14. 14 35
      hxsl/GlslOut.hx
  15. 4 0
      hxsl/HlslOut.hx

+ 1 - 1
h3d/impl/DirectXDriver.hx

@@ -665,7 +665,7 @@ class DirectXDriver extends h3d.impl.Driver {
 
 	override function hasFeature(f:Feature) {
 		return switch(f) {
-		case Queries:
+		case Queries, BottomLeftCoords:
 			false;
 		default:
 			true;

+ 4 - 0
h3d/impl/Driver.hx

@@ -91,6 +91,10 @@ enum Feature {
 		Allows advanced shader operations (webgl2, opengl3+, directx 9.0c+)
 	*/
 	ShaderModel3;
+	/*
+		Tells if the driver uses bottom-left coordinates for textures.
+	*/
+	BottomLeftCoords;
 }
 
 enum QueryKind {

+ 2 - 8
h3d/impl/GlDriver.hx

@@ -902,9 +902,6 @@ class GlDriver extends Driver {
 		} else {
 			var img = bmp.toNative();
 			gl.bindTexture(GL.TEXTURE_2D, t.t.t);
-			#if js
-			gl.pixelStorei(GL.UNPACK_FLIP_Y_WEBGL, 1);
-			#end
 			gl.texImage2D(GL.TEXTURE_2D, mipLevel, t.t.internalFmt, getChannels(t.t), t.t.pixelFmt, img.getImageData(0, 0, bmp.width, bmp.height));
 			restoreBind();
 		}
@@ -985,14 +982,12 @@ class GlDriver extends Driver {
 		var face = cubic ? CUBE_FACES[side] : GL.TEXTURE_2D;
 		gl.bindTexture(bind, t.t.t);
 		pixels.convert(t.format);
+		pixels.setFlip(false);
 		#if hl
-		pixels.setFlip(!cubic);
 		gl.texImage2D(face, mipLevel, t.t.internalFmt, pixels.width, pixels.height, 0, getChannels(t.t), t.t.pixelFmt, streamData(pixels.bytes.getData(),pixels.offset,pixels.width*pixels.height*4));
 		#elseif lime
-		pixels.setFlip(!cubic);
 		gl.texImage2D(face, mipLevel, t.t.internalFmt, pixels.width, pixels.height, 0, getChannels(t.t), t.t.pixelFmt, bytesToUint8Array(pixels.bytes));
 		#else
-		gl.pixelStorei(GL.UNPACK_FLIP_Y_WEBGL, cubic ? 0 : 1);
 		gl.texImage2D(face, mipLevel, t.t.internalFmt, pixels.width, pixels.height, 0, getChannels(t.t), t.t.pixelFmt, bytesToUint8Array(pixels.bytes));
 		#end
 		restoreBind();
@@ -1303,7 +1298,7 @@ class GlDriver extends Driver {
 	function checkFeature( f : Feature ) {
 		return switch( f ) {
 
-		case HardwareAccelerated, AllocDepthBuffer:
+		case HardwareAccelerated, AllocDepthBuffer, BottomLeftCoords:
 			true;
 
 		case StandardDerivatives, MultipleRenderTargets, SRGBTextures if( glES >= 3 ):
@@ -1340,7 +1335,6 @@ class GlDriver extends Driver {
 		#if (js || hl)
 		gl.readPixels(0, 0, pixels.width, pixels.height, getChannels(curTarget.t), curTarget.t.pixelFmt, @:privateAccess pixels.bytes.b);
 		@:privateAccess pixels.innerFormat = curTarget.format;
-		if( !curTarget.flags.has(Cube) ) pixels.flags.set(FlipY);
 		#end
 	}
 

+ 1 - 10
h3d/mat/Texture.hx

@@ -15,17 +15,9 @@ class Texture {
 		#elseif (usesys && !hldx && !hlsdl && !usegl)
 			haxe.GraphicsDriver.nativeFormat
 		#else
-			RGBA // OpenGL, WebGL
+			RGBA
 		#end;
 
-	/**
-		Tells if the Driver requires y-flipping the texture pixels before uploading.
-	**/
-	public static inline var nativeFlip = 	#if (hlsdl||usegl) true
-											#elseif (openfl) false
-											#elseif (lime && (cpp || neko || nodejs)) true
-											#else false #end;
-
 	var t : h3d.impl.Driver.Texture;
 	var mem : h3d.impl.MemoryManager;
 	#if debug
@@ -226,7 +218,6 @@ class Texture {
 				p.bytes.set(k++,b);
 				p.bytes.set(k++,a);
 			}
-			if( nativeFlip ) p.flags.set(FlipY);
 			if( layer < 0 ) {
 				for( i in 0...layerCount )
 					uploadPixels(p, 0, i);

+ 5 - 4
h3d/prim/Plane2D.hx

@@ -15,25 +15,26 @@ class Plane2D extends Primitive {
 
 	override function alloc( engine : h3d.Engine ) {
 		var v = new hxd.FloatBuffer();
+		var y = engine.driver.hasFeature(BottomLeftCoords) ? 1. : 0.;
 		v.push( -1);
 		v.push( -1);
 		v.push( 0);
-		v.push( 1);
+		v.push( 1 - y);
 
 		v.push( -1);
 		v.push( 1);
 		v.push( 0);
-		v.push( 0);
+		v.push( y);
 
 		v.push( 1);
 		v.push( -1);
 		v.push( 1);
-		v.push( 1);
+		v.push( 1 - y);
 
 		v.push( 1);
 		v.push( 1);
 		v.push( 1);
-		v.push( 0);
+		v.push( y);
 
 		buffer = h3d.Buffer.ofFloats(v, 4, [Quads, RawFormat]);
 	}

+ 2 - 2
h3d/shader/BaseMesh.hx

@@ -61,14 +61,14 @@ class BaseMesh extends hxsl.Shader {
 			pixelColor = color;
 			specPower = specularPower;
 			specColor = specularColor * specularAmount;
-			screenUV = (projectedPosition.xy / projectedPosition.w) * vec2(0.5, -0.5) + 0.5;
+			screenUV = screenToUv(projectedPosition.xy / projectedPosition.w);
 			depth = projectedPosition.z / projectedPosition.w;
 		}
 
 		function __init__fragment() {
 			transformedNormal = transformedNormal.normalize();
 			// same as __init__, but will force calculus inside fragment shader, which limits varyings
-			screenUV = (projectedPosition.xy / projectedPosition.w) * vec2(0.5, -0.5) + 0.5;
+			screenUV = screenToUv(projectedPosition.xy / projectedPosition.w);
 			depth = projectedPosition.z / projectedPosition.w; // in case it's used in vertex : we don't want to interpolate in screen space
 			specPower = specularPower;
 			specColor = specularColor * specularAmount;

+ 1 - 2
h3d/shader/Blur.hx

@@ -62,8 +62,7 @@ class Blur extends ScreenShader {
 
 		function getPosition( uv : Vec2 ) : Vec3 {
 			var depth = unpack(depthTexture.get(uv));
-			var uv2 = (uv - 0.5) * vec2(2, -2);
-			var temp = vec4(uv2, depth, 1) * cameraInverseViewProj;
+			var temp = vec4(uvToScreen(uv), depth, 1) * cameraInverseViewProj;
 			var originWS = temp.xyz / temp.w;
 			return originWS;
 		}

+ 1 - 1
h3d/shader/SAO.hx

@@ -48,7 +48,7 @@ class SAO extends ScreenShader {
 
 		function getPosition( uv : Vec2 ) : Vec3 {
 			var depth = depthTexture.get(uv);
-			var uv2 = (uv - 0.5) * vec2(2, -2);
+			var uv2 = uvToScreen(uv);
 			var temp = vec4(uv2, depth, 1) * cameraInverseViewProj;
 			var originWS = temp.xyz / temp.w;
 			return originWS;

+ 2 - 17
h3d/shader/Shadow.hx

@@ -14,25 +14,10 @@ class Shadow extends hxsl.Shader {
 		var transformedPosition : Vec3;
 		var pixelTransformedPosition : Vec3;
 		@private var shadowPos : Vec3;
-		@const var perPixel : Bool;
-
-		function vertex() {
-			if( !perPixel ) shadowPos = transformedPosition * shadow.proj * vec3(0.5, -0.5, 1) + vec3(0.5, 0.5, 0);
-		}
 
 		function fragment() {
-
-			var shadowPos = if( perPixel ) pixelTransformedPosition * shadow.proj * vec3(0.5, -0.5, 1) + vec3(0.5, 0.5, 0) else shadowPos;
-
-			var depth = shadow.map.get(shadowPos.xy);
-
-			#if false
-			// TODO : integrate surface-based bias
-			cosTheta = N.L
-			float bias = 0.005*tan(acos(cosTheta));
-			bias = clamp(bias, 0, 0.01)
-			#end
-
+			var shadowPos = pixelTransformedPosition * shadow.proj;
+			var depth = shadow.map.get(screenToUv(shadowPos.xy));
 			var zMax = shadowPos.z.saturate();
 			var delta = (depth + shadow.bias).min(zMax) - zMax;
 			var shade = exp( shadow.power * delta  ).saturate();

+ 1 - 2
h3d/shader/VolumeDecal.hx

@@ -19,10 +19,9 @@ class VolumeDecal extends hxsl.Shader {
 		function fragment() {
 			var matrix = camera.inverseViewProj * global.modelViewInverse;
 			var screenPos = projectedPosition.xy / projectedPosition.w;
-			var tuv = screenPos * vec2(0.5, -0.5) + vec2(0.5, 0.5);
 			var ruv = vec4(
 				screenPos,
-				unpack(depthMap.get(tuv)),
+				unpack(depthMap.get(screenToUv(screenPos))),
 				1
 			);
 			var wpos = ruv * matrix;

+ 1 - 1
hxd/res/Image.hx

@@ -201,7 +201,7 @@ class Image extends Resource {
 			function load() {
 				// immediately loading the PNG is faster than going through loadBitmap
 				tex.alloc();
-				var pixels = getPixels(h3d.mat.Texture.nativeFormat, h3d.mat.Texture.nativeFlip);
+				var pixels = getPixels(h3d.mat.Texture.nativeFormat);
 				if( pixels.width != tex.width || pixels.height != tex.height )
 					pixels.makeSquare();
 				tex.uploadPixels(pixels);

+ 3 - 1
hxsl/Ast.hx

@@ -225,12 +225,14 @@ enum TGlobal {
 	Unpack;
 	PackNormal;
 	UnpackNormal;
+	ScreenToUv;
+	UvToScreen;
 	// extensions
 	DFdx;
 	DFdy;
 	Fwidth;
+	// debug / internal
 	ChannelRead;
-	// debug
 	Trace;
 }
 

+ 11 - 7
hxsl/Checker.hx

@@ -106,20 +106,24 @@ class Checker {
 			case DFdx, DFdy, Fwidth:
 				genFloat;
 			case Pack:
-				[ { args : [ { name : "value", type : TFloat } ], ret : TVec(4, VFloat) } ];
+				[ { args : [ { name : "value", type : TFloat } ], ret : vec4 } ];
 			case Unpack:
-				[ { args : [ { name : "value", type : TVec(4, VFloat) } ], ret : TFloat } ];
+				[ { args : [ { name : "value", type : vec4 } ], ret : TFloat } ];
 			case UnpackNormal:
-				[ { args : [ { name : "value", type : TVec(4, VFloat) } ], ret : TVec(3, VFloat) } ];
+				[ { args : [ { name : "value", type : vec4 } ], ret : vec3 } ];
 			case PackNormal:
-				[ { args : [ { name : "value", type : TVec(3, VFloat) } ], ret : TVec(4, VFloat) } ];
+				[ { args : [ { name : "value", type : vec3 } ], ret : vec4 } ];
 			case ChannelRead:
 				[
 					{ args : [ { name : "channel", type : TChannel(1) }, { name : "uv", type : vec2 } ], ret : TFloat },
-					{ args : [ { name : "channel", type : TChannel(2) }, { name : "uv", type : vec2 } ], ret : TVec(2,VFloat) },
-					{ args : [ { name : "channel", type : TChannel(3) }, { name : "uv", type : vec2 } ], ret : TVec(3,VFloat) },
-					{ args : [ { name : "channel", type : TChannel(4) }, { name : "uv", type : vec2 } ], ret : TVec(4,VFloat) },
+					{ args : [ { name : "channel", type : TChannel(2) }, { name : "uv", type : vec2 } ], ret : vec2 },
+					{ args : [ { name : "channel", type : TChannel(3) }, { name : "uv", type : vec2 } ], ret : vec3 },
+					{ args : [ { name : "channel", type : TChannel(4) }, { name : "uv", type : vec2 } ], ret : vec4 },
 				];
+			case ScreenToUv:
+				[{ args : [{ name : "screenPos", type : vec2 }], ret : vec2 }];
+			case UvToScreen:
+				[{ args : [{ name : "uv", type : vec2 }], ret : vec2 }];
 			case Trace:
 				[];
 			}

+ 14 - 35
hxsl/GlslOut.hx

@@ -44,14 +44,12 @@ class GlslOut {
 	var isES2(get,never) : Bool;
 	var uniformBuffer : Int = 0;
 	public var varNames : Map<Int,String>;
-	public var flipY : Bool;
 	public var glES : Null<Float>;
 	public var version : Null<Int>;
 
 	public function new() {
 		varNames = new Map();
 		allNames = new Map();
-		flipY = true;
 	}
 
 	inline function get_isES() return glES != null;
@@ -225,44 +223,21 @@ class GlslOut {
 			decl("vec3 unpackNormal( vec4 v ) { return normalize((v.xyz - vec3(0.5)) * vec3(2.)); }");
 		case Texture:
 			switch( args[0].t ) {
-			case TSampler2D, TSampler2DArray, TChannel(_) if( !flipY ):
-				if( isES2 )
-					return "texture2D";
-			case TSampler2D, TChannel(_):
-				// convert S/T (bottom left) to U/V (top left)
-				// we don't use 1. because of pixel rounding (fixes artifacts in blur)
-				decl('vec4 _texture2D( sampler2D t, vec2 v ) { return ${isES2?"texture2D":"texture"}(t,vec2(v.x,0.999999-v.y)); }');
-				return "_texture2D";
-			case TSampler2DArray:
-				decl('vec4 _texture2DArr( sampler2DArray t, vec3 v ) { return texture(t,vec3(v.x,0.999999-v.y,v.z)); }');
-				return "_texture2DArr";
-			case TSamplerCube:
-				if( isES2 )
-					return "textureCube";
+			case TSampler2D, TSampler2DArray, TChannel(_) if( isES2 ):
+				return "texture2D";
+			case TSamplerCube if( isES2 ):
+				return "textureCube";
 			default:
-				throw "assert";
 			}
 		case TextureLod:
 			switch( args[0].t ) {
-			case TSampler2D, TSampler2DArray, TChannel(_) if( !flipY ):
-				if( isES2 ) {
-					decl("#extension GL_EXT_shader_texture_lod : enable");
-					return "texture2DLodEXT";
-				}
-			case TSampler2D, TChannel(_):
-				var tlod = isES2 ? "texture2DLod" : "textureLod";
-				decl('vec4 _texture2DLod( sampler2D t, vec2 v, float lod ) { return $tlod(t,vec2(v.x,0.999999-v.y)); }');
-				return "_texture2DLod";
-			case TSampler2DArray:
-				decl('vec4 _texture2DArrLod( sampler2DArray t, vec3 v, float lod ) { return textureLod(t,vec3(v.x,0.999999-v.y,v.z)); }');
-				return "_texture2DArrLod";
-			case TSamplerCube:
-				if( isES2 ) {
-					decl("#extension GL_EXT_shader_texture_lod : enable");
-					return "textureCubeLodEXT";
-				}
+			case TSampler2D, TSampler2DArray, TChannel(_) if( isES2 ):
+				decl("#extension GL_EXT_shader_texture_lod : enable");
+				return "texture2DLodEXT";
+			case TSamplerCube if( isES2 ):
+				decl("#extension GL_EXT_shader_texture_lod : enable");
+				return "textureCubeLodEXT";
 			default:
-				throw "assert";
 			}
 		case Mod if( rt == TInt && isES ):
 			decl("int _imod( int x, int y ) { return int(mod(float(x),float(y))); }");
@@ -271,6 +246,10 @@ class GlslOut {
 			decl(MAT34);
 			decl("mat3 _mat3( _mat3x4 v ) { return mat3(v.a.xyz,v.b.xyz,v.c.xyz); }");
 			return "_mat3";
+		case ScreenToUv:
+			decl("vec2 screenToUv( vec2 v ) { return v * vec2(0.5,0.5) + vec2(0.5,0.5); }");
+		case UvToScreen:
+			decl("vec2 uvToScreen( vec2 v ) { return v * vec2(2.,2.) + vec2(-1., -1.); }");
 		default:
 		}
 		return GLOBALS.get(g);

+ 4 - 0
hxsl/HlslOut.hx

@@ -292,6 +292,10 @@ class HlslOut {
 				decl("float3 unpackNormal( float4 p ) { return normalize(p.xyz * 2. - 1.); }");
 			case Atan:
 				decl("float atan( float y, float x ) { return atan2(y,x); }");
+			case ScreenToUv:
+				decl("float2 screenToUv( float2 v ) { return v * float2(0.5, -0.5) + float2(0.5,0.5); }");
+			case UvToScreen:
+				decl("float2 uvToScreen( float2 v ) { return v * float2(2.,-2.) + float2(-1., 1.); }");
 			default:
 			}
 			add(GLOBALS.get(g));