0 Daumen
130 Aufrufe

Ich muss einen Negativshader programmieren für ein videospiel in unity. Kann mir einer erklären wie das geht? Auch von der Mathematik her?

Gefragt von

1 Antwort

+5 Daumen
 
Beste Antwort

Ein "Negative-Shader" ist mathematisch nicht sonderlich spannend. Gehen wir vom RGB-Farbraum mit einem Farbvektor \(v=\left(\begin{matrix}\mathrm{r}&\mathrm{g}&\mathrm{b}\end{matrix}\right)^T\) aus, musst Du zur Berechnung des entsprechend negativen Pendants lediglich jede Farbvektorkomponente von \(255\) abziehen, also 
$$v'=\left(\begin{matrix}255\\255\\255\end{matrix}\right)-\left(\begin{matrix}\mathrm{r}\\\mathrm{g}\\\mathrm{b}\end{matrix}\right)=\left(\begin{matrix}255-\mathrm{r}\\255-\mathrm{g}\\255-\mathrm{b}\end{matrix}\right)$$Unity rechnet allerdings mit Werten bezogen auf \(1.0\), was sich durch eine Division durch \(255\) leicht umrechnen lässt (solltest Du mit Online-Tools experimentieren, die in \(\left\{x\in\mathbb{N}_0\mid 0\leq x\leq 255\right\}\) rechnen). Glücklicherweise liest Unity die Textur auch direkt mit diesen Werten ein, wodurch Du keine Umrechnung durchführen musst. 

Eine mögliche Lösung für den Shader könnte so aussehen:

Shader "Negative" {

    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {}
    }

    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200
        CGINCLUDE

      #include "UnityCG.cginc"

        sampler2D _MainTex;

        // Funktion zur Negation von Farbwerten
        float4 negate (sampler2D tex, float2 uv) {
            float4 texel = tex2D(tex, uv);
            texel.x = 1.0 - texel.x;
            texel.y = 1.0 - texel.y;
            texel.z = 1.0 - texel.z;
            return texel;
        }

        // Funktion, mit der die Bildverarbeitung durchgeführt wird.
        float4 frag (v2f_img IN) : COLOR {
            // Farbwertberechnung
            float4 frag_color = negate(_MainTex, IN.uv);
            return float4(frag_color.x, frag_color.y, frag_color.z, 1.0);
        }

        ENDCG

        Pass {
            CGPROGRAM
                #pragma vertex vert_img
                #pragma fragment frag
                ENDCG
        }
    }
    FallBack Off
}

Dieser Code ist als .shader-Datei zu speichern und an ein benutzerdefiniertes Material zu binden. Das Material kann dann einem (Game-)Object zugewiesen werden. Mein Test liefert: 

COLs.png
Ich habe mal für meine VR-Brille einen Kantendetektor (nach Laplace) in Unity geschrieben, der dann auch in Echtzeit den visuellen Input gerendert hat. Das sieht schon schick aus ;-) Da die Berechnung dafür weitaus komplexer ist, sollte das mit dem Negativeshader auch gehen. Willst Du das in Kombination mit VR nutzen oder einfach "nur" zur Modellierung?

Beantwortet von 7,8 k

Tschuldige aber ich verstehe den Code absolut nicht :D das sieht sehr kompliziert aus. wenn der geht ist mir das aber auch egal :)) irgendwie ändert sich nichts wenn ich das material verwende. weisst du woran das liegen könnte, ich habe das so gemacht wie du es beschrieben hast oder ihc habe was vergessen?

Erzeuge ein Material:
1.pngSchiebe die Shader-Datei auf das Material:

2.png

Das Material sollte nun folgendermaßen aussehen:

3.png

Ziehe das Material auf das Bild in der Szene:

4.pngSollte es dann immer noch Probleme geben, müsstest Du schon etwas präziser werden.

Wenn Du noch andere Shader programmieren willst, kannst Du den obigen Code als Rahmenprogramm verwenden. Du musst lediglich in der Funktion 

float4 frag (v2f_img IN) : COLOR

Mit entsprechenden Anpassungen der Umrechnungsfunktionen, die in dem durch { } gekapselten Block aufgerufen werden.

jetzt gehts!!!!! ich hatte vergessen die bunte datei auf das material zu ziehen.

Ein anderes Problem?

Stell deine Frage

Willkommen bei der Stacklounge! Stell deine Frage sofort und kostenfrei

x
Made by a lovely community
...