Skip to main content
GameDev.net gamedev.net
✓ Solved 🔒 Locked

Hemisphere to square and back mapping

Started by Josh Klint Jul 2 at 12:21 AM 1 replies 250+ views
Original Post
Josh Klint
Josh Klint

I need C++ code that reliably converts a normalized 2D texture coordinate on a square [0, 1] to a 3D vector that maps to a hemisphere, with positive Y.

I think dual-paraboloid code could do this, but I am having trouble finding working examples. This person seems to have encountered the same problem, but they didn't bother to document their solution:
https://gamedev.net/forums/topic/649346-square-hemisphere-mapping/

I need these functions filled in:

Vec3 TexCoordToHemisphere(const float u, const float v)
Vec2 HemisphereToTexCoord(const float dx, const float dy, const float dz)

Thanks in advanced for your any help you can provide.

Accepted Answer

This code works:

	Vec3 TexCoordToHemisphere(const float u, const float v)
	{
		// [0,1] -> [-1,1] paraboloid domain
		float px = 2.0f * u - 1.0f;
		float py = 2.0f * (1.0f - v) - 1.0f; // v up -> py positive

		float p2 = px * px + py * py;

		// Optional robustness clamp
		if (p2 > 1.0f) p2 = 1.0f;

		float inv = 1.0f / (1.0f + p2);
		float z = (1.0f - p2) * inv;      // z = (1 - p^2) / (1 + p^2)
		float scale = 2.0f * inv;             // 1 + z = 2 / (1 + p^2)

		float x = px * scale;                 // x = px * (1 + z)
		float y = py * scale;                 // y = py * (1 + z)

		return Vec3(x, y, z);                 // already unit length
	}

	Vec2 HemisphereToTexCoord(const float dx, const float dy, const float dz)
	{
		// Assume (dx,dy,dz) is normalized and dz >= 0 (front hemisphere)
		float denom = 1.0f + dz;

		float px = dx / denom;
		float py = dy / denom;

		float u = px * 0.5f + 0.5f;
		float v = 1.0f - (py * 0.5f + 0.5f);  // Y-up -> v decreases with +y

		return Vec2(u, v);
	}

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.