1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-07-02 09:03:37 +00:00

Implement render to depth buffer.

Fixed shadows in Pilot Wings.
Removed special texrect for NFL Quaterback 98 monitor: it is now supported by general code
This commit is contained in:
Sergey Lipskiy 2016-05-08 17:25:22 +06:00
parent 8ab1ca7468
commit ccff245f85
8 changed files with 141 additions and 29 deletions

View File

@ -17,34 +17,44 @@ const GLuint TlutImageUnit = 1;
const GLuint depthImageUnit = 2;
DepthBuffer::DepthBuffer() : m_address(0), m_width(0), m_uly(0), m_lry(0),
m_FBO(0), m_pDepthImageTexture(NULL), m_pDepthBufferTexture(NULL),
m_cleared(false), m_pResolveDepthBufferTexture(NULL), m_resolved(false)
m_depthImageFBO(0), m_pDepthImageTexture(NULL), m_pDepthBufferTexture(NULL),
m_cleared(false), m_pResolveDepthBufferTexture(NULL), m_resolved(false),
m_pDepthBufferCopyTexture(NULL), m_copied(false)
{
glGenFramebuffers(1, &m_FBO);
glGenFramebuffers(1, &m_copyFBO);
if (video().getRender().isImageTexturesSupported() && config.frameBufferEmulation.N64DepthCompare != 0)
glGenFramebuffers(1, &m_depthImageFBO);
}
DepthBuffer::DepthBuffer(DepthBuffer && _other) :
m_address(_other.m_address), m_width(_other.m_width), m_uly(_other.m_uly), m_lry(_other.m_lry),
m_FBO(_other.m_FBO), m_pDepthImageTexture(_other.m_pDepthImageTexture), m_pDepthBufferTexture(_other.m_pDepthBufferTexture),
m_cleared(_other.m_cleared), m_pResolveDepthBufferTexture(_other.m_pResolveDepthBufferTexture), m_resolved(_other.m_resolved)
m_depthImageFBO(_other.m_depthImageFBO), m_pDepthImageTexture(_other.m_pDepthImageTexture), m_pDepthBufferTexture(_other.m_pDepthBufferTexture),
m_cleared(_other.m_cleared), m_pResolveDepthBufferTexture(_other.m_pResolveDepthBufferTexture), m_resolved(_other.m_resolved),
m_pDepthBufferCopyTexture(_other.m_pDepthBufferCopyTexture), m_copied(m_copied)
{
_other.m_FBO = 0;
_other.m_depthImageFBO = 0;
_other.m_pDepthImageTexture = NULL;
_other.m_pDepthBufferTexture = NULL;
_other.m_pResolveDepthBufferTexture = NULL;
_other.m_resolved = false;
_other.m_pDepthBufferCopyTexture = NULL;
_other.m_copied = false;
}
DepthBuffer::~DepthBuffer()
{
if (m_FBO != 0)
glDeleteFramebuffers(1, &m_FBO);
if (m_depthImageFBO != 0)
glDeleteFramebuffers(1, &m_depthImageFBO);
if (m_pDepthImageTexture != NULL)
textureCache().removeFrameBufferTexture(m_pDepthImageTexture);
if (m_pDepthBufferTexture != NULL)
textureCache().removeFrameBufferTexture(m_pDepthBufferTexture);
if (m_pResolveDepthBufferTexture != NULL)
textureCache().removeFrameBufferTexture(m_pResolveDepthBufferTexture);
if (m_copyFBO != 0)
glDeleteFramebuffers(1, &m_copyFBO);
if (m_pDepthBufferCopyTexture != NULL)
textureCache().removeFrameBufferTexture(m_pDepthBufferCopyTexture);
}
void DepthBuffer::initDepthImageTexture(FrameBuffer * _pBuffer)
@ -81,7 +91,7 @@ void DepthBuffer::initDepthImageTexture(FrameBuffer * _pBuffer)
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_depthImageFBO);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pDepthImageTexture->glName, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _pBuffer->m_FBO);
@ -163,6 +173,7 @@ void DepthBuffer::setDepthAttachment(GLenum _target)
else
#endif
glFramebufferTexture2D(_target, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_pDepthBufferTexture->glName, 0);
m_copied = false;
m_resolved = false;
}
@ -212,6 +223,47 @@ CachedTexture * DepthBuffer::resolveDepthBufferTexture(FrameBuffer * _pBuffer)
#endif
}
#ifndef GLES2
CachedTexture * DepthBuffer::copyDepthBufferTexture(FrameBuffer * _pBuffer)
{
if (m_copied)
return m_pDepthBufferCopyTexture;
if (m_pDepthBufferCopyTexture == NULL) {
m_pDepthBufferCopyTexture = textureCache().addFrameBufferTexture();
_initDepthBufferTexture(_pBuffer, m_pDepthBufferCopyTexture, false);
}
glScissor(0, 0, m_pDepthBufferTexture->realWidth, m_pDepthBufferTexture->realHeight);
glBindFramebuffer(GL_READ_FRAMEBUFFER, _pBuffer->m_FBO);
glReadBuffer(GL_COLOR_ATTACHMENT0);
assert(checkFBO());
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_copyFBO);
#ifdef GL_MULTISAMPLING_SUPPORT
GLenum textarget = config.video.multisampling != 0 ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
#else
GLenum textarget = GL_TEXTURE_2D;
#endif
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
textarget,
_pBuffer->m_pTexture->glName,
0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_pDepthBufferCopyTexture->glName, 0);
assert(checkFBO());
glBlitFramebuffer(
0, 0, m_pDepthBufferTexture->realWidth, m_pDepthBufferTexture->realHeight,
0, 0, m_pDepthBufferTexture->realWidth, m_pDepthBufferTexture->realHeight,
GL_DEPTH_BUFFER_BIT, GL_NEAREST
);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _pBuffer->m_FBO);
m_copied = true;
gDP.changed |= CHANGED_SCISSOR;
return m_pDepthBufferCopyTexture;
}
#endif
void DepthBuffer::activateDepthBufferTexture(FrameBuffer * _pBuffer)
{
textureCache().activateTexture(0, resolveDepthBufferTexture(_pBuffer));
@ -335,11 +387,11 @@ void DepthBufferList::clearBuffer(u32 _uly, u32 _lry)
m_pCurrent->m_uly = _uly;
m_pCurrent->m_lry = _lry;
#ifdef GL_IMAGE_TEXTURES_SUPPORT
if (m_pCurrent->m_FBO == 0 || !video().getRender().isImageTexturesSupported() || config.frameBufferEmulation.N64DepthCompare == 0)
if (m_pCurrent->m_depthImageFBO == 0 || !video().getRender().isImageTexturesSupported() || config.frameBufferEmulation.N64DepthCompare == 0)
return;
float color[4] = {1.0f, 1.0f, 0.0f, 1.0f};
glBindImageTexture(depthImageUnit, 0, 0, GL_FALSE, 0, GL_READ_WRITE, fboFormats.depthImageInternalFormat);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_pCurrent->m_FBO);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_pCurrent->m_depthImageFBO);
const u32 cycleType = gDP.otherMode.cycleType;
gDP.otherMode.cycleType = G_CYC_FILL;
video().getRender().drawRect(0,0,VI.width, VI.height, color);

