From 6e9c3acaa4e321d70940783dc9bbfb65974e6d20 Mon Sep 17 00:00:00 2001 From: Maicon Date: Sun, 29 Jun 2025 09:04:58 +0100 Subject: [PATCH 1/8] Add run examples using zig and emscripten for web --- build.zig | 244 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 178 insertions(+), 66 deletions(-) diff --git a/build.zig b/build.zig index e445bf576..754078534 100644 --- a/build.zig +++ b/build.zig @@ -4,6 +4,9 @@ const builtin = @import("builtin"); /// Minimum supported version of Zig const min_ver = "0.13.0"; +const emccOutputDir = "zig-out" ++ std.fs.path.sep_str ++ "htmlout" ++ std.fs.path.sep_str; +const emccOutputFile = "index.html"; + comptime { const order = std.SemanticVersion.order; const parse = std.SemanticVersion.parse; @@ -45,6 +48,26 @@ fn emSdkSetupStep(b: *std.Build, emsdk: *std.Build.Dependency) !?*std.Build.Step } } +// Adaoted from Not-Nik/raylib-zig +fn emscriptenRunStep(b: *std.Build, emsdk: *std.Build.Dependency, examplePath: []const u8) !*std.Build.Step.Run { + const dot_emsc_path = emsdk.path("upstream/emscripten/cache/sysroot/include").getPath(b); + // If compiling on windows , use emrun.bat. + const emrunExe = switch (builtin.os.tag) { + .windows => "emrun.bat", + else => "emrun", + }; + var emrun_run_arg = try b.allocator.alloc(u8, dot_emsc_path.len + emrunExe.len + 1); + defer b.allocator.free(emrun_run_arg); + + if (b.sysroot == null) { + emrun_run_arg = try std.fmt.bufPrint(emrun_run_arg, "{s}", .{emrunExe}); + } else { + emrun_run_arg = try std.fmt.bufPrint(emrun_run_arg, "{s}" ++ std.fs.path.sep_str ++ "{s}", .{ dot_emsc_path, emrunExe }); + } + const run_cmd = b.addSystemCommand(&.{ emrun_run_arg, examplePath }); + return run_cmd; +} + /// A list of all flags from `src/config.h` that one may override const config_h_flags = outer: { // Set this value higher if compile errors happen as `src/config.h` gets larger @@ -85,6 +108,9 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. "-D_GNU_SOURCE", "-DGL_SILENCE_DEPRECATION=199309L", "-fno-sanitize=undefined", // https://github.com/raysan5/raylib/issues/3674 + // This is off by default but some linux distributions have it on by default + // No Stack Protector is set to prevent the issues when running the examples for emscripten + "-fno-stack-protector", }); if (options.shared) { @@ -511,12 +537,9 @@ fn addExamples( optimize: std.builtin.OptimizeMode, raylib: *std.Build.Step.Compile, ) !*std.Build.Step { - if (target.result.os.tag == .emscripten) { - return &b.addFail("Emscripten building via Zig unsupported").step; - } - const all = b.step(module, "All " ++ module ++ " examples"); const module_subpath = b.pathJoin(&.{ "examples", module }); + const module_resources = b.pathJoin(&.{ module_subpath, "resources@resources" }); var dir = try std.fs.cwd().openDir(b.pathFromRoot(module_subpath), .{ .iterate = true }); defer if (comptime builtin.zig_version.minor >= 12) dir.close(); @@ -530,71 +553,160 @@ fn addExamples( // zig's mingw headers do not include pthread.h if (std.mem.eql(u8, "core_loading_thread", name) and target.result.os.tag == .windows) continue; - const exe = b.addExecutable(.{ - .name = name, - .target = target, - .optimize = optimize, - }); - exe.addCSourceFile(.{ .file = b.path(path), .flags = &.{} }); - exe.linkLibC(); + if (target.result.os.tag == .emscripten) { + const exe_lib = b.addStaticLibrary(.{ + .name = name, + .target = target, + .optimize = optimize, + }); + exe_lib.addCSourceFile(.{ + .file = b.path(path), + .flags = &.{ + "-fno-stack-protector", + }, + }); + exe_lib.linkLibC(); + exe_lib.rdynamic = true; - // special examples that test using these external dependencies directly - // alongside raylib - if (std.mem.eql(u8, name, "rlgl_standalone")) { - exe.addIncludePath(b.path("src")); - exe.addIncludePath(b.path("src/external/glfw/include")); - if (!hasCSource(raylib.root_module, "rglfw.c")) { - exe.addCSourceFile(.{ .file = b.path("src/rglfw.c"), .flags = &.{} }); + exe_lib.root_module.addCMacro("PLATFORM_WEB", ""); + exe_lib.shared_memory = false; + exe_lib.root_module.single_threaded = false; + + if (std.mem.eql(u8, name, "raylib_opengl_interop")) { + exe_lib.addIncludePath(b.path("src/external")); } + + exe_lib.linkLibrary(raylib); + + // Include emscripten for cross compilation + if (b.lazyDependency("emsdk", .{})) |emsdk_dep| { + if (try emSdkSetupStep(b, emsdk_dep)) |emSdkStep| { + exe_lib.step.dependOn(&emSdkStep.step); + } + + exe_lib.addIncludePath(emsdk_dep.path("upstream/emscripten/cache/sysroot/include")); + // addAssets(b, exe_lib); + // Create the output directory because emcc can't do it. + + const emccOutputDirExample = b.pathJoin(&.{ emccOutputDir, name, std.fs.path.sep_str }); + const mkdir_command = switch (builtin.os.tag) { + .windows => b.addSystemCommand(&.{ "cmd.exe", "/c", "if", "not", "exist", emccOutputDirExample, "mkdir", emccOutputDirExample }), + else => b.addSystemCommand(&.{ "mkdir", "-p", emccOutputDirExample }), + }; + + const emcc_exe = switch (builtin.os.tag) { // TODO bundle emcc as a build dependency + .windows => "emcc.bat", + else => "emcc", + }; + + const emcc_exe_path = b.pathJoin(&.{ emsdk_dep.path("upstream/emscripten").getPath(b), emcc_exe }); + const emcc_command = b.addSystemCommand(&[_][]const u8{emcc_exe_path}); + emcc_command.step.dependOn(&mkdir_command.step); + const emccOutputDirExampleWithFile = b.pathJoin(&.{ emccOutputDir, name, std.fs.path.sep_str, emccOutputFile }); + emcc_command.addArgs(&[_][]const u8{ + "-o", + emccOutputDirExampleWithFile, + "-sFULL-ES3=1", + "-sUSE_GLFW=3", + "-sSTACK_OVERFLOW_CHECK=1", + "-sASYNCIFY", + "-O0", + "--emrun", + "--preload-file", + module_resources, + "--shell-file", + b.path("src/shell.html").getPath(b), + }); + + const link_items: []const *std.Build.Step.Compile = &.{ + raylib, + exe_lib, + }; + for (link_items) |item| { + emcc_command.addFileArg(item.getEmittedBin()); + emcc_command.step.dependOn(&item.step); + } + + const run_step = emscriptenRunStep(b, emsdk_dep, emccOutputDirExampleWithFile) catch |err| { + // do some stuff, maybe log an error + std.debug.print("EmscriptenRunStep error: {}\n", .{err}); + continue; + }; + run_step.step.dependOn(&emcc_command.step); + run_step.addArg("--no_browser"); + const run_option = b.step(name, name); + + run_option.dependOn(&run_step.step); + + all.dependOn(&emcc_command.step); + } + } else { + const exe = b.addExecutable(.{ + .name = name, + .target = target, + .optimize = optimize, + }); + exe.addCSourceFile(.{ .file = b.path(path), .flags = &.{} }); + exe.linkLibC(); + + // special examples that test using these external dependencies directly + // alongside raylib + if (std.mem.eql(u8, name, "rlgl_standalone")) { + exe.addIncludePath(b.path("src")); + exe.addIncludePath(b.path("src/external/glfw/include")); + if (!hasCSource(raylib.root_module, "rglfw.c")) { + exe.addCSourceFile(.{ .file = b.path("src/rglfw.c"), .flags = &.{} }); + } + } + if (std.mem.eql(u8, name, "raylib_opengl_interop")) { + exe.addIncludePath(b.path("src/external")); + } + + exe.linkLibrary(raylib); + + switch (target.result.os.tag) { + .windows => { + exe.linkSystemLibrary("winmm"); + exe.linkSystemLibrary("gdi32"); + exe.linkSystemLibrary("opengl32"); + + exe.root_module.addCMacro("PLATFORM_DESKTOP", ""); + }, + .linux => { + exe.linkSystemLibrary("GL"); + exe.linkSystemLibrary("rt"); + exe.linkSystemLibrary("dl"); + exe.linkSystemLibrary("m"); + exe.linkSystemLibrary("X11"); + + exe.root_module.addCMacro("PLATFORM_DESKTOP", ""); + }, + .macos => { + exe.linkFramework("Foundation"); + exe.linkFramework("Cocoa"); + exe.linkFramework("OpenGL"); + exe.linkFramework("CoreAudio"); + exe.linkFramework("CoreVideo"); + exe.linkFramework("IOKit"); + + exe.root_module.addCMacro("PLATFORM_DESKTOP", ""); + }, + else => { + @panic("Unsupported OS"); + }, + } + + const install_cmd = b.addInstallArtifact(exe, .{}); + + const run_cmd = b.addRunArtifact(exe); + run_cmd.cwd = b.path(module_subpath); + run_cmd.step.dependOn(&install_cmd.step); + + const run_step = b.step(name, name); + run_step.dependOn(&run_cmd.step); + + all.dependOn(&install_cmd.step); } - if (std.mem.eql(u8, name, "raylib_opengl_interop")) { - exe.addIncludePath(b.path("src/external")); - } - - exe.linkLibrary(raylib); - - switch (target.result.os.tag) { - .windows => { - exe.linkSystemLibrary("winmm"); - exe.linkSystemLibrary("gdi32"); - exe.linkSystemLibrary("opengl32"); - - exe.root_module.addCMacro("PLATFORM_DESKTOP", ""); - }, - .linux => { - exe.linkSystemLibrary("GL"); - exe.linkSystemLibrary("rt"); - exe.linkSystemLibrary("dl"); - exe.linkSystemLibrary("m"); - exe.linkSystemLibrary("X11"); - - exe.root_module.addCMacro("PLATFORM_DESKTOP", ""); - }, - .macos => { - exe.linkFramework("Foundation"); - exe.linkFramework("Cocoa"); - exe.linkFramework("OpenGL"); - exe.linkFramework("CoreAudio"); - exe.linkFramework("CoreVideo"); - exe.linkFramework("IOKit"); - - exe.root_module.addCMacro("PLATFORM_DESKTOP", ""); - }, - else => { - @panic("Unsupported OS"); - }, - } - - const install_cmd = b.addInstallArtifact(exe, .{}); - - const run_cmd = b.addRunArtifact(exe); - run_cmd.cwd = b.path(module_subpath); - run_cmd.step.dependOn(&install_cmd.step); - - const run_step = b.step(name, name); - run_step.dependOn(&run_cmd.step); - - all.dependOn(&install_cmd.step); } return all; } From 8f50436dc924cd8696d0fea1bf21ec8de521dfa3 Mon Sep 17 00:00:00 2001 From: Maicon Date: Sun, 29 Jun 2025 09:11:41 +0100 Subject: [PATCH 2/8] Fix comments --- build.zig | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/build.zig b/build.zig index 754078534..214de2970 100644 --- a/build.zig +++ b/build.zig @@ -585,9 +585,8 @@ fn addExamples( } exe_lib.addIncludePath(emsdk_dep.path("upstream/emscripten/cache/sysroot/include")); - // addAssets(b, exe_lib); - // Create the output directory because emcc can't do it. + // Create the output directory because emcc can't do it. const emccOutputDirExample = b.pathJoin(&.{ emccOutputDir, name, std.fs.path.sep_str }); const mkdir_command = switch (builtin.os.tag) { .windows => b.addSystemCommand(&.{ "cmd.exe", "/c", "if", "not", "exist", emccOutputDirExample, "mkdir", emccOutputDirExample }), @@ -628,7 +627,6 @@ fn addExamples( } const run_step = emscriptenRunStep(b, emsdk_dep, emccOutputDirExampleWithFile) catch |err| { - // do some stuff, maybe log an error std.debug.print("EmscriptenRunStep error: {}\n", .{err}); continue; }; From 1db006b0825f7e0bb2db59f2aa683211857f8388 Mon Sep 17 00:00:00 2001 From: Colin Woodbury Date: Mon, 30 Jun 2025 05:40:17 +0900 Subject: [PATCH 3/8] docs: mention another Common Lisp binding --- BINDINGS.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/BINDINGS.md b/BINDINGS.md index 986c27abc..719a902a0 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -18,6 +18,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [cl-raylib](https://github.com/longlene/cl-raylib) | 4.0 | [Common Lisp](https://common-lisp.net) | MIT | | [claylib/wrap](https://github.com/defun-games/claylib) | 4.5 | [Common Lisp](https://common-lisp.net) | Zlib | | [claw-raylib](https://github.com/bohonghuang/claw-raylib) | **auto** | [Common Lisp](https://common-lisp.net) | Apache-2.0 | +| [raylib](https://github.com/fosskers/raylib) | 5.5 | [Common Lisp](https://common-lisp.net) | MPL-2.0 | | [chez-raylib](https://github.com/Yunoinsky/chez-raylib) | **auto** | [Chez Scheme](https://cisco.github.io/ChezScheme) | GPLv3 | | [CLIPSraylib](https://github.com/mrryanjohnston/CLIPSraylib) | **auto** | [CLIPS](https://www.clipsrules.net/) | MIT | | [raylib-cr](https://github.com/sol-vin/raylib-cr) | 4.6-dev (5e1a81) | [Crystal](https://crystal-lang.org) | Apache-2.0 | @@ -50,7 +51,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [raylib-luajit-generated](https://github.com/james2doyle/raylib-luajit-generated) | 5.5 | [Lua](http://www.lua.org) | MIT | | [raylib-matte](https://github.com/jcorks/raylib-matte) | 4.6-dev | [Matte](https://github.com/jcorks/matte) | **???** | | [Raylib.nelua](https://github.com/AuzFox/Raylib.nelua) | **5.5** | [nelua](https://nelua.io) | Zlib | -| [raylib-bindings](https://github.com/vaiorabbit/raylib-bindings) | 5.6-dev | [Ruby](https://www.ruby-lang.org/en) | Zlib | +| [raylib-bindings](https://github.com/vaiorabbit/raylib-bindings) | 5.6-dev | [Ruby](https://www.ruby-lang.org/en) | Zlib | | [naylib](https://github.com/planetis-m/naylib) | **5.6-dev** | [Nim](https://nim-lang.org) | MIT | | [node-raylib](https://github.com/RobLoach/node-raylib) | 4.5 | [Node.js](https://nodejs.org/en) | Zlib | | [raylib-odin](https://github.com/odin-lang/Odin/tree/master/vendor/raylib) | **5.5** | [Odin](https://odin-lang.org) | BSD-3Clause | From 0cae8890b85395285df3767de4baf1925148b8ea Mon Sep 17 00:00:00 2001 From: Maicon Date: Mon, 30 Jun 2025 09:54:20 +0100 Subject: [PATCH 4/8] Remove -fno-stack-protector as it is not needed and add requestFullscreen on exported methods --- build.zig | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/build.zig b/build.zig index 214de2970..4026a23eb 100644 --- a/build.zig +++ b/build.zig @@ -108,9 +108,6 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. "-D_GNU_SOURCE", "-DGL_SILENCE_DEPRECATION=199309L", "-fno-sanitize=undefined", // https://github.com/raysan5/raylib/issues/3674 - // This is off by default but some linux distributions have it on by default - // No Stack Protector is set to prevent the issues when running the examples for emscripten - "-fno-stack-protector", }); if (options.shared) { @@ -365,7 +362,6 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. setDesktopPlatform(raylib, options.platform); }, .emscripten => { - // Include emscripten for cross compilation if (b.lazyDependency("emsdk", .{})) |dep| { if (try emSdkSetupStep(b, dep)) |emSdkStep| { raylib.step.dependOn(&emSdkStep.step); @@ -561,19 +557,17 @@ fn addExamples( }); exe_lib.addCSourceFile(.{ .file = b.path(path), - .flags = &.{ - "-fno-stack-protector", - }, + .flags = &.{}, }); exe_lib.linkLibC(); - exe_lib.rdynamic = true; - - exe_lib.root_module.addCMacro("PLATFORM_WEB", ""); - exe_lib.shared_memory = false; - exe_lib.root_module.single_threaded = false; + if (std.mem.eql(u8, name, "rlgl_standalone")) { + //TODO: Make rlgl_standalone example work + continue; + } if (std.mem.eql(u8, name, "raylib_opengl_interop")) { - exe_lib.addIncludePath(b.path("src/external")); + //TODO: Make raylib_opengl_interop example work + continue; } exe_lib.linkLibrary(raylib); @@ -593,7 +587,7 @@ fn addExamples( else => b.addSystemCommand(&.{ "mkdir", "-p", emccOutputDirExample }), }; - const emcc_exe = switch (builtin.os.tag) { // TODO bundle emcc as a build dependency + const emcc_exe = switch (builtin.os.tag) { .windows => "emcc.bat", else => "emcc", }; @@ -608,6 +602,7 @@ fn addExamples( "-sFULL-ES3=1", "-sUSE_GLFW=3", "-sSTACK_OVERFLOW_CHECK=1", + "-sEXPORTED_RUNTIME_METHODS=['requestFullscreen']", "-sASYNCIFY", "-O0", "--emrun", @@ -626,10 +621,7 @@ fn addExamples( emcc_command.step.dependOn(&item.step); } - const run_step = emscriptenRunStep(b, emsdk_dep, emccOutputDirExampleWithFile) catch |err| { - std.debug.print("EmscriptenRunStep error: {}\n", .{err}); - continue; - }; + const run_step = try emscriptenRunStep(b, emsdk_dep, emccOutputDirExampleWithFile); run_step.step.dependOn(&emcc_command.step); run_step.addArg("--no_browser"); const run_option = b.step(name, name); From eef1bac3e249212e2d83da48c71a4ca73cf535b3 Mon Sep 17 00:00:00 2001 From: Maicon Santana Date: Mon, 30 Jun 2025 19:38:34 +0100 Subject: [PATCH 5/8] fix misspelling --- build.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.zig b/build.zig index 4026a23eb..14e9af21e 100644 --- a/build.zig +++ b/build.zig @@ -48,7 +48,7 @@ fn emSdkSetupStep(b: *std.Build, emsdk: *std.Build.Dependency) !?*std.Build.Step } } -// Adaoted from Not-Nik/raylib-zig +// Adapted from Not-Nik/raylib-zig fn emscriptenRunStep(b: *std.Build, emsdk: *std.Build.Dependency, examplePath: []const u8) !*std.Build.Step.Run { const dot_emsc_path = emsdk.path("upstream/emscripten/cache/sysroot/include").getPath(b); // If compiling on windows , use emrun.bat. From bee524e5e6443a8abe6ae76a943db6109a26171f Mon Sep 17 00:00:00 2001 From: sir-irk Date: Tue, 1 Jul 2025 13:23:05 -0500 Subject: [PATCH 6/8] fixing offset for processing tangents for gltf loading --- src/rmodels.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/rmodels.c b/src/rmodels.c index 84daabc15..ac6f4c594 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -5577,7 +5577,7 @@ static Model LoadGLTF(const char *fileName) } else TRACELOG(LOG_WARNING, "MODEL: [%s] Normal attribute data format not supported, use vec3 float", fileName); } - else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_tangent) // TANGENT, vec3, float + else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_tangent) // TANGENT, vec4, float, w is tangent basis sign { cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data; @@ -5593,10 +5593,10 @@ static Model LoadGLTF(const char *fileName) float *tangents = model.meshes[meshIndex].tangents; for (unsigned int k = 0; k < attribute->count; k++) { - Vector3 tt = Vector3Transform((Vector3){ tangents[3*k], tangents[3*k+1], tangents[3*k+2] }, worldMatrix); - tangents[3*k] = tt.x; - tangents[3*k+1] = tt.y; - tangents[3*k+2] = tt.z; + Vector3 tt = Vector3Transform((Vector3){ tangents[4*k], tangents[4*k+1], tangents[4*k+2] }, worldMatrix); + tangents[4*k] = tt.x; + tangents[4*k+1] = tt.y; + tangents[4*k+2] = tt.z; } } else TRACELOG(LOG_WARNING, "MODEL: [%s] Tangent attribute data format not supported, use vec4 float", fileName); From f86295732a5a15156917d2b92696826bae72ac6d Mon Sep 17 00:00:00 2001 From: sir-irk Date: Tue, 1 Jul 2025 15:18:11 -0500 Subject: [PATCH 7/8] fixing shader tangents to be vec4 --- examples/shaders/resources/shaders/glsl100/pbr.vs | 6 +++--- examples/shaders/resources/shaders/glsl120/pbr.vs | 8 ++++---- examples/shaders/resources/shaders/glsl330/pbr.vs | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/shaders/resources/shaders/glsl100/pbr.vs b/examples/shaders/resources/shaders/glsl100/pbr.vs index a55c0ea4b..079ccdc70 100644 --- a/examples/shaders/resources/shaders/glsl100/pbr.vs +++ b/examples/shaders/resources/shaders/glsl100/pbr.vs @@ -4,7 +4,7 @@ attribute vec3 vertexPosition; attribute vec2 vertexTexCoord; attribute vec3 vertexNormal; -attribute vec3 vertexTangent; +attribute vec4 vertexTangent; attribute vec4 vertexColor; // Input uniform values @@ -52,7 +52,7 @@ mat3 transpose(mat3 m) void main() { // Compute binormal from vertex normal and tangent - vec3 vertexBinormal = cross(vertexNormal, vertexTangent); + vec3 vertexBinormal = cross(vertexNormal, vertexTangent.xyz) * vertexTangent.w; // Compute fragment normal based on normal transformations mat3 normalMatrix = transpose(inverse(mat3(matModel))); @@ -62,7 +62,7 @@ void main() fragTexCoord = vertexTexCoord*2.0; fragNormal = normalize(normalMatrix*vertexNormal); - vec3 fragTangent = normalize(normalMatrix*vertexTangent); + vec3 fragTangent = normalize(normalMatrix*vertexTangent.xyz) * vertexTangent.w; fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal); vec3 fragBinormal = normalize(normalMatrix*vertexBinormal); fragBinormal = cross(fragNormal, fragTangent); diff --git a/examples/shaders/resources/shaders/glsl120/pbr.vs b/examples/shaders/resources/shaders/glsl120/pbr.vs index d3cc66488..4b68ef673 100644 --- a/examples/shaders/resources/shaders/glsl120/pbr.vs +++ b/examples/shaders/resources/shaders/glsl120/pbr.vs @@ -4,7 +4,7 @@ attribute vec3 vertexPosition; attribute vec2 vertexTexCoord; attribute vec3 vertexNormal; -attribute vec3 vertexTangent; +attribute vec4 vertexTangent; attribute vec4 vertexColor; // Input uniform values @@ -52,7 +52,7 @@ mat3 transpose(mat3 m) void main() { // Compute binormal from vertex normal and tangent - vec3 vertexBinormal = cross(vertexNormal, vertexTangent); + vec3 vertexBinormal = cross(vertexNormal, vertexTangent.xyz) * vertexTangent.w; // Compute fragment normal based on normal transformations mat3 normalMatrix = transpose(inverse(mat3(matModel))); @@ -62,7 +62,7 @@ void main() fragTexCoord = vertexTexCoord*2.0; fragNormal = normalize(normalMatrix*vertexNormal); - vec3 fragTangent = normalize(normalMatrix*vertexTangent); + vec3 fragTangent = normalize(normalMatrix*vertexTangent.xyz) * vertexTangent.w; fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal); vec3 fragBinormal = normalize(normalMatrix*vertexBinormal); fragBinormal = cross(fragNormal, fragTangent); @@ -71,4 +71,4 @@ void main() // Calculate final vertex position gl_Position = mvp*vec4(vertexPosition, 1.0); -} \ No newline at end of file +} diff --git a/examples/shaders/resources/shaders/glsl330/pbr.vs b/examples/shaders/resources/shaders/glsl330/pbr.vs index 6f262313c..a9e65e96c 100644 --- a/examples/shaders/resources/shaders/glsl330/pbr.vs +++ b/examples/shaders/resources/shaders/glsl330/pbr.vs @@ -4,7 +4,7 @@ in vec3 vertexPosition; in vec2 vertexTexCoord; in vec3 vertexNormal; -in vec3 vertexTangent; +in vec4 vertexTangent; in vec4 vertexColor; // Input uniform values @@ -26,7 +26,7 @@ const float normalOffset = 0.1; void main() { // Compute binormal from vertex normal and tangent - vec3 vertexBinormal = cross(vertexNormal, vertexTangent); + vec3 vertexBinormal = cross(vertexNormal, vertexTangent.xyz) * vertexTangent.w; // Compute fragment normal based on normal transformations mat3 normalMatrix = transpose(inverse(mat3(matModel))); @@ -36,7 +36,7 @@ void main() fragTexCoord = vertexTexCoord*2.0; fragNormal = normalize(normalMatrix*vertexNormal); - vec3 fragTangent = normalize(normalMatrix*vertexTangent); + vec3 fragTangent = normalize(normalMatrix*vertexTangent.xyz) * vertexTangent.w; fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal); vec3 fragBinormal = normalize(normalMatrix*vertexBinormal); fragBinormal = cross(fragNormal, fragTangent); @@ -45,4 +45,4 @@ void main() // Calculate final vertex position gl_Position = mvp*vec4(vertexPosition, 1.0); -} \ No newline at end of file +} From ed509193d9d311648f5b6e4010588a1186118f19 Mon Sep 17 00:00:00 2001 From: sir-irk Date: Tue, 1 Jul 2025 15:30:50 -0500 Subject: [PATCH 8/8] remving w multiply on the tangent itself --- examples/shaders/resources/shaders/glsl100/pbr.vs | 2 +- examples/shaders/resources/shaders/glsl120/pbr.vs | 2 +- examples/shaders/resources/shaders/glsl330/pbr.vs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/shaders/resources/shaders/glsl100/pbr.vs b/examples/shaders/resources/shaders/glsl100/pbr.vs index 079ccdc70..baf003842 100644 --- a/examples/shaders/resources/shaders/glsl100/pbr.vs +++ b/examples/shaders/resources/shaders/glsl100/pbr.vs @@ -62,7 +62,7 @@ void main() fragTexCoord = vertexTexCoord*2.0; fragNormal = normalize(normalMatrix*vertexNormal); - vec3 fragTangent = normalize(normalMatrix*vertexTangent.xyz) * vertexTangent.w; + vec3 fragTangent = normalize(normalMatrix*vertexTangent.xyz); fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal); vec3 fragBinormal = normalize(normalMatrix*vertexBinormal); fragBinormal = cross(fragNormal, fragTangent); diff --git a/examples/shaders/resources/shaders/glsl120/pbr.vs b/examples/shaders/resources/shaders/glsl120/pbr.vs index 4b68ef673..e9750a60a 100644 --- a/examples/shaders/resources/shaders/glsl120/pbr.vs +++ b/examples/shaders/resources/shaders/glsl120/pbr.vs @@ -62,7 +62,7 @@ void main() fragTexCoord = vertexTexCoord*2.0; fragNormal = normalize(normalMatrix*vertexNormal); - vec3 fragTangent = normalize(normalMatrix*vertexTangent.xyz) * vertexTangent.w; + vec3 fragTangent = normalize(normalMatrix*vertexTangent.xyz); fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal); vec3 fragBinormal = normalize(normalMatrix*vertexBinormal); fragBinormal = cross(fragNormal, fragTangent); diff --git a/examples/shaders/resources/shaders/glsl330/pbr.vs b/examples/shaders/resources/shaders/glsl330/pbr.vs index a9e65e96c..8aabb6baf 100644 --- a/examples/shaders/resources/shaders/glsl330/pbr.vs +++ b/examples/shaders/resources/shaders/glsl330/pbr.vs @@ -36,7 +36,7 @@ void main() fragTexCoord = vertexTexCoord*2.0; fragNormal = normalize(normalMatrix*vertexNormal); - vec3 fragTangent = normalize(normalMatrix*vertexTangent.xyz) * vertexTangent.w; + vec3 fragTangent = normalize(normalMatrix*vertexTangent.xyz); fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal); vec3 fragBinormal = normalize(normalMatrix*vertexBinormal); fragBinormal = cross(fragNormal, fragTangent);