12

In Unity, when writing shaders,

is it possible for the shader itself to "know" what the screen resolution is, and indeed for the shader to control single physical pixels?

I'm thinking only of the case of writing shaders for 2D objects (such as for UI use, or at any event with an ortho camera).

(Of course, normally to show a physical-pixel perfect PNG on screen, you merely have a say 400 pixel PNG, and you arrange scaling so that the shader, happens to be drawing to, precisely 400 physical pixels. What I'm wondering about is a shader that just draws, for example a physical-pixel perfect black line - it would have to "know" exactly where the physical-pixels are.)

Fattie
  • 27,874
  • 70
  • 431
  • 719

4 Answers4

7

There is a ShaderLab built-in value called _ScreenParams.

_ScreenParams.x is the screen width in pixels. _ScreenParams.y is the screen height in pixels.

Here's the documentation page: http://docs.unity3d.com/462/Documentation/Manual/SL-BuiltinValues.html

HalpPlz
  • 691
  • 4
  • 11
5

I don't think this is going to happen. Your rendering is tied to current selected video mode and it doesn't even have to match your physical screen size (if that is what you mean by pixel-perfect).

The closest you are going to get with this is if you render at recommended resolution for your display device and use pixel shader to shade an entire screen. This way, one 'physical pixel' is going to be roughly equal to one actual rendered pixel. Other than that, it is impossible to associate physical (that is your display's) pixels to rendered ones.

This is unless, of course, I somehow misunderstood your intentions.

MarengoHue
  • 1,789
  • 13
  • 34
  • Hi MM. Fascinating. TBC then, there's just no way to access "physical screen pixel count" from the shader then. (I've noticed folks often do this as a "trick" by having a helper script pass it in as a number, from outside.) – Fattie Jan 22 '16 at 17:43
  • The problem is physical screen has very little to do with actual rendering which is carried out by your graphics card, which in turn knows about video mode, not actual display size. – MarengoHue Jan 22 '16 at 17:50
  • Gotchya. That explanation is a great help. Look, when looking at my ordinary Mac right now, the small orange square "Questions" at the top of this web page, is indeed rendered in a physical-pixel-perfect manner. (I just enlarged that and triple-checked that!) And Safari / the operating system does that on various screen sizes. What's the deal there? – Fattie Jan 22 '16 at 17:57
  • 1
    Passing physical screen size as a constant to a shader is not a trick but a well-known and a pretty easy practice. It's even better if you calculate stuff you need for your shader in a c# script and pass that along instead of calculating constants based on screen size in shader. – Valentin Simonov Jan 24 '16 at 22:44
4

is it possible for the shader itself to "know" what the screen resolution is

I don't think so.

and indeed for the shader to control single physical pixels?

Yes. Pixel shaders know what pixel they are drawing and can also sample other pixels.

Ted Bigham
  • 4,237
  • 1
  • 26
  • 31
  • Ahhhhhh .. so when you say they know "what pixel" they are drawing on ..... you mean that's certainly a PHYSICAL pixel? Is that right? there are so many layers of abstraction, it's difficult to understand these things if you're a non-expert. – Fattie Jan 22 '16 at 23:42
  • So -- to clarify my question -- to be sure to be sure, these "pixel shaders" you mention, to clarify, one would actually WORK DIFFERENTLY if on a 1024 screen, when the same app is on a 1600 screen ... am I on the right track? – Fattie Jan 22 '16 at 23:43
  • is it true that "fragment shader" is literally another word for "pixel shader" -- they two different terms for exactly the same thing? or, do I have it all wrong? thanks for this!! – Fattie Jan 22 '16 at 23:44
  • 1
    It depends on what you mean by PHYSICAL pixel. If you mean (for example) the 1280x720 distinct addressable pixels, then yes the pixel shader knows which one it's drawing. If you're taking about the lower level hardware that physically makes up monitor, then the shader will only know that if the monitor is in its native mode. – Ted Bigham Jan 23 '16 at 07:47
  • 1
    The pixel shader should not operate differently for a different resolution screen. It will just have a different range of pixels thrown at it from the vertex shader. The vertex shader will behave differently depending on many things, including the screen resolution. – Ted Bigham Jan 23 '16 at 08:10
  • 1
    Pixel shader is from HLSL, and fragment shader is Cg. They are pretty much the same things, but it also implies which system you are using. – Ted Bigham Jan 23 '16 at 08:10
2

First of all, please define 'Pixel perfect' and 'Physical pixel'.

If by physical pixel you mean your display's pixel (monitor, laptop display, any other hardware you might use) then you are out of luck. Shaders don't operate on those, they operate on their own 'abstract pixels'.

You can think about it in this way: Your graphics are rendered in a picture with some configurable resolution (say 800x600 pixels). You can still display this picture on a 1920x1080 display in full screen no problem, it would look crappy though. This is what's happening with actual display and video card rendering. What determines the actual amount of rendered pixels is your video mode (picture's resolution in the above example). And physical pixels are your display's pixels. When rendering you can only operate on the first kind.

This leads us to a conclusion that when you render the graphics at the exact same resolution as your display's native resolution, you can safely say that you endeed render it as 'Physical Pixels'.

In unity, you can pass the renderer some external data (this might include your current screen resolution (for example as a Vector2, see this). However you most likely don't need any of this, since pixel shaders already operate on pixels (rendered pixels, determined by your current video mode). That means that if you use some resolution which is lesser than your native one, you most likely will not be able to render a single pixel.

Hope it helped.

Fattie
  • 27,874
  • 70
  • 431
  • 719
MarengoHue
  • 1,789
  • 13
  • 34
  • Hi MM, hmm, it's trivial to get the physical pixels of a display in native programming, and it is always available in Unity, too. HalpPlz is saying it indeed *is available* in ShaderLab! _ScreenParams.x ... which is great news. – Fattie Feb 03 '16 at 12:38
  • BTW here on SO, to see all the edits of a question, just click the "edited..." link (just under the question tags to the right) – Fattie Feb 03 '16 at 12:41
  • I am pretty sure that _ScreenParams.x is referring to the resolution defined by the Video Mode, not the actual display size. – MarengoHue Feb 04 '16 at 11:19
  • Right, it seems to be the "current render target width" – Fattie Feb 04 '16 at 12:27