atteneder / KtxUnity

Load KTX and Basis Universal textures at runtime
Apache License 2.0
223 stars 42 forks source link

Unable to load basis compressed normal map. #24

Closed sarangborude closed 4 years ago

sarangborude commented 4 years ago

I am trying to get the Normal map texture from a basis encoded file. I specify the filePath in the field for MyClass : TextureFileLoader(BasisUniversalTexture)

I am getting the following error.

UnityException: LoadRawTextureData: not enough data provided (will result in overread). UnityEngine.Texture2D.LoadRawTextureData[T] (Unity.Collections.NativeArray`1[T] data) (at /Users/builduser/buildslave/unity/build/Runtime/Export/Graphics/Texture.cs:631) KtxUnity.BasisUniversalTexture+d__2.MoveNext () (at Library/PackageCache/com.atteneder.ktx@0.8.1/Runtime/Scripts/BasisUniversalTexture.cs:103) UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at /Users/builduser/buildslave/unity/build/Runtime/Export/Scripting/Coroutines.cs:17)

sarangborude commented 4 years ago

@atteneder So I was digging in the code, I don't really have a computer graphics background, but really want to get this working. There are couple things that I found in the BasisUniversalTexture.LoadBytesRoutine() method. seems like the BasisUniversalJob doesn't contain the texture data after the file is parsed. I am expecting to get an RG11 encoded normal map.

In the function below, when I log the format values it outputs RGBA_BC7_SRGB (BC7_RGBA) when I was hoping for RG11. I feel like the data is not present because of the discrepancy in the formats.

`IEnumerator TranscodeImage2D(BasisUniversalTranscoderInstance transcoder, NativeSlice data, bool linear) { Debug.Log("Transcoding Image.........."); // Can turn to parameter in future uint imageIndex = 0;

        var meta = transcoder.LoadMetaData();

        var formats = GetFormat( meta, meta.images[imageIndex].levels[0], linear );

        if(formats.HasValue) {
            Debug.LogFormat("Transcode to GraphicsFormat {0} ({1})", formats.Value.format, formats.Value.transcodeFormat);

if KTX_VERBOSE

            Debug.LogFormat("Transcode to GraphicsFormat {0} ({1})",formats.Value.format,formats.Value.transcodeFormat);

endif

            Profiler.BeginSample("BasisUniversalJob");
            var job = new BasisUniversalJob();

            job.imageIndex = imageIndex;

            job.result = new NativeArray<bool>(1,KtxNativeInstance.defaultAllocator);

            var jobHandle = BasisUniversal.LoadBytesJob(
                ref job,
                transcoder,
                data,
                formats.Value.transcodeFormat
                );

            Profiler.EndSample();

            while(!jobHandle.IsCompleted) {
                yield return null;
            }
            jobHandle.Complete();

            if(job.result[0]) {
                Profiler.BeginSample("LoadBytesRoutineGPUupload");
                uint width;
                uint height;
                meta.GetSize(out width,out height);
                var flags = TextureCreationFlags.None;
                if(meta.images[imageIndex].levels.Length>1) {
                    flags |= TextureCreationFlags.MipChain;
                }
                texture = new Texture2D((int)width,(int)height,formats.Value.format,flags);
                texture.LoadRawTextureData(job.textureData);
                texture.Apply(false,true);
                Profiler.EndSample();
            } else {
                Debug.LogError(ERR_MSG_TRANSCODE_FAILED);
            }
            job.sizes.Dispose();
            job.offsets.Dispose();
            job.textureData.Dispose();
            job.result.Dispose();
        }
    }`

Any help is appreciated.

atteneder commented 4 years ago

Hi @sarangborude,

Can you provide the mentioned texture for testing? (basis file, original file and encoding options ideally)

Loading "classic" normal maps (tangent space RGB) should work (you have to explicitely load it as linear texture; no sRGB), but ETC1s mode has lots of artifacts. One workaround is to use UASTC mode, the more profound solution is to encode the RG channels into a basis texture with two slices, where the color is the X- and the alpha channel is the Y component.

I presume you're trying the latter via the -separate_rg_to_color_alpha option of basisu, right? I haven't tried this yet myself. I presume I'd need to make changes in both the native library (C++) and the C# bindings for this to work.

If you want to try, a demo, how to override/explicitely set the texture format transcoded to can be found in the FormatTest scene of the KtxUnityDemo project:

https://github.com/atteneder/KtxUnityDemo/blob/5f14e9c426432dad9bbeaa8cbc0847b1a7b32bac/Assets/Scripts/FormatTest.cs#L105

But again, never tried RG normal maps so I doubt you'll get results quick.

atteneder commented 4 years ago

Created a feature issue #26