Jump to content
Unity Insider Forum

Kamera und Beleuchtung


Kojote

Recommended Posts

Grüße!

Mir geht folgender Gedanke durch den Kopf. Ich würde gern in meinem UI sowohl beim Spieler als ein beim Target ein aktuelles Bild des Spielers haben.

So wie es bisher hier ist:

687f42906-cat26310c700ffd1b50946842.jpg

Bisher ist dies hier im Beispiel nur ein Platzhalter. Meine Idee ist mit einer extra Camera ein Bild des Gesichts zu machen und unter der ID des jeweiligen Spielers zu sichern. Das Bild wäre ca. 256 x 256 Pixel groß. Man könnte dafür die Screenshot funktion nutzen. Problem ist, dadurch das es ein Multiplayer Spiel ist und die Spieler die Möglichkeit haben ständig ihr Aussehen zu ändern, muss das Bild auch bei jedem anklicken des Ziels aktualisiert werden, was die Sache natürlich komplizierter macht.

Idee 1.:

Jedes mal wenn ein Ziel angeklickt wird, wird eine Kopie des Ziels instanziert, ihm eine Camera verpasst, Bildchen gemacht und dieses dann als Target angezeig, Kopie wird zerstört.

Idee 2.:

Jedes Ziel hat eine zweite Camera die nur das Gesicht rendert und man sich von dieser Camera das Bild holt. Nachteil hier ist, die derzeitige Beleuchtung hat Einfluss auf das Bild, was unschöne Ergebnisse liefern kann. Genauso kann ich nicht wissen, wann der Spieler das Ziel anklickt. Klickt er das Ziel an, während es zum Beispiel gerade gähnt, wird das Zielbild recht komisch werden.

Idee 3.:

Jeder Spieler bekommt eine Camera ans Gesicht gebunden, diese könnte man dann auf eine Rendertexture holen und anzeigen lassen. Problem aber auch hier wieder die Bleuchtung. Ich möchte ein Standardbeleuchtung für das Gesicht haben, nicht die aus der Scene. Wäre aber denke ich nur wieder mit einer Kopie möglich, die ich in einen extra dafür vorgesehenen Raum instanziere.

Frage an euch, habt ihr eine Idee wie man dies umsetzen kann?

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • Kojote changed the title to Kamera und Beleuchtung

Lichter heraus filtern wird nicht funktionieren. Aus dem Grund bin ich jetzt dazu übergangen doch mit Instantiate zu arbeiten und mir eine Kopie des Ziels zu holen.

Von der Kopie wollte ich nun einen Screenshot für ein Image erstellen. Jedoch bekomm ich statt dem erwünschten Bild nur ein weißes bzw. graues leicht durchsichtes Sprite.

        private void Start() {
            renderCam = GetComponent<Camera>();
            StartCoroutine(Screen());
        }

        private IEnumerator Screen() {
            yield return new WaitForEndOfFrame();

            RenderTexture renderTexture = renderCam.targetTexture;

            Texture2D renderResult = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.ARGB32, false);

            renderResult.Apply();
            Rect rect = new Rect(0, 0, renderTexture.width, renderTexture.height);
            renderResult.ReadPixels(rect, 0, 0);


            sr.sprite = Sprite.Create(renderResult, new Rect(0, 0, 128, 128), new Vector2());
        }

Sieht einer hier nen Fehler?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich hab im Netz noch mal eine Schreibweise gefunden, funktioniert bei 24 Leutchen. Außer bei mir...

