Skip to content

Commit

Permalink
#219: WIP commit, adding dummy shadow map VP/FP and corresponding C++…
Browse files Browse the repository at this point in the history
… wrapper. Add texture atlas and rectangle class.
  • Loading branch information
codereader committed Mar 24, 2022
1 parent 172cae0 commit 8f32f03
Show file tree
Hide file tree
Showing 17 changed files with 325 additions and 5 deletions.
28 changes: 28 additions & 0 deletions install/gl/shadowmap_fp.glsl
@@ -0,0 +1,28 @@
#version 120

uniform sampler2D u_Diffuse;
uniform float u_AlphaTest;
uniform mat4 u_ObjectTransform;

// The final diffuse texture coordinate at this vertex, calculated in the vertex shader
varying vec2 var_TexDiffuse;

void main()
{
if (u_AlphaTest < 0)
{
gl_FragColor.a = 1.0;
gl_FragColor.rgb = vec3(1.0, 1.0, 0.0);
}
else
{
vec4 tex = texture2D(u_Diffuse, var_TexDiffuse);

if (tex.a <= u_AlphaTest)
{
discard;
}

gl_FragColor = tex;
}
}
23 changes: 23 additions & 0 deletions install/gl/shadowmap_vs.glsl
@@ -0,0 +1,23 @@
#version 140

in vec4 attr_Position; // bound to attribute 0 in source, in object space
in vec4 attr_TexCoord; // bound to attribute 8 in source

uniform mat4 u_ObjectTransform; // object transform (object2world)

// The two top-rows of the diffuse stage texture transformation matrix
uniform vec4 u_DiffuseTextureMatrix[2];

// The final diffuse texture coordinate at this vertex
varying vec2 var_TexDiffuse;

void main()
{
// Apply the supplied object transform to the incoming vertex
// transform vertex position into homogenous clip-space
gl_Position = u_ModelViewProjection * u_ObjectTransform * attr_Position;

// Apply the stage texture transform to the incoming tex coord, component wise
var_TexDiffuse.x = dot(u_DiffuseTextureMatrix[0], attr_TexCoord);
var_TexDiffuse.y = dot(u_DiffuseTextureMatrix[1], attr_TexCoord);
}
15 changes: 15 additions & 0 deletions libs/render/Rectangle.h
@@ -0,0 +1,15 @@
#pragma once

namespace render
{

// Defines a rectangular area within a larger one
struct Rectangle
{
int x;
int y;
int width;
int height;
};

}
1 change: 1 addition & 0 deletions radiantcore/CMakeLists.txt
Expand Up @@ -217,6 +217,7 @@ add_library(radiantcore MODULE
rendersystem/backend/glprogram/GLSLBumpProgram.cpp
rendersystem/backend/glprogram/GLSLCubeMapProgram.cpp
rendersystem/backend/glprogram/GLSLDepthFillAlphaProgram.cpp
rendersystem/backend/glprogram/ShadowMapProgram.cpp
rendersystem/backend/BuiltInShader.cpp
rendersystem/backend/ColourShader.cpp
rendersystem/backend/LightInteractions.cpp
Expand Down
16 changes: 16 additions & 0 deletions radiantcore/rendersystem/backend/FrameBuffer.h
Expand Up @@ -11,11 +11,13 @@ class FrameBuffer
private:
GLuint _fbo;
std::size_t _width;
std::size_t _height;
GLuint _textureNumber;

FrameBuffer() :
_fbo(0),
_width(0),
_height(0),
_textureNumber(0)
{}

Expand All @@ -33,6 +35,16 @@ class FrameBuffer
_fbo = 0;
}

std::size_t getWidth() const
{
return _width;
}

std::size_t getHeight() const
{
return _height;
}

void bind()
{
glBindFramebuffer(GL_FRAMEBUFFER, _fbo);
Expand Down Expand Up @@ -62,7 +74,11 @@ class FrameBuffer
static_cast<GLsizei>(size), static_cast<GLsizei>(size),
0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);

// Attach the texture to the FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, buffer->_textureNumber, 0);

buffer->_width = size;
buffer->_height = size;

return buffer;
}
Expand Down
2 changes: 2 additions & 0 deletions radiantcore/rendersystem/backend/GLProgramFactory.cpp
Expand Up @@ -5,6 +5,7 @@
#include "glprogram/GLSLCubeMapProgram.h"
#include "glprogram/GLSLBumpProgram.h"
#include "glprogram/GenericVFPProgram.h"
#include "glprogram/ShadowMapProgram.h"

