-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[rmodels] Optional GPU skinning (#4321)
* Added optional GPU skinning * Added skinned bone matrices support for different file formats. * Moved new shader locations to end of enum to avoid breaking existing examples. Added gpu skinning on drawing of instanced meshes. * Added GPU skinning example. * Removed variable declaration to avoid shadowing warning.
- Loading branch information
1 parent
2f0cf8f
commit 86ead96
Showing
11 changed files
with
437 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
/******************************************************************************************* | ||
* | ||
* raylib [core] example - Doing skinning on the gpu using a vertex shader | ||
* | ||
* Example originally created with raylib 4.5, last time updated with raylib 4.5 | ||
* | ||
* Example contributed by Daniel Holden (@orangeduck) and reviewed by Ramon Santamaria (@raysan5) | ||
* | ||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, | ||
* BSD-like license that allows static linking with closed source software | ||
* | ||
* Copyright (c) 2024 Daniel Holden (@orangeduck) | ||
* | ||
********************************************************************************************/ | ||
|
||
#include "raylib.h" | ||
|
||
#include "raymath.h" | ||
|
||
#if defined(PLATFORM_DESKTOP) | ||
#define GLSL_VERSION 330 | ||
#else // PLATFORM_ANDROID, PLATFORM_WEB | ||
#define GLSL_VERSION 100 | ||
#endif | ||
|
||
//------------------------------------------------------------------------------------ | ||
// Program main entry point | ||
//------------------------------------------------------------------------------------ | ||
int main(void) | ||
{ | ||
// Initialization | ||
//-------------------------------------------------------------------------------------- | ||
const int screenWidth = 800; | ||
const int screenHeight = 450; | ||
|
||
InitWindow(screenWidth, screenHeight, "raylib [models] example - GPU skinning"); | ||
|
||
// Define the camera to look into our 3d world | ||
Camera camera = { 0 }; | ||
camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; // Camera position | ||
camera.target = (Vector3){ 0.0f, 2.0f, 0.0f }; // Camera looking at point | ||
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) | ||
camera.fovy = 45.0f; // Camera field-of-view Y | ||
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type | ||
|
||
// Load gltf model | ||
Model characterModel = LoadModel("resources/models/gltf/greenman.glb"); // Load character model | ||
|
||
// Load skinning shader | ||
Shader skinningShader = LoadShader(TextFormat("resources/shaders/glsl%i/skinning.vs", GLSL_VERSION), | ||
TextFormat("resources/shaders/glsl%i/skinning.fs", GLSL_VERSION)); | ||
|
||
characterModel.materials[1].shader = skinningShader; | ||
|
||
// Load gltf model animations | ||
int animsCount = 0; | ||
unsigned int animIndex = 0; | ||
unsigned int animCurrentFrame = 0; | ||
ModelAnimation *modelAnimations = LoadModelAnimations("resources/models/gltf/greenman.glb", &animsCount); | ||
|
||
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position | ||
|
||
DisableCursor(); // Limit cursor to relative movement inside the window | ||
|
||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second | ||
//-------------------------------------------------------------------------------------- | ||
|
||
// Main game loop | ||
while (!WindowShouldClose()) // Detect window close button or ESC key | ||
{ | ||
// Update | ||
//---------------------------------------------------------------------------------- | ||
UpdateCamera(&camera, CAMERA_THIRD_PERSON); | ||
|
||
// Select current animation | ||
if (IsKeyPressed(KEY_T)) animIndex = (animIndex + 1)%animsCount; | ||
else if (IsKeyPressed(KEY_G)) animIndex = (animIndex + animsCount - 1)%animsCount; | ||
|
||
// Update model animation | ||
ModelAnimation anim = modelAnimations[animIndex]; | ||
animCurrentFrame = (animCurrentFrame + 1)%anim.frameCount; | ||
UpdateModelAnimationBoneMatrices(characterModel, anim, animCurrentFrame); | ||
//---------------------------------------------------------------------------------- | ||
|
||
// Draw | ||
//---------------------------------------------------------------------------------- | ||
BeginDrawing(); | ||
|
||
ClearBackground(RAYWHITE); | ||
|
||
BeginMode3D(camera); | ||
|
||
// Draw character | ||
characterModel.transform = MatrixTranslate(position.x, position.y, position.z); | ||
UpdateModelAnimationBoneMatrices(characterModel, anim, animCurrentFrame); | ||
DrawMesh(characterModel.meshes[0], characterModel.materials[1], characterModel.transform); | ||
|
||
DrawGrid(10, 1.0f); | ||
EndMode3D(); | ||
|
||
DrawText("Use the T/G to switch animation", 10, 10, 20, GRAY); | ||
|
||
EndDrawing(); | ||
//---------------------------------------------------------------------------------- | ||
} | ||
|
||
// De-Initialization | ||
//-------------------------------------------------------------------------------------- | ||
UnloadModelAnimations(modelAnimations, animsCount); | ||
UnloadModel(characterModel); // Unload character model and meshes/material | ||
UnloadShader(skinningShader); | ||
|
||
CloseWindow(); // Close window and OpenGL context | ||
//-------------------------------------------------------------------------------------- | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#version 100 | ||
|
||
// Input vertex attributes (from vertex shader) | ||
in vec2 fragTexCoord; | ||
in vec4 fragColor; | ||
|
||
// Output fragment color | ||
out vec4 finalColor; | ||
|
||
uniform sampler2D texture0; | ||
uniform vec4 colDiffuse; | ||
|
||
void main() | ||
{ | ||
vec4 texelColor = texture(texture0, fragTexCoord); | ||
finalColor = texelColor*colDiffuse*fragColor; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
#version 100 | ||
|
||
in vec3 vertexPosition; | ||
in vec2 vertexTexCoord; | ||
in vec4 vertexColor; | ||
in vec4 vertexBoneIds; | ||
in vec4 vertexBoneWeights; | ||
|
||
#define MAX_BONE_NUM 128 | ||
uniform mat4 boneMatrices[MAX_BONE_NUM]; | ||
|
||
uniform mat4 mvp; | ||
|
||
out vec2 fragTexCoord; | ||
out vec4 fragColor; | ||
|
||
void main() | ||
{ | ||
int boneIndex0 = int(vertexBoneIds.x); | ||
int boneIndex1 = int(vertexBoneIds.y); | ||
int boneIndex2 = int(vertexBoneIds.z); | ||
int boneIndex3 = int(vertexBoneIds.w); | ||
|
||
vec4 skinnedPosition = | ||
vertexBoneWeights.x * (boneMatrices[boneIndex0] * vec4(vertexPosition, 1.0f)) + | ||
vertexBoneWeights.y * (boneMatrices[boneIndex1] * vec4(vertexPosition, 1.0f)) + | ||
vertexBoneWeights.z * (boneMatrices[boneIndex2] * vec4(vertexPosition, 1.0f)) + | ||
vertexBoneWeights.w * (boneMatrices[boneIndex3] * vec4(vertexPosition, 1.0f)); | ||
|
||
fragTexCoord = vertexTexCoord; | ||
fragColor = vertexColor; | ||
|
||
gl_Position = mvp * skinnedPosition; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#version 330 | ||
|
||
// Input vertex attributes (from vertex shader) | ||
in vec2 fragTexCoord; | ||
in vec4 fragColor; | ||
|
||
// Output fragment color | ||
out vec4 finalColor; | ||
|
||
uniform sampler2D texture0; | ||
uniform vec4 colDiffuse; | ||
|
||
void main() | ||
{ | ||
vec4 texelColor = texture(texture0, fragTexCoord); | ||
finalColor = texelColor*colDiffuse*fragColor; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
#version 330 | ||
|
||
in vec3 vertexPosition; | ||
in vec2 vertexTexCoord; | ||
in vec4 vertexColor; | ||
in vec4 vertexBoneIds; | ||
in vec4 vertexBoneWeights; | ||
|
||
#define MAX_BONE_NUM 128 | ||
uniform mat4 boneMatrices[MAX_BONE_NUM]; | ||
|
||
uniform mat4 mvp; | ||
|
||
out vec2 fragTexCoord; | ||
out vec4 fragColor; | ||
|
||
void main() | ||
{ | ||
int boneIndex0 = int(vertexBoneIds.x); | ||
int boneIndex1 = int(vertexBoneIds.y); | ||
int boneIndex2 = int(vertexBoneIds.z); | ||
int boneIndex3 = int(vertexBoneIds.w); | ||
|
||
vec4 skinnedPosition = | ||
vertexBoneWeights.x * (boneMatrices[boneIndex0] * vec4(vertexPosition, 1.0f)) + | ||
vertexBoneWeights.y * (boneMatrices[boneIndex1] * vec4(vertexPosition, 1.0f)) + | ||
vertexBoneWeights.z * (boneMatrices[boneIndex2] * vec4(vertexPosition, 1.0f)) + | ||
vertexBoneWeights.w * (boneMatrices[boneIndex3] * vec4(vertexPosition, 1.0f)); | ||
|
||
fragTexCoord = vertexTexCoord; | ||
fragColor = vertexColor; | ||
|
||
gl_Position = mvp * skinnedPosition; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.