Skip to content

Commit

Permalink
Fix the textures/normals that are flipped (#182)
Browse files Browse the repository at this point in the history
* Fix the textures/normals that are flipped

* Fix objects out of range
  • Loading branch information
spimort authored Feb 1, 2025
1 parent 2b76ee1 commit 9e2a138
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,21 @@ const int ALPHA_CHANNEL_USAGE_NONE = 0;
const int ALPHA_CHANNEL_USAGE_ROUGHNESS = 1;
const int ALPHA_CHANNEL_USAGE_HEIGHT = 2;

// unpack_normal from zylann's shader
vec3 unpack_normal(vec4 rgba) {
vec3 n = rgba.xzy * 2.0 - vec3(1.0);
// Had to negate Z because it comes from Y in the normal map,
// and OpenGL-style normal maps are Y-up.
n.z *= -1.0;
return n;
}

// pack_normal from zylann's shader
vec4 pack_normal(vec3 n, float a) {
n.z *= -1.0;
return vec4((n.xzy + vec3(1.0)) * 0.5, a);
}

vec2 rotate(vec2 v, float cosa, float sina) {
return vec2(cosa * v.x - sina * v.y, sina * v.x + cosa * v.y);
}
Expand All @@ -43,7 +58,7 @@ vec4 depth_blend2(vec4 a_value, float a_bump, vec4 b_value, float b_bump, float
}

// Antitile from zylann's shader
vec4 texture_array_antitile(sampler2DArray texLinear, sampler2DArray texNearest, vec3 uv) {
vec4 texture_array_antitile(sampler2DArray texLinear, sampler2DArray texNearest, vec3 uv, bool isNormal) {
float frequency = 2.0;
float scale = 1.3;
float sharpness = 0.7;
Expand All @@ -64,6 +79,12 @@ vec4 texture_array_antitile(sampler2DArray texLinear, sampler2DArray texNearest,
col0 = texture(texLinear, uv);
col1 = texture(texLinear, uv2);
}

if (isNormal) {
vec3 n = unpack_normal(col1);
n.xz = rotate(n.xz, cosa, -sina);
col1 = pack_normal(n, col1.a);
}

// Periodically alternate between the two versions using a warped checker pattern
float t = 1.1 + 0.5
Expand Down Expand Up @@ -104,11 +125,11 @@ float contrast(float factor, float v) {
return max(0.0, min(1.0, factor * (v - 0.5) + 0.5));
}

void fillVec4WithFilterTexture(vec3 textureUV, sampler2DArray linearTextures, sampler2DArray nearestTextures, out vec4 resultTexture) {
vec4 fillVec4WithFilterTexture(vec3 textureUV, sampler2DArray linearTextures, sampler2DArray nearestTextures, bool isNormal) {
if (NearestFilter) {
resultTexture = UseAntitile ? texture_array_antitile(linearTextures, nearestTextures, textureUV) : texture(nearestTextures, textureUV);
return UseAntitile ? texture_array_antitile(linearTextures, nearestTextures, textureUV, isNormal) : texture(nearestTextures, textureUV);
} else {
resultTexture = UseAntitile ? texture_array_antitile(linearTextures, nearestTextures, textureUV) : texture(linearTextures, textureUV);
return UseAntitile ? texture_array_antitile(linearTextures, nearestTextures, textureUV, isNormal) : texture(linearTextures, textureUV);
}
}

Expand Down Expand Up @@ -142,19 +163,19 @@ void calculateHeightmapFragment(
vec4 currentRoughness = vec4(0);
vec4 currentHeight = vec4(0);

fillVec4WithFilterTexture(textureUV, Textures, TexturesNearest, currentTexture);
currentTexture = fillVec4WithFilterTexture(textureUV, Textures, TexturesNearest, false);
currentRoughness = vec4(currentTexture.a * float(AlbedoAlphaChannelUsage == ALPHA_CHANNEL_USAGE_ROUGHNESS));
currentHeight = vec4(currentTexture.a * float(AlbedoAlphaChannelUsage == ALPHA_CHANNEL_USAGE_HEIGHT));
if (HasNormalTextures) {
fillVec4WithFilterTexture(textureUV, Normals, NormalsNearest, currentNormal);
currentNormal = fillVec4WithFilterTexture(textureUV, Normals, NormalsNearest, true);
currentRoughness = max(currentRoughness, vec4(currentNormal.a * float(AlbedoAlphaChannelUsage != ALPHA_CHANNEL_USAGE_ROUGHNESS && NormalAlphaChannelUsage == ALPHA_CHANNEL_USAGE_ROUGHNESS)));
currentHeight = max(currentHeight, vec4(currentNormal.a * float(AlbedoAlphaChannelUsage != ALPHA_CHANNEL_USAGE_HEIGHT && NormalAlphaChannelUsage == ALPHA_CHANNEL_USAGE_HEIGHT)));
}
if (HasRoughnessTextures) {
fillVec4WithFilterTexture(textureUV, RoughnessTextures, RoughnessTexturesNearest, currentRoughness);
currentRoughness = fillVec4WithFilterTexture(textureUV, RoughnessTextures, RoughnessTexturesNearest, false);
}
if (HasHeightTextures) {
fillVec4WithFilterTexture(textureUV, HeightTextures, HeightTexturesNearest, currentHeight);
currentHeight = fillVec4WithFilterTexture(textureUV, HeightTextures, HeightTexturesNearest, false);
}

vec4 currentSplatmap = texture(Splatmaps, splatmapUV);
Expand Down
48 changes: 48 additions & 0 deletions addons/terrabrush/Scripts/Clipmap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ public void CreateMesh() {
Array.Fill(normals, new Vector3(0, 1, 0));
arrays[(int) Mesh.ArrayType.Normal] = normals;

arrays[(int) Mesh.ArrayType.Tangent] = CalculateTangents(vertices, uvs).ToArray();

var arrayMesh = new ArrayMesh();
arrayMesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arrays);

Expand Down Expand Up @@ -210,6 +212,52 @@ private void AddSquareVertices(List<Vector3> vertices, List<Vector2> uvs, float
});
}

private List<float> CalculateTangents(List<Vector3> vertices, List<Vector2> uvs) {
var tangents = new List<float>();
int triangleCount = vertices.Count / 3;

for (int i = 0; i < triangleCount; i++) {
var v0 = vertices[i * 3];
var v1 = vertices[i * 3 + 1];
var v2 = vertices[i * 3 + 2];

var uv0 = uvs[i * 3];
var uv1 = uvs[i * 3 + 1];
var uv2 = uvs[i * 3 + 2];

// Calculate the edges
var edge1 = v1 - v0;
var edge2 = v2 - v0;

// Calculate the UV space edges
var deltaUV1 = uv1 - uv0;
var deltaUV2 = uv2 - uv0;

// Calculate tangent
var inversedDeterminant = 1.0f / ((deltaUV1.X * deltaUV2.Y) - (deltaUV1.Y * deltaUV2.X));
var tangent = ((edge1 * deltaUV2.Y) - (edge2 * deltaUV1.Y)) * inversedDeterminant;
tangent = tangent.Normalized();

// Create tangent for each vertex of the triangle
tangents.Add(tangent.X);
tangents.Add(tangent.Y);
tangents.Add(tangent.Z);
tangents.Add(1.0f); // W is for a positive sign (1.0)

tangents.Add(tangent.X);
tangents.Add(tangent.Y);
tangents.Add(tangent.Z);
tangents.Add(1.0f);

tangents.Add(tangent.X);
tangents.Add(tangent.Y);
tangents.Add(tangent.Z);
tangents.Add(1.0f);
}

return tangents;
}

public void UpdateAABB() {
var zonePositions = TerrainZones.Zones.Select(zone => zone.ZonePosition).ToArray();
var maxX = zonePositions.Max(x => Math.Abs(x.X));
Expand Down
4 changes: 2 additions & 2 deletions addons/terrabrush/Scripts/Objects.cs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public void UpdateObjectsHeight(List<ZoneResource> zones) {
var yPosition = int.Parse(positions[1]);

var resultPosition = GetPositionWithNoise(noiseImage, xPosition, yPosition);
if (IsImagePositionInRange(resultPosition.X, resultPosition.Y)) {
if (IsImagePositionInRange(resultPosition.X, resultPosition.Z)) {
var heightImagePosition = GetHeightPositionForResolution(new Vector2(resultPosition.X, resultPosition.Z), resolutionZoneSize);
objectNode.Position = new Vector3(objectNode.Position.X, GetObjectHeight(heightmapImage, waterImage, heightImagePosition.X, heightImagePosition.Y), objectNode.Position.Z);
}
Expand All @@ -183,7 +183,7 @@ public void CalculateObjectPresenceForPixel(Image heightmapImage, Image waterIma
}

var resultPosition = GetPositionWithNoise(noiseImage, x, y);
if (IsImagePositionInRange(resultPosition.X, resultPosition.Y)) {
if (IsImagePositionInRange(resultPosition.X, resultPosition.Z)) {
var resolutionZoneSize = ZoneUtils.GetImageSizeForResolution(ZonesSize, Resolution);
var heightImagePosition = GetHeightPositionForResolution(new Vector2(resultPosition.X, resultPosition.Z), resolutionZoneSize);
var heightmapPixel = Utils.GetPixelLinear(heightmapImage, heightImagePosition.X, heightImagePosition.Y);
Expand Down
2 changes: 1 addition & 1 deletion addons/terrabrush/Scripts/ObjectsOctreeMultiMesh.cs
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ public void CalculateObjectPresenceForPixel(Image heightmapImage, Image waterIma
}

var resultPosition = GetPositionWithNoise(noiseImage, x, y);
if (IsImagePositionInRange(resultPosition.X, resultPosition.Y)) {
if (IsImagePositionInRange(resultPosition.X, resultPosition.Z)) {
var resolutionZoneSize = ZoneUtils.GetImageSizeForResolution(ZonesSize, Resolution);
var heightImagePosition = GetHeightPositionForResolution(new Vector2(resultPosition.X, resultPosition.Z), resolutionZoneSize);
var heightmapPixel = Utils.GetPixelLinear(heightmapImage, heightImagePosition.X, heightImagePosition.Y);
Expand Down
2 changes: 1 addition & 1 deletion addons/terrabrush/plugin.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
name="TerraBrush"
description=""
author="spimort"
version="0.11.1-alpha"
version="0.11.2-alpha"
script="Plugin.cs"

0 comments on commit 9e2a138

Please sign in to comment.