Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

Quad Outline Color "Wrong"

A topic by RubyDev created 37 days ago Views: 155 Replies: 20
Viewing posts 1 to 21
(2 edits)
It seems the entire image of the quad is blended with the outline color instead of replaced with the outline color. This does not result in an authentic outline color. Example here is this brown-orange, if I make the outline brown-orange I'd expect the "background"-quads to also get this outline color.

Alternatively it would be nice if quads could avoid outlines all together.

Fortunately I have a workaround in my game, as I only need 1 type of outline color (a close-but-not-actually-black-tone) and I found a fix in tinkering with the shader, checking if the vertex color is magenta (a color I'll never use) and then adjust the color. This way the fragment function can determine if it's currently drawing an outline or not (because magenta is the signal that it's an outline) and then not consider the mask.rgb and give out the authentic outline color.

if(i.color.r == 1 && i.color.b == 1 && i.color.g == 0)
{
    col.rgb = i.color.rgb;
} else
{
    col.rgb = mask.rgb * i.color.rgb;
}
col.a = text.a * mask.a * i.color.a;

Would be interested if there was a better way to solve this cause it would be nice if my fix wasn't so hacky. Also my fix doesn't solve wanting e.g.: this brown outline (even though nobody ever probably wants an ugly outline like this, I just chose it to visualize the effect it has on the quad)

I wasn't able to find another topic here on the forum or anywhere else that spoke about this issue. Maybe everybody just uses black outlines and it never appeared.

EDIT: The more I thinker with it, I don't understand the choice that quads get an outline in general, it's tough to make work for using icons. Do you think there could be a way to disable that? Or is it so ingrained in the shader functionality that that's just the way it works?

EDIT2: I got another question. Would it ever be possible to make quad size independent of font size? Because I use pixel icons but I offer in the game that the player can chose different fonts, e.g.: pixel font but also HD font. Problem is, they have different sizes (font sizes) base-line, which translates to different font-sizes for the component, which then means the icon has different size because the quad size is relative. :( 

Developer

Hey!


1)  

Basically, Unity's default "outline" component (which I've only added support for in the last update, so still seeing its limitations...) will do this to render outlines: Take the existing vert, set the colour to the desired colour, and move it a bit. So when it actually renders, the same coloured *texture* is still applied, but now multiplied by the outline colour. If you set a quad's color mode to "silhouette", you can see *that* works as expected, since the quad will render as if it's text, relying on vertex colour to receive color. This behaviour would happen if a quad is rendered on the default "Text Mesh" component as well.


To fix this, I'd have to either change it so STM somehow provides a different Material to the Outline component, which clears the "mask" property that provides the texture used on non-silhouette quads, or make a custom outline script that does this... For both of these, while Unity *does* have the IMaterialModifier interface similar to the IMeshModifer interface used by the outline component, but I can't seem to find a way to wedge it between the actual render and the outline, either both or neither, giving the same result as a silhouette quad. So I don't think there's a way to do this with the default outline component...


The included "Ultra" shader has its own outline rendering technique that avoids this by the way, since I can manipulate textures in a shader in a way I can't in C#, will that work for you instead of the Outline component? 


Additionally, the shader you're editing there seems to be doing exactly what the silhouette quads do anyway, I think... Where if there's no "mask" it ends up multiplying by 1, ignoring the mask. So... if that's the result you're after, I'd suggest changing the "Color Mode" of quads to "Silhouette".


2) 

Not sure if this is properly feasible, since there's multiple ways to tackle outlines and I don't want to lock stuff down too much... You could set it up so that typing quads looks like this: <m=default><q=myQuad></m> to switch materials mid-string though? More on this in the next answer:


3) 

Similar to the last one, but I've run into this myself thinking it would be convenient for pixel-based fonts to force a specific size. I decided against it, since while you can assign an integer to a quad saying "always render at this size"! You also have to factor in things like pixel-to-unit ratios, where a quad rendering at a size of 16 might look fine on a canvas, but be way too big outside of a canvas... so things could end up inconsistent in the same project. So the solution I ended up going with was like the last one: Write some code for STM's pre-parsing event that forces quads to a specific size, but on a per-mesh basis! (e.g. spits out a string like <size=0.16><q=myQuad></size> when it sees a <q=x> tag.) I've got some example regex code in the "links" sample scene, but let me know if you'd like this solution, I just have to clean up my own messy code that does this exact thing.



So... short version: Try the outlines on the Ultra shader, try setting your quads to be silhouettes, and per-mesh quad resizing is how I'd go about this and I really should include that as a utility script asap.

Thanks for the quick and friendly reply! 

For 2) that's actually an interesting idea to swap material and thus also shader, that would actually fix that issue!

For 3) that's also a good idea, I will try to do this. Basically you mean with the <size> tag I can force a font size and thus "force" the relative size to always be absolute? That's kinda genius, I will try that.

I must admit I couldn't sit still so I started working on a "sub-system" which will basically tokenize and split text into elements and layouting. It splits the text into objects and wraps them automatically cause that way I can maybe use my own image components in the middle of text.

Developer

Hey, whatever solution works for you, works! But yes, there's a lot of text tags and rendering settings to play around with. (for example, <s=float> sets relative size, while <size=float> sets the size variable directly)


