2023-03-05 18:14:43 +01:00
# ifndef TEXTURES_CPP
# define TEXTURES_CPP
# include <glad/glad.h>
# include <GLFW/glfw3.h>
# include "stb_image.h"
# include "textures.hpp"
void setTextureSCoordinate ( const GLenum textureTarget , const GLint sCoordinateOption , const float * borderColor )
{
// https://registry.khronos.org/OpenGL-Refpages/gl4/html/glTexParameter.xhtml
// first argument is texture target (by default we work with 2D textures so it will be GL_TEXTURE_2D)
// second argument is what option we want to set and for which texture axis (s, t or r)
// Third argument is texture wrapping mode
glTexParameteri ( textureTarget , GL_TEXTURE_WRAP_S , sCoordinateOption ) ;
if ( sCoordinateOption = = GL_CLAMP_TO_BORDER & & borderColor ! = NULL )
{
// if we use GL_CLAMP_TO_BORDER all of the space that is not occupied by texture will be occupied by color
// we pass the color we want to use in float array (RGB + transparency)
glTexParameterfv ( GL_TEXTURE_2D , GL_TEXTURE_BORDER_COLOR , borderColor ) ;
}
}
void setTextureTCoordinate ( const GLenum textureTarget , const GLint tCoordinateOption , const float * borderColor )
{
// for comments concerning glTexParameteri and glTexParameterfv go to setTextureSCoordinate function
if ( textureTarget = = GL_TEXTURE_2D | | textureTarget = = GL_TEXTURE_3D )
{
glTexParameteri ( textureTarget , GL_TEXTURE_WRAP_T , tCoordinateOption ) ;
if ( tCoordinateOption = = GL_CLAMP_TO_BORDER & & borderColor ! = NULL )
{
glTexParameterfv ( GL_TEXTURE_2D , GL_TEXTURE_BORDER_COLOR , borderColor ) ;
}
}
}
void setTextureRCoordinate ( const GLenum textureTarget , const GLint rCoordinateOption , const float * borderColor )
{
// for comments concerning glTexParameteri and glTexParameterfv go to setTextureSCoordinate function
if ( textureTarget = = GL_TEXTURE_3D )
{
glTexParameteri ( textureTarget , GL_TEXTURE_WRAP_R , rCoordinateOption ) ;
if ( rCoordinateOption = = GL_CLAMP_TO_BORDER & & borderColor ! = NULL )
{
glTexParameterfv ( GL_TEXTURE_2D , GL_TEXTURE_BORDER_COLOR , borderColor ) ;
}
}
}
// Coordinate options can be: GL_REPEAT, GL_MIRRORED_REPEAT, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER
// s t r are equivalent to x y z
void setTextureParametersINT ( const GLenum textureTarget , const GLint sCoordinateOption , const GLint tCoordinateOption , const GLint rCoordinateOption , const float * borderColor )
{
setTextureSCoordinate ( textureTarget , sCoordinateOption , borderColor ) ;
setTextureTCoordinate ( textureTarget , tCoordinateOption , borderColor ) ;
setTextureRCoordinate ( textureTarget , rCoordinateOption , borderColor ) ;
}
void setTextureFilteringAndMipMap ( const GLenum textureTarget , const GLenum filterType , const GLint textureFilteringMethod , const GLint mipMapFilteringMethod )
{
// mipMapFilteringMethod can be equal to: GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR
// NEAREST_MIPMAP - take nearest mipmap to match pixel size
// LINEAR_MIPMAP - interpolate between two mipmaps that match the size of a pixel
// NEAREST (at the end) - samples texture based on nearest neighbor interpolation
// LINEAR (at the end) - samples texture using linear interpolation
// setting anything else than GL_TEXTURE_MIN_FILTER as a second parameter results in GL_INVALID_ENUM error
glTexParameteri ( textureTarget , GL_TEXTURE_MIN_FILTER , mipMapFilteringMethod ) ;
// https://registry.khronos.org/OpenGL-Refpages/gl4/html/glTexParameter.xhtml
// first argument is texture target (by default we work with 2D textures so it will be GL_TEXTURE_2D)
// second argument is specifying whether this filter works for magnifying textures GL_TEXTURE_MAG_FILTER or minifying GL_TEXTURE_MIN_FILTER
// third argument is how we should magnify/minify textures, whether we should choose the color of pixel closest to the coordinates GL_NEAREST (default)
// or should we blend the neighboring pixels and choose blended color GL_LINEAR
glTexParameteri ( textureTarget , filterType , textureFilteringMethod ) ;
}
2023-03-05 20:02:41 +01:00
unsigned char * loadTexture ( const char * texturePath , int textureWidth , int textureHeight , int colorChannels )
{
// first argument is the location of an image
// second and third is its width and height
// fourth is number of color channels
unsigned char * data = stbi_load ( texturePath , & textureWidth , & textureHeight , & colorChannels , 0 ) ;
return data ;
}
2023-03-11 19:08:15 +01:00
unsigned int generateAndBindTexture ( const GLenum textureTarget , const GLsizei numberOfTextures ) {
2023-03-05 20:02:41 +01:00
unsigned int texture ;
// first argument is how many textures we want to generate
// second is an array of unsigned int in which we will store id of those textures
2023-03-11 19:08:15 +01:00
glGenTextures ( numberOfTextures , & texture ) ;
2023-03-05 20:02:41 +01:00
// then we bind texture
2023-03-11 19:08:15 +01:00
glBindTexture ( textureTarget , texture ) ;
return texture ;
}
unsigned int loadAndBindTextureFile ( unsigned int texture , const char * texturePath , const int textureWidth , const int textureHeight , const int colorChannels ) {
2023-03-05 20:02:41 +01:00
unsigned char * data = loadTexture ( texturePath , textureWidth , textureHeight , colorChannels ) ;
if ( data ) {
2023-03-11 19:08:15 +01:00
// generate texture
/*
first argument is texture target , setting it to GL_TEXTURE_2D will only affect 2 D targets and not 1 D or 3 D
2 nd is mipmap level for which to create texture , base level is 0
3 rd is in what format we want to store texture ( our image has only rgb values so rgb )
4 th and 5 th are the width and height of texture
6 th argument is always 0 ( legacy , its called border parameter )
7 th and 8 th are the format and datatype of source image , we store the image data as chars ( bytes ) so we pass that
9 th last argument is actual data of the texture
*/
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGB , textureWidth , textureHeight , 0 , GL_RGB , GL_UNSIGNED_BYTE , data ) ;
glGenerateMipmap ( GL_TEXTURE_2D ) ;
// after generating texture, lets free the memory from image
stbi_image_free ( data ) ;
return texture ;
2023-03-05 20:02:41 +01:00
}
else
{
std : : cout < < " Failed to load texture! " < < std : : endl ;
return - 1 ;
}
}
2023-03-05 18:14:43 +01:00
2023-03-11 19:08:15 +01:00
unsigned int generateTexture ( const char * texturePath , const int textureWidth , const int textureHeight , const int colorChannels ) {
unsigned int texture = generateAndBindTexture ( GL_TEXTURE_2D , 1 ) ;
texture = loadAndBindTextureFile ( texture , texturePath , textureWidth , textureHeight , colorChannels ) ;
}
// const char* texturePath, int textureWidth, int textureHeight, int colorChannels, const GLenum textureTarget, const GLint sCoordinateOption, const GLint tCoordinateOption, const GLint rCoordinateOption, const float* borderColor
unsigned int loadAndCreateTexture ( ) {
// load and create a texture
// -------------------------
unsigned int texture = generateAndBindTexture ( GL_TEXTURE_2D , 1 ) ;
setTextureParametersINT ( GL_TEXTURE_2D , GL_REPEAT , GL_REPEAT ) ;
// set texture filtering parameters
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
// load image, create texture and generate mipmaps
int width = 430 , height = 288 , nrChannels ;
texture = loadAndBindTextureFile ( texture , " assets/Preview.png " , width , height , nrChannels ) ;
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D , texture ) ;
}
2023-03-05 18:14:43 +01:00
# endif // TEXTURES_CPP