properly handle texture compression

This commit is contained in:
Mikulas Florek 2021-03-30 20:37:40 +02:00
parent 72715eec6d
commit 78652c670e
12 changed files with 40 additions and 45 deletions

View file

@ -4,7 +4,6 @@ layer "default"
emission(0.000000) emission(0.000000)
metallic(0.000000) metallic(0.000000)
roughness(1.000000) roughness(1.000000)
alpha_ref(0.300000)
defines {} defines {}
color { 1.000000, 1.000000, 1.000000, 1.000000 } color { 1.000000, 1.000000, 1.000000, 1.000000 }
texture "" texture ""

View file

@ -4,7 +4,6 @@ layer "default"
emission(0.000000) emission(0.000000)
metallic(0.000000) metallic(0.000000)
roughness(1.000000) roughness(1.000000)
alpha_ref(0.300000)
defines {} defines {}
color { 1.000000, 1.000000, 1.000000, 1.000000 } color { 1.000000, 1.000000, 1.000000, 1.000000 }
texture "" texture ""

View file

@ -4,7 +4,6 @@ layer "default"
emission(0.000000) emission(0.000000)
metallic(0.000000) metallic(0.000000)
roughness(1.000000) roughness(1.000000)
alpha_ref(0.300000)
defines {} defines {}
color { 1.000000, 0.999990, 0.999990, 1.000000 } color { 1.000000, 0.999990, 0.999990, 1.000000 }
texture "" texture ""

View file

@ -4,7 +4,6 @@ layer "default"
emission(0.000000) emission(0.000000)
metallic(0.000000) metallic(0.000000)
roughness(1.000000) roughness(1.000000)
alpha_ref(0.300000)
defines {} defines {}
color { 1.000000, 1.000000, 1.000000, 1.000000 } color { 1.000000, 1.000000, 1.000000, 1.000000 }
texture "" texture ""

View file

@ -4,7 +4,6 @@ layer "default"
emission(0.000000) emission(0.000000)
metallic(1.000000) metallic(1.000000)
roughness(0.040000) roughness(0.040000)
alpha_ref(0.300000)
defines {} defines {}
color { 1.000000, 0.000000, 0.000000, 1.000000 } color { 1.000000, 0.000000, 0.000000, 1.000000 }
texture "" texture ""

View file

@ -4,7 +4,6 @@ layer "default"
emission(0.000000) emission(0.000000)
metallic(1.000000) metallic(1.000000)
roughness(0.780000) roughness(0.780000)
alpha_ref(0.300000)
defines {} defines {}
color { 0.000000, 0.310755, 0.543779, 1.000000 } color { 0.000000, 0.310755, 0.543779, 1.000000 }
texture "" texture ""

View file

@ -4,7 +4,6 @@ layer "default"
emission(0.000000) emission(0.000000)
metallic(0.000000) metallic(0.000000)
roughness(0.800000) roughness(0.800000)
alpha_ref(0.300000)
defines {} defines {}
color { 0.000001, 0.000000, 0.000000, 1.000000 } color { 0.000001, 0.000000, 0.000000, 1.000000 }
texture "" texture ""

View file

@ -4,7 +4,6 @@ layer "default"
emission(0.000000) emission(0.000000)
metallic(0.000000) metallic(0.000000)
roughness(1.000000) roughness(1.000000)
alpha_ref(0.300000)
defines {} defines {}
color { 1.000000, 1.000000, 1.000000, 1.000000 } color { 1.000000, 1.000000, 1.000000, 1.000000 }
texture "demo.png" texture "demo.png"

View file