You might also want to look at "STMPagination" included in one of the sample scenes. (Maybe I should move this to the Utilities folder...) which lets you automatically have one text mesh read into another, which could have useful code for formatting like this.


I kinda want to make the script I was working on into a generic regex editor now, so I'll see what I can do in terms of that... but whatever gets the desired end result is good!

(1 edit)

Playing around with the ultra shader right now and it seems nice!
Is there any downside to using the ultra shader? (Performance?!)

I also already got the consistent icon size going using the <size> tag! About to try not giving it an outline by swapping to another material. 
EDIT: Yep that works... perfectly. 

Developer

I don't think the performance is too much of an impact... the original goal with the Ultra shader was to replace the other ones, but if text just needs to render simply, I may as well include a more basic shader to use/use for editing.


There's *one* small downside, which I'm currently fixing, but it's such a rare use-case that no one has reported it for a year until I noticed it myself last week. Already got workarounds for it btw, just deciding on the best one to implement.


And awesome, make sure to set up materials with the Text Data editor! But if you've already figured out quads you're probably familiar with this system already.

(1 edit)

One small question (cause I couldn't find, or I don't know where to look in the documentation) but can I "extend" the bounds of text?
E.g.: to show thicker outlines?
I assume for this one e.g.: on the 'A' it cuts off cause the rect isn't big enough. IIRC TextMeshPro had some sort of "extra padding" flag, not sure if something similar exists in your asset.

 

EDIT: And thanks for the reply on the Ultra shader question.

Developer

Oh jeez, the Ultra shader should be doing exactly what you're describing - I pushed a version earlier this week that *might* have messed something up in that regard, will try and fix ASAP.

(1 edit)

Very cool! 馃榿

Btw. can you explain to me why my icon further up on one font than another? Does this have something to do with what's the size of the font or what sort of metric makes this be like it? Got any suggestion how I could make it more consistent to align with "bottom of the text" or is this just issue with fonts I am using?

Maybe there exists some tag magic again that I could use to fix this, lol.

EDIT: I guess <y=-0.2> kinda did it, would just need to save somewhere how much icon offset every font approx. needs.

Developer

Yep, this is exactly what I encountered when doing pixel things myself, probably better to keep bottom-aligned, and use the <y> tag for alignment with different fonts/sizes. Whatever script is controlling the size on a per-mesh basis could implement this, too.

Thanks for the crazy live-tech support! Do not regret buying this asset, rewriting a lot of code right now and it's a cool opportunity to implement this.

I stumbled upon one more question, when I make my icon <size=9> but the font is size 8, the line will then be size 9. Is there a tag or something I can use to set line height? 

Developer

Ah right, lines of text are automatically decided by the biggest-sized character in a row. I've never had a request for this before, but I could add a toggle somewhere to disable this and force line heights to be whatever the size set on the text mesh is? Otherwise, you can edit the linespacing value. (You can change this with a tag, too: <lineSpacing=float>)

(1 edit)

I think it would be a nice feature, maybe even a tag? <lineSize>.
I guess I can just math it out myself though, a <lineSpacing=-1> should kinda do the same as if I made the line height 8, instead of 9.

It seems I never run out of questions (though I am heading to bed in 5 minutes over here.):
Is there a way I can set the width of "space"? In TextMeshPro I think this used to be in the Font Asset. I already thought of a workaround using the tab instead of space, (I won't use tab anyways) I just wanted to ask. For some reason some of the pixel fonts I use seem to have a massive space size. I assume it's set by the font and you can't really override it.

Developer

Hm, a sure-fire way to get the width you want would be a blank quad. You could run something on the preparse event to replace all instances of " " with "<q=mySpace>" for example. 


I've considered adding kerning options for instances like this, but most of the time fonts are configured just fine, and I feel it's better to leave it open-ended for solutions that can be modified for different projects... But I should probably include a blank quad replacement script for situations like this, then!

Well the 'space' character is probably appearing quite often, will it be a bad choice for performance to spam the text with invisible quads or is it basically same as drawing any letter?

Developer

It shouldn't be any worse than using a single quad in a string! I'll have to think about a proper solution though, changing the advance of a space without needing to do a substitution can be useful, but choosing an implementation for this is taxing... Like it *could* be the start of a kerning option ScriptableObject, with overrides for specific characters (and potentially overrides for combos of characters), or I could alternatively add a <space>/<space=name>/<space=float> tag, and give that a TextData type to match... Or maybe it would be better as <x> an alternative to <y>? I just did a major update and my head needs a rest before I make more major design decisions, I think...

I understand that completely.

Well for now you solved all my problems! (I assume the outline fix that you already did is coming/came in an update?)

Thanks for the massive help again.

Developer

Hopefully the outline fix works! I *think * just finished it... But on that topic, do outlines for the Ultra shader render differently inside/outside of Unity UI for you? For me, it was just a Unity UI issue, but maybe there's something else I missed? Also, is your Unity version 2020.3 or later?

Can confirm they work on Super Text Mesh 3D.

I am on Unity 2022.3.61f1

I just re-downloaded the asset and it seems to not work for me in UI yet.  It's a world space canvas btw.

My asset version number is 1.14.2 

Developer

Okay, hoping this next patch fixes it, then! Just need a bit more time to implement some other things, but if you send me an email through my website with your invoice no., I can send you a working build

I wasn't able to find an e-mail. Sent you a DM on X (formerly known as twitter).