Ein generelles Problem an Shader ist, dass das Ergebnis massiv davon abhängt, was du überhaupt in den Shader reingibts. Du musst also genau wissen, was für Werte in welcher Form erwartet werden und diese dann auch genau so liefern.
Normalmapping ansich ist eigentlich trivial: Anstatt den Normalvektor pro Vertex zu setzen, liest du ihn aus einer Textur. Das ist schon alles. Schwieriger wird es dann, wenn man die Details betrachtet: Was steht überhaupt in der Normalmap? Wie muss welcher Farbkanal interpretiert werden, wie bekomme ich meinen Normalvektor aus der Farbe? In welchem Koordinatensystem ist dieser Vektor dann überhaupt? Ist die Textur für Tangentspace-Mapping oder Modelspace-Mapping vorgesehen? In welchem Koordinatensystem führe ich die Lichtberechnung durch? Muss ich die Lichtrichtung oder die Normalen transformieren? Vielleicht auch beide, oder keine von beiden?
Du kannst nicht einfach einen Normalmapping Shader von irgendwo kopieren und hoffen, dass er bei dir funktioniert. Bei all den oben gestellten Fragen gibt es kein Richtig oder Falsch, nahezu jede Kombination funktioniert, sie haben nur unterschiedliche Vor- und Nachteile. Aber solange du nicht auf jede Frage eine eindeutige Antwort für dein gesamtes Programm hast, wird das Ergebnis immer irgendwie falsch sein. Und DAS ist es, was Shaderprogrammierung kniffelig macht. Zumindest solange du nur Dinge wie Normalmapping umsetzen willst.
Mein Tipp: Versteht, was du tust. Dann musst du auch keinen Shader-Code kopieren, der bei dir eh nicht funktioniert. Sobald du verstanden hast, was genau du überhaupt machen möchtest, ist die Umsetzung eigentlich sehr einfach. Und solange du es nicht verstanden hast, wird dir vermutlich auch niemand sagen können, wo dein Fehler ist (eben weil das Gesamtproblem komplex ist und hier lange nicht alle Infos stehen, die nötig wären).