Calling nvdxt.exe (NVIDIA Texture Compression Tool) in C++ for Image to DDS Conversion

Calling nvdxt.exe (NVIDIA Texture Compression Tool) in C++ for Image to DDS Conversion

To call <span>nvdxt.exe</span> (NVIDIA Texture Compression Tool) in C++ for converting images to DDS format, command line parameters must be passed to specify the input file, output path, and compression format. Below is the complete implementation plan, including parameter descriptions, error handling, and code examples:

1. Core Parameter Descriptions of <span>nvdxt.exe</span>

<span>nvdxt.exe</span> controls the conversion behavior through command line parameters, with commonly used parameters as follows:

Parameter Function Example
<span>-file</span> Specifies the input image path (supports JPG/PNG/BMP, etc.) <span>-file "D:/textures/metal.png"</span>
<span>-output</span> Specifies the output DDS file path <span>-output "D:/textures/metal.dds"</span>
<span>-dxt1</span> Uses DXT1 compression (suitable for RGB textures without Alpha channel, compression ratio 4:1) <span>-dxt1</span>
<span>-dxt1a</span> Uses DXT1 compression (with 1-bit Alpha channel, suitable for hard-edge transparency) <span>-dxt1a</span>
<span>-dxt3</span> Uses DXT3 compression (with explicit Alpha channel, suitable for sharp transparent edges) <span>-dxt3</span>
<span>-dxt5</span> Uses DXT5 compression (with interpolated Alpha channel, suitable for semi-transparent effects like glass and smoke) <span>-dxt5</span>
<span>-3Dc</span> Uses 3Dc compression (suitable for normal maps, retains more detail) <span>-3Dc</span>
<span>-nomipmap</span> Does not generate Mipmap (by default, multi-level Mipmap is automatically generated for distant rendering optimization) <span>-nomipmap</span>
<span>-quality</span> Compression quality (0 = fastest, 3 = highest quality, default 1) <span>-quality 3</span>

Calling nvdxt.exe (NVIDIA Texture Compression Tool) in C++ for Image to DDS Conversion

2. Implementation Code for Calling <span>nvdxt.exe</span> in C++

The following code encapsulates the calling logic, supporting the setting of input and output paths, compression format, and includes complete error handling:

#include <windows.h>
#include <string>
#include <iostream>
#include <tchar.h>
// Compression format enumeration (corresponding to formats supported by nvdxt)
enum class NvdxtCompressionType {
    DXT1,    // No Alpha
    DXT1A,   // 1-bit Alpha
    DXT3,    // Explicit Alpha
    DXT5,    // Interpolated Alpha
    BC3n     // Normal map specific (3Dc)
};
/**
 * Call nvdxt.exe to convert an image to DDS
 * @param nvdxtPath Full path to nvdxt.exe
 * @param inputImagePath Input image path (e.g., JPG/PNG)
 * @param outputDdsPath Output DDS file path
 * @param compressionType Compression format
 * @param generateMipmap Whether to generate Mipmap (default is true)
 * @return Returns true if conversion is successful, false otherwise
 */
