8#include <tinystl/allocator.h>
9#include <tinystl/string.h>
10#include <tinystl/vector.h>
11namespace stl = tinystl;
15#include <bx/commandline.h>
18#include <bx/readerwriter.h>
23#include <bimg/decode.h>
36bx::AllocatorI* getDefaultAllocator()
38 static bx::DefaultAllocator allocator;
42static bx::AllocatorI* g_allocator = getDefaultAllocator();
43typedef bx::StringT<&g_allocator> String;
45class FileReader :
public bx::FileReader
47 typedef bx::FileReader super;
50 virtual bool open(
const bx::FilePath& _filePath, bx::Error* _err)
override
52 return super::open(_filePath, _err);
56class FileWriter :
public bx::FileWriter
58 typedef bx::FileWriter super;
61 virtual bool open(
const bx::FilePath& _filePath,
bool _append, bx::Error* _err)
override
63 return super::open(_filePath, _append, _err);
67bx::AllocatorI* getAllocator()
75void*
load(bx::FileReaderI* _reader, bx::AllocatorI* _allocator,
const char* _filePath, uint32_t* _size)
77 if(bx::open(_reader, _filePath))
79 uint32_t
size = (uint32_t)bx::getSize(_reader);
80 void* data = bx::alloc(_allocator,
size);
81 bx::read(_reader, data,
size, bx::ErrorAssert{});
91 DBG(
"Failed to open: %s.", _filePath);
102void*
load(
const char* _filePath, uint32_t* _size)
104 entry::FileReader reader;
105 return load(&reader, entry::getAllocator(), _filePath, _size);
110 bx::free(entry::getAllocator(), _ptr);
113static const bgfx::Memory* loadMem(bx::FileReaderI* _reader,
const char* _filePath)
115 if(bx::open(_reader, _filePath))
117 uint32_t
size = (uint32_t)bx::getSize(_reader);
118 const bgfx::Memory* mem = bgfx::alloc(
size + 1);
119 bx::read(_reader, mem->data,
size, bx::ErrorAssert{});
121 mem->data[mem->size - 1] =
'\0';
125 DBG(
"Failed to load %s.", _filePath);
129static void* loadMem(bx::FileReaderI* _reader, bx::AllocatorI* _allocator,
const char* _filePath, uint32_t* _size)
131 if(bx::open(_reader, _filePath))
133 uint32_t
size = (uint32_t)bx::getSize(_reader);
134 void* data = bx::alloc(_allocator,
size);
135 bx::read(_reader, data,
size, bx::ErrorAssert{});
145 DBG(
"Failed to load %s.", _filePath);
149static bgfx::ShaderHandle loadShader(bx::FileReaderI* _reader,
const char* _name)
153 const char* shaderPath =
"???";
155 switch(bgfx::getRendererType())
157 case bgfx::RendererType::Noop:
158 case bgfx::RendererType::Direct3D11:
159 case bgfx::RendererType::Direct3D12:
160 shaderPath =
"shaders/dx11/";
162 case bgfx::RendererType::Agc:
163 case bgfx::RendererType::Gnm:
164 shaderPath =
"shaders/pssl/";
166 case bgfx::RendererType::Metal:
167 shaderPath =
"shaders/metal/";
169 case bgfx::RendererType::Nvn:
170 shaderPath =
"shaders/nvn/";
172 case bgfx::RendererType::OpenGL:
173 shaderPath =
"shaders/glsl/";
175 case bgfx::RendererType::OpenGLES:
176 shaderPath =
"shaders/essl/";
178 case bgfx::RendererType::Vulkan:
179 shaderPath =
"shaders/spirv/";
182 case bgfx::RendererType::Count:
183 BX_ASSERT(
false,
"You should not be here!");
187 bx::strCopy(filePath, BX_COUNTOF(filePath), shaderPath);
188 bx::strCat(filePath, BX_COUNTOF(filePath), _name);
189 bx::strCat(filePath, BX_COUNTOF(filePath),
".bin");
191 bgfx::ShaderHandle
handle = bgfx::createShader(loadMem(_reader, filePath));
192 bgfx::setName(
handle, _name);
197bgfx::ShaderHandle loadShader(
const char* _name)
199 entry::FileReader reader;
200 return loadShader(&reader, _name);
203bgfx::ProgramHandle
loadProgram(bx::FileReaderI* _reader,
const char* _vsName,
const char* _fsName)
205 bgfx::ShaderHandle vsh = loadShader(_reader, _vsName);
206 bgfx::ShaderHandle fsh = BGFX_INVALID_HANDLE;
209 fsh = loadShader(_reader, _fsName);
212 return bgfx::createProgram(vsh, fsh,
true );
215bgfx::ProgramHandle
loadProgram(
const char* _vsName,
const char* _fsName)
217 entry::FileReader reader;
221static void imageReleaseCb(
void* _ptr,
void* _userData)
224 bimg::ImageContainer* imageContainer = (bimg::ImageContainer*)_userData;
225 bimg::imageFree(imageContainer);
229 const char* _filePath,
232 bgfx::TextureInfo* _info,
233 bimg::Orientation::Enum* _orientation)
236 bgfx::TextureHandle
handle = BGFX_INVALID_HANDLE;
239 void* data =
load(_reader, entry::getAllocator(), _filePath, &
size);
242 bimg::ImageContainer* imageContainer = bimg::imageParse(entry::getAllocator(), data,
size);
244 if (NULL != imageContainer)
246 if (NULL != _orientation)
248 *_orientation = imageContainer->m_orientation;
251 const bgfx::Memory* mem = bgfx::makeRef(
252 imageContainer->m_data
253 , imageContainer->m_size
261 bgfx::calcTextureSize(
263 , uint16_t(imageContainer->m_width)
264 , uint16_t(imageContainer->m_height)
265 , uint16_t(imageContainer->m_depth)
266 , imageContainer->m_cubeMap
267 , 1 < imageContainer->m_numMips
268 , imageContainer->m_numLayers
269 , bgfx::TextureFormat::Enum(imageContainer->m_format)
273 if (imageContainer->m_cubeMap)
275 handle = bgfx::createTextureCube(
276 uint16_t(imageContainer->m_width)
277 , 1 < imageContainer->m_numMips
278 , imageContainer->m_numLayers
279 , bgfx::TextureFormat::Enum(imageContainer->m_format)
284 else if (1 < imageContainer->m_depth)
286 handle = bgfx::createTexture3D(
287 uint16_t(imageContainer->m_width)
288 , uint16_t(imageContainer->m_height)
289 , uint16_t(imageContainer->m_depth)
290 , 1 < imageContainer->m_numMips
291 , bgfx::TextureFormat::Enum(imageContainer->m_format)
296 else if (bgfx::isTextureValid(0,
false, imageContainer->m_numLayers, bgfx::TextureFormat::Enum(imageContainer->m_format), _flags) )
298 handle = bgfx::createTexture2D(
299 uint16_t(imageContainer->m_width)
300 , uint16_t(imageContainer->m_height)
301 , 1 < imageContainer->m_numMips
302 , imageContainer->m_numLayers
303 , bgfx::TextureFormat::Enum(imageContainer->m_format)
309 if (bgfx::isValid(
handle) )
311 const bx::StringView
name(_filePath);
323 bgfx::TextureInfo* _info,
324 bimg::Orientation::Enum* _orientation)
326 entry::FileReader reader;
327 return loadTexture(&reader, _name, _flags, _skip, _info, _orientation);
330bimg::ImageContainer*
imageLoad(
const void* data, uint32_t
size, bgfx::TextureFormat::Enum _dstFormat)
332 return bimg::imageParse(entry::getAllocator(), data,
size, bimg::TextureFormat::Enum(_dstFormat));
335bimg::ImageContainer*
imageLoad(
const char* _filePath, bgfx::TextureFormat::Enum _dstFormat)
337 entry::FileReader reader;
340 void* data = loadMem(&reader, entry::getAllocator(), _filePath, &
size);
342 return bimg::imageParse(entry::getAllocator(), data,
size, bimg::TextureFormat::Enum(_dstFormat));
346 uint16_t _numVertices,
347 bgfx::VertexLayout _layout,
348 const uint16_t* _indices,
349 uint32_t _numIndices)
363 float* tangents =
new float[6 * _numVertices];
364 bx::memSet(tangents, 0, 6 * _numVertices *
sizeof(
float));
370 for(uint32_t ii = 0, num = _numIndices / 3; ii < num; ++ii)
372 const uint16_t* indices = &_indices[ii * 3];
373 uint32_t i0 = indices[0];
374 uint32_t i1 = indices[1];
375 uint32_t i2 = indices[2];
377 bgfx::vertexUnpack(&v0.m_x, bgfx::Attrib::Position, _layout, _vertices, i0);
378 bgfx::vertexUnpack(&v0.m_u, bgfx::Attrib::TexCoord0, _layout, _vertices, i0);
380 bgfx::vertexUnpack(&v1.m_x, bgfx::Attrib::Position, _layout, _vertices, i1);
381 bgfx::vertexUnpack(&v1.m_u, bgfx::Attrib::TexCoord0, _layout, _vertices, i1);
383 bgfx::vertexUnpack(&v2.m_x, bgfx::Attrib::Position, _layout, _vertices, i2);
384 bgfx::vertexUnpack(&v2.m_u, bgfx::Attrib::TexCoord0, _layout, _vertices, i2);
386 const float bax = v1.m_x - v0.m_x;
387 const float bay = v1.m_y - v0.m_y;
388 const float baz = v1.m_z - v0.m_z;
389 const float bau = v1.m_u - v0.m_u;
390 const float bav = v1.m_v - v0.m_v;
392 const float cax = v2.m_x - v0.m_x;
393 const float cay = v2.m_y - v0.m_y;
394 const float caz = v2.m_z - v0.m_z;
395 const float cau = v2.m_u - v0.m_u;
396 const float cav = v2.m_v - v0.m_v;
398 const float det = (bau * cav - bav * cau);
399 const float invDet = 1.0f / det;
401 const float tx = (bax * cav - cax * bav) * invDet;
402 const float ty = (bay * cav - cay * bav) * invDet;
403 const float tz = (baz * cav - caz * bav) * invDet;
405 const float bx = (cax * bau - bax * cau) * invDet;
406 const float by = (cay * bau - bay * cau) * invDet;
407 const float bz = (caz * bau - baz * cau) * invDet;
409 for(uint32_t jj = 0; jj < 3; ++jj)
411 float* tanu = &tangents[indices[jj] * 6];
412 float* tanv = &tanu[3];
423 for(uint32_t ii = 0; ii < _numVertices; ++ii)
425 const bx::Vec3 tanu = bx::load<bx::Vec3>(&tangents[ii * 6]);
426 const bx::Vec3 tanv = bx::load<bx::Vec3>(&tangents[ii * 6 + 3]);
429 bgfx::vertexUnpack(nxyzw, bgfx::Attrib::Normal, _layout, _vertices, ii);
431 const bx::Vec3
normal = bx::load<bx::Vec3>(nxyzw);
432 const float ndt = bx::dot(
normal, tanu);
433 const bx::Vec3 nxt = bx::cross(
normal, tanu);
434 const bx::Vec3 tmp = bx::sub(tanu, bx::mul(
normal, ndt));
437 bx::store(tangent, bx::normalize(tmp));
438 tangent[3] = bx::dot(nxt, tanv) < 0.0f ? -1.0f : 1.0f;
440 bgfx::vertexPack(tangent,
true, bgfx::Attrib::Tangent, _layout, _vertices, ii);
446bool saveToFile(bgfx::ViewId viewId,
const char* _filePath, bgfx::FrameBufferHandle fbo, uint32_t width, uint32_t height)
449 auto input_tex = bgfx::getTexture(fbo);
451 auto format = bgfx::TextureFormat::RGBA8;
452 auto bimg_format =
static_cast<bimg::TextureFormat::Enum
>(format);
456 uint64_t flags = 0 | BGFX_TEXTURE_BLIT_DST | BGFX_TEXTURE_READ_BACK | BGFX_SAMPLER_U_CLAMP |
457 BGFX_SAMPLER_V_CLAMP;
458 auto blit_tex = bgfx::createTexture2D(width, height,
false, 1, format, flags,
nullptr);
460 bgfx::TextureInfo info;
461 bgfx::calcTextureSize(info, width, height, 1,
false,
false, 1, format);
465 bgfx::blit(viewId, blit_tex, 0, 0, input_tex);
469 tinystl::vector<uint8_t>
input(info.storageSize);
472 uint32_t frameNumber = bgfx::readTexture(blit_tex,
input.data());
476 while(bgfx::frame() != frameNumber)
482 bx::FilePath filePath(_filePath);
484 if(bx::makeAll(filePath.getPath()))
486 bx::FileWriter writer;
487 if(bx::open(&writer, filePath))
490 bimg::imageWritePng(&writer,
493 info.width * (info.bitsPerPixel / 8),
506bool imageSave(
const char* saveAs, bimg::ImageContainer* image)
513 bx::FileWriter writer;
516 if (bx::open(&writer, saveAs,
false, &err))
518 if (!bx::strFindI(saveAs,
"tga").isEmpty())
520 bimg::imageWriteTga(&writer, image->m_width, image->m_height, image->m_width * 4, image->m_data,
false,
false, &err);
522 else if (!bx::strFindI(saveAs,
"ktx").isEmpty())
524 bimg::imageWriteKtx(&writer, *image, image->m_data, image->m_size, &err);
527 else if (!bx::strFindI(saveAs,
"dds").isEmpty())
529 bimg::imageWriteDds(&writer, *image, image->m_data, image->m_size, &err);
532 else if (!bx::strFindI(saveAs,
"png").isEmpty())
534 if (image->m_format != bimg::TextureFormat::RGBA8)
537 auto converted = bimg::imageConvert(entry::getAllocator(), bimg::TextureFormat::RGBA8, *image);
541 bimg::imageGetRawData(*converted, 0, 0, converted->m_data, converted->m_size, mip);
542 bimg::imageWritePng(&writer
547 , converted->m_format
551 bimg::imageFree(converted);
562 bimg::imageGetRawData(*image, 0, 0, image->m_data, image->m_size, mip);
563 bimg::imageWritePng(&writer
575 else if (!bx::strFindI(saveAs,
"exr").isEmpty())
578 bimg::imageGetRawData(*image, 0, 0, image->m_data, image->m_size, mip);
579 bimg::imageWriteExr(&writer
589 else if (!bx::strFindI(saveAs,
"hdr").isEmpty())
592 bimg::imageGetRawData(*image, 0, 0, image->m_data, image->m_size, mip);
593 bimg::imageWriteHdr(&writer
596 , mip.m_width*getBitsPerPixel(mip.m_format)/8
void calcTangents(void *_vertices, uint16_t _numVertices, bgfx::VertexLayout _layout, const uint16_t *_indices, uint32_t _numIndices)
bgfx::ProgramHandle loadProgram(bx::FileReaderI *_reader, const char *_vsName, const char *_fsName)
bimg::ImageContainer * imageLoad(const void *data, uint32_t size, bgfx::TextureFormat::Enum _dstFormat)
bool imageSave(const char *saveAs, bimg::ImageContainer *image)
bgfx::TextureHandle loadTexture(bx::FileReaderI *_reader, const char *_filePath, uint64_t _flags, uint8_t _skip, bgfx::TextureInfo *_info, bimg::Orientation::Enum *_orientation)
bool saveToFile(bgfx::ViewId viewId, const char *_filePath, bgfx::FrameBufferHandle fbo, uint32_t width, uint32_t height)
void * load(bx::FileReaderI *_reader, bx::AllocatorI *_allocator, const char *_filePath, uint32_t *_size)