Search Unity

Offset parameters

Discussion in 'Shaders' started by besuser, May 18, 2009.

  1. besuser

    besuser

    Joined:
    Oct 9, 2007
    Posts:
    292
    The docs say:
    Offset Factor, Units

    But I can't figure out what this means. I presume factor is a multiplier for the units, but in what direction? Toward/Away from the camera? Along the surface normal?

    I'm trying to simulate a highlight effect by stacking mesh clones with different materials, but I'm having difficulty getting the highlight material to render on top. I tried to utilize the options given in the BlendedDecal shader from the wiki, but it doesn't seem to make any difference how I set the offset values.

    Here's my current attempt in case my problem is obvious:

    Shader "Vertex Highlight Constant" {
    Properties {
    _Color ("Main Color", Color) = (1,1,1,1)
    _MainTex ("Base (RGB)", 2D) = "white" {}
    }

    SubShader {

    ColorMaterial AmbientAndDiffuse
    Lighting Off
    SeperateSpecular Off
    ZTest LEqual
    ZWrite Off
    Tags{"Queue" = "Transparent"}

    Pass {
    Offset -1, -1

    SetTexture [_MainTex] {
    Combine texture * primary, texture * primary
    }
    SetTexture [_MainTex] {
    constantColor [_Color]
    Combine previous * constant, previous * constant
    }
    }
    }

    Fallback " VertexLit", 1
    }
     
  2. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    I am also interested in an answer for this.
     
  3. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    The offset is towards or away from the camera. The way the values are used is complicated, because it's implementation-dependent. You can find a little more information in the OpenGL docs for glPolygonOffset(), but it's probably down to trial and error in the end.
     
  4. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    Thanks. From this statement...

    ...it would seem to me that the offset values ought to be (1, -1), for the usage found in this thread, but it's (-1, -1) instead. Why is that? It seems to me that you should multiply the depth by 1, and then move closer by r. Why doesn't multiplying by -1 place the polygons behind the camera?

    (I don't know much about OpenGL yet.)
     
  5. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    If both coefficients are negative, the result is a negative offset, reducing depth (bringing the vertex closer to the camera).
     
  6. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    I don't understand that.

    1 * DZ + r * -1

    suggests to me that you take the Z-depth of what is onscreen, then move it closer by the smallest allowable amount. Obviously I'm not understanding what DZ is.

    -1 * DZ

    suggests to me that you take the distance from the camera of what is onscreen, and move it behind the camera by that distance.
     
  7. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    The result of that equation is the offset, not the depth. The offset is added to the computed depth of the vertices. DZ is not just Z depth. As you quoted, "DZ is a measurement of the change in depth relative to the screen area of the polygon." I don't know exactly what this means, but it sounds like a derivative of depth with respect to screen position.
     
  8. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    Here's what we want from the OpenGL FAQ:
     
  9. Zergling103

    Zergling103

    Joined:
    Aug 16, 2011
    Posts:
    392
    Here's a pet peeve of mine:

    Offset OffsetFactor , OffsetUnits
    Set depth offset. Note that this command intentionally only accepts constants (i.e., not shader parameters) as of Unity 3.0.

    intentionally

    intentionally

    why.jpg

    Honeslty. Why? Why can't you let us make our own decisions? Why do you assume we have no idea what we are doing and purposefully impose limitations to keep us safe from some nonexistent danger? ._.
     
    Last edited: Oct 19, 2012
    howong and ViktorKom like this.
  10. Ludeme Games

    Ludeme Games

    Joined:
    Aug 3, 2012
    Posts:
    9
    I also am very unhappy about the inability to set the offset as a per material parameter right now. If anyone knows a workaround for this please reply.
     
    howong and ViktorKom like this.
  11. aciil

    aciil

    Joined:
    May 4, 2018
    Posts:
    3
    Late follow up but it should save a headache to someone as its near first hint when researching usage of Offset.
    Parameterize Offsets works for me in unity 2018 with extremely high units, such large as -+1000000 range. I am not sure this is intended.
     
    Last edited: Aug 6, 2020
  12. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,350
    So, this is a pretty crazy thread necro, and there are probably other posts that explain why but I'll explain it again here.

    Offset
    is an graphics API feature, not something Unity created. This is important because of how it's specified in the OpenGL spec. Or more importantly how it is not specified.
    https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPolygonOffset.xhtml

    That part I bolded, "implementation-specific", means it's up to whatever the GPU manufacturer decides it is. Which means every single GPU is a little different... Or sometimes a lot different. Also note the feature is intended to be used for pushing two things that are coplanar be slightly not coplanar. Which means two surfaces that are overlapping and flickering, this is supposed to let you make one be slightly closer to the camera so it's in top. If you're trying to use it to move something closer to the camera by a significant distance, anything more than "ever so slightly", it's probably not what you want to use.
     
    levelappstudios likes this.
  13. aciil

    aciil

    Joined:
    May 4, 2018
    Posts:
    3
    Yeah on the topic of shifting depth alone. Until you noted depth change per unit is undefined between systems I was thinking it a simpler solution of depth layering passes (such as outline hulls) precisely without doing extra clip matrix math in vertex.
     
  14. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,350
    Doing a clip z offset in the vertex shader is cheaper than using
    Offset
    , as strange as that sounds. Offset is applied after the fragment is processed, which means the GPU can't do any early fragment rejection, and means you pay the cost of the entire mesh being drawn even if it's behind other objects. Adjusting the clip position in the vertex shader means the GPU can still do rejection of occluded fragments.
     
  15. Nil_xd

    Nil_xd

    Joined:
    Mar 2, 2021
    Posts:
    1
    Would you mind explaining "clip z offset in vertex shader" a bit further?
     
  16. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,350
    The position the vertex shader outputs is the homogeneous clip space position. It's 4 component position representing a -w to +w "on screen" range on the x and y, and either -w to +w or 0.0 to w on the z "in near / far plane" range, with the w being either the view space depth or 1.0 depending on if it's a perspective or orthographic projection.

    You can partially replicate an
    Offset
    using something like this:
    Code (csharp):
    1. // the code you usually see in a vertex shader to calculate the clip space position
    2. o.pos = UnityObjectToClipPos(v.vertex)
    3.  
    4. // offset z with a very small value
    5. // note this is positive unlike the Offset render state values
    6. float offset = 0.00001;
    7. #if defined(UNITY_REVERSED_Z)
    8. // all APIs but OpenGL use a reversed depth, so add to bring closer to the camera
    9. o.pos.z += offset * o.pos.w;
    10. #else
    11. // else if OpenGL you need to subtract to bring closer to the camera
    12. o.pos.z -= offset * o.pos.w;
    13. #endif
    Adjust that
    offset
    value to whatever you need to get it to be visible.

    The real
    Offset
    does quite a bit more than just that one offset towards the camera, but it's implementation changes between different APIs, and even different devices, so there's no "one" implementation. For Direct3D the spec for this is an offset "unit" of 1.0 (second value) will offset the depth by exactly the smallest floating point precision for the current depth value, where as the "factor" offsets based on a bit of a magic number depending on how much the surface is facing away from the camera, and even on Direct3D the implementation appears to be device specific.