261 lines
7.1 KiB
C++
261 lines
7.1 KiB
C++
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <string>
|
|
#include <cassert>
|
|
#include <cmath>
|
|
#include <vector>
|
|
#include <iostream>
|
|
#include <array>
|
|
|
|
#include <GL/gl3w.h>
|
|
#include <GLFW/glfw3.h>
|
|
|
|
#define FOURCC_DXT1 0x31545844 // Equivalent to "DXT1" in ASCII
|
|
#define FOURCC_DXT3 0x33545844 // Equivalent to "DXT3" in ASCII
|
|
#define FOURCC_DXT5 0x35545844 // Equivalent to "DXT5" in ASCII
|
|
|
|
GLuint loadDDS(const std::string& imagepath, bool linear){
|
|
|
|
unsigned char header[124];
|
|
|
|
FILE *fp;
|
|
|
|
/* try to open the file */
|
|
fp = fopen(imagepath.c_str(), "rb");
|
|
if (fp == NULL){
|
|
printf("%s could not be opened.\n", imagepath.c_str()); getchar();
|
|
return 0;
|
|
}
|
|
|
|
/* verify the type of file */
|
|
char filecode[4];
|
|
fread(filecode, 1, 4, fp);
|
|
if (strncmp(filecode, "DDS ", 4) != 0) {
|
|
fclose(fp);
|
|
return 0;
|
|
}
|
|
|
|
/* get the surface desc */
|
|
fread(&header, 124, 1, fp);
|
|
|
|
unsigned int height = *(unsigned int*)&(header[8 ]);
|
|
unsigned int width = *(unsigned int*)&(header[12]);
|
|
unsigned int linearSize = *(unsigned int*)&(header[16]);
|
|
unsigned int mipMapCount = *(unsigned int*)&(header[24]);
|
|
unsigned int fourCC = *(unsigned int*)&(header[80]);
|
|
|
|
|
|
unsigned char * buffer;
|
|
unsigned int bufsize;
|
|
/* how big is it going to be including all mipmaps? */
|
|
bufsize = mipMapCount > 1 ? linearSize * 2 : linearSize;
|
|
buffer = (unsigned char*)malloc(bufsize * sizeof(unsigned char));
|
|
fread(buffer, 1, bufsize, fp);
|
|
/* close the file pointer */
|
|
fclose(fp);
|
|
|
|
unsigned int format;
|
|
switch(fourCC)
|
|
{
|
|
case FOURCC_DXT1:
|
|
format = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
|
|
break;
|
|
case FOURCC_DXT3:
|
|
format = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
|
|
break;
|
|
case FOURCC_DXT5:
|
|
format = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
|
|
break;
|
|
default:
|
|
free(buffer);
|
|
return 0;
|
|
}
|
|
|
|
// Create one OpenGL texture
|
|
GLuint textureID;
|
|
glGenTextures(1, &textureID);
|
|
|
|
// "Bind" the newly created texture : all future texture functions will modify this texture
|
|
glBindTexture(GL_TEXTURE_2D, textureID);
|
|
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
|
|
|
|
unsigned int blockSize = (format == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT) ? 8 : 16;
|
|
unsigned int offset = 0;
|
|
|
|
/* load the mipmaps */
|
|
for (unsigned int level = 0; level < mipMapCount && (width || height); ++level)
|
|
{
|
|
unsigned int size = ((width+3)/4)*((height+3)/4)*blockSize;
|
|
glCompressedTexImage2D(GL_TEXTURE_2D, level, format, width, height,
|
|
0, size, buffer + offset);
|
|
|
|
offset += size;
|
|
width /= 2;
|
|
height /= 2;
|
|
|
|
// Deal with Non-Power-Of-Two textures. This code is not included in the webpage to reduce clutter.
|
|
if(width < 1) width = 1;
|
|
if(height < 1) height = 1;
|
|
|
|
}
|
|
|
|
free(buffer);
|
|
|
|
glTextureParameteri(textureID, GL_TEXTURE_MAG_FILTER, linear ? GL_LINEAR : GL_NEAREST);
|
|
glTextureParameteri(textureID, GL_TEXTURE_MIN_FILTER, linear ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST);
|
|
|
|
glGenerateTextureMipmap(textureID);
|
|
|
|
return textureID;
|
|
|
|
}
|
|
|
|
GLuint loadDDSArray(const std::vector<std::string>& imagepaths, float mipMapLOD, float anisotropy) {
|
|
|
|
unsigned char header[124];
|
|
|
|
auto imagepath = imagepaths.begin();
|
|
|
|
FILE *fp;
|
|
|
|
/* try to open the file */
|
|
fp = fopen(imagepath->c_str(), "rb");
|
|
if (fp == NULL)
|
|
{
|
|
printf("%s could not be opened.\n", imagepath->c_str());
|
|
getchar();
|
|
return 0;
|
|
}
|
|
|
|
/* verify the type of file */
|
|
char filecode[4];
|
|
fread(filecode, 1, 4, fp);
|
|
if (strncmp(filecode, "DDS ", 4) != 0)
|
|
{
|
|
fclose(fp);
|
|
return 0;
|
|
}
|
|
|
|
/* get the surface desc */
|
|
fread(&header, 124, 1, fp);
|
|
|
|
unsigned int mainHeight = *(unsigned int *)&(header[8]);
|
|
unsigned int mainWidth = *(unsigned int *)&(header[12]);
|
|
unsigned int mainFourCC = *(unsigned int *)&(header[80]);
|
|
fclose(fp);
|
|
|
|
unsigned int mainFormat;
|
|
switch (mainFourCC)
|
|
{
|
|
case FOURCC_DXT1:
|
|
mainFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
|
|
break;
|
|
case FOURCC_DXT3:
|
|
mainFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
|
|
break;
|
|
case FOURCC_DXT5:
|
|
mainFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
// Create one OpenGL texture array
|
|
GLuint textureID;
|
|
glCreateTextures(GL_TEXTURE_2D_ARRAY, 1, &textureID);
|
|
glTextureStorage3D(textureID, 1 + std::floor(std::log2(std::max(mainWidth, mainHeight))), mainFormat, mainWidth, mainHeight, imagepaths.size());
|
|
|
|
ushort layer = 0;
|
|
for (imagepath = imagepaths.begin(); imagepath != imagepaths.end(); ++imagepath, ++layer)
|
|
{
|
|
GLuint subTextureID = loadDDS(*imagepath, false);
|
|
glCopyImageSubData(subTextureID, GL_TEXTURE_2D, 0, 0, 0, 0, textureID, GL_TEXTURE_2D_ARRAY, 0, 0, 0, layer, mainWidth, mainHeight, 1);
|
|
glDeleteTextures(1, &subTextureID);
|
|
}
|
|
|
|
glTextureParameteri(textureID, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTextureParameteri(textureID, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
|
glTextureParameterf(textureID, GL_TEXTURE_LOD_BIAS, mipMapLOD);
|
|
glTextureParameterf(textureID, GL_TEXTURE_MAX_ANISOTROPY, anisotropy);
|
|
|
|
glGenerateTextureMipmap(textureID);
|
|
|
|
return textureID;
|
|
|
|
}
|
|
|
|
GLuint loadDDSCube(const std::array<std::string, 6>& imagepaths) {
|
|
|
|
unsigned char header[124];
|
|
|
|
auto imagepath = imagepaths.begin();
|
|
|
|
FILE *fp;
|
|
|
|
/* try to open the file */
|
|
fp = fopen(imagepath->c_str(), "rb");
|
|
if (fp == NULL)
|
|
{
|
|
printf("%s could not be opened.\n", imagepath->c_str());
|
|
getchar();
|
|
return 0;
|
|
}
|
|
|
|
/* verify the type of file */
|
|
char filecode[4];
|
|
fread(filecode, 1, 4, fp);
|
|
if (strncmp(filecode, "DDS ", 4) != 0)
|
|
{
|
|
fclose(fp);
|
|
return 0;
|
|
}
|
|
|
|
/* get the surface desc */
|
|
fread(&header, 124, 1, fp);
|
|
|
|
unsigned int mainHeight = *(unsigned int *)&(header[8]);
|
|
unsigned int mainWidth = *(unsigned int *)&(header[12]);
|
|
unsigned int mainFourCC = *(unsigned int *)&(header[80]);
|
|
fclose(fp);
|
|
|
|
unsigned int mainFormat;
|
|
switch (mainFourCC)
|
|
{
|
|
case FOURCC_DXT1:
|
|
mainFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
|
|
break;
|
|
case FOURCC_DXT3:
|
|
mainFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
|
|
break;
|
|
case FOURCC_DXT5:
|
|
mainFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
// Create one OpenGL texture array
|
|
GLuint textureID;
|
|
glCreateTextures(GL_TEXTURE_CUBE_MAP, 1, &textureID);
|
|
glTextureStorage2D(textureID, 1, mainFormat, mainWidth, mainHeight);
|
|
|
|
ushort layer = 0;
|
|
for (imagepath = imagepaths.begin(); imagepath != imagepaths.end(); ++imagepath, ++layer)
|
|
{
|
|
GLuint subTextureID = loadDDS(*imagepath, false);
|
|
glCopyImageSubData(subTextureID, GL_TEXTURE_2D, 0, 0, 0, 0, textureID, GL_TEXTURE_CUBE_MAP, 0, 0, 0, layer, mainWidth, mainHeight, 1);
|
|
glDeleteTextures(1, &subTextureID);
|
|
}
|
|
|
|
glTextureParameteri(textureID, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTextureParameteri(textureID, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTextureParameteri(textureID, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTextureParameteri(textureID, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTextureParameteri(textureID, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
|
|
glGenerateTextureMipmap(textureID);
|
|
|
|
return textureID;
|
|
|
|
} |