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 };
|
2017-01-07 01:32:13 +03:00
|
|
|
|
|
|
|
GLuint ID;
|
2016-08-29 11:06:13 +03:00
|
|
|
int width, height;
|
2017-01-07 01:32:13 +03:00
|
|
|
Format format;
|
2016-12-22 03:37:49 +03:00
|
|
|
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
|
|
|
|
2016-12-22 03:37:49 +03:00
|
|
|
GLenum target = cube ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
|
2017-04-23 00:12:30 +03:00
|
|
|
bool isShadow = format == SHADOW;
|
2016-12-22 03:37:49 +03:00
|
|
|
|
2017-01-07 01:32:13 +03:00
|
|
|
if (format == SHADOW && !Core::support.shadowSampler) {
|
|
|
|
format = DEPTH;
|
|
|
|
filter = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (format == DEPTH) {
|
|
|
|
if (Core::support.depthTexture)
|
2016-12-22 03:37:49 +03:00
|
|
|
filter = false;
|
2017-01-07 01:32:13 +03:00
|
|
|
else
|
|
|
|
format = RGBA;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (format == RGBA_HALF) {
|
|
|
|
if (Core::support.texHalf)
|
2017-03-14 03:46:48 +03:00
|
|
|
filter = filter && Core::support.texHalfLinear;
|
2017-01-07 01:32:13 +03:00
|
|
|
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;
|
2017-01-07 01:32:13 +03:00
|
|
|
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);
|
|
|
|
}
|
2016-12-07 03:37:40 +03:00
|
|
|
|
2017-04-23 04:49:12 +03:00
|
|
|
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) {
|
2017-04-23 00:12:30 +03:00
|
|
|
float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
|
|
|
glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, color);
|
|
|
|
}
|
2016-12-22 03:37:49 +03:00
|
|
|
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter ? GL_LINEAR : GL_NEAREST);
|
|
|
|
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter ? GL_LINEAR : GL_NEAREST);
|
2017-01-07 01:32:13 +03:00
|
|
|
|
|
|
|
struct FormatDesc {
|
|
|
|
GLuint ifmt, fmt;
|
|
|
|
GLenum type;
|
2017-02-06 04:37:56 +03:00
|
|
|
} formats[MAX] = {
|
2017-03-14 03:46:48 +03:00
|
|
|
{ GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE }, // LUMINANCE
|
2017-02-06 04:37:56 +03:00
|
|
|
{ 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
|
2017-02-06 04:37:56 +03:00
|
|
|
{ GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT }, // SHADOW
|
2017-01-07 01:32:13 +03:00
|
|
|
};
|
2016-12-07 03:37:40 +03:00
|
|
|
|
2017-01-07 01:32:13 +03:00
|
|
|
FormatDesc &desc = formats[format];
|
|
|
|
|
2016-12-22 03:37:49 +03:00
|
|
|
for (int i = 0; i < 6; i++) {
|
2017-01-07 01:32:13 +03:00
|
|
|
glTexImage2D(cube ? (GL_TEXTURE_CUBE_MAP_POSITIVE_X + i) : GL_TEXTURE_2D, 0, desc.ifmt, width, height, 0, desc.fmt, desc.type, data);
|
2016-12-22 03:37:49 +03:00
|
|
|
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
|
|
|
}
|
2016-12-07 03:37:40 +03:00
|
|
|
|
2016-12-22 03:37:49 +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-12-07 03:37:40 +03:00
|
|
|
}
|
2016-08-16 01:13:15 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|