Shadow mapping
This commit is contained in:
2
Makefile
2
Makefile
@@ -1,5 +1,5 @@
|
||||
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
|
||||
LIBS=-lglbinding -lSDL2 -lSDL2_image -lobj
|
||||
CXXSRCS=main.cc objectParser.cc
|
||||
|
||||
12
Object.hh
12
Object.hh
@@ -10,23 +10,27 @@ class Object {
|
||||
public:
|
||||
Object(VBOManager& vboManager, std::vector<objVertexAttribs> const& vas, std::vector<uint16_t> const& indices,
|
||||
Program& prog)
|
||||
: _vboManager(vboManager), _prog(prog), _indices(indices) {
|
||||
: _vboManager(vboManager), _prog(prog), _indices(indices), _vaID(0) {
|
||||
construct(vas);
|
||||
}
|
||||
|
||||
Object(VBOManager& vboManager, std::string const& filename, Program& prog)
|
||||
: _vboManager(vboManager), _prog(prog) {
|
||||
: _vboManager(vboManager), _prog(prog), _vaID(0) {
|
||||
auto tmp = readObject(filename);
|
||||
_indices = std::get<1>(tmp);
|
||||
construct(std::get<0>(tmp));
|
||||
}
|
||||
|
||||
~Object() {
|
||||
glDeleteVertexArrays(1, &_vaID);
|
||||
}
|
||||
|
||||
void draw(glm::mat4 const& modelview) const {
|
||||
void draw(glm::mat4 const& modelview, Program *override = nullptr) const {
|
||||
glBindVertexArray(_vaID);
|
||||
_prog.use();
|
||||
if (override)
|
||||
override->use();
|
||||
else
|
||||
_prog.use();
|
||||
glUniformMatrix4fv(_prog.getUniformLocation("model_matrix"), 1, GL_FALSE,
|
||||
glm::value_ptr(modelview));
|
||||
glDrawElements(GL_TRIANGLES, _indices.size(), GL_UNSIGNED_SHORT, _indices.data());
|
||||
|
||||
110
main.cc
110
main.cc
@@ -63,8 +63,8 @@ int main(int argc, char *argv[])
|
||||
window = SDL_CreateWindow("SDL2 Test",
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
640,
|
||||
480,
|
||||
1680,
|
||||
1050,
|
||||
/*SDL_WINDOW_FULLSCREEN_DESKTOP |*/ SDL_WINDOW_OPENGL);
|
||||
|
||||
if (!window) {
|
||||
@@ -131,11 +131,35 @@ int main(int argc, char *argv[])
|
||||
std::printf("Warning: extension GL_EXT_texture_filter_anisotropic not supported\n");
|
||||
Texture2D redTex("textures/red.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")};
|
||||
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();
|
||||
glUniformMatrix4fv(prog.getUniformLocation("projection_matrix"), 1, GL_FALSE,
|
||||
glm::value_ptr(proj));
|
||||
@@ -143,6 +167,13 @@ int main(int argc, char *argv[])
|
||||
glm::value_ptr(view));
|
||||
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 pyramid(vboManager, "objects/pyramid.obj", prog);
|
||||
Object plane(vboManager, "objects/plane.obj", prog);
|
||||
@@ -165,18 +196,87 @@ 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);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
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::rotate(SDL_GetTicks()*0.001f, glm::vec3(1.0f, 0.0f, 0.0f)) *
|
||||
glm::translate(glm::vec3(-0.5f, -0.5f, 0.5f));
|
||||
cubeTex.bind();
|
||||
|
||||
// Shadow maps must be rendered before real drawing can begin
|
||||
glClientWaitSync(fence, SyncObjectMask(), 0xffffffffu);
|
||||
glDeleteSync(fence);
|
||||
|
||||
box.draw(model);
|
||||
whiteTex.bind();
|
||||
plane.draw(glm::translate(glm::vec3(2.0f, -2.5f, 0.0f))*
|
||||
glm::rotate(0.35f, glm::vec3(0.0f, 1.0f, 0.0f)));
|
||||
glm::rotate(0.35f, glm::vec3(0.0f, 1.0f, 0.0f)));
|
||||
redTex.bind();
|
||||
pyramid.draw(glm::translate(glm::vec3(-2.0f, 0.0f, 0.0f)));
|
||||
|
||||
|
||||
@@ -384,7 +384,7 @@ public:
|
||||
obj_parser.parse(filename);
|
||||
}
|
||||
|
||||
std::vector<objVertexAttribs> buildVA()
|
||||
std::vector<objVertexAttribs> buildVA() const
|
||||
{
|
||||
std::vector<objVertexAttribs> ret;
|
||||
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
|
||||
|
||||
const uint lights = 2u;
|
||||
|
||||
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 vec3 fragNorm;
|
||||
//in vec3 light0Vect;
|
||||
in vec3 light;
|
||||
in vec3 lightColors[lights];
|
||||
in vec3 lightVecs[lights];
|
||||
|
||||
out vec4 color;
|
||||
|
||||
const float bias = 0.00;
|
||||
|
||||
void main(void) {
|
||||
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;
|
||||
|
||||
out vec2 fragTC;
|
||||
out vec3 light;
|
||||
out vec3 lightColors[lights];
|
||||
out vec3 lightVecs[lights];
|
||||
|
||||
void main(void) {
|
||||
vec4 vertex_Pos = model_matrix * vec4(vertex, 1.0);
|
||||
@@ -28,12 +29,13 @@ void main(void) {
|
||||
fragTC = vertexTC;
|
||||
|
||||
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) {
|
||||
vec3 lightVec = lightPos[i]-vertex_Pos.xyz;
|
||||
lightVecs[i] = -lightVec;
|
||||
vec3 lightNorm = normalize(lightVec);
|
||||
float lightDist = length(lightVec);
|
||||
light += lightColor[i]*clamp(dot(vertexNorm_trans, lightNorm), 0.0, 1.0)*
|
||||
clamp(lightIntensity[i]/(lightDist*lightDist), 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);
|
||||
}
|
||||
}
|
||||
|
||||
82
texture.hh
82
texture.hh
@@ -22,6 +22,88 @@ static unsigned ilog2(unsigned in)
|
||||
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 {
|
||||
public:
|
||||
Texture2D(unsigned width, unsigned height) {
|
||||
|
||||
Reference in New Issue
Block a user