#include "itextstream.h"
#include "iregistry.h"
Expand All @@ -27,6 +28,7 @@ GLProgramFactory::GLProgramFactory()
_builtInPrograms[ShaderProgram::DepthFillAlpha] = std::make_shared<GLSLDepthFillAlphaProgram>();
_builtInPrograms[ShaderProgram::Interaction] = std::make_shared<GLSLBumpProgram>();
_builtInPrograms[ShaderProgram::CubeMap] = std::make_shared<GLSLCubeMapProgram>();
_builtInPrograms[ShaderProgram::ShadowMap] = std::make_shared<ShadowMapProgram>();
}

GLProgram* GLProgramFactory::getBuiltInProgram(ShaderProgram builtInProgram)
Expand Down
1 change: 1 addition & 0 deletions radiantcore/rendersystem/backend/GLProgramFactory.h
Expand Up @@ -18,6 +18,7 @@ enum class ShaderProgram
DepthFillAlpha,
Interaction,
CubeMap,
ShadowMap,
};

/**
Expand Down
87 changes: 85 additions & 2 deletions radiantcore/rendersystem/backend/LightInteractions.cpp
Expand Up @@ -3,6 +3,7 @@
#include "OpenGLShader.h"
#include "ObjectRenderer.h"
#include "glprogram/GLSLDepthFillAlphaProgram.h"
#include "glprogram/ShadowMapProgram.h"

namespace render
{
Expand Down Expand Up @@ -155,9 +156,91 @@ void LightInteractions::fillDepthBuffer(OpenGLState& state, GLSLDepthFillAlphaPr
}
}

void LightInteractions::drawShadowMap(OpenGLState& state)
void LightInteractions::drawShadowMap(OpenGLState& state, const Rectangle& rectangle, ShadowMapProgram& program)
{

// Enable GL state and save to state
glDepthMask(true);
state.setRenderFlag(RENDER_DEPTHWRITE);

glDepthFunc(GL_LEQUAL);
state.setDepthFunc(GL_LEQUAL);

// Set up the viewport to write to a specific area within the shadow map texture
glViewport(rectangle.x, rectangle.y, 6 * rectangle.width, rectangle.width);
glClear(GL_DEPTH_BUFFER_BIT);

std::vector<IGeometryStore::Slot> untransformedObjects;
untransformedObjects.reserve(1000);

// No alpha test for now
program.setAlphaTest(-1);

// Render all the objects that have a depth filling stage
for (const auto& [entity, objectsByShader] : _objectsByEntity)
{
for (const auto& [shader, objects] : objectsByShader)
{
auto depthFillPass = shader->getDepthFillPass();

if (!depthFillPass) continue;

#if 0
const auto& material = shader->getMaterial();
assert(material);

auto coverage = material->getCoverage();

// Skip translucent materials
if (coverage == Material::MC_TRANSLUCENT) continue;

if (coverage == Material::MC_PERFORATED)
{
// Evaluate the shader stages of this material
depthFillPass->evaluateShaderStages(renderTime, entity);

// Apply the alpha test value, it might be affected by time and entity parms
program.setAlphaTest(depthFillPass->getAlphaTestValue());

// If there's a diffuse stage, apply the correct texture
OpenGLState::SetTextureState(state.texture0, depthFillPass->state().texture0, GL_TEXTURE0, GL_TEXTURE_2D);

// Set evaluated stage texture transformation matrix to the GLSL uniform
program.setDiffuseTextureTransform(depthFillPass->getDiffuseTextureTransform());
}
else
{
// No alpha test on this material, pass -1 to deactivate texture sampling
// in the GLSL program
program.setAlphaTest(-1);
}
#endif

for (const auto& object : objects)
{
// We submit all objects with an identity matrix in a single multi draw call
if (!object.get().isOriented())
{
untransformedObjects.push_back(object.get().getStorageLocation());
continue;
}

program.setObjectTransform(object.get().getObjectTransform());

ObjectRenderer::SubmitGeometry(object.get().getStorageLocation(), GL_TRIANGLES, _store);
++_depthDrawCalls;
}

if (!untransformedObjects.empty())
{
program.setObjectTransform(Matrix4::getIdentity());

ObjectRenderer::SubmitGeometry(untransformedObjects, GL_TRIANGLES, _store);
++_depthDrawCalls;

untransformedObjects.clear();
}
}
}
}

void LightInteractions::drawInteractions(OpenGLState& state, GLSLBumpProgram& program,
Expand Down
4 changes: 3 additions & 1 deletion radiantcore/rendersystem/backend/LightInteractions.h
Expand Up @@ -7,6 +7,7 @@
#include "isurfacerenderer.h"
#include "irenderableobject.h"
#include "irenderview.h"
#include "render/Rectangle.h"

namespace render
{
Expand All @@ -15,6 +16,7 @@ class OpenGLState;
class OpenGLShader;
class GLSLDepthFillAlphaProgram;
class GLSLBumpProgram;
class ShadowMapProgram;

/**
* Defines interactions between a light and one or more entity renderables
Expand Down Expand Up @@ -91,7 +93,7 @@ class LightInteractions
void fillDepthBuffer(OpenGLState& state, GLSLDepthFillAlphaProgram& program,
const IRenderView& view, std::size_t renderTime, std::vector<IGeometryStore::Slot>& untransformedObjectsWithoutAlphaTest);

void drawShadowMap(OpenGLState& state);
void drawShadowMap(OpenGLState& state, const Rectangle& rectangle, ShadowMapProgram& program);

void drawInteractions(OpenGLState& state, GLSLBumpProgram& program, const IRenderView& view, std::size_t renderTime);
};
Expand Down
19 changes: 18 additions & 1 deletion radiantcore/rendersystem/backend/LightingModeRenderer.cpp
@@ -1,5 +1,6 @@
#include "LightingModeRenderer.h"

#include "GLProgramFactory.h"
#include "LightingModeRenderResult.h"
#include "LightInteractions.h"
#include "OpenGLShaderPass.h"
Expand All @@ -20,6 +21,22 @@ IRenderResult::Ptr LightingModeRenderer::render(RenderStateFlags globalFlagsMask
if (!_shadowMapFbo)
{
_shadowMapFbo = FrameBuffer::CreateShadowMapBuffer();
// Define the shadow atlas
_shadowMapAtlas.resize(4);

for (int i = 0; i < 6; ++i)
{
_shadowMapAtlas[i].x = 0;
_shadowMapAtlas[i].y = static_cast<int>((_shadowMapFbo->getHeight() / 6) * i);
_shadowMapAtlas[i].width = static_cast<int>(_shadowMapFbo->getWidth() / 6);
_shadowMapAtlas[i].height = static_cast<int>(_shadowMapFbo->getHeight() / 6);
}
}

if (!_shadowMapProgram)
{
_shadowMapProgram = dynamic_cast<ShadowMapProgram*>(_programFactory.getBuiltInProgram(ShaderProgram::ShadowMap));
assert(_shadowMapProgram);
}

// Construct default OpenGL state
Expand Down Expand Up @@ -70,7 +87,7 @@ IRenderResult::Ptr LightingModeRenderer::render(RenderStateFlags globalFlagsMask
{
if (!interactionList.castsShadows()) continue;

interactionList.drawShadowMap(current);
interactionList.drawShadowMap(current, _shadowMapAtlas[0], *_shadowMapProgram);
result->shadowDrawCalls += interactionList.getShadowMapDrawCalls();
break;
}
Expand Down
16 changes: 15 additions & 1 deletion radiantcore/rendersystem/backend/LightingModeRenderer.h
Expand Up @@ -5,6 +5,8 @@
#include "SceneRenderer.h"
#include "igeometrystore.h"
#include "FrameBuffer.h"
#include "render/Rectangle.h"
#include "glprogram/ShadowMapProgram.h"

namespace render
{
Expand All @@ -29,6 +31,8 @@ class LightingModeRenderer final :
std::vector<IGeometryStore::Slot> _untransformedObjectsWithoutAlphaTest;

FrameBuffer::Ptr _shadowMapFbo;
std::vector<Rectangle> _shadowMapAtlas;
ShadowMapProgram* _shadowMapProgram;

public:
LightingModeRenderer(GLProgramFactory& programFactory,
Expand All @@ -38,11 +42,21 @@ class LightingModeRenderer final :
_programFactory(programFactory),
_geometryStore(store),
_lights(lights),
_entities(entities)
_entities(entities),
_shadowMapProgram(nullptr)
{
_untransformedObjectsWithoutAlphaTest.reserve(10000);
}

~LightingModeRenderer()
{
if (_shadowMapProgram)
{
_shadowMapProgram->destroy();
_shadowMapProgram = nullptr;
}
}

IRenderResult::Ptr render(RenderStateFlags globalFlagsMask, const IRenderView& view, std::size_t time) override;

private:
Expand Down

0 comments on commit 8f32f03

Please sign in to comment.