mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 15:45:38 +00:00
"Fixed" the long-time weird rendering artifacts that are apparently caused by vertex coordinates not being integers.
A better fix would be to move to OpenGL 3/GLES 2 and do rounding in the shader. But I don't have time for that.
This commit is contained in:
parent
daa62123d1
commit
07edad611f
10
DEVNOTES.md
10
DEVNOTES.md
|
@ -33,3 +33,13 @@ Creating a new GameListView Class
|
|||
=================================
|
||||
|
||||
1. Don't allow the user to navigate to the root node's parent. If you use a stack of some sort to keep track of past cursor states this will be a natural side effect.
|
||||
|
||||
|
||||
|
||||
Creating a new Component
|
||||
========================
|
||||
|
||||
If your component is not made up of other components, and you draw something to the screen with OpenGL, make sure:
|
||||
|
||||
* Your vertex positions are rounded before you render (you can use round(float) in Util.h to do this).
|
||||
* Your transform matrix's translation is rounded (you can use roundMatrix(affine3f) in Util.h to do this).
|
|
@ -38,6 +38,7 @@ namespace Renderer
|
|||
void setMatrix(const Eigen::Affine3f& transform);
|
||||
|
||||
void drawRect(int x, int y, int w, int h, unsigned int color, GLenum blend_sfactor = GL_SRC_ALPHA, GLenum blend_dfactor = GL_ONE_MINUS_SRC_ALPHA);
|
||||
void drawRect(float x, float y, float w, float h, unsigned int color, GLenum blend_sfactor = GL_SRC_ALPHA, GLenum blend_dfactor = GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <boost/filesystem.hpp>
|
||||
#include "Log.h"
|
||||
#include <stack>
|
||||
#include "Util.h"
|
||||
|
||||
namespace Renderer {
|
||||
std::stack<Eigen::Vector4i> clipStack;
|
||||
|
@ -87,6 +88,11 @@ namespace Renderer {
|
|||
}
|
||||
}
|
||||
|
||||
void drawRect(float x, float y, float w, float h, unsigned int color, GLenum blend_sfactor, GLenum blend_dfactor)
|
||||
{
|
||||
drawRect((int)round(x), (int)round(y), (int)round(w), (int)round(h), color, blend_sfactor, blend_dfactor);
|
||||
}
|
||||
|
||||
void drawRect(int x, int y, int w, int h, unsigned int color, GLenum blend_sfactor, GLenum blend_dfactor)
|
||||
{
|
||||
#ifdef USE_OPENGL_ES
|
||||
|
|
|
@ -43,6 +43,10 @@ namespace Renderer
|
|||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
|
||||
// multisample anti-aliasing
|
||||
//SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
|
||||
//SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 2);
|
||||
|
||||
#ifdef USE_OPENGL_ES
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
|
||||
#endif
|
||||
|
@ -91,12 +95,6 @@ namespace Renderer
|
|||
|
||||
sdlContext = SDL_GL_CreateContext(sdlWindow);
|
||||
|
||||
//usually display width/height are not specified, i.e. zero, which SDL automatically takes as "native resolution"
|
||||
//so, since other things rely on the size of the screen (damn currently unnormalized coordinate system), we set it here
|
||||
//even though the system was already initialized - this makes sure it gets reinitialized to the original resolution when we return from a game
|
||||
//display_width = sdlWindow->w;
|
||||
//display_height = sdlWindow->h;
|
||||
|
||||
//hide mouse cursor
|
||||
initialCursorState = SDL_ShowCursor(0) == 1;
|
||||
|
||||
|
|
38
src/Util.cpp
38
src/Util.cpp
|
@ -19,4 +19,40 @@ std::string& strToUpper(std::string& str)
|
|||
std::string strToUpper(const std::string& str)
|
||||
{
|
||||
return strToUpper(str.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
float round(float num)
|
||||
{
|
||||
return (float)((int)(num + 0.5f));
|
||||
}
|
||||
|
||||
Eigen::Affine3f& roundMatrix(Eigen::Affine3f& mat)
|
||||
{
|
||||
mat.translation()[0] = round(mat.translation()[0]);
|
||||
mat.translation()[1] = round(mat.translation()[1]);
|
||||
return mat;
|
||||
}
|
||||
|
||||
Eigen::Affine3f roundMatrix(const Eigen::Affine3f& mat)
|
||||
{
|
||||
Eigen::Affine3f ret = mat;
|
||||
roundMatrix(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Eigen::Vector3f roundVector(const Eigen::Vector3f& vec)
|
||||
{
|
||||
Eigen::Vector3f ret = vec;
|
||||
ret[0] = round(ret[0]);
|
||||
ret[1] = round(ret[1]);
|
||||
ret[2] = round(ret[2]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Eigen::Vector2f roundVector(const Eigen::Vector2f& vec)
|
||||
{
|
||||
Eigen::Vector2f ret = vec;
|
||||
ret[0] = round(ret[0]);
|
||||
ret[1] = round(ret[1]);
|
||||
return ret;
|
||||
}
|
||||
|
|
11
src/Util.h
11
src/Util.h
|
@ -1,5 +1,14 @@
|
|||
#include <string>
|
||||
#include <Eigen/Dense>
|
||||
|
||||
std::string strToUpper(const char* from);
|
||||
std::string& strToUpper(std::string& str);
|
||||
std::string strToUpper(const std::string& str);
|
||||
std::string strToUpper(const std::string& str);
|
||||
|
||||
Eigen::Affine3f& roundMatrix(Eigen::Affine3f& mat);
|
||||
Eigen::Affine3f roundMatrix(const Eigen::Affine3f& mat);
|
||||
|
||||
Eigen::Vector3f roundVector(const Eigen::Vector3f& vec);
|
||||
Eigen::Vector2f roundVector(const Eigen::Vector2f& vec);
|
||||
|
||||
float round(float num);
|
||||
|
|
|
@ -85,13 +85,14 @@ void ButtonComponent::updateImage()
|
|||
|
||||
void ButtonComponent::render(const Eigen::Affine3f& parentTrans)
|
||||
{
|
||||
Eigen::Affine3f trans = parentTrans * getTransform();
|
||||
|
||||
Eigen::Affine3f trans = roundMatrix(parentTrans * getTransform());
|
||||
|
||||
mBox.render(trans);
|
||||
|
||||
if(mTextCache)
|
||||
{
|
||||
Eigen::Vector3f centerOffset((mSize.x() - mTextCache->metrics.size.x()) / 2, (mSize.y() - mTextCache->metrics.size.y()) / 2, 0);
|
||||
centerOffset = roundVector(centerOffset);
|
||||
trans = trans.translate(centerOffset);
|
||||
|
||||
Renderer::setMatrix(trans);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "ComponentList.h"
|
||||
#include "../Util.h"
|
||||
|
||||
#define TOTAL_HORIZONTAL_PADDING_PX 20
|
||||
|
||||
|
@ -128,16 +129,16 @@ void ComponentList::render(const Eigen::Affine3f& parentTrans)
|
|||
if(!size())
|
||||
return;
|
||||
|
||||
Eigen::Affine3f trans = parentTrans * getTransform();
|
||||
|
||||
Eigen::Affine3f trans = roundMatrix(parentTrans * getTransform());
|
||||
|
||||
// clip everything to be inside our bounds
|
||||
Eigen::Vector3f dim(mSize.x(), mSize.y(), 0);
|
||||
dim = trans * dim - trans.translation();
|
||||
Renderer::pushClipRect(Eigen::Vector2i((int)trans.translation().x(),
|
||||
(int)trans.translation().y()), Eigen::Vector2i((int)dim.x(), (int)dim.y()));
|
||||
Renderer::pushClipRect(Eigen::Vector2i((int)trans.translation().x(), (int)trans.translation().y()),
|
||||
Eigen::Vector2i((int)round(dim.x()), (int)round(dim.y())));
|
||||
|
||||
// scroll the camera
|
||||
trans.translate(Eigen::Vector3f(0, -mCameraOffset, 0));
|
||||
trans.translate(Eigen::Vector3f(0, -round(mCameraOffset), 0));
|
||||
|
||||
// draw our entries
|
||||
renderChildren(trans);
|
||||
|
@ -154,24 +155,24 @@ void ComponentList::render(const Eigen::Affine3f& parentTrans)
|
|||
// (1 - dst) + 0x77
|
||||
|
||||
const float selectedRowHeight = getRowHeight(mEntries.at(mCursor).data);
|
||||
Renderer::drawRect(0, (int)mSelectorBarOffset, (int)mSize.x(), (int)selectedRowHeight, 0xFFFFFFFF,
|
||||
Renderer::drawRect(0.0f, mSelectorBarOffset, mSize.x(), selectedRowHeight, 0xFFFFFFFF,
|
||||
GL_ONE_MINUS_DST_COLOR, GL_ZERO);
|
||||
Renderer::drawRect(0, (int)mSelectorBarOffset, (int)mSize.x(), (int)selectedRowHeight, 0x777777FF,
|
||||
Renderer::drawRect(0.0f, mSelectorBarOffset, mSize.x(), selectedRowHeight, 0x777777FF,
|
||||
GL_ONE, GL_ONE);
|
||||
|
||||
// hack to draw 2px dark on left/right of the bar
|
||||
Renderer::drawRect(0, (int)mSelectorBarOffset, 2, (int)selectedRowHeight, 0x878787FF);
|
||||
Renderer::drawRect((int)mSize.x() - 2, (int)mSelectorBarOffset, 2, (int)selectedRowHeight, 0x878787FF);
|
||||
Renderer::drawRect(0.0f, mSelectorBarOffset, 2.0f, selectedRowHeight, 0x878787FF);
|
||||
Renderer::drawRect(mSize.x() - 2.0f, mSelectorBarOffset, 2.0f, selectedRowHeight, 0x878787FF);
|
||||
}
|
||||
|
||||
// draw separators
|
||||
float y = 0;
|
||||
for(unsigned int i = 0; i < mEntries.size(); i++)
|
||||
{
|
||||
Renderer::drawRect(0, (int)y, (int)mSize.x(), 1, 0xC6C7C6FF);
|
||||
Renderer::drawRect(0.0f, y, mSize.x(), 1.0f, 0xC6C7C6FF);
|
||||
y += getRowHeight(mEntries.at(i).data);
|
||||
}
|
||||
Renderer::drawRect(0, (int)y, (int)mSize.x(), 1, 0xC6C7C6FF);
|
||||
Renderer::drawRect(0.0f, y, mSize.x(), 1.0f, 0xC6C7C6FF);
|
||||
|
||||
Renderer::popClipRect();
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "../Renderer.h"
|
||||
#include "../Window.h"
|
||||
#include "../Log.h"
|
||||
#include "../Util.h"
|
||||
|
||||
DateTimeComponent::DateTimeComponent(Window* window) : GuiComponent(window),
|
||||
mEditing(false), mEditIndex(0), mDisplayMode(DISP_DATE), mRelativeUpdateAccumulator(0),
|
||||
|
@ -136,7 +137,7 @@ void DateTimeComponent::update(int deltaTime)
|
|||
|
||||
void DateTimeComponent::render(const Eigen::Affine3f& parentTrans)
|
||||
{
|
||||
Eigen::Affine3f trans = parentTrans * getTransform();
|
||||
Eigen::Affine3f trans = roundMatrix(parentTrans * getTransform());
|
||||
Renderer::setMatrix(trans);
|
||||
|
||||
if(mTextCache)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "../Log.h"
|
||||
#include "../Renderer.h"
|
||||
#include "../ThemeData.h"
|
||||
#include "../Util.h"
|
||||
|
||||
Eigen::Vector2i ImageComponent::getTextureSize() const
|
||||
{
|
||||
|
@ -136,7 +137,7 @@ void ImageComponent::setColorShift(unsigned int color)
|
|||
|
||||
void ImageComponent::render(const Eigen::Affine3f& parentTrans)
|
||||
{
|
||||
Eigen::Affine3f trans = parentTrans * getTransform();
|
||||
Eigen::Affine3f trans = roundMatrix(parentTrans * getTransform());
|
||||
Renderer::setMatrix(trans);
|
||||
|
||||
if(mTexture && getOpacity() > 0)
|
||||
|
@ -172,6 +173,9 @@ void ImageComponent::buildImageArray(int posX, int posY, GLfloat* points, GLfloa
|
|||
points[8] = posX - (mSize.x() * mOrigin.x()); points[9] = posY + (mSize.y() * (1 - mOrigin.y()));
|
||||
points[10] = posX + (mSize.x() * (1 -mOrigin.x())); points[11] = posY + (mSize.y() * (1 - mOrigin.y()));
|
||||
|
||||
// round vertices
|
||||
for(int i = 0; i < 12; i++)
|
||||
points[i] = round(points[i]);
|
||||
|
||||
|
||||
texs[0] = 0; texs[1] = py;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "../Log.h"
|
||||
#include "../Renderer.h"
|
||||
#include "../ThemeData.h"
|
||||
#include "../Util.h"
|
||||
|
||||
NinePatchComponent::NinePatchComponent(Window* window, const std::string& path, unsigned int edgeColor, unsigned int centerColor) : GuiComponent(window),
|
||||
mEdgeColor(edgeColor), mCenterColor(centerColor),
|
||||
|
@ -121,11 +122,18 @@ void NinePatchComponent::buildVertices()
|
|||
|
||||
v += 6;
|
||||
}
|
||||
|
||||
// round vertices
|
||||
for(int i = 0; i < 6*9; i++)
|
||||
{
|
||||
mVertices[i].pos = roundVector(mVertices[i].pos);
|
||||
}
|
||||
}
|
||||
|
||||
void NinePatchComponent::render(const Eigen::Affine3f& parentTrans)
|
||||
{
|
||||
Eigen::Affine3f trans = parentTrans * getTransform();
|
||||
Eigen::Affine3f trans = roundMatrix(parentTrans * getTransform());
|
||||
|
||||
if(mTexture && mVertices != NULL)
|
||||
{
|
||||
Renderer::setMatrix(trans);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "RatingComponent.h"
|
||||
#include "../Renderer.h"
|
||||
#include "../Window.h"
|
||||
#include "../Util.h"
|
||||
|
||||
RatingComponent::RatingComponent(Window* window) : GuiComponent(window)
|
||||
{
|
||||
|
@ -71,11 +72,14 @@ void RatingComponent::updateVertices()
|
|||
mVertices[10].pos << fw, 0.0f;
|
||||
mVertices[10].tex << numStars, 1.0f;
|
||||
mVertices[11] = mVertices[7];
|
||||
|
||||
for(int i = 0; i < 12; i++)
|
||||
mVertices[i].pos = roundVector(mVertices[i].pos);
|
||||
}
|
||||
|
||||
void RatingComponent::render(const Eigen::Affine3f& parentTrans)
|
||||
{
|
||||
Eigen::Affine3f trans = parentTrans * getTransform();
|
||||
Eigen::Affine3f trans = roundMatrix(parentTrans * getTransform());
|
||||
Renderer::setMatrix(trans);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "../Renderer.h"
|
||||
#include "../resources/Font.h"
|
||||
#include "../Log.h"
|
||||
#include "../Util.h"
|
||||
|
||||
SliderComponent::SliderComponent(Window* window, float min, float max, float increment, const std::string& suffix) : GuiComponent(window),
|
||||
mMin(min), mMax(max), mIncrement(increment), mMoveRate(0), mRepeatWaitTimer(0), mKnob(window), mSuffix(suffix)
|
||||
|
@ -74,7 +75,7 @@ void SliderComponent::update(int deltaTime)
|
|||
|
||||
void SliderComponent::render(const Eigen::Affine3f& parentTrans)
|
||||
{
|
||||
Eigen::Affine3f trans = parentTrans * getTransform();
|
||||
Eigen::Affine3f trans = roundMatrix(parentTrans * getTransform());
|
||||
Renderer::setMatrix(trans);
|
||||
|
||||
// render suffix
|
||||
|
@ -84,8 +85,8 @@ void SliderComponent::render(const Eigen::Affine3f& parentTrans)
|
|||
float width = mSize.x() - mKnob.getSize().x() - (mValueCache ? mValueCache->metrics.size.x() + 4 : 0);
|
||||
|
||||
//render line
|
||||
const int lineWidth = 2;
|
||||
Renderer::drawRect((int)mKnob.getSize().x() / 2, (int)mSize.y() / 2 - lineWidth / 2, (int)width, lineWidth, 0x777777FF);
|
||||
const float lineWidth = 2;
|
||||
Renderer::drawRect(mKnob.getSize().x() / 2, mSize.y() / 2 - lineWidth / 2, width, lineWidth, 0x777777FF);
|
||||
|
||||
//render knob
|
||||
mKnob.render(trans);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "../Log.h"
|
||||
#include "../Window.h"
|
||||
#include "../ThemeData.h"
|
||||
#include "../Util.h"
|
||||
|
||||
TextComponent::TextComponent(Window* window) : GuiComponent(window),
|
||||
mFont(Font::get(FONT_SIZE_MEDIUM)), mColor(0x000000FF), mAutoCalcExtent(true, true), mCentered(false)
|
||||
|
@ -68,11 +69,12 @@ void TextComponent::setCentered(bool center)
|
|||
|
||||
void TextComponent::render(const Eigen::Affine3f& parentTrans)
|
||||
{
|
||||
Eigen::Affine3f trans = parentTrans * getTransform();
|
||||
Eigen::Affine3f trans = roundMatrix(parentTrans * getTransform());
|
||||
|
||||
Eigen::Vector3f dim(mSize.x(), mSize.y(), 0);
|
||||
dim = trans * dim - trans.translation();
|
||||
Renderer::pushClipRect(Eigen::Vector2i((int)trans.translation().x(), (int)trans.translation().y()), Eigen::Vector2i((int)dim.x(), (int)dim.y()));
|
||||
Renderer::pushClipRect(Eigen::Vector2i((int)trans.translation().x(), (int)trans.translation().y()),
|
||||
Eigen::Vector2i((int)(dim.x() + 0.5f), (int)(dim.y() + 0.5f)));
|
||||
|
||||
if(mTextCache)
|
||||
{
|
||||
|
@ -80,6 +82,7 @@ void TextComponent::render(const Eigen::Affine3f& parentTrans)
|
|||
{
|
||||
const Eigen::Vector2f& textSize = mTextCache->metrics.size;
|
||||
Eigen::Vector3f off((getSize().x() - textSize.x()) / 2, (getSize().y() - textSize.y()) / 2, 0);
|
||||
off = roundVector(off);
|
||||
|
||||
trans.translate(off);
|
||||
Renderer::setMatrix(trans);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "../Renderer.h"
|
||||
#include <boost/filesystem.hpp>
|
||||
#include "../Log.h"
|
||||
#include "../Util.h"
|
||||
|
||||
FT_Library Font::sLibrary;
|
||||
bool Font::libraryInitialized = false;
|
||||
|
@ -475,6 +476,12 @@ TextCache* Font::buildTextCache(const std::string& text, float offsetX, float of
|
|||
vert[i + 5].tex[0] = vert[i + 1].tex.x();
|
||||
vert[i + 5].tex[1] = vert[i + 0].tex.y();
|
||||
|
||||
// round
|
||||
for(int j = 0; j < 6; j++)
|
||||
{
|
||||
vert[i + j].pos = roundVector(vert[i + j].pos);
|
||||
}
|
||||
|
||||
x += charData[letter].advX * fontScale;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue