Ich versuche derzeit, eine Voxel Engine mit Direct3D 9 und C ++ zu entwickeln. Um die Speichernutzung gering zu halten, übergebe ich nur die Position, die Ausrichtung und den Versatz der aktuellen Voxel-Textur im Texturatlas jedes Scheitelpunkts an den Scheitelpunkt-Shader.
Der Vertex-Shader berechnet dann die Normalen und übergibt sie an den Pixel-Shader. Ich habe diesen Artikel gefunden, der beschreibt, wie man Voxel nur mit ihrer Position und normal in glsl texturiert.
Dies ist der Teil, der die Texturkoordinaten in meinem Pixel-Shader (SM3) berechnet:
float2 tileUV = float2(dot(input.normal.zxy, input.pos3D),
dot(input.normal.yzx, input.pos3D));
float2 texcoord = input.texOffset + tileSize * frac(tileUV);
Dieser Code funktioniert gut für Flächen, die in negative Z-Richtung zeigen (normal [0,0, -1]). Die Rückseite wird jedoch um 180 ° und die Seiten und oberen / unteren Quadrate um 90 ° / 270 ° gedreht .
Ich bin mir nicht sicher, ob dies korrekt aus glsl übersetzt wurde, da dieses Verhalten das erwartete in hlsl sein sollte, wenn ich es von Hand berechne. Gibt es etwas, das ich beaufsichtigt habe, oder sollte ich einen anderen Ansatz anstreben?
Bearbeiten:
Ich habe es jetzt geschafft, die Gesichter erfolgreich zu texturieren, indem ich die vorherige Berechnung durch die folgende ersetzt habe:
if(input.normal.y != 0.0f) // handle top/bottom surfaces as front/back faces
{
input.pos3D.y = input.pos3D.z;
input.normal.z = -input.normal.y;
input.normal.y = 0.0f;
}
texcoord.x = input.texOffset.x + tileSize * frac(float3(1.0f, 1.0f, 1.0f) + cross(frac(input.pos3D), input.normal)).y;
texcoord.y = input.texOffset.y + tileSize * (1.0f - frac(input.pos3D.y));
Gibt es eine Möglichkeit, die Gleichung zu vereinfachen / zu optimieren? Ich kann auch erwähnen, dass die Voxel alle achsenausgerichtet und auf ganzzahlige Koordinaten geklemmt sind.
Edit2:
Dies ist die modifizierte Formel von zogis Antwort, die wie erwartet funktioniert.
float3 n = abs(normal.xyz);
float2 texcoord = float2(input.texOffset.x + tileSize * dot(n, frac(input.pos3D.zxx)),
input.texOffset.y + tileSize + tileSize * dot(-n, frac(input.pos3D.yzy)));