الكاميرا في unity (الجزء الأول)

culling

وهي عملية تحديد الكائنات التي سوف يتم رسمها

Camera.main.cullingMask = LayerMask.GetMask (new[] {"layer1"});//تحدديد الطبقات التي تراها الكاميرا
float[] distances = new float[32];// تحديد مسافة الرؤية لكل طبقة
distances[LayerMask.NameToLayer("layer1")] = 3;
Camera.main.layerCullDistances = distances;
Camera.main.layerCullSpherical = true;// تحديد نوع مقياس المسافة عن الكاميرا بالاعتماد على العمق "فولس" او بحساب المسافة بين موقع الكائن والكاميرا "اون"

culling matrix

Camera.main.cullingMatrix = cullingCamera.projectionMatrix * cullingCamera.worldToCameraMatrix;

 Camera.main.ResetCullingMatrix ();// for disable culling matrix

افترض ان لديك كاميرا اخرى اسمها cullingCamera واردت فقط ان ترى العناصر التي تراها الكاميرا الأخرى دون ان تلعب في ابعادها بالنسبة للكاميرا الاصلية وهذا مايقوم به الكود السابق .

وفي حال اردت للكاميرا ان تعمل rendering لمشهد دون الآخر

Camera.scene=SceneManagement.Scene

camera events

هي messages ترسلها unity للتعامل مع احداث الكاميرا بعضها يجب ان تكون في component في كائن الكاميرا وبعضها يمكن وضعها في اي كائن مرئي (renderable).
يتم تنفيذ الدوال التالية لكل كامير في المشهد كاميرا ثم الكاميرا الذي تليها ويستثنى منها OnBecameVisible و OnBecameInvisible فيتم تنفيذهم عندم تتغير حالة الكائن بين مرئي وغير مرئي .

لمعرفة الكاميرا الحالية التي تتم فيها العمليات

Camera.current
  1. OnPreCull توضع داخل الكاميرا ويتم استدعائها قبل عمل  culling للمشهد .
  2. OnBecameVisible وتوضع داخل الكائن ويتم استدعائها عندما يكون الكائن مرئي من قبل كاميرا واحدة على الأقل
  3. OnBecameInvisible وتوضع داخل الكائن ويتم استدعائها عندما يكون الكائن غير مرئي من جميع الكاميرات
  4. OnWillRenderObject تضعها للكائنات ويتم استدعائها لكل كاميرا يشاهد هذا العنصر لذلك يتم استدعائها اكثر من مرة في كل frame .
  5. OnPreRender توضع في الكاميرا ويتم استدعائها قبل عمل Render للمشهد
  6. OnPostRender توضع داخل الكاميرا ويتم استدعائها عند الانتهاء من عمل rendering للمشهد
  7. OnRenderObject توضع داخل ال object وهي مشابهة ل OnPostRender
  8. OnRenderImage توضع داخل الكاميرا وتستخدم لعمل تأثيرات للصورة النهائية للمشهد

مثال قلب المشهد على المحور y

void OnPreCull()
{
	Camera.main.ResetWorldToCameraMatrix();
	Camera.main.ResetProjectionMatrix();
	Camera.main.projectionMatrix = Camera.main.projectionMatrix * Matrix4x4.Scale(new Vector3(1, -1, 1));
}

// Set it to true so we can watch the flipped Objects
void OnPreRender()
{
	GL.invertCulling = true;
}

// Set it to false again because we dont want to affect all other cammeras.
void OnPostRender()
{
	GL.invertCulling = false;
}

مثال عمل  image effects  عن طريق OnRenderImage

public class ExampleClass : MonoBehaviour {
    public Material mat;
    void OnRenderImage(RenderTexture src, RenderTexture dest) {
        Graphics.Blit(src, dest, mat);
    }
}

مثال رسم في OnRenderObject

public class ExampleClass : MonoBehaviour {
    public Mesh mainMesh;
    public Mesh miniMapMesh;
    void OnRenderObject() {
        if (Camera.current.name == "MiniMapcam")
            Graphics.DrawMeshNow(miniMapMesh, transform.position, transform.rotation);
        else
            Graphics.DrawMeshNow(mainMesh, transform.position, transform.rotation);
    }
}

مثال OnBecameVisible

public class ExampleClass : MonoBehaviour {
    void OnBecameVisible() {
        enabled = true;
    }
}

مثال قراءة محتوى ال frame buffer

public class ExampleClass : MonoBehaviour {
    public bool grab;
    public Renderer display;
    void OnPostRender() {
        if (grab) {
            Texture2D tex = new Texture2D(128, 128);
            tex.ReadPixels(new Rect(0, 0, 128, 128), 0, 0);
            tex.Apply();
            display.material.mainTexture = tex;
            grab = false;
        }
    }
}

 

billboard

وهو ان يكون الكائن اتجاهه مواجه للكاميرا

//y facing z in camera
Vector3 zcameraDirection=Camera.main.transform.TransformDirection (Vector3.forward);
Vector3 ycameraDirection=Camera.main.transform.TransformDirection (Vector3.up);
this.gameObject.transform.rotation = Quaternion.LookRotation (ycameraDirection,zcameraDirection * -1);
//or z facing to z in camera
transform.LookAt(transform.position + Camera.main.transform.rotation * Vector3.forward,
	Camera.main.transform.rotation * Vector3.up);