Skip to content

Commit

Permalink
"Fixed" the long-time weird rendering artifacts that are apparently c…
Browse files Browse the repository at this point in the history
…aused 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.
  • Loading branch information
Aloshi committed Mar 19, 2014
1 parent daa6212 commit 07edad6
Show file tree
Hide file tree
Showing 15 changed files with 120 additions and 30 deletions.
10 changes: 10 additions & 0 deletions DEVNOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
1 change: 1 addition & 0 deletions src/Renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 6 additions & 0 deletions src/Renderer_draw_gl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <boost/filesystem.hpp>
#include "Log.h"
#include <stack>
#include "Util.h"

namespace Renderer {
std::stack<Eigen::Vector4i> clipStack;
Expand Down Expand Up @@ -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
Expand Down
10 changes: 4 additions & 6 deletions src/Renderer_init_sdlgl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;

Expand Down
38 changes: 37 additions & 1 deletion src/Util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 10 additions & 1 deletion src/Util.h
Original file line number Diff line number Diff line change
@@ -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);
5 changes: 3 additions & 2 deletions src/components/ButtonComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
23 changes: 12 additions & 11 deletions src/components/ComponentList.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "ComponentList.h"
#include "../Util.h"

#define TOTAL_HORIZONTAL_PADDING_PX 20

Expand Down Expand Up @@ -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);
Expand All @@ -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();
}
Expand Down
3 changes: 2 additions & 1 deletion src/components/DateTimeComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 5 additions & 1 deletion src/components/ImageComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "../Log.h"
#include "../Renderer.h"
#include "../ThemeData.h"
#include "../Util.h"

Eigen::Vector2i ImageComponent::getTextureSize() const
{
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down
10 changes: 9 additions & 1 deletion src/components/NinePatchComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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);
Expand Down
6 changes: 5 additions & 1 deletion src/components/RatingComponent.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "RatingComponent.h"
#include "../Renderer.h"
#include "../Window.h"
#include "../Util.h"

RatingComponent::RatingComponent(Window* window) : GuiComponent(window)
{
Expand Down Expand Up @@ -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);
Expand Down
7 changes: 4 additions & 3 deletions src/components/SliderComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand Down
7 changes: 5 additions & 2 deletions src/components/TextComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -68,18 +69,20 @@ 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)
{
if(mCentered)
{
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);
Expand Down
7 changes: 7 additions & 0 deletions src/resources/Font.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down

0 comments on commit 07edad6

Please sign in to comment.