Added support for offscreen rendering and high resolution shadow maps
parent
b033e35385
commit
2665847c41
|
@ -107,7 +107,8 @@ enum RenderState
|
||||||
RENDER_STATE_DEPTH_WRITE,
|
RENDER_STATE_DEPTH_WRITE,
|
||||||
RENDER_STATE_ALPHA_TEST,
|
RENDER_STATE_ALPHA_TEST,
|
||||||
RENDER_STATE_CULLING,
|
RENDER_STATE_CULLING,
|
||||||
RENDER_STATE_DEPTH_BIAS
|
RENDER_STATE_DEPTH_BIAS,
|
||||||
|
RENDER_STATE_OFFSCREEN_RENDERING
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -380,6 +381,9 @@ public:
|
||||||
//! Sets the current fill mode
|
//! Sets the current fill mode
|
||||||
virtual void SetFillMode(FillMode mode) = 0;
|
virtual void SetFillMode(FillMode mode) = 0;
|
||||||
|
|
||||||
|
//! Initializes offscreen buffer
|
||||||
|
virtual void InitOffscreenBuffer(int width, int height) = 0;
|
||||||
|
|
||||||
//! Copies content of framebuffer to texture
|
//! Copies content of framebuffer to texture
|
||||||
virtual void CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, int width, int height) = 0;
|
virtual void CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, int width, int height) = 0;
|
||||||
|
|
||||||
|
|
|
@ -355,6 +355,10 @@ FillMode CNullDevice::GetFillMode()
|
||||||
return FILL_POINT;
|
return FILL_POINT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CNullDevice::InitOffscreenBuffer(int width, int height)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void CNullDevice::CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, int width, int height)
|
void CNullDevice::CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,6 +139,8 @@ public:
|
||||||
virtual void SetFillMode(FillMode mode) ;
|
virtual void SetFillMode(FillMode mode) ;
|
||||||
virtual FillMode GetFillMode();
|
virtual FillMode GetFillMode();
|
||||||
|
|
||||||
|
virtual void InitOffscreenBuffer(int width, int height);
|
||||||
|
|
||||||
virtual void CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, int width, int height);
|
virtual void CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, int width, int height);
|
||||||
|
|
||||||
virtual void* GetFrameBufferPixels() const;
|
virtual void* GetFrameBufferPixels() const;
|
||||||
|
|
|
@ -128,6 +128,14 @@ enum TexMixArgument
|
||||||
{
|
{
|
||||||
//! Color from current texture
|
//! Color from current texture
|
||||||
TEX_MIX_ARG_TEXTURE,
|
TEX_MIX_ARG_TEXTURE,
|
||||||
|
//! Color from texture unit 0
|
||||||
|
TEX_MIX_ARG_TEXTURE_0,
|
||||||
|
//! Color from texture unit 1
|
||||||
|
TEX_MIX_ARG_TEXTURE_1,
|
||||||
|
//! Color from texture unit 2
|
||||||
|
TEX_MIX_ARG_TEXTURE_2,
|
||||||
|
//! Color from texture unit 3
|
||||||
|
TEX_MIX_ARG_TEXTURE_3,
|
||||||
//! Color computed by previous texture unit (current in DirectX; previous in OpenGL)
|
//! Color computed by previous texture unit (current in DirectX; previous in OpenGL)
|
||||||
TEX_MIX_ARG_COMPUTED_COLOR,
|
TEX_MIX_ARG_COMPUTED_COLOR,
|
||||||
//! (Source) color of textured fragment (diffuse in DirectX; primary color in OpenGL)
|
//! (Source) color of textured fragment (diffuse in DirectX; primary color in OpenGL)
|
||||||
|
|
|
@ -117,7 +117,7 @@ CEngine::CEngine(CApplication *app)
|
||||||
m_textureMipmapLevel = 1;
|
m_textureMipmapLevel = 1;
|
||||||
m_textureAnisotropy = 1;
|
m_textureAnisotropy = 1;
|
||||||
m_shadowMapping = false;
|
m_shadowMapping = false;
|
||||||
m_npotShadowMap = false;
|
m_offscreenShadowRendering = false;
|
||||||
m_totoMode = true;
|
m_totoMode = true;
|
||||||
m_lensMode = true;
|
m_lensMode = true;
|
||||||
m_waterMode = true;
|
m_waterMode = true;
|
||||||
|
@ -186,7 +186,7 @@ CEngine::CEngine(CApplication *app)
|
||||||
if (CProfile::GetInstance().GetIntProperty("Setup", "ShadowMapping", value))
|
if (CProfile::GetInstance().GetIntProperty("Setup", "ShadowMapping", value))
|
||||||
{
|
{
|
||||||
m_shadowMapping = (value > 0);
|
m_shadowMapping = (value > 0);
|
||||||
m_npotShadowMap = (value > 1);
|
m_offscreenShadowRendering = (value > 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_defaultTexParams.format = TEX_IMG_AUTO;
|
m_defaultTexParams.format = TEX_IMG_AUTO;
|
||||||
|
@ -3336,6 +3336,9 @@ void CEngine::Draw3DScene()
|
||||||
params.coords[i].mode = TEX_GEN_NONE;
|
params.coords[i].mode = TEX_GEN_NONE;
|
||||||
|
|
||||||
m_device->SetTextureCoordGeneration(2, params);
|
m_device->SetTextureCoordGeneration(2, params);
|
||||||
|
|
||||||
|
m_device->SetTexture(3, 0);
|
||||||
|
m_device->SetTextureEnabled(3, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draws the shadows , if shadows enabled
|
// Draws the shadows , if shadows enabled
|
||||||
|
@ -3515,8 +3518,6 @@ void CEngine::RenderShadowMap()
|
||||||
|
|
||||||
m_app->StartPerformanceCounter(PCNT_RENDER_SHADOW_MAP);
|
m_app->StartPerformanceCounter(PCNT_RENDER_SHADOW_MAP);
|
||||||
|
|
||||||
m_device->Clear();
|
|
||||||
|
|
||||||
// If no shadow map texture exists, create it
|
// If no shadow map texture exists, create it
|
||||||
if (m_shadowMap.id == 0)
|
if (m_shadowMap.id == 0)
|
||||||
{
|
{
|
||||||
|
@ -3524,9 +3525,18 @@ void CEngine::RenderShadowMap()
|
||||||
|
|
||||||
int depth = m_app->GetInstance().GetVideoConfig().depthSize;
|
int depth = m_app->GetInstance().GetVideoConfig().depthSize;
|
||||||
|
|
||||||
if (m_npotShadowMap)
|
if (m_offscreenShadowRendering)
|
||||||
{
|
{
|
||||||
width = height = Math::Min(m_size.x, m_size.y);
|
int size;
|
||||||
|
|
||||||
|
if (CProfile::GetInstance().GetIntProperty("Setup", "OffscreenBuffer", size))
|
||||||
|
{
|
||||||
|
width = height = size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
width = height = 2048;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3542,12 +3552,23 @@ void CEngine::RenderShadowMap()
|
||||||
|
|
||||||
m_shadowMap = m_device->CreateDepthTexture(width, height, depth);
|
m_shadowMap = m_device->CreateDepthTexture(width, height, depth);
|
||||||
|
|
||||||
|
if (m_offscreenShadowRendering)
|
||||||
|
{
|
||||||
|
m_device->InitOffscreenBuffer(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
GetLogger()->Info("Created shadow map texture: %dx%d, depth %d\n", width, height, depth);
|
GetLogger()->Info("Created shadow map texture: %dx%d, depth %d\n", width, height, depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_offscreenShadowRendering)
|
||||||
|
{
|
||||||
|
m_device->SetRenderState(RENDER_STATE_OFFSCREEN_RENDERING, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_device->Clear();
|
||||||
|
|
||||||
// change state to rendering shadow maps
|
// change state to rendering shadow maps
|
||||||
m_device->SetColorMask(false, false, false, false);
|
m_device->SetColorMask(false, false, false, false);
|
||||||
//m_device->SetDepthTestFunc(COMP_FUNC_LEQUAL);
|
|
||||||
m_device->SetRenderState(RENDER_STATE_DEPTH_TEST, true);
|
m_device->SetRenderState(RENDER_STATE_DEPTH_TEST, true);
|
||||||
m_device->SetRenderState(RENDER_STATE_DEPTH_WRITE, true);
|
m_device->SetRenderState(RENDER_STATE_DEPTH_WRITE, true);
|
||||||
m_device->SetRenderState(RENDER_STATE_BLENDING, false);
|
m_device->SetRenderState(RENDER_STATE_BLENDING, false);
|
||||||
|
@ -3561,16 +3582,18 @@ void CEngine::RenderShadowMap()
|
||||||
// recompute matrices
|
// recompute matrices
|
||||||
Math::Vector worldUp(1.0f, 0.0f, 0.0f);
|
Math::Vector worldUp(1.0f, 0.0f, 0.0f);
|
||||||
Math::Vector dir = m_lookatPt - m_eyePt;
|
Math::Vector dir = m_lookatPt - m_eyePt;
|
||||||
float change = Math::Max(1.0f, dir.Length() / 25.0f);
|
float change = Math::Max(0.5f, (5.0f + dir.Length()) / 25.0f);
|
||||||
dir.Normalize();
|
dir.Normalize();
|
||||||
Math::Vector pos = m_lookatPt + 40.0f * dir;
|
Math::Vector pos = m_lookatPt + 40.0f * dir;
|
||||||
|
|
||||||
Math::Vector lightPos = pos + Math::Vector(3.0f, 30.0f, 3.0f);
|
Math::Vector lightPos = pos + Math::Vector(3.0f, 30.0f, 3.0f);
|
||||||
Math::Vector lookAt = pos + Math::Vector(0.0, 100.0f, 0.0f);
|
Math::Vector lookAt = pos + Math::Vector(0.0, 100.0f, 0.0f);
|
||||||
|
|
||||||
float dist = 75.0f; // *change;
|
float dist = 75.0f * change;
|
||||||
|
|
||||||
Math::LoadOrthoProjectionMatrix(m_shadowProjMat, -dist, dist, -dist, dist, -50.0f, 50.0f);
|
if (m_offscreenShadowRendering) dist = 400.0f * change;
|
||||||
|
|
||||||
|
Math::LoadOrthoProjectionMatrix(m_shadowProjMat, -dist, dist, -dist, dist, -200.0f, 200.0f);
|
||||||
Math::LoadViewMatrix(m_shadowViewMat, lightPos, lookAt, worldUp);
|
Math::LoadViewMatrix(m_shadowViewMat, lightPos, lookAt, worldUp);
|
||||||
|
|
||||||
Math::Matrix temporary = Math::MultiplyMatrices(m_shadowProjMat, m_shadowViewMat);
|
Math::Matrix temporary = Math::MultiplyMatrices(m_shadowProjMat, m_shadowViewMat);
|
||||||
|
@ -3642,12 +3665,16 @@ void CEngine::RenderShadowMap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_device->SetCullMode(CULL_CCW);
|
//m_device->SetRenderState(RENDER_STATE_DEPTH_BIAS, false);
|
||||||
m_device->SetRenderState(RENDER_STATE_DEPTH_BIAS, false);
|
|
||||||
|
|
||||||
// copy depth buffer to shadow map
|
// copy depth buffer to shadow map
|
||||||
m_device->CopyFramebufferToTexture(m_shadowMap, 0, 0, 0, 0, m_shadowMap.size.x, m_shadowMap.size.y);
|
m_device->CopyFramebufferToTexture(m_shadowMap, 0, 0, 0, 0, m_shadowMap.size.x, m_shadowMap.size.y);
|
||||||
|
|
||||||
|
if (m_offscreenShadowRendering)
|
||||||
|
{
|
||||||
|
m_device->SetRenderState(RENDER_STATE_OFFSCREEN_RENDERING, false);
|
||||||
|
}
|
||||||
|
|
||||||
// restore default state
|
// restore default state
|
||||||
m_device->SetViewport(0, 0, m_size.x, m_size.y);
|
m_device->SetViewport(0, 0, m_size.x, m_size.y);
|
||||||
|
|
||||||
|
|
|
@ -1457,8 +1457,8 @@ protected:
|
||||||
int m_textureAnisotropy;
|
int m_textureAnisotropy;
|
||||||
//! true if shadow mapping enabled
|
//! true if shadow mapping enabled
|
||||||
bool m_shadowMapping;
|
bool m_shadowMapping;
|
||||||
//! Override for NPOT shadow map texture
|
//! true enables offscreen shadow rendering
|
||||||
bool m_npotShadowMap;
|
bool m_offscreenShadowRendering;
|
||||||
|
|
||||||
//! Map of loaded textures (by name)
|
//! Map of loaded textures (by name)
|
||||||
std::map<std::string, Texture> m_texNameMap;
|
std::map<std::string, Texture> m_texNameMap;
|
||||||
|
|
|
@ -75,6 +75,10 @@ CGLDevice::CGLDevice(const GLDeviceConfig &config)
|
||||||
m_glMajor = 1;
|
m_glMajor = 1;
|
||||||
m_glMinor = 1;
|
m_glMinor = 1;
|
||||||
m_shadowMappingSupport = SMS_NONE;
|
m_shadowMappingSupport = SMS_NONE;
|
||||||
|
|
||||||
|
m_framebuffer = 0;
|
||||||
|
m_colorBuffer = 0;
|
||||||
|
m_depthBuffer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -217,6 +221,15 @@ bool CGLDevice::Create()
|
||||||
if (!m_multitextureAvailable)
|
if (!m_multitextureAvailable)
|
||||||
GetLogger()->Warn("GLEW reports multitexturing not supported - graphics quality will be degraded!\n");
|
GetLogger()->Warn("GLEW reports multitexturing not supported - graphics quality will be degraded!\n");
|
||||||
|
|
||||||
|
m_framebufferObject = glewIsSupported("GL_EXT_framebuffer_object");
|
||||||
|
if (m_framebufferObject)
|
||||||
|
{
|
||||||
|
glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &m_maxRenderbufferSize);
|
||||||
|
|
||||||
|
GetLogger()->Info("Offscreen rendering available\n");
|
||||||
|
GetLogger()->Info("Maximum renderbuffer size: %d\n", m_maxRenderbufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
// Detect Shadow mapping support
|
// Detect Shadow mapping support
|
||||||
if (m_glMajor >= 2 || m_glMinor >= 4) // Core depth texture+shadow, OpenGL 1.4+
|
if (m_glMajor >= 2 || m_glMinor >= 4) // Core depth texture+shadow, OpenGL 1.4+
|
||||||
{
|
{
|
||||||
|
@ -1054,6 +1067,14 @@ void CGLDevice::UpdateTextureParams(int index)
|
||||||
// Color arg1
|
// Color arg1
|
||||||
if (params.colorArg1 == TEX_MIX_ARG_TEXTURE)
|
if (params.colorArg1 == TEX_MIX_ARG_TEXTURE)
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
|
||||||
|
else if (params.colorArg1 == TEX_MIX_ARG_TEXTURE_0)
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE0);
|
||||||
|
else if (params.colorArg1 == TEX_MIX_ARG_TEXTURE_1)
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE1);
|
||||||
|
else if (params.colorArg1 == TEX_MIX_ARG_TEXTURE_2)
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE2);
|
||||||
|
else if (params.colorArg1 == TEX_MIX_ARG_TEXTURE_3)
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE3);
|
||||||
else if (params.colorArg1 == TEX_MIX_ARG_COMPUTED_COLOR)
|
else if (params.colorArg1 == TEX_MIX_ARG_COMPUTED_COLOR)
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
|
||||||
else if (params.colorArg1 == TEX_MIX_ARG_SRC_COLOR)
|
else if (params.colorArg1 == TEX_MIX_ARG_SRC_COLOR)
|
||||||
|
@ -1065,6 +1086,14 @@ void CGLDevice::UpdateTextureParams(int index)
|
||||||
// Color arg2
|
// Color arg2
|
||||||
if (params.colorArg2 == TEX_MIX_ARG_TEXTURE)
|
if (params.colorArg2 == TEX_MIX_ARG_TEXTURE)
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE);
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE);
|
||||||
|
else if (params.colorArg2 == TEX_MIX_ARG_TEXTURE_0)
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE0);
|
||||||
|
else if (params.colorArg2 == TEX_MIX_ARG_TEXTURE_1)
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE1);
|
||||||
|
else if (params.colorArg2 == TEX_MIX_ARG_TEXTURE_2)
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE2);
|
||||||
|
else if (params.colorArg2 == TEX_MIX_ARG_TEXTURE_3)
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE3);
|
||||||
else if (params.colorArg2 == TEX_MIX_ARG_COMPUTED_COLOR)
|
else if (params.colorArg2 == TEX_MIX_ARG_COMPUTED_COLOR)
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS);
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS);
|
||||||
else if (params.colorArg2 == TEX_MIX_ARG_SRC_COLOR)
|
else if (params.colorArg2 == TEX_MIX_ARG_SRC_COLOR)
|
||||||
|
@ -1097,6 +1126,14 @@ after_tex_color:
|
||||||
// Alpha arg1
|
// Alpha arg1
|
||||||
if (params.alphaArg1 == TEX_MIX_ARG_TEXTURE)
|
if (params.alphaArg1 == TEX_MIX_ARG_TEXTURE)
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
|
||||||
|
else if (params.alphaArg1 == TEX_MIX_ARG_TEXTURE_0)
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE0);
|
||||||
|
else if (params.alphaArg1 == TEX_MIX_ARG_TEXTURE_1)
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE1);
|
||||||
|
else if (params.alphaArg1 == TEX_MIX_ARG_TEXTURE_2)
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE2);
|
||||||
|
else if (params.alphaArg1 == TEX_MIX_ARG_TEXTURE_3)
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE3);
|
||||||
else if (params.alphaArg1 == TEX_MIX_ARG_COMPUTED_COLOR)
|
else if (params.alphaArg1 == TEX_MIX_ARG_COMPUTED_COLOR)
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
|
||||||
else if (params.alphaArg1 == TEX_MIX_ARG_SRC_COLOR)
|
else if (params.alphaArg1 == TEX_MIX_ARG_SRC_COLOR)
|
||||||
|
@ -1108,6 +1145,14 @@ after_tex_color:
|
||||||
// Alpha arg2
|
// Alpha arg2
|
||||||
if (params.alphaArg2 == TEX_MIX_ARG_TEXTURE)
|
if (params.alphaArg2 == TEX_MIX_ARG_TEXTURE)
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE);
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE);
|
||||||
|
else if (params.alphaArg2 == TEX_MIX_ARG_TEXTURE_0)
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE0);
|
||||||
|
else if (params.alphaArg2 == TEX_MIX_ARG_TEXTURE_1)
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE1);
|
||||||
|
else if (params.alphaArg2 == TEX_MIX_ARG_TEXTURE_2)
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE2);
|
||||||
|
else if (params.alphaArg2 == TEX_MIX_ARG_TEXTURE_3)
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE3);
|
||||||
else if (params.alphaArg2 == TEX_MIX_ARG_COMPUTED_COLOR)
|
else if (params.alphaArg2 == TEX_MIX_ARG_COMPUTED_COLOR)
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PREVIOUS);
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PREVIOUS);
|
||||||
else if (params.alphaArg2 == TEX_MIX_ARG_SRC_COLOR)
|
else if (params.alphaArg2 == TEX_MIX_ARG_SRC_COLOR)
|
||||||
|
@ -1728,6 +1773,21 @@ void CGLDevice::SetRenderState(RenderState state, bool enabled)
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if (state == RENDER_STATE_OFFSCREEN_RENDERING)
|
||||||
|
{
|
||||||
|
if (!m_framebufferObject)
|
||||||
|
{
|
||||||
|
GetLogger()->Error("Cannot enable offscreen rendering without framebuffer object!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_framebuffer == 0)
|
||||||
|
InitOffscreenBuffer(2048, 2048);
|
||||||
|
|
||||||
|
GLuint toBind = (enabled ? m_framebuffer : 0);
|
||||||
|
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, toBind);
|
||||||
|
}
|
||||||
|
|
||||||
GLenum flag = 0;
|
GLenum flag = 0;
|
||||||
|
|
||||||
|
@ -1895,6 +1955,42 @@ void CGLDevice::SetFillMode(FillMode mode)
|
||||||
else assert(false);
|
else assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGLDevice::InitOffscreenBuffer(int width, int height)
|
||||||
|
{
|
||||||
|
if (!m_framebufferObject) return;
|
||||||
|
|
||||||
|
width = Math::Min(width, m_maxRenderbufferSize);
|
||||||
|
height = Math::Min(height, m_maxRenderbufferSize);
|
||||||
|
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||||
|
|
||||||
|
if (m_colorBuffer != 0)
|
||||||
|
glDeleteRenderbuffersEXT(1, &m_colorBuffer);
|
||||||
|
|
||||||
|
glGenRenderbuffersEXT(1, &m_colorBuffer);
|
||||||
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_colorBuffer);
|
||||||
|
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, width, height);
|
||||||
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
|
||||||
|
|
||||||
|
if (m_depthBuffer != 0)
|
||||||
|
glDeleteRenderbuffersEXT(1, &m_depthBuffer);
|
||||||
|
|
||||||
|
glGenRenderbuffersEXT(1, &m_depthBuffer);
|
||||||
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBuffer);
|
||||||
|
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height);
|
||||||
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
|
||||||
|
|
||||||
|
if (m_framebuffer == 0)
|
||||||
|
glGenFramebuffersEXT(1, &m_framebuffer);
|
||||||
|
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_framebuffer);
|
||||||
|
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_colorBuffer);
|
||||||
|
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthBuffer);
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||||
|
|
||||||
|
GetLogger()->Info("Initialized offscreen buffer %dx%d\n", width, height);
|
||||||
|
}
|
||||||
|
|
||||||
void CGLDevice::CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, int width, int height)
|
void CGLDevice::CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
if (texture.id == 0) return;
|
if (texture.id == 0) return;
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include "graphics/core/device.h"
|
#include "graphics/core/device.h"
|
||||||
|
#include "GL/glew.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -197,6 +198,8 @@ public:
|
||||||
|
|
||||||
virtual void SetFillMode(FillMode mode) OVERRIDE;
|
virtual void SetFillMode(FillMode mode) OVERRIDE;
|
||||||
|
|
||||||
|
virtual void InitOffscreenBuffer(int width, int height) OVERRIDE;
|
||||||
|
|
||||||
virtual void CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, int width, int height) OVERRIDE;
|
virtual void CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, int width, int height) OVERRIDE;
|
||||||
|
|
||||||
virtual void* GetFrameBufferPixels() const OVERRIDE;
|
virtual void* GetFrameBufferPixels() const OVERRIDE;
|
||||||
|
@ -272,12 +275,24 @@ private:
|
||||||
bool m_anisotropyAvailable;
|
bool m_anisotropyAvailable;
|
||||||
//! Maximum anisotropy level
|
//! Maximum anisotropy level
|
||||||
int m_maxAnisotropy;
|
int m_maxAnisotropy;
|
||||||
|
//! Whether offscreen rendering is available
|
||||||
|
bool m_framebufferObject;
|
||||||
//! Which vertex buffer type to use
|
//! Which vertex buffer type to use
|
||||||
VertexBufferType m_vertexBufferType;
|
VertexBufferType m_vertexBufferType;
|
||||||
//! Map of saved VBO objects
|
//! Map of saved VBO objects
|
||||||
std::map<unsigned int, VboObjectInfo> m_vboObjects;
|
std::map<unsigned int, VboObjectInfo> m_vboObjects;
|
||||||
//! Last ID of VBO object
|
//! Last ID of VBO object
|
||||||
unsigned int m_lastVboId;
|
unsigned int m_lastVboId;
|
||||||
|
|
||||||
|
// Offscreen buffer
|
||||||
|
//! Framebuffer object
|
||||||
|
GLuint m_framebuffer;
|
||||||
|
//! Color renderbuffer
|
||||||
|
GLuint m_colorBuffer;
|
||||||
|
//! Depth renderbuffer
|
||||||
|
GLuint m_depthBuffer;
|
||||||
|
//! Maximum available renderbuffer size
|
||||||
|
int m_maxRenderbufferSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue