Closed mreinstein closed 4 years ago
Hi @mreinstein,
first I suggest deciding whether the issue is caused by the higher DPI (Retina) or not. To perform a Retina test, make your font size double (this will make the
fontSize *= 2;
canvas.style.width = (canvas.width/2)+"px";
canvas.style.height = (canvas.height/2)+"px";
...and let us know how does this look like.
However, I believe that pixel density is not the real issue here -- font rendering is. ROT uses vector fonts that are designed to be antialiased (not crispy), Hauberk apparently uses raster fonts. I would suggest looking for suitable TTF/OTF/WOFF fonts that are specifically designed to emulate crispy look (I have no knowledge of these).
Note, however, that roguelike games can look totally okay even with vector/antialiased fonts -- I created several and I was always pretty satisfied with their looks:
Is it possibly to use raster font images natively with rot.js? I know libtcod uses them as its main ASCII-loading tool. I am trying to get super-crispy looking Code Page 437 ASCII characters and that is really turning into pain in the browser lol. I have one working, but it is extremely blurry like the OP mentioned no matter which font type I seem to use. Thank you!
I wanted exactly this look in my 7DRL entry for 2015: https://github.com/blinkdog/7drl-2015
So I borrowed a PNG of the CP437 characters from somebody else's 7DRL 2014 entry: Necromancer Simulator 2014 https://github.com/blinkdog/7drl-2015/blob/master/img/terminal8x8.png
And then used a little bit of code to make a tile map that could behave a lot like text: https://github.com/blinkdog/7drl-2015/blob/master/src/main/coffee/tiles.coffee
If cheating with a tilemap image isn't desirable, then there may be some help in the techniques here, but I'm not really sure if it applies to canvas text commands or not: https://stackoverflow.com/a/49357655
@TimTCrouch @blinkdog I've been experimenting with my own renderer, which is heavily inspired from malison/hauberk as a starting point. It uses a raster based sprite font.
https://github.com/mreinstein/ascii-diagrams
Right now the renderer itself is coupled to this ascii diagraming prototype tool (which was the inspiration for starting this in the first place.) It could/should be pulled out into a standalone renderer module.
The code for this is pretty minimal and open source (the raster based font renderer is only about 200 lines so far.) It seems pretty efficient. Would be happy to accept PRs, ideas, etc. If you find this useful.
Hi folks,
rot.js's text rendering power is ultimately based on (and limited by) the underlying HTML <canvas>
feature. If you manage to get the <canvas>
working the way you like, it is very probable that we can fix rot.js to do the same. Keep in mind, however, that the canvas is primarily designed for vector fonts, so we might be out of luck here - and the only way to get a pixel-perfect rendering is to use image tiles. (Nothing wrong with that approach!)
If you find a way to render TTF/OTF/WOFF in a crispy fashion, let me know what CSS/JS properties need to be applied and I will happily mirror those to rot.js codebase.
I deployed a copy of this to the web, you can play with it here if you like. you can draw boxes, connect lines between boxes, label lines and boxes, etc. This looks non-blurry on both retina and non-retina screens:
https://ascii-diagrams-xybsmgbvoj.now.sh/
@ondras I can't speak to rendering ttf/otf/woff, but this demo is the visual behavior I'm after. It uses font sprite images. The code for this is pretty minimal, if there's value in including any of this logic in rot.js I'm all for it! 👍
It uses font sprite images.
Well, image tiles are always an option. They are already supported in rot.js, so anyone is free to use them.
is there a working example of using an image tile? I could evaluate if this is producing similar visual results
is there a working example of using an image tile? I could evaluate if this is producing similar visual results
The official interactive manual shows regular graphical tiles; they are always drawn 1:1, WYSIWYG. If you can give me a proper tileset image, I can throw together a trivial demo for you.
@ondras here is a tileset image: https://github.com/mreinstein/ascii-diagrams/blob/master/font/font_8_10.png
here is the codepage mapping: https://github.com/mreinstein/ascii-diagrams/blob/master/raster-font/unicode_map.js
here is the code that performs the mapping between character glyph and position within the tileset image (sx, sy): https://github.com/mreinstein/ascii-diagrams/blob/master/raster-font/index.js#L161-L163
Okay @mreinstein, a quick demo using your tileset: https://jsfiddle.net/fzeuy3sc/
looks great!
@ondras a follow up question: besides browser support, is there any benefit to using the rot canvas renderer over webgl? I would think webgl would be more performant with the same amount of setup code.
I would think webgl would be more performant with the same amount of setup code.
Definitely. That is the reason for the WebGL renderer :) Even though Roguelike games are often not that demanding with respect to rendering.
Its code is much newer and less mature, though. I am pretty certain it does not 100% match the feature set of a regular canvas renderer, with respect to tile stacks, colorization and/or opacity.
I am pretty certain it does not 100% match the feature set of a regular canvas renderer, with respect to tile stacks, colorization and/or opacity.
thanks for clarifying! do you have a sense of what the actual feature gap is?
thanks for clarifying! do you have a sense of what the actual feature gap is?
I skimmed the code and there does not seem to be any incompleteness visible or mentioned. I suggest you try it right away, because you can always switch to the regular "tile"
anytime you run into issues.
Also it might be worth mentioning that the WebGL renderer requires your textures to be of a same-origin with respect to the calling page.
I've updated my diagramming tool to use rot.js with the webgl tileimage renderer. Seems to work pretty well!
https://ascii-diagrams-nlrfivgdbe.now.sh
I found 2 issues with the test fiddle that you provided:
canvas
element needs a css property set, to disable interpolation on images:
image-rendering: pixelated;
I haven't checked browser support for this particular property but I'm pretty sure there are other vendor extensions too.test 12 ▶ 34
in the text box. Only test 12
appears. I fixed this by creating a proper tilemapping file for the given image font: https://github.com/mreinstein/ascii-diagrams/blob/master/tile-map.jsI think writing up this demo in the main documentation would be really helpful; I suspect a lot of people that are using rot.js are after this kind of rendering. If I can help with this in any way, happy to do so.
Thanks again for your help with this!
I found 2 issues with the test fiddle that you provided:
Right, the fiddle was a proof-of-concept, not a full-blown example covering all features and edge cases.
* the `canvas` element needs a css property set, to disable interpolation on images:
Sounds correct, even though only for cases where the canvas has to be scaled. I suppose this covers the devicePixelRatio > 1
cases, e.g. Retina devices.
On the other hand, enabling/forcing nearest neighbor interpolation (as oposed to the default linear interp) might be a matter of personal taste. I would like to leave this option up to the developer.
* special characters don't work in the text field; they're not being mapped correctly
Right, my mapping was a fast hack. Ideally, the author of the raster font image would provide a mapping as well.
I think writing up this demo in the main documentation would be really helpful
I agree that some kind of a code sample specifically for this case might be useful. Not sure if a good fit for the manual, though -- it does not really showcase a particular rot.js feature. Perhaps a blogpost or a fiddle or a roguebasin wiki page...
Right, the fiddle was a proof-of-concept, not a full-blown example covering all features and edge cases.
Let me clarify; I'm not picking on you or your solution. It's great! My point is that these 2 changes are needed to render crisp, raster based fonts on rot.js :)
I agree that some kind of a code sample specifically for this case might be useful. Perhaps a blogpost or a fiddle or a roguebasin wiki page.
I think if you were to provide a visual comparison between these 2 rendering strategies (aliased fonts vs crisp raster tileImage fonts) and ask your users "which looks better" you might find that more people than you expect would want the crisp behavior. and it's not that hard to put a note in one of the main documentation pages. We're talking about 3-4 sentences to enable the crisp rendering.
We're talking about 3-4 sentences to enable the crisp rendering.
Right. Can you please confirm that this only applies to retina-like setups with devicePixelRatio > 1
? I do not have currently any of these devices available and my current setup does not show any difference with/without the image-rendering
property, as the raster tiles are always 1:1 (always crisp).
Can you please confirm that this only applies to retina-like setups with devicePixelRatio > 1?
confirmed
I added a paragraph mentioning this into the Manual: https://ondras.github.io/rot.js/manual/#tiles
looks good. I'll close this issue, since there is a way to achieve the desired effect and it's somewhat documented in the manual. Thanks for taking the time to work with me on this!
Here is text rendered on my screen via rot.js [1] :
Here is text rendered on my screen via some library called malison [2] [3]:
Both use a
<canvas>
element to display these grids. Is there a way to get rot.js to render text crisply, without this blurring/anti-aliasing? Mywindow.devicePixelRatio
is 2.[1] https://ondras.github.io/rot.js/manual/#display
[2] https://github.com/munificent/malison
[3] http://munificent.github.io/hauberk/