Merge branch 'raysan5:master' into pure
This commit is contained in:
commit
6b23824289
58 changed files with 691 additions and 391 deletions
|
|
@ -50,7 +50,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers
|
||||||
| [raylib-matte](https://github.com/jcorks/raylib-matte) | 4.6-dev | [Matte](https://github.com/jcorks/matte) | **???** |
|
| [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.0** | [nelua](https://nelua.io) | Zlib |
|
| [Raylib.nelua](https://github.com/AuzFox/Raylib.nelua) | **5.0** | [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.1-dev** | [Nim](https://nim-lang.org) | MIT |
|
| [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 |
|
| [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 |
|
| [raylib-odin](https://github.com/odin-lang/Odin/tree/master/vendor/raylib) | **5.5** | [Odin](https://odin-lang.org) | BSD-3Clause |
|
||||||
| [raylib_odin_bindings](https://github.com/Deathbat2190/raylib_odin_bindings) | 4.0-dev | [Odin](https://odin-lang.org) | MIT |
|
| [raylib_odin_bindings](https://github.com/Deathbat2190/raylib_odin_bindings) | 4.0-dev | [Odin](https://odin-lang.org) | MIT |
|
||||||
|
|
@ -69,6 +69,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers
|
||||||
| [raylibr](https://github.com/jeroenjanssens/raylibr) | 4.0 | [R](https://www.r-project.org) | MIT |
|
| [raylibr](https://github.com/jeroenjanssens/raylibr) | 4.0 | [R](https://www.r-project.org) | MIT |
|
||||||
| [raylib-ffi](https://github.com/ewpratten/raylib-ffi) | 5.5 | [Rust](https://www.rust-lang.org) | GPLv3 |
|
| [raylib-ffi](https://github.com/ewpratten/raylib-ffi) | 5.5 | [Rust](https://www.rust-lang.org) | GPLv3 |
|
||||||
| [raylib-rs](https://github.com/raylib-rs/raylib-rs) | **5.5** | [Rust](https://www.rust-lang.org) | Zlib |
|
| [raylib-rs](https://github.com/raylib-rs/raylib-rs) | **5.5** | [Rust](https://www.rust-lang.org) | Zlib |
|
||||||
|
| [raylib-ruby](https://github.com/wilsonsilva/raylib-ruby) | 4.5 | [Ruby](https://www.ruby-lang.org) | Zlib |
|
||||||
| [Relib](https://github.com/RedCubeDev-ByteSpace/Relib) | 3.5 | [ReCT](https://github.com/RedCubeDev-ByteSpace/ReCT) | **???** |
|
| [Relib](https://github.com/RedCubeDev-ByteSpace/Relib) | 3.5 | [ReCT](https://github.com/RedCubeDev-ByteSpace/ReCT) | **???** |
|
||||||
| [racket-raylib](https://github.com/eutro/racket-raylib) | 4.0 | [Racket](https://racket-lang.org) | MIT/Apache-2.0 |
|
| [racket-raylib](https://github.com/eutro/racket-raylib) | 4.0 | [Racket](https://racket-lang.org) | MIT/Apache-2.0 |
|
||||||
| [raylib-swift](https://github.com/STREGAsGate/Raylib) | 4.0 | [Swift](https://swift.org) | MIT |
|
| [raylib-swift](https://github.com/STREGAsGate/Raylib) | 4.0 | [Swift](https://swift.org) | MIT |
|
||||||
|
|
|
||||||
2
LICENSE
2
LICENSE
|
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 2013-2024 Ramon Santamaria (@raysan5)
|
Copyright (c) 2013-2025 Ramon Santamaria (@raysan5)
|
||||||
|
|
||||||
This software is provided "as-is", without any express or implied warranty. In no event
|
This software is provided "as-is", without any express or implied warranty. In no event
|
||||||
will the authors be held liable for any damages arising from the use of this software.
|
will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
|
|
||||||
24
build.zig
24
build.zig
|
|
@ -13,9 +13,9 @@ comptime {
|
||||||
|
|
||||||
fn setDesktopPlatform(raylib: *std.Build.Step.Compile, platform: PlatformBackend) void {
|
fn setDesktopPlatform(raylib: *std.Build.Step.Compile, platform: PlatformBackend) void {
|
||||||
switch (platform) {
|
switch (platform) {
|
||||||
.glfw => raylib.defineCMacro("PLATFORM_DESKTOP_GLFW", null),
|
.glfw => raylib.root_module.addCMacro("PLATFORM_DESKTOP_GLFW", ""),
|
||||||
.rgfw => raylib.defineCMacro("PLATFORM_DESKTOP_RGFW", null),
|
.rgfw => raylib.root_module.addCMacro("PLATFORM_DESKTOP_RGFW", ""),
|
||||||
.sdl => raylib.defineCMacro("PLATFORM_DESKTOP_SDL", null),
|
.sdl => raylib.root_module.addCMacro("PLATFORM_DESKTOP_SDL", ""),
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -173,7 +173,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.opengl_version != .auto) {
|
if (options.opengl_version != .auto) {
|
||||||
raylib.defineCMacro(options.opengl_version.toCMacroStr(), null);
|
raylib.root_module.addCMacro(options.opengl_version.toCMacroStr(), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
raylib.addIncludePath(b.path("src/platforms"));
|
raylib.addIncludePath(b.path("src/platforms"));
|
||||||
|
|
@ -191,7 +191,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
|
||||||
try c_source_files.append("src/rglfw.c");
|
try c_source_files.append("src/rglfw.c");
|
||||||
|
|
||||||
if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) {
|
if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) {
|
||||||
raylib.defineCMacro("_GLFW_X11", null);
|
raylib.root_module.addCMacro("_GLFW_X11", "");
|
||||||
raylib.linkSystemLibrary("GLX");
|
raylib.linkSystemLibrary("GLX");
|
||||||
raylib.linkSystemLibrary("X11");
|
raylib.linkSystemLibrary("X11");
|
||||||
raylib.linkSystemLibrary("Xcursor");
|
raylib.linkSystemLibrary("Xcursor");
|
||||||
|
|
@ -211,7 +211,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
|
||||||
, .{});
|
, .{});
|
||||||
@panic("`wayland-scanner` not found");
|
@panic("`wayland-scanner` not found");
|
||||||
};
|
};
|
||||||
raylib.defineCMacro("_GLFW_WAYLAND", null);
|
raylib.root_module.addCMacro("_GLFW_WAYLAND", "");
|
||||||
raylib.linkSystemLibrary("EGL");
|
raylib.linkSystemLibrary("EGL");
|
||||||
raylib.linkSystemLibrary("wayland-client");
|
raylib.linkSystemLibrary("wayland-client");
|
||||||
raylib.linkSystemLibrary("xkbcommon");
|
raylib.linkSystemLibrary("xkbcommon");
|
||||||
|
|
@ -230,16 +230,16 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
|
||||||
} else {
|
} else {
|
||||||
if (options.opengl_version == .auto) {
|
if (options.opengl_version == .auto) {
|
||||||
raylib.linkSystemLibrary("GLESv2");
|
raylib.linkSystemLibrary("GLESv2");
|
||||||
raylib.defineCMacro("GRAPHICS_API_OPENGL_ES2", null);
|
raylib.root_module.addCMacro("GRAPHICS_API_OPENGL_ES2", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
raylib.linkSystemLibrary("EGL");
|
raylib.linkSystemLibrary("EGL");
|
||||||
raylib.linkSystemLibrary("gbm");
|
raylib.linkSystemLibrary("gbm");
|
||||||
raylib.linkSystemLibrary2("libdrm", .{ .use_pkg_config = .force });
|
raylib.linkSystemLibrary2("libdrm", .{ .use_pkg_config = .force });
|
||||||
|
|
||||||
raylib.defineCMacro("PLATFORM_DRM", null);
|
raylib.root_module.addCMacro("PLATFORM_DRM", "");
|
||||||
raylib.defineCMacro("EGL_NO_X11", null);
|
raylib.root_module.addCMacro("EGL_NO_X11", "");
|
||||||
raylib.defineCMacro("DEFAULT_BATCH_BUFFER_ELEMENT", "2048");
|
raylib.root_module.addCMacro("DEFAULT_BATCH_BUFFER_ELEMENT", "");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.freebsd, .openbsd, .netbsd, .dragonfly => {
|
.freebsd, .openbsd, .netbsd, .dragonfly => {
|
||||||
|
|
@ -290,9 +290,9 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
|
||||||
raylib.addIncludePath(dep.path("upstream/emscripten/cache/sysroot/include"));
|
raylib.addIncludePath(dep.path("upstream/emscripten/cache/sysroot/include"));
|
||||||
}
|
}
|
||||||
|
|
||||||
raylib.defineCMacro("PLATFORM_WEB", null);
|
raylib.root_module.addCMacro("PLATFORM_WEB", "");
|
||||||
if (options.opengl_version == .auto) {
|
if (options.opengl_version == .auto) {
|
||||||
raylib.defineCMacro("GRAPHICS_API_OPENGL_ES2", null);
|
raylib.root_module.addCMacro("GRAPHICS_API_OPENGL_ES2", "");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@
|
||||||
|
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.xcode_frameworks = .{
|
.xcode_frameworks = .{
|
||||||
.url = "git+https://github.com/hexops/xcode-frameworks#a6bf82e032d4d9923ad5c222d466710fcc05f249",
|
.url = "git+https://github.com/hexops/xcode-frameworks#9a45f3ac977fd25dff77e58c6de1870b6808c4a7",
|
||||||
.hash = "12208da4dfcd9b53fb367375fb612ec73f38e53015f1ce6ae6d6e8437a637078e170",
|
.hash = "122098b9174895f9708bc824b0f9e550c401892c40a900006459acf2cbf78acd99bb",
|
||||||
.lazy = true,
|
.lazy = true,
|
||||||
},
|
},
|
||||||
.emsdk = .{
|
.emsdk = .{
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,14 @@ elseif (${PLATFORM} MATCHES "Android")
|
||||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
list(APPEND raylib_sources ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)
|
list(APPEND raylib_sources ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)
|
||||||
include_directories(${ANDROID_NDK}/sources/android/native_app_glue)
|
include_directories(${ANDROID_NDK}/sources/android/native_app_glue)
|
||||||
|
|
||||||
|
# NOTE: We remove '-Wl,--no-undefined' (set by default) as it conflicts with '-Wl,-undefined,dynamic_lookup' needed
|
||||||
|
# for compiling with the missing 'void main(void)' declaration in `android_main()`.
|
||||||
|
# We also remove other unnecessary or problematic flags.
|
||||||
|
|
||||||
|
string(REPLACE "-Wl,--no-undefined -Qunused-arguments" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
|
||||||
|
string(REPLACE "-static-libstdc++" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
|
||||||
|
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--exclude-libs,libatomic.a -Wl,--build-id -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--warn-shared-textrel -Wl,--fatal-warnings -u ANativeActivity_onCreate -Wl,-undefined,dynamic_lookup")
|
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--exclude-libs,libatomic.a -Wl,--build-id -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--warn-shared-textrel -Wl,--fatal-warnings -u ANativeActivity_onCreate -Wl,-undefined,dynamic_lookup")
|
||||||
|
|
||||||
find_library(OPENGL_LIBRARY OpenGL)
|
find_library(OPENGL_LIBRARY OpenGL)
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,21 @@ endif ()
|
||||||
# The rlgl_standalone example only targets desktop, without shared libraries.
|
# The rlgl_standalone example only targets desktop, without shared libraries.
|
||||||
if (BUILD_SHARED_LIBS OR NOT ${PLATFORM} MATCHES "Desktop")
|
if (BUILD_SHARED_LIBS OR NOT ${PLATFORM} MATCHES "Desktop")
|
||||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/rlgl_standalone.c)
|
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/rlgl_standalone.c)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# The audio examples fail to link if raylib is built without raudio
|
||||||
|
if (NOT SUPPORT_MODULE_RAUDIO)
|
||||||
|
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/audio/audio_mixed_processor.c)
|
||||||
|
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/audio/audio_module_playing.c)
|
||||||
|
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/audio/audio_music_stream.c)
|
||||||
|
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/audio/audio_raw_stream.c)
|
||||||
|
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/audio/audio_sound_loading.c)
|
||||||
|
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/audio/audio_sound_multi.c)
|
||||||
|
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/audio/audio_stream_effects.c)
|
||||||
|
|
||||||
|
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/embedded_files_loading.c)
|
||||||
|
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/textures/textures_sprite_button.c)
|
||||||
|
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/textures/textures_sprite_explosion.c)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include_directories(BEFORE SYSTEM others/external/include)
|
include_directories(BEFORE SYSTEM others/external/include)
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
# > PLATFORM_ANDROID:
|
# > PLATFORM_ANDROID:
|
||||||
# - Android (ARM, ARM64)
|
# - Android (ARM, ARM64)
|
||||||
#
|
#
|
||||||
# Copyright (c) 2013-2024 Ramon Santamaria (@raysan5)
|
# Copyright (c) 2013-2025 Ramon Santamaria (@raysan5)
|
||||||
#
|
#
|
||||||
# This software is provided "as-is", without any express or implied warranty. In no event
|
# This software is provided "as-is", without any express or implied warranty. In no event
|
||||||
# will the authors be held liable for any damages arising from the use of this software.
|
# will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
#
|
#
|
||||||
# raylib makefile for Android project (APK building)
|
# raylib makefile for Android project (APK building)
|
||||||
#
|
#
|
||||||
# Copyright (c) 2017-2024 Ramon Santamaria (@raysan5)
|
# Copyright (c) 2017-2025 Ramon Santamaria (@raysan5)
|
||||||
#
|
#
|
||||||
# This software is provided "as-is", without any express or implied warranty. In no event
|
# This software is provided "as-is", without any express or implied warranty. In no event
|
||||||
# will the authors be held liable for any damages arising from the use of this software.
|
# will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
#
|
#
|
||||||
# raylib makefile for Web platform
|
# raylib makefile for Web platform
|
||||||
#
|
#
|
||||||
# Copyright (c) 2013-2024 Ramon Santamaria (@raysan5)
|
# Copyright (c) 2013-2025 Ramon Santamaria (@raysan5)
|
||||||
#
|
#
|
||||||
# This software is provided "as-is", without any express or implied warranty. In no event
|
# This software is provided "as-is", without any express or implied warranty. In no event
|
||||||
# will the authors be held liable for any damages arising from the use of this software.
|
# will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ fn add_module(comptime module: []const u8, b: *std.Build, target: std.Build.Reso
|
||||||
exe.linkSystemLibrary("gdi32");
|
exe.linkSystemLibrary("gdi32");
|
||||||
exe.linkSystemLibrary("opengl32");
|
exe.linkSystemLibrary("opengl32");
|
||||||
|
|
||||||
exe.defineCMacro("PLATFORM_DESKTOP", null);
|
exe.root_module.addCMacro("PLATFORM_DESKTOP", "");
|
||||||
},
|
},
|
||||||
.linux => {
|
.linux => {
|
||||||
exe.linkSystemLibrary("GL");
|
exe.linkSystemLibrary("GL");
|
||||||
|
|
@ -55,7 +55,7 @@ fn add_module(comptime module: []const u8, b: *std.Build, target: std.Build.Reso
|
||||||
exe.linkSystemLibrary("m");
|
exe.linkSystemLibrary("m");
|
||||||
exe.linkSystemLibrary("X11");
|
exe.linkSystemLibrary("X11");
|
||||||
|
|
||||||
exe.defineCMacro("PLATFORM_DESKTOP", null);
|
exe.root_module.addCMacro("PLATFORM_DESKTOP", "");
|
||||||
},
|
},
|
||||||
.macos => {
|
.macos => {
|
||||||
exe.linkFramework("Foundation");
|
exe.linkFramework("Foundation");
|
||||||
|
|
@ -65,7 +65,7 @@ fn add_module(comptime module: []const u8, b: *std.Build, target: std.Build.Reso
|
||||||
exe.linkFramework("CoreVideo");
|
exe.linkFramework("CoreVideo");
|
||||||
exe.linkFramework("IOKit");
|
exe.linkFramework("IOKit");
|
||||||
|
|
||||||
exe.defineCMacro("PLATFORM_DESKTOP", null);
|
exe.root_module.addCMacro("PLATFORM_DESKTOP", "");
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
@panic("Unsupported OS");
|
@panic("Unsupported OS");
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ int main(void)
|
||||||
// Update
|
// Update
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// If anyone moves this frame, how far will they move based on the time since the last frame
|
// If anyone moves this frame, how far will they move based on the time since the last frame
|
||||||
// this moves thigns at 10 world units per second, regardless of the actual FPS
|
// this moves things at 10 world units per second, regardless of the actual FPS
|
||||||
float offsetThisFrame = 10.0f*GetFrameTime();
|
float offsetThisFrame = 10.0f*GetFrameTime();
|
||||||
|
|
||||||
// Move Player1 forward and backwards (no turning)
|
// Move Player1 forward and backwards (no turning)
|
||||||
|
|
@ -171,4 +171,4 @@ int main(void)
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ BEGIN
|
||||||
VALUE "FileDescription", "raylib example"
|
VALUE "FileDescription", "raylib example"
|
||||||
VALUE "FileVersion", "1.0"
|
VALUE "FileVersion", "1.0"
|
||||||
VALUE "InternalName", "raylib-example"
|
VALUE "InternalName", "raylib-example"
|
||||||
VALUE "LegalCopyright", "(c) 2024 raylib technologies (@raylibtech)"
|
VALUE "LegalCopyright", "(c) 2025 raylib technologies (@raylibtech)"
|
||||||
//VALUE "OriginalFilename", "raylib_app.exe"
|
//VALUE "OriginalFilename", "raylib_app.exe"
|
||||||
VALUE "ProductName", "raylib-example"
|
VALUE "ProductName", "raylib-example"
|
||||||
VALUE "ProductVersion", "1.0"
|
VALUE "ProductVersion", "1.0"
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,19 @@
|
||||||
in vec3 vertexPosition;
|
in vec3 vertexPosition;
|
||||||
in vec2 vertexTexCoord;
|
in vec2 vertexTexCoord;
|
||||||
in vec4 vertexColor;
|
in vec4 vertexColor;
|
||||||
|
in vec3 vertexNormal;
|
||||||
in vec4 vertexBoneIds;
|
in vec4 vertexBoneIds;
|
||||||
in vec4 vertexBoneWeights;
|
in vec4 vertexBoneWeights;
|
||||||
|
|
||||||
// Input uniform values
|
// Input uniform values
|
||||||
uniform mat4 mvp;
|
uniform mat4 mvp;
|
||||||
|
uniform mat4 matNormal;
|
||||||
uniform mat4 boneMatrices[MAX_BONE_NUM];
|
uniform mat4 boneMatrices[MAX_BONE_NUM];
|
||||||
|
|
||||||
// Output vertex attributes (to fragment shader)
|
// Output vertex attributes (to fragment shader)
|
||||||
out vec2 fragTexCoord;
|
out vec2 fragTexCoord;
|
||||||
out vec4 fragColor;
|
out vec4 fragColor;
|
||||||
|
out vec3 fragNormal;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
|
@ -29,9 +32,18 @@ void main()
|
||||||
vertexBoneWeights.y*(boneMatrices[boneIndex1]*vec4(vertexPosition, 1.0)) +
|
vertexBoneWeights.y*(boneMatrices[boneIndex1]*vec4(vertexPosition, 1.0)) +
|
||||||
vertexBoneWeights.z*(boneMatrices[boneIndex2]*vec4(vertexPosition, 1.0)) +
|
vertexBoneWeights.z*(boneMatrices[boneIndex2]*vec4(vertexPosition, 1.0)) +
|
||||||
vertexBoneWeights.w*(boneMatrices[boneIndex3]*vec4(vertexPosition, 1.0));
|
vertexBoneWeights.w*(boneMatrices[boneIndex3]*vec4(vertexPosition, 1.0));
|
||||||
|
|
||||||
|
vec4 skinnedNormal =
|
||||||
|
vertexBoneWeights.x*(boneMatrices[boneIndex0]*vec4(vertexNormal, 0.0)) +
|
||||||
|
vertexBoneWeights.y*(boneMatrices[boneIndex1]*vec4(vertexNormal, 0.0)) +
|
||||||
|
vertexBoneWeights.z*(boneMatrices[boneIndex2]*vec4(vertexNormal, 0.0)) +
|
||||||
|
vertexBoneWeights.w*(boneMatrices[boneIndex3]*vec4(vertexNormal, 0.0));
|
||||||
|
skinnedNormal.w = 0.0;
|
||||||
|
|
||||||
fragTexCoord = vertexTexCoord;
|
fragTexCoord = vertexTexCoord;
|
||||||
fragColor = vertexColor;
|
fragColor = vertexColor;
|
||||||
|
|
||||||
|
fragNormal = normalize(vec3(matNormal*skinnedNormal));
|
||||||
|
|
||||||
gl_Position = mvp*skinnedPosition;
|
gl_Position = mvp*skinnedPosition;
|
||||||
}
|
}
|
||||||
|
|
@ -54,102 +54,108 @@ uniform vec3 viewPos;
|
||||||
uniform vec3 ambientColor;
|
uniform vec3 ambientColor;
|
||||||
uniform float ambient;
|
uniform float ambient;
|
||||||
|
|
||||||
// refl in range 0 to 1
|
// Reflectivity in range 0.0 to 1.0
|
||||||
// returns base reflectivity to 1
|
// NOTE: Reflectivity is increased when surface view at larger angle
|
||||||
// incrase reflectivity when surface view at larger angle
|
vec3 SchlickFresnel(float hDotV,vec3 refl)
|
||||||
vec3 schlickFresnel(float hDotV,vec3 refl)
|
|
||||||
{
|
{
|
||||||
return refl + (1.0 - refl) * pow(1.0 - hDotV,5.0);
|
return refl + (1.0 - refl)*pow(1.0 - hDotV, 5.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
float ggxDistribution(float nDotH,float roughness)
|
float GgxDistribution(float nDotH,float roughness)
|
||||||
{
|
{
|
||||||
float a = roughness * roughness * roughness * roughness;
|
float a = roughness*roughness*roughness*roughness;
|
||||||
float d = nDotH * nDotH * (a - 1.0) + 1.0;
|
float d = nDotH*nDotH*(a - 1.0) + 1.0;
|
||||||
d = PI * d * d;
|
d = PI*d*d;
|
||||||
return a / max(d,0.0000001);
|
return (a/max(d,0.0000001));
|
||||||
}
|
}
|
||||||
|
|
||||||
float geomSmith(float nDotV,float nDotL,float roughness)
|
float GeomSmith(float nDotV,float nDotL,float roughness)
|
||||||
{
|
{
|
||||||
float r = roughness + 1.0;
|
float r = roughness + 1.0;
|
||||||
float k = r * r / 8.0;
|
float k = r*r/8.0;
|
||||||
float ik = 1.0 - k;
|
float ik = 1.0 - k;
|
||||||
float ggx1 = nDotV / (nDotV * ik + k);
|
float ggx1 = nDotV/(nDotV*ik + k);
|
||||||
float ggx2 = nDotL / (nDotL * ik + k);
|
float ggx2 = nDotL/(nDotL*ik + k);
|
||||||
return ggx1 * ggx2;
|
return ggx1*ggx2;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 pbr(){
|
vec3 ComputePBR()
|
||||||
vec3 albedo = texture2D(albedoMap,vec2(fragTexCoord.x*tiling.x+offset.x,fragTexCoord.y*tiling.y+offset.y)).rgb;
|
{
|
||||||
albedo = vec3(albedoColor.x*albedo.x,albedoColor.y*albedo.y,albedoColor.z*albedo.z);
|
vec3 albedo = texture2D(albedoMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb;
|
||||||
float metallic = clamp(metallicValue,0.0,1.0);
|
albedo = vec3(albedoColor.x*albedo.x, albedoColor.y*albedo.y, albedoColor.z*albedo.z);
|
||||||
float roughness = clamp(roughnessValue,0.0,1.0);
|
|
||||||
float ao = clamp(aoValue,0.0,1.0);
|
float metallic = clamp(metallicValue, 0.0, 1.0);
|
||||||
if(useTexMRA == 1) {
|
float roughness = clamp(roughnessValue, 0.0, 1.0);
|
||||||
vec4 mra = texture2D(mraMap, vec2(fragTexCoord.x * tiling.x + offset.x, fragTexCoord.y * tiling.y + offset.y));
|
float ao = clamp(aoValue, 0.0, 1.0);
|
||||||
metallic = clamp(mra.r+metallicValue,0.04,1.0);
|
|
||||||
roughness = clamp(mra.g+roughnessValue,0.04,1.0);
|
if (useTexMRA == 1)
|
||||||
ao = (mra.b+aoValue)*0.5;
|
{
|
||||||
}
|
vec4 mra = texture2D(mraMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y));
|
||||||
|
metallic = clamp(mra.r + metallicValue, 0.04, 1.0);
|
||||||
|
roughness = clamp(mra.g + roughnessValue, 0.04, 1.0);
|
||||||
|
ao = (mra.b + aoValue)*0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 N = normalize(fragNormal);
|
||||||
|
if (useTexNormal == 1)
|
||||||
|
{
|
||||||
|
N = texture2D(normalMap, vec2(fragTexCoord.x*tiling.x + offset.y, fragTexCoord.y*tiling.y + offset.y)).rgb;
|
||||||
|
N = normalize(N*2.0 - 1.0);
|
||||||
|
N = normalize(N*TBN);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 V = normalize(viewPos - fragPosition);
|
||||||
|
|
||||||
vec3 N = normalize(fragNormal);
|
vec3 emissive = vec3(0);
|
||||||
if(useTexNormal == 1) {
|
emissive = (texture2D(emissiveMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb).g*emissiveColor.rgb*emissivePower*float(useTexEmissive);
|
||||||
N = texture2D(normalMap, vec2(fragTexCoord.x * tiling.x + offset.y, fragTexCoord.y * tiling.y + offset.y)).rgb;
|
|
||||||
N = normalize(N * 2.0 - 1.0);
|
// return N;//vec3(metallic,metallic,metallic);
|
||||||
N = normalize(N * TBN);
|
// If dia-electric use base reflectivity of 0.04 otherwise ut is a metal use albedo as base reflectivity
|
||||||
}
|
vec3 baseRefl = mix(vec3(0.04), albedo.rgb, metallic);
|
||||||
|
vec3 lightAccum = vec3(0.0); // Acumulate lighting lum
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
vec3 L = normalize(lights[i].position - fragPosition); // Compute light vector
|
||||||
|
vec3 H = normalize(V + L); // Compute halfway bisecting vector
|
||||||
|
float dist = length(lights[i].position - fragPosition); // Compute distance to light
|
||||||
|
float attenuation = 1.0/(dist*dist*0.23); // Compute attenuation
|
||||||
|
vec3 radiance = lights[i].color.rgb*lights[i].intensity*attenuation; // Compute input radiance, light energy comming in
|
||||||
|
|
||||||
|
// Cook-Torrance BRDF distribution function
|
||||||
|
float nDotV = max(dot(N,V), 0.0000001);
|
||||||
|
float nDotL = max(dot(N,L), 0.0000001);
|
||||||
|
float hDotV = max(dot(H,V), 0.0);
|
||||||
|
float nDotH = max(dot(N,H), 0.0);
|
||||||
|
float D = GgxDistribution(nDotH, roughness); // Larger the more micro-facets aligned to H
|
||||||
|
float G = GeomSmith(nDotV, nDotL, roughness); // Smaller the more micro-facets shadow
|
||||||
|
vec3 F = SchlickFresnel(hDotV, baseRefl); // Fresnel proportion of specular reflectance
|
||||||
|
|
||||||
|
vec3 spec = (D*G*F)/(4.0*nDotV*nDotL);
|
||||||
|
|
||||||
vec3 V = normalize(viewPos - fragPosition);
|
// Difuse and spec light can't be above 1.0
|
||||||
|
// kD = 1.0 - kS diffuse component is equal 1.0 - spec comonent
|
||||||
|
vec3 kD = vec3(1.0) - F;
|
||||||
|
|
||||||
vec3 e = vec3(0);
|
// Mult kD by the inverse of metallnes, only non-metals should have diffuse light
|
||||||
e = (texture2D(emissiveMap, vec2(fragTexCoord.x*tiling.x+offset.x, fragTexCoord.y*tiling.y+offset.y)).rgb).g * emissiveColor.rgb*emissivePower * float(useTexEmissive);
|
kD *= 1.0 - metallic;
|
||||||
|
lightAccum += ((kD*albedo.rgb/PI + spec)*radiance*nDotL)*float(lights[i].enabled); // Angle of light has impact on result
|
||||||
//return N;//vec3(metallic,metallic,metallic);
|
}
|
||||||
//if dia-electric use base reflectivity of 0.04 otherwise ut is a metal use albedo as base reflectivity
|
|
||||||
vec3 baseRefl = mix(vec3(0.04),albedo.rgb,metallic);
|
vec3 ambientFinal = (ambientColor + albedo)*ambient*0.5;
|
||||||
vec3 Lo = vec3(0.0); // acumulate lighting lum
|
|
||||||
|
return (ambientFinal + lightAccum*ao + emissive);
|
||||||
for(int i=0;i<4;++i){
|
|
||||||
|
|
||||||
vec3 L = normalize(lights[i].position - fragPosition); // calc light vector
|
|
||||||
vec3 H = normalize(V + L); // calc halfway bisecting vector
|
|
||||||
float dist = length(lights[i].position - fragPosition); // calc distance to light
|
|
||||||
float attenuation = 1.0 / (dist * dist * 0.23); // calc attenuation
|
|
||||||
vec3 radiance = lights[i].color.rgb * lights[i].intensity * attenuation; // calc input radiance,light energy comming in
|
|
||||||
|
|
||||||
//Cook-Torrance BRDF distribution function
|
|
||||||
float nDotV = max(dot(N,V),0.0000001);
|
|
||||||
float nDotL = max(dot(N,L),0.0000001);
|
|
||||||
float hDotV = max(dot(H,V),0.0);
|
|
||||||
float nDotH = max(dot(N,H),0.0);
|
|
||||||
float D = ggxDistribution(nDotH,roughness); // larger the more micro-facets aligned to H
|
|
||||||
float G = geomSmith(nDotV,nDotL,roughness); // smaller the more micro-facets shadow
|
|
||||||
vec3 F = schlickFresnel(hDotV, baseRefl); // fresnel proportion of specular reflectance
|
|
||||||
|
|
||||||
vec3 spec = (D * G * F) / (4.0 * nDotV * nDotL);
|
|
||||||
// difuse and spec light can't be above 1.0
|
|
||||||
// kD = 1.0 - kS diffuse component is equal 1.0 - spec comonent
|
|
||||||
vec3 kD = vec3(1.0) - F;
|
|
||||||
//mult kD by the inverse of metallnes , only non-metals should have diffuse light
|
|
||||||
kD *= 1.0 - metallic;
|
|
||||||
Lo += ((kD * albedo.rgb / PI + spec) * radiance * nDotL)*float(lights[i].enabled); // angle of light has impact on result
|
|
||||||
}
|
|
||||||
vec3 ambient_final = (ambientColor + albedo)* ambient * 0.5;
|
|
||||||
return ambient_final+Lo*ao+e;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec3 color = pbr();
|
vec3 color = ComputePBR();
|
||||||
|
|
||||||
//HDR tonemapping
|
|
||||||
color = pow(color,color + vec3(1.0));
|
|
||||||
//gamma correction
|
|
||||||
color = pow(color,vec3(1.0/2.2));
|
|
||||||
|
|
||||||
gl_FragColor = vec4(color,1.0);
|
// HDR tonemapping
|
||||||
|
color = pow(color, color + vec3(1.0));
|
||||||
|
|
||||||
|
// Gamma correction
|
||||||
|
color = pow(color, vec3(1.0/2.2));
|
||||||
|
|
||||||
|
gl_FragColor = vec4(color,1.0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,17 +26,17 @@ const float normalOffset = 0.1;
|
||||||
// https://github.com/glslify/glsl-inverse
|
// https://github.com/glslify/glsl-inverse
|
||||||
mat3 inverse(mat3 m)
|
mat3 inverse(mat3 m)
|
||||||
{
|
{
|
||||||
float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];
|
float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];
|
||||||
float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];
|
float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];
|
||||||
float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];
|
float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];
|
||||||
|
|
||||||
float b01 = a22*a11 - a12*a21;
|
float b01 = a22*a11 - a12*a21;
|
||||||
float b11 = -a22*a10 + a12*a20;
|
float b11 = -a22*a10 + a12*a20;
|
||||||
float b21 = a21*a10 - a11*a20;
|
float b21 = a21*a10 - a11*a20;
|
||||||
|
|
||||||
float det = a00*b01 + a01*b11 + a02*b21;
|
float det = a00*b01 + a01*b11 + a02*b21;
|
||||||
|
|
||||||
return mat3(b01, (-a22*a01 + a02*a21), (a12*a01 - a02*a11),
|
return mat3(b01, (-a22*a01 + a02*a21), (a12*a01 - a02*a11),
|
||||||
b11, (a22*a00 - a02*a20), (-a12*a00 + a02*a10),
|
b11, (a22*a00 - a02*a20), (-a12*a00 + a02*a10),
|
||||||
b21, (-a21*a00 + a01*a20), (a11*a00 - a01*a10))/det;
|
b21, (-a21*a00 + a01*a20), (a11*a00 - a01*a10))/det;
|
||||||
}
|
}
|
||||||
|
|
@ -44,24 +44,23 @@ mat3 inverse(mat3 m)
|
||||||
// https://github.com/glslify/glsl-transpose
|
// https://github.com/glslify/glsl-transpose
|
||||||
mat3 transpose(mat3 m)
|
mat3 transpose(mat3 m)
|
||||||
{
|
{
|
||||||
return mat3(m[0][0], m[1][0], m[2][0],
|
return mat3(m[0][0], m[1][0], m[2][0],
|
||||||
m[0][1], m[1][1], m[2][1],
|
m[0][1], m[1][1], m[2][1],
|
||||||
m[0][2], m[1][2], m[2][2]);
|
m[0][2], m[1][2], m[2][2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
// Compute binormal from vertex normal and tangent
|
||||||
// calc binormal from vertex normal and tangent
|
|
||||||
vec3 vertexBinormal = cross(vertexNormal, vertexTangent);
|
vec3 vertexBinormal = cross(vertexNormal, vertexTangent);
|
||||||
// calc fragment normal based on normal transformations
|
|
||||||
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
|
|
||||||
// calc fragment position based on model transformations
|
|
||||||
|
|
||||||
|
// Compute fragment normal based on normal transformations
|
||||||
|
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
|
||||||
|
|
||||||
|
// Compute fragment position based on model transformations
|
||||||
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0));
|
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0));
|
||||||
|
|
||||||
fragTexCoord = vertexTexCoord*2.0;
|
fragTexCoord = vertexTexCoord*2.0;
|
||||||
|
|
||||||
fragNormal = normalize(normalMatrix*vertexNormal);
|
fragNormal = normalize(normalMatrix*vertexNormal);
|
||||||
vec3 fragTangent = normalize(normalMatrix*vertexTangent);
|
vec3 fragTangent = normalize(normalMatrix*vertexTangent);
|
||||||
fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal);
|
fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal);
|
||||||
|
|
@ -71,5 +70,5 @@ void main()
|
||||||
TBN = transpose(mat3(fragTangent, fragBinormal, fragNormal));
|
TBN = transpose(mat3(fragTangent, fragBinormal, fragNormal));
|
||||||
|
|
||||||
// Calculate final vertex position
|
// Calculate final vertex position
|
||||||
gl_Position = mvp * vec4(vertexPosition, 1.0);
|
gl_Position = mvp*vec4(vertexPosition, 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ varying vec3 fragNormal;
|
||||||
varying vec4 shadowPos;
|
varying vec4 shadowPos;
|
||||||
varying mat3 TBN;
|
varying mat3 TBN;
|
||||||
|
|
||||||
|
|
||||||
// Input uniform values
|
// Input uniform values
|
||||||
uniform int numOfLights;
|
uniform int numOfLights;
|
||||||
uniform sampler2D albedoMap;
|
uniform sampler2D albedoMap;
|
||||||
|
|
@ -53,102 +52,108 @@ uniform vec3 viewPos;
|
||||||
uniform vec3 ambientColor;
|
uniform vec3 ambientColor;
|
||||||
uniform float ambient;
|
uniform float ambient;
|
||||||
|
|
||||||
// refl in range 0 to 1
|
// Reflectivity in range 0.0 to 1.0
|
||||||
// returns base reflectivity to 1
|
// NOTE: Reflectivity is increased when surface view at larger angle
|
||||||
// incrase reflectivity when surface view at larger angle
|
vec3 SchlickFresnel(float hDotV,vec3 refl)
|
||||||
vec3 schlickFresnel(float hDotV,vec3 refl)
|
|
||||||
{
|
{
|
||||||
return refl + (1.0 - refl) * pow(1.0 - hDotV,5.0);
|
return refl + (1.0 - refl)*pow(1.0 - hDotV, 5.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
float ggxDistribution(float nDotH,float roughness)
|
float GgxDistribution(float nDotH,float roughness)
|
||||||
{
|
{
|
||||||
float a = roughness * roughness * roughness * roughness;
|
float a = roughness*roughness*roughness*roughness;
|
||||||
float d = nDotH * nDotH * (a - 1.0) + 1.0;
|
float d = nDotH*nDotH*(a - 1.0) + 1.0;
|
||||||
d = PI * d * d;
|
d = PI*d*d;
|
||||||
return a / max(d,0.0000001);
|
return (a/max(d,0.0000001));
|
||||||
}
|
}
|
||||||
|
|
||||||
float geomSmith(float nDotV,float nDotL,float roughness)
|
float GeomSmith(float nDotV,float nDotL,float roughness)
|
||||||
{
|
{
|
||||||
float r = roughness + 1.0;
|
float r = roughness + 1.0;
|
||||||
float k = r * r / 8.0;
|
float k = r*r/8.0;
|
||||||
float ik = 1.0 - k;
|
float ik = 1.0 - k;
|
||||||
float ggx1 = nDotV / (nDotV * ik + k);
|
float ggx1 = nDotV/(nDotV*ik + k);
|
||||||
float ggx2 = nDotL / (nDotL * ik + k);
|
float ggx2 = nDotL/(nDotL*ik + k);
|
||||||
return ggx1 * ggx2;
|
return ggx1*ggx2;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 pbr(){
|
vec3 ComputePBR()
|
||||||
vec3 albedo = texture2D(albedoMap,vec2(fragTexCoord.x*tiling.x+offset.x,fragTexCoord.y*tiling.y+offset.y)).rgb;
|
{
|
||||||
albedo = vec3(albedoColor.x*albedo.x,albedoColor.y*albedo.y,albedoColor.z*albedo.z);
|
vec3 albedo = texture2D(albedoMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb;
|
||||||
float metallic = clamp(metallicValue,0.0,1.0);
|
albedo = vec3(albedoColor.x*albedo.x, albedoColor.y*albedo.y, albedoColor.z*albedo.z);
|
||||||
float roughness = clamp(roughnessValue,0.0,1.0);
|
|
||||||
float ao = clamp(aoValue,0.0,1.0);
|
float metallic = clamp(metallicValue, 0.0, 1.0);
|
||||||
if(useTexMRA == 1) {
|
float roughness = clamp(roughnessValue, 0.0, 1.0);
|
||||||
vec4 mra = texture2D(mraMap, vec2(fragTexCoord.x * tiling.x + offset.x, fragTexCoord.y * tiling.y + offset.y));
|
float ao = clamp(aoValue, 0.0, 1.0);
|
||||||
metallic = clamp(mra.r+metallicValue,0.04,1.0);
|
|
||||||
roughness = clamp(mra.g+roughnessValue,0.04,1.0);
|
if (useTexMRA == 1)
|
||||||
ao = (mra.b+aoValue)*0.5;
|
{
|
||||||
}
|
vec4 mra = texture2D(mraMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y));
|
||||||
|
metallic = clamp(mra.r + metallicValue, 0.04, 1.0);
|
||||||
|
roughness = clamp(mra.g + roughnessValue, 0.04, 1.0);
|
||||||
|
ao = (mra.b + aoValue)*0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 N = normalize(fragNormal);
|
||||||
|
if (useTexNormal == 1)
|
||||||
|
{
|
||||||
|
N = texture2D(normalMap, vec2(fragTexCoord.x*tiling.x + offset.y, fragTexCoord.y*tiling.y + offset.y)).rgb;
|
||||||
|
N = normalize(N*2.0 - 1.0);
|
||||||
|
N = normalize(N*TBN);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 V = normalize(viewPos - fragPosition);
|
||||||
|
|
||||||
vec3 N = normalize(fragNormal);
|
vec3 emissive = vec3(0);
|
||||||
if(useTexNormal == 1) {
|
emissive = (texture2D(emissiveMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb).g*emissiveColor.rgb*emissivePower*float(useTexEmissive);
|
||||||
N = texture2D(normalMap, vec2(fragTexCoord.x * tiling.x + offset.y, fragTexCoord.y * tiling.y + offset.y)).rgb;
|
|
||||||
N = normalize(N * 2.0 - 1.0);
|
// return N;//vec3(metallic,metallic,metallic);
|
||||||
N = normalize(N * TBN);
|
// If dia-electric use base reflectivity of 0.04 otherwise ut is a metal use albedo as base reflectivity
|
||||||
}
|
vec3 baseRefl = mix(vec3(0.04), albedo.rgb, metallic);
|
||||||
|
vec3 lightAccum = vec3(0.0); // Acumulate lighting lum
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
vec3 L = normalize(lights[i].position - fragPosition); // Compute light vector
|
||||||
|
vec3 H = normalize(V + L); // Compute halfway bisecting vector
|
||||||
|
float dist = length(lights[i].position - fragPosition); // Compute distance to light
|
||||||
|
float attenuation = 1.0/(dist*dist*0.23); // Compute attenuation
|
||||||
|
vec3 radiance = lights[i].color.rgb*lights[i].intensity*attenuation; // Compute input radiance, light energy comming in
|
||||||
|
|
||||||
|
// Cook-Torrance BRDF distribution function
|
||||||
|
float nDotV = max(dot(N,V), 0.0000001);
|
||||||
|
float nDotL = max(dot(N,L), 0.0000001);
|
||||||
|
float hDotV = max(dot(H,V), 0.0);
|
||||||
|
float nDotH = max(dot(N,H), 0.0);
|
||||||
|
float D = GgxDistribution(nDotH, roughness); // Larger the more micro-facets aligned to H
|
||||||
|
float G = GeomSmith(nDotV, nDotL, roughness); // Smaller the more micro-facets shadow
|
||||||
|
vec3 F = SchlickFresnel(hDotV, baseRefl); // Fresnel proportion of specular reflectance
|
||||||
|
|
||||||
|
vec3 spec = (D*G*F)/(4.0*nDotV*nDotL);
|
||||||
|
|
||||||
vec3 V = normalize(viewPos - fragPosition);
|
// Difuse and spec light can't be above 1.0
|
||||||
|
// kD = 1.0 - kS diffuse component is equal 1.0 - spec comonent
|
||||||
|
vec3 kD = vec3(1.0) - F;
|
||||||
|
|
||||||
vec3 e = vec3(0);
|
// Mult kD by the inverse of metallnes, only non-metals should have diffuse light
|
||||||
e = (texture2D(emissiveMap, vec2(fragTexCoord.x*tiling.x+offset.x, fragTexCoord.y*tiling.y+offset.y)).rgb).g * emissiveColor.rgb*emissivePower * float(useTexEmissive);
|
kD *= 1.0 - metallic;
|
||||||
|
lightAccum += ((kD*albedo.rgb/PI + spec)*radiance*nDotL)*float(lights[i].enabled); // Angle of light has impact on result
|
||||||
//return N;//vec3(metallic,metallic,metallic);
|
}
|
||||||
//if dia-electric use base reflectivity of 0.04 otherwise ut is a metal use albedo as base reflectivity
|
|
||||||
vec3 baseRefl = mix(vec3(0.04),albedo.rgb,metallic);
|
vec3 ambientFinal = (ambientColor + albedo)*ambient*0.5;
|
||||||
vec3 Lo = vec3(0.0); // acumulate lighting lum
|
|
||||||
|
return (ambientFinal + lightAccum*ao + emissive);
|
||||||
for(int i=0;i<numOfLights;++i){
|
|
||||||
|
|
||||||
vec3 L = normalize(lights[i].position - fragPosition); // calc light vector
|
|
||||||
vec3 H = normalize(V + L); // calc halfway bisecting vector
|
|
||||||
float dist = length(lights[i].position - fragPosition); // calc distance to light
|
|
||||||
float attenuation = 1.0 / (dist * dist * 0.23); // calc attenuation
|
|
||||||
vec3 radiance = lights[i].color.rgb * lights[i].intensity * attenuation; // calc input radiance,light energy comming in
|
|
||||||
|
|
||||||
//Cook-Torrance BRDF distribution function
|
|
||||||
float nDotV = max(dot(N,V),0.0000001);
|
|
||||||
float nDotL = max(dot(N,L),0.0000001);
|
|
||||||
float hDotV = max(dot(H,V),0.0);
|
|
||||||
float nDotH = max(dot(N,H),0.0);
|
|
||||||
float D = ggxDistribution(nDotH,roughness); // larger the more micro-facets aligned to H
|
|
||||||
float G = geomSmith(nDotV,nDotL,roughness); // smaller the more micro-facets shadow
|
|
||||||
vec3 F = schlickFresnel(hDotV, baseRefl); // fresnel proportion of specular reflectance
|
|
||||||
|
|
||||||
vec3 spec = (D * G * F) / (4.0 * nDotV * nDotL);
|
|
||||||
// difuse and spec light can't be above 1.0
|
|
||||||
// kD = 1.0 - kS diffuse component is equal 1.0 - spec comonent
|
|
||||||
vec3 kD = vec3(1.0) - F;
|
|
||||||
//mult kD by the inverse of metallnes , only non-metals should have diffuse light
|
|
||||||
kD *= 1.0 - metallic;
|
|
||||||
Lo += ((kD * albedo.rgb / PI + spec) * radiance * nDotL)*float(lights[i].enabled); // angle of light has impact on result
|
|
||||||
}
|
|
||||||
vec3 ambient_final = (ambientColor + albedo)* ambient * 0.5;
|
|
||||||
return ambient_final+Lo*ao+e;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec3 color = pbr();
|
vec3 color = ComputePBR();
|
||||||
|
|
||||||
//HDR tonemapping
|
|
||||||
color = pow(color,color + vec3(1.0));
|
|
||||||
//gamma correction
|
|
||||||
color = pow(color,vec3(1.0/2.2));
|
|
||||||
|
|
||||||
gl_FragColor = vec4(color,1.0);
|
// HDR tonemapping
|
||||||
|
color = pow(color, color + vec3(1.0));
|
||||||
|
|
||||||
|
// Gamma correction
|
||||||
|
color = pow(color, vec3(1.0/2.2));
|
||||||
|
|
||||||
|
gl_FragColor = vec4(color,1.0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
#version 120
|
#version 120
|
||||||
|
|
||||||
// Input vertex attributes
|
// Input vertex attributes
|
||||||
attribute vec3 vertexPosition;
|
attribute vec3 vertexPosition;
|
||||||
attribute vec2 vertexTexCoord;
|
attribute vec2 vertexTexCoord;
|
||||||
attribute vec3 vertexNormal;
|
attribute vec3 vertexNormal;
|
||||||
attribute vec3 vertexTangent;
|
attribute vec3 vertexTangent;
|
||||||
attribute vec4 vertexColor;
|
attribute vec4 vertexColor;
|
||||||
|
|
||||||
// Input uniform values
|
// Input uniform values
|
||||||
uniform mat4 mvp;
|
uniform mat4 mvp;
|
||||||
|
|
@ -26,17 +26,17 @@ const float normalOffset = 0.1;
|
||||||
// https://github.com/glslify/glsl-inverse
|
// https://github.com/glslify/glsl-inverse
|
||||||
mat3 inverse(mat3 m)
|
mat3 inverse(mat3 m)
|
||||||
{
|
{
|
||||||
float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];
|
float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];
|
||||||
float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];
|
float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];
|
||||||
float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];
|
float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];
|
||||||
|
|
||||||
float b01 = a22*a11 - a12*a21;
|
float b01 = a22*a11 - a12*a21;
|
||||||
float b11 = -a22*a10 + a12*a20;
|
float b11 = -a22*a10 + a12*a20;
|
||||||
float b21 = a21*a10 - a11*a20;
|
float b21 = a21*a10 - a11*a20;
|
||||||
|
|
||||||
float det = a00*b01 + a01*b11 + a02*b21;
|
float det = a00*b01 + a01*b11 + a02*b21;
|
||||||
|
|
||||||
return mat3(b01, (-a22*a01 + a02*a21), (a12*a01 - a02*a11),
|
return mat3(b01, (-a22*a01 + a02*a21), (a12*a01 - a02*a11),
|
||||||
b11, (a22*a00 - a02*a20), (-a12*a00 + a02*a10),
|
b11, (a22*a00 - a02*a20), (-a12*a00 + a02*a10),
|
||||||
b21, (-a21*a00 + a01*a20), (a11*a00 - a01*a10))/det;
|
b21, (-a21*a00 + a01*a20), (a11*a00 - a01*a10))/det;
|
||||||
}
|
}
|
||||||
|
|
@ -44,24 +44,23 @@ mat3 inverse(mat3 m)
|
||||||
// https://github.com/glslify/glsl-transpose
|
// https://github.com/glslify/glsl-transpose
|
||||||
mat3 transpose(mat3 m)
|
mat3 transpose(mat3 m)
|
||||||
{
|
{
|
||||||
return mat3(m[0][0], m[1][0], m[2][0],
|
return mat3(m[0][0], m[1][0], m[2][0],
|
||||||
m[0][1], m[1][1], m[2][1],
|
m[0][1], m[1][1], m[2][1],
|
||||||
m[0][2], m[1][2], m[2][2]);
|
m[0][2], m[1][2], m[2][2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
// Compute binormal from vertex normal and tangent
|
||||||
// calc binormal from vertex normal and tangent
|
|
||||||
vec3 vertexBinormal = cross(vertexNormal, vertexTangent);
|
vec3 vertexBinormal = cross(vertexNormal, vertexTangent);
|
||||||
// calc fragment normal based on normal transformations
|
|
||||||
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
|
|
||||||
// calc fragment position based on model transformations
|
|
||||||
|
|
||||||
|
// Compute fragment normal based on normal transformations
|
||||||
|
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
|
||||||
|
|
||||||
|
// Compute fragment position based on model transformations
|
||||||
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0));
|
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0));
|
||||||
|
|
||||||
fragTexCoord = vertexTexCoord*2.0;
|
fragTexCoord = vertexTexCoord*2.0;
|
||||||
|
|
||||||
fragNormal = normalize(normalMatrix*vertexNormal);
|
fragNormal = normalize(normalMatrix*vertexNormal);
|
||||||
vec3 fragTangent = normalize(normalMatrix*vertexTangent);
|
vec3 fragTangent = normalize(normalMatrix*vertexTangent);
|
||||||
fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal);
|
fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal);
|
||||||
|
|
@ -71,5 +70,5 @@ void main()
|
||||||
TBN = transpose(mat3(fragTangent, fragBinormal, fragNormal));
|
TBN = transpose(mat3(fragTangent, fragBinormal, fragNormal));
|
||||||
|
|
||||||
// Calculate final vertex position
|
// Calculate final vertex position
|
||||||
gl_Position = mvp * vec4(vertexPosition, 1.0);
|
gl_Position = mvp*vec4(vertexPosition, 1.0);
|
||||||
}
|
}
|
||||||
|
|
@ -64,16 +64,16 @@ vec3 SchlickFresnel(float hDotV,vec3 refl)
|
||||||
|
|
||||||
float GgxDistribution(float nDotH,float roughness)
|
float GgxDistribution(float nDotH,float roughness)
|
||||||
{
|
{
|
||||||
float a = roughness * roughness * roughness * roughness;
|
float a = roughness*roughness*roughness*roughness;
|
||||||
float d = nDotH * nDotH * (a - 1.0) + 1.0;
|
float d = nDotH*nDotH*(a - 1.0) + 1.0;
|
||||||
d = PI * d * d;
|
d = PI*d*d;
|
||||||
return a / max(d,0.0000001);
|
return (a/max(d,0.0000001));
|
||||||
}
|
}
|
||||||
|
|
||||||
float GeomSmith(float nDotV,float nDotL,float roughness)
|
float GeomSmith(float nDotV,float nDotL,float roughness)
|
||||||
{
|
{
|
||||||
float r = roughness + 1.0;
|
float r = roughness + 1.0;
|
||||||
float k = r*r / 8.0;
|
float k = r*r/8.0;
|
||||||
float ik = 1.0 - k;
|
float ik = 1.0 - k;
|
||||||
float ggx1 = nDotV/(nDotV*ik + k);
|
float ggx1 = nDotV/(nDotV*ik + k);
|
||||||
float ggx2 = nDotL/(nDotL*ik + k);
|
float ggx2 = nDotL/(nDotL*ik + k);
|
||||||
|
|
@ -91,7 +91,7 @@ vec3 ComputePBR()
|
||||||
|
|
||||||
if (useTexMRA == 1)
|
if (useTexMRA == 1)
|
||||||
{
|
{
|
||||||
vec4 mra = texture(mraMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y))*useTexMRA;
|
vec4 mra = texture(mraMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y));
|
||||||
metallic = clamp(mra.r + metallicValue, 0.04, 1.0);
|
metallic = clamp(mra.r + metallicValue, 0.04, 1.0);
|
||||||
roughness = clamp(mra.g + roughnessValue, 0.04, 1.0);
|
roughness = clamp(mra.g + roughnessValue, 0.04, 1.0);
|
||||||
ao = (mra.b + aoValue)*0.5;
|
ao = (mra.b + aoValue)*0.5;
|
||||||
|
|
@ -108,10 +108,10 @@ vec3 ComputePBR()
|
||||||
vec3 V = normalize(viewPos - fragPosition);
|
vec3 V = normalize(viewPos - fragPosition);
|
||||||
|
|
||||||
vec3 emissive = vec3(0);
|
vec3 emissive = vec3(0);
|
||||||
emissive = (texture(emissiveMap, vec2(fragTexCoord.x*tiling.x+offset.x, fragTexCoord.y*tiling.y+offset.y)).rgb).g * emissiveColor.rgb*emissivePower * useTexEmissive;
|
emissive = (texture(emissiveMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb).g*emissiveColor.rgb*emissivePower*useTexEmissive;
|
||||||
|
|
||||||
// return N;//vec3(metallic,metallic,metallic);
|
// return N;//vec3(metallic,metallic,metallic);
|
||||||
// if dia-electric use base reflectivity of 0.04 otherwise ut is a metal use albedo as base reflectivity
|
// If dia-electric use base reflectivity of 0.04 otherwise ut is a metal use albedo as base reflectivity
|
||||||
vec3 baseRefl = mix(vec3(0.04), albedo.rgb, metallic);
|
vec3 baseRefl = mix(vec3(0.04), albedo.rgb, metallic);
|
||||||
vec3 lightAccum = vec3(0.0); // Acumulate lighting lum
|
vec3 lightAccum = vec3(0.0); // Acumulate lighting lum
|
||||||
|
|
||||||
|
|
@ -145,7 +145,7 @@ vec3 ComputePBR()
|
||||||
|
|
||||||
vec3 ambientFinal = (ambientColor + albedo)*ambient*0.5;
|
vec3 ambientFinal = (ambientColor + albedo)*ambient*0.5;
|
||||||
|
|
||||||
return ambientFinal + lightAccum*ao + emissive;
|
return (ambientFinal + lightAccum*ao + emissive);
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
|
|
|
||||||
|
|
@ -27,12 +27,12 @@ void main()
|
||||||
{
|
{
|
||||||
// Compute binormal from vertex normal and tangent
|
// Compute binormal from vertex normal and tangent
|
||||||
vec3 vertexBinormal = cross(vertexNormal, vertexTangent);
|
vec3 vertexBinormal = cross(vertexNormal, vertexTangent);
|
||||||
|
|
||||||
// Compute fragment normal based on normal transformations
|
// Compute fragment normal based on normal transformations
|
||||||
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
|
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
|
||||||
|
|
||||||
// Compute fragment position based on model transformations
|
// Compute fragment position based on model transformations
|
||||||
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0f));
|
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0));
|
||||||
|
|
||||||
fragTexCoord = vertexTexCoord*2.0;
|
fragTexCoord = vertexTexCoord*2.0;
|
||||||
fragNormal = normalize(normalMatrix*vertexNormal);
|
fragNormal = normalize(normalMatrix*vertexNormal);
|
||||||
|
|
|
||||||
|
|
@ -134,14 +134,15 @@ int main(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we initialize the sampler2D uniform's in the deferred shader.
|
// Now we initialize the sampler2D uniform's in the deferred shader.
|
||||||
// We do this by setting the uniform's value to the color channel slot we earlier
|
// We do this by setting the uniform's values to the texture units that
|
||||||
// bound our textures to.
|
// we later bind our g-buffer textures to.
|
||||||
rlEnableShader(deferredShader.id);
|
rlEnableShader(deferredShader.id);
|
||||||
|
int texUnitPosition = 0;
|
||||||
rlSetUniformSampler(rlGetLocationUniform(deferredShader.id, "gPosition"), 0);
|
int texUnitNormal = 1;
|
||||||
rlSetUniformSampler(rlGetLocationUniform(deferredShader.id, "gNormal"), 1);
|
int texUnitAlbedoSpec = 2;
|
||||||
rlSetUniformSampler(rlGetLocationUniform(deferredShader.id, "gAlbedoSpec"), 2);
|
SetShaderValue(deferredShader, rlGetLocationUniform(deferredShader.id, "gPosition"), &texUnitPosition, RL_SHADER_UNIFORM_SAMPLER2D);
|
||||||
|
SetShaderValue(deferredShader, rlGetLocationUniform(deferredShader.id, "gNormal"), &texUnitNormal, RL_SHADER_UNIFORM_SAMPLER2D);
|
||||||
|
SetShaderValue(deferredShader, rlGetLocationUniform(deferredShader.id, "gAlbedoSpec"), &texUnitAlbedoSpec, RL_SHADER_UNIFORM_SAMPLER2D);
|
||||||
rlDisableShader();
|
rlDisableShader();
|
||||||
|
|
||||||
// Assign out lighting shader to model
|
// Assign out lighting shader to model
|
||||||
|
|
@ -208,11 +209,10 @@ int main(void)
|
||||||
// Draw
|
// Draw
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
|
|
||||||
ClearBackground(RAYWHITE);
|
|
||||||
|
|
||||||
// Draw to the geometry buffer by first activating it
|
// Draw to the geometry buffer by first activating it
|
||||||
rlEnableFramebuffer(gBuffer.framebuffer);
|
rlEnableFramebuffer(gBuffer.framebuffer);
|
||||||
|
rlClearColor(0, 0, 0, 0);
|
||||||
rlClearScreenBuffers(); // Clear color and depth buffer
|
rlClearScreenBuffers(); // Clear color and depth buffer
|
||||||
|
|
||||||
rlDisableColorBlend();
|
rlDisableColorBlend();
|
||||||
|
|
@ -246,14 +246,14 @@ int main(void)
|
||||||
BeginMode3D(camera);
|
BeginMode3D(camera);
|
||||||
rlDisableColorBlend();
|
rlDisableColorBlend();
|
||||||
rlEnableShader(deferredShader.id);
|
rlEnableShader(deferredShader.id);
|
||||||
// Activate our g-buffer textures
|
// Bind our g-buffer textures
|
||||||
// These will now be bound to the sampler2D uniforms `gPosition`, `gNormal`,
|
// We are binding them to locations that we earlier set in sampler2D uniforms `gPosition`, `gNormal`,
|
||||||
// and `gAlbedoSpec`
|
// and `gAlbedoSpec`
|
||||||
rlActiveTextureSlot(0);
|
rlActiveTextureSlot(texUnitPosition);
|
||||||
rlEnableTexture(gBuffer.positionTexture);
|
rlEnableTexture(gBuffer.positionTexture);
|
||||||
rlActiveTextureSlot(1);
|
rlActiveTextureSlot(texUnitNormal);
|
||||||
rlEnableTexture(gBuffer.normalTexture);
|
rlEnableTexture(gBuffer.normalTexture);
|
||||||
rlActiveTextureSlot(2);
|
rlActiveTextureSlot(texUnitAlbedoSpec);
|
||||||
rlEnableTexture(gBuffer.albedoSpecTexture);
|
rlEnableTexture(gBuffer.albedoSpecTexture);
|
||||||
|
|
||||||
// Finally, we draw a fullscreen quad to our default framebuffer
|
// Finally, we draw a fullscreen quad to our default framebuffer
|
||||||
|
|
@ -269,8 +269,8 @@ int main(void)
|
||||||
rlBlitFramebuffer(0, 0, screenWidth, screenHeight, 0, 0, screenWidth, screenHeight, 0x00000100); // GL_DEPTH_BUFFER_BIT
|
rlBlitFramebuffer(0, 0, screenWidth, screenHeight, 0, 0, screenWidth, screenHeight, 0x00000100); // GL_DEPTH_BUFFER_BIT
|
||||||
rlDisableFramebuffer();
|
rlDisableFramebuffer();
|
||||||
|
|
||||||
// Since our shader is now done and disabled, we can draw our lights in default
|
// Since our shader is now done and disabled, we can draw spheres
|
||||||
// forward rendering
|
// that represent light positions in default forward rendering
|
||||||
BeginMode3D(camera);
|
BeginMode3D(camera);
|
||||||
rlEnableShader(rlGetShaderIdDefault());
|
rlEnableShader(rlGetShaderIdDefault());
|
||||||
for(int i = 0; i < MAX_LIGHTS; i++)
|
for(int i = 0; i < MAX_LIGHTS; i++)
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue