Skip to content

Commit

Permalink
Fixed supportGPUSkinning problem
Browse files Browse the repository at this point in the history
I removed mat->supportsGPUSkinning and replaced it by passing this information at the shader creation moment in SLMesh::draw when the material gets activated
  • Loading branch information
hsm4 committed Dec 8, 2023
1 parent 9d3d44b commit 8b8695d
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 71 deletions.
17 changes: 13 additions & 4 deletions modules/sl/source/SLMaterial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -502,9 +502,11 @@ void SLMaterial::generateProgramPS(bool renderInstanced)
At the end the shader program will begin its usage with SLGLProgram::beginUse.
@param cam Pointer to the active camera
@param lights Pointer to the scene vector of lights
@param skybox Pointer to the skybox
@param supportsSkinning flag if skinning in shader should be supported
*/
void SLMaterial::activate(SLCamera* cam, SLVLight* lights, SLSkybox* skybox)
void SLMaterial::activate(SLCamera* cam,
SLVLight* lights,
SLbool supportGPUSkinning)
{
SLGLState* stateGL = SLGLState::instance();

Expand All @@ -525,12 +527,19 @@ void SLMaterial::activate(SLCamera* cam, SLVLight* lights, SLSkybox* skybox)
{
// Check first the asset manager if the requested program type already exists
string programName;
SLGLProgramGenerated::buildProgramName(this, lights, programName);
SLGLProgramGenerated::buildProgramName(this,
lights,
supportGPUSkinning,
programName);
_program = _assetManager->getProgramByName(programName);

// If the program was not found by name generate a new one
if (!_program)
_program = new SLGLProgramGenerated(_assetManager, programName, this, lights);
_program = new SLGLProgramGenerated(_assetManager,
programName,
this,
lights,
supportGPUSkinning);
}

// Check if shader had a compile error and the error texture should be shown
Expand Down
8 changes: 1 addition & 7 deletions modules/sl/source/SLMaterial.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,9 @@ class SLMaterial : public SLObject

~SLMaterial() override;
void generateProgramPS(bool renderInstanced = false);
void activate(SLCamera* cam,
SLVLight* lights,
SLSkybox* skybox = nullptr);
void activate(SLCamera* cam, SLVLight* lights, SLbool supportGPUSkinning);
SLint passToUniforms(SLGLProgram* program, SLint nextTexUnit);


void deleteDataGpu();

//! Returns true if there is any transparency in diffuse alpha or textures
Expand Down Expand Up @@ -201,7 +198,6 @@ class SLMaterial : public SLObject
void program(SLGLProgram* sp) { _program = sp; }
void programTF(SLGLProgram* sp) { _programTF = sp; }
void skybox(SLSkybox* sb) { _skybox = sb; }
void supportsGPUSkinning(SLbool supportsGPUSkinning) { _supportsGPUSkinning = supportsGPUSkinning; }
void ps(SLParticleSystem* ps) { _ps = ps; }

// Getters
Expand All @@ -224,7 +220,6 @@ class SLMaterial : public SLObject
SLGLProgram* program() { return _program; }
SLGLProgram* programTF() { return _programTF; }
SLSkybox* skybox() { return _skybox; }
SLbool supportsGPUSkinning() { return _supportsGPUSkinning; }
SLParticleSystem* ps() { return _ps; }
SLVNode& nodesVisible2D() { return _nodesVisible2D; }
SLVNode& nodesVisible3D() { return _nodesVisible3D; }
Expand Down Expand Up @@ -255,7 +250,6 @@ class SLMaterial : public SLObject
SLGLProgram* _programTF{}; //!< pointer to a GLSL shader program for transformFeedback
SLint _numTextures; //!< number of textures in all _textures vectors array
SLSkybox* _skybox; //!< pointer to the skybox
bool _supportsGPUSkinning = false; //!< whether skinning is performed on the GPU or on the CPU

// For particle system
SLParticleSystem* _ps; //!< pointer to a particle system
Expand Down
53 changes: 27 additions & 26 deletions modules/sl/source/gl/SLGLProgramGenerated.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1715,10 +1715,12 @@ const string fragMainVideoBkgd = R"(
*/
void SLGLProgramGenerated::buildProgramName(SLMaterial* mat,
SLVLight* lights,
SLbool supportGPUSkinning,
string& programName)
{
assert(mat && "No material pointer passed!");
assert(lights && !lights->empty() && "No lights passed!");

programName = "gen";

if (mat->hasTextureType(TT_videoBkgd))
Expand All @@ -1744,14 +1746,14 @@ void SLGLProgramGenerated::buildProgramName(SLMaterial* mat,
programName += "D"; // Directional light
}
else if (light->spotCutOffDEG() < 180.0f)
programName += "S"; // Spot light
programName += "S"; // Spotlight
else
programName += "P"; // Point light
programName += "P"; // Pointlight
if (light->createsShadows())
programName += "s"; // Creates shadows
}

if (mat->supportsGPUSkinning())
if (supportGPUSkinning)
programName += "-S";
}
//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -1851,7 +1853,8 @@ void SLGLProgramGenerated::buildProgramNamePS(SLMaterial* mat,
* @param lights Pointer of vector of lights
*/
void SLGLProgramGenerated::buildProgramCode(SLMaterial* mat,
SLVLight* lights)
SLVLight* lights,
SLbool supportGPUSkinning)
{
if (mat->name() == "IBLMat")
{
Expand All @@ -1876,11 +1879,11 @@ void SLGLProgramGenerated::buildProgramCode(SLMaterial* mat,

if (mat->reflectionModel() == RM_BlinnPhong)
{
buildPerPixBlinn(mat, lights);
buildPerPixBlinn(mat, lights, supportGPUSkinning);
}
else if (mat->reflectionModel() == RM_CookTorrance)
{
buildPerPixCook(mat, lights);
buildPerPixCook(mat, lights, supportGPUSkinning);
}
else if (mat->reflectionModel() == RM_Custom)
{
Expand Down Expand Up @@ -1925,7 +1928,9 @@ void SLGLProgramGenerated::buildProgramCodePS(SLMaterial* mat,
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
void SLGLProgramGenerated::buildPerPixCook(SLMaterial* mat, SLVLight* lights)
void SLGLProgramGenerated::buildPerPixCook(SLMaterial* mat,
SLVLight* lights,
SLbool supportGPUSkinning)
{
assert(mat && lights);
assert(_shaders.size() > 1 &&
Expand All @@ -1948,9 +1953,6 @@ void SLGLProgramGenerated::buildPerPixCook(SLMaterial* mat, SLVLight* lights)
bool uv1 = mat->usesUVIndex(1);
bool sky = mat->skybox() != nullptr;

// Check if the shader has to support skinning
bool skinning = mat->supportsGPUSkinning();

// Assemble vertex shader code
string vertCode;
vertCode += shaderHeader((int)lights->size());
Expand All @@ -1959,11 +1961,11 @@ void SLGLProgramGenerated::buildPerPixCook(SLMaterial* mat, SLVLight* lights)
vertCode += vertInput_a_pn;
if (uv0) vertCode += vertInput_a_uv0;
if (Nm) vertCode += vertInput_a_tangent;
if (skinning) vertCode += vertInput_a_skinning;
if (supportGPUSkinning) vertCode += vertInput_a_skinning;
vertCode += vertInput_u_matrices_all;
// if (sky) vertCode += vertInput_u_matrix_invMv;
if (Nm) vertCode += vertInput_u_lightNm;
if (skinning) vertCode += vertInput_u_skinning;
if (supportGPUSkinning) vertCode += vertInput_u_skinning;

// Vertex shader outputs
vertCode += vertOutput_v_P_VS;
Expand All @@ -1975,7 +1977,7 @@ void SLGLProgramGenerated::buildPerPixCook(SLMaterial* mat, SLVLight* lights)

// Vertex shader main loop
vertCode += main_Begin;
if (skinning) vertCode += Nm ? vertMain_skinning_Nm : vertMain_skinning;
if (supportGPUSkinning) vertCode += Nm ? vertMain_skinning_Nm : vertMain_skinning;
vertCode += vertMain_v_P_VS;
if (Sm) vertCode += vertMain_v_P_WS_Sm;
vertCode += vertMain_v_N_VS;
Expand All @@ -1985,9 +1987,9 @@ void SLGLProgramGenerated::buildPerPixCook(SLMaterial* mat, SLVLight* lights)
vertCode += vertMain_EndAll;

// Vertex shader variables
setVariable(vertCode, "localPosition", skinning ? "skinnedPosition" : "a_position");
setVariable(vertCode, "localNormal", skinning ? "skinnedNormal" : "a_normal");
if (Nm) setVariable(vertCode, "localTangent", skinning ? "skinnedTangent" : "a_tangent");
setVariable(vertCode, "localPosition", supportGPUSkinning ? "skinnedPosition" : "a_position");
setVariable(vertCode, "localNormal", supportGPUSkinning ? "skinnedNormal" : "a_normal");
if (Nm) setVariable(vertCode, "localTangent", supportGPUSkinning ? "skinnedTangent" : "a_tangent");

addCodeToShader(_shaders[0], vertCode, _name + ".vert");

Expand Down Expand Up @@ -2055,7 +2057,9 @@ void SLGLProgramGenerated::buildPerPixCook(SLMaterial* mat, SLVLight* lights)
addCodeToShader(_shaders[1], fragCode, _name + ".frag");
}
//-----------------------------------------------------------------------------
void SLGLProgramGenerated::buildPerPixBlinn(SLMaterial* mat, SLVLight* lights)
void SLGLProgramGenerated::buildPerPixBlinn(SLMaterial* mat,
SLVLight* lights,
SLbool supportGPUSkinning)
{
assert(mat && lights);
assert(_shaders.size() > 1 &&
Expand All @@ -2073,9 +2077,6 @@ void SLGLProgramGenerated::buildPerPixBlinn(SLMaterial* mat, SLVLight* lights)
bool uv0 = mat->usesUVIndex(0);
bool uv1 = mat->usesUVIndex(1);

// Check if the shader has to support skinning
bool skinning = mat->supportsGPUSkinning();

// Assemble vertex shader code
string vertCode;
vertCode += shaderHeader((int)lights->size());
Expand All @@ -2085,10 +2086,10 @@ void SLGLProgramGenerated::buildPerPixBlinn(SLMaterial* mat, SLVLight* lights)
if (uv0) vertCode += vertInput_a_uv0;
if (uv1) vertCode += vertInput_a_uv1;
if (Nm) vertCode += vertInput_a_tangent;
if (skinning) vertCode += vertInput_a_skinning;
if (supportGPUSkinning) vertCode += vertInput_a_skinning;
vertCode += vertInput_u_matrices_all;
if (Nm) vertCode += vertInput_u_lightNm;
if (skinning) vertCode += vertInput_u_skinning;
if (supportGPUSkinning) vertCode += vertInput_u_skinning;

// Vertex shader outputs
vertCode += vertOutput_v_P_VS;
Expand All @@ -2100,7 +2101,7 @@ void SLGLProgramGenerated::buildPerPixBlinn(SLMaterial* mat, SLVLight* lights)

// Vertex shader main loop
vertCode += main_Begin;
if (skinning) vertCode += Nm ? vertMain_skinning_Nm : vertMain_skinning;
if (supportGPUSkinning) vertCode += Nm ? vertMain_skinning_Nm : vertMain_skinning;
vertCode += vertMain_v_P_VS;
if (Sm) vertCode += vertMain_v_P_WS_Sm;
vertCode += vertMain_v_N_VS;
Expand All @@ -2110,9 +2111,9 @@ void SLGLProgramGenerated::buildPerPixBlinn(SLMaterial* mat, SLVLight* lights)
vertCode += vertMain_EndAll;

// Vertex shader variables
setVariable(vertCode, "localPosition", skinning ? "skinnedPosition" : "a_position");
setVariable(vertCode, "localNormal", skinning ? "skinnedNormal" : "a_normal");
if (Nm) setVariable(vertCode, "localTangent", skinning ? "skinnedTangent" : "a_tangent");
setVariable(vertCode, "localPosition", supportGPUSkinning ? "skinnedPosition" : "a_position");
setVariable(vertCode, "localNormal", supportGPUSkinning ? "skinnedNormal" : "a_normal");
if (Nm) setVariable(vertCode, "localTangent", supportGPUSkinning ? "skinnedTangent" : "a_tangent");

addCodeToShader(_shaders[0], vertCode, _name + ".vert");

Expand Down
17 changes: 11 additions & 6 deletions modules/sl/source/gl/SLGLProgramGenerated.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,15 @@ class SLGLProgramGenerated : public SLGLProgram
SLGLProgramGenerated(SLAssetManager* am,
const string& programName,
SLMaterial* mat,
SLVLight* lights)
SLVLight* lights,
SLbool supportGPUSkinning)
: SLGLProgram(am,
"",
"",
"",
programName)
{
buildProgramCode(mat, lights);
buildProgramCode(mat, lights, supportGPUSkinning);
}

//! ctor for generated shader program PS
Expand Down Expand Up @@ -95,23 +96,27 @@ class SLGLProgramGenerated : public SLGLProgram
static bool lightsDoShadowMapping(SLVLight* lights);
static void buildProgramName(SLMaterial* mat,
SLVLight* lights,
SLbool supportGPUSkinning,
string& programName);
static void buildProgramNamePS(SLMaterial* mat,
string& programName,
bool isDrawProg,
bool renderInstanced);

void buildProgramCodePS(SLMaterial* mat, bool isDrawProg, bool renderInstanced = false);
void buildProgramCodePS(SLMaterial* mat,
bool isDrawProg,
bool renderInstanced = false);
void buildProgramCode(SLMaterial* mat,
SLVLight* lights);
SLVLight* lights,
SLbool supportGPUSkinning);
void beginShader(SLCamera* cam,
SLMaterial* mat,
SLVLight* lights) override { beginUse(cam, mat, lights); }
void endShader() override { endUse(); }

private:
void buildPerPixCook(SLMaterial* mat, SLVLight* lights);
void buildPerPixBlinn(SLMaterial* mat, SLVLight* lights);
void buildPerPixCook(SLMaterial* mat, SLVLight* lights, SLbool supportGPUSkinning);
void buildPerPixBlinn(SLMaterial* mat, SLVLight* lights, SLbool supportGPUSkinning);
void buildPerPixParticle(SLMaterial* mat);
void buildPerPixParticleInstanced(SLMaterial* mat);
void buildPerPixParticleUpdate(SLMaterial* mat);
Expand Down
13 changes: 6 additions & 7 deletions modules/sl/source/input/SLAssimpImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -691,7 +691,6 @@ SLMaterial* SLAssimpImporter::loadMaterial(SLAssetManager* am,

// Create SLMaterial instance. It is also added to the SLScene::_materials vector
SLMaterial* slMat = new SLMaterial(am, name.c_str());
slMat->supportsGPUSkinning(true);

// load all the textures for this aiMat and add it to the aiMat vector
for (int tt = aiTextureType_NONE; tt <= aiTextureType_UNKNOWN; ++tt)
Expand Down Expand Up @@ -841,7 +840,6 @@ SLMaterial* SLAssimpImporter::loadMaterial(SLAssetManager* am,
aiMat->Get(AI_MATKEY_OPACITY, opacity);
aiMat->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR, metalness);
aiMat->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR, roughness);
aiString texRoughnessMetallic;

// increase shininess if specular color is not low.
// The aiMat will otherwise be too bright
Expand Down Expand Up @@ -1297,10 +1295,11 @@ SLAnimation* SLAssimpImporter::loadAnimation(SLAnimManager& animManager, aiAnima
SLuint id = 0;
SLbool isJointNode = (affectedNode == nullptr);

// @todo: this is currently a work around but it can happen that we receive normal node animationtracks and joint animationtracks
// we don't allow node animation tracks in a skeleton animation, so we should split an animation in two seperate
// animations if this happens. for now we just ignore node animation tracks if we already have joint tracks
// ofc this will crash if the first track is a node anim but its just temporary
// @todo: this is currently a work around but it can happen that we receive normal node animation tracks
// and joint animation tracks we don't allow node animation tracks in a skeleton animation, so we
// should split an animation in two separate animations if this happens. for now we just ignore node
// animation tracks if we already have joint tracks ofc this will crash if the first track is a node
// anim but its just temporary
if (!isJointNode && isSkeletonAnim)
continue;

Expand Down Expand Up @@ -1444,7 +1443,7 @@ children has a mesh. aiNode can contain only transform or joint nodes without
any visuals.
@todo this function doesn't look well optimized. It's currently used if the option to
only load nodes containing meshes somewhere in their heirarchy is enabled.
only load nodes containing meshes somewhere in their hierarchy is enabled.
This means we call it on ancestor nodes first. This also means that we will
redundantly traverse the same exact nodes multiple times. This isn't a pressing
issue at the moment but should be tackled when this importer is being optimized
Expand Down
Loading

0 comments on commit 8b8695d

Please sign in to comment.