3D Light Shader wird vor d3d_transform_set_identity angewandt

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • 3D Light Shader wird vor d3d_transform_set_identity angewandt

    Hallo zusammen,
    da die von GameMaker bereitgestellte Lichtengine sehr begrenzt und verbuggt ist, habe ich mich mal etwas mit Shadern beschäftigt und zufälligerweise etwas zum laufen gebracht, was funktioniert :D (Bin darin sehr unerfahren)
    Nun aber zu meinem Problem, wenn ich die d3d_transform_set_identity() - Funktion anwende und mein Objekt z.B. drehe wird das Licht so berechnet, als wäre mein Objekt noch nicht verdreht. Was am Ende dann falsche Ergebnisse liefert, wenn ich es drehe. Über Hilfe wäre ich sehr dankbar.

    Der Draw Code von meinem Objekt:

    GML-Quellcode

    1. d3d_transform_set_identity()
    2. d3d_transform_add_rotation_y(90);
    3. d3d_transform_add_rotation_z(direction+180);
    4. d3d_transform_add_translation(x,y,0);
    5. shader_set(sh_light_range)
    6. shader_set_uniform_f(shader_pos_light, o_light.x-x, o_light.y-y , 0); //o_light.x und y wird minus x und y gerechnet, da durch d3d_transform_add_translation(x,y,0) die Position des Objekt auf (0|0|0) gesetzt und dann gedreht wird.
    7. d3d_draw_block(-4,-4,-4,4,4,4,tex,1,1);
    8. shader_reset()
    9. d3d_transform_set_identity()
    Alles anzeigen


    Fragment-Shader:

    GML-Quellcode

    1. //
    2. // Simple passthrough fragment shader
    3. //
    4. varying vec2 v_vTexcoord;
    5. varying vec4 v_vColour;
    6. varying vec3 v_vNormal;
    7. varying vec3 v_vPosition;
    8. uniform vec3 LightPos;
    9. void main()
    10. {
    11. vec3 PixelPos = v_vPosition;
    12. vec3 VectorToLight = normalize(LightPos - PixelPos);
    13. float BrightnessAngle = clamp(dot(VectorToLight,v_vNormal),0.,1.); // Winkel zwischen Oberfläche und Lichtposition wird berechnet. Flacher Winkel = Dunkler , senkrechter Winkel = hell
    14. vec3 position = PixelPos.xyz - LightPos.xyz;
    15. float BrightnessDistance = clamp(1.-length(position)/300.,0.,1.); // Helligkeit auf Distanz vermindern
    16. float Brightness = (BrightnessAngle*BrightnessDistance)+0.1; // Gesamte Helligkeit berechnen + 0.1 für Ambiente
    17. gl_FragColor = vec4(v_vColour.r*Brightness,v_vColour.g*Brightness,v_vColour.b*Brightness,v_vColour.a) * texture2D( gm_BaseTexture, v_vTexcoord );
    18. }
    Alles anzeigen


    MFG
    Husi012 hat mich nicht mehr in seiner Signatur, ich bin trotzdem noch fame.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Dufner ()

  • Du musst die lichtnormale mit der transponierten inversen welttransformationsmatrix multiplizieren.
    Auf der alten GMC hat einer so eine Funktion mit einem kleinen codesnippet gepostet die du in den shader copy&pasten kannst:
    gmc.yoyogames.com/index.php?showtopic=587700&page=1
  • Erstmal vielen Dank Für die schnelle Antwort, werde das mal ausprobieren.

    Wie ich sehe hast du deutlich mehr Ahnung als ich in diesem Bereich, leider finde ich keine Tutorials im Internet welche mir wirklich alles genau beschreiben. Ich wäre mega froh darüber, falls du mir Tutorials empfehlen kannst, damit ich das alles hier in Zukunft auch verstehe :D

    LEWA schrieb:

    Du musst die lichtnormale mit der transponierten inversen welttransformationsmatrix multiplizieren.
    Husi012 hat mich nicht mehr in seiner Signatur, ich bin trotzdem noch fame.
  • Habe leider keine direkten tutorials die ich empfehlen könnte. (Das meiste wass ich weiss hat sich mit der Zeit durch selbstexperimente und recherche gesammelt.)
    Falls du schwierigkeiten hasst den code in den shader einzubauen habe ich das mal schnell für dich gemacht. :)

    GML-Quellcode

    1. //
    2. // Simple passthrough fragment shader
    3. //
    4. varying vec2 v_vTexcoord;
    5. varying vec4 v_vColour;
    6. varying vec3 v_vNormal;
    7. varying vec3 v_vPosition;
    8. uniform vec3 LightPos;
    9. mat3 TransposeInverse(mat4 M)
    10. {
    11. mat3 NormalMatrix;
    12. NormalMatrix[0][0] = (M[1][1] * M[2][2] - M[1][2] * M[2][1]);
    13. NormalMatrix[1][0] = (M[0][2] * M[2][1] - M[0][1] * M[2][2]);
    14. NormalMatrix[2][0] = (M[0][1] * M[1][2] - M[0][2] * M[1][1]);
    15. NormalMatrix[0][1] = (M[1][2] * M[2][0] - M[1][0] * M[2][2]);
    16. NormalMatrix[1][1] = (M[0][0] * M[2][2] - M[0][2] * M[2][0]);
    17. NormalMatrix[2][1] = (M[0][2] * M[1][0] - M[0][0] * M[1][2]);
    18. NormalMatrix[0][2] = (M[1][0] * M[2][1] - M[1][1] * M[2][0]);
    19. NormalMatrix[1][2] = (M[0][1] * M[2][0] - M[0][0] * M[2][1]);
    20. NormalMatrix[2][2] = (M[0][0] * M[1][1] - M[0][1] * M[1][0]);
    21. return NormalMatrix;
    22. }
    23. void main()
    24. {
    25. vec3 PixelPos = v_vPosition;
    26. vec3 VectorToLight = normalize(LightPos - PixelPos);
    27. //normal kalkulation
    28. mat3 NormalMatrix = TransposeInverse(gm_Matrices[MATRIX_WORLD]);
    29. vec3 wvNormal = normalize(NormalMatrix * v_vNormal);
    30. float BrightnessAngle = clamp(dot(VectorToLight,wvNormal ),0.,1.); // Winkel zwischen Oberfläche und Lichtposition wird berechnet. Flacher Winkel = Dunkler , senkrechter Winkel = hell
    31. vec3 position = PixelPos.xyz - LightPos.xyz;
    32. float BrightnessDistance = clamp(1.-length(position)/300.,0.,1.); // Helligkeit auf Distanz vermindern
    33. float Brightness = (BrightnessAngle*BrightnessDistance)+0.1; // Gesamte Helligkeit berechnen + 0.1 für Ambiente
    34. gl_FragColor = vec4(v_vColour.r*Brightness,v_vColour.g*Brightness,v_vColour.b*Brightness,v_vColour.a) * texture2D( gm_BaseTexture, v_vTexcoord );
    35. }
    Alles anzeigen


    //Edit: UPS! Grade bemerkt dass dies der fragment shader ist. *facepalm*
    Wenn die Matrix_world im fragmentshader existiert,sollte das trotzdem funktionieren, aber performanter waere es dies im vertex shader zu machen:

    GML-Quellcode

    1. //im vertex shader:
    2. //nachdem du v_vNormal definiert hast
    3. mat3 NormalMatrix = TransposeInverse(gm_Matrices[MATRIX_WORLD]);
    4. v_vNormal = normalize(NormalMatrix * v_vNormal);


  • Man braucht hier nicht unbedingt die transponierte Matrix. Die Matrix MATRIX_WORLD allein reicht hier aus, indem man den vierten des Vektors auf Null setzt. Dadurch wird eine Verschiebung verhindert und nur der Vektor gedreht und skaliert. Das einzige Problem besteht hier bei einer ungleichmäßigen Skalierung, sollte aber wesentlich schneller funktionieren.

    Quellcode

    1. v_vNormal = normalize(gm_Matrices[MATRIX_WORLD] * vec4(v_vNormal, 0.0)).xyz;


    Wie lautetet denn dein Vertex shader?

  • Bis jetzt hatte ich leider noch keine Zeit, mich etwas mehr damit zu beschäftigen. Werde ich aber in Zukunft noch nachholen und habe mich mal nach Büchern für GLSL umgeschaut. Leider sind diese, wo ich bis jetzt auf deutsch finden konnte, etwas veraltet.

    Der Code von @Chris987 funktioniert bis jetzt schon mal und habe den einfach mal kurz kopiert, da er anscheinend schneller ist und nur eine Zeile braucht. Danke an beide für die Hilfe! ^^

    Edit:
    Der Vertexshader ist bis auf die Übergabe von Normalen der selbe. Die Lichtberechnung mache ich gewollt über den Fragmentshaderm da ich mit Lowpolygonen arbeite ^^
    Husi012 hat mich nicht mehr in seiner Signatur, ich bin trotzdem noch fame.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Dufner ()