bool ConvertToDDS(const std::wstring& nvdxtPath,
                  const std::wstring& inputImagePath,
                  const std::wstring& outputDdsPath,
                  NvdxtCompressionType compressionType,
                  bool generateMipmap = true) {
    // 1. Check if nvdxt.exe exists
    if (GetFileAttributesW(nvdxtPath.c_str()) == INVALID_FILE_ATTRIBUTES) {
        std::wcerr << L"Error: nvdxt.exe does not exist - " << nvdxtPath << std::endl;
        return false;
    }
    // 2. Build command line parameters
    std::wstring cmdParams;
    cmdParams += L" -file \"" + inputImagePath + L"\"";       // Input file (path with spaces must be quoted)
    cmdParams += L" -output \"" + outputDdsPath + L"\"";     // Output file
    // Compression format parameters
    switch (compressionType) {
        case NvdxtCompressionType::DXT1:  cmdParams += L" -dxt1"; break;
        case NvdxtCompressionType::DXT1A: cmdParams += L" -dxt1a"; break;
        case NvdxtCompressionType::DXT3:  cmdParams += L" -dxt3"; break;
        case NvdxtCompressionType::DXT5:  cmdParams += L" -dxt5"; break;
        case NvdxtCompressionType::BC3n:  cmdParams += L" -3Dc"; break;
        default:             std::wcerr << L"Error: Unsupported compression format" << std::endl;
            return false;
    }
    // Whether to generate Mipmap
    if (!generateMipmap) {
        cmdParams += L" -nomipmap";
    }
    // 3. Call nvdxt.exe and wait for completion
    SHELLEXECUTEINFOW shExecInfo = {0};
    shExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW);
    shExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;  // Retain process handle for waiting
    shExecInfo.lpFile = nvdxtPath.c_str();       // Executable file path
    shExecInfo.lpParameters = cmdParams.c_str(); // Command line parameters
    shExecInfo.nShow = SW_HIDE;                  // Hide console window
    if (!ShellExecuteExW(&shExecInfo)) {
        DWORD errorCode = GetLastError();
        std::wcerr << L"Failed to call nvdxt.exe, error code:" << errorCode << std::endl;
        return false;
    }
    // Wait for conversion to complete (timeout set to 30 seconds to avoid infinite blocking)
    DWORD waitResult = WaitForSingleObject(shExecInfo.hProcess, 30000);
    if (waitResult != WAIT_OBJECT_0) {
        std::wcerr << L"Conversion timed out or was interrupted - " << inputImagePath << std::endl;
        TerminateProcess(shExecInfo.hProcess, 0); // Terminate process on timeout
        CloseHandle(shExecInfo.hProcess);
        return false;
    }
    // 4. Check if output file was generated
    if (GetFileAttributesW(outputDdsPath.c_str()) == INVALID_FILE_ATTRIBUTES) {
        std::wcerr << L"Conversion failed, DDS file not generated - " << outputDdsPath << std::endl;
        CloseHandle(shExecInfo.hProcess);
        return false;
    }
    // Release resources
    CloseHandle(shExecInfo.hProcess);
    std::wcout << L"Conversion successful - " << outputDdsPath << std::endl;
    return true;
}
// Usage example
int main() {
    // Configure paths (note: paths with spaces must be quoted, or use paths without spaces)
    std::wstring nvdxtPath = L"D:/tools/nvdxt.exe";
    std::wstring inputImage = L"D:/textures/metal_basecolor.png";
    std::wstring outputDds = L"D:/textures/metal_basecolor.dds";
    // Convert to DXT5 format with Alpha and generate Mipmap
    bool success = ConvertToDDS(
        nvdxtPath,
        inputImage,
        outputDds,
        NvdxtCompressionType::DXT5,  // Common DXT5 for base color map
        true
    );
    if (!success) {
        std::wcout << L"Conversion failed" << std::endl;
        return 1;
    }
    // Convert normal map (using 3Dc format)
    inputImage = L"D:/textures/metal_normal.png";
    outputDds = L"D:/textures/metal_normal.dds";
    success = ConvertToDDS(
        nvdxtPath,
        inputImage,
        outputDds,
        NvdxtCompressionType::BC3n,  // Normal map specific 3Dc format
        true
    );
    return 0;
}

3. Key Considerations

  1. Path Handling:

  • If the input/output paths contain spaces, they must be enclosed in double quotes (e.g., <span>-file "D:/my textures/metal.png"</span>), otherwise <span>nvdxt.exe</span> will fail to parse.
  • It is recommended to use absolute paths to avoid “file not found” errors caused by relative paths.
  • Compression Format Selection:

    • Base color maps (Albedo): Preferably use <span>DXT5</span> (with soft Alpha) or <span>DXT1</span> (no Alpha).
    • Normal maps: Must use <span>BC3n</span> (i.e., <span>-3Dc</span>), to retain normal vector precision.
    • Roughness/Metallic maps: Use <span>DXT1</span> (no Alpha) or <span>DXT5</span> (with Alpha channel to store additional information).
  • Error Handling:

    • Check if <span>nvdxt.exe</span> exists (using <span>GetFileAttributes</span>).
    • Capture the return value of <span>ShellExecuteEx</span> and use <span>GetLastError</span> to obtain specific errors (e.g., invalid path, insufficient permissions).
    • Set a timeout (e.g., 30 seconds) to avoid processes being blocked indefinitely due to exceptions.
  • Multithreading and Batch Processing:

    • If batch converting multiple files, you can call them in parallel using multithreading (be careful to control concurrency to avoid exhausting system resources).
    • The example uses <span>WaitForSingleObject</span> to synchronously wait for a single conversion to complete; for batch processing, you can change it to asynchronous waiting (e.g., <span>WaitForMultipleObjects</span>).

    Calling nvdxt.exe (NVIDIA Texture Compression Tool) in C++ for Image to DDS Conversion

    4. Common Issue Troubleshooting

    • “nvdxt.exe is not a valid Win32 application”: This may be due to the <span>nvdxt.exe</span> version being incompatible with the system (e.g., 32-bit tool running on a 64-bit system), you need to download the corresponding version.
    • Output DDS file size is 0: The input image format is unsupported (e.g., WebP), or there are conflicting compression parameters (e.g., using <span>-dxt1a</span> for an image without Alpha).
    • Mipmap generation exception: The input image dimensions are not powers of two (e.g., 256×256, 512×512), <span>nvdxt.exe</span> may generate incorrect Mipmaps, ensure the image dimensions meet the requirements.

    With the above implementation, you can reliably call <span>nvdxt.exe</span> to complete texture compression, suitable for integration into game resource packaging pipelines or texture processing tools.

    Leave a Comment