問題是當我嘗試將高度貼圖轉換為法線貼圖時。結果是錯誤的。由于某種原因,紋理中有 3 個光源從頂部(綠色)、右側(紅色)和左側(藍色)發射。
這是我正在使用的 GeoMath.hlsl 代碼
static const float PI = 3.141592653589793238462643383279;
float2 longitudeLatitudeToUV(float2 longLat) {
float longitude = longLat[0];
float latitude = longLat[1];
float u = longitude / (2 * PI) 0.5;
float v = latitude / PI 0.5;
return float2(u,v);
}
float3 longitudeLatitudeToPoint(float2 longLat) {
float longitude = longLat[0];
float latitude = longLat[1];
float x;
float y;
float z;
y = sin(latitude);
float r = cos(latitude);
x = sin(longitude) * r;
z = -cos(longitude) * r;
return float3(x, y, z);
}
float2 uvToLongitudeLatitude(float2 uv) {
float longitude = (uv.x - 0.5) * (2 * PI);
float latitude = (uv.y - 0.5) * PI;
return float2(longitude, latitude);
}
float2 pointToLongitudeLatitude(float3 p) {
float longitude = atan2(p.x, p.z);
float latitude = asin(p.y);
return float2(longitude, latitude);
}
float2 pointToUV(float3 p) {
p = normalize(p);
return longitudeLatitudeToUV(pointToLongitudeLatitude(p));
}
這是我用來將高度貼圖轉換為法線貼圖的計算著色器。
#pragma kernel CSMain
#include "GeoMath.hlsl"
Texture2D<float> _HeightMap;
RWTexture2D<float4> _NormalMap;
int _TextureSize_Width;
int _TextureSize_Height;
float _WorldRadius;
float _HeightMultiplier;
float3 CalculateWorldPoint(uint2 texCoord)
{
float2 uv = texCoord / float2(_TextureSize_Width - 1, _TextureSize_Height - 1);
float2 longLat = uvToLongitudeLatitude(uv);
float3 spherePoint = longitudeLatitudeToPoint(longLat);
float height01 = _HeightMap[texCoord].r 1.0;
float worldHeight = _WorldRadius height01 * _HeightMultiplier;
return spherePoint * worldHeight;
}
uint2 WrapIndex(uint2 texCoord)
{
texCoord.x = (texCoord.x _TextureSize_Width) % _TextureSize_Width;
texCoord.y = max(min(_TextureSize_Height - 1, texCoord.y), 0);
return texCoord;
}
[numthreads(8,8,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
float3 normalVector;
float3 posNorth = CalculateWorldPoint(WrapIndex(id.xy uint2(0, 1)));
float3 posSouth = CalculateWorldPoint(WrapIndex(id.xy uint2(0, -1)));
float3 posEast = CalculateWorldPoint(WrapIndex(id.xy uint2(1, 0)));
float3 posWest = CalculateWorldPoint(WrapIndex(id.xy uint2(-1, 0)));
float3 dirNorth = normalize(posNorth - posSouth);
float3 dirEast = normalize(posEast - posWest);
normalVector = normalize(cross(dirNorth, dirEast));
_NormalMap[id.xy] = float4(normalVector, 1.0);
}
這是我得到的結果低于高度圖(頂部),從上面的代碼生成的法線圖(底部)
uj5u.com熱心網友回復:
我相信您正在嘗試獲取物件空間法線。但是缺少一個微小的細節。每個軸的歸一化 vector3 的可能值為 -1..1。像素的可能值:0..1。
您只需要調整范圍。
這一行大致解決了問題:
_NormalMap[id.xy] = float4(normalVector / 2 float3(0.5, 0.5, 0.5), 1.0);
結果
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/536469.html
標籤:unity3d