HLSL - Voxel-Texturierung


7

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)));

Antworten:


2

Die erste Formel, die Sie erwähnt haben, ist nicht für das gewünschte Ergebnis geeignet. Ich schlage stattdessen die folgende Formel vor:

float3 n = abs(input.normal.xyz);
float2 tileUV = float2(dot(n,  input.pos3D.zxx),
                       dot(-n, input.pos3D.yzy));

Der nVektor wählt grundsätzlich die Seite des Würfels aus, da genau eine Koordinate 1 ist, die anderen 0. Da der Ursprung im Texturkoordinatenraum in DirectX in der oberen linken Ecke der Textur liegt, in OpenGL unten links muss die zweite Texturkoordinate negiert werden.


Vielen Dank, mit kleinen Änderungen funktioniert dies wie erwartet. Siehe meine Bearbeitung für die endgültige Formel.
user000user
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.