View File

@ -13,6 +13,7 @@ struct DepthBuffer
void initDepthImageTexture(FrameBuffer * _pBuffer);
void initDepthBufferTexture(FrameBuffer * _pBuffer);
CachedTexture * resolveDepthBufferTexture(FrameBuffer * _pBuffer);
CachedTexture * copyDepthBufferTexture(FrameBuffer * _pBuffer);
void setDepthAttachment(GLenum _target);
void activateDepthBufferTexture(FrameBuffer * _pBuffer);
@ -21,16 +22,21 @@ struct DepthBuffer
u32 m_address, m_width;
u32 m_uly, m_lry; // Top and bottom bounds of fillrect command.
GLuint m_FBO;
GLuint m_depthImageFBO;
CachedTexture *m_pDepthImageTexture;
CachedTexture *m_pDepthBufferTexture;
bool m_cleared;
// multisampling
CachedTexture *m_pResolveDepthBufferTexture;
bool m_resolved;
// render to depth buffer
GLuint m_copyFBO;
CachedTexture *m_pDepthBufferCopyTexture;
bool m_copied;
private:
void _initDepthBufferTexture(FrameBuffer * _pBuffer, CachedTexture *_pTexture, bool _multisample);
void _DepthBufferTexture(FrameBuffer * _pBuffer);
};
class DepthBufferList

View File

@ -21,6 +21,7 @@ public:
void updateAlphaTestInfo(bool _bForce = false);
void updateTextureInfo(bool _bForce = false);
void updateRenderState(bool _bForce = false);
void updateRenderTarget(bool _bForce = false);
void updateScreenCoordsScale(bool _bForce = false);
void updateBlendMode(bool _bForce = false);
void disableBlending();
@ -110,13 +111,14 @@ private:
struct UniformLocation
{
iUniform uTex0, uTex1, uMSTex0, uMSTex1, uTexNoise, uTlutImage, uZlutImage, uDepthImage,
iUniform uTex0, uTex1, uMSTex0, uMSTex1, uDepthTex,
uTexNoise, uTlutImage, uZlutImage, uDepthImage,
uFogUsage, uEnableLod, uEnableAlphaTest,
uEnableDepth, uEnableDepthCompare, uEnableDepthUpdate,
uDepthMode, uDepthSource, uRenderState,
uMaxTile, uTextureDetail, uTexturePersp, uTextureFilterMode, uMSAASamples,
uAlphaCompareMode, uAlphaDitherMode, uColorDitherMode,
uCvgXAlpha, uAlphaCvgSel,
uCvgXAlpha, uAlphaCvgSel, uRenderTarget,
uForceBlendCycle1, uForceBlendCycle2;
fUniform uMinLod, uDeltaZ, uAlphaTestValue, uMSAAScale;

View File

@ -398,6 +398,22 @@ ShaderCombiner::ShaderCombiner(Combiner & _color, Combiner & _alpha, const gDPCo
if (video().getRender().isImageTexturesSupported() && config.frameBufferEmulation.N64DepthCompare != 0)
strFragmentShader.append(" if (!depth_compare()) discard; \n");
strFragmentShader.append(
#ifdef GLESX
"#ifdef GL_NV_fragdepth \n"
#endif
" if (uRenderTarget != 0) { \n"
" if (uRenderTarget > 1) { \n"
" ivec2 coord = ivec2(gl_FragCoord.xy); \n"
" if (gl_FragDepth >= texelFetch(uDepthTex, coord, 0).r) discard; \n"
" } \n"
" gl_FragDepth = fragColor.r; \n"
" } \n"
#ifdef GLESX
"#endif \n"
#endif
);
strFragmentShader.append(fragment_shader_end);
if (config.generalEmulation.enableNoise == 0)
@ -480,6 +496,7 @@ ShaderCombiner::~ShaderCombiner() {
void ShaderCombiner::_locateUniforms() {
LocateUniform(uTex0);
LocateUniform(uTex1);
LocateUniform(uDepthTex);
LocateUniform(uTexNoise);
LocateUniform(uTlutImage);
LocateUniform(uZlutImage);
@ -490,6 +507,7 @@ void ShaderCombiner::_locateUniforms() {
LocateUniform(uColorDitherMode);
LocateUniform(uCvgXAlpha);
LocateUniform(uAlphaCvgSel);
LocateUniform(uRenderTarget);
LocateUniform(uEnableLod);
LocateUniform(uEnableAlphaTest);
LocateUniform(uEnableDepth);
@ -545,6 +563,7 @@ void ShaderCombiner::update(bool _bForce) {
if (_bForce) {
m_uniforms.uTexNoise.set(g_noiseTexIndex, true);
m_uniforms.uDepthTex.set(g_depthTexIndex, true);
if (usesTexture()) {
m_uniforms.uTex0.set(0, true);
m_uniforms.uTex1.set(1, true);
@ -568,6 +587,7 @@ void ShaderCombiner::update(bool _bForce) {
updateTextureInfo(_bForce);
updateAlphaTestInfo(_bForce);
updateDepthInfo(_bForce);
updateRenderTarget(_bForce);
updateScreenCoordsScale(_bForce);
}
@ -576,6 +596,20 @@ void ShaderCombiner::updateRenderState(bool _bForce)
m_uniforms.uRenderState.set(video().getRender().getRenderState(), _bForce);
}
void ShaderCombiner::updateRenderTarget(bool _bForce)
{
int renderTarget = 0;
if (gDP.colorImage.address == gDP.depthImageAddress &&
gDP.otherMode.cycleType != G_CYC_FILL &&
(config.generalEmulation.hacks & hack_ZeldaMM) == 0
) {
FrameBuffer * pCurBuf = frameBufferList().getCurrent();
if (pCurBuf != nullptr && pCurBuf->m_pDepthBuffer != nullptr)
renderTarget = gDP.otherMode.depthCompare + 1;
}
m_uniforms.uRenderTarget.set(renderTarget, _bForce);
}
void ShaderCombiner::updateScreenCoordsScale(bool _bForce)
{
FrameBuffer * pCurrentBuffer = frameBufferList().getCurrent();

View File

@ -142,6 +142,7 @@ static const char* fragment_shader_header_common_variables =
MAIN_SHADER_VERSION
"uniform sampler2D uTex0; \n"
"uniform sampler2D uTex1; \n"
"uniform sampler2D uDepthTex; \n"
"layout (std140) uniform ColorsBlock {\n"
" lowp vec4 uFogColor; \n"
" lowp vec4 uCenterColor; \n"
@ -164,6 +165,7 @@ MAIN_SHADER_VERSION
"uniform lowp int uEnableAlphaTest; \n"
"uniform lowp int uCvgXAlpha; \n"
"uniform lowp int uAlphaCvgSel; \n"
"uniform lowp int uRenderTarget; \n"
"uniform lowp float uAlphaTestValue;\n"
"uniform mediump vec2 uDepthScale; \n"
"uniform lowp ivec4 uBlendMux1; \n"
@ -189,6 +191,7 @@ static const char* fragment_shader_header_common_variables_ms_tex1 =
static const char* fragment_shader_header_common_variables_notex =
MAIN_SHADER_VERSION
"uniform sampler2D uDepthTex; \n"
"layout (std140) uniform ColorsBlock {\n"
" lowp vec4 uFogColor; \n"
" lowp vec4 uCenterColor; \n"
@ -209,6 +212,7 @@ MAIN_SHADER_VERSION
"uniform lowp int uEnableAlphaTest; \n"
"uniform lowp int uCvgXAlpha; \n"
"uniform lowp int uAlphaCvgSel; \n"
"uniform lowp int uRenderTarget; \n"
"uniform lowp float uAlphaTestValue;\n"
"uniform mediump vec2 uDepthScale; \n"
"uniform lowp ivec4 uBlendMux1; \n"

View File

@ -685,6 +685,31 @@ void OGLRender::_updateStates(RENDER_STATE _renderState) const
}
cmbInfo.updateParameters(_renderState);
#ifndef GLES2
if (gDP.colorImage.address == gDP.depthImageAddress &&
gDP.otherMode.cycleType != G_CYC_FILL &&
(config.generalEmulation.hacks & hack_ZeldaMM) == 0
) {
FrameBuffer * pCurBuf = frameBufferList().getCurrent();
if (pCurBuf != nullptr && pCurBuf->m_pDepthBuffer != nullptr) {
if (gDP.otherMode.depthCompare != 0) {
CachedTexture * pDepthTexture = pCurBuf->m_pDepthBuffer->copyDepthBufferTexture(pCurBuf);
if (pDepthTexture == nullptr)
return;
glActiveTexture(GL_TEXTURE0 + g_depthTexIndex);
glBindTexture(GL_TEXTURE_2D, pDepthTexture->glName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_ALWAYS);
glDepthMask(TRUE);
gDP.changed |= CHANGED_RENDERMODE;
}
}
#endif
}
void OGLRender::_setColorArray() const
@ -818,6 +843,7 @@ void OGLRender::drawTriangles()
_prepareDrawTriangle(false);
glDrawElements(GL_TRIANGLES, triangles.num, GL_UNSIGNED_BYTE, triangles.elements);
// glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
triangles.num = 0;
}
@ -978,18 +1004,6 @@ bool texturedRectDepthBufferCopy(const OGLRender::TexturedRectParams & _params)
return false;
}
static
bool texturedRectDepthBufferRender(const OGLRender::TexturedRectParams & _params)
{
if (gDP.colorImage.address == gDP.depthImageAddress) {
FrameBuffer * pCurBuf = frameBufferList().getCurrent();
if (pCurBuf == nullptr || pCurBuf->m_pDepthBuffer == nullptr)
return true;
return !SetDepthTextureCombiner();
}
return false;
}
static
bool texturedRectCopyToItself(const OGLRender::TexturedRectParams & _params)
{
@ -1537,8 +1551,6 @@ void OGLRender::_setSpecialTexrect() const
texturedRectSpecial = texturedRectPaletteMod;
else if (strstr(name, (const char *)"ZELDA"))
texturedRectSpecial = texturedRectMonochromeBackground;
else if (strstr(name, (const char *)"quarterback_club_98"))
texturedRectSpecial = texturedRectDepthBufferRender;
else
texturedRectSpecial = NULL;
}

View File

@ -20,7 +20,8 @@
using namespace std;
const GLuint g_noiseTexIndex = 2;
const GLuint g_MSTex0Index = g_noiseTexIndex + 1;
const GLuint g_depthTexIndex = g_noiseTexIndex + 1;
const GLuint g_MSTex0Index = g_depthTexIndex + 1;
inline u32 GetNone( u64 *src, u16 x, u16 i, u8 palette )
{

View File

@ -7,6 +7,7 @@
#include "convert.h"
extern const GLuint g_noiseTexIndex;
extern const GLuint g_depthTexIndex;
extern const GLuint g_MSTex0Index;
typedef u32 (*GetTexelFunc)( u64 *src, u16 x, u16 i, u8 palette );