Skip to content

Commit f8ec2c1

Browse files
committed
libRocket now responds consistently to auto-texture-scaling, and supports (and prefers) padding over scaling
Thanks to Ed Swartz for helping to track down these issues!
1 parent ecaffd5 commit f8ec2c1

File tree

2 files changed

+82
-32
lines changed

2 files changed

+82
-32
lines changed

panda/src/rocket/rocketRenderInterface.cxx

Lines changed: 78 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,10 @@ render(Rocket::Core::Context* context, CullTraverser *trav) {
6666
// Description: Called internally to make a Geom from Rocket data.
6767
////////////////////////////////////////////////////////////////////
6868
PT(Geom) RocketRenderInterface::
69-
make_geom(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, GeomEnums::UsageHint uh) {
69+
make_geom(Rocket::Core::Vertex* vertices,
70+
int num_vertices, int* indices, int num_indices,
71+
GeomEnums::UsageHint uh, const LVecBase2 &tex_scale) {
72+
7073
PT(GeomVertexData) vdata = new GeomVertexData("", GeomVertexFormat::get_v3c4t2(), uh);
7174
vdata->unclean_set_num_rows(num_vertices);
7275
{
@@ -81,7 +84,8 @@ make_geom(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int nu
8184
vwriter.add_data3f(LVector3f::right() * vertex.position.x + LVector3f::up() * vertex.position.y);
8285
cwriter.add_data4i(vertex.colour.red, vertex.colour.green,
8386
vertex.colour.blue, vertex.colour.alpha);
84-
twriter.add_data2f(vertex.tex_coord.x, 1.0f - vertex.tex_coord.y);
87+
twriter.add_data2f(vertex.tex_coord.x * tex_scale[0],
88+
(1.0f - vertex.tex_coord.y) * tex_scale[1]);
8589
}
8690
}
8791

@@ -140,12 +144,24 @@ render_geom(const Geom* geom, const RenderState* state, const Rocket::Core::Vect
140144
// that the application does not wish to optimize.
141145
////////////////////////////////////////////////////////////////////
142146
void RocketRenderInterface::
143-
RenderGeometry(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rocket::Core::TextureHandle texture, const Rocket::Core::Vector2f& translation) {
144-
PT(Geom) geom = make_geom(vertices, num_vertices, indices, num_indices, GeomEnums::UH_stream);
147+
RenderGeometry(Rocket::Core::Vertex* vertices,
148+
int num_vertices, int* indices, int num_indices,
149+
Rocket::Core::TextureHandle thandle,
150+
const Rocket::Core::Vector2f& translation) {
151+
152+
Texture *texture = (Texture *)thandle;
153+
154+
LVecBase2 tex_scale(1, 1);
155+
if (texture != (Texture *)NULL) {
156+
tex_scale = texture->get_tex_scale();
157+
}
158+
159+
PT(Geom) geom = make_geom(vertices, num_vertices, indices, num_indices,
160+
GeomEnums::UH_stream, tex_scale);
145161

146162
CPT(RenderState) state;
147-
if ((Texture*) texture != (Texture*) NULL) {
148-
state = RenderState::make(TextureAttrib::make((Texture*) texture));
163+
if (texture != (Texture *)NULL) {
164+
state = RenderState::make(TextureAttrib::make(texture));
149165
} else {
150166
state = RenderState::make_empty();
151167
}
@@ -160,30 +176,40 @@ RenderGeometry(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, i
160176
// it believes will be static for the forseeable future.
161177
////////////////////////////////////////////////////////////////////
162178
Rocket::Core::CompiledGeometryHandle RocketRenderInterface::
163-
CompileGeometry(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rocket::Core::TextureHandle texture) {
179+
CompileGeometry(Rocket::Core::Vertex* vertices,
180+
int num_vertices, int* indices, int num_indices,
181+
Rocket::Core::TextureHandle thandle) {
182+
183+
Texture *texture = (Texture *)thandle;
164184

165185
CompiledGeometry *c = new CompiledGeometry;
166-
c->_geom = make_geom(vertices, num_vertices, indices, num_indices, GeomEnums::UH_static);
186+
LVecBase2 tex_scale(1, 1);
187+
188+
if (texture != (Texture *)NULL) {
189+
rocket_cat.debug()
190+
<< "Compiling geom " << c->_geom << " with texture '"
191+
<< texture->get_name() << "'\n";
192+
193+
tex_scale = texture->get_tex_scale();
167194

168-
if ((Texture*) texture != (Texture*) NULL) {
169195
PT(TextureStage) stage = new TextureStage("");
170196
stage->set_mode(TextureStage::M_modulate);
171197

172198
CPT(TextureAttrib) attr = DCAST(TextureAttrib, TextureAttrib::make());
173-
attr = DCAST(TextureAttrib, attr->add_on_stage(stage, (Texture*) texture));
199+
attr = DCAST(TextureAttrib, attr->add_on_stage(stage, (Texture *)texture));
174200

175201
c->_state = RenderState::make(attr);
176202

177-
rocket_cat.debug()
178-
<< "Compiled geom " << c->_geom << " with texture '"
179-
<< ((Texture*) texture)->get_name() << "'\n";
180203
} else {
181-
c->_state = RenderState::make_empty();
182-
183204
rocket_cat.debug()
184-
<< "Compiled geom " << c->_geom << " without texture\n";
205+
<< "Compiling geom " << c->_geom << " without texture\n";
206+
207+
c->_state = RenderState::make_empty();
185208
}
186209

210+
c->_geom = make_geom(vertices, num_vertices, indices, num_indices,
211+
GeomEnums::UH_static, tex_scale);
212+
187213
return (Rocket::Core::CompiledGeometryHandle) c;
188214
}
189215

@@ -222,7 +248,16 @@ LoadTexture(Rocket::Core::TextureHandle& texture_handle,
222248
Rocket::Core::Vector2i& texture_dimensions,
223249
const Rocket::Core::String& source) {
224250

225-
PT(Texture) tex = TexturePool::load_texture(Filename::from_os_specific(source.CString()));
251+
// Prefer padding over scaling to avoid blurring people's pixel art.
252+
LoaderOptions options;
253+
if (Texture::get_textures_power_2() == ATS_none) {
254+
options.set_auto_texture_scale(ATS_none);
255+
} else {
256+
options.set_auto_texture_scale(ATS_pad);
257+
}
258+
259+
Filename fn = Filename::from_os_specific(source.CString());
260+
PT(Texture) tex = TexturePool::load_texture(fn, 0, false, options);
226261
if (tex == NULL) {
227262
texture_handle = 0;
228263
texture_dimensions.x = 0;
@@ -233,8 +268,12 @@ LoadTexture(Rocket::Core::TextureHandle& texture_handle,
233268
tex->set_minfilter(SamplerState::FT_nearest);
234269
tex->set_magfilter(SamplerState::FT_nearest);
235270

236-
texture_dimensions.x = tex->get_x_size();
237-
texture_dimensions.y = tex->get_y_size();
271+
// Since libRocket may make layout decisions based on the size of
272+
// the image, it's important that we give it the original size of
273+
// the image file in order to produce consistent results.
274+
texture_dimensions.x = tex->get_orig_file_x_size();
275+
texture_dimensions.y = tex->get_orig_file_y_size();
276+
238277
tex->ref();
239278
texture_handle = (Rocket::Core::TextureHandle) tex.p();
240279

@@ -255,18 +294,26 @@ GenerateTexture(Rocket::Core::TextureHandle& texture_handle,
255294
PT(Texture) tex = new Texture;
256295
tex->setup_2d_texture(source_dimensions.x, source_dimensions.y,
257296
Texture::T_unsigned_byte, Texture::F_rgba);
297+
298+
// Pad to nearest power of two if necessary. It may not be necessary
299+
// as libRocket seems to give power-of-two sizes already, but can't hurt.
300+
tex->set_size_padded(source_dimensions.x, source_dimensions.y);
301+
258302
PTA_uchar image = tex->modify_ram_image();
259303

260304
// Convert RGBA to BGRA
261-
size_t row_size = source_dimensions.x * 4;
262-
size_t y2 = image.size();
263-
for (size_t y = 0; y < image.size(); y += row_size) {
264-
y2 -= row_size;
265-
for (size_t i = 0; i < row_size; i += 4) {
266-
image[y2 + i + 0] = source[y + i + 2];
267-
image[y2 + i + 1] = source[y + i + 1];
268-
image[y2 + i + 2] = source[y + i];
269-
image[y2 + i + 3] = source[y + i + 3];
305+
size_t src_stride = source_dimensions.x * 4;
306+
size_t dst_stride = tex->get_x_size() * 4;
307+
const unsigned char *src_ptr = source + (src_stride * source_dimensions.y);
308+
unsigned char *dst_ptr = &image[0];
309+
310+
for (; src_ptr >= source; dst_ptr += dst_stride) {
311+
src_ptr -= src_stride;
312+
for (size_t i = 0; i < src_stride; i += 4) {
313+
dst_ptr[i + 0] = src_ptr[i + 2];
314+
dst_ptr[i + 1] = src_ptr[i + 1];
315+
dst_ptr[i + 2] = src_ptr[i];
316+
dst_ptr[i + 3] = src_ptr[i + 3];
270317
}
271318
}
272319

@@ -289,9 +336,9 @@ GenerateTexture(Rocket::Core::TextureHandle& texture_handle,
289336
////////////////////////////////////////////////////////////////////
290337
void RocketRenderInterface::
291338
ReleaseTexture(Rocket::Core::TextureHandle texture_handle) {
292-
Texture* tex = (Texture*) texture_handle;
293-
if (tex != (Texture*) NULL) {
294-
tex->unref();
339+
Texture *tex = (Texture *)texture_handle;
340+
if (tex != (Texture *)NULL) {
341+
unref_delete(tex);
295342
}
296343
}
297344

panda/src/rocket/rocketRenderInterface.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ class RocketRenderInterface : public Rocket::Core::RenderInterface {
3939
CPT(RenderState) _state;
4040
};
4141

42-
PT(Geom) make_geom(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, GeomEnums::UsageHint uh);
42+
PT(Geom) make_geom(Rocket::Core::Vertex* vertices,
43+
int num_vertices, int* indices, int num_indices,
44+
GeomEnums::UsageHint uh, const LVecBase2 &tex_scale);
4345
void render_geom(const Geom* geom, const RenderState* state, const Rocket::Core::Vector2f& translation);
4446

4547
void RenderGeometry(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rocket::Core::TextureHandle texture, const Rocket::Core::Vector2f& translation);
@@ -70,6 +72,7 @@ class RocketRenderInterface : public Rocket::Core::RenderInterface {
7072
CPT(TransformState) _net_transform;
7173
CPT(RenderState) _net_state;
7274
Rocket::Core::Vector2i _dimensions;
75+
7376
};
7477

7578
#endif

0 commit comments

Comments
 (0)