Quay lại Blog
Hướng dẫn

Normal Map Conventions: OpenGL vs DirectX Explained

Tại sao normal map của bạn trông bị đảo ngược trong Unreal nhưng lại tốt trong Unity — giải thích đơn giản về quy ước trục Y trong tangent-space, kèm theo những giải pháp cụ thể.

Admin23 tháng 4, 20264 phút đọc11

Bạn cắm một normal map vào Unreal và bề mặt sáng lên như thể mặt trời đang chiếu từ dưới lên. Bạn cắm cùng một file vào Unity hoặc Blender — trông tuyệt vời. Mesh giống nhau. Texture giống nhau. Chuyện gì đang xảy ra vậy?

Hai ngành công nghiệp, một trục không đồng ý

Normal map lưu trữ hướng bề mặt trong các kênh RGB của chúng. Red = X, green = Y, blue = Z. Mỗi engine PBR giải mã chúng giống nhau với một ngoại lệ: dấu của Y.

Quy ước OpenGL (Y+): kênh green sáng hơn có nghĩa là bề mặt chỉ lên. Được sử dụng bởi Unity, Godot, Blender (Cycles và Eevee), xuất khẩu mặc định của Substance Painter, và mọi engine dựa trên WebGL.

Quy ước DirectX (Y−): green sáng hơn có nghĩa là bề mặt chỉ xuống. Được sử dụng bởi Unreal Engine, chuỗi công cụ Direct3D cũ, và một số asset CryEngine/Xbox-era.

Cùng các byte trong PNG. Ý nghĩa vật lý ngược nhau.

Cách nhận biết ngay lập tức

Nhìn vào một bump hình bán cầu (như một nút hoặc mái vòm) trong normal map của bạn. Trong quy ước OpenGL, phần dưới của bump sẽ có green tối hơn vì bề mặt đang quay về phía Y−, lùi lại khỏi ánh sáng. Trong quy ước DirectX, phần dưới có green sáng hơn.

Nếu ánh sáng của bạn trông ngược trong engine — điểm sáng ở nơi mà bóng tối phải là — bạn có sự không khớp về quy ước.

Giải pháp mất 5 giây

Trong Unreal, hộp thoại nhập texture có một hộp kiểm Flip Green Channel. Bật nó lên và engine sẽ đảo kênh G tại thời điểm lấy mẫu. Không cần phải xuất lại nguồn của bạn.

Trong Unity, đặt loại texture thành Normal map và công cụ nhập sẽ xử lý mọi thứ — Unity kỳ vọng OpenGL, nhưng nó sẽ cảnh báo bạn nếu file trông sai. Trong Blender, sử dụng chuỗi nút Separate Color → Invert G → Combine Color, hoặc chỉ cần chọn đầu vào kiểu DirectX trực tiếp trong nút Normal Map.

Tại sao lại có hai tiêu chuẩn ngay từ đầu?

Trong những năm 1990, OpenGL và DirectX định nghĩa các không gian tọa độ texture ngược lại — OpenGL có Y tăng lên, DirectX có Y tăng xuống. Khi normal map trở nên phổ biến vào giữa những năm 2000, mỗi chuỗi công cụ đã đưa không gian của nó vào các output của nó. Sự khác biệt này kéo dài vì lật một pipeline được thiết lập là tốn kém.

Tạo Normal Map mà không có sự nhầm lẫn

aukimi Normal Map Generator cho phép bạn chọn quy ước một cách rõ ràng khi bạn xuất. Nó chạy gradient Sobel trên độ sáng của heightmap của bạn, sau đó đóng gói (−dx·s, −dy·s, 1) vào RGB — với Y được lật khi bạn chọn DirectX. Bạn có thể chuyển đổi quy ước sau khi tạo và tải xuống lại mà không cần tải lên lại bất cứ điều gì.

Nội bộ công thức là giống nhau. Sự khác biệt duy nhất là dấu chúng tôi áp dụng cho thành phần Y trước khi viết kênh xanh lục. Biết điều đó, bạn có thể chuyển đổi một file giữa các quy ước bằng bất kỳ trình chỉnh sửa hình ảnh nào: mở PNG, chọn kênh xanh lục, đảo ngược nó, lưu. Đó là tất cả những gì "Flip Green Channel" làm trong Unreal.

Tham khảo nhanh

  • Unity, Godot, Blender, Substance Painter (default): OpenGL (Y+).
  • Unreal Engine, legacy Direct3D: DirectX (Y−).
  • Trông sai trong Unreal? Bật Flip Green Channel trong cài đặt nhập.
  • Trông sai trong Unity? Bạn có thể đã xuất từ một công cụ quy ước DirectX — đảo kênh xanh lục hoặc xuất lại.

Khi bạn nắm vững quy ước, giải pháp là tầm thường. Phần khó nhất là nhận ra nó lần đầu tiên.

#normal-map#3d#pbr#shaders#opengl#directx

Bạn thích bài viết này?

ShareHN