1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-02-26 00:13:09 +01:00
openlara/src/texture.h

115 lines
4.1 KiB
C
Raw Normal View History

2016-08-16 01:13:15 +03:00
#ifndef H_TEXTURE
#define H_TEXTURE
#include "core.h"
struct Texture {
2017-04-01 21:24:53 +03:00
enum Format : uint32 { LUMINANCE, RGBA, RGB16, RGBA16, RGBA_FLOAT, RGBA_HALF, DEPTH, DEPTH_STENCIL, SHADOW, MAX };
GLuint ID;
2016-08-29 11:06:13 +03:00
int width, height;
Format format;
bool cube;
2016-08-16 01:13:15 +03:00
2017-03-07 01:41:11 +03:00
Texture(int width, int height, Format format, bool cube, void *data = NULL, bool filter = true) : cube(cube) {
if (!Core::support.texNPOT) {
width = nextPow2(width);
height = nextPow2(height);
}
this->width = width;
this->height = height;
2016-08-29 11:06:13 +03:00
glGenTextures(1, &ID);
bind(0);
2016-08-16 01:13:15 +03:00
GLenum target = cube ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
bool isShadow = format == SHADOW;
if (format == SHADOW && !Core::support.shadowSampler) {
format = DEPTH;
filter = false;
}
if (format == DEPTH) {
if (Core::support.depthTexture)
filter = false;
else
format = RGBA;
}
if (format == RGBA_HALF) {
if (Core::support.texHalf)
2017-03-14 03:46:48 +03:00
filter = filter && Core::support.texHalfLinear;
else
format = RGBA_FLOAT;
}
if (format == RGBA_FLOAT) {
if (Core::support.texFloat)
2017-03-14 03:46:48 +03:00
filter = filter && Core::support.texFloatLinear;
else
format = RGBA;
}
this->format = format;
if (format == SHADOW) {
glTexParameteri(target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glTexParameteri(target, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
}
bool border = isShadow && Core::support.texBorder;
glTexParameteri(target, GL_TEXTURE_WRAP_S, border ? GL_CLAMP_TO_BORDER : GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_T, border ? GL_CLAMP_TO_BORDER : GL_CLAMP_TO_EDGE);
if (border) {
float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, color);
}
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter ? GL_LINEAR : GL_NEAREST);
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter ? GL_LINEAR : GL_NEAREST);
struct FormatDesc {
GLuint ifmt, fmt;
GLenum type;
} formats[MAX] = {
2017-03-14 03:46:48 +03:00
{ GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE }, // LUMINANCE
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE }, // RGBA
{ GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 }, // RGB16
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 }, // RGBA16
{ GL_RGBA32F, GL_RGBA, GL_FLOAT }, // RGBA_FLOAT
{ GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT }, // RGBA_HALF
{ GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT }, // DEPTH
2017-04-01 21:24:53 +03:00
{ GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 }, // DEPTH_STENCIL
{ GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT }, // SHADOW
};
FormatDesc &desc = formats[format];
for (int i = 0; i < 6; i++) {
glTexImage2D(cube ? (GL_TEXTURE_CUBE_MAP_POSITIVE_X + i) : GL_TEXTURE_2D, 0, desc.ifmt, width, height, 0, desc.fmt, desc.type, data);
if (!cube) break;
}
2016-08-29 11:06:13 +03:00
}
2016-08-16 01:13:15 +03:00
2016-08-29 11:06:13 +03:00
virtual ~Texture() {
glDeleteTextures(1, &ID);
}
2016-08-16 01:13:15 +03:00
2016-08-29 11:06:13 +03:00
void bind(int sampler) {
2017-03-14 03:46:48 +03:00
if (Core::active.textures[sampler] != this) {
Core::active.textures[sampler] = this;
glActiveTexture(GL_TEXTURE0 + sampler);
glBindTexture(cube ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, ID);
}
2016-08-29 11:06:13 +03:00
}
void unbind(int sampler) {
2017-03-14 03:46:48 +03:00
if (Core::active.textures[sampler]) {
Core::active.textures[sampler] = NULL;
glActiveTexture(GL_TEXTURE0 + sampler);
glBindTexture(cube ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, 0);
}
}
2016-08-16 01:13:15 +03:00
};
#endif