"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:
Aloshi 2014-03-19 15:03:23 -05:00
parent daa62123d1
commit 07edad611f
15 changed files with 120 additions and 30 deletions

View file

@ -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).

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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;
}

View file

@ -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);

View file

@ -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);

View file

@ -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();
}

View file

@ -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)

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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;
}