Shadow mapping
This commit is contained in:
2
Makefile
2
Makefile
@@ -1,5 +1,5 @@
|
|||||||
CXX=g++
|
CXX=g++
|
||||||
CXXOPTS=-Og -ggdb -Wall -Wextra -pedantic -Wno-unused-function -Wno-unused-parameter -std=c++11
|
CXXOPTS=-Og -ggdb -Wall -Wextra -pedantic -Wno-unused-function -Wno-unused-parameter -Wno-sign-compare -std=c++11
|
||||||
LDOPTS=-flto
|
LDOPTS=-flto
|
||||||
LIBS=-lglbinding -lSDL2 -lSDL2_image -lobj
|
LIBS=-lglbinding -lSDL2 -lSDL2_image -lobj
|
||||||
CXXSRCS=main.cc objectParser.cc
|
CXXSRCS=main.cc objectParser.cc
|
||||||
|
|||||||
10
Object.hh
10
Object.hh
@@ -10,22 +10,26 @@ class Object {
|
|||||||
public:
|
public:
|
||||||
Object(VBOManager& vboManager, std::vector<objVertexAttribs> const& vas, std::vector<uint16_t> const& indices,
|
Object(VBOManager& vboManager, std::vector<objVertexAttribs> const& vas, std::vector<uint16_t> const& indices,
|
||||||
Program& prog)
|
Program& prog)
|
||||||
: _vboManager(vboManager), _prog(prog), _indices(indices) {
|
: _vboManager(vboManager), _prog(prog), _indices(indices), _vaID(0) {
|
||||||
construct(vas);
|
construct(vas);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object(VBOManager& vboManager, std::string const& filename, Program& prog)
|
Object(VBOManager& vboManager, std::string const& filename, Program& prog)
|
||||||
: _vboManager(vboManager), _prog(prog) {
|
: _vboManager(vboManager), _prog(prog), _vaID(0) {
|
||||||
auto tmp = readObject(filename);
|
auto tmp = readObject(filename);
|
||||||
_indices = std::get<1>(tmp);
|
_indices = std::get<1>(tmp);
|
||||||
construct(std::get<0>(tmp));
|
construct(std::get<0>(tmp));
|
||||||
}
|
}
|
||||||
|
|
||||||
~Object() {
|
~Object() {
|
||||||
|
glDeleteVertexArrays(1, &_vaID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(glm::mat4 const& modelview) const {
|
void draw(glm::mat4 const& modelview, Program *override = nullptr) const {
|
||||||
glBindVertexArray(_vaID);
|
glBindVertexArray(_vaID);
|
||||||
|
if (override)
|
||||||
|
override->use();
|
||||||
|
else
|
||||||
_prog.use();
|
_prog.use();
|
||||||
glUniformMatrix4fv(_prog.getUniformLocation("model_matrix"), 1, GL_FALSE,
|
glUniformMatrix4fv(_prog.getUniformLocation("model_matrix"), 1, GL_FALSE,
|
||||||
glm::value_ptr(modelview));
|
glm::value_ptr(modelview));
|
||||||
|
|||||||
106
main.cc
106
main.cc
@@ -63,8 +63,8 @@ int main(int argc, char *argv[])
|
|||||||
window = SDL_CreateWindow("SDL2 Test",
|
window = SDL_CreateWindow("SDL2 Test",
|
||||||
SDL_WINDOWPOS_UNDEFINED,
|
SDL_WINDOWPOS_UNDEFINED,
|
||||||
SDL_WINDOWPOS_UNDEFINED,
|
SDL_WINDOWPOS_UNDEFINED,
|
||||||
640,
|
1680,
|
||||||
480,
|
1050,
|
||||||
/*SDL_WINDOW_FULLSCREEN_DESKTOP |*/ SDL_WINDOW_OPENGL);
|
/*SDL_WINDOW_FULLSCREEN_DESKTOP |*/ SDL_WINDOW_OPENGL);
|
||||||
|
|
||||||
if (!window) {
|
if (!window) {
|
||||||
@@ -132,9 +132,33 @@ int main(int argc, char *argv[])
|
|||||||
Texture2D redTex("textures/red.png");
|
Texture2D redTex("textures/red.png");
|
||||||
Texture2D whiteTex("textures/white.png");
|
Texture2D whiteTex("textures/white.png");
|
||||||
|
|
||||||
|
const unsigned lights = 2;
|
||||||
|
const unsigned shadowMapSize = 512;
|
||||||
|
glm::mat4 shadowProj = glm::perspectiveFov(90.0f, static_cast<float>(shadowMapSize),
|
||||||
|
static_cast<float>(shadowMapSize), 1.0f, 128.0f);
|
||||||
|
std::vector<TextureCubeMap> shadowMaps;
|
||||||
|
for(unsigned i = 0;i < lights;++i) {
|
||||||
|
shadowMaps.emplace_back(shadowMapSize);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_FUNC, static_cast<GLint>(GL_LESS));
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, static_cast<GLint>(GL_COMPARE_REF_TO_TEXTURE));
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::vec3 lightPos[lights] = {glm::vec3(2.0, -2.0, 10.0),
|
||||||
|
glm::vec3(2.0, 2.0, 10.0)};
|
||||||
|
// const glm::vec3 lightColor[lights] = {glm::vec3(1.0, 0.9, 0.8),
|
||||||
|
// glm::vec3(0.0, 1.0, 0.0)};
|
||||||
|
// const float lightIntensity[lights] = {75.0f, 25.0f};
|
||||||
|
|
||||||
|
|
||||||
|
Framebuffer shadowFB;
|
||||||
|
|
||||||
VertexShader vs{fileToString("shaders/textured.vs")};
|
VertexShader vs{fileToString("shaders/textured.vs")};
|
||||||
FragmentShader fs{fileToString("shaders/textured.fs")};
|
FragmentShader fs{fileToString("shaders/textured.fs")};
|
||||||
Program prog(vs, fs);
|
Program prog{vs, fs};
|
||||||
|
|
||||||
|
VertexShader shadowVs{fileToString("shaders/shadow.vs")};
|
||||||
|
FragmentShader shadowFs{fileToString("shaders/shadow.fs")};
|
||||||
|
Program shadowProg{shadowVs, shadowFs};
|
||||||
|
|
||||||
prog.use();
|
prog.use();
|
||||||
glUniformMatrix4fv(prog.getUniformLocation("projection_matrix"), 1, GL_FALSE,
|
glUniformMatrix4fv(prog.getUniformLocation("projection_matrix"), 1, GL_FALSE,
|
||||||
@@ -143,6 +167,13 @@ int main(int argc, char *argv[])
|
|||||||
glm::value_ptr(view));
|
glm::value_ptr(view));
|
||||||
glUniform1i(prog.getUniformLocation("texBase"), 0);
|
glUniform1i(prog.getUniformLocation("texBase"), 0);
|
||||||
|
|
||||||
|
const GLint shadowMapTUs[] = {1, 2};
|
||||||
|
glUniform1iv(prog.getUniformLocation("texShadowMaps"), 2, shadowMapTUs);
|
||||||
|
|
||||||
|
shadowProg.use();
|
||||||
|
glUniformMatrix4fv(prog.getUniformLocation("projection_matrix"), 1, GL_FALSE,
|
||||||
|
glm::value_ptr(shadowProj));
|
||||||
|
|
||||||
Object box(vboManager, "objects/woodbox.obj", prog);
|
Object box(vboManager, "objects/woodbox.obj", prog);
|
||||||
Object pyramid(vboManager, "objects/pyramid.obj", prog);
|
Object pyramid(vboManager, "objects/pyramid.obj", prog);
|
||||||
Object plane(vboManager, "objects/plane.obj", prog);
|
Object plane(vboManager, "objects/plane.obj", prog);
|
||||||
@@ -165,14 +196,83 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw shadow maps
|
||||||
|
GLint origVP[4];
|
||||||
|
glGetIntegerv(GL_VIEWPORT, origVP);
|
||||||
|
glViewport(0, 0, shadowMapSize, shadowMapSize);
|
||||||
|
shadowProg.use();
|
||||||
|
shadowFB.bind();
|
||||||
|
glPolygonOffset(1.1f, 4.0f);
|
||||||
|
glEnable(GL_POLYGON_OFFSET_FILL);
|
||||||
|
glEnable(GL_POLYGON_OFFSET_LINE);
|
||||||
|
glEnable(GL_POLYGON_OFFSET_POINT);
|
||||||
|
for (unsigned light = 0;light < lights;++light) {
|
||||||
|
for (unsigned i = 0;i < 6;++i) {
|
||||||
|
GLenum const face[6] = {GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
|
||||||
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
||||||
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z};
|
||||||
|
|
||||||
|
const glm::vec3 dir[6] = {glm::vec3(1.0f, 0.0f, 0.0f),
|
||||||
|
glm::vec3(-1.0f, 0.0f, 0.0f),
|
||||||
|
glm::vec3(0.0f, 1.0f, 0.0f),
|
||||||
|
glm::vec3(0.0f, -1.0f, 0.0f),
|
||||||
|
glm::vec3(0.0f, 0.0f, 1.0f),
|
||||||
|
glm::vec3(0.0f, 0.0f, -1.0f)};
|
||||||
|
const glm::vec3 up[6] = {glm::vec3(0.0f, 1.0f, 0.0f),
|
||||||
|
glm::vec3(0.0f, -1.0f, 0.0f),
|
||||||
|
glm::vec3(1.0f, 0.0f, 0.0f),
|
||||||
|
glm::vec3(-1.0f, 0.0f, 0.0f),
|
||||||
|
glm::vec3(0.0f, 1.0f, 0.0f),
|
||||||
|
glm::vec3(0.0f, -1.0f, 0.0f)};
|
||||||
|
|
||||||
|
shadowMaps[light].bind();
|
||||||
|
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
|
||||||
|
face[i], shadowMaps[light].getID(), 0);
|
||||||
|
glClear(GL_DEPTH_BUFFER_BIT);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
glm::mat4 view = glm::lookAt(lightPos[light],
|
||||||
|
lightPos[light]+dir[i],
|
||||||
|
up[i]);
|
||||||
|
glUniformMatrix4fv(prog.getUniformLocation("view_matrix"), 1, GL_FALSE,
|
||||||
|
glm::value_ptr(view));
|
||||||
|
|
||||||
|
glm::mat4 model = glm::translate(glm::vec3(0.5f, 0.5f, -0.5f)) *
|
||||||
|
glm::rotate(SDL_GetTicks()*0.001f, glm::vec3(1.0f, 0.0f, 0.0f)) *
|
||||||
|
glm::translate(glm::vec3(-0.5f, -0.5f, 0.5f));
|
||||||
|
box.draw(model, &shadowProg);
|
||||||
|
plane.draw(glm::translate(glm::vec3(2.0f, -2.5f, 0.0f))*
|
||||||
|
glm::rotate(0.35f, glm::vec3(0.0f, 1.0f, 0.0f)), &shadowProg);
|
||||||
|
pyramid.draw(glm::translate(glm::vec3(-2.0f, 0.0f, 0.0f)), &shadowProg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLsync fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, UnusedMask());
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
|
glViewport(origVP[0], origVP[1], origVP[2], origVP[3]);
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glEnable(GL_CULL_FACE);
|
glEnable(GL_CULL_FACE);
|
||||||
|
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||||
|
glDisable(GL_POLYGON_OFFSET_LINE);
|
||||||
|
glDisable(GL_POLYGON_OFFSET_POINT);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE2);
|
||||||
|
shadowMaps[1].bind();
|
||||||
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
shadowMaps[0].bind();
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
glm::mat4 model = glm::translate(glm::vec3(0.5f, 0.5f, -0.5f)) *
|
glm::mat4 model = glm::translate(glm::vec3(0.5f, 0.5f, -0.5f)) *
|
||||||
glm::rotate(SDL_GetTicks()*0.001f, glm::vec3(1.0f, 0.0f, 0.0f)) *
|
glm::rotate(SDL_GetTicks()*0.001f, glm::vec3(1.0f, 0.0f, 0.0f)) *
|
||||||
glm::translate(glm::vec3(-0.5f, -0.5f, 0.5f));
|
glm::translate(glm::vec3(-0.5f, -0.5f, 0.5f));
|
||||||
cubeTex.bind();
|
cubeTex.bind();
|
||||||
|
|
||||||
|
// Shadow maps must be rendered before real drawing can begin
|
||||||
|
glClientWaitSync(fence, SyncObjectMask(), 0xffffffffu);
|
||||||
|
glDeleteSync(fence);
|
||||||
|
|
||||||
box.draw(model);
|
box.draw(model);
|
||||||
whiteTex.bind();
|
whiteTex.bind();
|
||||||
plane.draw(glm::translate(glm::vec3(2.0f, -2.5f, 0.0f))*
|
plane.draw(glm::translate(glm::vec3(2.0f, -2.5f, 0.0f))*
|
||||||
|
|||||||
@@ -384,7 +384,7 @@ public:
|
|||||||
obj_parser.parse(filename);
|
obj_parser.parse(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<objVertexAttribs> buildVA()
|
std::vector<objVertexAttribs> buildVA() const
|
||||||
{
|
{
|
||||||
std::vector<objVertexAttribs> ret;
|
std::vector<objVertexAttribs> ret;
|
||||||
for (auto const& ent : _vertex_tc_norm) {
|
for (auto const& ent : _vertex_tc_norm) {
|
||||||
|
|||||||
5
shaders/shadow.fs
Normal file
5
shaders/shadow.fs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
// Only standard depth calc.
|
||||||
|
}
|
||||||
12
shaders/shadow.vs
Normal file
12
shaders/shadow.vs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#version 330 core
|
||||||
|
#extension GL_ARB_shading_language_420pack : enable
|
||||||
|
|
||||||
|
uniform mat4 projection_matrix;
|
||||||
|
uniform mat4 view_matrix;
|
||||||
|
uniform mat4 model_matrix;
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 vertex;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
gl_Position = projection_matrix * view_matrix * model_matrix * vec4(vertex, 1.0);
|
||||||
|
}
|
||||||
@@ -1,16 +1,52 @@
|
|||||||
#version 330 core
|
#version 330 core
|
||||||
|
|
||||||
|
const uint lights = 2u;
|
||||||
|
|
||||||
uniform sampler2D texBase;
|
uniform sampler2D texBase;
|
||||||
|
uniform samplerCubeShadow texShadowMaps[lights];
|
||||||
|
|
||||||
|
float VectorToDepth (vec3 Vec)
|
||||||
|
{
|
||||||
|
vec3 AbsVec = abs(Vec);
|
||||||
|
float LocalZcomp = max(AbsVec.x, max(AbsVec.y, AbsVec.z));
|
||||||
|
|
||||||
|
// Replace f and n with the far and near plane values you used when
|
||||||
|
// you drew your cube map.
|
||||||
|
const float f = 128.0;
|
||||||
|
const float n = 1.0;
|
||||||
|
|
||||||
|
float NormZComp = (f+n) / (f-n) - (2*f*n)/(f-n)/LocalZcomp;
|
||||||
|
return (NormZComp + 1.0) * 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
in vec2 fragTC;
|
in vec2 fragTC;
|
||||||
//in vec3 fragNorm;
|
//in vec3 fragNorm;
|
||||||
//in vec3 light0Vect;
|
//in vec3 light0Vect;
|
||||||
in vec3 light;
|
in vec3 lightColors[lights];
|
||||||
|
in vec3 lightVecs[lights];
|
||||||
|
|
||||||
out vec4 color;
|
out vec4 color;
|
||||||
|
|
||||||
|
const float bias = 0.00;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
vec4 texColor = texture(texBase, fragTC);
|
vec4 texColor = texture(texBase, fragTC);
|
||||||
|
|
||||||
color = texColor*vec4(light, 1.0)+texColor*0.05;
|
vec4 col = vec4(0.0, 0.0, 0.0, 0.0);
|
||||||
|
{
|
||||||
|
float depth = VectorToDepth(lightVecs[0])-bias;
|
||||||
|
vec3 nlv = normalize(lightVecs[0]);
|
||||||
|
float depth_compare = texture(texShadowMaps[0], vec4(nlv, depth));
|
||||||
|
// color = vec4(depth_compare, 0.0, 0.0, 1.0);
|
||||||
|
col += texColor*vec4(lightColors[0], 1.0)*depth_compare;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
float depth = VectorToDepth(lightVecs[1])-bias;
|
||||||
|
vec3 nlv = normalize(lightVecs[1]);
|
||||||
|
float depth_compare = texture(texShadowMaps[1], vec4(nlv, depth));
|
||||||
|
// color = vec4(depth_compare, 0.0, 0.0, 1.0);
|
||||||
|
col += texColor*vec4(lightColors[1], 1.0)*depth_compare;
|
||||||
|
}
|
||||||
|
color = col+texColor*0.05;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ layout(location = 1) in vec2 vertexTC;
|
|||||||
layout(location = 2) in vec3 vertexNorm;
|
layout(location = 2) in vec3 vertexNorm;
|
||||||
|
|
||||||
out vec2 fragTC;
|
out vec2 fragTC;
|
||||||
out vec3 light;
|
out vec3 lightColors[lights];
|
||||||
|
out vec3 lightVecs[lights];
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
vec4 vertex_Pos = model_matrix * vec4(vertex, 1.0);
|
vec4 vertex_Pos = model_matrix * vec4(vertex, 1.0);
|
||||||
@@ -28,12 +29,13 @@ void main(void) {
|
|||||||
fragTC = vertexTC;
|
fragTC = vertexTC;
|
||||||
|
|
||||||
vec3 vertexNorm_trans = (model_matrix*vec4(vertexNorm, 0.0)).xyz;
|
vec3 vertexNorm_trans = (model_matrix*vec4(vertexNorm, 0.0)).xyz;
|
||||||
light = vec3(0.0, 0.0, 0.0);
|
|
||||||
for (uint i = 0u;i < lights;++i) {
|
for (uint i = 0u;i < lights;++i) {
|
||||||
vec3 lightVec = lightPos[i]-vertex_Pos.xyz;
|
vec3 lightVec = lightPos[i]-vertex_Pos.xyz;
|
||||||
|
lightVecs[i] = -lightVec;
|
||||||
vec3 lightNorm = normalize(lightVec);
|
vec3 lightNorm = normalize(lightVec);
|
||||||
float lightDist = length(lightVec);
|
float lightDist = length(lightVec);
|
||||||
light += lightColor[i]*clamp(dot(vertexNorm_trans, lightNorm), 0.0, 1.0)*
|
lightColors[i] = lightColor[i]*clamp(dot(vertexNorm_trans, lightNorm), 0.0, 1.0)*
|
||||||
clamp(lightIntensity[i]/(lightDist*lightDist), 0.0, 1.0);
|
clamp(lightIntensity[i]/(lightDist*lightDist), 0.0, 1.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
82
texture.hh
82
texture.hh
@@ -22,6 +22,88 @@ static unsigned ilog2(unsigned in)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Framebuffer {
|
||||||
|
public:
|
||||||
|
Framebuffer() {
|
||||||
|
glGenFramebuffers(1, &_fbID);
|
||||||
|
}
|
||||||
|
|
||||||
|
~Framebuffer() {
|
||||||
|
glDeleteFramebuffers(1, &_fbID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind() const {
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbID);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint getID() const {
|
||||||
|
return _fbID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void attachTexture(GLenum textarget, GLuint texID) {
|
||||||
|
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
|
||||||
|
textarget, texID, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GLuint _fbID;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TextureCubeMap {
|
||||||
|
public:
|
||||||
|
TextureCubeMap(unsigned size) {
|
||||||
|
glGenTextures(1, &_texID);
|
||||||
|
glBindTexture(GL_TEXTURE_CUBE_MAP, _texID);
|
||||||
|
|
||||||
|
if(SDL_GL_ExtensionSupported("GL_ARB_texture_storage"))
|
||||||
|
glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_DEPTH_COMPONENT24,
|
||||||
|
size, size);
|
||||||
|
else {
|
||||||
|
std::printf("Warning: extension GL_ARB_texture_storage not supported!\n");
|
||||||
|
for (unsigned i = 0;i < 6;++i) {
|
||||||
|
GLenum const face[6] = {GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
|
||||||
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
||||||
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z};
|
||||||
|
glTexImage2D(face[i], 0, static_cast<GLint>(GL_DEPTH_COMPONENT16), size, size, 0,
|
||||||
|
GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, static_cast<GLint>(GL_LINEAR));
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, static_cast<GLint>(GL_LINEAR));
|
||||||
|
}
|
||||||
|
|
||||||
|
~TextureCubeMap() {
|
||||||
|
glDeleteTextures(1, &_texID);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureCubeMap(TextureCubeMap const& copy) = delete;
|
||||||
|
TextureCubeMap& operator=(TextureCubeMap const& copy) = delete;
|
||||||
|
|
||||||
|
TextureCubeMap(TextureCubeMap && move) : _texID(move._texID) {
|
||||||
|
move._texID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureCubeMap& operator=(TextureCubeMap && move) {
|
||||||
|
glDeleteTextures(1, &_texID);
|
||||||
|
_texID = move._texID;
|
||||||
|
move._texID = 0;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind() const {
|
||||||
|
glBindTexture(GL_TEXTURE_CUBE_MAP, _texID);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint getID() const {
|
||||||
|
return _texID;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GLuint _texID;
|
||||||
|
};
|
||||||
|
|
||||||
class Texture2D {
|
class Texture2D {
|
||||||
public:
|
public:
|
||||||
Texture2D(unsigned width, unsigned height) {
|
Texture2D(unsigned width, unsigned height) {
|
||||||
|
|||||||
Reference in New Issue
Block a user