WIP
This commit is contained in:
+1
-1
Submodule assets updated: 10a611659d...e8d98c2dae
@@ -19,6 +19,7 @@ class Resource
|
||||
|
||||
protected:
|
||||
Resource() { }
|
||||
virtual ~Resource() { }
|
||||
|
||||
public:
|
||||
//Should be thrown in a Resource's constructor if it cannot complete because another resource is still loading.
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
#ifndef DDS_h__
|
||||
#define DDS_h__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "../Common.h"
|
||||
#include "../Core/ResourceManager.h"
|
||||
#include "Image.h"
|
||||
|
||||
// DXT5
|
||||
class DDS : public Image, public Resource
|
||||
{
|
||||
public:
|
||||
DDS(std::string path);
|
||||
~DDS();
|
||||
|
||||
void FlipY(unsigned char* data, std::size_t rowBytes, std::size_t totalSize, std::size_t numBlocksWide);
|
||||
|
||||
private:
|
||||
static const uint32_t MagicNumber = 0x20534444; // "DDS "
|
||||
|
||||
struct Header_t
|
||||
{
|
||||
uint32_t Size;
|
||||
uint32_t Flags;
|
||||
uint32_t Height;
|
||||
uint32_t Width;
|
||||
uint32_t PitchOrLinearSize;
|
||||
uint32_t Depth;
|
||||
uint32_t MipMapCount;
|
||||
uint32_t RESERVED1[11];
|
||||
struct PixelFormat_t
|
||||
{
|
||||
uint32_t Size;
|
||||
uint32_t Flags;
|
||||
uint32_t FourCC;
|
||||
uint32_t RGBBitCount;
|
||||
uint32_t RBitMask;
|
||||
uint32_t GBitMask;
|
||||
uint32_t BBitMask;
|
||||
uint32_t ABitMask;
|
||||
} PixelFormat;
|
||||
uint32_t Caps;
|
||||
uint32_t Caps2;
|
||||
uint32_t Caps3;
|
||||
uint32_t Caps4;
|
||||
uint32_t RESERVED2;
|
||||
} m_Header;
|
||||
|
||||
struct Block_t
|
||||
{
|
||||
struct Alpha_t
|
||||
{
|
||||
uint8_t Colors[2];
|
||||
uint8_t Data[6];
|
||||
} Alpha;
|
||||
struct Data_t
|
||||
{
|
||||
uint16_t Colors[2];
|
||||
uint8_t Data[4];
|
||||
} Data;
|
||||
};
|
||||
|
||||
std::size_t m_NumBlocksWide;
|
||||
std::size_t m_NumBlocksHigh;
|
||||
std::size_t m_RowBytes;
|
||||
|
||||
void flipBlock(Block_t* block);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
struct Image
|
||||
{
|
||||
virtual ~Image() { }
|
||||
|
||||
enum class ImageFormat
|
||||
{
|
||||
Unknown,
|
||||
@@ -13,7 +15,10 @@ struct Image
|
||||
unsigned int Width = 0;
|
||||
unsigned int Height = 0;
|
||||
ImageFormat Format = ImageFormat::Unknown;
|
||||
unsigned int MipMapLevels = 0;
|
||||
bool Compressed = false;
|
||||
unsigned char* Data = nullptr;
|
||||
std::size_t ByteSize = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#ifndef Texture_h__
|
||||
#define Texture_h__
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include "../OpenGL.h"
|
||||
#include "BaseTexture.h"
|
||||
#include "PNG.h"
|
||||
#include "DDS.h"
|
||||
|
||||
class Texture : public BaseTexture
|
||||
{
|
||||
@@ -18,7 +20,6 @@ public:
|
||||
void Bind(GLenum textureUnit = GL_TEXTURE0);
|
||||
|
||||
GLuint m_Texture = 0;
|
||||
unsigned char* Data = nullptr;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||
<Entity xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
|
||||
|
||||
<Components>
|
||||
<c:SceneLight>
|
||||
<AmbientColor A="1" B="1" G="1" R="1"/>
|
||||
</c:SceneLight>
|
||||
<c:Sprite>
|
||||
<DiffuseTexture>Textures/Core/UnitRaptor.png</DiffuseTexture>
|
||||
<GlowMap></GlowMap>
|
||||
</c:Sprite>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="0" Z="-1.60000002"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
|
||||
<Children/>
|
||||
|
||||
</Entity>
|
||||
@@ -118,6 +118,29 @@
|
||||
</Entity>
|
||||
</Children>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>Models/Weapons/Blue/AssaultWeaponBlue.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="0.224672914" Z="0.838116169"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Sprite>
|
||||
<DiffuseTexture>Textures/Test/DXT5_noMipmaps.dds</DiffuseTexture>
|
||||
<GlowMap></GlowMap>
|
||||
</c:Sprite>
|
||||
<c:Transform>
|
||||
<Position X="-1.11805892" Y="0.598229825" Z="0.345348239"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
</Children>
|
||||
|
||||
</Entity>
|
||||
|
||||
@@ -33,8 +33,8 @@ void _LOG(_LOG_LEVEL logLevel, const char* file, const char* func, unsigned int
|
||||
va_end(args);
|
||||
|
||||
if (logLevel == LOG_LEVEL_ERROR) {
|
||||
//std::cerr << file << ":" << line << " " << func << std::endl;
|
||||
//std::cerr << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl;
|
||||
std::cerr << file << ":" << line << " " << func << std::endl;
|
||||
std::cerr << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl;
|
||||
} else {
|
||||
std::cout << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl;
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ void CubeMapPass::LoadTextures(std::string input)
|
||||
for (int i = 0; i < 6; i++) {
|
||||
std::string str;
|
||||
str = "Textures/Test/CubeMap/" + input + "/CubeMapTest0" + std::to_string(i) + ".png";
|
||||
Texture* img = ResourceManager::Load<Texture>(str);
|
||||
m_CubeMapTextures.push_back(img);
|
||||
//Texture* img = ResourceManager::Load<Texture>(str);
|
||||
//m_CubeMapTextures.push_back(img);
|
||||
}
|
||||
GenerateCubeMapTexture();
|
||||
m_PreviusCubeMapTexture = input;
|
||||
@@ -29,7 +29,7 @@ void CubeMapPass::GenerateCubeMapTexture()
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapTexture);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA32F, m_CubeMapTextures[0]->Width, m_CubeMapTextures[0]->Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_CubeMapTextures[i]->Data);
|
||||
//glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA32F, m_CubeMapTextures[0]->Width, m_CubeMapTextures[0]->Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_CubeMapTextures[i]->Data);
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
#include "Rendering/DDS.h"
|
||||
|
||||
DDS::DDS(std::string path)
|
||||
{
|
||||
std::ifstream in(path.c_str(), std::ios_base::binary | std::ios_base::ate);
|
||||
if (!in.is_open()) {
|
||||
throw Resource::FailedLoadingException("Failed to open file.");
|
||||
}
|
||||
unsigned int fileSize = static_cast<unsigned int>(in.tellg());
|
||||
in.seekg(0, std::ios_base::beg);
|
||||
|
||||
if (fileSize < sizeof(MagicNumber) + sizeof(DDS::Header_t)) {
|
||||
throw Resource::FailedLoadingException("Invalid DDS file; not even big enough to contain the DDS header!");
|
||||
}
|
||||
|
||||
// Read magic number
|
||||
uint32_t magicNumber;
|
||||
in.read(reinterpret_cast<char*>(&magicNumber), sizeof(MagicNumber));
|
||||
if (magicNumber != DDS::MagicNumber) {
|
||||
throw Resource::FailedLoadingException("Invalid DDS file; magic number doesn't match.");
|
||||
}
|
||||
|
||||
// Read header
|
||||
in.read(reinterpret_cast<char*>(&m_Header), sizeof(DDS::Header_t));
|
||||
|
||||
// Validate header
|
||||
if (m_Header.Size != sizeof(DDS::Header_t) || m_Header.PixelFormat.Size != sizeof(DDS::Header_t::PixelFormat_t)) {
|
||||
throw Resource::FailedLoadingException("Corrupt DDS file; header size doesn't match!");
|
||||
}
|
||||
|
||||
// Make sure it's DC3 (DXT5)
|
||||
char format[5];
|
||||
memcpy(&format, &m_Header.PixelFormat.FourCC, 4);
|
||||
format[4] = '\0';
|
||||
if (strcmp(format, "DXT5")) {
|
||||
std::stringstream ss;
|
||||
ss << "Invalid DDS file; Unsupported compression format \"" << format << "\"";
|
||||
throw Resource::FailedLoadingException(ss.str().c_str());
|
||||
}
|
||||
|
||||
this->Width = m_Header.Width;
|
||||
this->Height = m_Header.Height;
|
||||
this->Format = Image::ImageFormat::RGBA;
|
||||
this->Compressed = true;
|
||||
if (m_Header.MipMapCount != 0) {
|
||||
this->MipMapLevels = m_Header.MipMapCount - 1;
|
||||
}
|
||||
|
||||
// Read data
|
||||
std::size_t dataSize = fileSize - sizeof(MagicNumber) - sizeof(DDS::Header_t);
|
||||
this->Data = new unsigned char[dataSize];
|
||||
this->ByteSize = dataSize;
|
||||
in.read(reinterpret_cast<char*>(this->Data), dataSize);
|
||||
|
||||
// Flip!
|
||||
unsigned int w = this->Width;
|
||||
unsigned int h = this->Height;
|
||||
unsigned char* mipMapData = this->Data;
|
||||
for (unsigned int i = 0; i < this->MipMapLevels; ++i) {
|
||||
std::size_t bpe = 16;
|
||||
std::size_t numBlocksWide = std::max<std::size_t>(1, (w + 3) / 4);
|
||||
std::size_t numBlocksHigh = std::max<std::size_t>(1, (h + 3) / 4);
|
||||
std::size_t rowBytes = numBlocksWide * bpe;
|
||||
std::size_t numRows = numBlocksHigh;
|
||||
std::size_t numBytes = rowBytes * numBlocksHigh;
|
||||
FlipY(mipMapData, rowBytes, numBytes, numBlocksWide);
|
||||
w = w >> 1;
|
||||
h = h >> 1;
|
||||
mipMapData += numBytes;
|
||||
}
|
||||
}
|
||||
|
||||
DDS::~DDS()
|
||||
{
|
||||
if (this->Data != nullptr) {
|
||||
delete[] this->Data;
|
||||
this->Data = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void DDS::FlipY(unsigned char* data, std::size_t rowBytes, std::size_t totalSize, std::size_t numBlocksWide)
|
||||
{
|
||||
std::size_t height = totalSize / rowBytes;
|
||||
unsigned char* topLine = data;
|
||||
unsigned char* bottomLine = data + (height - 1) * rowBytes;
|
||||
for (std::size_t line = 0; line < height / 2; ++line) {
|
||||
Block_t* topBlocks = reinterpret_cast<Block_t*>(topLine);
|
||||
Block_t* bottomBlocks = reinterpret_cast<Block_t*>(bottomLine);
|
||||
for (std::size_t block = 0; block < numBlocksWide; ++block) {
|
||||
flipBlock(&topBlocks[block]);
|
||||
flipBlock(&bottomBlocks[block]);
|
||||
std::swap(topBlocks[block], bottomBlocks[block]);
|
||||
}
|
||||
topLine += rowBytes;
|
||||
bottomLine -= rowBytes;
|
||||
}
|
||||
}
|
||||
|
||||
void DDS::flipBlock(Block_t* block)
|
||||
{
|
||||
// Extract both rows of pixel Data into a 32 bit sized values.
|
||||
uint32_t pixelRow0 = block->Alpha.Data[0] + ((block->Alpha.Data[1] + (block->Alpha.Data[2] << 8)) << 8);
|
||||
uint32_t pixelRow1 = block->Alpha.Data[3] + ((block->Alpha.Data[4] + (block->Alpha.Data[5] << 8)) << 8);
|
||||
|
||||
// Swap the extracted row Data. These values will be read from and shifted into the final block locations.
|
||||
uint32_t pixelRow0Swapped = ((pixelRow0 & 0x000fff) << 12) | ((pixelRow0 & 0xfff000) >> 12);
|
||||
uint32_t pixelRow1Swapped = ((pixelRow1 & 0x000fff) << 12) | ((pixelRow1 & 0xfff000) >> 12);
|
||||
|
||||
// Swapped Data from row 1 is written
|
||||
block->Alpha.Data[0] = static_cast<uint8_t>(pixelRow1Swapped & 0x0000ff);
|
||||
block->Alpha.Data[1] = static_cast<uint8_t>((pixelRow1Swapped & 0x00ff00) >> 8);
|
||||
block->Alpha.Data[2] = static_cast<uint8_t>((pixelRow1Swapped & 0xff0000) >> 16);
|
||||
|
||||
// Swapped Data from row 0 is written
|
||||
block->Alpha.Data[3] = static_cast<uint8_t>(pixelRow0Swapped & 0x0000ff);
|
||||
block->Alpha.Data[4] = static_cast<uint8_t>((pixelRow0Swapped & 0x00ff00) >> 8);
|
||||
block->Alpha.Data[5] = static_cast<uint8_t>((pixelRow0Swapped & 0xff0000) >> 16);
|
||||
|
||||
std::swap(block->Data.Data[0], block->Data.Data[3]);
|
||||
std::swap(block->Data.Data[1], block->Data.Data[2]);
|
||||
}
|
||||
@@ -96,10 +96,10 @@ PNG::~PNG()
|
||||
|
||||
void PNG::pngErrorFunction(png_structp png_ptr, png_const_charp error_msg)
|
||||
{
|
||||
LOG_WARNING("%s", error_msg);
|
||||
LOG_WARNING("libpng error: %s", error_msg);
|
||||
}
|
||||
|
||||
void PNG::pngWarningFunction(png_structp png_ptr, png_const_charp warning_msg)
|
||||
{
|
||||
LOG_WARNING("%s", warning_msg);
|
||||
LOG_WARNING("libpng warning: %s", warning_msg);
|
||||
}
|
||||
|
||||
@@ -271,7 +271,7 @@ void RawModelCustom::ReadMaterialTextureProperties(RawModelCustom::TextureProper
|
||||
}
|
||||
texture.TexturePath = "Textures/";
|
||||
texture.TexturePath += (fileData + offset);
|
||||
texture.TexturePath += ".png";
|
||||
texture.TexturePath += ".dds";
|
||||
offset += nameLength;
|
||||
if (offset + sizeof(glm::vec2) > fileByteSize) {
|
||||
throw Resource::FailedLoadingException("Reading Material texture UVTiling failed");
|
||||
|
||||
@@ -2,7 +2,15 @@
|
||||
|
||||
Texture::Texture(std::string path)
|
||||
{
|
||||
PNG* img = ResourceManager::Load<PNG, true>(path); //TODO: Make this threaded. Catch exeptions in all other load places.
|
||||
std::string ext = boost::filesystem::path(path).extension().string();
|
||||
Image* img;
|
||||
if (ext == ".png") {
|
||||
img = ResourceManager::Load<PNG, true>(path);
|
||||
} else if (ext == ".dds") {
|
||||
img = ResourceManager::Load<DDS, true>(path);
|
||||
} else {
|
||||
throw Resource::FailedLoadingException("Texture extension is not .png nor .dds");
|
||||
}
|
||||
|
||||
//PNG image(path);
|
||||
|
||||
@@ -18,7 +26,6 @@ Texture::Texture(std::string path)
|
||||
|
||||
this->Width = img->Width;
|
||||
this->Height = img->Height;
|
||||
this->Data = img->Data;
|
||||
|
||||
GLint format;
|
||||
switch (img->Format) {
|
||||
@@ -29,19 +36,57 @@ Texture::Texture(std::string path)
|
||||
format = GL_RGBA;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Construct the OpenGL texture
|
||||
glGenTextures(1, &m_Texture);
|
||||
glBindTexture(GL_TEXTURE_2D, m_Texture);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format, img->Width, img->Height, 0, format, GL_UNSIGNED_BYTE, img->Data);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
GLERROR("Texture load");
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
if (!img->Compressed) {
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
}
|
||||
unsigned int w = img->Width;
|
||||
unsigned int h = img->Width;
|
||||
unsigned char* data = img->Data;
|
||||
for (int mipLevel = 0; mipLevel < 1 + img->MipMapLevels; mipLevel++) {
|
||||
if (img->Compressed) {
|
||||
//LOG_DEBUG("mipLevel: %i", mipLevel);
|
||||
//LOG_DEBUG("w: %i", w);
|
||||
//LOG_DEBUG("h: %i", h);
|
||||
|
||||
std::size_t bpe = 16;
|
||||
std::size_t numBlocksWide = std::max<std::size_t>(1, (w + 3) / 4);
|
||||
std::size_t numBlocksHigh = std::max<std::size_t>(1, (h + 3) / 4);
|
||||
std::size_t rowBytes = numBlocksWide * bpe;
|
||||
std::size_t numRows = numBlocksHigh;
|
||||
std::size_t numBytes = rowBytes * numBlocksHigh;
|
||||
//LOG_DEBUG("numBytes: %i", numBytes);
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, mipLevel, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, w, h, 0, numBytes, data);
|
||||
data += numBytes;
|
||||
} else {
|
||||
glTexImage2D(GL_TEXTURE_2D, mipLevel, format, img->Width, img->Height, 0, format, GL_UNSIGNED_BYTE, img->Data);
|
||||
}
|
||||
|
||||
w = w >> 1;
|
||||
h = h >> 1;
|
||||
}
|
||||
//LOG_DEBUG("REMAINDER: %i", img->ByteSize - (data - img->Data));
|
||||
// Generate mipmaps if the image file doesn't contain them
|
||||
if (img->MipMapLevels == 0) {
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
if (ext == ".png") {
|
||||
ResourceManager::Release("PNG", path);
|
||||
} else if (ext == ".dds") {
|
||||
ResourceManager::Release("DDS", path);
|
||||
}
|
||||
|
||||
if (GLERROR("Texture load")) {
|
||||
throw Resource::FailedLoadingException("GL texture generation failed");
|
||||
}
|
||||
}
|
||||
|
||||
Texture::~Texture()
|
||||
|
||||
+2
-1
@@ -39,7 +39,8 @@ Game::Game(int argc, char* argv[])
|
||||
ResourceManager::RegisterType<Model>("Model");
|
||||
ResourceManager::RegisterType<RawModel>("RawModel");
|
||||
ResourceManager::RegisterType<Texture>("Texture");
|
||||
ResourceManager::RegisterType<PNG>("Png");
|
||||
ResourceManager::RegisterType<PNG>("PNG");
|
||||
ResourceManager::RegisterType<DDS>("DDS");
|
||||
ResourceManager::RegisterType<ShaderProgram>("ShaderProgram");
|
||||
ResourceManager::RegisterType<EntityFile>("EntityFile");
|
||||
ResourceManager::RegisterType<Font>("FontFile");
|
||||
|
||||
Reference in New Issue
Block a user