|
@@ -463,27 +463,28 @@ namespace bs
|
|
|
/** Method that maps a direction to a point on a plane in range [0, 1] using spherical mapping. */
|
|
/** Method that maps a direction to a point on a plane in range [0, 1] using spherical mapping. */
|
|
|
Vector2 mapCubemapDirToSpherical(const Vector3& dir)
|
|
Vector2 mapCubemapDirToSpherical(const Vector3& dir)
|
|
|
{
|
|
{
|
|
|
|
|
+ // Using the OpenGL spherical mapping formula
|
|
|
Vector3 nrmDir = Vector3::normalize(dir);
|
|
Vector3 nrmDir = Vector3::normalize(dir);
|
|
|
|
|
+ nrmDir.z += 1.0f;
|
|
|
|
|
|
|
|
- float u = acos(Math::abs(nrmDir.z)) / Math::PI;
|
|
|
|
|
- if (nrmDir.x > 0.0f)
|
|
|
|
|
- u = 1.0f - u;
|
|
|
|
|
|
|
+ float m = 2 * nrmDir.length();
|
|
|
|
|
|
|
|
- float v = 1.0f - acos(nrmDir.y) / Math::PI;
|
|
|
|
|
|
|
+ float u = nrmDir.x / m + 0.5f;
|
|
|
|
|
+ float v = nrmDir.y / m + 0.5f;
|
|
|
|
|
|
|
|
return Vector2(u, v);
|
|
return Vector2(u, v);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /** Method that maps a direction to a point on a plane in range [0, 1] using cylindrical mapping. */
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Method that maps a direction to a point on a plane in range [0, 1] using cylindrical mapping. This mapping is also
|
|
|
|
|
+ * know as longitude-latitude mapping, Blinn/Newell mapping or equirectangular cylindrical mapping.
|
|
|
|
|
+ */
|
|
|
Vector2 mapCubemapDirToCylindrical(const Vector3& dir)
|
|
Vector2 mapCubemapDirToCylindrical(const Vector3& dir)
|
|
|
{
|
|
{
|
|
|
Vector3 nrmDir = Vector3::normalize(dir);
|
|
Vector3 nrmDir = Vector3::normalize(dir);
|
|
|
|
|
|
|
|
- float u = 0.75f - atan2(nrmDir.z, nrmDir.x) / Math::HALF_PI;
|
|
|
|
|
- if (u > 1.0f)
|
|
|
|
|
- u -= 1.0f;
|
|
|
|
|
-
|
|
|
|
|
- float v = 1.0f - acos(nrmDir.y) / Math::PI;
|
|
|
|
|
|
|
+ float u = (atan2(nrmDir.z, nrmDir.x) + Math::PI) / Math::TWO_PI;
|
|
|
|
|
+ float v = acos(nrmDir.y) / Math::PI;
|
|
|
|
|
|
|
|
return Vector2(u, v);
|
|
return Vector2(u, v);
|
|
|
}
|
|
}
|
|
@@ -521,8 +522,8 @@ namespace bs
|
|
|
{
|
|
{
|
|
|
{ 2, 1, 0, { 1.0f, -1.0f, 1.0f }}, // X+
|
|
{ 2, 1, 0, { 1.0f, -1.0f, 1.0f }}, // X+
|
|
|
{ 2, 1, 0, { -1.0f, -1.0f, -1.0f }}, // X-
|
|
{ 2, 1, 0, { -1.0f, -1.0f, -1.0f }}, // X-
|
|
|
- { 0, 2, 1, { -1.0f, 1.0f, -1.0f }}, // Y+
|
|
|
|
|
- { 0, 2, 1, { -1.0f, -1.0f, 1.0f }}, // Y-
|
|
|
|
|
|
|
+ { 0, 2, 1, { 1.0f, -1.0f, 1.0f }}, // Y+
|
|
|
|
|
+ { 0, 2, 1, { 1.0f, 1.0f, -1.0f }}, // Y-
|
|
|
{ 0, 1, 2, { 1.0f, -1.0f, -1.0f }}, // Z+
|
|
{ 0, 1, 2, { 1.0f, -1.0f, -1.0f }}, // Z+
|
|
|
{ 0, 1, 2, { -1.0f, -1.0f, 1.0f }} // Z-
|
|
{ 0, 1, 2, { -1.0f, -1.0f, 1.0f }} // Z-
|
|
|
};
|
|
};
|
|
@@ -541,14 +542,14 @@ namespace bs
|
|
|
Vector2 sourceCoord = (Vector2((float)x, (float)y) * invSize) * 2.0f - Vector2(1.0f, 1.0f);
|
|
Vector2 sourceCoord = (Vector2((float)x, (float)y) * invSize) * 2.0f - Vector2(1.0f, 1.0f);
|
|
|
Vector3 direction = Vector3(sourceCoord.x, sourceCoord.y, 1.0f);
|
|
Vector3 direction = Vector3(sourceCoord.x, sourceCoord.y, 1.0f);
|
|
|
|
|
|
|
|
|
|
+ direction *= remapInfo.sign;
|
|
|
|
|
+
|
|
|
// Rotate towards current face
|
|
// Rotate towards current face
|
|
|
Vector3 rotatedDir;
|
|
Vector3 rotatedDir;
|
|
|
rotatedDir[remapInfo.idx[0]] = direction.x;
|
|
rotatedDir[remapInfo.idx[0]] = direction.x;
|
|
|
rotatedDir[remapInfo.idx[1]] = direction.y;
|
|
rotatedDir[remapInfo.idx[1]] = direction.y;
|
|
|
rotatedDir[remapInfo.idx[2]] = direction.z;
|
|
rotatedDir[remapInfo.idx[2]] = direction.z;
|
|
|
|
|
|
|
|
- rotatedDir *= remapInfo.sign;
|
|
|
|
|
-
|
|
|
|
|
// Find location in the source to sample from
|
|
// Find location in the source to sample from
|
|
|
Vector2 sourceUV = remap(rotatedDir);
|
|
Vector2 sourceUV = remap(rotatedDir);
|
|
|
Color color = source->sampleColorAt(sourceUV);
|
|
Color color = source->sampleColorAt(sourceUV);
|
|
@@ -563,6 +564,9 @@ namespace bs
|
|
|
bool FreeImgImporter::generateCubemap(const SPtr<PixelData>& source, CubemapSourceType sourceType,
|
|
bool FreeImgImporter::generateCubemap(const SPtr<PixelData>& source, CubemapSourceType sourceType,
|
|
|
std::array<SPtr<PixelData>, 6>& output)
|
|
std::array<SPtr<PixelData>, 6>& output)
|
|
|
{
|
|
{
|
|
|
|
|
+ // Note: Expose this as a parameter if needed:
|
|
|
|
|
+ UINT32 cubemapSupersampling = 1; // Set to amount of samples
|
|
|
|
|
+
|
|
|
Vector2I faceSize;
|
|
Vector2I faceSize;
|
|
|
bool cross = false;
|
|
bool cross = false;
|
|
|
bool vertical = false;
|
|
bool vertical = false;
|
|
@@ -613,9 +617,6 @@ namespace bs
|
|
|
// Don't allow sizes larger than 4096
|
|
// Don't allow sizes larger than 4096
|
|
|
faceSize.x = std::min(faceSize.x, 4096);
|
|
faceSize.x = std::min(faceSize.x, 4096);
|
|
|
|
|
|
|
|
- // We also do 4x super-sampling, so increase size accordingly
|
|
|
|
|
- faceSize.x *= 4;
|
|
|
|
|
-
|
|
|
|
|
faceSize.y = faceSize.x;
|
|
faceSize.y = faceSize.x;
|
|
|
|
|
|
|
|
break;
|
|
break;
|
|
@@ -649,16 +650,28 @@ namespace bs
|
|
|
break;
|
|
break;
|
|
|
case CubemapSourceType::Cylindrical:
|
|
case CubemapSourceType::Cylindrical:
|
|
|
{
|
|
{
|
|
|
|
|
+ UINT32 superSampledFaceSize = faceSize.x * cubemapSupersampling;
|
|
|
|
|
+
|
|
|
std::array<SPtr<PixelData>, 6> superSampledOutput;
|
|
std::array<SPtr<PixelData>, 6> superSampledOutput;
|
|
|
- readCubemapUVRemap(source, superSampledOutput, faceSize.x, &mapCubemapDirToCylindrical);
|
|
|
|
|
- downsampleCubemap(superSampledOutput, output, faceSize.x / 4);
|
|
|
|
|
|
|
+ readCubemapUVRemap(source, superSampledOutput, superSampledFaceSize, &mapCubemapDirToCylindrical);
|
|
|
|
|
+
|
|
|
|
|
+ if (faceSize.x != superSampledFaceSize)
|
|
|
|
|
+ downsampleCubemap(superSampledOutput, output, faceSize.x);
|
|
|
|
|
+ else
|
|
|
|
|
+ output = superSampledOutput;
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|
|
|
case CubemapSourceType::Spherical:
|
|
case CubemapSourceType::Spherical:
|
|
|
{
|
|
{
|
|
|
|
|
+ UINT32 superSampledFaceSize = faceSize.x * cubemapSupersampling;
|
|
|
|
|
+
|
|
|
std::array<SPtr<PixelData>, 6> superSampledOutput;
|
|
std::array<SPtr<PixelData>, 6> superSampledOutput;
|
|
|
- readCubemapUVRemap(source, superSampledOutput, faceSize.x, &mapCubemapDirToSpherical);
|
|
|
|
|
- downsampleCubemap(superSampledOutput, output, faceSize.x / 4);
|
|
|
|
|
|
|
+ readCubemapUVRemap(source, superSampledOutput, superSampledFaceSize, &mapCubemapDirToSpherical);
|
|
|
|
|
+
|
|
|
|
|
+ if (faceSize.x != superSampledFaceSize)
|
|
|
|
|
+ downsampleCubemap(superSampledOutput, output, faceSize.x);
|
|
|
|
|
+ else
|
|
|
|
|
+ output = superSampledOutput;
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|
|
|
default: // Single-image
|
|
default: // Single-image
|