All surfaces follow D3D Y convention, i.e. (0, 0) is "top-left" rather than GL's "bottom-left". This eliminates the need to flip the default FBO to the D3D convention using additional blits when presenting and reduces VRAM usage for redundant window sized surfaces.
I took out the gl_Position.y flip from the vertex shader so FBOs are rendered
according to D3D conventions.
Texture lookups are flipped on Y to compensate. Cube map +Y and -Y faces are swapped. Y is now flipped in various other places, including uploading and reading back texture data from / to system memory, functions that take pixel space coordinates, winding order for culling, the implementation of ddy, the calculation of gl_Position and gl_FragCoord in fragment shaders and the flipping of compressed texture tiles.
Review URL: http://codereview.appspot.com/3265041
git-svn-id: https://angleproject.googlecode.com/svn/trunk@536 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/compiler/OutputHLSL.cpp b/src/compiler/OutputHLSL.cpp
index 57e99d2..d6e9232 100644
--- a/src/compiler/OutputHLSL.cpp
+++ b/src/compiler/OutputHLSL.cpp
@@ -196,11 +196,25 @@
out << uniforms;
out << "\n";
+ // The texture fetch functions "flip" the Y coordinate in one way or another. This is because textures are stored
+ // according to the OpenGL convention, i.e. (0, 0) is "bottom left", rather than the D3D convention where (0, 0)
+ // is "top left". Since the HLSL texture fetch functions expect textures to be stored according to the D3D
+ // convention, the Y coordinate passed to these functions is adjusted to compensate.
+ //
+ // The simplest case is texture2D where the mapping is Y -> 1-Y, which maps [0, 1] -> [1, 0].
+ //
+ // The texture2DProj functions are more complicated because the projection divides by either Z or W. For the vec3
+ // case, the mapping is Y -> Z-Y or Y/Z -> 1-Y/Z, which again maps [0, 1] -> [1, 0].
+ //
+ // For cube textures the mapping is Y -> -Y, which maps [-1, 1] -> [1, -1]. This is not sufficient on its own for the
+ // +Y and -Y faces, which are now on the "wrong sides" of the cube. This is compensated for by exchanging the
+ // +Y and -Y faces everywhere else throughout the code.
+
if (mUsesTexture2D)
{
out << "float4 gl_texture2D(sampler2D s, float2 t)\n"
"{\n"
- " return tex2D(s, t);\n"
+ " return tex2D(s, float2(t.x, 1 - t.y));\n"
"}\n"
"\n";
}
@@ -209,7 +223,7 @@
{
out << "float4 gl_texture2D(sampler2D s, float2 t, float bias)\n"
"{\n"
- " return tex2Dbias(s, float4(t.x, t.y, 0, bias));\n"
+ " return tex2Dbias(s, float4(t.x, 1 - t.y, 0, bias));\n"
"}\n"
"\n";
}
@@ -218,12 +232,12 @@
{
out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n"
"{\n"
- " return tex2Dproj(s, float4(t.x, t.y, 0, t.z));\n"
+ " return tex2Dproj(s, float4(t.x, t.z - t.y, 0, t.z));\n"
"}\n"
"\n"
"float4 gl_texture2DProj(sampler2D s, float4 t)\n"
"{\n"
- " return tex2Dproj(s, t);\n"
+ " return tex2Dproj(s, float4(t.x, t.w - t.y, t.z, t.w));\n"
"}\n"
"\n";
}
@@ -232,12 +246,12 @@
{
out << "float4 gl_texture2DProj(sampler2D s, float3 t, float bias)\n"
"{\n"
- " return tex2Dbias(s, float4(t.x / t.z, t.y / t.z, 0, bias));\n"
+ " return tex2Dbias(s, float4(t.x / t.z, 1 - (t.y / t.z), 0, bias));\n"
"}\n"
"\n"
"float4 gl_texture2DProj(sampler2D s, float4 t, float bias)\n"
"{\n"
- " return tex2Dbias(s, float4(t.x / t.w, t.y / t.w, 0, bias));\n"
+ " return tex2Dbias(s, float4(t.x / t.w, 1 - (t.y / t.w), 0, bias));\n"
"}\n"
"\n";
}
@@ -246,7 +260,7 @@
{
out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n"
"{\n"
- " return texCUBE(s, t);\n"
+ " return texCUBE(s, float3(t.x, -t.y, t.z));\n"
"}\n"
"\n";
}
@@ -255,7 +269,7 @@
{
out << "float4 gl_textureCube(samplerCUBE s, float3 t, float bias)\n"
"{\n"
- " return texCUBEbias(s, float4(t.x, t.y, t.z, bias));\n"
+ " return texCUBEbias(s, float4(t.x, -t.y, t.z, bias));\n"
"}\n"
"\n";
}
@@ -968,7 +982,7 @@
case EOpLength: outputTriplet(visit, "length(", "", ")"); break;
case EOpNormalize: outputTriplet(visit, "normalize(", "", ")"); break;
case EOpDFdx: outputTriplet(visit, "ddx(", "", ")"); break;
- case EOpDFdy: outputTriplet(visit, "ddy(", "", ")"); break;
+ case EOpDFdy: outputTriplet(visit, "(-ddy(", "", "))"); break;
case EOpFwidth: outputTriplet(visit, "fwidth(", "", ")"); break;
case EOpAny: outputTriplet(visit, "any(", "", ")"); break;
case EOpAll: outputTriplet(visit, "all(", "", ")"); break;