enhanced Texture and FrameBuffer class to prepare incoming features on shadowmaps
This commit is contained in:
parent
cbefe4f86e
commit
1acf555854
22
shaders/gbuffer.geom.glsl
Normal file
22
shaders/gbuffer.geom.glsl
Normal file
@ -0,0 +1,22 @@
|
||||
#version 330 core
|
||||
|
||||
layout(triangles) in;
|
||||
layout(triangle_strip, max_vertices = 18) out;
|
||||
|
||||
uniform mat4 view[6];
|
||||
uniform mat4 proj;
|
||||
|
||||
// debug parameter
|
||||
flat out int fcolor_idx;
|
||||
|
||||
void main(void){
|
||||
for (int layerId = 0; layerId < 6; ++layerId){
|
||||
for (int i = 0; i < gl_in.length(); ++i){
|
||||
gl_Layer = layerId;
|
||||
fcolor_idx = layerId;
|
||||
gl_Position = proj * view[layerId] * gl_in[i].gl_Position;
|
||||
EmitVertex();
|
||||
}
|
||||
EndPrimitive();
|
||||
}
|
||||
}
|
@ -30,6 +30,6 @@ GBuffer::GBuffer(int width, int height) : FrameBuffer()
|
||||
|
||||
GBuffer::~GBuffer()
|
||||
{
|
||||
for(Texture* t : textures)
|
||||
for(Texture* t : m_textures)
|
||||
delete(t);
|
||||
}
|
||||
|
@ -6,16 +6,17 @@
|
||||
const FrameBuffer* FrameBuffer::screen = new FrameBuffer(0);
|
||||
|
||||
FrameBuffer::FrameBuffer() :
|
||||
allocated(true)
|
||||
allocated(true),
|
||||
m_target(GL_FRAMEBUFFER)
|
||||
{
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glGenFramebuffers(1, &m_frameBufferId);
|
||||
}
|
||||
|
||||
FrameBuffer::~FrameBuffer()
|
||||
{
|
||||
if(allocated)
|
||||
glDeleteFramebuffers(1, &fbo);
|
||||
for(Texture* t : textures)
|
||||
glDeleteFramebuffers(1, &m_frameBufferId);
|
||||
for(Texture* t : m_textures)
|
||||
{
|
||||
t->unbind();
|
||||
delete(t);
|
||||
@ -24,48 +25,45 @@ FrameBuffer::~FrameBuffer()
|
||||
|
||||
void FrameBuffer::addTexture(Texture* tex, GLenum attachment)
|
||||
{
|
||||
if(fbo != 0)
|
||||
if(m_frameBufferId != 0)
|
||||
{
|
||||
textures.push_back(tex);
|
||||
m_textures.push_back(tex);
|
||||
bindFBO();
|
||||
if(tex->isCubeMap())
|
||||
{
|
||||
// TODO
|
||||
// http://cg.siomax.ru/index.php/computer-graphics/10-one-pass-rendering-to-cube-map
|
||||
}
|
||||
glFramebufferTexture(m_target, attachment, tex->getId(), 0);
|
||||
else
|
||||
{
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, tex->getTarget(), tex->getId(), 0);
|
||||
if(attachment != GL_DEPTH_ATTACHMENT) // TODO stencil attachment must be tested too
|
||||
attachments.push_back(attachment);
|
||||
}
|
||||
|
||||
if((attachment != GL_DEPTH_ATTACHMENT && attachment != GL_STENCIL_ATTACHMENT) && attachment != GL_DEPTH_STENCIL_ATTACHMENT)
|
||||
m_attachments.push_back(attachment);
|
||||
}
|
||||
}
|
||||
|
||||
void FrameBuffer::initColorAttachments()
|
||||
{
|
||||
if(fbo != 0 && attachments.size() != 0)
|
||||
if(m_frameBufferId != 0 && m_attachments.size() != 0)
|
||||
{
|
||||
bindFBO();
|
||||
glDrawBuffers(attachments.size(), attachments.data());
|
||||
glDrawBuffers(m_attachments.size(), m_attachments.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
glDrawBuffer(GL_NONE);
|
||||
glReadBuffer(GL_NONE);
|
||||
}
|
||||
check();
|
||||
}
|
||||
|
||||
void FrameBuffer::deleteTextures()
|
||||
{
|
||||
for(Texture* t : textures)
|
||||
for(Texture* t : m_textures)
|
||||
delete(t);
|
||||
textures.clear();
|
||||
m_textures.clear();
|
||||
glDrawBuffer(GL_NONE);
|
||||
}
|
||||
|
||||
void FrameBuffer::bindFBO(GLenum target) const
|
||||
void FrameBuffer::bindFBO() const
|
||||
{
|
||||
glBindFramebuffer(target, fbo);
|
||||
glBindFramebuffer(m_target, m_frameBufferId);
|
||||
}
|
||||
|
||||
bool FrameBuffer::check()
|
||||
@ -100,8 +98,8 @@ bool FrameBuffer::check()
|
||||
|
||||
Texture* FrameBuffer::getTexture(int texId)
|
||||
{
|
||||
if(fbo != 0)
|
||||
return textures[texId];
|
||||
if(m_frameBufferId != 0)
|
||||
return m_textures[texId];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
@ -15,9 +15,10 @@ protected:
|
||||
bool check();
|
||||
|
||||
const bool allocated;
|
||||
GLuint fbo;
|
||||
std::vector<Texture*> textures;
|
||||
std::vector<GLuint> attachments;
|
||||
GLenum m_target;
|
||||
GLuint m_frameBufferId;
|
||||
std::vector<Texture*> m_textures;
|
||||
std::vector<GLuint> m_attachments;
|
||||
|
||||
public:
|
||||
/**
|
||||
@ -30,7 +31,7 @@ public:
|
||||
/**
|
||||
* @brief this constructor is only used to get a handle on an existing Framebuffer created by another library
|
||||
*/
|
||||
FrameBuffer(GLuint id) : allocated(false), fbo(id) {}
|
||||
FrameBuffer(GLuint id) : allocated(false), m_target(GL_FRAMEBUFFER), m_frameBufferId(id) {}
|
||||
|
||||
/**
|
||||
* @brief the destructor does not destroy the textures, however, deleteTextures will do that
|
||||
@ -43,10 +44,13 @@ public:
|
||||
|
||||
void deleteTextures();
|
||||
|
||||
void setTarget(GLenum target = GL_FRAMEBUFFER) { m_target = target; }
|
||||
|
||||
/**
|
||||
* @brief bindFBO binds the framebuffer on the specified target
|
||||
* @brief bindFBO binds the framebuffer
|
||||
* to unbind the framebuffer (bind the screen), you can use FrameBuffer::screen->bindFBO();
|
||||
*/
|
||||
void bindFBO(GLenum target = GL_FRAMEBUFFER) const;
|
||||
void bindFBO() const;
|
||||
|
||||
/**
|
||||
* @brief getTexture returns an attached texture, indexed from their adding order.
|
||||
|
152
src/light.cpp
152
src/light.cpp
@ -27,93 +27,117 @@ const glm::mat4 Light::biasMatrix(
|
||||
|
||||
Light::Light()
|
||||
{
|
||||
initPointLight();
|
||||
initAmbientLight();
|
||||
}
|
||||
|
||||
void Light::initAmbientLight(glm::vec3 lightColor)
|
||||
{
|
||||
type = AMBIENT;
|
||||
position = glm::vec3(0);
|
||||
color = lightColor;
|
||||
shadowCaster = false;
|
||||
isDir = false;
|
||||
viewMatrix = glm::mat4();
|
||||
m_type = AMBIENT;
|
||||
m_position = glm::vec3(0); // not used
|
||||
m_direction = glm::vec3(0, 0, 1); // not used
|
||||
m_cutOffAngle = 0; // not used
|
||||
m_color = lightColor;
|
||||
m_attenuation = 0; // not used
|
||||
m_shadowCaster = false; // not used
|
||||
}
|
||||
|
||||
void Light::initDirectionnalLight(glm::vec3 dir, glm::vec3 lightColor)
|
||||
{
|
||||
type = DIRECTIONNAL;
|
||||
position = glm::vec3(0);
|
||||
direction = dir;
|
||||
color = lightColor;
|
||||
shadowCaster = false;
|
||||
isDir = true;
|
||||
viewMatrix = glm::lookAt(position, position+direction, glm::vec3(0, 1, 0));
|
||||
m_type = DIRECTIONNAL;
|
||||
m_position = glm::vec3(0); // not used
|
||||
m_direction = dir;
|
||||
m_cutOffAngle = 0; // not used
|
||||
m_color = lightColor;
|
||||
m_attenuation = 0; // not used
|
||||
m_shadowCaster = false;
|
||||
}
|
||||
|
||||
void Light::initPointLight(glm::vec3 pos, glm::vec3 lightColor, float att)
|
||||
{
|
||||
type = POINT;
|
||||
position = pos;
|
||||
cutOffAngle = 360;
|
||||
color = lightColor;
|
||||
shadowCaster = false;
|
||||
isDir = false;
|
||||
viewMatrix = glm::mat4();
|
||||
attenuation = att;
|
||||
m_type = POINT;
|
||||
m_position = pos;
|
||||
m_direction = glm::vec3(0, 0, 1); // used to orient the shadowmap
|
||||
m_cutOffAngle = 0; // not used
|
||||
m_color = lightColor;
|
||||
m_attenuation = att;
|
||||
m_shadowCaster = false;
|
||||
}
|
||||
|
||||
void Light::initSpotLight(glm::vec3 pos, glm::vec3 dir, float spotAngle, glm::vec3 lightColor)
|
||||
void Light::initSpotLight(glm::vec3 pos, glm::vec3 dir, float spotAngle, glm::vec3 lightColor, float att)
|
||||
{
|
||||
type = SPOT;
|
||||
position = pos;
|
||||
direction = dir;
|
||||
cutOffAngle = spotAngle;
|
||||
color = lightColor;
|
||||
shadowCaster = false;
|
||||
isDir = false;
|
||||
m_type = SPOT;
|
||||
m_position = pos;
|
||||
m_direction = dir;
|
||||
m_cutOffAngle = spotAngle;
|
||||
m_color = lightColor;
|
||||
m_attenuation = att;
|
||||
m_shadowCaster = false;
|
||||
}
|
||||
|
||||
bool Light::isDirectionnal()
|
||||
void Light::initShadowMap(int resolution, glm::vec3 dim)
|
||||
{
|
||||
return isDir;
|
||||
}
|
||||
m_shadowMapResolution = resolution;
|
||||
Texture* tex;
|
||||
|
||||
void Light::initShadowMap(int resWidth, int resHeight, glm::vec3 dim)
|
||||
{
|
||||
shadowMapWidth = resWidth;
|
||||
shadowMapHeight = resHeight;
|
||||
viewMatrix = glm::lookAt(position, position-direction, glm::vec3(0, 1, 0));
|
||||
if(type == DIRECTIONNAL)
|
||||
projectionMatrix = glm::ortho(-dim.x/2, dim.x/2, -dim.y/2, dim.y/2, -dim.z/2, dim.z/2);
|
||||
else
|
||||
; // TODO : glm::projection
|
||||
switch(m_type)
|
||||
{
|
||||
case DIRECTIONNAL:
|
||||
// 3 orthogonal matrices (cascaded shadowmaps)
|
||||
// 3 square textures
|
||||
m_viewMatrix = glm::lookAt(m_position, m_position-m_direction, glm::vec3(0, 1, 0));
|
||||
m_projectionMatrix = glm::ortho(-dim.x/2, dim.x/2, -dim.y/2, dim.y/2, -dim.z/2, dim.z/2);
|
||||
tex = new Texture(GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, resolution, resolution, GL_FLOAT, GL_TEXTURE_2D);
|
||||
break;
|
||||
case POINT:
|
||||
// see http://learnopengl.com/#!Advanced-Lighting/Shadows/Point-Shadows
|
||||
|
||||
shadowCaster = true;
|
||||
shadowMap = new FrameBuffer();
|
||||
// Depth buffer
|
||||
Texture* tex = new Texture(GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, resWidth, resHeight, GL_FLOAT);
|
||||
tex->setFiltering(GL_LINEAR);
|
||||
tex->setWrap(GL_CLAMP_TO_EDGE);
|
||||
tex->setParameter(GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
|
||||
tex->setParameter(GL_TEXTURE_COMPARE_FUNC, GL_LESS);
|
||||
shadowMap->addTexture(tex, GL_DEPTH_ATTACHMENT);
|
||||
shadowMap->initColorAttachments();
|
||||
// 6 projection matrices
|
||||
// 1 cubemap texture
|
||||
m_viewMatrix = glm::lookAt(m_position, m_position-glm::vec3(0, 0, 1), glm::vec3(0, 1, 0));
|
||||
m_projectionMatrix = glm::perspective(90.f, 1.f, 0.1f, 100.f);
|
||||
tex = new Texture(GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, resolution, resolution, GL_FLOAT, GL_TEXTURE_CUBE_MAP);
|
||||
break;
|
||||
case SPOT:
|
||||
// 1 projection matrix
|
||||
// 1 square texture
|
||||
m_viewMatrix = glm::lookAt(m_position, m_position+m_direction, glm::vec3(0, 1, 0));
|
||||
m_projectionMatrix = glm::perspective(m_cutOffAngle, 1.f, 0.1f, 100.f);
|
||||
tex = new Texture(GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, resolution, resolution, GL_FLOAT, GL_TEXTURE_2D);
|
||||
break;
|
||||
case AMBIENT:
|
||||
return;
|
||||
}
|
||||
|
||||
// shader compilation
|
||||
// TODO : do not compile shader for every light
|
||||
ShaderSource source;
|
||||
Resource::ResourceMap shaderMap;
|
||||
Resource::getResourcePack_shaders(shaderMap);
|
||||
source.setSource(shaderMap["shaders/shadow.vert.glsl"], ShaderSource::VERTEX);
|
||||
if(m_type == POINT)
|
||||
source.setSource(shaderMap["shaders/shadow.geom.glsl"], ShaderSource::GEOMETRY);
|
||||
source.setSource(shaderMap["shaders/shadow.frag.glsl"], ShaderSource::FRAGMENT);
|
||||
shaders[0] = source.compile(Mesh::MESH_3D, getFlags());
|
||||
shaders[1] = source.compile(Mesh::MESH_3D & Mesh::MATERIAL_ALPHA_MASK, getFlags());
|
||||
m_shaders[0] = source.compile(Mesh::MESH_3D, getFlags());
|
||||
m_shaders[1] = source.compile(Mesh::MESH_3D & Mesh::MATERIAL_ALPHA_MASK, getFlags());
|
||||
|
||||
// Depth buffer
|
||||
tex->setFiltering(GL_LINEAR);
|
||||
tex->setWrap(GL_CLAMP_TO_EDGE);
|
||||
tex->setParameter(GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
|
||||
tex->setParameter(GL_TEXTURE_COMPARE_FUNC, GL_LESS);
|
||||
|
||||
// framebuffer
|
||||
m_shadowCaster = true;
|
||||
m_shadowMap = new FrameBuffer();
|
||||
m_shadowMap->addTexture(tex, GL_DEPTH_ATTACHMENT);
|
||||
m_shadowMap->initColorAttachments();
|
||||
}
|
||||
|
||||
void Light::generateShadowMap(Scene* scene)
|
||||
{
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glViewport(0, 0, shadowMapWidth, shadowMapHeight);
|
||||
shadowMap->bindFBO();
|
||||
glViewport(0, 0, m_shadowMapResolution, m_shadowMapResolution);
|
||||
m_shadowMap->bindFBO();
|
||||
glClearDepth(1.0);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
@ -128,9 +152,9 @@ void Light::generateShadowMap(Scene* scene)
|
||||
// compute matrix attributes
|
||||
glm::mat4 lightMVP = getProjectionMatrix() * (getViewMatrix() * node->modelMatrix);
|
||||
int hasAlpha = (node->mesh->getFlags() & (1 << Mesh::MATERIAL_ALPHA_MASK)) > 0;
|
||||
shaders[hasAlpha]->bind();
|
||||
shaders[hasAlpha]->bindMat4(shaders[hasAlpha]->getLocation("MVP"), lightMVP);
|
||||
node->mesh->draw(shaders[hasAlpha], false, hasAlpha, false);
|
||||
m_shaders[hasAlpha]->bind();
|
||||
m_shaders[hasAlpha]->bindMat4(m_shaders[hasAlpha]->getLocation("MVP"), lightMVP);
|
||||
node->mesh->draw(m_shaders[hasAlpha], false, hasAlpha, false);
|
||||
}
|
||||
}
|
||||
//glCullFace(GL_BACK);
|
||||
@ -138,19 +162,19 @@ void Light::generateShadowMap(Scene* scene)
|
||||
|
||||
Texture* Light::getShadowMap()
|
||||
{
|
||||
return shadowMap->getTexture(0);
|
||||
return m_shadowMap->getTexture(0);
|
||||
}
|
||||
|
||||
void Light::setPosition(glm::vec3 new_pos)
|
||||
{
|
||||
position = new_pos;
|
||||
viewMatrix = glm::lookAt(position, position+direction, glm::vec3(0, 1, 0));
|
||||
m_position = new_pos;
|
||||
m_viewMatrix = glm::lookAt(m_position, m_position+m_direction, glm::vec3(0, 1, 0));
|
||||
}
|
||||
|
||||
unsigned int Light::getFlags()
|
||||
{
|
||||
unsigned int flags = 0;
|
||||
switch(type)
|
||||
switch(m_type)
|
||||
{
|
||||
case AMBIENT :
|
||||
flags = 1 << AMBIENT_FLAG;
|
||||
@ -165,7 +189,7 @@ unsigned int Light::getFlags()
|
||||
flags = 1 << SPOT_FLAG;
|
||||
break;
|
||||
}
|
||||
if(shadowCaster)
|
||||
if(m_shadowCaster)
|
||||
flags |= 1 << SHADOWMAP_FLAG;
|
||||
return flags;
|
||||
}
|
||||
|
52
src/light.h
52
src/light.h
@ -36,27 +36,26 @@ public:
|
||||
void initAmbientLight(glm::vec3 lightColor = glm::vec3(0.1f));
|
||||
void initDirectionnalLight(glm::vec3 dir = glm::vec3(0, -1, 0), glm::vec3 lightColor = glm::vec3(1));
|
||||
void initPointLight(glm::vec3 pos = glm::vec3(0), glm::vec3 lightColor = glm::vec3(1), float att = 1);
|
||||
void initSpotLight(glm::vec3 pos = glm::vec3(0), glm::vec3 dir = glm::vec3(1, 0, 0), float spotAngle = 360, glm::vec3 lightColor = glm::vec3(1));
|
||||
void initSpotLight(glm::vec3 pos = glm::vec3(0), glm::vec3 dir = glm::vec3(1, 0, 0), float spotAngle = 360, glm::vec3 lightColor = glm::vec3(1), float att = 1);
|
||||
|
||||
bool isDirectionnal();
|
||||
LightType getType() {return type;}
|
||||
glm::vec3 getDir() {return direction;}
|
||||
glm::vec3 getPos() {return position;}
|
||||
glm::vec3 getColor() {return color;}
|
||||
float getAttenuation() {return attenuation;}
|
||||
LightType getType() {return m_type;}
|
||||
glm::vec3 getDir() {return m_direction;}
|
||||
glm::vec3 getPos() {return m_position;}
|
||||
glm::vec3 getColor() {return m_color;}
|
||||
float getAttenuation() {return m_attenuation;}
|
||||
|
||||
bool isShadowCaster() {return shadowCaster;}
|
||||
void initShadowMap(int resWidth, int resHeight, glm::vec3 dim = glm::vec3(1));
|
||||
bool isShadowCaster() {return m_shadowCaster;}
|
||||
void initShadowMap(int resolution, glm::vec3 dim = glm::vec3(1));
|
||||
void generateShadowMap(Scene* scene);
|
||||
Texture* getShadowMap();
|
||||
|
||||
void setAttenuation(float a) {attenuation = a;}
|
||||
void setAttenuation(float a) {m_attenuation = a;}
|
||||
void setPosition(glm::vec3 new_pos);
|
||||
void setColor(glm::vec3 new_color) {color = new_color;}
|
||||
void setColor(glm::vec3 new_color) {m_color = new_color;}
|
||||
|
||||
// camera inheritance
|
||||
glm::mat4 getProjectionMatrix() {return projectionMatrix;}
|
||||
glm::mat4 getViewMatrix() {return viewMatrix;}
|
||||
glm::mat4 getProjectionMatrix() {return m_projectionMatrix;}
|
||||
glm::mat4 getViewMatrix() {return m_viewMatrix;}
|
||||
// does nothing, just required for inheriting Camera
|
||||
void resize(int width, int height) {}
|
||||
|
||||
@ -66,24 +65,21 @@ public:
|
||||
unsigned int getFlags();
|
||||
private:
|
||||
// standard attributes
|
||||
LightType type;
|
||||
LightType m_type;
|
||||
|
||||
glm::vec3 position;
|
||||
glm::vec3 direction;
|
||||
float cutOffAngle;
|
||||
float attenuation;
|
||||
glm::vec3 color;
|
||||
|
||||
bool isDir;
|
||||
glm::vec3 m_position;
|
||||
glm::vec3 m_direction;
|
||||
float m_cutOffAngle;
|
||||
float m_attenuation;
|
||||
glm::vec3 m_color;
|
||||
|
||||
// shadowmap attributes
|
||||
bool shadowCaster;
|
||||
int shadowMapWidth;
|
||||
int shadowMapHeight;
|
||||
FrameBuffer* shadowMap;
|
||||
Shader* shaders[2];
|
||||
glm::mat4 viewMatrix;
|
||||
glm::mat4 projectionMatrix;
|
||||
bool m_shadowCaster;
|
||||
int m_shadowMapResolution;
|
||||
FrameBuffer* m_shadowMap;
|
||||
Shader* m_shaders[2];
|
||||
glm::mat4 m_viewMatrix;
|
||||
glm::mat4 m_projectionMatrix;
|
||||
};
|
||||
|
||||
#endif // LIGHT_H
|
||||
|
@ -33,7 +33,7 @@ public:
|
||||
// creates a standard texture from an image
|
||||
Texture(Image* myImage, bool makeMipMaps = true);
|
||||
// creates a cubeMap from 6 images
|
||||
Texture(Image* myCubemapImages[6], bool makeMipMaps = true);
|
||||
Texture(Image* myCubemapImages[6], bool makeMipMaps = true);
|
||||
// creates a texture from another
|
||||
Texture(Texture* tex, bool halfDim = false);
|
||||
|
||||
|
@ -66,8 +66,10 @@ void TextureBlur::blur()
|
||||
{
|
||||
FrameBuffer* src = fbos + i;
|
||||
FrameBuffer* dst = fbos + (i + 1);
|
||||
src->bindFBO(GL_READ_FRAMEBUFFER);
|
||||
dst->bindFBO(GL_DRAW_FRAMEBUFFER);
|
||||
src->setTarget(GL_READ_FRAMEBUFFER);
|
||||
src->bindFBO();
|
||||
dst->setTarget(GL_DRAW_FRAMEBUFFER);
|
||||
dst->bindFBO();
|
||||
glBlitFramebuffer(0, 0,
|
||||
src->getTexture(0)->getWidth(),
|
||||
src->getTexture(0)->getHeight(),
|
||||
|
Loading…
x
Reference in New Issue
Block a user