engineer-thesis-WUT/Engine/engine/textures.cpp

118 lines
5.9 KiB
C++
Raw Normal View History

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;
}
unsigned int generateTexture(const char* texturePath, const int textureWidth, const int textureHeight, const int colorChannels) {
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
glGenTextures(1, &texture);
// then we bind texture
glBindTexture(GL_TEXTURE_2D, texture);
unsigned char *data = loadTexture(texturePath, textureWidth, textureHeight, colorChannels);
if(data) {
// generate texture
/*
first argument is texture target, setting it to GL_TEXTURE_2D will only affect 2D targets and not 1D or 3D
2nd is mipmap level for which to create texture, base level is 0
3rd is in what format we want to store texture (our image has only rgb values so rgb)
4th and 5th are the width and height of texture
6th argument is always 0 (legacy, its called border parameter)
7th and 8th are the format and datatype of source image, we store the image data as chars (bytes) so we pass that
9th 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;
}
else
{
std::cout << "Failed to load texture! " << std::endl;
return -1;
}
}
2023-03-05 18:14:43 +01:00
#endif // TEXTURES_CPP