Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

_CameraToWorld broken?

Discussion in 'Shaders' started by Farfarer, Mar 1, 2013.

  1. Farfarer

    Farfarer

    Joined:
    Aug 17, 2010
    Posts:
    2,249
    Is it back to being broken again?

    Doesn't appear to do anything in my shaders, I'm having to use a script on the camera to feed in a custom one.
     
  2. MarigoldFleur

    MarigoldFleur

    Joined:
    May 12, 2012
    Posts:
    1,353
    Not to be snarky, but has it ever worked?
     
  3. Farfarer

    Farfarer

    Joined:
    Aug 17, 2010
    Posts:
    2,249
    Apparently it was fixed in the 3.x cycle.

    Some of the internal shaders currently use it, too. God knows how.

    Could be it's only activated or updated at certain times.
     
  4. equil

    equil

    Joined:
    Jan 18, 2010
    Posts:
    15
    haven't used that matrix before, but since it isn't in the docs (built-in shader values), perhaps you need to declare it manually in your shader file?

    Of the top of my head i think a workaround could be to transform your camera coordinates by UNITY_MATRIX_IT_MV, followed by _Object2World.
     
  5. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    _CameraToWorld is updated before rendering any camera, and there haven't been changes to its value for ages. It is the local-to-world (without scale) matrix of the camera.

    How is it not working for you?
     
  6. Farfarer

    Farfarer

    Joined:
    Aug 17, 2010
    Posts:
    2,249
    I don't have my code to hand, but I'm pretty sure I'm passing in Camera.cameraToWorldMatrix as my own my own matrix4x4.

    I'm using it to work out the world space position of particles, which appear to have their positions in camera space.

    This doesn't give the same results when I use the built-in _CaneraToWorld.
     
  7. Farfarer

    Farfarer

    Joined:
    Aug 17, 2010
    Posts:
    2,249
    Yeah, just checked and I'm using
    Code (csharp):
    1. function OnPreCull () {
    2.     Shader.SetGlobalMatrix ("_Camera2World", this.camera.cameraToWorldMatrix );
    3. }
    To send my own _Camera2World matrix. The built-in one doesn't give the same results.

    Shader on a 0.5 radius sphere of particles with just the matrix changed and resulting world position displayed as RGB.

    World position is calculated as mul(_Matrix, v.vertex);
     
  8. snlehton

    snlehton

    Joined:
    Jun 11, 2010
    Posts:
    99
    Is _CameraToWorld documented somewhere? Our scripts in Rochard are using it, but I don't see any documentation or references to it...
     
  9. invicticide

    invicticide

    Joined:
    Nov 15, 2009
    Posts:
    109
    I'm having problems with this as well.

    I set up a test like this:
    • In the vertex function, multiply the vertex position by _CameraToWorld and store it in the output struct
    • In the fragment function, return that stored world position as a color
    • In the scene or game view, while paused, rotate the camera around a particle system that uses this shader
    I would expect the color coming out of the shader to remain fixed for any given pixel; after all, the simulation is paused and so the actual world space positions of the particles are not changing. But the actual result is that the color does change as I orbit the camera. That doesn't make any sense to me at all.

    I also tried passing in a custom camera-to-world matrix like so:

    Code (CSharp):
    1. function OnPreCull () {
    2.     Shader.SetGlobalMatrix ("_Camera2World", Camera.main.cameraToWorldMatrix);
    3. }
    ...but I only ever seem to get an identity matrix out of that. Using it in the shader has no effect on anything. :(
     
  10. invicticide

    invicticide

    Joined:
    Nov 15, 2009
    Posts:
    109
    Oh for god's sake, my OnPreCull was never getting called. Now that I corrected that, the custom camera-to-world matrix solution works fine.

    The built-in _CameraToWorld is still wonk as hell, though.
     
    amitshah likes this.
  11. snlehton

    snlehton

    Joined:
    Jun 11, 2010
    Posts:
    99
    One thing that came to my mind. Have you checked if batching could be reason for this not to work correctly? Because if mesh gets batched, the model2world is actually identity (= batched mesh is considered to be a the origin, unaffected).
     
    amitshah likes this.
  12. amitshah

    amitshah

    Joined:
    Dec 15, 2016
    Posts:
    2
    This is still a problem in unity 5.6, I have to pass in the matrix through a custom parameter in OnRenderImage:
    Matrix4x4 MV = camera.cameraToWorldMatrix;
    mat.SetMatrix("_CameraMV", MV);
     
  13. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    The problem is the View and Camera matrixes are different things. They're both related to the camera, but there not identical. Why? I don't know exactly, but to go from view position to world position you need to use the inverse of the View matrix.

    At least as of Unity 5.6, if you have something that's in View space (ie: mul(UNITY_MATRIX_MV, v.vertex) or unity_MatrixMV) you can use unity_MatrixInvV or UNITY_MATRIX_I_V to go from View to World. The built in unity_CameraToWorld is used for going from a depth buffer to world space.

    My guess the difference between the View and Camera is the z axis is inverted, so unity_CameraToWorld expects things in front of the camera to be in positive Z, where unity_MatrixInvV expects things in front of the camera to be in negative Z?