#include "misc.h" #include #include #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 settings) { GLuint vao; glGenVertexArrays(1, &vao); glBindVertexArray(vao); settings(); glBindVertexArray(0); return vao; } GLuint CreateFramebufferObject(GLuint & colorBuffer, GLuint & depthBuffer, int width, int height, GLuint *colorBuffer2) { GLuint fbo; glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); //colorbuffer glGenTextures(1, &colorBuffer); glBindTexture(GL_TEXTURE_2D, colorBuffer); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glBindTexture(GL_TEXTURE_2D, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0);//绑定刚才生成的texture到GL_COLOR_ATTACHMENT0 //colorbuffer2 if (colorBuffer2 != nullptr) { glGenTextures(1, colorBuffer2); glBindTexture(GL_TEXTURE_2D, *colorBuffer2); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glBindTexture(GL_TEXTURE_2D, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, *colorBuffer2, 0);//绑定刚才生成的texture到GL_COLOR_ATTACHMENT0 GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }; glDrawBuffers(2, buffers); } //depthbuffer glGenTextures(1, &depthBuffer); glBindTexture(GL_TEXTURE_2D, depthBuffer); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr); glBindTexture(GL_TEXTURE_2D, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthBuffer, 0); //check GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { printf("create framebuffer object fail\n"); } glBindFramebuffer(GL_FRAMEBUFFER, 0); return fbo; } 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