public IEnumerator CaptureFaceImage(Image image) {
            yield return new WaitForEndOfFrame();

            Debug.LogError("Bitte recht unfreundlich!");

            try {
                // Erstellen des Screenshots
                Debug.LogError("Try");
                RenderTexture rt = new RenderTexture(targetImageWidth, targetImageHeight, 0);
                rt.depth = 24;
                rt.antiAliasing = 8;
                targetCamera.targetTexture = rt;
                targetCamera.RenderDontRestore();
                RenderTexture.active = rt;
                Texture2D texture = new Texture2D(targetImageWidth, targetImageHeight, TextureFormat.ARGB32, false, true);
                texture.ReadPixels(new Rect(0, 0, targetImageWidth, targetImageHeight), 0, 0);
                texture.filterMode = FilterMode.Point;
                texture.Apply();

                targetCamera.targetTexture = null;
                RenderTexture.active = null;
                Destroy(rt);

                // Screenshot an Sprite Uebergeben
                image.sprite = Sprite.Create(texture, new Rect(0, 0, 256, 256), new Vector2(0, 0));

                createImage = false;
            } catch {
                Debug.LogError("Catch");
                image.sprite = emptySprite;

                createImage = false;
            }

            Destroy(avatar);
            targetCamera = null;
            avatar = null;            
        }

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Noch nen Versuch, dieses mal mit Ausgabe als Datei:

RenderTexture rt = new RenderTexture(targetImageWidth, targetImageHeight, 24);
                targetCamera.targetTexture = rt;
                Texture2D screenShot = new Texture2D(targetImageWidth, targetImageHeight, TextureFormat.RGB24, false);
                targetCamera.Render();
                RenderTexture.active = rt;
                screenShot.ReadPixels(new Rect(0, 0, targetImageWidth, targetImageHeight), 0, 0);
                targetCamera.targetTexture = null;
                RenderTexture.active = null;
                Destroy(rt);

                image.sprite = Sprite.Create(screenShot, new Rect(0, 0, 256, 256), new Vector2(0, 0));

                byte[] bytes = screenShot.EncodeToPNG();
                string filename = ScreenShotName(targetImageWidth, targetImageHeight);
                System.IO.File.WriteAllBytes(filename, bytes);
                Debug.Log(string.Format("Took screenshot to: {0}", filename));

Als Bild bekomme ich das:

fl6zi9o3.png

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Glaub ich hab den "Fehler" gefunden, es scheint das "TextureFormat" zu sein.

Nutze ich diese Zeile:

Texture2D texture = new Texture2D(targetImageWidth, targetImageHeight, TextureFormat.RGB24, false, true);

Heraus bekomme ich das:

https://ibb.co/F85C2fb

Nicht sehr schön, aber zumindest mal was mit Farbe. Jetzt muss ich nur noch das richtige TexturFormat für mich finden. 😕

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Fehler gefunden und der war mal richtig blöd zu finden.

Da ich die Camera nur brauche, wenn ich ein Bild machen will, ist die Komponente deaktiviert. Wenn ich ein Bild mache, aktiviere ich bevor ich das Bild machen möchte die Camera. Wenn der Frame zu Ende ist, wird das Bild gemacht. Anscheinend braucht die Camera mehr Zeit um aktiv zu werden.
Sprich, das Bild wird gemacht, während die Camera noch gar nicht aktiv ist. Ich habe jetzt eine kleine Wartezeit zwischen Camera aktivierung und Bilderstellung eingebaut, jetzt funktioniert es.

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Was ich aber nicht verstehe ist das hier:

https://ibb.co/cDzWLt0

Bild unten ist die Scenenbeleuchtung. Bild oben ist eine Kopie des Charakters in einer Box unter der Welt. Das es hier kleine Unterschiede gibt ist normal, an der Belichtung der Box muss ich noch arbeiten. Jedoch was mich verwundert ist die Mitte. Warum ist das Image was von der Camera oben gemacht wird so wenig gesättigt und überhellt?

Ausgabe in Datei bringt auch ein nicht überhelltes Ergebnis:

https://ibb.co/CWN1XKy

Link zu diesem Kommentar
Auf anderen Seiten teilen

Texture2D texture = new Texture2D(targetImageWidth, targetImageHeight, TextureFormat.ARGB32, false, true);

Texture2D Parameter: Width | Height | TextureFormat | MipChain | Linear

Das Projekt läuft auf Linear. Demzufolge dachte ich auch, das bei Linear in diesem Fall auch ein True sein sollte.

Falsch, die Zeile sollte so lauten:

Texture2D texture = new Texture2D(targetImageWidth, targetImageHeight, TextureFormat.ARGB32, false);

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...