You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
330 lines
8.5 KiB
330 lines
8.5 KiB
#include "misc.h"
|
|
#include <stdio.h>
|
|
#include <windows.h>
|
|
#include "FreeImage.h"
|
|
|
|
#pragma comment(lib,"FreeImage.lib")
|
|
|
|
GLuint CreateBufferObject(GLenum bufferType, GLsizeiptr size, GLenum usage, void * data)
|
|
{
|
|
GLuint object;
|
|
glGenBuffers(1, &object);
|
|
glBindBuffer(bufferType, object);
|
|
glBufferData(bufferType, size, data, usage);
|
|
glBindBuffer(bufferType, 0);
|
|
|
|
return object;
|
|
}
|
|
|
|
GLuint CreateVAOWithVBOSettings(std::function<void()> settings)
|
|
{
|
|
GLuint vao;
|
|
glGenVertexArrays(1, &vao);
|
|
glBindVertexArray(vao);
|
|
settings();
|
|
glBindVertexArray(0);
|
|
return vao;
|
|
}
|
|
|
|
char* LoadFileContent(const char *path) {
|
|
FILE* pFile = fopen(path, "rb");
|
|
if (pFile) {
|
|
fseek(pFile, 0, SEEK_END);
|
|
int nLen = ftell(pFile);
|
|
char* buffer = nullptr;
|
|
if (nLen != 0) {
|
|
buffer = new char[nLen + 1];
|
|
rewind(pFile);
|
|
fread(buffer, nLen, 1, pFile);
|
|
buffer[nLen] = '\0';
|
|
}
|
|
else {
|
|
printf("load file %s fail, content is 0\n", path);
|
|
}
|
|
fclose(pFile);
|
|
return buffer;
|
|
}
|
|
else {
|
|
printf("open file %s fail\n", path);
|
|
}
|
|
fclose(pFile);
|
|
return nullptr;
|
|
}
|
|
|
|
GLuint CompileShader(GLenum shaderType, const char * shaderPath)
|
|
{
|
|
//创建shader
|
|
GLuint shader = glCreateShader(shaderType);
|
|
if (shader == 0) {
|
|
printf("glCreateShader false\n");
|
|
return 0;
|
|
}
|
|
//读取shader代码
|
|
const char* shaderCode = LoadFileContent(shaderPath);
|
|
if (shaderCode == nullptr) {
|
|
printf("load shader code from file: %s false\n", shaderPath);
|
|
return 0;
|
|
}
|
|
//把shader代码 从内存传到显存
|
|
glShaderSource(shader, 1, &shaderCode, nullptr);
|
|
glCompileShader(shader);
|
|
|
|
GLint compileResult = GL_TRUE;
|
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
|
|
if (compileResult == GL_FALSE) {
|
|
char szLog[1024] = { 0 };
|
|
GLsizei logLen = 0;//实际错误日志长度
|
|
glGetShaderInfoLog(shader, 1024, &logLen, szLog);
|
|
printf("Compile shader fail error log is : %s \n shader code :\n %s \n ", szLog, shaderCode);
|
|
glDeleteShader(shader);
|
|
return 0;
|
|
}
|
|
|
|
return shader;
|
|
}
|
|
|
|
/**
|
|
* 创建一个GPU程序
|
|
*/
|
|
GLuint CreateGPUProgram(const char* vsShaderPath, const char* fsShaderPath) {
|
|
|
|
GLuint vsShader = CompileShader(GL_VERTEX_SHADER,vsShaderPath);
|
|
GLuint fsShader = CompileShader(GL_FRAGMENT_SHADER,fsShaderPath);
|
|
|
|
//创建program
|
|
GLuint program = glCreateProgram();
|
|
|
|
//绑定shader
|
|
glAttachShader(program, vsShader);
|
|
glAttachShader(program, fsShader);
|
|
|
|
//连接
|
|
glLinkProgram(program);
|
|
|
|
//解绑shader
|
|
glDetachShader(program, vsShader);
|
|
glDetachShader(program, fsShader);
|
|
|
|
//删除shader
|
|
glDeleteShader(vsShader);
|
|
glDeleteShader(fsShader);
|
|
|
|
//检查错误
|
|
GLint nResult;
|
|
glGetProgramiv(program, GL_LINK_STATUS, &nResult);
|
|
if (nResult == GL_FALSE) {
|
|
char log[1024] = { 0 };
|
|
GLsizei writed = 0;
|
|
glGetProgramInfoLog(program, 1024, &writed, log);
|
|
printf("Create CPU program fail error %s\n", log);
|
|
glDeleteProgram(program);
|
|
program = 0;
|
|
}
|
|
|
|
return program;
|
|
}
|
|
|
|
static unsigned char* DecodeBMPData(unsigned char* imgData, int &width, int &height) {
|
|
//decode bmp
|
|
int pixelDataOffset = *((int*)(imgData + 10));
|
|
width = *((int*)(imgData + 18));
|
|
height = *((int*)(imgData + 22));
|
|
|
|
unsigned char* pixelData = imgData + pixelDataOffset;
|
|
|
|
//bgr 转 rgb
|
|
for (int i = 0; i < width * height * 3; i += 3) {
|
|
unsigned char tmp = pixelData[i + 2];
|
|
pixelData[i + 2] = pixelData[i + 0];
|
|
pixelData[i + 0] = tmp;
|
|
}
|
|
return pixelData;
|
|
}
|
|
|
|
GLuint CreateTextureFromBMP(const char * imagePath)
|
|
{
|
|
unsigned char* imgData = (unsigned char*)LoadFileContent(imagePath);
|
|
|
|
if (*((unsigned short*)imgData) != 0x4D42) {
|
|
printf("cannot decode %s\n", imagePath);
|
|
return 0;
|
|
}
|
|
|
|
int width, height;
|
|
unsigned char* pixelData = DecodeBMPData(imgData, width, height);
|
|
|
|
GLuint texture;
|
|
glGenTextures(1, &texture);
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, pixelData);
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
|
delete imgData;
|
|
return texture;
|
|
}
|
|
|
|
|
|
|
|
static GLuint CreateTexture(int w, int h, const void* data, GLenum type)
|
|
{
|
|
GLuint texId;
|
|
glGenTextures(1, &texId);
|
|
glBindTexture(GL_TEXTURE_2D, texId);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexImage2D(GL_TEXTURE_2D, 0, type, w, h, 0, type, GL_UNSIGNED_BYTE, data);
|
|
return texId;
|
|
}
|
|
|
|
GLuint CreateTextureFromFile(const char * imagePath)
|
|
{
|
|
//1 获取图片格式
|
|
FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(imagePath, 0);
|
|
if (fifmt == FIF_UNKNOWN)
|
|
{
|
|
printf("File %s not found! ", imagePath);
|
|
return 0;
|
|
}
|
|
//2 加载图片
|
|
FIBITMAP *dib = FreeImage_Load(fifmt, imagePath, 0);
|
|
|
|
FREE_IMAGE_COLOR_TYPE type = FreeImage_GetColorType(dib);
|
|
|
|
//! 获取数据指针
|
|
FIBITMAP* temp = dib;
|
|
dib = FreeImage_ConvertTo32Bits(dib);
|
|
FreeImage_Unload(temp);
|
|
|
|
BYTE* pixels = (BYTE*)FreeImage_GetBits(dib);
|
|
int width = FreeImage_GetWidth(dib);
|
|
int height = FreeImage_GetHeight(dib);
|
|
|
|
for (int i = 0; i < width * height * 4; i += 4)
|
|
{
|
|
BYTE temp = pixels[i];
|
|
pixels[i] = pixels[i + 2];
|
|
pixels[i + 2] = temp;
|
|
}
|
|
|
|
GLuint res = CreateTexture(width, height, pixels, GL_RGBA);
|
|
FreeImage_Unload(dib);
|
|
return res;
|
|
}
|
|
|
|
const unsigned long FORMAT_DXT1 = 0x31545844l; // 这里其实DXT1倒叙的ascii码
|
|
static unsigned char* DecodeDXT1Data(unsigned char* imgData, int &width, int &height, int &pixelSize) {
|
|
height = *((int*)(imgData + sizeof(unsigned long) * 3));
|
|
width = *((int*)(imgData + sizeof(unsigned long) * 4));
|
|
pixelSize = *((int*)(imgData + sizeof(unsigned long) * 5));
|
|
|
|
unsigned long compressFormat;
|
|
compressFormat = *((int*)(imgData + sizeof(unsigned long) * 21));
|
|
|
|
switch (compressFormat) {
|
|
case FORMAT_DXT1:
|
|
printf("decode dxt1\n");
|
|
break;
|
|
}
|
|
unsigned char* pixelData = new unsigned char[pixelSize];
|
|
|
|
memcpy(pixelData, imgData + sizeof(unsigned long) * 32, pixelSize);
|
|
|
|
return pixelData;
|
|
}
|
|
|
|
GLuint CreateTextureFromDds(const char * imagePath)
|
|
{
|
|
unsigned char* imgData = (unsigned char*)LoadFileContent(imagePath);
|
|
|
|
if (memcmp(imgData, "DDS ", 4) != 0) {
|
|
printf("cannot decode %s\n", imagePath);
|
|
return 0;
|
|
}
|
|
|
|
int width, height;
|
|
int pixelSize = 0;
|
|
unsigned char* pixelData = DecodeDXT1Data(imgData, width, height, pixelSize);
|
|
|
|
GLuint texture;
|
|
glGenTextures(1, &texture);
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
//GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
|
|
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, width, height, 0, pixelSize, pixelData);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
delete imgData;
|
|
return texture;
|
|
}
|
|
void SaveImage(const char*imagePath, unsigned char*imgData, int width, int height)
|
|
{
|
|
FILE*pFile = fopen(imagePath, "wb");
|
|
if (pFile)
|
|
{
|
|
BITMAPFILEHEADER bfh;
|
|
memset(&bfh, 0, sizeof(BITMAPFILEHEADER));
|
|
bfh.bfType = 0x4D42;
|
|
bfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + width*height * 3;
|
|
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
|
|
fwrite(&bfh, sizeof(BITMAPFILEHEADER), 1, pFile);
|
|
|
|
BITMAPINFOHEADER bih;
|
|
memset(&bih, 0, sizeof(BITMAPINFOHEADER));
|
|
bih.biWidth = width;
|
|
bih.biHeight = height;
|
|
bih.biBitCount = 24;
|
|
bih.biSize = sizeof(BITMAPINFOHEADER);
|
|
fwrite(&bih, sizeof(BITMAPINFOHEADER), 1, pFile);
|
|
unsigned char temp = 0;
|
|
for (int i = 0; i<width*height * 3; i += 3)
|
|
{
|
|
temp = imgData[i + 2];
|
|
imgData[i + 2] = imgData[i];
|
|
imgData[i] = temp;
|
|
}
|
|
fwrite(imgData, 1, width*height * 3, pFile);
|
|
fclose(pFile);
|
|
}
|
|
}
|
|
|
|
void CheckGLError(const char*file, int line)
|
|
{
|
|
|
|
GLenum error = glGetError();
|
|
if (error != GL_NO_ERROR)
|
|
{
|
|
switch (error)
|
|
{
|
|
case GL_INVALID_ENUM:
|
|
printf("GL Error GL_INVALID_ENUM %s : %d\n", file, line);
|
|
break;
|
|
case GL_INVALID_VALUE:
|
|
printf("GL Error GL_INVALID_VALUE %s : %d\n", file, line);
|
|
break;
|
|
case GL_INVALID_OPERATION:
|
|
printf("GL Error GL_INVALID_OPERATION %s : %d\n", file, line);
|
|
break;
|
|
case GL_STACK_OVERFLOW:
|
|
printf("GL Error GL_STACK_OVERFLOW %s : %d\n", file, line);
|
|
break;
|
|
case GL_STACK_UNDERFLOW:
|
|
printf("GL Error GL_STACK_UNDERFLOW %s : %d\n", file, line);
|
|
break;
|
|
case GL_OUT_OF_MEMORY:
|
|
printf("GL Error GL_OUT_OF_MEMORY %s : %d\n", file, line);
|
|
break;
|
|
default:
|
|
printf("GL Error 0x%x %s : %d\n", error, file, line);
|
|
break;
|
|
}
|
|
}
|
|
}
|