Skip to content

Instantly share code, notes, and snippets.

@kcbanner
Last active August 29, 2015 13:58
Show Gist options
  • Save kcbanner/9947215 to your computer and use it in GitHub Desktop.
Save kcbanner/9947215 to your computer and use it in GitHub Desktop.
void GLRenderManager::render() {
GLSpriteBatch* batch;
std::list<GLSpriteBatch*>::iterator i;
// Sort batches by layer and upload to GPU
mActiveBatches.sort(sortByLayer());
for (i = mActiveBatches.begin(); i != mActiveBatches.end(); ++i) {
batch = *i;
// Upload the batch if its dirty
if (batch->dirty) {
batch->upload();
}
}
// Render all non-UI and non-background sprites to diffuse FBO
glDisable(GL_FRAMEBUFFER_SRGB);
mDiffuseFbo->bind();
glViewport(0, 0, mViewportDimensions.x, mViewportDimensions.y);
glClear(GL_COLOR_BUFFER_BIT);
const glm::mat4* view = mCamera->getView();
for (int layerIter = LAYER_BACKGROUND_TILES; layerIter < LAYER_UI; layerIter++) {
renderLayer((Layer)layerIter, view, &projection_, false);
}
// Render all the illuminating layers to the light fbo
mLightFbo->bind();
glClear(GL_COLOR_BUFFER_BIT);
for (int layerIter = LAYER_BACKGROUND_TILES; layerIter < LAYER_UI; layerIter++) {
renderLayer((Layer)layerIter, view, &projection_, true);
}
// Render all occluders
mOccluderFbo->bind();
glClear(GL_COLOR_BUFFER_BIT);
for (i = mActiveBatchesByLayer[LAYER_FOREGROUND_TILES].begin();
i != mActiveBatchesByLayer[LAYER_FOREGROUND_TILES].end(); ++i) {
batch = *i;
renderBatch(batch, view, &projection_);
}
const Rect& visibleArea = mCamera->getVisibleArea();
for (std::list<Light*>::iterator lightIter = mLights.begin(); lightIter != mLights.end(); ++lightIter) {
Light* light;
Rect lightRect;
glm::vec2 lightCollision;
light = *lightIter;
if (!light->getEnabled()) {
continue;
}
lightRect.position = light->getPosition();
lightRect.extents.x = light->getRange();
lightRect.extents.y = lightRect.extents.x;
// TODO: Cull lights that are not visible
/*
if (g_CollisionManager.collide(&visibleArea, &lightRect, &lightCollision)) {
continue;
}
*/
// Render shadow map
glViewport(0, 0, MAX_LIGHT_RANGE, MAX_LIGHT_RANGE);
glBindVertexArray(mQuadVao);
mShadowMapFbo->bind();
mShadowMapProgram->Use();
mShadowMapProgram->SetUniform("projection", &mSquareProjection);
mShadowMapProgram->SetUniform("occluder", bindTexture(mOccluderTexture));
mShadowMapProgram->SetUniform("range", light->getRange());
glm::vec4 screenSpaceLightPosition = projection_ * *view * glm::vec4(
light->getPosition().x, light->getPosition().y, 0.0f, 1.0f);
mShadowMapProgram->SetUniform("position", glm::vec2(screenSpaceLightPosition.x, screenSpaceLightPosition.y));
mShadowMapProgram->SetUniform("scale", glm::scale(glm::mat4(1.0f), float(mWindowHeight) / float(mWindowWidth), 1.0f, 1.0f));
glClear(GL_COLOR_BUFFER_BIT);
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, (const GLvoid*)0);
// Render the light to the light FBO
glViewport(0, 0, mViewportDimensions.x, mViewportDimensions.y);
mLightFbo->bind();
mLightProgram->Use();
mLightProgram->SetUniform("projection", &projection_);
mLightProgram->SetUniform("view", view);
mLightProgram->SetUniform("size", (float)MAX_LIGHT_RANGE, (float)MAX_LIGHT_RANGE);
mLightProgram->SetUniform("position", light->getPosition());
mLightProgram->SetUniform("shadowmap", bindTexture(mShadowMapTexture));
mLightProgram->SetUniform("range", light->getRange());
mLightProgram->SetUniform("brightness", light->getBrightness());
mLightProgram->SetUniform("color", light->getColor());
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, (const GLvoid*)0);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glEnable(GL_FRAMEBUFFER_SRGB);
glViewport(0, 0, mWindowWidth, mWindowHeight);
glClear(GL_COLOR_BUFFER_BIT);
// Render background to the screen
renderLayer(LAYER_BACKGROUND, &mStaticView, &projection_, false);
// Composite the lights and diffuse sprites
glBindVertexArray(mQuadVao);
mCompositeProgram->Use();
mCompositeProgram->SetUniform("projection", &mCompositeProjection);
mCompositeProgram->SetUniform("diffuseTexture", bindTexture(mDiffuseTexture));
mCompositeProgram->SetUniform("lightsTexture", bindTexture(mLightTexture));
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, (const GLvoid*)0);
// Debug
mDebugQuadProgram->Use();
mDebugQuadProgram->SetUniform("projection", &projection_);
mDebugQuadProgram->SetUniform("diffuse", bindTexture(mOccluderTexture));
mDebugQuadProgram->SetUniform("offset", glm::vec2(80.0f, 60.0f));
mDebugQuadProgram->SetUniform("size", glm::vec2(186.6f, 100.0f));
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, (const GLvoid*)0);
mDebugQuadProgram->SetUniform("diffuse", bindTexture(mLightTexture));
mDebugQuadProgram->SetUniform("offset", glm::vec2(270.0f, 60.0f));
mDebugQuadProgram->SetUniform("size", glm::vec2(186.6f, 100.0f));
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, (const GLvoid*)0);
mDebugQuadProgram->SetUniform("projection", &mSquareProjection);
mDebugQuadProgram->SetUniform("diffuse", bindTexture(mShadowMapTexture));
mDebugQuadProgram->SetUniform("offset", glm::vec2(80.0f, 135.0f));
mDebugQuadProgram->SetUniform("size", glm::vec2(128.0f, 10.0f));
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, (const GLvoid*)0);
glBindVertexArray(0);
glfwSwapBuffers();
}
mViewportDimensions.x = (float)mWindowWidth / 3.0f;
mViewportDimensions.y = (float)mWindowHeight / 3.0f;
projection_ = glm::ortho(0.0f, mViewportDimensions.x,
0.0f, mViewportDimensions.y);
mCompositeProjection = glm::ortho(-0.5f, 0.5f,
-0.5f, 0.5f);
mOccluderProjection = glm::ortho(0.0f, (float)MAX_LIGHT_RANGE,
0.0f, (float)MAX_LIGHT_RANGE);
template <typename valType>
GLM_FUNC_QUALIFIER detail::tmat4x4<valType> ortho
(
valType const & left,
valType const & right,
valType const & bottom,
valType const & top,
valType const & zNear,
valType const & zFar
)
{
detail::tmat4x4<valType> Result(1);
Result[0][0] = valType(2) / (right - left);
Result[1][1] = valType(2) / (top - bottom);
Result[2][2] = - valType(2) / (zFar - zNear);
Result[3][0] = - (right + left) / (right - left);
Result[3][1] = - (top + bottom) / (top - bottom);
Result[3][2] = - (zFar + zNear) / (zFar - zNear);
return Result;
}
template <typename valType>
GLM_FUNC_QUALIFIER detail::tmat4x4<valType> ortho(
valType const & left,
valType const & right,
valType const & bottom,
valType const & top)
{
detail::tmat4x4<valType> Result(1);
Result[0][0] = valType(2) / (right - left);
Result[1][1] = valType(2) / (top - bottom);
Result[2][2] = - valType(1);
Result[3][0] = - (right + left) / (right - left);
Result[3][1] = - (top + bottom) / (top - bottom);
return Result;
}
#version 150
#define PI 3.14159265359
#define ALPHA_THRESHOLD 0.9
#define STEPS 256
uniform mat4 projection;
uniform sampler2D occluder;
uniform float range;
uniform vec2 position;
uniform mat4 scale;
in vec2 texcoord;
out vec4 color0;
void main(void) {
float distance = 1.0;
// PI * 0.5 to PI * 2.5
float theta = PI * (1.5 + (2 * texcoord.s - 1.0));
for (float y = 0.0; y < STEPS; y += 1.0) {
float currentDistance = y / STEPS;
// Polar coordinates -> rectangular
float r = currentDistance;
// Scale
vec4 coord = scale * vec4(-r * sin(theta), -r * cos(theta), 0.0, 1.0);
// Coordinate to sample from the occluder texture
vec2 sampleCoord = vec2(coord.xy * 1 / 1.17 + position.xy) / 2.0 + 0.5;
vec4 sample = texture2D(occluder, sampleCoord);
// If the sample is above our threshold, check the distance
// and see if it is shorter than the current distance
// TODO: Use step instead of branch
if (sample.a > ALPHA_THRESHOLD) {
distance = min(distance, currentDistance);
}
}
color0 = vec4(distance, 0.0, 0.0, 1.0);
}
#version 150
uniform mat4 projection;
in vec4 vertex;
out vec2 texcoord;
void main(void) {
texcoord = vertex.zw;
gl_Position = projection * vec4(vertex.x, -vertex.y, 0.0f, 1.0f);
}
#version 150
uniform sampler2D diffuse;
in vec2 texcoord_out;
out vec4 color0;
void main(void) {
vec4 diffuse_color = texture2D(diffuse, texcoord_out);
color0 = diffuse_color;
}
#version 150
uniform mat4 projection;
uniform mat4 view;
uniform vec2 tex_size;
in vec4 vertex;
in vec2 position;
in vec2 size;
in vec2 texcoord;
in vec2 flip;
out vec2 texcoord_out;
void main(void) {
texcoord_out = vertex.zw * (size / tex_size) + texcoord;
gl_Position = projection * view * vec4(vertex.xy * size * flip + position, 0.0, 1.0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment