mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-21 21:35:38 +00:00
Add supersampling anti-aliasing
Late christmas present. Due to the way alpha works on the model3 adding regular anti-aliasing doesn't really work. Supersampling is very much a brute force solution, render the scene at a higher resolution and mipmap it. It's enabled via command line with the -ss option, for example -ss=4 for 4x supersampling or by adding Supersampling = 4 in the config file. Note non power of two values work as well, so 3 gives a very good balance between speed and quality. 8 will make your GPU bleed, since it is essentially rendering 64 pixels for every visible pixel on the screen.
This commit is contained in:
parent
33b84c89aa
commit
c039d08c03
|
@ -116,6 +116,7 @@ SRC_FILES = \
|
|||
Src/Graphics/New3D/R3DScrollFog.cpp \
|
||||
Src/Graphics/FBO.cpp \
|
||||
Src/Graphics/Render2D.cpp \
|
||||
Src/Graphics/SuperAA.cpp \
|
||||
Src/Model3/TileGen.cpp \
|
||||
Src/Model3/Model3.cpp \
|
||||
Src/CPU/PowerPC/ppc.cpp \
|
||||
|
|
|
@ -17,7 +17,7 @@ public:
|
|||
virtual void UploadTextures(unsigned level, unsigned x, unsigned y, unsigned width, unsigned height) = 0;
|
||||
virtual void AttachMemory(const uint32_t *cullingRAMLoPtr, const uint32_t *cullingRAMHiPtr, const uint32_t *polyRAMPtr, const uint32_t *vromPtr, const uint16_t *textureRAMPtr) = 0;
|
||||
virtual void SetStepping(int stepping) = 0;
|
||||
virtual bool Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXRes, unsigned totalYRes) = 0;
|
||||
virtual bool Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXRes, unsigned totalYRes, unsigned aaTarget) = 0;
|
||||
virtual void SetSunClamp(bool enable) = 0;
|
||||
virtual void SetSignedShade(bool enable) = 0;
|
||||
virtual float GetLosValue(int layer) = 0;
|
||||
|
|
|
@ -963,6 +963,10 @@ void CLegacy3D::RenderFrame(void)
|
|||
|
||||
// Begin frame
|
||||
ClearErrors(); // must be cleared each frame
|
||||
|
||||
if (m_aaTarget) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_aaTarget); // if we have an AA target draw to it instead of the default back buffer
|
||||
}
|
||||
|
||||
// Z buffering (Z buffer is cleared by display list viewport nodes)
|
||||
glDepthFunc(GL_LESS);
|
||||
|
@ -1039,6 +1043,10 @@ void CLegacy3D::RenderFrame(void)
|
|||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
if (m_aaTarget) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0); // restore target if needed
|
||||
}
|
||||
}
|
||||
|
||||
void CLegacy3D::EndFrame(void)
|
||||
|
@ -1089,7 +1097,7 @@ void CLegacy3D::SetStepping(int stepping)
|
|||
DebugLog("Legacy3D set to Step %d.%d\n", (step>>4)&0xF, step&0xF);
|
||||
}
|
||||
|
||||
bool CLegacy3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXResParam, unsigned totalYResParam)
|
||||
bool CLegacy3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXResParam, unsigned totalYResParam, unsigned aaTarget)
|
||||
{
|
||||
// Allocate memory for texture buffer
|
||||
textureBuffer = new(std::nothrow) GLfloat[1024*1024*4];
|
||||
|
@ -1097,6 +1105,8 @@ bool CLegacy3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned
|
|||
return ErrorLog("Insufficient memory for texture decode buffer.");
|
||||
|
||||
glGetError(); // clear error flag
|
||||
|
||||
m_aaTarget = aaTarget;
|
||||
|
||||
// Create model caches and VBOs
|
||||
if (CreateModelCache(&VROMCache, NUM_STATIC_VERTS, NUM_LOCAL_VERTS, NUM_STATIC_MODELS, 0x4000000/4, NUM_DISPLAY_LIST_ITEMS, false))
|
||||
|
@ -1310,7 +1320,8 @@ float CLegacy3D::GetLosValue(int layer)
|
|||
}
|
||||
|
||||
CLegacy3D::CLegacy3D(const Util::Config::Node &config)
|
||||
: m_config(config)
|
||||
: m_config(config),
|
||||
m_aaTarget(0)
|
||||
{
|
||||
cullingRAMLo = NULL;
|
||||
cullingRAMHi = NULL;
|
||||
|
|
|
@ -328,7 +328,7 @@ public:
|
|||
* occurred. Any allocated memory will not be freed until the
|
||||
* destructor is called. Prints own error messages.
|
||||
*/
|
||||
bool Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXRes, unsigned totalYRes);
|
||||
bool Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXRes, unsigned totalYRes, unsigned aaTarget);
|
||||
|
||||
/*
|
||||
* SetSunClamp(bool enable);
|
||||
|
@ -457,6 +457,7 @@ private:
|
|||
GLfloat spotColor[3];
|
||||
GLint viewportX, viewportY;
|
||||
GLint viewportWidth, viewportHeight;
|
||||
GLuint m_aaTarget;
|
||||
|
||||
// Scene graph processing
|
||||
int listDepth; // how many lists have we recursed into
|
||||
|
|
|
@ -22,7 +22,8 @@ CNew3D::CNew3D(const Util::Config::Node &config, const std::string& gameName) :
|
|||
m_r3dScrollFog(config),
|
||||
m_gameName(gameName),
|
||||
m_textureBuffer(0),
|
||||
m_vao(0)
|
||||
m_vao(0),
|
||||
m_aaTarget(0)
|
||||
{
|
||||
m_cullingRAMLo = nullptr;
|
||||
m_cullingRAMHi = nullptr;
|
||||
|
@ -121,7 +122,7 @@ void CNew3D::SetStepping(int stepping)
|
|||
}
|
||||
}
|
||||
|
||||
bool CNew3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXResParam, unsigned totalYResParam)
|
||||
bool CNew3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXResParam, unsigned totalYResParam, unsigned aaTarget)
|
||||
{
|
||||
// Resolution and offset within physical display area
|
||||
m_xRatio = xRes * (float)(1.0 / 496.0);
|
||||
|
@ -132,6 +133,7 @@ bool CNew3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yR
|
|||
m_yRes = yRes;
|
||||
m_totalXRes = totalXResParam;
|
||||
m_totalYRes = totalYResParam;
|
||||
m_aaTarget = aaTarget;
|
||||
|
||||
m_r3dFrameBuffers.DestroyFBO(); // remove any old ones if created
|
||||
m_r3dFrameBuffers.CreateFBO(totalXResParam, totalYResParam);
|
||||
|
@ -440,7 +442,16 @@ void CNew3D::RenderFrame(void)
|
|||
}
|
||||
|
||||
m_r3dFrameBuffers.SetFBO(Layer::none);
|
||||
|
||||
if (m_aaTarget) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_aaTarget); // if we have an AA target draw to it instead of the default back buffer
|
||||
}
|
||||
|
||||
m_r3dFrameBuffers.Draw();
|
||||
|
||||
if (m_aaTarget) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void CNew3D::BeginFrame(void)
|
||||
|
@ -1009,6 +1020,7 @@ void CNew3D::RenderViewport(UINT32 addr)
|
|||
m_planes.bnrv = Util::Uint32AsFloat(vpnode[0x11]);
|
||||
m_planes.bnbu = Util::Uint32AsFloat(vpnode[0x12]);
|
||||
m_planes.bnbw = Util::Uint32AsFloat(vpnode[0x13]);
|
||||
m_planes.correction = 1.0f; // might get changed by the calc viewport method
|
||||
|
||||
vp->angle_left = (0.0f - jo) / cv;
|
||||
vp->angle_right = (1.0f - jo) / cv;
|
||||
|
|
|
@ -141,7 +141,7 @@ public:
|
|||
* occurred. Any allocated memory will not be freed until the
|
||||
* destructor is called. Prints own error messages.
|
||||
*/
|
||||
bool Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXRes, unsigned totalYRes);
|
||||
bool Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXRes, unsigned totalYRes, unsigned aaTarget);
|
||||
|
||||
/*
|
||||
* SetSunClamp(bool enable);
|
||||
|
@ -223,6 +223,7 @@ private:
|
|||
void DisableRenderStates();
|
||||
void TranslateLosPosition(int inX, int inY, int& outX, int& outY);
|
||||
bool ProcessLos(int priority);
|
||||
void CalcViewport(Viewport* vp);
|
||||
|
||||
/*
|
||||
* Data
|
||||
|
@ -286,6 +287,7 @@ private:
|
|||
R3DShader m_r3dShader;
|
||||
R3DScrollFog m_r3dScrollFog;
|
||||
R3DFrameBuffers m_r3dFrameBuffers;
|
||||
GLuint m_aaTarget; // optional, maybe zero
|
||||
|
||||
int m_currentPriority;
|
||||
|
||||
|
@ -300,9 +302,7 @@ private:
|
|||
float bnbu;
|
||||
float bnbw;
|
||||
float correction;
|
||||
} m_planes;
|
||||
|
||||
void CalcViewport (Viewport* vp);
|
||||
} m_planes;
|
||||
};
|
||||
|
||||
} // New3D
|
||||
|
|
|
@ -298,7 +298,6 @@ void R3DFrameBuffers::AllocShaderTrans()
|
|||
|
||||
void R3DFrameBuffers::Draw()
|
||||
{
|
||||
SetFBO (Layer::none); // make sure to draw on the back buffer
|
||||
glViewport (0, 0, m_width, m_height); // cover the entire screen
|
||||
glDisable (GL_DEPTH_TEST); // disable depth testing / writing
|
||||
glDisable (GL_CULL_FACE);
|
||||
|
|
|
@ -310,11 +310,19 @@ void CRender2D::Setup2D(bool isBottom)
|
|||
// Clear everything if requested or just overscan areas for wide screen mode
|
||||
if (isBottom)
|
||||
{
|
||||
if (m_aaTarget) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_aaTarget); // set target if needed
|
||||
}
|
||||
|
||||
glClearColor(0.0, 0.0, 0.0, 0.0);
|
||||
glViewport (0, 0, m_totalXPixels, m_totalYPixels);
|
||||
glDisable (GL_SCISSOR_TEST); // scissor is enabled to fix the 2d/3d miss match problem
|
||||
glClear (GL_COLOR_BUFFER_BIT); // we want to clear outside the scissored areas so must disable it
|
||||
glEnable (GL_SCISSOR_TEST);
|
||||
|
||||
if (m_aaTarget) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0); // restore target if needed
|
||||
}
|
||||
}
|
||||
|
||||
// Set up the viewport and orthogonal projection
|
||||
|
@ -327,6 +335,10 @@ void CRender2D::Setup2D(bool isBottom)
|
|||
|
||||
void CRender2D::DrawSurface(GLuint textureID)
|
||||
{
|
||||
if (m_aaTarget) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_aaTarget); // set target if needed
|
||||
}
|
||||
|
||||
m_shader.EnableShader();
|
||||
|
||||
glEnable (GL_BLEND);
|
||||
|
@ -338,6 +350,10 @@ void CRender2D::DrawSurface(GLuint textureID)
|
|||
glDisable (GL_BLEND);
|
||||
|
||||
m_shader.DisableShader();
|
||||
|
||||
if (m_aaTarget) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0); // restore target if needed
|
||||
}
|
||||
}
|
||||
|
||||
float CRender2D::LineToPercentStart(int lineNumber)
|
||||
|
@ -470,16 +486,17 @@ void CRender2D::AttachVRAM(const uint8_t* vramPtr)
|
|||
DebugLog("Render2D attached VRAM\n");
|
||||
}
|
||||
|
||||
bool CRender2D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXRes, unsigned totalYRes)
|
||||
bool CRender2D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXRes, unsigned totalYRes, unsigned aaTarget)
|
||||
{
|
||||
// Resolution
|
||||
m_xPixels = xRes;
|
||||
m_yPixels = yRes;
|
||||
m_xOffset = xOffset;
|
||||
m_yOffset = yOffset;
|
||||
m_totalXPixels = totalXRes;
|
||||
m_totalYPixels = totalYRes;
|
||||
m_correction = (UINT32)(((yRes / 384.f) * 2) + 0.5f); // for some reason the 2d layer is 2 pixels off the 3D
|
||||
m_xPixels = xRes;
|
||||
m_yPixels = yRes;
|
||||
m_xOffset = xOffset;
|
||||
m_yOffset = yOffset;
|
||||
m_totalXPixels = totalXRes;
|
||||
m_totalYPixels = totalYRes;
|
||||
m_correction = (UINT32)(((yRes / 384.f) * 2) + 0.5f); // for some reason the 2d layer is 2 pixels off the 3D
|
||||
m_aaTarget = aaTarget;
|
||||
|
||||
return OKAY;
|
||||
}
|
||||
|
|
|
@ -158,7 +158,7 @@ public:
|
|||
* OKAY is successful, otherwise FAILED if a non-recoverable error
|
||||
* occurred. Prints own error messages.
|
||||
*/
|
||||
bool Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXRes, unsigned totalYRes);
|
||||
bool Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXRes, unsigned totalYRes, unsigned aaTarget);
|
||||
|
||||
/*
|
||||
* CRender2D(config):
|
||||
|
@ -198,6 +198,7 @@ private:
|
|||
unsigned m_totalXPixels = 0; // total display surface resolution
|
||||
unsigned m_totalYPixels = 0;
|
||||
unsigned m_correction = 0;
|
||||
GLuint m_aaTarget = 0;
|
||||
|
||||
GLuint m_vao;
|
||||
GLSLShader m_shader;
|
||||
|
|
137
Src/Graphics/SuperAA.cpp
Normal file
137
Src/Graphics/SuperAA.cpp
Normal file
|
@ -0,0 +1,137 @@
|
|||
#include "SuperAA.h"
|
||||
#include <string>
|
||||
|
||||
SuperAA::SuperAA(int aaValue) :
|
||||
m_aa(aaValue),
|
||||
m_vao(0),
|
||||
m_width(0),
|
||||
m_height(0)
|
||||
{
|
||||
if (aaValue > 1) {
|
||||
|
||||
const char* vertexShader = R"glsl(
|
||||
|
||||
#version 410 core
|
||||
|
||||
// outputs
|
||||
out vec2 fsTexCoord;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
const vec4 vertices[] = vec4[](vec4(-1.0, -1.0, 0.0, 1.0),
|
||||
vec4(-1.0, 1.0, 0.0, 1.0),
|
||||
vec4( 1.0, -1.0, 0.0, 1.0),
|
||||
vec4( 1.0, 1.0, 0.0, 1.0));
|
||||
|
||||
fsTexCoord = (vertices[gl_VertexID % 4].xy + 1.0) / 2.0;
|
||||
gl_Position = vertices[gl_VertexID % 4];
|
||||
}
|
||||
|
||||
)glsl";
|
||||
|
||||
|
||||
std::string fragmentShaderVersion = R"glsl(
|
||||
#version 410 core
|
||||
|
||||
)glsl";
|
||||
|
||||
std::string aaString = "const int aa = ";
|
||||
aaString += std::to_string(aaValue);
|
||||
aaString += ";\n";
|
||||
|
||||
std::string fragmentShader = R"glsl(
|
||||
|
||||
// inputs
|
||||
uniform sampler2D tex1; // base tex
|
||||
in vec2 fsTexCoord;
|
||||
|
||||
// outputs
|
||||
out vec4 fragColor;
|
||||
|
||||
vec4 GetTextureValue(sampler2D s, vec2 texCoord)
|
||||
{
|
||||
vec2 size = vec2(textureSize(s,0)); // want the values as floats
|
||||
ivec2 texPos = ivec2(size * texCoord);
|
||||
vec4 texColour = vec4(0.0);
|
||||
|
||||
for(int i=0; i < aa; i++) {
|
||||
for(int j=0; j < aa; j++) {
|
||||
texColour += texelFetch(s,ivec2(texPos.x+i,texPos.y+j),0);
|
||||
}
|
||||
}
|
||||
|
||||
texColour /= float(aa * aa);
|
||||
|
||||
return texColour;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
fragColor = GetTextureValue(tex1, fsTexCoord);
|
||||
}
|
||||
|
||||
)glsl";
|
||||
|
||||
std::string fragmentShaderString = fragmentShaderVersion + aaString + fragmentShader;
|
||||
|
||||
// load shaders
|
||||
m_shader.LoadShaders(vertexShader, fragmentShaderString.c_str());
|
||||
m_shader.GetUniformLocationMap("tex1");
|
||||
|
||||
// setup uniform memory
|
||||
m_shader.EnableShader();
|
||||
glUniform1i(m_shader.attribLocMap["tex1"], 0); // texture will be bound to unit zero
|
||||
m_shader.DisableShader();
|
||||
|
||||
glGenVertexArrays(1, &m_vao);
|
||||
glBindVertexArray(m_vao);
|
||||
// no states needed since we do it in the shader
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
}
|
||||
|
||||
// need an active context bound to the current thread to destroy our objects
|
||||
SuperAA::~SuperAA()
|
||||
{
|
||||
m_shader.UnloadShaders();
|
||||
m_fbo.Destroy();
|
||||
|
||||
if (m_vao) {
|
||||
glDeleteVertexArrays(1, &m_vao);
|
||||
m_vao = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SuperAA::Init(int width, int height)
|
||||
{
|
||||
if (m_aa > 1) {
|
||||
m_fbo.Destroy();
|
||||
m_fbo.Create(width * m_aa, height * m_aa);
|
||||
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
}
|
||||
}
|
||||
|
||||
void SuperAA::Draw()
|
||||
{
|
||||
if (m_aa > 1) {
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, m_fbo.GetTextureID());
|
||||
glBindVertexArray(m_vao);
|
||||
glViewport(0, 0, m_width, m_height);
|
||||
m_shader.EnableShader();
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
m_shader.DisableShader();
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
}
|
||||
|
||||
GLuint SuperAA::GetTargetID()
|
||||
{
|
||||
return m_fbo.GetFBOID(); // will return 0 if no render target which will be our default frame buffer (back buffer)
|
||||
}
|
31
Src/Graphics/SuperAA.h
Normal file
31
Src/Graphics/SuperAA.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
|
||||
#include "FBO.h"
|
||||
#include "New3D/GLSLShader.h"
|
||||
|
||||
// This class just implements super sampling. Super sampling looks fantastic but is quite expensive.
|
||||
// 8x and beyond values can start to eat ridiculous amounts of memory / gpu time, for less and less noticable returns
|
||||
// 4x works and looks great
|
||||
// values such as 3 are also possible, that works out 9 samples per pixel
|
||||
// The algorithm is super simple, just add up all samples and divide by the number
|
||||
|
||||
class SuperAA
|
||||
{
|
||||
public:
|
||||
SuperAA(int aaValue);
|
||||
~SuperAA();
|
||||
|
||||
void Init(int width, int height); // width & height are real window dimensions
|
||||
void Draw(); // this is a no-op if AA is 1, since we'll be drawing straight on the back buffer anyway
|
||||
|
||||
GLuint GetTargetID();
|
||||
|
||||
private:
|
||||
FBO m_fbo;
|
||||
GLSLShader m_shader;
|
||||
const int m_aa;
|
||||
GLuint m_vao;
|
||||
int m_width;
|
||||
int m_height;
|
||||
};
|
||||
|
|
@ -35,6 +35,7 @@ class CRender2D;
|
|||
class IRender3D;
|
||||
class CInputs;
|
||||
class COutputs;
|
||||
class SuperAA;
|
||||
|
||||
/*
|
||||
* IEmulator:
|
||||
|
@ -150,7 +151,7 @@ public:
|
|||
* Render2DPtr Pointer to a tile renderer object.
|
||||
* Render3DPtr Same as above but for a 3D renderer.
|
||||
*/
|
||||
virtual void AttachRenderers(CRender2D *Render2DPtr, IRender3D *Render3DPtr) = 0;
|
||||
virtual void AttachRenderers(CRender2D *Render2DPtr, IRender3D *Render3DPtr, SuperAA *superAA) = 0;
|
||||
|
||||
/*
|
||||
* AttachInputs(InputsPtr):
|
||||
|
|
|
@ -2163,6 +2163,7 @@ void CModel3::RenderFrame(void)
|
|||
TileGen.RenderFrameTop();
|
||||
GPU.EndFrame();
|
||||
TileGen.EndFrame();
|
||||
m_superAA->Draw();
|
||||
}
|
||||
|
||||
EndFrameVideo();
|
||||
|
@ -3062,10 +3063,11 @@ bool CModel3::LoadGame(const Game &game, const ROMSet &rom_set)
|
|||
return OKAY;
|
||||
}
|
||||
|
||||
void CModel3::AttachRenderers(CRender2D *Render2DPtr, IRender3D *Render3DPtr)
|
||||
void CModel3::AttachRenderers(CRender2D *Render2DPtr, IRender3D *Render3DPtr, SuperAA *superAA)
|
||||
{
|
||||
TileGen.AttachRenderer(Render2DPtr);
|
||||
GPU.AttachRenderer(Render3DPtr);
|
||||
m_superAA = superAA;
|
||||
}
|
||||
|
||||
void CModel3::AttachInputs(CInputs *InputsPtr)
|
||||
|
@ -3209,7 +3211,8 @@ CModel3::CModel3(Util::Config::Node &config)
|
|||
TileGen(config),
|
||||
GPU(config),
|
||||
SoundBoard(config),
|
||||
m_jtag(GPU)
|
||||
m_jtag(GPU),
|
||||
m_superAA(nullptr)
|
||||
{
|
||||
// Initialize pointers so dtor can know whether to free them
|
||||
memoryPool = NULL;
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
#include "Network/INetBoard.h"
|
||||
#endif // NET_BOARD
|
||||
#include "Util/NewConfig.h"
|
||||
#include "Graphics/SuperAA.h"
|
||||
|
||||
|
||||
/*
|
||||
* FrameTimings
|
||||
|
@ -92,7 +94,7 @@ public:
|
|||
void RenderFrame(void);
|
||||
void Reset(void);
|
||||
const Game &GetGame(void) const;
|
||||
void AttachRenderers(CRender2D *Render2DPtr, IRender3D *Render3DPtr);
|
||||
void AttachRenderers(CRender2D *Render2DPtr, IRender3D *Render3DPtr, SuperAA *superAA);
|
||||
void AttachInputs(CInputs *InputsPtr);
|
||||
void AttachOutputs(COutputs *OutputsPtr);
|
||||
bool Init(void);
|
||||
|
@ -321,6 +323,7 @@ private:
|
|||
CDriveBoard *DriveBoard; // Drive board
|
||||
CCrypto m_cryptoDevice; // Encryption device
|
||||
CJTAG m_jtag; // JTAG interface
|
||||
SuperAA *m_superAA;
|
||||
#ifdef NET_BOARD
|
||||
INetBoard *NetBoard; // Net board
|
||||
bool m_runNetBoard;
|
||||
|
|
|
@ -94,6 +94,7 @@
|
|||
#include "Model3/Model3.h"
|
||||
#include "OSD/Audio.h"
|
||||
#include "Graphics/New3D/VBO.h"
|
||||
#include "Graphics/SuperAA.h"
|
||||
|
||||
#include <iostream>
|
||||
#include "Util/BMPFile.h"
|
||||
|
@ -122,6 +123,7 @@ SDL_Window *s_window = nullptr;
|
|||
static unsigned xOffset, yOffset; // offset of renderer output within OpenGL viewport
|
||||
static unsigned xRes, yRes; // renderer output resolution (can be smaller than GL viewport)
|
||||
static unsigned totalXRes, totalYRes; // total resolution (the whole GL viewport)
|
||||
static int aaValue = 1; // default is 1 which is no aa
|
||||
|
||||
/*
|
||||
* Crosshair stuff
|
||||
|
@ -185,11 +187,11 @@ static bool SetGLGeometry(unsigned *xOffsetPtr, unsigned *yOffsetPtr, unsigned *
|
|||
// Scissor box (to clip visible area)
|
||||
if (s_runtime_config["WideScreen"].ValueAsDefault<bool>(false))
|
||||
{
|
||||
glScissor(0, correction, *totalXResPtr, *totalYResPtr - (correction * 2));
|
||||
glScissor(0* aaValue, correction* aaValue, *totalXResPtr * aaValue, (*totalYResPtr - (correction * 2)) * aaValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
glScissor(*xOffsetPtr + correction, *yOffsetPtr + correction, *xResPtr - (correction * 2), *yResPtr - (correction * 2));
|
||||
glScissor((*xOffsetPtr + correction) * aaValue, (*yOffsetPtr + correction) * aaValue, (*xResPtr - (correction * 2)) * aaValue, (*yResPtr - (correction * 2)) * aaValue);
|
||||
}
|
||||
return OKAY;
|
||||
}
|
||||
|
@ -971,13 +973,17 @@ int Supermodel(const Game &game, ROMSet *rom_set, IEmulator *Model3, CInputs *In
|
|||
uint64_t nextTime = 0;
|
||||
|
||||
// Initialize the renderers
|
||||
SuperAA* superAA = new SuperAA(aaValue);
|
||||
superAA->Init(totalXRes, totalYRes); // pass actual frame sizes here
|
||||
CRender2D *Render2D = new CRender2D(s_runtime_config);
|
||||
IRender3D *Render3D = s_runtime_config["New3DEngine"].ValueAs<bool>() ? ((IRender3D *) new New3D::CNew3D(s_runtime_config, Model3->GetGame().name)) : ((IRender3D *) new Legacy3D::CLegacy3D(s_runtime_config));
|
||||
if (OKAY != Render2D->Init(xOffset, yOffset, xRes, yRes, totalXRes, totalYRes))
|
||||
|
||||
if (OKAY != Render2D->Init(xOffset*aaValue, yOffset*aaValue, xRes*aaValue, yRes*aaValue, totalXRes*aaValue, totalYRes*aaValue, superAA->GetTargetID()))
|
||||
goto QuitError;
|
||||
if (OKAY != Render3D->Init(xOffset, yOffset, xRes, yRes, totalXRes, totalYRes))
|
||||
if (OKAY != Render3D->Init(xOffset*aaValue, yOffset*aaValue, xRes*aaValue, yRes*aaValue, totalXRes*aaValue, totalYRes*aaValue, superAA->GetTargetID()))
|
||||
goto QuitError;
|
||||
Model3->AttachRenderers(Render2D,Render3D);
|
||||
|
||||
Model3->AttachRenderers(Render2D,Render3D, superAA);
|
||||
|
||||
// Reset emulator
|
||||
Model3->Reset();
|
||||
|
@ -1105,8 +1111,8 @@ int Supermodel(const Game &game, ROMSet *rom_set, IEmulator *Model3, CInputs *In
|
|||
// Delete renderers and recreate them afterwards since GL context will most likely be lost when switching from/to fullscreen
|
||||
delete Render2D;
|
||||
delete Render3D;
|
||||
Render2D = NULL;
|
||||
Render3D = NULL;
|
||||
Render2D = nullptr;
|
||||
Render3D = nullptr;
|
||||
|
||||
// Resize screen
|
||||
totalXRes = xRes = s_runtime_config["XResolution"].ValueAs<unsigned>();
|
||||
|
@ -1117,13 +1123,15 @@ int Supermodel(const Game &game, ROMSet *rom_set, IEmulator *Model3, CInputs *In
|
|||
goto QuitError;
|
||||
|
||||
// Recreate renderers and attach to the emulator
|
||||
superAA->Init(totalXRes, totalYRes);
|
||||
Render2D = new CRender2D(s_runtime_config);
|
||||
Render3D = s_runtime_config["New3DEngine"].ValueAs<bool>() ? ((IRender3D *) new New3D::CNew3D(s_runtime_config, Model3->GetGame().name)) : ((IRender3D *) new Legacy3D::CLegacy3D(s_runtime_config));
|
||||
if (OKAY != Render2D->Init(xOffset, yOffset, xRes, yRes, totalXRes, totalYRes))
|
||||
if (OKAY != Render2D->Init(xOffset * aaValue, yOffset * aaValue, xRes * aaValue, yRes * aaValue, totalXRes * aaValue, totalYRes * aaValue, superAA->GetTargetID()))
|
||||
goto QuitError;
|
||||
if (OKAY != Render3D->Init(xOffset, yOffset, xRes, yRes, totalXRes, totalYRes))
|
||||
if (OKAY != Render3D->Init(xOffset * aaValue, yOffset * aaValue, xRes * aaValue, yRes * aaValue, totalXRes * aaValue, totalYRes * aaValue, superAA->GetTargetID()))
|
||||
goto QuitError;
|
||||
Model3->AttachRenderers(Render2D,Render3D);
|
||||
|
||||
Model3->AttachRenderers(Render2D, Render3D, superAA);
|
||||
|
||||
Render3D->UploadTextures(0, 0, 0, 2048, 2048); // sync texture memory
|
||||
|
||||
|
@ -1331,6 +1339,7 @@ int Supermodel(const Game &game, ROMSet *rom_set, IEmulator *Model3, CInputs *In
|
|||
// Shut down renderers
|
||||
delete Render2D;
|
||||
delete Render3D;
|
||||
delete superAA;
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -1338,6 +1347,8 @@ int Supermodel(const Game &game, ROMSet *rom_set, IEmulator *Model3, CInputs *In
|
|||
QuitError:
|
||||
delete Render2D;
|
||||
delete Render3D;
|
||||
delete superAA;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1478,7 +1489,7 @@ static Util::Config::Node DefaultConfig()
|
|||
config.SetEmpty("WindowYPosition");
|
||||
config.Set("FullScreen", false);
|
||||
config.Set("BorderlessWindow", false);
|
||||
|
||||
config.Set("Supersampling", 1);
|
||||
config.Set("WideScreen", false);
|
||||
config.Set("Stretch", false);
|
||||
config.Set("WideBackground", false);
|
||||
|
@ -1558,6 +1569,7 @@ static void Help(void)
|
|||
puts("");
|
||||
puts("Video Options:");
|
||||
puts(" -res=<x>,<y> Resolution [Default: 496,384]");
|
||||
puts(" -ss=<n> Supersampling (range 1-8)");
|
||||
puts(" -window-pos=<x>,<y> Window position [Default: centered]");
|
||||
puts(" -window Windowed mode [Default]");
|
||||
puts(" -borderless Windowed mode with no border");
|
||||
|
@ -1819,6 +1831,29 @@ static ParsedCommandLine ParseCommandLine(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (arg == "-ss" || arg.find("-ss=") == 0) {
|
||||
|
||||
std::vector<std::string> parts = Util::Format(arg).Split('=');
|
||||
|
||||
if (parts.size() != 2)
|
||||
{
|
||||
ErrorLog("'-ss' requires an integer argument (e.g., '-ss=2').");
|
||||
cmd_line.error = true;
|
||||
}
|
||||
else {
|
||||
|
||||
try {
|
||||
int val = std::stoi(parts[1]);
|
||||
val = std::clamp(val, 1, 8);
|
||||
|
||||
cmd_line.config.Set("Supersampling", val);
|
||||
}
|
||||
catch (...) {
|
||||
ErrorLog("'-ss' requires an integer argument (e.g., '-ss=2').");
|
||||
cmd_line.error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (arg == "-true-hz")
|
||||
cmd_line.config.Set("RefreshRate", 57.524f);
|
||||
else if (arg == "-print-gl-info")
|
||||
|
@ -1967,6 +2002,8 @@ int main(int argc, char **argv)
|
|||
#endif // SUPERMODEL_DEBUGGER
|
||||
std::string selectedInputSystem = s_runtime_config["InputSystem"].ValueAs<std::string>();
|
||||
|
||||
aaValue = s_runtime_config["Supersampling"].ValueAs<int>();
|
||||
|
||||
// Create a window
|
||||
xRes = 496;
|
||||
yRes = 384;
|
||||
|
|
|
@ -328,6 +328,7 @@ xcopy /D /Y "$(ProjectDir)..\Assets\*" "$(TargetDir)Assets"</Command>
|
|||
<ClCompile Include="..\Src\Graphics\New3D\Vec.cpp" />
|
||||
<ClCompile Include="..\Src\Graphics\Render2D.cpp" />
|
||||
<ClCompile Include="..\Src\Graphics\Shader.cpp" />
|
||||
<ClCompile Include="..\Src\Graphics\SuperAA.cpp" />
|
||||
<ClCompile Include="..\Src\Inputs\Input.cpp" />
|
||||
<ClCompile Include="..\Src\Inputs\Inputs.cpp" />
|
||||
<ClCompile Include="..\Src\Inputs\InputSource.cpp" />
|
||||
|
@ -507,6 +508,7 @@ xcopy /D /Y "$(ProjectDir)..\Assets\*" "$(TargetDir)Assets"</Command>
|
|||
<ClInclude Include="..\Src\Graphics\Render2D.h" />
|
||||
<ClInclude Include="..\Src\Graphics\Shader.h" />
|
||||
<ClInclude Include="..\Src\Graphics\Shaders2D.h" />
|
||||
<ClInclude Include="..\Src\Graphics\SuperAA.h" />
|
||||
<ClInclude Include="..\Src\Inputs\Input.h" />
|
||||
<ClInclude Include="..\Src\Inputs\Inputs.h" />
|
||||
<ClInclude Include="..\Src\Inputs\InputSource.h" />
|
||||
|
|
|
@ -470,6 +470,9 @@
|
|||
<ClCompile Include="..\Src\Graphics\FBO.cpp">
|
||||
<Filter>Source Files\Graphics</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Src\Graphics\SuperAA.cpp">
|
||||
<Filter>Source Files\Graphics</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<MASM Include="..\Src\CPU\68K\Turbo68K\Turbo68K.asm">
|
||||
|
@ -856,6 +859,9 @@
|
|||
<ClInclude Include="..\Src\Graphics\New3D\R3DShaderCommon.h">
|
||||
<Filter>Header Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\SuperAA.h">
|
||||
<Filter>Header Files\Graphics</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="..\Src\Debugger\ReadMe.txt">
|
||||
|
|
Loading…
Reference in a new issue