CSCI441 OpenGL Library 6.1.0.0
CS@Mines CSCI441 Computer Graphics Course Library
Loading...
Searching...
No Matches
TextureUtils.hpp
Go to the documentation of this file.
1
14#ifndef CSCI441_TEXTURE_UTILS_HPP
15#define CSCI441_TEXTURE_UTILS_HPP
16
17#include "constants.h"
18#include "LogUtils.hpp"
19
20#ifdef CSCI441_USE_GLEW
21 #include <GL/glew.h>
22#else
23 #include <glad/gl.h>
24#endif
25
26#ifdef CSCI441_TEXTURE_UTILS_IMPLEMENTATION
27# ifndef STB_IMAGE_WRITE_IMPLEMENTATION // guard against redefinition errors
28# define STB_IMAGE_IMPLEMENTATION
29# endif
30#endif
31#include <stb_image.h>
32
33#include <cstdio>
34#include <cstring>
35#include <string>
36
37//**********************************************************************************
38
39namespace CSCI441 {
40
45 namespace TextureUtils {
46
65 bool loadPPM( const char *filename, int &imageWidth, int &imageHeight, unsigned char* &imageData );
66
81 [[maybe_unused]] GLuint loadAndRegisterTexture( const char *filename,
82 GLint minFilter = GL_LINEAR,
83 GLint magFilter = GL_LINEAR,
84 GLint wrapS = GL_REPEAT,
85 GLint wrapT = GL_REPEAT,
86 GLboolean flipOnY = GL_TRUE,
87 GLboolean printAllMessages = GL_TRUE,
88 GLboolean enableMipmaps = GL_TRUE,
89 GLboolean enableAniso = GL_TRUE);
90
107 GLuint loadAndRegister2DTexture( const char *filename,
108 GLint minFilter = GL_LINEAR,
109 GLint magFilter = GL_LINEAR,
110 GLint wrapS = GL_REPEAT,
111 GLint wrapT = GL_REPEAT,
112 GLboolean flipOnY = GL_TRUE,
113 GLboolean printAllMessages = GL_TRUE,
114 GLboolean enableMipmaps = GL_TRUE,
115 GLboolean enableAniso = GL_TRUE);
116
123 [[maybe_unused]] void loadCubeMapFaceTexture(GLint cubeMapFace, const char* filename);
124 }
125}
126
127//**********************************************************************************
128// Outward facing function implementations
129
130inline bool CSCI441::TextureUtils::loadPPM( const char *filename, int &imageWidth, int &imageHeight, unsigned char* &imageData ) {
131 FILE *fp = fopen(filename, "r");
132 int temp, maxValue;
133 fscanf(fp, "P%d", &temp);
134 if(temp != 3) {
135 CSCI441::LogUtils::logError("[ERROR]: CSCI441::TextureUtils::loadPPM(): PPM file is not of correct format! (Must be P3, is P%d.)\n", temp);
136 fclose(fp);
137 return false;
138 }
139
140 //got the file header right...
141 fscanf(fp, "%d", &imageWidth);
142 fscanf(fp, "%d", &imageHeight);
143 fscanf(fp, "%d", &maxValue);
144
145 //now that we know how big it is, allocate the buffer...
146 imageData = new unsigned char[imageWidth*imageHeight*3];
147 if(!imageData) {
148 CSCI441::LogUtils::logError("[ERROR]: CSCI441::TextureUtils::loadPPM(): couldn't allocate image memory. Dimensions: %d x %d.\n", imageWidth, imageHeight);
149 fclose(fp);
150 return false;
151 }
152
153 //and read the data in.
154 for(int j = 0; j < imageHeight; j++) {
155 for(int i = 0; i < imageWidth; i++) {
156 int r, g, b;
157 fscanf(fp, "%d", &r);
158 fscanf(fp, "%d", &g);
159 fscanf(fp, "%d", &b);
160
161 imageData[(j*imageWidth+i)*3+0] = r;
162 imageData[(j*imageWidth+i)*3+1] = g;
163 imageData[(j*imageWidth+i)*3+2] = b;
164 }
165 }
166
167 fclose(fp);
168 return true;
169}
170
171[[maybe_unused]]
172inline GLuint CSCI441::TextureUtils::loadAndRegisterTexture( const char *filename, const GLint minFilter, const GLint magFilter, const GLint wrapS, const GLint wrapT, const GLboolean flipOnY, const GLboolean printAllMessages, const GLboolean enableMipmaps, const GLboolean enableAniso ) {
173 return loadAndRegister2DTexture( filename, minFilter, magFilter, wrapS, wrapT, flipOnY, printAllMessages, enableMipmaps, enableAniso );
174}
175
176inline GLuint CSCI441::TextureUtils::loadAndRegister2DTexture( const char *filename, const GLint minFilter, const GLint magFilter, const GLint wrapS, const GLint wrapT, const GLboolean flipOnY, const GLboolean printAllMessages, const GLboolean enableMipmaps, const GLboolean enableAniso ) {
177 int imageWidth, imageHeight, imageChannels;
178 GLuint texHandle = 0;
179 stbi_set_flip_vertically_on_load(flipOnY);
180 unsigned char *data = stbi_load( filename, &imageWidth, &imageHeight, &imageChannels, 0);
181
182 if( !data ) {
183 if( strstr(filename, ".ppm") != NULL ) {
184 loadPPM(filename, imageWidth, imageHeight, data);
185 imageChannels = 3;
186 }
187 if( !data ) {
188 if(printAllMessages) CSCI441::LogUtils::logError("[ERROR]: CSCI441::TextureUtils::loadAndRegister2DTexture(): Could not load texture \"%s\"\n", filename );
189 return texHandle;
190 }
191 }
192
193 glGenTextures(1, &texHandle );
194 glBindTexture( GL_TEXTURE_2D, texHandle );
195 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter );
196 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter );
197 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS );
198 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT );
199 const GLint STORAGE_TYPE = (imageChannels == 4 ? GL_RGBA : GL_RGB);
200 glTexImage2D( GL_TEXTURE_2D, 0, STORAGE_TYPE, imageWidth, imageHeight, 0, STORAGE_TYPE, GL_UNSIGNED_BYTE, data);
201
202 if(enableMipmaps) glGenerateMipmap(GL_TEXTURE_2D);
203
204 if(enableAniso) {
205 // anisotropic filtering became core in OpenGL 4.6, but was widely supported via extensions prior to then
206 GLint major = 0, minor = 0;
207 glGetIntegerv(GL_MAJOR_VERSION, &major);
208 glGetIntegerv(GL_MINOR_VERSION, &minor);
209 // check if anisotropic filtering is enabled
210 if( (major > 4 || (major == 4 && minor >= 6)) || GL_EXT_texture_filter_anisotropic ) {
211 GLfloat maxAniso = 1.0f;
212 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAniso);
213 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAniso);
214 }
215 }
216
217 CSCI441::LogUtils::log("[INFO]: Successfully loaded texture \"%s\" with handle %d\n", filename, texHandle );
218
219 return texHandle;
220}
221
222[[maybe_unused]]
223inline void CSCI441::TextureUtils::loadCubeMapFaceTexture(const GLint cubeMapFace, const char* FILENAME) {
224 int imageWidth, imageHeight, imageChannels;
225 unsigned char *data = stbi_load( FILENAME, &imageWidth, &imageHeight, &imageChannels, 0);
226
227 if( data ) {
228 const GLint STORAGE_TYPE = (imageChannels == 4 ? GL_RGBA : GL_RGB);
229 glTexImage2D(cubeMapFace, 0, STORAGE_TYPE, imageWidth, imageHeight, 0, STORAGE_TYPE, GL_UNSIGNED_BYTE, data);
230 stbi_image_free(data);
231 } else {
232 CSCI441::LogUtils::logError("[ERROR]: CSCI441::TextureUtils::loadCubeMapFaceTexture(): Could not load texture map \"%s\"\n", FILENAME );
233 }
234}
235
236#endif // CSCI441_TEXTURE_UTILS_HPP
void loadCubeMapFaceTexture(GLint cubeMapFace, const char *filename)
loads a texture into memory of a cube face
Definition: TextureUtils.hpp:223
bool loadPPM(const char *filename, int &imageWidth, int &imageHeight, unsigned char *&imageData)
loads a PPM into memory
Definition: TextureUtils.hpp:130
GLuint loadAndRegister2DTexture(const char *filename, GLint minFilter=GL_LINEAR, GLint magFilter=GL_LINEAR, GLint wrapS=GL_REPEAT, GLint wrapT=GL_REPEAT, GLboolean flipOnY=GL_TRUE, GLboolean printAllMessages=GL_TRUE, GLboolean enableMipmaps=GL_TRUE, GLboolean enableAniso=GL_TRUE)
loads and registers a texture into memory returning a texture handle
Definition: TextureUtils.hpp:176
GLuint loadAndRegisterTexture(const char *filename, GLint minFilter=GL_LINEAR, GLint magFilter=GL_LINEAR, GLint wrapS=GL_REPEAT, GLint wrapT=GL_REPEAT, GLboolean flipOnY=GL_TRUE, GLboolean printAllMessages=GL_TRUE, GLboolean enableMipmaps=GL_TRUE, GLboolean enableAniso=GL_TRUE)
loads and registers a texture into memory returning a texture handle
Definition: TextureUtils.hpp:172
void log(const char *MSG,...)
log a message to both the standard output stream and file
Definition: LogUtils.hpp:116
void logError(const char *MSG,...)
log a message to both the standard error stream and file
Definition: LogUtils.hpp:128
CSCI441 Helper Functions for OpenGL.
Definition: ArcballCam.hpp:17
OpenGL Texture Utility functions.