cleanup and refactoring

This commit is contained in:
CDaut 2024-05-25 11:53:25 +02:00
parent 2302158928
commit 76f6bf62a4
Signed by: clara
GPG key ID: 223391B52FAD4463
1285 changed files with 757994 additions and 8 deletions

View file

@ -0,0 +1,53 @@
## Table of Contents
- [khr_df.h](#khr_dfh)
- [nv_ktx.h](#nv_ktxh)
- [tiny_converter.hpp](#tiny_converterhpp)
## khr_df.h
This header defines a structure that can describe the layout of image
formats in memory. This means that the data format is transparent to
the application, and the expectation is that this should be used when
the layout is defined external to the API. Many Khronos APIs deliberately
keep the internal layout of images opaque, to allow proprietary layouts
and optimizations. This structure is not appropriate for describing
opaque layouts.
## nv_ktx.h
A mostly self-contained reader and writer for KTX2 files and reader for KTX1
files. Relies on Vulkan (for KTX2), GL (for KTX1), and the
Khronos Data Format.
Sample usage for reading files:
```cpp
KTXImage image;
ErrorWithText maybe_error = image.readFromFile("data/image.ktx2");
if(maybe_error.has_value())
{
// Do something with the error message, maybe_error.value()
}
else
{
// Access subresources using image.subresource(...), and upload them
// to the GPU using your graphics API of choice.
}
```
Define NVP_SUPPORTS_ZSTD, NVP_SUPPORTS_GZLIB, and NVP_SUPPORTS_BASISU to
include the Zstd, Zlib, and Basis Universal headers respectively, and to
enable reading these formats. This will also enable writing Zstd and
Basis Universal-compressed formats.
If you're using this inside the nvpro-samples framework, you can add all
three quickly by adding _add_package_KTX() to your dependencies
in CMakeLists.txt.
## tiny_converter.hpp
Class TinyConverter
> This class is used to convert a tinyobj::ObjReader to a tinygltf::Model.

View file

@ -0,0 +1,73 @@
/*
* Copyright (c) 2019-2021, NVIDIA CORPORATION. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-FileCopyrightText: Copyright (c) 2019-2021 NVIDIA CORPORATION
* SPDX-License-Identifier: Apache-2.0
*/
/// @DOC_SKIP (keyword to exclude this file from automatic README.md generation)
#pragma once
#include <stdio.h>
inline void saveBMP(const char* bmpfilename, int width, int height, const unsigned char* bgra)
{
#pragma pack(push, 1)
struct
{
unsigned short bfType;
unsigned int bfSize;
unsigned int bfReserved;
unsigned int bfOffBits;
unsigned int biSize;
signed int biWidth;
signed int biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned int biCompression;
unsigned int biSizeImage;
signed int biXPelsPerMeter;
signed int biYPelsPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
} bmpinfo;
#pragma pack(pop)
const unsigned int imageDataSize = width * height * 4 * static_cast<unsigned int>(sizeof(unsigned char));
bmpinfo.bfType = 19778;
bmpinfo.bfSize = static_cast<unsigned int>(sizeof(bmpinfo)) + imageDataSize;
bmpinfo.bfReserved = 0;
bmpinfo.bfOffBits = 54;
bmpinfo.biSize = 40;
bmpinfo.biWidth = width;
bmpinfo.biHeight = height;
bmpinfo.biPlanes = 1;
bmpinfo.biBitCount = 32;
bmpinfo.biCompression = 0;
bmpinfo.biSizeImage = 0;
bmpinfo.biXPelsPerMeter = 0;
bmpinfo.biYPelsPerMeter = 0;
bmpinfo.biClrUsed = 0;
bmpinfo.biClrImportant = 0;
FILE* bmpfile = fopen(bmpfilename, "wb");
fwrite(&bmpinfo, sizeof(bmpinfo), 1, bmpfile);
fwrite(bgra, sizeof(char), imageDataSize, bmpfile);
fclose(bmpfile);
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,633 @@
/* The Khronos Data Format Specification (version 1.3) */
/*
** Copyright (c) 2015-19 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
/** @DOC_START
This header defines a structure that can describe the layout of image
formats in memory. This means that the data format is transparent to
the application, and the expectation is that this should be used when
the layout is defined external to the API. Many Khronos APIs deliberately
keep the internal layout of images opaque, to allow proprietary layouts
and optimizations. This structure is not appropriate for describing
opaque layouts.
@DOC_END */
/* We stick to standard C89 constructs for simplicity and portability. */
#ifndef _KHR_DATA_FORMAT_H_
#define _KHR_DATA_FORMAT_H_
/* Accessors */
typedef enum _khr_word_e
{
KHR_DF_WORD_VENDORID = 0U,
KHR_DF_WORD_DESCRIPTORTYPE = 0U,
KHR_DF_WORD_VERSIONNUMBER = 1U,
KHR_DF_WORD_DESCRIPTORBLOCKSIZE = 1U,
KHR_DF_WORD_MODEL = 2U,
KHR_DF_WORD_PRIMARIES = 2U,
KHR_DF_WORD_TRANSFER = 2U,
KHR_DF_WORD_FLAGS = 2U,
KHR_DF_WORD_TEXELBLOCKDIMENSION0 = 3U,
KHR_DF_WORD_TEXELBLOCKDIMENSION1 = 3U,
KHR_DF_WORD_TEXELBLOCKDIMENSION2 = 3U,
KHR_DF_WORD_TEXELBLOCKDIMENSION3 = 3U,
KHR_DF_WORD_BYTESPLANE0 = 4U,
KHR_DF_WORD_BYTESPLANE1 = 4U,
KHR_DF_WORD_BYTESPLANE2 = 4U,
KHR_DF_WORD_BYTESPLANE3 = 4U,
KHR_DF_WORD_BYTESPLANE4 = 5U,
KHR_DF_WORD_BYTESPLANE5 = 5U,
KHR_DF_WORD_BYTESPLANE6 = 5U,
KHR_DF_WORD_BYTESPLANE7 = 5U,
KHR_DF_WORD_SAMPLESTART = 6U,
KHR_DF_WORD_SAMPLEWORDS = 4U
} khr_df_word_e;
typedef enum _khr_df_shift_e
{
KHR_DF_SHIFT_VENDORID = 0U,
KHR_DF_SHIFT_DESCRIPTORTYPE = 17U,
KHR_DF_SHIFT_VERSIONNUMBER = 0U,
KHR_DF_SHIFT_DESCRIPTORBLOCKSIZE = 16U,
KHR_DF_SHIFT_MODEL = 0U,
KHR_DF_SHIFT_PRIMARIES = 8U,
KHR_DF_SHIFT_TRANSFER = 16U,
KHR_DF_SHIFT_FLAGS = 24U,
KHR_DF_SHIFT_TEXELBLOCKDIMENSION0 = 0U,
KHR_DF_SHIFT_TEXELBLOCKDIMENSION1 = 8U,
KHR_DF_SHIFT_TEXELBLOCKDIMENSION2 = 16U,
KHR_DF_SHIFT_TEXELBLOCKDIMENSION3 = 24U,
KHR_DF_SHIFT_BYTESPLANE0 = 0U,
KHR_DF_SHIFT_BYTESPLANE1 = 8U,
KHR_DF_SHIFT_BYTESPLANE2 = 16U,
KHR_DF_SHIFT_BYTESPLANE3 = 24U,
KHR_DF_SHIFT_BYTESPLANE4 = 0U,
KHR_DF_SHIFT_BYTESPLANE5 = 8U,
KHR_DF_SHIFT_BYTESPLANE6 = 16U,
KHR_DF_SHIFT_BYTESPLANE7 = 24U
} khr_df_shift_e;
typedef enum _khr_df_mask_e
{
KHR_DF_MASK_VENDORID = 0x1FFFFU,
KHR_DF_MASK_DESCRIPTORTYPE = 0x7FFFU,
KHR_DF_MASK_VERSIONNUMBER = 0xFFFFU,
KHR_DF_MASK_DESCRIPTORBLOCKSIZE = 0xFFFFU,
KHR_DF_MASK_MODEL = 0xFFU,
KHR_DF_MASK_PRIMARIES = 0xFFU,
KHR_DF_MASK_TRANSFER = 0xFFU,
KHR_DF_MASK_FLAGS = 0xFFU,
KHR_DF_MASK_TEXELBLOCKDIMENSION0 = 0xFFU,
KHR_DF_MASK_TEXELBLOCKDIMENSION1 = 0xFFU,
KHR_DF_MASK_TEXELBLOCKDIMENSION2 = 0xFFU,
KHR_DF_MASK_TEXELBLOCKDIMENSION3 = 0xFFU,
KHR_DF_MASK_BYTESPLANE0 = 0xFFU,
KHR_DF_MASK_BYTESPLANE1 = 0xFFU,
KHR_DF_MASK_BYTESPLANE2 = 0xFFU,
KHR_DF_MASK_BYTESPLANE3 = 0xFFU,
KHR_DF_MASK_BYTESPLANE4 = 0xFFU,
KHR_DF_MASK_BYTESPLANE5 = 0xFFU,
KHR_DF_MASK_BYTESPLANE6 = 0xFFU,
KHR_DF_MASK_BYTESPLANE7 = 0xFFU
} khr_df_mask_e;
/* Helper macro:
Extract field X from basic descriptor block BDB */
#define KHR_DFDVAL(BDB, X) (((BDB)[KHR_DF_WORD_##X] >> (KHR_DF_SHIFT_##X)) & (KHR_DF_MASK_##X))
/* Helper macro:
Set field X of basic descriptor block BDB */
#define KHR_DFDSETVAL(BDB, X, val) \
((BDB)[KHR_DF_WORD_##X] = ((BDB)[KHR_DF_WORD_##X] & ~((KHR_DF_MASK_##X) << (KHR_DF_SHIFT_##X))) \
| (((val) & (KHR_DF_MASK_##X)) << (KHR_DF_SHIFT_##X)))
/* Offsets relative to the start of a sample */
typedef enum _khr_df_sampleword_e
{
KHR_DF_SAMPLEWORD_BITOFFSET = 0U,
KHR_DF_SAMPLEWORD_BITLENGTH = 0U,
KHR_DF_SAMPLEWORD_CHANNELID = 0U,
KHR_DF_SAMPLEWORD_QUALIFIERS = 0U,
KHR_DF_SAMPLEWORD_SAMPLEPOSITION0 = 1U,
KHR_DF_SAMPLEWORD_SAMPLEPOSITION1 = 1U,
KHR_DF_SAMPLEWORD_SAMPLEPOSITION2 = 1U,
KHR_DF_SAMPLEWORD_SAMPLEPOSITION3 = 1U,
KHR_DF_SAMPLEWORD_SAMPLEPOSITION_ALL = 1U,
KHR_DF_SAMPLEWORD_SAMPLELOWER = 2U,
KHR_DF_SAMPLEWORD_SAMPLEUPPER = 3U
} khr_df_sampleword_e;
typedef enum _khr_df_sampleshift_e
{
KHR_DF_SAMPLESHIFT_BITOFFSET = 0U,
KHR_DF_SAMPLESHIFT_BITLENGTH = 16U,
KHR_DF_SAMPLESHIFT_CHANNELID = 24U,
/* N.B. Qualifiers are defined as an offset into a byte */
KHR_DF_SAMPLESHIFT_QUALIFIERS = 24U,
KHR_DF_SAMPLESHIFT_SAMPLEPOSITION0 = 0U,
KHR_DF_SAMPLESHIFT_SAMPLEPOSITION1 = 8U,
KHR_DF_SAMPLESHIFT_SAMPLEPOSITION2 = 16U,
KHR_DF_SAMPLESHIFT_SAMPLEPOSITION3 = 24U,
KHR_DF_SAMPLESHIFT_SAMPLEPOSITION_ALL = 0U,
KHR_DF_SAMPLESHIFT_SAMPLELOWER = 0U,
KHR_DF_SAMPLESHIFT_SAMPLEUPPER = 0U
} khr_df_sampleshift_e;
typedef enum _khr_df_samplemask_e
{
KHR_DF_SAMPLEMASK_BITOFFSET = 0xFFFFU,
KHR_DF_SAMPLEMASK_BITLENGTH = 0xFF,
KHR_DF_SAMPLEMASK_CHANNELID = 0xF,
/* N.B. Qualifiers are defined as an offset into a byte */
KHR_DF_SAMPLEMASK_QUALIFIERS = 0xF0,
KHR_DF_SAMPLEMASK_SAMPLEPOSITION0 = 0xFF,
KHR_DF_SAMPLEMASK_SAMPLEPOSITION1 = 0xFF,
KHR_DF_SAMPLEMASK_SAMPLEPOSITION2 = 0xFF,
KHR_DF_SAMPLEMASK_SAMPLEPOSITION3 = 0xFF,
/* ISO C restricts enum values to range of int hence the
cast. We do it verbosely instead of using -1 to ensure
it is a 32-bit value even if int is 64 bits. */
KHR_DF_SAMPLEMASK_SAMPLEPOSITION_ALL = (int)0xFFFFFFFFU,
KHR_DF_SAMPLEMASK_SAMPLELOWER = (int)0xFFFFFFFFU,
KHR_DF_SAMPLEMASK_SAMPLEUPPER = (int)0xFFFFFFFFU
} khr_df_samplemask_e;
/* Helper macro:
Extract field X of sample S from basic descriptor block BDB */
#define KHR_DFDSVAL(BDB, S, X) \
(((BDB)[KHR_DF_WORD_SAMPLESTART + ((S) * KHR_DF_WORD_SAMPLEWORDS) + KHR_DF_SAMPLEWORD_##X] >> (KHR_DF_SAMPLESHIFT_##X)) \
& (KHR_DF_SAMPLEMASK_##X))
/* Helper macro:
Set field X of sample S of basic descriptor block BDB */
#define KHR_DFDSETSVAL(BDB, S, X, val) \
((BDB)[KHR_DF_WORD_SAMPLESTART + ((S) * KHR_DF_WORD_SAMPLEWORDS) + KHR_DF_SAMPLEWORD_##X] = \
((BDB)[KHR_DF_WORD_SAMPLESTART + ((S) * KHR_DF_WORD_SAMPLEWORDS) + KHR_DF_SAMPLEWORD_##X] \
& ~((uint32_t)(KHR_DF_SAMPLEMASK_##X) << (KHR_DF_SAMPLESHIFT_##X))) \
| (((val) & (uint32_t)(KHR_DF_SAMPLEMASK_##X)) << (KHR_DF_SAMPLESHIFT_##X)))
/* Helper macro:
Number of samples in basic descriptor block BDB */
#define KHR_DFDSAMPLECOUNT(BDB) \
(((KHR_DFDVAL(BDB, DESCRIPTORBLOCKSIZE) >> 2) - KHR_DF_WORD_SAMPLESTART) / KHR_DF_WORD_SAMPLEWORDS)
/* Helper macro:
Size in words of basic descriptor block for S samples */
#define KHR_DFDSIZEWORDS(S) (KHR_DF_WORD_SAMPLESTART + (S) * KHR_DF_WORD_SAMPLEWORDS)
/* Vendor ids */
typedef enum _khr_df_vendorid_e
{
/* Standard Khronos descriptor */
KHR_DF_VENDORID_KHRONOS = 0U,
KHR_DF_VENDORID_MAX = 0x1FFFFU
} khr_df_vendorid_e;
/* Descriptor types */
typedef enum _khr_df_khr_descriptortype_e
{
/* Default Khronos basic descriptor block */
KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT = 0U,
/* Extension descriptor block for additional planes */
KHR_DF_KHR_DESCRIPTORTYPE_ADDITIONAL_PLANES = 0x6001U,
/* Extension descriptor block for additional dimensions */
KHR_DF_KHR_DESCRIPTORTYPE_ADDITIONAL_DIMENSIONS = 0x6002U,
/* Bit indicates modifying requires understanding this extension */
KHR_DF_KHR_DESCRIPTORTYPE_NEEDED_FOR_WRITE_BIT = 0x2000U,
/* Bit indicates processing requires understanding this extension */
KHR_DF_KHR_DESCRIPTORTYPE_NEEDED_FOR_DECODE_BIT = 0x4000U,
KHR_DF_KHR_DESCRIPTORTYPE_MAX = 0x7FFFU
} khr_df_khr_descriptortype_e;
/* Descriptor block version */
typedef enum _khr_df_versionnumber_e
{
/* Standard Khronos descriptor */
KHR_DF_VERSIONNUMBER_1_0 = 0U, /* Version 1.0 of the specification */
KHR_DF_VERSIONNUMBER_1_1 = 0U, /* Version 1.1 did not bump the version number */
KHR_DF_VERSIONNUMBER_1_2 = 1U, /* Version 1.2 increased the version number */
KHR_DF_VERSIONNUMBER_1_3 = 2U, /* Version 1.3 increased the version number */
KHR_DF_VERSIONNUMBER_LATEST = KHR_DF_VERSIONNUMBER_1_3,
KHR_DF_VERSIONNUMBER_MAX = 0xFFFFU
} khr_df_versionnumber_e;
/* Model in which the color coordinate space is defined.
There is no requirement that a color format use all the
channel types that are defined in the color model. */
typedef enum _khr_df_model_e
{
/* No interpretation of color channels defined */
KHR_DF_MODEL_UNSPECIFIED = 0U,
/* Color primaries (red, green, blue) + alpha, depth and stencil */
KHR_DF_MODEL_RGBSDA = 1U,
/* Color differences (Y', Cb, Cr) + alpha, depth and stencil */
KHR_DF_MODEL_YUVSDA = 2U,
/* Color differences (Y', I, Q) + alpha, depth and stencil */
KHR_DF_MODEL_YIQSDA = 3U,
/* Perceptual color (CIE L*a*b*) + alpha, depth and stencil */
KHR_DF_MODEL_LABSDA = 4U,
/* Subtractive colors (cyan, magenta, yellow, black) + alpha */
KHR_DF_MODEL_CMYKA = 5U,
/* Non-color coordinate data (X, Y, Z, W) */
KHR_DF_MODEL_XYZW = 6U,
/* Hue, saturation, value, hue angle on color circle, plus alpha */
KHR_DF_MODEL_HSVA_ANG = 7U,
/* Hue, saturation, lightness, hue angle on color circle, plus alpha */
KHR_DF_MODEL_HSLA_ANG = 8U,
/* Hue, saturation, value, hue on color hexagon, plus alpha */
KHR_DF_MODEL_HSVA_HEX = 9U,
/* Hue, saturation, lightness, hue on color hexagon, plus alpha */
KHR_DF_MODEL_HSLA_HEX = 10U,
/* Lightweight approximate color difference (luma, orange, green) */
KHR_DF_MODEL_YCGCOA = 11U,
/* ITU BT.2020 constant luminance YcCbcCrc */
KHR_DF_MODEL_YCCBCCRC = 12U,
/* ITU BT.2100 constant intensity ICtCp */
KHR_DF_MODEL_ICTCP = 13U,
/* CIE 1931 XYZ color coordinates (X, Y, Z) */
KHR_DF_MODEL_CIEXYZ = 14U,
/* CIE 1931 xyY color coordinates (X, Y, Y) */
KHR_DF_MODEL_CIEXYY = 15U,
/* Compressed formats start at 128. */
/* These compressed formats should generally have a single sample,
sited at the 0,0 position of the texel block. Where multiple
channels are used to distinguish formats, these should be cosited. */
/* Direct3D (and S3) compressed formats */
/* Note that premultiplied status is recorded separately */
/* DXT1 "channels" are RGB (0), Alpha (1) */
/* DXT1/BC1 with one channel is opaque */
/* DXT1/BC1 with a cosited alpha sample is transparent */
KHR_DF_MODEL_DXT1A = 128U,
KHR_DF_MODEL_BC1A = 128U,
/* DXT2/DXT3/BC2, with explicit 4-bit alpha */
KHR_DF_MODEL_DXT2 = 129U,
KHR_DF_MODEL_DXT3 = 129U,
KHR_DF_MODEL_BC2 = 129U,
/* DXT4/DXT5/BC3, with interpolated alpha */
KHR_DF_MODEL_DXT4 = 130U,
KHR_DF_MODEL_DXT5 = 130U,
KHR_DF_MODEL_BC3 = 130U,
/* BC4 - single channel interpolated 8-bit data */
/* (The UNORM/SNORM variation is recorded in the channel data) */
KHR_DF_MODEL_BC4 = 131U,
/* BC5 - two channel interpolated 8-bit data */
/* (The UNORM/SNORM variation is recorded in the channel data) */
KHR_DF_MODEL_BC5 = 132U,
/* BC6H - DX11 format for 16-bit float channels */
KHR_DF_MODEL_BC6H = 133U,
/* BC7 - DX11 format */
KHR_DF_MODEL_BC7 = 134U,
/* Gap left for future desktop expansion */
/* Mobile compressed formats follow */
/* A format of ETC1 indicates that the format shall be decodable
by an ETC1-compliant decoder and not rely on ETC2 features */
KHR_DF_MODEL_ETC1 = 160U,
/* A format of ETC2 is permitted to use ETC2 encodings on top of
the baseline ETC1 specification */
/* The ETC2 format has channels "red", "green", "RGB" and "alpha",
which should be cosited samples */
/* Punch-through alpha can be distinguished from full alpha by
the plane size in bytes required for the texel block */
KHR_DF_MODEL_ETC2 = 161U,
/* Adaptive Scalable Texture Compression */
/* ASTC HDR vs LDR is determined by the float flag in the channel */
/* ASTC block size can be distinguished by texel block size */
KHR_DF_MODEL_ASTC = 162U,
/* ETC1S is a simplified subset of ETC1 */
KHR_DF_MODEL_ETC1S = 163U,
/* PowerVR Texture Compression */
KHR_DF_MODEL_PVRTC = 164U,
KHR_DF_MODEL_PVRTC2 = 165U,
/* Proprietary formats (ATITC, etc.) should follow */
KHR_DF_MODEL_MAX = 0xFFU
} khr_df_model_e;
/* Definition of channel names for each color model */
typedef enum _khr_df_model_channels_e
{
/* Unspecified format with nominal channel numbering */
KHR_DF_CHANNEL_UNSPECIFIED_0 = 0U,
KHR_DF_CHANNEL_UNSPECIFIED_1 = 1U,
KHR_DF_CHANNEL_UNSPECIFIED_2 = 2U,
KHR_DF_CHANNEL_UNSPECIFIED_3 = 3U,
KHR_DF_CHANNEL_UNSPECIFIED_4 = 4U,
KHR_DF_CHANNEL_UNSPECIFIED_5 = 5U,
KHR_DF_CHANNEL_UNSPECIFIED_6 = 6U,
KHR_DF_CHANNEL_UNSPECIFIED_7 = 7U,
KHR_DF_CHANNEL_UNSPECIFIED_8 = 8U,
KHR_DF_CHANNEL_UNSPECIFIED_9 = 9U,
KHR_DF_CHANNEL_UNSPECIFIED_10 = 10U,
KHR_DF_CHANNEL_UNSPECIFIED_11 = 11U,
KHR_DF_CHANNEL_UNSPECIFIED_12 = 12U,
KHR_DF_CHANNEL_UNSPECIFIED_13 = 13U,
KHR_DF_CHANNEL_UNSPECIFIED_14 = 14U,
KHR_DF_CHANNEL_UNSPECIFIED_15 = 15U,
/* MODEL_RGBSDA - red, green, blue, stencil, depth, alpha */
KHR_DF_CHANNEL_RGBSDA_RED = 0U,
KHR_DF_CHANNEL_RGBSDA_R = 0U,
KHR_DF_CHANNEL_RGBSDA_GREEN = 1U,
KHR_DF_CHANNEL_RGBSDA_G = 1U,
KHR_DF_CHANNEL_RGBSDA_BLUE = 2U,
KHR_DF_CHANNEL_RGBSDA_B = 2U,
KHR_DF_CHANNEL_RGBSDA_STENCIL = 13U,
KHR_DF_CHANNEL_RGBSDA_S = 13U,
KHR_DF_CHANNEL_RGBSDA_DEPTH = 14U,
KHR_DF_CHANNEL_RGBSDA_D = 14U,
KHR_DF_CHANNEL_RGBSDA_ALPHA = 15U,
KHR_DF_CHANNEL_RGBSDA_A = 15U,
/* MODEL_YUVSDA - luma, Cb, Cr, stencil, depth, alpha */
KHR_DF_CHANNEL_YUVSDA_Y = 0U,
KHR_DF_CHANNEL_YUVSDA_CB = 1U,
KHR_DF_CHANNEL_YUVSDA_U = 1U,
KHR_DF_CHANNEL_YUVSDA_CR = 2U,
KHR_DF_CHANNEL_YUVSDA_V = 2U,
KHR_DF_CHANNEL_YUVSDA_STENCIL = 13U,
KHR_DF_CHANNEL_YUVSDA_S = 13U,
KHR_DF_CHANNEL_YUVSDA_DEPTH = 14U,
KHR_DF_CHANNEL_YUVSDA_D = 14U,
KHR_DF_CHANNEL_YUVSDA_ALPHA = 15U,
KHR_DF_CHANNEL_YUVSDA_A = 15U,
/* MODEL_YIQSDA - luma, in-phase, quadrature, stencil, depth, alpha */
KHR_DF_CHANNEL_YIQSDA_Y = 0U,
KHR_DF_CHANNEL_YIQSDA_I = 1U,
KHR_DF_CHANNEL_YIQSDA_Q = 2U,
KHR_DF_CHANNEL_YIQSDA_STENCIL = 13U,
KHR_DF_CHANNEL_YIQSDA_S = 13U,
KHR_DF_CHANNEL_YIQSDA_DEPTH = 14U,
KHR_DF_CHANNEL_YIQSDA_D = 14U,
KHR_DF_CHANNEL_YIQSDA_ALPHA = 15U,
KHR_DF_CHANNEL_YIQSDA_A = 15U,
/* MODEL_LABSDA - CIELAB/L*a*b* luma, red-green, blue-yellow, stencil, depth, alpha */
KHR_DF_CHANNEL_LABSDA_L = 0U,
KHR_DF_CHANNEL_LABSDA_A = 1U,
KHR_DF_CHANNEL_LABSDA_B = 2U,
KHR_DF_CHANNEL_LABSDA_STENCIL = 13U,
KHR_DF_CHANNEL_LABSDA_S = 13U,
KHR_DF_CHANNEL_LABSDA_DEPTH = 14U,
KHR_DF_CHANNEL_LABSDA_D = 14U,
KHR_DF_CHANNEL_LABSDA_ALPHA = 15U,
/* NOTE: KHR_DF_CHANNEL_LABSDA_A is not a synonym for alpha! */
/* MODEL_CMYKA - cyan, magenta, yellow, key/blacK, alpha */
KHR_DF_CHANNEL_CMYKSDA_CYAN = 0U,
KHR_DF_CHANNEL_CMYKSDA_C = 0U,
KHR_DF_CHANNEL_CMYKSDA_MAGENTA = 1U,
KHR_DF_CHANNEL_CMYKSDA_M = 1U,
KHR_DF_CHANNEL_CMYKSDA_YELLOW = 2U,
KHR_DF_CHANNEL_CMYKSDA_Y = 2U,
KHR_DF_CHANNEL_CMYKSDA_KEY = 3U,
KHR_DF_CHANNEL_CMYKSDA_BLACK = 3U,
KHR_DF_CHANNEL_CMYKSDA_K = 3U,
KHR_DF_CHANNEL_CMYKSDA_ALPHA = 15U,
KHR_DF_CHANNEL_CMYKSDA_A = 15U,
/* MODEL_XYZW - coordinates x, y, z, w */
KHR_DF_CHANNEL_XYZW_X = 0U,
KHR_DF_CHANNEL_XYZW_Y = 1U,
KHR_DF_CHANNEL_XYZW_Z = 2U,
KHR_DF_CHANNEL_XYZW_W = 3U,
/* MODEL_HSVA_ANG - value (luma), saturation, hue, alpha, angular projection, conical space */
KHR_DF_CHANNEL_HSVA_ANG_VALUE = 0U,
KHR_DF_CHANNEL_HSVA_ANG_V = 0U,
KHR_DF_CHANNEL_HSVA_ANG_SATURATION = 1U,
KHR_DF_CHANNEL_HSVA_ANG_S = 1U,
KHR_DF_CHANNEL_HSVA_ANG_HUE = 2U,
KHR_DF_CHANNEL_HSVA_ANG_H = 2U,
KHR_DF_CHANNEL_HSVA_ANG_ALPHA = 15U,
KHR_DF_CHANNEL_HSVA_ANG_A = 15U,
/* MODEL_HSLA_ANG - lightness (luma), saturation, hue, alpha, angular projection, double conical space */
KHR_DF_CHANNEL_HSLA_ANG_LIGHTNESS = 0U,
KHR_DF_CHANNEL_HSLA_ANG_L = 0U,
KHR_DF_CHANNEL_HSLA_ANG_SATURATION = 1U,
KHR_DF_CHANNEL_HSLA_ANG_S = 1U,
KHR_DF_CHANNEL_HSLA_ANG_HUE = 2U,
KHR_DF_CHANNEL_HSLA_ANG_H = 2U,
KHR_DF_CHANNEL_HSLA_ANG_ALPHA = 15U,
KHR_DF_CHANNEL_HSLA_ANG_A = 15U,
/* MODEL_HSVA_HEX - value (luma), saturation, hue, alpha, hexagonal projection, conical space */
KHR_DF_CHANNEL_HSVA_HEX_VALUE = 0U,
KHR_DF_CHANNEL_HSVA_HEX_V = 0U,
KHR_DF_CHANNEL_HSVA_HEX_SATURATION = 1U,
KHR_DF_CHANNEL_HSVA_HEX_S = 1U,
KHR_DF_CHANNEL_HSVA_HEX_HUE = 2U,
KHR_DF_CHANNEL_HSVA_HEX_H = 2U,
KHR_DF_CHANNEL_HSVA_HEX_ALPHA = 15U,
KHR_DF_CHANNEL_HSVA_HEX_A = 15U,
/* MODEL_HSLA_HEX - lightness (luma), saturation, hue, alpha, hexagonal projection, double conical space */
KHR_DF_CHANNEL_HSLA_HEX_LIGHTNESS = 0U,
KHR_DF_CHANNEL_HSLA_HEX_L = 0U,
KHR_DF_CHANNEL_HSLA_HEX_SATURATION = 1U,
KHR_DF_CHANNEL_HSLA_HEX_S = 1U,
KHR_DF_CHANNEL_HSLA_HEX_HUE = 2U,
KHR_DF_CHANNEL_HSLA_HEX_H = 2U,
KHR_DF_CHANNEL_HSLA_HEX_ALPHA = 15U,
KHR_DF_CHANNEL_HSLA_HEX_A = 15U,
/* MODEL_YCGCOA - luma, green delta, orange delta, alpha */
KHR_DF_CHANNEL_YCGCOA_Y = 0U,
KHR_DF_CHANNEL_YCGCOA_CG = 1U,
KHR_DF_CHANNEL_YCGCOA_CO = 2U,
KHR_DF_CHANNEL_YCGCOA_ALPHA = 15U,
KHR_DF_CHANNEL_YCGCOA_A = 15U,
/* MODEL_CIEXYZ - CIE 1931 X, Y, Z */
KHR_DF_CHANNEL_CIEXYZ_X = 0U,
KHR_DF_CHANNEL_CIEXYZ_Y = 1U,
KHR_DF_CHANNEL_CIEXYZ_Z = 2U,
/* MODEL_CIEXYY - CIE 1931 x, y, Y */
KHR_DF_CHANNEL_CIEXYY_X = 0U,
KHR_DF_CHANNEL_CIEXYY_YCHROMA = 1U,
KHR_DF_CHANNEL_CIEXYY_YLUMA = 2U,
/* Compressed formats */
/* MODEL_DXT1A/MODEL_BC1A */
KHR_DF_CHANNEL_DXT1A_COLOR = 0U,
KHR_DF_CHANNEL_BC1A_COLOR = 0U,
KHR_DF_CHANNEL_DXT1A_ALPHAPRESENT = 1U,
KHR_DF_CHANNEL_DXT1A_ALPHA = 1U,
KHR_DF_CHANNEL_BC1A_ALPHAPRESENT = 1U,
KHR_DF_CHANNEL_BC1A_ALPHA = 1U,
/* MODEL_DXT2/3/MODEL_BC2 */
KHR_DF_CHANNEL_DXT2_COLOR = 0U,
KHR_DF_CHANNEL_DXT3_COLOR = 0U,
KHR_DF_CHANNEL_BC2_COLOR = 0U,
KHR_DF_CHANNEL_DXT2_ALPHA = 15U,
KHR_DF_CHANNEL_DXT3_ALPHA = 15U,
KHR_DF_CHANNEL_BC2_ALPHA = 15U,
/* MODEL_DXT4/5/MODEL_BC3 */
KHR_DF_CHANNEL_DXT4_COLOR = 0U,
KHR_DF_CHANNEL_DXT5_COLOR = 0U,
KHR_DF_CHANNEL_BC3_COLOR = 0U,
KHR_DF_CHANNEL_DXT4_ALPHA = 15U,
KHR_DF_CHANNEL_DXT5_ALPHA = 15U,
KHR_DF_CHANNEL_BC3_ALPHA = 15U,
/* MODEL_BC4 */
KHR_DF_CHANNEL_BC4_DATA = 0U,
/* MODEL_BC5 */
KHR_DF_CHANNEL_BC5_RED = 0U,
KHR_DF_CHANNEL_BC5_R = 0U,
KHR_DF_CHANNEL_BC5_GREEN = 1U,
KHR_DF_CHANNEL_BC5_G = 1U,
/* MODEL_BC6H */
KHR_DF_CHANNEL_BC6H_COLOR = 0U,
KHR_DF_CHANNEL_BC6H_DATA = 0U,
/* MODEL_BC7 */
KHR_DF_CHANNEL_BC7_DATA = 0U,
KHR_DF_CHANNEL_BC7_COLOR = 0U,
/* MODEL_ETC1 */
KHR_DF_CHANNEL_ETC1_DATA = 0U,
KHR_DF_CHANNEL_ETC1_COLOR = 0U,
/* MODEL_ETC2 */
KHR_DF_CHANNEL_ETC2_RED = 0U,
KHR_DF_CHANNEL_ETC2_R = 0U,
KHR_DF_CHANNEL_ETC2_GREEN = 1U,
KHR_DF_CHANNEL_ETC2_G = 1U,
KHR_DF_CHANNEL_ETC2_COLOR = 2U,
KHR_DF_CHANNEL_ETC2_ALPHA = 15U,
KHR_DF_CHANNEL_ETC2_A = 15U,
/* MODEL_ASTC */
KHR_DF_CHANNEL_ASTC_DATA = 0U,
/* MODEL_ETC1S */
KHR_DF_CHANNEL_ETC1S_DATA = 0U,
KHR_DF_CHANNEL_ETC1S_COLOR = 0U,
/* MODEL_PVRTC */
KHR_DF_CHANNEL_PVRTC_DATA = 0U,
KHR_DF_CHANNEL_PVRTC_COLOR = 0U,
/* MODEL_PVRTC2 */
KHR_DF_CHANNEL_PVRTC2_DATA = 0U,
KHR_DF_CHANNEL_PVRTC2_COLOR = 0U,
/* Common channel names shared by multiple formats */
KHR_DF_CHANNEL_COMMON_LUMA = 0U,
KHR_DF_CHANNEL_COMMON_L = 0U,
KHR_DF_CHANNEL_COMMON_STENCIL = 13U,
KHR_DF_CHANNEL_COMMON_S = 13U,
KHR_DF_CHANNEL_COMMON_DEPTH = 14U,
KHR_DF_CHANNEL_COMMON_D = 14U,
KHR_DF_CHANNEL_COMMON_ALPHA = 15U,
KHR_DF_CHANNEL_COMMON_A = 15U
} khr_df_model_channels_e;
/* Definition of the primary colors in color coordinates.
This is implicitly responsible for defining the conversion
between RGB an YUV color spaces.
LAB and related absolute color models should use
KHR_DF_PRIMARIES_CIEXYZ. */
typedef enum _khr_df_primaries_e
{
/* No color primaries defined */
KHR_DF_PRIMARIES_UNSPECIFIED = 0U,
/* Color primaries of ITU-R BT.709 and sRGB */
KHR_DF_PRIMARIES_BT709 = 1U,
/* Synonym for KHR_DF_PRIMARIES_BT709 */
KHR_DF_PRIMARIES_SRGB = 1U,
/* Color primaries of ITU-R BT.601 (625-line EBU variant) */
KHR_DF_PRIMARIES_BT601_EBU = 2U,
/* Color primaries of ITU-R BT.601 (525-line SMPTE C variant) */
KHR_DF_PRIMARIES_BT601_SMPTE = 3U,
/* Color primaries of ITU-R BT.2020 */
KHR_DF_PRIMARIES_BT2020 = 4U,
/* CIE theoretical color coordinate space */
KHR_DF_PRIMARIES_CIEXYZ = 5U,
/* Academy Color Encoding System primaries */
KHR_DF_PRIMARIES_ACES = 6U,
/* Color primaries of ACEScc */
KHR_DF_PRIMARIES_ACESCC = 7U,
/* Legacy NTSC 1953 primaries */
KHR_DF_PRIMARIES_NTSC1953 = 8U,
/* Legacy PAL 525-line primaries */
KHR_DF_PRIMARIES_PAL525 = 9U,
/* Color primaries of Display P3 */
KHR_DF_PRIMARIES_DISPLAYP3 = 10U,
/* Color primaries of Adobe RGB (1998) */
KHR_DF_PRIMARIES_ADOBERGB = 11U,
KHR_DF_PRIMARIES_MAX = 0xFFU
} khr_df_primaries_e;
/* Definition of the optical to digital transfer function
("gamma correction"). Most transfer functions are not a pure
power function and also include a linear element.
LAB and related absolute color representations should use
KHR_DF_TRANSFER_UNSPECIFIED. */
typedef enum _khr_df_transfer_e
{
/* No transfer function defined */
KHR_DF_TRANSFER_UNSPECIFIED = 0U,
/* Linear transfer function (value proportional to intensity) */
KHR_DF_TRANSFER_LINEAR = 1U,
/* Perceptually-linear transfer function of sRGH (~2.4) */
KHR_DF_TRANSFER_SRGB = 2U,
/* Perceptually-linear transfer function of ITU non-HDR specifications (~1/.45) */
KHR_DF_TRANSFER_ITU = 3U,
/* SMTPE170M (digital NTSC) defines an alias for the ITU transfer function (~1/.45) */
KHR_DF_TRANSFER_SMTPE170M = 3U,
/* Perceptually-linear gamma function of original NTSC (simple 2.2 gamma) */
KHR_DF_TRANSFER_NTSC = 4U,
/* Sony S-log used by Sony video cameras */
KHR_DF_TRANSFER_SLOG = 5U,
/* Sony S-log 2 used by Sony video cameras */
KHR_DF_TRANSFER_SLOG2 = 6U,
/* ITU BT.1886 EOTF */
KHR_DF_TRANSFER_BT1886 = 7U,
/* ITU BT.2100 HLG OETF */
KHR_DF_TRANSFER_HLG_OETF = 8U,
/* ITU BT.2100 HLG EOTF */
KHR_DF_TRANSFER_HLG_EOTF = 9U,
/* ITU BT.2100 PQ EOTF */
KHR_DF_TRANSFER_PQ_EOTF = 10U,
/* ITU BT.2100 PQ OETF */
KHR_DF_TRANSFER_PQ_OETF = 11U,
/* DCI P3 transfer function */
KHR_DF_TRANSFER_DCIP3 = 12U,
/* Legacy PAL OETF */
KHR_DF_TRANSFER_PAL_OETF = 13U,
/* Legacy PAL 625-line EOTF */
KHR_DF_TRANSFER_PAL625_EOTF = 14U,
/* Legacy ST240 transfer function */
KHR_DF_TRANSFER_ST240 = 15U,
/* ACEScc transfer function */
KHR_DF_TRANSFER_ACESCC = 16U,
/* ACEScct transfer function */
KHR_DF_TRANSFER_ACESCCT = 17U,
/* Adobe RGB (1998) transfer function */
KHR_DF_TRANSFER_ADOBERGB = 18U,
KHR_DF_TRANSFER_MAX = 0xFFU
} khr_df_transfer_e;
typedef enum _khr_df_flags_e
{
KHR_DF_FLAG_ALPHA_STRAIGHT = 0U,
KHR_DF_FLAG_ALPHA_PREMULTIPLIED = 1U
} khr_df_flags_e;
typedef enum _khr_df_sample_datatype_qualifiers_e
{
KHR_DF_SAMPLE_DATATYPE_LINEAR = 1U << 4U,
KHR_DF_SAMPLE_DATATYPE_EXPONENT = 1U << 5U,
KHR_DF_SAMPLE_DATATYPE_SIGNED = 1U << 6U,
KHR_DF_SAMPLE_DATATYPE_FLOAT = 1U << 7U
} khr_df_sample_datatype_qualifiers_e;
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,357 @@
/*
* Copyright (c) 2016-2021, NVIDIA CORPORATION. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-FileCopyrightText: Copyright (c) 2016-2021 NVIDIA CORPORATION
* SPDX-License-Identifier: Apache-2.0
*/
//--------------------------------------------------------------------
/// @DOC_SKIP (keyword to exclude this file from automatic README.md generation)
#ifndef __DDS_H__
#define __DDS_H__
#if defined(WIN32)
#include <windows.h>
#endif
#include <assert.h>
#include <deque>
#include <stdint.h>
#include <string>
#define COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
#define COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
#define COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
#define COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
#define RED 0x1903
#define RG8 0x822B
#define RGB8 0x8051
#define RGBA8 0x8058
#define BGR_EXT 0x80E0
#define BGRA_EXT 0x80E1
#define LUMINANCE 0x1909
namespace nv_dds {
// surface description flags
const uint32_t DDSF_CAPS = 0x00000001l;
const uint32_t DDSF_HEIGHT = 0x00000002l;
const uint32_t DDSF_WIDTH = 0x00000004l;
const uint32_t DDSF_PITCH = 0x00000008l;
const uint32_t DDSF_PIXELFORMAT = 0x00001000l;
const uint32_t DDSF_MIPMAPCOUNT = 0x00020000l;
const uint32_t DDSF_LINEARSIZE = 0x00080000l;
const uint32_t DDSF_DEPTH = 0x00800000l;
// pixel format flags
const uint32_t DDSF_ALPHAPIXELS = 0x00000001l;
const uint32_t DDSF_FOURCC = 0x00000004l;
const uint32_t DDSF_RGB = 0x00000040l;
const uint32_t DDSF_RGBA = 0x00000041l;
// dwCaps1 flags
const uint32_t DDSF_COMPLEX = 0x00000008l;
const uint32_t DDSF_TEXTURE = 0x00001000l;
const uint32_t DDSF_MIPMAP = 0x00400000l;
// dwCaps2 flags
const uint32_t DDSF_CUBEMAP = 0x00000200l;
const uint32_t DDSF_CUBEMAP_POSITIVEX = 0x00000400l;
const uint32_t DDSF_CUBEMAP_NEGATIVEX = 0x00000800l;
const uint32_t DDSF_CUBEMAP_POSITIVEY = 0x00001000l;
const uint32_t DDSF_CUBEMAP_NEGATIVEY = 0x00002000l;
const uint32_t DDSF_CUBEMAP_POSITIVEZ = 0x00004000l;
const uint32_t DDSF_CUBEMAP_NEGATIVEZ = 0x00008000l;
const uint32_t DDSF_CUBEMAP_ALL_FACES = 0x0000FC00l;
const uint32_t DDSF_VOLUME = 0x00200000l;
// compressed texture types
const uint32_t FOURCC_DXT1 = 0x31545844l; //(MAKEFOURCC('D','X','T','1'))
const uint32_t FOURCC_DXT3 = 0x33545844l; //(MAKEFOURCC('D','X','T','3'))
const uint32_t FOURCC_DXT5 = 0x35545844l; //(MAKEFOURCC('D','X','T','5'))
struct DXTColBlock
{
unsigned short col0;
unsigned short col1;
unsigned char row[4];
};
struct DXT3AlphaBlock
{
unsigned short row[4];
};
struct DXT5AlphaBlock
{
unsigned char alpha0;
unsigned char alpha1;
unsigned char row[6];
};
struct DDS_PIXELFORMAT
{
uint32_t dwSize;
uint32_t dwFlags;
uint32_t dwFourCC;
uint32_t dwRGBBitCount;
uint32_t dwRBitMask;
uint32_t dwGBitMask;
uint32_t dwBBitMask;
uint32_t dwABitMask;
};
struct DDS_HEADER
{
uint32_t dwSize;
uint32_t dwFlags;
uint32_t dwHeight;
uint32_t dwWidth;
uint32_t dwPitchOrLinearSize;
uint32_t dwDepth;
uint32_t dwMipMapCount;
uint32_t dwReserved1[11];
DDS_PIXELFORMAT ddspf;
uint32_t dwCaps1;
uint32_t dwCaps2;
uint32_t dwReserved2[3];
};
enum TextureType
{
TextureNone,
TextureFlat, // 1D, 2D, and rectangle textures
Texture3D,
TextureCubemap
};
class CSurface
{
public:
CSurface();
CSurface(unsigned int w, unsigned int h, unsigned int d, unsigned int imgsize, const unsigned char* pixels);
CSurface(const CSurface& copy);
CSurface& operator=(const CSurface& rhs);
virtual ~CSurface();
operator unsigned char*() const;
virtual void create(unsigned int w, unsigned int h, unsigned int d, unsigned int imgsize, const unsigned char* pixels);
virtual void clear();
inline unsigned int get_width() const { return m_width; }
inline unsigned int get_height() const { return m_height; }
inline unsigned int get_depth() const { return m_depth; }
inline unsigned int get_size() const { return m_size; }
private:
unsigned int m_width;
unsigned int m_height;
unsigned int m_depth;
unsigned int m_size;
unsigned char* m_pixels;
};
class CTexture : public CSurface
{
friend class CDDSImage;
public:
CTexture();
CTexture(unsigned int w, unsigned int h, unsigned int d, unsigned int imgsize, const unsigned char* pixels);
CTexture(const CTexture& copy);
CTexture& operator=(const CTexture& rhs);
~CTexture();
void create(unsigned int w, unsigned int h, unsigned int d, unsigned int imgsize, const unsigned char* pixels);
void clear();
inline const CSurface& get_mipmap(unsigned int index) const
{
assert(!m_mipmaps.empty());
assert(index < m_mipmaps.size());
return m_mipmaps[index];
}
inline void add_mipmap(const CSurface& mipmap) { m_mipmaps.push_back(mipmap); }
inline unsigned int get_num_mipmaps() const { return (unsigned int)m_mipmaps.size(); }
protected:
inline CSurface& get_mipmap(unsigned int index)
{
assert(!m_mipmaps.empty());
assert(index < m_mipmaps.size());
return m_mipmaps[index];
}
private:
std::deque<CSurface> m_mipmaps;
};
class CDDSImage
{
public:
CDDSImage();
virtual ~CDDSImage();
void create_textureFlat(unsigned int format, unsigned int components, const CTexture& baseImage);
void create_texture3D(unsigned int format, unsigned int components, const CTexture& baseImage);
void create_textureCubemap(unsigned int format,
unsigned int components,
const CTexture& positiveX,
const CTexture& negativeX,
const CTexture& positiveY,
const CTexture& negativeY,
const CTexture& positiveZ,
const CTexture& negativeZ);
void clear();
virtual bool load(std::string filename, bool flipImage = true, bool RGB2RGBA = true);
bool save(std::string filename, bool flipImage = true);
inline operator unsigned char*()
{
assert(m_valid);
assert(!m_images.empty());
return m_images[0];
}
inline unsigned int get_width()
{
assert(m_valid);
assert(!m_images.empty());
return m_images[0].get_width();
}
inline unsigned int get_height()
{
assert(m_valid);
assert(!m_images.empty());
return m_images[0].get_height();
}
inline unsigned int get_depth()
{
assert(m_valid);
assert(!m_images.empty());
return m_images[0].get_depth();
}
inline unsigned int get_size()
{
assert(m_valid);
assert(!m_images.empty());
return m_images[0].get_size();
}
inline unsigned int get_num_mipmaps()
{
assert(m_valid);
assert(!m_images.empty());
return m_images[0].get_num_mipmaps();
}
inline const CSurface& get_mipmap(unsigned int index) const
{
assert(m_valid);
assert(!m_images.empty());
if(index < m_images[0].get_num_mipmaps())
return m_images[0].get_mipmap(index);
else
return m_images[0];
}
inline const CTexture& get_cubemap_face(unsigned int face) const
{
assert(m_valid);
assert(!m_images.empty());
assert(m_images.size() == 6);
assert(m_type == TextureCubemap);
assert(face < 6);
return m_images[face];
}
inline unsigned int get_components() { return m_components; }
inline unsigned int get_format() { return m_format; }
inline unsigned int get_internal_format() { return m_internal_format; }
inline TextureType get_type() { return m_type; }
inline bool is_compressed()
{
if((m_format == COMPRESSED_RGBA_S3TC_DXT1_EXT) || (m_format == COMPRESSED_RGBA_S3TC_DXT3_EXT)
|| (m_format == COMPRESSED_RGBA_S3TC_DXT5_EXT))
return true;
else
return false;
}
inline bool is_cubemap() { return (m_type == TextureCubemap); }
inline bool is_volume() { return (m_type == Texture3D); }
inline bool is_valid() { return m_valid; }
inline bool is_dword_aligned()
{
assert(m_valid);
int dwordLineSize = get_dword_aligned_linesize(get_width(), m_components * 8);
int curLineSize = get_width() * m_components;
return (dwordLineSize == curLineSize);
}
protected:
unsigned int clamp_size(unsigned int size);
unsigned int size_dxtc(unsigned int width, unsigned int height);
unsigned int size_rgb(unsigned int width, unsigned int height);
inline void swap_endian(void* val);
// calculates 4-byte aligned width of image
inline unsigned int get_dword_aligned_linesize(unsigned int width, unsigned int bpp)
{
return ((width * bpp + 31) & -32) >> 3;
}
void flip(CSurface& surface);
void flip_texture(CTexture& texture);
void swap(void* byte1, void* byte2, unsigned int size);
void flip_blocks_dxtc1(DXTColBlock* line, unsigned int numBlocks);
void flip_blocks_dxtc3(DXTColBlock* line, unsigned int numBlocks);
void flip_blocks_dxtc5(DXTColBlock* line, unsigned int numBlocks);
void flip_dxt5_alpha(DXT5AlphaBlock* block);
void write_texture(const CTexture& texture, FILE* fp);
unsigned int m_format, m_internal_format;
unsigned int m_components;
TextureType m_type;
bool m_valid;
std::deque<CTexture> m_images;
};
} // namespace nv_dds
#endif

View file

@ -0,0 +1,322 @@
/*
* Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-FileCopyrightText: Copyright (c) 2021 NVIDIA CORPORATION
* SPDX-License-Identifier: Apache-2.0
*/
/** @DOC_START
A mostly self-contained reader and writer for KTX2 files and reader for KTX1
files. Relies on Vulkan (for KTX2), GL (for KTX1), and the
Khronos Data Format.
Sample usage for reading files:
```cpp
KTXImage image;
ErrorWithText maybe_error = image.readFromFile("data/image.ktx2");
if(maybe_error.has_value())
{
// Do something with the error message, maybe_error.value()
}
else
{
// Access subresources using image.subresource(...), and upload them
// to the GPU using your graphics API of choice.
}
```
Define NVP_SUPPORTS_ZSTD, NVP_SUPPORTS_GZLIB, and NVP_SUPPORTS_BASISU to
include the Zstd, Zlib, and Basis Universal headers respectively, and to
enable reading these formats. This will also enable writing Zstd and
Basis Universal-compressed formats.
If you're using this inside the nvpro-samples framework, you can add all
three quickly by adding _add_package_KTX() to your dependencies
in CMakeLists.txt.
-- @DOC_END */
#ifndef __NV_KTX_H__
#define __NV_KTX_H__
#include <array>
#include <iostream>
#include <map>
#include <optional>
#include <string>
#include <vector>
#include <vulkan/vulkan_core.h>
namespace nv_ktx {
// These functions return an empty std::optional if they succeeded, and a
// value with text describing the error if they failed.
using ErrorWithText = std::optional<std::string>;
// KTX files can store key/value pairs, where the key is a UTF-8
// null-terminated string and the value is an arbitrary byte array
// (but often a null-terminated ASCII string).
using KeyValueData = std::map<std::string, std::vector<char>>;
// Apps can define custom functions that return the size in bytes of new
// VkFormats. Functions of this type should take in the width, height, and
// depth of a format in the first 3 parameters, the VkFormat in the 4th, and
// return the size in bytes of an image with those dimensions in the last
// parameter. Passing in an image size of (1, 1, 1) should give the size of
// the smallest possible nonzero image. If the format is unknown, it should
// return a string; if it succeeds, it should return {}.
using CustomExportSizeFuncPtr = ErrorWithText (*)(size_t, size_t, size_t, VkFormat, size_t&);
// Configurable settings for reading files. This is a struct so that it can
// be extended in the future.
struct ReadSettings
{
// Whether to read all mips (true), or only the base mip (false).
bool mips = true;
// See docs for CustomExportSizeFuncPtr
CustomExportSizeFuncPtr custom_size_callback = nullptr;
// If true, the reader will validate that the KTX file contains at least 1
// byte per subresource. This will involve seeking to the end of the stream
// to determine the length of the stream or file.
bool validate_input_size = true;
// Limits the maximum uncompressed image size size per mip and
// supercompression global data size in bytes; produces errors for any files
// with a larger size. This allows certain types of issues with
// supercompression to be caught before the rest of the file is loaded. If
// one wants to allow larger images, they should set this to a larger value
// (such as UINT64_MAX).
uint64_t max_resource_size_in_bytes = 1ULL << 30;
// By default, UASTC is transcoded to BC7 instead of ASTC. Setting this to
// true will transcode UASTC to ASTC.
bool device_supports_astc = false;
};
enum class WriteSupercompressionType
{
NONE, // Apply no supercompression, or use the supercompression included with ETC1S.
ZSTD, // ZStandard
};
enum class EncodeRGBA8ToFormat
{
NO, // Don't encode the data to a Basis Universal format.
// For the following modes, the image format must be VK_FORMAT_B8G8R8A8_SRGB
// or VK_FORMAT_B8G8R8A8_UNORM. Basis Universal will then be called to encode
// the data and write the KTX2 file.
UASTC, // Highest-quality format; RGBA data, usually decodes to ASTC or BC7.
ETC1S_RGBA, // RGBA data; usually decodes to BC7 (8bpp).
ETC1S_RGB // RGB channels only; usually decodes to BC7 (8bpp).
};
enum class UASTCEncodingQuality
{
FASTEST = 0,
FASTER = 1,
DEFAULT = 2,
SLOWER = 3,
VERYSLOW = 4
};
// Configurable settings for writing files. This is a struct so that it can
// be extended in the future.
struct WriteSettings
{
// Type of supercompression to apply if any
WriteSupercompressionType supercompression = WriteSupercompressionType::NONE;
// Supercompression quality level for Zstandard, which is supported by all
// formats other than ETC1s. This ranges from ZSTD_minCLevel() to
// ZSTD_maxCLevel().
// Higher levels are slower.
int supercompression_level = 0;
// See docs for CustomExportSizeFuncPtr
CustomExportSizeFuncPtr custom_size_callback = nullptr;
// Whether to encode the data to a Basis format. If not NO, the image format
// must be VK_FORMAT_B8G8R8A8_SRGB or VK_FORMAT_B8G8R8A8_UNORM.
EncodeRGBA8ToFormat encode_rgba8_to_format = EncodeRGBA8ToFormat::NO;
// Applies when encoding RGBA8 to UASTC. Corresponds to cPackUASTCLevel in Basis.
UASTCEncodingQuality uastc_encoding_quality = UASTCEncodingQuality::DEFAULT;
// Applies when encoding RGBA8 to ETC1S. Ranges from 0 to BASISU_MAX_COMPRESSION_LEVEL.
// Higher levels are slower.
int etc1s_encoding_level = 3;
// Lambda for UASTC Rate-Distortion Optimization, from 0 to 50. Higher numbers
// compress more at lower quality.
float rdo_lambda = 10.0f;
// Enables Rate-Distortion Optimization for ETC1S.
bool rdo_etc1s = true;
};
// An enum for each of the possible elements in a ktxSwizzle value.
enum class KTX_SWIZZLE
{
ZERO = 0,
ONE,
R,
G,
B,
A
};
// Represents the inflated contents of a KTX or KTX2 file. This includes:
// - the VkFormat of the image data,
// - the formatted (i.e. encoded/compressed) image data for
// each element, mip level, and face,
// - and the table of key/value pairs.
// The stored data is not supercompressed, as we supercompress and inflate when
// writing and reading to and from KTX files.
struct KTXImage
{
public:
// Clears, then sets up storage for an image with the given dimensions. These
// can be set to 0 instead of 1 along each dimension to indicate different
// texture types, such as 1D or 2D. See table 4.1 in the KTX 2.0
// specification, or the comments on these variables below.
//
// Width, height, depth, and VkFormat should be set manually using the
// member variables. This does not allocate the encoded subresources.
// This can fail e.g. if the parameters are so large that the app runs out of
// memory when allocating space.
ErrorWithText allocate(
// The number of mips (levels) in the image, including the base mip.
uint32_t _num_mips = 1,
// The number of array elements (layers) in the image. 0 for a non-array
// texture (this has meaning in OpenGL, but not in Vulkan).
// If representing an incomplete cube map (i.e. a cube map where not all
// faces are stored), this is
// (faces per cube map) * (number of cube maps)
// and _num_faces is 1.
uint32_t _num_layers = 0,
// The number of faces in the image (1 for a 2D texture, 6 for a cube map)
uint32_t _num_faces = 1);
// Clears all stored image and table data.
void clear();
// Determines the VkImageType corresponding to this KTXImage based on the
// dimensions, according to Table 4.1 of the KTX 2.0 specification.
// In the invalid case where mip_0_width == 0, returns VK_IMAGE_TYPE_1D.
VkImageType getImageType() const;
// Returns whether the loaded file was a KTX1 (1) or KTX2 (2) file.
uint32_t getKTXVersion() const;
// Mutably accesses the subresource at the given mip, layer, and face. If the
// given indices are out of range, throws an std::out_of_range exception.
std::vector<char>& subresource(uint32_t mip = 0, uint32_t layer = 0, uint32_t face = 0);
// Reads this structure from a KTX stream, advancing the stream as well.
// Returns an optional error message if the read failed.
ErrorWithText readFromStream(std::istream& input, // The input stream, at the start of the KTX data
const ReadSettings& readSettings); // Settings for the reader
// Wrapper for readFromStream for a filename.
ErrorWithText readFromFile(const char* filename, // The .ktx or .ktx2 file to read from.
const ReadSettings& readSettings); // Settings for the reader
// Writes this structure in KTX2 format to a stream.
ErrorWithText writeKTX2Stream(std::ostream& output, // The output stream, at the point to start writing
const WriteSettings& writeSettings); // Settings for the writer
// Wrapper for writeKTX2Stream for a filename. Customarily, the filename ends
// in .ktx2.
ErrorWithText writeKTX2File(const char* filename, // The output stream, at the point to start writing
const WriteSettings& writeSettings); // Settings for the writer
public:
// These members can be freely modified.
// The format of the data in this image. When reading a KTX1 file (which
// specifies a GL format), we automatically convert to a VkFormat.
VkFormat format = VK_FORMAT_UNDEFINED;
// The width in pixels of the largest mip. Must be > 0.
uint32_t mip_0_width = 1;
// The height in pixels of the largest mip. 0 for a 1D texture.
uint32_t mip_0_height = 0;
// The depth in pixels of the largest mip. 0 for a 1D or 2D texture.
uint32_t mip_0_depth = 0;
// The number of mips (levels) in the image, including the base mip. Always
// greater than or equal to 1.
uint32_t num_mips = 1;
// The number of array elements (layers) in the image. 0 for a non-array
// texture (this has meaning in OpenGL, but not in Vulkan).
// If representing an incomplete cube map (i.e. a cube map where not all
// faces are stored), this is
// (faces per cube map) * (number of cube maps)
// and _num_faces is 1.
uint32_t num_layers_possibly_0 = 0;
// The number of faces in the image (1 for a 2D texture, 6 for a cube map)
uint32_t num_faces = 0;
// This file's key/value table. Note that for the ktxSwizzle key, one should
// use the swizzle element instead!
KeyValueData key_value_data{};
// KTX files can set the number of mips to 0 to indicate that
// the application should generate a full mip chain.
bool app_should_generate_mips = false;
// Whether this data represents an image with premultiplied alpha
// (generally, storing (r*a, g*a, b*a, a) instead of (r, g, b, a)).
// This is used when writing the Data Format Descriptor in KTX2.
bool is_premultiplied = false;
// Whether the Data Format Descriptor transferFunction for this data is
// KHR_DF_TRANSFER_SRGB. (Otherwise, it is KHR_DF_TRANSFER_LINEAR.)
// More informally, says "when a GPU accesses this texture, should it perform
// sRGB-to-linear conversion". For instance, this is usually true for color
// textures, and false for normal maps and depth maps. Validation requires
// this to match the VkFormat - except in special cases such as Basis UASTC
// and Universal.
bool is_srgb = true;
// Specifies how the red, green, blue, and alpha channels should be sampled
// from the source data. For instance, {R, G, ZERO, ONE} means the red and
// green channels should be sampled from the red and green texture components
// respectively, the blue channel is sampled as 0, and the alpha channel is
// sampled as 1.
// Note that values here should be read in lieu of the key_value_data's
// ktxSwizzle key! This is to make Basis Universal usage easier in the future.
std::array<KTX_SWIZZLE, 4> swizzle = {KTX_SWIZZLE::R, KTX_SWIZZLE::G, KTX_SWIZZLE::B, KTX_SWIZZLE::A};
// The loader will transcode supercompressed files to an appropriate format
// when supercompression libraries are available, so a loaded supercompressed
// file typically looks like a regular BC4, BC7 or ASTC file. One can read
// this field to determine what the original supercompressed format was.
enum class InputSupercompression
{
eNone,
eBasisUASTC,
eBasisETC1S
} input_supercompression = InputSupercompression::eNone;
private:
// Private functions used by readFromStream after it determines whether the
// stream is a KTX1 or KTX2 stream.
ErrorWithText readFromKTX1Stream(std::istream& input, const ReadSettings& readSettings);
ErrorWithText readFromKTX2Stream(std::istream& input, const ReadSettings& readSettings);
// Whether the loaded file was a KTX1 (1) or KTX2 (2) file.
uint32_t read_ktx_version = 1;
private:
// A structure containing all the image's encoded, non-supercompressed
// image data. We store this in a buffer with an entry per subresource, and
// provide accessors to it.
std::vector<std::vector<char>> data;
};
} // namespace nv_ktx
#include "nv_ktx.inl"
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,371 @@
/*
* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-FileCopyrightText: Copyright (c) 2014-2021 NVIDIA CORPORATION
* SPDX-License-Identifier: Apache-2.0
*/
#include "tiny_converter.hpp"
void TinyConverter::convert(tinygltf::Model& gltf, const tinyobj::ObjReader& reader)
{
// Default assets
gltf.asset.copyright = "NVIDIA Corporation";
gltf.asset.generator = "OBJ converter";
gltf.asset.version = "2.0"; // glTF version 2.0
// Adding one buffer
gltf.buffers.emplace_back();
auto& tBuffer = gltf.buffers.back();
// Materials
for(const auto& mat : reader.GetMaterials())
convertMaterial(gltf, mat);
if(gltf.materials.empty())
gltf.materials.emplace_back(); // Default material
// Unordered map of unique Vertex
auto hash = [&](const Vertex& v) { return makeHash(v); };
auto equal = [&](const Vertex& l, const Vertex& r) { return l == r; };
std::unordered_map<Vertex, size_t, decltype(hash), decltype(equal)> vertexToIdx(0, hash, equal);
// Building unique vertices
auto& attrib = reader.GetAttrib();
std::vector<glm::vec3> vertices;
std::vector<glm::vec3> normals;
std::vector<glm::vec2> texcoords;
vertices.reserve((int)(attrib.vertices.size()) / 3);
normals.reserve((int)(attrib.normals.size()) / 3);
texcoords.reserve((int)(attrib.texcoords.size()) / 2);
Bbox bb;
for(const auto& shape : reader.GetShapes())
{
for(const auto& index : shape.mesh.indices)
{
const auto v = getVertex(attrib, index);
if(vertexToIdx.find(v) == vertexToIdx.end())
{
vertexToIdx[v] = vertexToIdx.size();
vertices.push_back(v.pos);
bb.insert(v.pos);
if(!attrib.normals.empty())
normals.push_back(v.nrm);
if(!attrib.texcoords.empty())
texcoords.push_back(v.tex);
}
}
}
vertices.shrink_to_fit();
normals.shrink_to_fit();
texcoords.shrink_to_fit();
// Number of unique vertices
uint32_t nbVertices = (uint32_t)vertexToIdx.size();
// Estimate size of buffer before appending data
uint32_t nbIndices{0};
for(const auto& shape : reader.GetShapes())
nbIndices += (uint32_t)shape.mesh.indices.size();
size_t bufferEstimateSize{0};
bufferEstimateSize += nbVertices * sizeof(glm::vec3);
bufferEstimateSize += normals.empty() ? 0 : nbVertices * sizeof(glm::vec3);
bufferEstimateSize += texcoords.empty() ? 0 : nbVertices * sizeof(glm::vec2);
bufferEstimateSize += nbIndices * sizeof(uint32_t);
tBuffer.data.reserve(bufferEstimateSize); // Reserving to make the allocations faster
// Storing the information in the glTF buffer
{
struct OffsetLen
{
uint32_t offset{0};
uint32_t len{0};
};
// Make buffer of attribs
OffsetLen olIdx, olPos, olNrm, olTex;
auto& tBuffer = gltf.buffers.back();
olPos.offset = static_cast<uint32_t>(tBuffer.data.size());
olPos.len = appendData(tBuffer, vertices);
olNrm.offset = static_cast<uint32_t>(tBuffer.data.size());
olNrm.len = appendData(tBuffer, normals);
olTex.offset = static_cast<uint32_t>(tBuffer.data.size());
olTex.len = appendData(tBuffer, texcoords);
// Same buffer views for all shapes
int posBufferView{-1};
int nrmBufferView{-1};
int texBufferView{-1};
// Buffer View (POSITION)
{
gltf.bufferViews.emplace_back();
auto& tBufferView = gltf.bufferViews.back();
tBufferView.buffer = 0;
tBufferView.byteOffset = olPos.offset;
tBufferView.byteStride = 3 * sizeof(float);
tBufferView.byteLength = nbVertices * tBufferView.byteStride;
// Accessor (POSITION)
gltf.accessors.emplace_back();
auto& tAccessor = gltf.accessors.back();
tAccessor.bufferView = static_cast<int>(gltf.bufferViews.size() - 1);
tAccessor.byteOffset = 0;
tAccessor.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
tAccessor.count = nbVertices;
tAccessor.type = TINYGLTF_TYPE_VEC3;
tAccessor.minValues = {bb.min()[0], bb.min()[1], bb.min()[2]};
tAccessor.maxValues = {bb.max()[0], bb.max()[1], bb.max()[2]};
assert(tAccessor.count > 0);
posBufferView = (int)gltf.accessors.size() - 1;
}
// Buffer View (NORMAL)
if(!attrib.normals.empty())
{
gltf.bufferViews.emplace_back();
auto& tBufferView = gltf.bufferViews.back();
tBufferView.buffer = 0;
tBufferView.byteOffset = olNrm.offset;
tBufferView.byteStride = 3 * sizeof(float);
tBufferView.byteLength = nbVertices * tBufferView.byteStride;
// Accessor (NORMAL)
gltf.accessors.emplace_back();
auto& tAccessor = gltf.accessors.back();
tAccessor.bufferView = static_cast<int>(gltf.bufferViews.size() - 1);
tAccessor.byteOffset = 0;
tAccessor.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
tAccessor.count = nbVertices;
tAccessor.type = TINYGLTF_TYPE_VEC3;
nrmBufferView = (int)gltf.accessors.size() - 1;
}
// Buffer View (TEXCOORD_0)
if(!attrib.texcoords.empty())
{
gltf.bufferViews.emplace_back();
auto& tBufferView = gltf.bufferViews.back();
tBufferView.buffer = 0;
tBufferView.byteOffset = olTex.offset;
tBufferView.byteStride = 2 * sizeof(float);
tBufferView.byteLength = nbVertices * tBufferView.byteStride;
// Accessor (TEXCOORD_0)
gltf.accessors.emplace_back();
auto& tAccessor = gltf.accessors.back();
tAccessor.bufferView = static_cast<int>(gltf.bufferViews.size() - 1);
tAccessor.byteOffset = 0;
tAccessor.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
tAccessor.count = nbVertices;
tAccessor.type = TINYGLTF_TYPE_VEC2;
texBufferView = (int)gltf.accessors.size() - 1;
}
// Create one node/mesh/primitive per shape
for(const auto& shape : reader.GetShapes())
{
uint32_t idxBufferView{0};
// Finding the unique vertex index for the shape
std::vector<uint32_t> indices;
indices.reserve(shape.mesh.indices.size());
for(const auto& index : shape.mesh.indices)
{
const auto v = getVertex(attrib, index);
size_t idx = vertexToIdx[v];
indices.push_back((uint32_t)idx);
}
// Appending the index data to the glTF buffer
auto& tBuffer = gltf.buffers.back();
olIdx.offset = static_cast<uint32_t>(tBuffer.data.size());
olIdx.len = appendData(tBuffer, indices);
// Adding a Buffer View (INDICES)
{
gltf.bufferViews.emplace_back();
auto& tBufferView = gltf.bufferViews.back();
tBufferView.buffer = 0;
tBufferView.byteOffset = olIdx.offset;
tBufferView.byteStride = 0; // "bufferView.byteStride must not be defined for indices accessor." ;
tBufferView.byteLength = sizeof(uint32_t) * indices.size();
// Accessor (INDICES)
gltf.accessors.emplace_back();
auto& tAccessor = gltf.accessors.back();
tAccessor.bufferView = static_cast<int>(gltf.bufferViews.size() - 1);
tAccessor.byteOffset = 0;
tAccessor.componentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT;
tAccessor.count = indices.size();
tAccessor.type = TINYGLTF_TYPE_SCALAR;
idxBufferView = static_cast<int>(gltf.accessors.size() - 1);
}
// Adding a glTF mesh
tinygltf::Mesh mesh;
mesh.name = shape.name;
// One primitive under the mesh
mesh.primitives.emplace_back();
auto& tPrim = mesh.primitives.back();
tPrim.mode = TINYGLTF_MODE_TRIANGLES;
// Material reference
// #TODO - We assume all primitives have the same material
tPrim.material = shape.mesh.material_ids.empty() ? 0 : shape.mesh.material_ids[0];
tPrim.material = std::max(0, tPrim.material);
// Setting all buffer views
tPrim.indices = idxBufferView;
tPrim.attributes["POSITION"] = posBufferView;
if(nrmBufferView > 0)
tPrim.attributes["NORMAL"] = nrmBufferView;
if(texBufferView > 0)
tPrim.attributes["TEXCOORD_0"] = texBufferView;
// Adding the mesh
gltf.meshes.emplace_back(mesh);
// Adding the node referencing the mesh we just have created
tinygltf::Node node;
node.name = mesh.name;
node.mesh = static_cast<int>(gltf.meshes.size() - 1);
gltf.nodes.emplace_back(node);
}
}
// Scene
gltf.defaultScene = 0;
tinygltf::Scene scene;
for(int n = 0; n < (int)gltf.nodes.size(); n++)
scene.nodes.push_back(n);
gltf.scenes.emplace_back(scene);
// Shrink back
tBuffer.data.shrink_to_fit();
}
TinyConverter::Vertex TinyConverter::getVertex(const tinyobj::attrib_t& attrib, const tinyobj::index_t& index)
{
Vertex v;
const float* vp = &attrib.vertices[3ULL * index.vertex_index];
v.pos = {*(vp + 0), *(vp + 1), *(vp + 2)};
if(!attrib.normals.empty() && index.normal_index >= 0)
{
const float* np = &attrib.normals[3ULL * index.normal_index];
v.nrm = {*(np + 0), *(np + 1), *(np + 2)};
}
if(!attrib.texcoords.empty() && index.texcoord_index >= 0)
{
const float* tp = &attrib.texcoords[2ULL * index.texcoord_index + 0];
v.tex = {*tp, 1.0f - *(tp + 1)};
}
return v;
}
void TinyConverter::convertMaterial(tinygltf::Model& gltf, const tinyobj::material_t& mat)
{
tinygltf::TextureInfo baseColorTexture;
tinygltf::TextureInfo emissiveTexture;
tinygltf::NormalTextureInfo normalTexture;
tinygltf::OcclusionTextureInfo occlusionTexture;
tinygltf::TextureInfo metallicRoughnessTexture = createMetallicRoughnessTexture(mat.metallic_texname, mat.roughness_texname);
baseColorTexture.index = convertTexture(gltf, mat.diffuse_texname);
emissiveTexture.index = convertTexture(gltf, mat.emissive_texname);
normalTexture.index = convertTexture(gltf, mat.normal_texname);
occlusionTexture.index = convertTexture(gltf, mat.ambient_texname);
tinygltf::Material gMat;
gMat.name = mat.name;
gMat.emissiveFactor = {mat.emission[0], mat.emission[1], mat.emission[2]};
gMat.pbrMetallicRoughness.baseColorFactor = {mat.diffuse[0], mat.diffuse[1], mat.diffuse[2], 1};
gMat.pbrMetallicRoughness.metallicFactor = (mat.specular[0] + mat.specular[1] + mat.specular[2]) / 3.0f;
gMat.pbrMetallicRoughness.roughnessFactor = mat.shininess;
gMat.doubleSided = false;
gMat.normalTexture = normalTexture;
gMat.occlusionTexture = occlusionTexture;
gMat.emissiveTexture = emissiveTexture;
gMat.pbrMetallicRoughness.baseColorTexture = baseColorTexture;
gMat.pbrMetallicRoughness.metallicRoughnessTexture = metallicRoughnessTexture;
gltf.materials.emplace_back(gMat);
}
int TinyConverter::convertTexture(tinygltf::Model& gltf, const std::string& diffuse_texname)
{
if(diffuse_texname.empty())
return -1;
int sourceImg = findImage(gltf, diffuse_texname);
if(sourceImg < 0)
{
tinygltf::Image img;
img.uri = diffuse_texname;
gltf.images.emplace_back(img);
sourceImg = (int)gltf.images.size() - 1;
}
int sourceTex = findTexture(gltf, sourceImg);
if(sourceTex < 0)
{
tinygltf::Texture tex;
tex.source = sourceImg;
gltf.textures.emplace_back(tex);
sourceTex = (int)gltf.textures.size() - 1;
}
return sourceTex;
}
int TinyConverter::findImage(tinygltf::Model& gltf, const std::string& texname)
{
int idx{-1};
for(const auto& i : gltf.images)
{
++idx;
if(i.uri == texname)
return idx;
}
return -1;
}
int TinyConverter::findTexture(tinygltf::Model& gltf, int source)
{
int idx{-1};
for(const auto& t : gltf.textures)
{
++idx;
if(t.source == source)
return idx;
}
return -1;
}
tinygltf::TextureInfo TinyConverter::createMetallicRoughnessTexture(std::string metallic_texname, std::string roughness_texname)
{
tinygltf::TextureInfo tex;
return tex;
// #TODO Mix metallic and roughness in one channel and add inline image or save to disk?
}

View file

@ -0,0 +1,122 @@
/*
* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-FileCopyrightText: Copyright (c) 2014-2021 NVIDIA CORPORATION
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <functional>
#include <glm/glm.hpp>
#include "tiny_gltf.h"
#include "tiny_obj_loader.h"
/** @DOC_START
Class TinyConverter
> This class is used to convert a tinyobj::ObjReader to a tinygltf::Model.
@DOC_END */
class TinyConverter
{
public:
void convert(tinygltf::Model& gltf, const tinyobj::ObjReader& reader);
private:
//---- Hash Combination ----
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3876.pdf
template <typename T>
void hashCombine(std::size_t& seed, const T& val)
{
seed ^= std::hash<T>()(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
// Auxiliary generic functions to create a hash value using a seed
template <typename T, typename... Types>
void hashCombine(std::size_t& seed, const T& val, const Types&... args)
{
hashCombine(seed, val);
hashCombine(seed, args...);
}
// Optional auxiliary generic functions to support hash_val() without arguments
void hashCombine(std::size_t& seed) {}
// Generic function to create a hash value out of a heterogeneous list of arguments
template <typename... Types>
std::size_t hashVal(const Types&... args)
{
std::size_t seed = 0;
hashCombine(seed, args...);
return seed;
}
//--------------
struct Vertex
{
glm::vec3 pos;
glm::vec3 nrm;
glm::vec2 tex;
bool operator==(const Vertex& l) const { return this->pos == l.pos && this->nrm == l.nrm && this->tex == l.tex; }
};
Vertex getVertex(const tinyobj::attrib_t& attrib, const tinyobj::index_t& index);
void convertMaterial(tinygltf::Model& gltf, const tinyobj::material_t& mat);
int convertTexture(tinygltf::Model& gltf, const std::string& diffuse_texname);
int findImage(tinygltf::Model& gltf, const std::string& texname);
int findTexture(tinygltf::Model& gltf, int source);
tinygltf::TextureInfo createMetallicRoughnessTexture(std::string metallic_texname, std::string roughness_texname);
// This is appending the incoming data to the binary buffer and return the amount in byte of data that was added.
template <class T>
uint32_t appendData(tinygltf::Buffer& buffer, const T& inData)
{
auto* pData = reinterpret_cast<const char*>(inData.data());
uint32_t len = static_cast<uint32_t>(sizeof(inData[0]) * inData.size());
buffer.data.insert(buffer.data.end(), pData, pData + len);
return len;
}
struct Bbox
{
Bbox() = default;
void insert(const glm::vec3& v)
{
m_min = {std::min(m_min[0], v[0]), std::min(m_min[1], v[1]), std::min(m_min[2], v[2])};
m_max = {std::max(m_max[0], v[0]), std::max(m_max[1], v[1]), std::max(m_max[2], v[2])};
}
inline glm::vec3 min() { return m_min; }
inline glm::vec3 max() { return m_max; }
private:
glm::vec3 m_min{std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max()};
glm::vec3 m_max{-std::numeric_limits<float>::max(), -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max()};
};
std::size_t makeHash(const Vertex& v)
{
return hashVal(v.pos.x, v.pos.y, v.pos.z, v.nrm.x, v.nrm.y, v.nrm.z, v.tex.x, v.tex.y);
}
};