Skip to content

feat: add normal map preprocessing pipeline for correct channel layout conversion#87

Merged
Limitex merged 9 commits intomainfrom
fix/normal-map
Feb 27, 2026
Merged

feat: add normal map preprocessing pipeline for correct channel layout conversion#87
Limitex merged 9 commits intomainfrom
fix/normal-map

Conversation

@Limitex
Copy link
Owner

@Limitex Limitex commented Feb 25, 2026

closes #40

@Limitex Limitex self-assigned this Feb 25, 2026
Copilot AI review requested due to automatic review settings February 25, 2026 16:45
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a normal-map-aware preprocessing and resize pipeline so normal maps can be resized/compressed without channel-layout corruption (DXTnm AG vs RG vs RGB) and without gamma/sRGB side effects.

Changes:

  • Add NormalMapPreprocessor and NormalMapSourceLayoutDetector to detect/convert normal map channel layouts before compression.
  • Update TextureCompressorService to preprocess normal maps before EditorUtility.CompressTexture, including fallback handling and semantic-alpha decisions for BC7.
  • Update TextureProcessor to support isNormalMap resizing (linear read/write + higher-precision RT when available) and add extensive editor tests covering the pipeline end-to-end.

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
Editor/TextureCompressor/Core/Services/TextureProcessor.cs Adds isNormalMap resize path using linear color space + float/half RT selection.
Editor/TextureCompressor/Core/Services/TextureCompressorService.cs Integrates normal map preprocessing + source-layout detection into compression and fallback flow.
Editor/TextureCompressor/Core/Services/TextureFormatSelector.cs Narrows responsibility to format prediction; exposes ResolvePlatform.
Editor/TextureCompressor/Core/Services/NormalMapPreprocessor.cs New normal map channel packing/normalization logic for BC5/DXT5/BC7 + semantic alpha rules.
Editor/TextureCompressor/Core/Services/NormalMapSourceLayoutDetector.cs New heuristic detector for AG vs RG vs RGB layouts in ambiguous formats (DXT5/BC7).
Tests/Editor/TestUtilities/NormalMapTestTextureFactory.cs (+ .meta) Adds deterministic normal-map texture generators for test patterns and layouts.
Tests/Editor/Core/Services/TextureProcessorTests.cs Expands resize tests to cover normal-map-specific behavior.
Tests/Editor/Core/Services/TextureFormatSelectorTests.cs Removes compression-invocation tests now handled at service level; adds platform resolution tests.
Tests/Editor/Core/Services/TextureCompressorServiceTests.cs Adds extensive integration tests for compression format selection, frozen overrides, layout detection, and alpha semantics.
Tests/Editor/Core/Services/NormalMapSourceLayoutDetectorTests.cs (+ .meta) Adds unit tests for layout detection and resolve behavior.
Tests/Editor/Core/Services/NormalMapResizePipelineTests.cs (+ .meta) Adds resize pipeline regression tests focused on normal map integrity.
Tests/Editor/Core/Services/NormalMapPreprocessorTests.cs (+ .meta) Adds unit tests for preprocessing conversions and normalization behavior.
Tests/Editor/Core/Services/NormalMapPreprocessorPipelineTests.cs (+ .meta) Adds end-to-end tests for resize + preprocess + real compression round-trips.
Tests/Editor/TestUtilities.meta Adds Unity folder meta for new test utilities location.
Comments suppressed due to low confidence (1)

Editor/TextureCompressor/Core/Services/TextureProcessor.cs:177

  • ResizeTo changes RenderTexture.active and allocates a temporary RenderTexture but doesn’t use a try/finally. If Graphics.Blit, ReadPixels, or Apply throws, RenderTexture.active may remain modified and the temporary RT may leak. Wrap the body in try/finally to always restore RenderTexture.active and ReleaseTemporary(rt) (and consider cleaning up the partially-created result).
                RenderTexture previous = RenderTexture.active;
                RenderTexture.active = rt;
                Graphics.Blit(source, rt);

                // Preserve mipmap setting from source texture
                // For normal maps, use linear color space to prevent gamma correction
                Texture2D result = new Texture2D(
                    newWidth,
                    newHeight,
                    TextureFormat.RGBA32,
                    source.mipmapCount > 1,
                    isNormalMap
                );
                result.ReadPixels(new Rect(0, 0, newWidth, newHeight), 0, 0);
                result.Apply(source.mipmapCount > 1);

                // Copy texture settings from source
                result.wrapModeU = source.wrapModeU;
                result.wrapModeV = source.wrapModeV;
                result.wrapModeW = source.wrapModeW;
                result.filterMode = source.filterMode;
                result.anisoLevel = source.anisoLevel;

                RenderTexture.active = previous;
                RenderTexture.ReleaseTemporary(rt);


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Limitex Limitex marked this pull request as ready for review February 25, 2026 17:06
Copilot AI review requested due to automatic review settings February 26, 2026 14:54
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Limitex Limitex merged commit 05e42fe into main Feb 27, 2026
4 checks passed
@Limitex Limitex deleted the fix/normal-map branch February 27, 2026 12:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] BC5 to BC5 breaks normal maps

2 participants