@ -102,7 +102,7 @@ vertex_shader [[
v_lod = i_lod; v_lod = i_lod;
#endif #endif
#if defined GRASS && defined VEGETATION #if defined GRASS && defined VEGETATION
p = vegetationAnim(i_pos_scale.xyz, p, 1 / (1 + u_stiffness)); p = vegetationAnim(i_pos_scale.xyz, p, 1.0 / (1.0 + u_stiffness));
v_darken = a_position.y > 0.1 ? 1 : 0.0; v_darken = a_position.y > 0.1 ? 1 : 0.0;
#elif defined VEGETATION #elif defined VEGETATION
#ifdef DEPTH #ifdef DEPTH

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 B

After

Width:  |  Height:  |  Size: 60 B

View file

@ -1160,8 +1160,14 @@ struct TexturePlugin final : AssetBrowser::IPlugin, AssetCompiler::IPlugin
output.setOutputHandler(&output_handler); output.setOutputHandler(&output_handler);
nvtt::CompressionOptions compression; nvtt::CompressionOptions compression;
compression.setFormat(meta.is_normalmap ? nvtt::Format_BC5 : (has_alpha ? nvtt::Format_BC3 : nvtt::Format_BC1)); if (w % 4 != 0 || h % 4 != 0) {
compression.setQuality(toNVTT(meta.quality)); logWarning("Can not compress ", path, " because its size (", w, ", ", h, ") is not multiple of 4");
compression.setFormat(has_alpha ? nvtt::Format_RGBA : nvtt::Format_RGB);
}
else {
compression.setFormat(meta.is_normalmap ? nvtt::Format_BC5 : (has_alpha ? nvtt::Format_BC3 : nvtt::Format_BC1));
compression.setQuality(toNVTT(meta.quality));
}
if (!context.process(input, compression, output)) { if (!context.process(input, compression, output)) {
return false; return false;
@ -1480,7 +1486,7 @@ struct TexturePlugin final : AssetBrowser::IPlugin, AssetCompiler::IPlugin
ImGuiEx::Label("SRGB"); ImGuiEx::Label("SRGB");
ImGui::Checkbox("##srgb", &m_meta.srgb); ImGui::Checkbox("##srgb", &m_meta.srgb);
bool is_tga = Path::hasExtension(texture->getPath().c_str(), "tga"); const bool is_tga = Path::hasExtension(texture->getPath().c_str(), "tga");
if (is_tga) { if (is_tga) {
ImGuiEx::Label("Compress"); ImGuiEx::Label("Compress");
ImGui::Checkbox("##cmprs", &m_meta.compress); ImGui::Checkbox("##cmprs", &m_meta.compress);
@ -1489,6 +1495,10 @@ struct TexturePlugin final : AssetBrowser::IPlugin, AssetCompiler::IPlugin
if ((m_meta.compress || !is_tga) && !m_meta.convert_to_raw) { if ((m_meta.compress || !is_tga) && !m_meta.convert_to_raw) {
ImGuiEx::Label("Compression quality"); ImGuiEx::Label("Compression quality");
ImGui::Combo("Quality", (i32*)&m_meta.quality, "Fastest\0Normal\0Production\0Highest\0"); ImGui::Combo("Quality", (i32*)&m_meta.quality, "Fastest\0Normal\0Production\0Highest\0");
if (texture->width % 4 != 0 || texture->height % 4 != 0) {
ImGui::TextUnformatted(ICON_FA_EXCLAMATION_TRIANGLE " Block compression will not be used because texture size is not multiple of 4");
}
} }
ImGuiEx::Label("Convert to RAW"); ImGuiEx::Label("Convert to RAW");

View file

@ -1129,8 +1129,6 @@ static bool upload(GLuint texture
else { else {
glCompressedTextureSubImage2D(texture, mip, 0, 0, width, height, internal_format, size, data_ptr); glCompressedTextureSubImage2D(texture, mip, 0, 0, width, height, internal_format, size, data_ptr);
} }
glTextureParameteri(texture, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTextureParameteri(texture, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
width = maximum(1, width >> 1); width = maximum(1, width >> 1);
height = maximum(1, height >> 1); height = maximum(1, height >> 1);
size = DDS::sizeDXTC(width, height, internal_format); size = DDS::sizeDXTC(width, height, internal_format);
@ -1154,7 +1152,6 @@ static bool upload(GLuint texture
for (u32 zz = 0; zz < size; ++zz) { for (u32 zz = 0; zz < size; ++zz) {
unpacked_ptr[zz] = palette[data_ptr[zz]]; unpacked_ptr[zz] = palette[data_ptr[zz]];
} }
//glPixelStorei(GL_UNPACK_ROW_LENGTH, height);
if(layers > 1) { if(layers > 1) {
glTextureSubImage3D(texture, mip, 0, 0, layer, width, height, 1, li->externalFormat, li->type, unpacked_ptr); glTextureSubImage3D(texture, mip, 0, 0, layer, width, height, 1, li->externalFormat, li->type, unpacked_ptr);
} }
@ -1173,7 +1170,6 @@ static bool upload(GLuint texture
u32 size = width * height * li->blockBytes; u32 size = width * height * li->blockBytes;
for (u32 mip = 0; mip < mipMapCount; ++mip) { for (u32 mip = 0; mip < mipMapCount; ++mip) {
const u8* data_ptr = (u8*)blob.skip(size); const u8* data_ptr = (u8*)blob.skip(size);
//glPixelStorei(GL_UNPACK_ROW_LENGTH, height);
if (layers > 1) { if (layers > 1) {
glTextureSubImage3D(texture, mip, 0, 0, layer, width, height, 1, li->externalFormat, li->type, data_ptr); glTextureSubImage3D(texture, mip, 0, 0, layer, width, height, 1, li->externalFormat, li->type, data_ptr);
} }
@ -1262,6 +1258,27 @@ bool loadLayers(TextureHandle handle, u32 layer_offset, const void* data, int si
return upload(handle->gl_handle, layer_offset, layers, hdr, li, is_srgb, blob, debug_name); return upload(handle->gl_handle, layer_offset, layers, hdr, li, is_srgb, blob, debug_name);
} }
static void setSampler(GLuint texture, TextureFlags flags) {
const GLint wrap_u = u32(flags & TextureFlags::CLAMP_U) ? GL_CLAMP_TO_EDGE : GL_REPEAT;
const GLint wrap_v = u32(flags & TextureFlags::CLAMP_V) ? GL_CLAMP_TO_EDGE : GL_REPEAT;
const GLint wrap_w = u32(flags & TextureFlags::CLAMP_W) ? GL_CLAMP_TO_EDGE : GL_REPEAT;
glTextureParameteri(texture, GL_TEXTURE_WRAP_S, wrap_u);
glTextureParameteri(texture, GL_TEXTURE_WRAP_T, wrap_v);
glTextureParameteri(texture, GL_TEXTURE_WRAP_R, wrap_w);
if (u32(flags & TextureFlags::POINT_FILTER)) {
glTextureParameteri(texture, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTextureParameteri(texture, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
else {
const bool no_mips = u32(flags & TextureFlags::NO_MIPS);
glTextureParameteri(texture, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTextureParameteri(texture, GL_TEXTURE_MIN_FILTER, no_mips ? GL_LINEAR : GL_LINEAR_MIPMAP_LINEAR);
}
const bool is_anisotropic_filter = u32(flags & TextureFlags::ANISOTROPIC_FILTER);
if (is_anisotropic_filter && gl->max_anisotropy > 0) {
glTextureParameterf(texture, GL_TEXTURE_MAX_ANISOTROPY, gl->max_anisotropy);
}
}
bool loadTexture(TextureHandle handle, const void* input, int input_size, TextureFlags flags, const char* debug_name) bool loadTexture(TextureHandle handle, const void* input, int input_size, TextureFlags flags, const char* debug_name)
{ {
@ -1350,15 +1367,7 @@ bool loadTexture(TextureHandle handle, const void* input, int input_size, Textur
if (!upload(texture, 0, layers, hdr, li, is_srgb, blob, debug_name)) return false; if (!upload(texture, 0, layers, hdr, li, is_srgb, blob, debug_name)) return false;
const GLint wrap_u = u32(flags & TextureFlags::CLAMP_U) ? GL_CLAMP : GL_REPEAT; setSampler(texture, flags);
const GLint wrap_v = u32(flags & TextureFlags::CLAMP_V) ? GL_CLAMP : GL_REPEAT;
const GLint wrap_w = u32(flags & TextureFlags::CLAMP_W) ? GL_CLAMP : GL_REPEAT;
glTextureParameteri(texture, GL_TEXTURE_WRAP_S, wrap_u);
glTextureParameteri(texture, GL_TEXTURE_WRAP_T, wrap_v);
glTextureParameteri(texture, GL_TEXTURE_WRAP_R, wrap_w);
if (is_anisotropic_filter && gl->max_anisotropy > 0) {
glTextureParameterf(texture, GL_TEXTURE_MAX_ANISOTROPY, gl->max_anisotropy);
}
Texture& t = *handle; Texture& t = *handle;
t.format = internal_format; t.format = internal_format;
@ -1395,7 +1404,6 @@ TextureHandle allocTextureHandle()
return t; return t;
} }
void createTextureView(TextureHandle view, TextureHandle texture) void createTextureView(TextureHandle view, TextureHandle texture)
{ {
checkThread(); checkThread();
@ -1412,11 +1420,12 @@ void createTextureView(TextureHandle view, TextureHandle texture)
glGenTextures(1, &view->gl_handle); glGenTextures(1, &view->gl_handle);
glTextureView(view->gl_handle, GL_TEXTURE_2D, texture->gl_handle, texture->format, 0, 1, 0, 1); glTextureView(view->gl_handle, GL_TEXTURE_2D, texture->gl_handle, texture->format, 0, 1, 0, 1);
setSampler(view->gl_handle, texture->flags);
view->width = texture->width; view->width = texture->width;
view->height = texture->height; view->height = texture->height;
} }
bool createTexture(TextureHandle handle, u32 w, u32 h, u32 depth, TextureFormat format, TextureFlags flags, const void* data, const char* debug_name) bool createTexture(TextureHandle handle, u32 w, u32 h, u32 depth, TextureFormat format, TextureFlags flags, const void* data, const char* debug_name)
{ {
checkThread(); checkThread();
@ -1516,24 +1525,8 @@ bool createTexture(TextureHandle handle, u32 w, u32 h, u32 depth, TextureFormat
glObjectLabel(GL_TEXTURE, texture, stringLength(debug_name), debug_name); glObjectLabel(GL_TEXTURE, texture, stringLength(debug_name), debug_name);
} }
glGenerateTextureMipmap(texture); glGenerateTextureMipmap(texture);
const GLint wrap_u = u32(flags & TextureFlags::CLAMP_U) ? GL_CLAMP_TO_EDGE : GL_REPEAT; setSampler(texture, flags);
const GLint wrap_v = u32(flags & TextureFlags::CLAMP_V) ? GL_CLAMP_TO_EDGE : GL_REPEAT;
const GLint wrap_w = u32(flags & TextureFlags::CLAMP_W) ? GL_CLAMP_TO_EDGE : GL_REPEAT;
glTextureParameteri(texture, GL_TEXTURE_WRAP_S, wrap_u);
glTextureParameteri(texture, GL_TEXTURE_WRAP_T, wrap_v);
glTextureParameteri(texture, GL_TEXTURE_WRAP_R, wrap_w);
if (u32(flags & TextureFlags::POINT_FILTER)) {
glTextureParameteri(texture, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTextureParameteri(texture, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
else {
glTextureParameteri(texture, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTextureParameteri(texture, GL_TEXTURE_MIN_FILTER, no_mips ? GL_LINEAR : GL_LINEAR_MIPMAP_LINEAR);
}
if (is_anisotropic_filter && gl->max_anisotropy > 0) {
glTextureParameterf(texture, GL_TEXTURE_MAX_ANISOTROPY, gl->max_anisotropy);
}
handle->gl_handle = texture; handle->gl_handle = texture;
handle->target = target; handle->target = target;