diff --git a/examples/FirstScene/main.cpp b/examples/FirstScene/main.cpp index 65f948375..62a4425c8 100644 --- a/examples/FirstScene/main.cpp +++ b/examples/FirstScene/main.cpp @@ -95,6 +95,10 @@ int main() // Ce paramètre sert à indiquer la mise à l'échelle désirée lors du chargement du modèle. params.mesh.scale.Set(0.01f); // Un centième de la taille originelle + // Les UVs de ce fichier sont retournées (repère OpenGL, origine coin bas-gauche) par rapport à ce que le moteur attend + // Nous devons dire au moteur de les retourner lors du chargement + params.mesh.flipUVs = true; + // On charge ensuite le modèle depuis son fichier // Le moteur va charger le fichier et essayer de retrouver les fichiers associés (comme les matériaux, textures, ...) if (!spaceship.LoadFromFile("resources/Spaceship/spaceship.obj", params)) diff --git a/include/Nazara/Graphics/Material.hpp b/include/Nazara/Graphics/Material.hpp index c381beb3a..0f41e0f39 100644 --- a/include/Nazara/Graphics/Material.hpp +++ b/include/Nazara/Graphics/Material.hpp @@ -135,7 +135,7 @@ class NAZARA_API NzMaterial : public NzResource struct ShaderInstance { const NzShader* shader; - NzUberShaderInstance* uberInstance; + NzUberShaderInstance* uberInstance = nullptr; int uniforms[nzMaterialUniform_Max+1]; }; diff --git a/include/Nazara/Utility/Enums.hpp b/include/Nazara/Utility/Enums.hpp index 52bc9cba6..25e09c10a 100644 --- a/include/Nazara/Utility/Enums.hpp +++ b/include/Nazara/Utility/Enums.hpp @@ -221,12 +221,14 @@ enum nzVertexComponent { nzVertexComponent_Unused = -1, + // Nous nous limitons à 16 composants de sommets car c'est le minimum supporté par le GPU nzVertexComponent_InstanceData0, nzVertexComponent_InstanceData1, nzVertexComponent_InstanceData2, nzVertexComponent_InstanceData3, nzVertexComponent_InstanceData4, nzVertexComponent_InstanceData5, + nzVertexComponent_Color, nzVertexComponent_Normal, nzVertexComponent_Position, nzVertexComponent_Tangent, @@ -236,14 +238,13 @@ enum nzVertexComponent nzVertexComponent_Userdata2, nzVertexComponent_Userdata3, nzVertexComponent_Userdata4, - nzVertexComponent_Userdata5, nzVertexComponent_FirstInstanceData = nzVertexComponent_InstanceData0, - nzVertexComponent_FirstVertexData = nzVertexComponent_Normal, + nzVertexComponent_FirstVertexData = nzVertexComponent_Color, nzVertexComponent_LastInstanceData = nzVertexComponent_InstanceData5, - nzVertexComponent_LastVertexData = nzVertexComponent_Userdata5, + nzVertexComponent_LastVertexData = nzVertexComponent_Userdata4, - nzVertexComponent_Max = nzVertexComponent_Userdata5 + nzVertexComponent_Max = nzVertexComponent_Userdata4 }; enum nzVertexLayout diff --git a/include/Nazara/Utility/Event.hpp b/include/Nazara/Utility/Event.hpp index 50062e7b5..723866011 100644 --- a/include/Nazara/Utility/Event.hpp +++ b/include/Nazara/Utility/Event.hpp @@ -9,6 +9,7 @@ #ifndef NAZARA_EVENT_HPP #define NAZARA_EVENT_HPP +#include #include #include diff --git a/include/Nazara/Utility/Mesh.hpp b/include/Nazara/Utility/Mesh.hpp index 8c2036f05..116bbc3e7 100644 --- a/include/Nazara/Utility/Mesh.hpp +++ b/include/Nazara/Utility/Mesh.hpp @@ -36,6 +36,9 @@ struct NAZARA_API NzMeshParams // Faut-il centrer le mesh autour de l'origine ? bool center = false; + // Faut-il retourner les UV ? + bool flipUVs = false; + // Faut-il optimiser les index buffers ? (Rendu plus rapide, mais le chargement dure plus longtemps) bool optimizeIndexBuffers = true; diff --git a/src/Nazara/Graphics/Loaders/OBJ/Loader.cpp b/src/Nazara/Graphics/Loaders/OBJ/Loader.cpp index 449a82f2f..07c1742ec 100644 --- a/src/Nazara/Graphics/Loaders/OBJ/Loader.cpp +++ b/src/Nazara/Graphics/Loaders/OBJ/Loader.cpp @@ -142,7 +142,7 @@ namespace if (index >= 0) { const NzVector3f& uvw = texCoords[index]; - vertex.uv.Set(uvw.x, uvw.y); + vertex.uv.Set(uvw.x, (parameters.mesh.flipUVs) ? 1.f - uvw.y : uvw.y); // Inversion des UVs si demandé } else hasTexCoords = false; diff --git a/src/Nazara/Renderer/OpenGL.cpp b/src/Nazara/Renderer/OpenGL.cpp index a34dce25b..476800edf 100644 --- a/src/Nazara/Renderer/OpenGL.cpp +++ b/src/Nazara/Renderer/OpenGL.cpp @@ -2104,16 +2104,16 @@ nzUInt8 NzOpenGL::VertexComponentIndex[] = 13, // nzVertexComponent_InstanceData3 14, // nzVertexComponent_InstanceData4 15, // nzVertexComponent_InstanceData5 + 4, // nzVertexComponent_Color 2, // nzVertexComponent_Normal 0, // nzVertexComponent_Position 3, // nzVertexComponent_Tangent 1, // nzVertexComponent_TexCoord - 4, // nzVertexComponent_Userdata0 - 5, // nzVertexComponent_Userdata1 - 6, // nzVertexComponent_Userdata2 - 7, // nzVertexComponent_Userdata3 - 8, // nzVertexComponent_Userdata4 - 9 // nzVertexComponent_Userdata5 + 5, // nzVertexComponent_Userdata0 + 6, // nzVertexComponent_Userdata1 + 7, // nzVertexComponent_Userdata2 + 8, // nzVertexComponent_Userdata3 + 9 // nzVertexComponent_Userdata4 }; static_assert(nzVertexComponent_Max+1 == 16, "Attribute index array is incomplete"); diff --git a/src/Nazara/Renderer/Shader.cpp b/src/Nazara/Renderer/Shader.cpp index 699e36442..7729c1035 100644 --- a/src/Nazara/Renderer/Shader.cpp +++ b/src/Nazara/Renderer/Shader.cpp @@ -155,6 +155,7 @@ bool NzShader::Create() glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_InstanceData3], "InstanceData3"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_InstanceData4], "InstanceData4"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_InstanceData5], "InstanceData5"); + glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Color], "VertexColor"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Normal], "VertexNormal"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Position], "VertexPosition"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Tangent], "VertexTangent"); @@ -164,7 +165,6 @@ bool NzShader::Create() glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Userdata2], "VertexUserdata2"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Userdata3], "VertexUserdata3"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Userdata4], "VertexUserdata4"); - glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Userdata5], "VertexUserdata5"); if (NzRenderer::HasCapability(nzRendererCap_MultipleRenderTargets)) { diff --git a/src/Nazara/Renderer/Texture.cpp b/src/Nazara/Renderer/Texture.cpp index 4a5996e4e..e19ef2bbf 100644 --- a/src/Nazara/Renderer/Texture.cpp +++ b/src/Nazara/Renderer/Texture.cpp @@ -1048,33 +1048,25 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int s return false; } - nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_impl->format); - - unsigned int size = box.width*box.height*box.depth*bpp; - std::unique_ptr flipped(new nzUInt8[size]); - NzImage::Copy(flipped.get(), pixels, bpp, box.width, box.height, box.depth, 0, 0, srcWidth, srcHeight); - - // Inversion de la texture pour le repère d'OpenGL - if (!NzPixelFormat::Flip(nzPixelFlipping_Horizontally, m_impl->format, box.width, box.height, box.depth, flipped.get(), flipped.get())) - NazaraWarning("Failed to flip image"); - - SetUnpackAlignement(bpp); + SetUnpackAlignement(NzPixelFormat::GetBytesPerPixel(m_impl->format)); + glPixelStorei(GL_UNPACK_ROW_LENGTH, srcWidth); + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, srcHeight); NzOpenGL::BindTexture(m_impl->type, m_impl->id); switch (m_impl->type) { case nzImageType_1D: - glTexSubImage1D(GL_TEXTURE_1D, level, box.x, box.width, format.dataFormat, format.dataType, flipped.get()); + glTexSubImage1D(GL_TEXTURE_1D, level, box.x, box.width, format.dataFormat, format.dataType, pixels); break; case nzImageType_1D_Array: case nzImageType_2D: - glTexSubImage2D(NzOpenGL::TextureTarget[m_impl->type], level, box.x, height-box.height-box.y, box.width, box.height, format.dataFormat, format.dataType, flipped.get()); + glTexSubImage2D(NzOpenGL::TextureTarget[m_impl->type], level, box.x, height-box.height-box.y, box.width, box.height, format.dataFormat, format.dataType, pixels); break; case nzImageType_2D_Array: case nzImageType_3D: - glTexSubImage3D(NzOpenGL::TextureTarget[m_impl->type], level, box.x, height-box.height-box.y, box.z, box.width, box.height, box.depth, format.dataFormat, format.dataType, flipped.get()); + glTexSubImage3D(NzOpenGL::TextureTarget[m_impl->type], level, box.x, height-box.height-box.y, box.z, box.width, box.height, box.depth, format.dataFormat, format.dataType, pixels); break; case nzImageType_Cubemap: @@ -1192,20 +1184,12 @@ bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRe return false; } - nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_impl->format); - - // Inversion de la texture pour le repère d'OpenGL - unsigned int size = rect.width*rect.height*bpp; - std::unique_ptr flipped(new nzUInt8[size]); - NzImage::Copy(flipped.get(), pixels, bpp, rect.width, rect.height, 1, 0, 0, srcWidth, srcHeight); - - if (!NzPixelFormat::Flip(nzPixelFlipping_Horizontally, m_impl->format, rect.width, rect.height, 1, flipped.get(), flipped.get())) - NazaraWarning("Failed to flip image"); - - SetUnpackAlignement(bpp); + SetUnpackAlignement(NzPixelFormat::GetBytesPerPixel(m_impl->format)); + glPixelStorei(GL_UNPACK_ROW_LENGTH, srcWidth); + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, srcHeight); NzOpenGL::BindTexture(m_impl->type, m_impl->id); - glTexSubImage2D(NzOpenGL::CubemapFace[face], level, rect.x, height-rect.height-rect.y, rect.width, rect.height, format.dataFormat, format.dataType, flipped.get()); + glTexSubImage2D(NzOpenGL::CubemapFace[face], level, rect.x, height-rect.height-rect.y, rect.width, rect.height, format.dataFormat, format.dataType, pixels); return true; } diff --git a/src/Nazara/Utility/Image.cpp b/src/Nazara/Utility/Image.cpp index 7b963e30d..d59e3a4c6 100644 --- a/src/Nazara/Utility/Image.cpp +++ b/src/Nazara/Utility/Image.cpp @@ -922,15 +922,17 @@ bool NzImage::LoadArrayFromImage(const NzImage& image, const NzVector2ui& atlasS NzVector2ui faceSize = imageSize/atlasSize; + unsigned int layerCount = atlasSize.x*atlasSize.y; + // Selon le type de l'image de base, on va créer un array d'images 2D ou 1D if (type == nzImageType_2D) - Create(nzImageType_2D_Array, image.GetFormat(), faceSize.x, faceSize.y); + Create(nzImageType_2D_Array, image.GetFormat(), faceSize.x, faceSize.y, layerCount); else - Create(nzImageType_1D_Array, image.GetFormat(), faceSize.x, 1); + Create(nzImageType_1D_Array, image.GetFormat(), faceSize.x, layerCount); unsigned int layer = 0; - for (unsigned int i = 0; i < atlasSize.x; ++i) - for (unsigned int j = 0; j < atlasSize.y; ++j) + for (unsigned int j = 0; j < atlasSize.y; ++j) + for (unsigned int i = 0; i < atlasSize.x; ++i) Copy(image, NzRectui(i*faceSize.x, j*faceSize.y, faceSize.x, faceSize.y), NzVector3ui(0, 0, layer++)); return true; diff --git a/src/Nazara/Utility/Loaders/MD2/Loader.cpp b/src/Nazara/Utility/Loaders/MD2/Loader.cpp index 693711f75..f57c53340 100644 --- a/src/Nazara/Utility/Loaders/MD2/Loader.cpp +++ b/src/Nazara/Utility/Loaders/MD2/Loader.cpp @@ -200,7 +200,10 @@ namespace { const unsigned int fixedIndex = indexFix[j]; const MD2_TexCoord& texC = texCoords[triangles[i].texCoords[fixedIndex]]; - vertex[triangles[i].vertices[fixedIndex]].uv.Set(static_cast(texC.u) / header.skinwidth, 1.f - static_cast(texC.v)/header.skinheight); + float u = static_cast(texC.u) / header.skinwidth; + float v = static_cast(texC.v) / header.skinheight; + + vertex[triangles[i].vertices[fixedIndex]].uv.Set(u, (parameters.flipUVs) ? 1.f - v : v); } } diff --git a/src/Nazara/Utility/Loaders/MD5Mesh/Loader.cpp b/src/Nazara/Utility/Loaders/MD5Mesh/Loader.cpp index 8b0a88802..b2b518dae 100644 --- a/src/Nazara/Utility/Loaders/MD5Mesh/Loader.cpp +++ b/src/Nazara/Utility/Loaders/MD5Mesh/Loader.cpp @@ -178,10 +178,7 @@ namespace } vertices->position = finalPos; - - // Le format MD5 spécifie ses UV avec l'origine en bas à gauche, contrairement au moteur - // dont l'origine est en haut à gauche, nous inversons donc la valeur en Y. - vertices->uv.Set(vertex.uv.x, 1.f - vertex.uv.y); + vertices->uv.Set(vertex.uv.x, (parameters.flipUVs) ? 1.f - vertex.uv.y : vertex.uv.y); // Inversion des UV si demandé vertices++; } @@ -271,7 +268,7 @@ namespace // On retourne le modèle dans le bon sens vertex->position = scale * (rotationQuat * finalPos); - vertex->uv.Set(md5Vertex.uv.x, 1.f - md5Vertex.uv.y); + vertex->uv.Set(md5Vertex.uv.x, (parameters.flipUVs) ? 1.f - md5Vertex.uv.y : md5Vertex.uv.y); // Inversion des UV si demandé vertex++; }