Skip to content

Commit ba20d37

Browse files
committed
Add Bicubic Filtering and optional SDF Rendering for some shapes
1 parent 4913c4b commit ba20d37

File tree

6 files changed

+163
-44
lines changed

6 files changed

+163
-44
lines changed

GL/include/shader.inl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,23 @@ namespace gl {
4444
use();
4545
glUniform1iv(getUniformLocation(name), count, value);
4646
}
47+
48+
template<>
49+
inline void shader::_setUniform<bool>(const char* name, int count, const bool* value)
50+
{
51+
use();
52+
if (count <= 16) {
53+
GLint tmp[16];
54+
for (int i = 0; i < count; i++)
55+
tmp[i] = value[i] ? 1 : 0;
56+
glUniform1iv(getUniformLocation(name), count, tmp);
57+
}
58+
else {
59+
GLint* tmp = new GLint[count];
60+
for (int i = 0; i < count; i++)
61+
tmp[i] = value[i] ? 1 : 0;
62+
glUniform1iv(getUniformLocation(name), count, tmp);
63+
delete[] tmp;
64+
}
65+
}
4766
}

Shared/include/openglrenderer.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,26 +24,34 @@ struct OpenGLContext {
2424

2525
class OpenGLRenderer final : public SarRenderer {
2626
public:
27+
static constexpr int FLAG_HD = 1;
28+
2729
OpenGLRenderer();
2830
~OpenGLRenderer();
2931

32+
void Render(SarFile& sar, gl::framebuffer& fbo);
33+
34+
void SetFlag(int flag, bool value) override;
3035
void Render(SarFile& sar, int texW, int texH, void* bgraData) override;
3136

3237
private:
33-
void initShapeMap();
38+
void initShapeAttrs();
3439

35-
struct shape_map {
40+
struct shape_attr {
3641
uint16_t m_Value;
42+
bool m_EnableSdf;
43+
3744
inline uint8_t x_pos() { return _BITFIELD(m_Value, 0, 4); }
3845
inline uint8_t y_pos() { return _BITFIELD(m_Value, 4, 4); }
3946
inline uint8_t sheet() { return _BITFIELD(m_Value, 8, 2); }
47+
inline bool sdf() { return m_EnableSdf; }
4048
};
4149

4250
OpenGLContext m_ctx;
4351

4452
gl::shader shader;
4553
gl::texture atlas;
46-
std::unordered_map<uint16_t, shape_map> m_ShapeMaps;
54+
std::unordered_map<uint16_t, shape_attr> m_ShapeAttrs;
4755
};
4856

4957
class glrenderer_exception final : public std::exception {

Shared/include/renderer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@
55
class SarRenderer {
66
public:
77
virtual ~SarRenderer() = 0;
8+
virtual void SetFlag(int flag, bool value) = 0;
89
virtual void Render(SarFile& sar, int texW, int texH, void* rgbaData) = 0;
910
};

Shared/rsrc/default.fs

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,79 @@
33
in vec3 Position;
44
in vec4 Color;
55
in vec2 TexCoords;
6-
flat in int DrawMode;
6+
flat in ivec2 DrawMode;
77

88
out vec4 FragColor;
99

1010
uniform sampler2D m_Tex;
1111
uniform mat4 m_TexSelector[4];
1212
uniform vec4 m_TexMixer[4];
13+
uniform float m_SdfOffset;
14+
uniform bool m_SdfEnable;
15+
16+
17+
vec4 cubic(float v){
18+
vec4 n = vec4(1.0, 2.0, 3.0, 4.0) - v;
19+
vec4 s = n * n * n;
20+
float x = s.x;
21+
float y = s.y - 4.0 * s.x;
22+
float z = s.z - 4.0 * s.y + 6.0 * s.x;
23+
float w = 6.0 - x - y - z;
24+
return vec4(x, y, z, w) * (1.0/6.0);
25+
}
26+
27+
vec4 textureBicubic(sampler2D sampler, vec2 texCoords){
28+
29+
vec2 texSize = textureSize(sampler, 0);
30+
vec2 invTexSize = 1.0 / texSize;
31+
32+
texCoords = texCoords * texSize - 0.5;
33+
34+
vec2 fxy = fract(texCoords);
35+
texCoords -= fxy;
36+
37+
vec4 xcubic = cubic(fxy.x);
38+
vec4 ycubic = cubic(fxy.y);
39+
40+
vec4 c = texCoords.xxyy + vec2 (-0.5, +1.5).xyxy;
41+
42+
vec4 s = vec4(xcubic.xz + xcubic.yw, ycubic.xz + ycubic.yw);
43+
vec4 offset = c + vec4(xcubic.yw, ycubic.yw) / s;
44+
45+
offset *= invTexSize.xxyy;
46+
47+
vec4 sample0 = texture(sampler, offset.xz);
48+
vec4 sample1 = texture(sampler, offset.yz);
49+
vec4 sample2 = texture(sampler, offset.xw);
50+
vec4 sample3 = texture(sampler, offset.yw);
51+
52+
float sx = s.x / (s.x + s.y);
53+
float sy = s.z / (s.z + s.w);
54+
55+
return mix(
56+
mix(sample3, sample2, sx), mix(sample1, sample0, sx)
57+
, sy);
58+
}
1359

1460
void main()
1561
{
16-
mat4 texSel = m_TexSelector[DrawMode];
17-
vec4 texMix = m_TexMixer[DrawMode];
18-
vec4 texCol = texture(m_Tex, TexCoords) * texSel;
62+
int selector = DrawMode.x;
63+
int sdfFactor = DrawMode.y;
64+
65+
mat4 texSel = m_TexSelector[selector];
66+
vec4 texMix = m_TexMixer[selector];
67+
vec4 texCol = textureBicubic(m_Tex, TexCoords) * texSel;
68+
1969
vec4 shape = mix(texCol, vec4(1), texMix);
70+
71+
if(m_SdfEnable) {
72+
float dist = texCol.w - m_SdfOffset;
73+
float delta = fwidth(dist) * 0.5;
74+
float edge = smoothstep(-delta, delta, dist);
75+
76+
vec4 shapeSdf = vec4(1,1,1, edge);
77+
shape = mix(shape, shapeSdf, sdfFactor);
78+
}
79+
2080
FragColor = shape * Color;
2181
}

Shared/rsrc/default.vs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
layout (location = 0) in vec3 aPos;
44
layout (location = 1) in vec4 aColor;
55
layout (location = 2) in vec2 aTexCoords;
6-
layout (location = 3) in int aDrawMode;
6+
layout (location = 3) in ivec2 aDrawMode;
77

88
out vec4 Color;
99
out vec2 TexCoords;
1010
out vec3 Position;
11-
flat out int DrawMode;
11+
flat out ivec2 DrawMode;
1212

1313
uniform mat4 m_View;
1414
uniform mat4 m_Proj;

Shared/src/openglrenderer.cpp

Lines changed: 66 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "stb_image.h"
33
#include "resource.h"
44
#include "debug.h"
5+
#include "..\include\openglrenderer.h"
56

67
#ifdef _USRDLL
78
extern HINSTANCE g_hInstDll;
@@ -51,7 +52,7 @@ OpenGLRenderer::OpenGLRenderer()
5152
char* fss = getRcdata(m_ctx.hInstance, IDR_SHADER_DEFAULT_FS, fsl);
5253
char* atl = getRcdata(m_ctx.hInstance, IDR_TEXTURE_ATLAS, texl);
5354

54-
initShapeMap();
55+
initShapeAttrs();
5556

5657
int atl_w, atl_h;
5758
int atl_cmp;
@@ -85,6 +86,8 @@ OpenGLRenderer::OpenGLRenderer()
8586

8687
shader.setUniform("m_TexSelector", texSelector);
8788
shader.setUniform("m_TexMixer", texMixer);
89+
shader.setUniform("m_SdfOffset", 0.3f);
90+
shader.setUniform("m_SdfEnable", false);
8891

8992
atlas.image2d(atl_w, atl_h, GL_RGBA, GL_UNSIGNED_BYTE, atl_data);
9093
}
@@ -97,14 +100,12 @@ OpenGLRenderer::~OpenGLRenderer()
97100

98101
}
99102

100-
void OpenGLRenderer::Render(SarFile& sar, int texW, int texH, void* bgraData)
101-
{
102-
// Prepare Data
103+
void OpenGLRenderer::Render(SarFile& sar, gl::framebuffer& fbo) {
103104

104105
std::vector<glm::vec3> vertices;
105106
std::vector<glm::vec4> colors;
106107
std::vector<glm::vec2> uvs;
107-
std::vector<GLint> drawMode;
108+
std::vector<glm::ivec2> drawMode;
108109
std::vector<GLuint> indices;
109110

110111
glm::vec2 uv[] = { {0,0},{0,1},{1,0}, {1,1} };
@@ -117,13 +118,13 @@ void OpenGLRenderer::Render(SarFile& sar, int texW, int texH, void* bgraData)
117118
if (l.hidden())
118119
continue;
119120

120-
auto map_it = m_ShapeMaps.find(l.shape());
121-
if (map_it == m_ShapeMaps.end()) {
121+
auto map_it = m_ShapeAttrs.find(l.shape());
122+
if (map_it == m_ShapeAttrs.end()) {
122123
DEBUG_PRINT("Invalid Shape ID: " << l.shape());
123124
continue;
124125
}
125126

126-
shape_map map = map_it->second;
127+
shape_attr map = map_it->second;
127128
glm::vec2 uv_offset = glm::vec2(map.x_pos(), map.y_pos());
128129
// 0 2
129130
// 1 3
@@ -147,7 +148,7 @@ void OpenGLRenderer::Render(SarFile& sar, int texW, int texH, void* bgraData)
147148
uvs.push_back(baseUv);
148149

149150
// Shape Mod
150-
drawMode.push_back(map.sheet());
151+
drawMode.push_back(glm::ivec2(map.sheet(), map.sdf() ? 1 : 0));
151152

152153
DEBUG_PRINT("UVs: " << baseUv.x << ", " << baseUv.y);
153154
}
@@ -165,12 +166,9 @@ void OpenGLRenderer::Render(SarFile& sar, int texW, int texH, void* bgraData)
165166
float halfH = sar.height() / 2.f;
166167
glm::mat4 proj = glm::ortho(-halfW - 0.5f, halfW - 0.5f, -halfH - 0.5f, halfH - 0.5f);
167168

168-
169-
// OpenGL Drawing
170169
{
171170
std::lock_guard<std::mutex> lock{ m_ctx.mutex };
172171

173-
gl::framebuffer fbo(texW, texH);
174172
shader.setUniform("m_View", view);
175173
shader.setUniform("m_Proj", proj);
176174

@@ -211,15 +209,15 @@ void OpenGLRenderer::Render(SarFile& sar, int texW, int texH, void* bgraData)
211209
glEnableVertexAttribArray(2);
212210

213211
attr_mod.bind();
214-
glVertexAttribIPointer(3, 1, GL_INT, 1 * sizeof(GLint), (void*)0);
212+
glVertexAttribIPointer(3, 2, GL_INT, 2 * sizeof(GLint), (void*)0);
215213
glEnableVertexAttribArray(3);
216214

217215
vao.unbind();
218216

219217
// Draw
220218
fbo.bind();
221219

222-
glViewport(0, 0, texW, texH);
220+
glViewport(0, 0, fbo.width, fbo.height);
223221

224222
glClearColor(1, 1, 1, 0);
225223
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
@@ -229,42 +227,75 @@ void OpenGLRenderer::Render(SarFile& sar, int texW, int texH, void* bgraData)
229227

230228
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
231229

232-
glReadPixels(0, 0, texW, texH, GL_BGRA, GL_UNSIGNED_BYTE, bgraData);
233-
234230
fbo.unbind();
235231
}
236232
}
237233

238-
void OpenGLRenderer::initShapeMap()
234+
void OpenGLRenderer::SetFlag(int flag, bool value)
235+
{
236+
switch (flag) {
237+
case FLAG_HD:
238+
{
239+
std::lock_guard<std::mutex> lock{ m_ctx.mutex };
240+
shader.use();
241+
shader.setUniform("m_SdfEnable", value);
242+
}
243+
break;
244+
}
245+
}
246+
247+
void OpenGLRenderer::Render(SarFile& sar, int texW, int texH, void* bgraData)
239248
{
240-
struct map_offset {
249+
gl::framebuffer fbo(texW, texH);
250+
251+
Render(sar, fbo);
252+
253+
fbo.bind();
254+
glReadPixels(0, 0, texW, texH, GL_BGRA, GL_UNSIGNED_BYTE, bgraData);
255+
fbo.unbind();
256+
}
257+
258+
void OpenGLRenderer::initShapeAttrs()
259+
{
260+
struct shape_attr_info {
241261
uint16_t start;
242262
uint16_t end;
243263
int16_t offset;
264+
bool sdfEnabled;
265+
};
266+
267+
shape_attr_info attrs[] = {
268+
/* Start End Offset SDF Shape Set */
269+
{ 0, 79, 0, true}, // Characters
270+
{ 240, 291, 16, true}, // Basic Diagram
271+
{ 320, 358, 0, true}, // Lines
272+
{ 400, 438, -16, true}, // Ink
273+
{ 480, 516, 32, false}, // Gradients
274+
{ 560, 584, 16, true}, // Fractals
275+
{ 608, 612, 16, true}, // Marks
276+
{ 640, 703, 0, true},
277+
{ 720, 753, 240, false} // Pictures
244278
};
245279

246-
map_offset fixups[] = {
247-
/* Start End Offset Shape Set */
248-
{ 0, 79, 0}, // Characters
249-
{ 240, 291, 16}, // Basic Diagram
250-
{ 320, 358, 0}, // Lines
251-
{ 400, 438, -16}, // Ink
252-
{ 480, 516, 32}, // Gradients
253-
{ 560, 584, 16}, // Fractals
254-
{ 608, 612, 16}, // Marks
255-
{ 640, 703, 0},
256-
{ 720, 753, 240} // Pictures
280+
uint16_t blacklist[] = {
281+
560 + 8, 560 + 20, 560 + 21, 560 + 22, 560 + 23, 560 + 24 // Some Fractals
257282
};
258283

259-
constexpr int num_fixups = sizeof(fixups) / sizeof(map_offset);
260-
for (int i = 0; i < num_fixups; i++) {
261-
map_offset& fixup = fixups[i];
262-
for (uint16_t shape_id = fixup.start; shape_id <= fixup.end; shape_id++) {
263-
uint16_t new_id = uint16_t(shape_id + fixup.offset);
264-
m_ShapeMaps[shape_id] = { new_id };
284+
constexpr int num_attrs = sizeof(attrs) / sizeof(shape_attr_info);
285+
for (int i = 0; i < num_attrs; i++) {
286+
shape_attr_info& attr = attrs[i];
287+
for (uint16_t shape_id = attr.start; shape_id <= attr.end; shape_id++) {
288+
uint16_t new_id = uint16_t(shape_id + attr.offset);
289+
m_ShapeAttrs[shape_id] = { new_id, attr.sdfEnabled };
265290
DEBUG_PRINT("Shape Mapping: " << shape_id << " => " << new_id);
266291
}
267292
}
293+
294+
constexpr int num_blacklisted = sizeof(blacklist) / sizeof(uint16_t);
295+
for (int i = 0; i < num_blacklisted; i++) {
296+
uint16_t shape = blacklist[i];
297+
m_ShapeAttrs[shape].m_EnableSdf = false;
298+
}
268299
}
269300

270301
OpenGLContext::OpenGLContext()

0 commit comments

Comments
 (0)