From 9fab556232522fbafb0935ec27c076b3e7f53ce2 Mon Sep 17 00:00:00 2001
From: Marino von Wattenwyl
Date: Fri, 16 Jun 2023 14:05:53 +0200
Subject: [PATCH 01/29] [SL] Add support for GPU skinning
GPU skinning can be enabled for a material, which causes the
shader generator to include code for applying the joint transforms
to the vertices. GPU skinning is currently enabled for models loaded
using assimp.
---
modules/sl/source/SLMaterial.h | 47 ++++++++++---------
modules/sl/source/gl/SLGLProgramGenerated.cpp | 45 ++++++++++++++++--
modules/sl/source/input/SLAssimpImporter.cpp | 1 +
modules/sl/source/mesh/SLMesh.cpp | 47 +++++++++++++++++--
4 files changed, 112 insertions(+), 28 deletions(-)
diff --git a/modules/sl/source/SLMaterial.h b/modules/sl/source/SLMaterial.h
index 60dbbd97..2a4d6f2f 100644
--- a/modules/sl/source/SLMaterial.h
+++ b/modules/sl/source/SLMaterial.h
@@ -198,6 +198,7 @@ class SLMaterial : public SLObject
void program(SLGLProgram* sp) { _program = sp; }
void programTF(SLGLProgram* sp) { _programTF = sp; }
void skybox(SLSkybox* sb) { _skybox = sb; }
+ void useGPUSkinning(SLbool useGPUSkinning) { _useGPUSkinning = useGPUSkinning; }
void ps(SLParticleSystem* ps) { _ps = ps; }
// Getters
@@ -220,6 +221,7 @@ class SLMaterial : public SLObject
SLGLProgram* program() { return _program; }
SLGLProgram* programTF() { return _programTF; }
SLSkybox* skybox() { return _skybox; }
+ SLbool useGPUSkinning() { return _useGPUSkinning; }
SLParticleSystem* ps() { return _ps; }
SLVNode& nodesVisible2D() { return _nodesVisible2D; }
SLVNode& nodesVisible3D() { return _nodesVisible3D; }
@@ -231,36 +233,37 @@ class SLMaterial : public SLObject
static SLfloat PERFECT; //!< PM: shininess/translucency limit
protected:
- SLAssetManager* _assetManager; //!< pointer to the asset manager (the owner) if available
- SLReflectionModel _reflectionModel; //!< reflection model (RM_BlinnPhong or RM_CookTorrance)
- SLCol4f _ambient; //!< ambient color (RGB reflection coefficients)
- SLCol4f _diffuse; //!< diffuse color (RGB reflection coefficients)
- SLCol4f _specular; //!< specular color (RGB reflection coefficients)
- SLCol4f _emissive; //!< emissive color coefficients
- SLfloat _shininess; //!< shininess exponent in Blinn-Phong model
- SLfloat _roughness; //!< roughness property (0-1) in Cook-Torrance model
- SLfloat _metalness; //!< metallic property (0-1) in Cook-Torrance model
- SLCol4f _transmissive; //!< transmissive color (RGB reflection coefficients) for path tracing
- SLfloat _translucency; //!< translucency exponent for light refraction for path tracing
- SLfloat _kr{}; //!< reflection coefficient 0.0 - 1.0 used for ray and path tracing
- SLfloat _kt{}; //!< transmission coefficient 0.0 - 1.0 used for ray and path tracing
- SLfloat _kn{}; //!< refraction index
- SLbool _getsShadows; //!< true if shadows are visible on this material
- SLGLProgram* _program{}; //!< pointer to a GLSL shader program
- 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
+ SLAssetManager* _assetManager; //!< pointer to the asset manager (the owner) if available
+ SLReflectionModel _reflectionModel; //!< reflection model (RM_BlinnPhong or RM_CookTorrance)
+ SLCol4f _ambient; //!< ambient color (RGB reflection coefficients)
+ SLCol4f _diffuse; //!< diffuse color (RGB reflection coefficients)
+ SLCol4f _specular; //!< specular color (RGB reflection coefficients)
+ SLCol4f _emissive; //!< emissive color coefficients
+ SLfloat _shininess; //!< shininess exponent in Blinn-Phong model
+ SLfloat _roughness; //!< roughness property (0-1) in Cook-Torrance model
+ SLfloat _metalness; //!< metallic property (0-1) in Cook-Torrance model
+ SLCol4f _transmissive; //!< transmissive color (RGB reflection coefficients) for path tracing
+ SLfloat _translucency; //!< translucency exponent for light refraction for path tracing
+ SLfloat _kr{}; //!< reflection coefficient 0.0 - 1.0 used for ray and path tracing
+ SLfloat _kt{}; //!< transmission coefficient 0.0 - 1.0 used for ray and path tracing
+ SLfloat _kn{}; //!< refraction index
+ SLbool _getsShadows; //!< true if shadows are visible on this material
+ SLGLProgram* _program{}; //!< pointer to a GLSL shader program
+ 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 _useGPUSkinning = false; //!< whether skinning is performed on the GPU or on the CPU
// For particle system
- SLParticleSystem* _ps; //!< pointer to a particle system
+ SLParticleSystem* _ps; //!< pointer to a particle system
SLVGLTexture _textures[TT_numTextureType]; //!< array of texture vectors one for each type
SLVGLTexture _textures3d; //!< texture vector for diffuse 3D textures
SLGLTexture* _errorTexture = nullptr; //!< pointer to error texture that is shown if another texture fails
SLstring _compileErrorTexFilePath; //!< path to the error texture
- SLVNode _nodesVisible2D; //!< Vector of all visible 2D nodes of with this material
- SLVNode _nodesVisible3D; //!< Vector of all visible 3D nodes of with this material
+ SLVNode _nodesVisible2D; //!< Vector of all visible 2D nodes of with this material
+ SLVNode _nodesVisible3D; //!< Vector of all visible 3D nodes of with this material
};
//-----------------------------------------------------------------------------
//! STL vector of material pointers
diff --git a/modules/sl/source/gl/SLGLProgramGenerated.cpp b/modules/sl/source/gl/SLGLProgramGenerated.cpp
index bdb9aabf..0423ee6c 100644
--- a/modules/sl/source/gl/SLGLProgramGenerated.cpp
+++ b/modules/sl/source/gl/SLGLProgramGenerated.cpp
@@ -50,6 +50,10 @@ const string vertInput_a_uv1 = R"(
layout (location = 3) in vec2 a_uv1; // Vertex tex.coord. 2 for AO)";
const string vertInput_a_tangent = R"(
layout (location = 5) in vec4 a_tangent; // Vertex tangent attribute)";
+const string vertInput_a_skinning = R"(
+
+layout (location = 6) in vec4 a_jointIds; // Vertex joint indices attributes
+layout (location = 7) in vec4 a_jointWeights; // Vertex joint weights attributes)";
//-----------------------------------------------------------------------------
const string vertInput_u_matrices_all = R"(
@@ -59,6 +63,10 @@ uniform mat4 u_pMatrix; // Projection matrix (camera to normalize device coo
const string vertInput_u_matrix_vOmv = R"(
uniform mat4 u_vOmvMatrix; // view or modelview matrix)";
//-----------------------------------------------------------------------------
+const string vertInput_u_jointMatrices = R"(
+
+uniform mat4 u_jointMatrices[100]; // Joint matrices for skinning)";
+//-----------------------------------------------------------------------------
const string vertInput_u_lightNm = R"(
uniform vec4 u_lightPosVS[NUM_LIGHTS]; // position of light in view space
@@ -188,6 +196,20 @@ const string vertMain_v_uv0 = R"(
v_uv0 = a_uv0; // pass diffuse color tex.coord. 1 for interpolation)";
const string vertMain_v_uv1 = R"(
v_uv1 = a_uv1; // pass diffuse color tex.coord. 1 for interpolation)";
+const string vertMain_skinning = R"(
+
+ vec4 totalPosition = vec4(0.0);
+ vec3 totalNormal = vec3(0.0);
+
+ for (int i = 0; i < 4; i++)
+ {
+ mat4 jointMatrix = u_jointMatrices[int(a_jointIds[i])];
+ totalPosition += a_jointWeights[i] * jointMatrix * a_position;
+ totalNormal += a_jointWeights[i] * mat3(jointMatrix) * a_normal;
+ }
+
+ v_P_VS = vec3(mvMatrix * totalPosition);
+ v_N_VS = normalize(vec3(nMatrix * totalNormal));)";
const string vertMain_TBN_Nm = R"(
// Building the matrix Eye Space -> Tangent Space
@@ -267,6 +289,14 @@ const string vertMain_EndAll = R"(
gl_Position = u_pMatrix * mvMatrix * a_position;
}
)";
+
+const string vertMain_EndSkinned = R"(
+
+ // pass the vertex w. the fix-function transform
+ gl_Position = u_pMatrix * mvMatrix * totalPosition;
+}
+)";
+
//-----------------------------------------------------------------------------
const string vertMain_PS_U_Begin = R"(
@@ -1582,7 +1612,7 @@ void SLGLProgramGenerated::buildProgramName(SLMaterial* mat,
if (light->doCascadedShadows())
programName += "C" + std::to_string(light->shadowMap()->numCascades()); // Directional light with cascaded shadowmap
else
- programName += "D"; // Directional light
+ programName += "D"; // Directional light
}
else if (light->spotCutOffDEG() < 180.0f)
programName += "S"; // Spot light
@@ -1591,6 +1621,9 @@ void SLGLProgramGenerated::buildProgramName(SLMaterial* mat,
if (light->createsShadows())
programName += "s"; // Creates shadows
}
+
+ if (mat->useGPUSkinning())
+ programName += "-S";
}
//-----------------------------------------------------------------------------
/*! See the class information for more insights of the generated name. This
@@ -1653,7 +1686,7 @@ void SLGLProgramGenerated::buildProgramNamePS(SLMaterial* mat,
if (FlBoTex) programName += "-FB";
if (WS) programName += "-WS";
}
- else // Updating program
+ else // Updating program
{
bool counterGap = mat->ps()->doCounterGap(); // Counter gap/lag
bool acc = mat->ps()->doAcc(); // Acceleration
@@ -1889,6 +1922,9 @@ void SLGLProgramGenerated::buildPerPixBlinn(SLMaterial* mat, SLVLight* lights)
bool uv0 = mat->usesUVIndex(0);
bool uv1 = mat->usesUVIndex(1);
+ // Check if we use GPU skinning
+ bool skinning = mat->useGPUSkinning();
+
// Assemble vertex shader code
string vertCode;
vertCode += shaderHeader((int)lights->size());
@@ -1898,7 +1934,9 @@ 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;
vertCode += vertInput_u_matrices_all;
+ if (skinning) vertCode += vertInput_u_jointMatrices;
if (Nm) vertCode += vertInput_u_lightNm;
// Vertex shader outputs
@@ -1916,8 +1954,9 @@ void SLGLProgramGenerated::buildPerPixBlinn(SLMaterial* mat, SLVLight* lights)
vertCode += vertMain_v_N_VS;
if (uv0) vertCode += vertMain_v_uv0;
if (uv1) vertCode += vertMain_v_uv1;
+ if (skinning) vertCode += vertMain_skinning;
if (Nm) vertCode += vertMain_TBN_Nm;
- vertCode += vertMain_EndAll;
+ vertCode += skinning ? vertMain_EndSkinned : vertMain_EndAll;
addCodeToShader(_shaders[0], vertCode, _name + ".vert");
diff --git a/modules/sl/source/input/SLAssimpImporter.cpp b/modules/sl/source/input/SLAssimpImporter.cpp
index 4d89bb61..823e7bca 100644
--- a/modules/sl/source/input/SLAssimpImporter.cpp
+++ b/modules/sl/source/input/SLAssimpImporter.cpp
@@ -691,6 +691,7 @@ 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->useGPUSkinning(true);
// load all the textures for this aiMat and add it to the aiMat vector
for (int tt = aiTextureType_NONE; tt <= aiTextureType_UNKNOWN; ++tt)
diff --git a/modules/sl/source/mesh/SLMesh.cpp b/modules/sl/source/mesh/SLMesh.cpp
index 99c21015..c46b5227 100644
--- a/modules/sl/source/mesh/SLMesh.cpp
+++ b/modules/sl/source/mesh/SLMesh.cpp
@@ -442,6 +442,9 @@ void SLMesh::draw(SLSceneView* sv, SLNode* node)
sp->uniformMatrix4fv("u_vMatrix", 1, (SLfloat*)&stateGL->viewMatrix);
sp->uniformMatrix4fv("u_pMatrix", 1, (SLfloat*)&stateGL->projectionMatrix);
+ if (!_jointMatrices.empty())
+ sp->uniformMatrix4fv("u_jointMatrices", 100, (SLfloat*)&_jointMatrices[0]);
+
SLint locTM = sp->getUniformLocation("u_tMatrix");
if (locTM >= 0)
{
@@ -597,7 +600,7 @@ void SLMesh::handleRectangleSelection(SLSceneView* sv,
(SLfloat)vp.width,
(SLfloat)vp.height);
SLMat4f v_mvp = v * mvp;
- set tempIselected; // Temp. vector for selected vertex indices
+ set tempIselected; // Temp. vector for selected vertex indices
if (!cam->selectRect().isEmpty()) // Do rectangle Selection
{
@@ -735,8 +738,44 @@ void SLMesh::generateVAO(SLGLVertexArray& vao)
}
}
+ bool useCPUSkinning = !Ji.empty() && !_mat->useGPUSkinning();
+ bool useGPUSkinning = _mat->useGPUSkinning();
+
+ SLVVec4f gpuIndices(P.size(), SLVec4f(0, 0, 0, 0));
+ SLVVec4f gpuWeights(P.size(), SLVec4f(1.0f, 0.0f, 0.0f, 0.0f));
+
+ if (!Ji.empty())
+ {
+ for (unsigned i = 0; i < P.size(); i++)
+ {
+ const SLVuchar& indices = Ji[i];
+
+ SLint i0 = indices.size() >= 1 ? indices[0] : 0;
+ SLint i1 = indices.size() >= 2 ? indices[1] : 0;
+ SLint i2 = indices.size() >= 3 ? indices[2] : 0;
+ SLint i3 = indices.size() >= 4 ? indices[3] : 0;
+
+ gpuIndices[i] = SLVec4f((SLfloat)i0, (SLfloat)i1, (SLfloat)i2, (SLfloat)i3);
+ }
+
+ for (unsigned i = 0; i < P.size(); i++)
+ {
+ const SLVfloat& weights = Jw[i];
+
+ SLfloat w0 = weights.size() >= 1 ? weights[0] : 0.0f;
+ SLfloat w1 = weights.size() >= 2 ? weights[1] : 0.0f;
+ SLfloat w2 = weights.size() >= 3 ? weights[2] : 0.0f;
+ SLfloat w3 = weights.size() >= 4 ? weights[3] : 0.0f;
+
+ gpuWeights[i] = SLVec4f(w0, w1, w2, w3);
+ }
+ }
+
+ vao.setAttrib(AT_jointIndex, AT_jointIndex, &gpuIndices);
+ vao.setAttrib(AT_jointWeight, AT_jointWeight, &gpuWeights);
+
vao.generate((SLuint)P.size(),
- !Ji.empty() ? BU_stream : BU_static,
+ useCPUSkinning ? BU_stream : BU_static,
Ji.empty());
}
//-----------------------------------------------------------------------------
@@ -1511,7 +1550,7 @@ void SLMesh::transformSkin(const std::function& cbInformNodes)
if (_jointMatrices.empty())
{
_jointMatrices.clear();
- _jointMatrices.resize((SLuint)_skeleton->numJoints());
+ _jointMatrices.resize(100);
}
// update the joint matrix array
@@ -1527,6 +1566,8 @@ void SLMesh::transformSkin(const std::function& cbInformNodes)
// flag acceleration structure to be rebuilt
_accelStructIsOutOfDate = true;
+ if (_mat->useGPUSkinning()) return;
+
// iterate over all vertices and write to new buffers
for (SLulong i = 0; i < P.size(); ++i)
{
From 27033f672ad0ae15121b5fa34db5161be2bcfa49 Mon Sep 17 00:00:00 2001
From: Marino von Wattenwyl
Date: Fri, 16 Jun 2023 14:43:24 +0200
Subject: [PATCH 02/29] [SL] Use integer joint IDs for GPU skinning
The a_jointIds attribute now has the type ivec4 instead of vec4.
This removes the cost of converting the IDs to floats on the CPU
and back to int on the GPU.
---
modules/math/source/SLVec4.h | 9 +++++----
modules/sl/source/gl/SLGLEnums.h | 1 +
modules/sl/source/gl/SLGLProgramGenerated.cpp | 4 ++--
modules/sl/source/gl/SLGLVertexArray.h | 5 +++++
modules/sl/source/gl/SLGLVertexBuffer.cpp | 15 ++++++++-------
modules/sl/source/mesh/SLMesh.cpp | 4 ++--
6 files changed, 23 insertions(+), 15 deletions(-)
diff --git a/modules/math/source/SLVec4.h b/modules/math/source/SLVec4.h
index e34b7b70..23598c31 100644
--- a/modules/math/source/SLVec4.h
+++ b/modules/math/source/SLVec4.h
@@ -232,15 +232,16 @@ template SLVec4 SLVec4::YELLOW = SLVec4(1.0f, 1.0f, 0.0f, 1.0f
template SLVec4 SLVec4::CYAN = SLVec4(0.0f, 1.0f, 1.0f, 1.0f);
template SLVec4 SLVec4::MAGENTA= SLVec4(1.0f, 0.0f, 1.0f, 1.0f);
//-----------------------------------------------------------------------------
-typedef SLVec4 SLVec4f;
-typedef SLVec4 SLVec4i;
-typedef SLVec4 SLCol4f;
+typedef SLVec4 SLVec4f;
+typedef SLVec4 SLVec4i;
+typedef SLVec4 SLCol4f;
typedef vector SLVVec4f;
+typedef vector SLVVec4i;
typedef vector SLVCol4f;
#ifdef SL_HAS_DOUBLE
-typedef SLVec4 SLVec4d;
+typedef SLVec4 SLVec4d;
typedef vector SLVVec4d;
#endif
//-----------------------------------------------------------------------------
diff --git a/modules/sl/source/gl/SLGLEnums.h b/modules/sl/source/gl/SLGLEnums.h
index b57ddf04..01c436d4 100644
--- a/modules/sl/source/gl/SLGLEnums.h
+++ b/modules/sl/source/gl/SLGLEnums.h
@@ -19,6 +19,7 @@
enum SLGLBufferType
{
BT_float = GL_FLOAT, //!< float vertex attributes
+ BT_int = GL_INT, //!< int vertex attributes
BT_ubyte = GL_UNSIGNED_BYTE, //!< vertex index type (0-2^8)
BT_ushort = GL_UNSIGNED_SHORT, //!< vertex index type (0-2^16)
BT_uint = GL_UNSIGNED_INT //!< vertex index type (0-2^32)
diff --git a/modules/sl/source/gl/SLGLProgramGenerated.cpp b/modules/sl/source/gl/SLGLProgramGenerated.cpp
index 0423ee6c..479a4395 100644
--- a/modules/sl/source/gl/SLGLProgramGenerated.cpp
+++ b/modules/sl/source/gl/SLGLProgramGenerated.cpp
@@ -52,7 +52,7 @@ const string vertInput_a_tangent = R"(
layout (location = 5) in vec4 a_tangent; // Vertex tangent attribute)";
const string vertInput_a_skinning = R"(
-layout (location = 6) in vec4 a_jointIds; // Vertex joint indices attributes
+layout (location = 6) in ivec4 a_jointIds; // Vertex joint indices attributes
layout (location = 7) in vec4 a_jointWeights; // Vertex joint weights attributes)";
//-----------------------------------------------------------------------------
const string vertInput_u_matrices_all = R"(
@@ -203,7 +203,7 @@ const string vertMain_skinning = R"(
for (int i = 0; i < 4; i++)
{
- mat4 jointMatrix = u_jointMatrices[int(a_jointIds[i])];
+ mat4 jointMatrix = u_jointMatrices[a_jointIds[i]];
totalPosition += a_jointWeights[i] * jointMatrix * a_position;
totalNormal += a_jointWeights[i] * mat3(jointMatrix) * a_normal;
}
diff --git a/modules/sl/source/gl/SLGLVertexArray.h b/modules/sl/source/gl/SLGLVertexArray.h
index 4b902f54..72561127 100644
--- a/modules/sl/source/gl/SLGLVertexArray.h
+++ b/modules/sl/source/gl/SLGLVertexArray.h
@@ -90,6 +90,11 @@ class SLGLVertexArray
SLint location,
SLVVec4f* data) { setAttrib(type, 4, location, &data->operator[](0)); }
+ //! Adds a vertex attribute with vector of SLVec4i
+ void setAttrib(SLGLAttributeType type,
+ SLint location,
+ SLVVec4i* data) { setAttrib(type, 4, location, &data->operator[](0), BT_int); }
+
//! Adds the index array for indexed element drawing
void setIndices(SLuint numIndicesElements,
SLGLBufferType indexDataType,
diff --git a/modules/sl/source/gl/SLGLVertexBuffer.cpp b/modules/sl/source/gl/SLGLVertexBuffer.cpp
index 935f776d..70b4c525 100644
--- a/modules/sl/source/gl/SLGLVertexBuffer.cpp
+++ b/modules/sl/source/gl/SLGLVertexBuffer.cpp
@@ -199,7 +199,7 @@ void SLGLVertexBuffer::generate(SLuint numVertices,
{
if (a.location > -1)
{ // Sets the vertex attribute data pointer to its corresponding GLSL variable
- if (a.dataType == BT_uint)
+ if (a.dataType == BT_int || a.dataType == BT_uint)
{
glVertexAttribIPointer((SLuint)a.location,
a.elementSize,
@@ -247,7 +247,7 @@ void SLGLVertexBuffer::generate(SLuint numVertices,
if (a.location > -1)
{ // Sets the vertex attribute data pointer to its corresponding GLSL variable
- if (a.dataType == BT_uint)
+ if (a.dataType == BT_int || a.dataType == BT_uint)
{
glVertexAttribIPointer((SLuint)a.location,
a.elementSize,
@@ -289,7 +289,7 @@ void SLGLVertexBuffer::generate(SLuint numVertices,
a.dataPointer);
// Sets the vertex attribute data pointer to its corresponding GLSL variable
- if (a.dataType == BT_uint)
+ if (a.dataType == BT_int || a.dataType == BT_uint)
{
glVertexAttribIPointer((SLuint)a.location,
a.elementSize,
@@ -367,10 +367,11 @@ SLuint SLGLVertexBuffer::sizeOfType(SLGLBufferType type)
{
switch (type)
{
- case BT_float: return sizeof(float);
- case BT_ubyte: return sizeof(unsigned char);
- case BT_ushort: return sizeof(unsigned short);
- case BT_uint: return sizeof(unsigned int);
+ case BT_float: return sizeof(SLfloat);
+ case BT_int: return sizeof(SLint);
+ case BT_ubyte: return sizeof(SLuchar);
+ case BT_ushort: return sizeof(SLushort);
+ case BT_uint: return sizeof(SLint);
default: SL_EXIT_MSG("Invalid buffer data type");
}
return 0;
diff --git a/modules/sl/source/mesh/SLMesh.cpp b/modules/sl/source/mesh/SLMesh.cpp
index c46b5227..251e3d99 100644
--- a/modules/sl/source/mesh/SLMesh.cpp
+++ b/modules/sl/source/mesh/SLMesh.cpp
@@ -741,7 +741,7 @@ void SLMesh::generateVAO(SLGLVertexArray& vao)
bool useCPUSkinning = !Ji.empty() && !_mat->useGPUSkinning();
bool useGPUSkinning = _mat->useGPUSkinning();
- SLVVec4f gpuIndices(P.size(), SLVec4f(0, 0, 0, 0));
+ SLVVec4i gpuIndices(P.size(), SLVec4i(0, 0, 0, 0));
SLVVec4f gpuWeights(P.size(), SLVec4f(1.0f, 0.0f, 0.0f, 0.0f));
if (!Ji.empty())
@@ -755,7 +755,7 @@ void SLMesh::generateVAO(SLGLVertexArray& vao)
SLint i2 = indices.size() >= 3 ? indices[2] : 0;
SLint i3 = indices.size() >= 4 ? indices[3] : 0;
- gpuIndices[i] = SLVec4f((SLfloat)i0, (SLfloat)i1, (SLfloat)i2, (SLfloat)i3);
+ gpuIndices[i] = SLVec4i(i0, i1, i2, i3);
}
for (unsigned i = 0; i < P.size(); i++)
From 6d8dc1ab3aec7bef22b945d306fbc28404595c8d Mon Sep 17 00:00:00 2001
From: Marino von Wattenwyl
Date: Mon, 19 Jun 2023 14:03:13 +0200
Subject: [PATCH 03/29] [SL] Force CPU skinning when required
---
modules/sl/source/SLScene.cpp | 8 +-
modules/sl/source/SLScene.h | 3 +-
modules/sl/source/SLSceneView.cpp | 3 +-
modules/sl/source/gl/SLGLProgramGenerated.cpp | 33 ++++---
modules/sl/source/mesh/SLMesh.cpp | 88 +++++++++++++------
modules/sl/source/mesh/SLMesh.h | 10 ++-
modules/sl/source/node/SLNode.cpp | 10 ++-
modules/sl/source/node/SLNode.h | 11 +--
8 files changed, 113 insertions(+), 53 deletions(-)
diff --git a/modules/sl/source/SLScene.cpp b/modules/sl/source/SLScene.cpp
index 89c239e7..53f5354b 100644
--- a/modules/sl/source/SLScene.cpp
+++ b/modules/sl/source/SLScene.cpp
@@ -134,7 +134,8 @@ void SLScene::unInit()
@return true if really something got updated
*/
bool SLScene::onUpdate(bool renderTypeIsRT,
- bool voxelsAreShown)
+ bool voxelsAreShown,
+ bool forceCPUSkinning)
{
PROFILE_FUNCTION();
@@ -176,8 +177,11 @@ bool SLScene::onUpdate(bool renderTypeIsRT,
// Do software skinning on all changed skeletons. Update any out of date acceleration structure for RT or if they're being rendered.
if (_root3D)
{
+ if (renderTypeIsRT || voxelsAreShown)
+ forceCPUSkinning = true;
+
// we use a lambda to inform nodes that share a mesh that the mesh got updated (so we don't have to transfer the root node)
- sceneHasChanged |= _root3D->updateMeshSkins([&](SLMesh* mesh)
+ sceneHasChanged |= _root3D->updateMeshSkins(forceCPUSkinning, [&](SLMesh* mesh)
{
SLVNode nodes = _root3D->findChildren(mesh, true);
for (auto* node : nodes)
diff --git a/modules/sl/source/SLScene.h b/modules/sl/source/SLScene.h
index f4981adf..8a09a6c4 100644
--- a/modules/sl/source/SLScene.h
+++ b/modules/sl/source/SLScene.h
@@ -114,7 +114,8 @@ class SLScene : public SLObject
// Misc.
bool onUpdate(bool renderTypeIsRT,
- bool voxelsAreShown);
+ bool voxelsAreShown,
+ bool forceCPUSkinning);
void init(SLAssetManager* am);
virtual void unInit();
void selectNodeMesh(SLNode* nodeToSelect, SLMesh* meshToSelect);
diff --git a/modules/sl/source/SLSceneView.cpp b/modules/sl/source/SLSceneView.cpp
index 57f5290a..fdf264b6 100644
--- a/modules/sl/source/SLSceneView.cpp
+++ b/modules/sl/source/SLSceneView.cpp
@@ -513,7 +513,8 @@ SLbool SLSceneView::onPaint()
// update current scene
sceneHasChanged = _s->onUpdate((_renderType == RT_rt),
- drawBit(SL_DB_VOXELS));
+ drawBit(SL_DB_VOXELS),
+ drawBit(SL_DB_WITHEDGES));
}
SLbool camUpdated = false;
diff --git a/modules/sl/source/gl/SLGLProgramGenerated.cpp b/modules/sl/source/gl/SLGLProgramGenerated.cpp
index 479a4395..6142ffc2 100644
--- a/modules/sl/source/gl/SLGLProgramGenerated.cpp
+++ b/modules/sl/source/gl/SLGLProgramGenerated.cpp
@@ -65,7 +65,9 @@ uniform mat4 u_vOmvMatrix; // view or modelview matrix)";
//-----------------------------------------------------------------------------
const string vertInput_u_jointMatrices = R"(
-uniform mat4 u_jointMatrices[100]; // Joint matrices for skinning)";
+uniform mat4 u_jointMatrices[100]; // Joint matrices for skinning
+uniform bool u_skinningEnabled; // Flag if the shader should perform skinning
+)";
//-----------------------------------------------------------------------------
const string vertInput_u_lightNm = R"(
@@ -198,18 +200,29 @@ const string vertMain_v_uv1 = R"(
v_uv1 = a_uv1; // pass diffuse color tex.coord. 1 for interpolation)";
const string vertMain_skinning = R"(
- vec4 totalPosition = vec4(0.0);
- vec3 totalNormal = vec3(0.0);
+ vec4 totalPosition;
+ vec3 totalNormal;
- for (int i = 0; i < 4; i++)
+ if (u_skinningEnabled)
{
- mat4 jointMatrix = u_jointMatrices[a_jointIds[i]];
- totalPosition += a_jointWeights[i] * jointMatrix * a_position;
- totalNormal += a_jointWeights[i] * mat3(jointMatrix) * a_normal;
- }
+ totalPosition = vec4(0.0);
+ totalNormal = vec3(0.0);
+
+ for (int i = 0; i < 4; i++)
+ {
+ mat4 jointMatrix = u_jointMatrices[a_jointIds[i]];
+ totalPosition += a_jointWeights[i] * jointMatrix * a_position;
+ totalNormal += a_jointWeights[i] * mat3(jointMatrix) * a_normal;
+ }
- v_P_VS = vec3(mvMatrix * totalPosition);
- v_N_VS = normalize(vec3(nMatrix * totalNormal));)";
+ v_P_VS = vec3(mvMatrix * totalPosition);
+ v_N_VS = normalize(vec3(nMatrix * totalNormal));
+ }
+ else
+ {
+ totalPosition = a_position;
+ totalNormal = a_normal;
+ })";
const string vertMain_TBN_Nm = R"(
// Building the matrix Eye Space -> Tangent Space
diff --git a/modules/sl/source/mesh/SLMesh.cpp b/modules/sl/source/mesh/SLMesh.cpp
index 251e3d99..6bc4d7d4 100644
--- a/modules/sl/source/mesh/SLMesh.cpp
+++ b/modules/sl/source/mesh/SLMesh.cpp
@@ -442,8 +442,16 @@ void SLMesh::draw(SLSceneView* sv, SLNode* node)
sp->uniformMatrix4fv("u_vMatrix", 1, (SLfloat*)&stateGL->viewMatrix);
sp->uniformMatrix4fv("u_pMatrix", 1, (SLfloat*)&stateGL->projectionMatrix);
- if (!_jointMatrices.empty())
- sp->uniformMatrix4fv("u_jointMatrices", 100, (SLfloat*)&_jointMatrices[0]);
+ // Pass skeleton joint matrices to the shader program
+ if (_mat->useGPUSkinning())
+ {
+ // Only perform skinning in the shader if we haven't performed CPU skinning and if there are joint IDs
+ SLbool skinningEnabled = !_isCPUSkinned && !Ji.empty();
+ sp->uniform1i("u_skinningEnabled", skinningEnabled);
+
+ if (skinningEnabled)
+ sp->uniformMatrix4fv("u_jointMatrices", 100, (SLfloat*)&_jointMatrices[0]);
+ }
SLint locTM = sp->getUniformLocation("u_tMatrix");
if (locTM >= 0)
@@ -890,8 +898,18 @@ SLbool SLMesh::hit(SLRay* ray, SLNode* node)
return true;
}
+ // Force the mesh to be skinned in software even if it would be normally skinned on the GPU.
+ // We need the results from the skinning on the CPU to perform the ray-triangle intersection.
+ if (_skeleton && _mat && _mat->useGPUSkinning() && !_isCPUSkinned)
+ transformSkin(true, [](SLMesh*) {});
+
if (_accelStruct)
+ {
+ if (_accelStructIsOutOfDate)
+ updateAccelStruct();
+
return _accelStruct->intersect(ray, node);
+ }
else
{ // intersect against all faces
SLbool wasHit = false;
@@ -1092,6 +1110,8 @@ flag is set. This can happen for mesh animations.
*/
void SLMesh::updateAccelStruct()
{
+ SL_LOG(".");
+
calcMinMax();
// Add half a percent in each direction to avoid zero size dimensions
@@ -1530,8 +1550,12 @@ a weight and an index. After the transform the VBO have to be updated.
This skinning process can also be done (a lot faster) on the GPU.
This software skinning is also needed for ray or path tracing.
*/
-void SLMesh::transformSkin(const std::function& cbInformNodes)
+void SLMesh::transformSkin(bool forceCPUSkinning,
+ const std::function& cbInformNodes)
{
+ if (_isSelected)
+ forceCPUSkinning = true;
+
// create the secondary buffers for P and N once
if (skinnedP.empty())
{
@@ -1556,44 +1580,54 @@ void SLMesh::transformSkin(const std::function& cbInformNodes)
// update the joint matrix array
_skeleton->getJointMatrices(_jointMatrices);
- // notify Parent Nodes to update AABB
+ // notify parent nodes to update AABB
cbInformNodes(this);
- // temporarily set finalP and finalN
- _finalP = &skinnedP;
- _finalN = &skinnedN;
-
// flag acceleration structure to be rebuilt
_accelStructIsOutOfDate = true;
- if (_mat->useGPUSkinning()) return;
+ // remember if this node has been skinned on the CPU
+ _isCPUSkinned = forceCPUSkinning;
- // iterate over all vertices and write to new buffers
- for (SLulong i = 0; i < P.size(); ++i)
+ // Perform software skinning if the material doesn't support CPU skinning or
+ // if the results of the skinning process are required somewehere else.
+ if (!_mat->useGPUSkinning() || forceCPUSkinning)
{
- skinnedP[i] = SLVec3f::ZERO;
- if (!N.empty()) skinnedN[i] = SLVec3f::ZERO;
+ _finalP = &skinnedP;
+ _finalN = &skinnedN;
- // accumulate final normal and positions
- for (SLulong j = 0; j < Ji[i].size(); ++j)
+ // iterate over all vertices and write to new buffers
+ for (SLulong i = 0; i < P.size(); ++i)
{
- const SLMat4f& jm = _jointMatrices[Ji[i][j]];
- SLVec4f tempPos = SLVec4f(jm * P[i]);
- skinnedP[i].x += tempPos.x * Jw[i][j];
- skinnedP[i].y += tempPos.y * Jw[i][j];
- skinnedP[i].z += tempPos.z * Jw[i][j];
+ skinnedP[i] = SLVec3f::ZERO;
+ if (!N.empty()) skinnedN[i] = SLVec3f::ZERO;
- if (!N.empty())
+ // accumulate final normal and positions
+ for (SLulong j = 0; j < Ji[i].size(); ++j)
{
- // Build the 3x3 submatrix in GLSL 110 (= mat3 jt3 = mat3(jt))
- // for the normal transform that is the normally the inverse transpose.
- // The inverse transpose can be ignored as long as we only have
- // rotation and uniform scaling in the 3x3 submatrix.
- SLMat3f jnm = jm.mat3();
- skinnedN[i] += jnm * N[i] * Jw[i][j];
+ const SLMat4f& jm = _jointMatrices[Ji[i][j]];
+ SLVec4f tempPos = SLVec4f(jm * P[i]);
+ skinnedP[i].x += tempPos.x * Jw[i][j];
+ skinnedP[i].y += tempPos.y * Jw[i][j];
+ skinnedP[i].z += tempPos.z * Jw[i][j];
+
+ if (!N.empty())
+ {
+ // Build the 3x3 submatrix in GLSL 110 (= mat3 jt3 = mat3(jt))
+ // for the normal transform that is the normally the inverse transpose.
+ // The inverse transpose can be ignored as long as we only have
+ // rotation and uniform scaling in the 3x3 submatrix.
+ SLMat3f jnm = jm.mat3();
+ skinnedN[i] += jnm * N[i] * Jw[i][j];
+ }
}
}
}
+ else
+ {
+ _finalP = &P;
+ _finalN = &N;
+ }
// update or create buffers
if (_vao.vaoID())
diff --git a/modules/sl/source/mesh/SLMesh.h b/modules/sl/source/mesh/SLMesh.h
index ff475e3f..6873db2a 100644
--- a/modules/sl/source/mesh/SLMesh.h
+++ b/modules/sl/source/mesh/SLMesh.h
@@ -151,7 +151,8 @@ class SLMesh : public SLObject
SLbool hitTriangleOS(SLRay* ray, SLNode* node, SLuint iT);
virtual void generateVAO(SLGLVertexArray& vao);
void computeHardEdgesIndices(float angleRAD, float epsilon);
- void transformSkin(const std::function& cbInformNodes);
+ void transformSkin(bool forceCPUSkinning,
+ const std::function& cbInformNodes);
void deselectPartialSelection();
#ifdef SL_HAS_OPTIX
@@ -208,8 +209,8 @@ class SLMesh : public SLObject
SLVushort IE16; //!< Vector of hard edges vertex indices 16 bit (see computeHardEdgesIndices)
SLVuint IE32; //!< Vector of hard edges vertex indices 32 bit (see computeHardEdgesIndices)
- SLVec3f minP; //!< min. vertex in OS
- SLVec3f maxP; //!< max. vertex in OS
+ SLVec3f minP; //!< min. vertex in OS
+ SLVec3f maxP; //!< max. vertex in OS
private:
void calcTangents();
@@ -243,9 +244,10 @@ class SLMesh : public SLObject
SLbool _isVolume; //!< Flag for RT if mesh is a closed volume
SLAccelStruct* _accelStruct; //!< KD-tree or uniform grid
- SLbool _accelStructIsOutOfDate; //!< Flag id accel.struct needs update
+ SLbool _accelStructIsOutOfDate; //!< Flag if accel. struct needs update
SLAnimSkeleton* _skeleton; //!< The skeleton this mesh is bound to
SLVMat4f _jointMatrices; //!< Joint matrix vector for this mesh
+ SLbool _isCPUSkinned; //!< Flag if mesh has been skinned on CPU during update
SLVVec3f* _finalP; //!< Pointer to final vertex position vector
SLVVec3f* _finalN; //!< pointer to final vertex normal vector
};
diff --git a/modules/sl/source/node/SLNode.cpp b/modules/sl/source/node/SLNode.cpp
index ee1e83a0..cee233cf 100644
--- a/modules/sl/source/node/SLNode.cpp
+++ b/modules/sl/source/node/SLNode.cpp
@@ -1106,19 +1106,23 @@ void SLNode::updateRec()
/*! Do software skinning on all changed skeletons && updateRec any out of date
acceleration structure for RT or if they're being rendered.
*/
-bool SLNode::updateMeshSkins(const std::function& cbInformNodes)
+bool SLNode::updateMeshSkins(bool forceCPUSkinning,
+ const std::function& cbInformNodes)
{
+ if (drawBit(SL_DB_WITHEDGES) || drawBit(SL_DB_ONLYEDGES) || drawBit(SL_DB_VOXELS))
+ forceCPUSkinning = true;
+
bool hasChanges = false;
// Do software skinning on changed skeleton
if (_mesh && _mesh->skeleton() && _mesh->skeleton()->changed())
{
- _mesh->transformSkin(cbInformNodes);
+ _mesh->transformSkin(forceCPUSkinning, cbInformNodes);
hasChanges = true;
}
for (auto* child : _children)
- hasChanges |= child->updateMeshSkins(cbInformNodes);
+ hasChanges |= child->updateMeshSkins(forceCPUSkinning, cbInformNodes);
return hasChanges;
}
diff --git a/modules/sl/source/node/SLNode.h b/modules/sl/source/node/SLNode.h
index 74e12451..c4e6ac1f 100644
--- a/modules/sl/source/node/SLNode.h
+++ b/modules/sl/source/node/SLNode.h
@@ -301,7 +301,8 @@ class SLNode
const SLAnimSkeleton* skeleton();
void updateRec();
virtual void doUpdate() {}
- bool updateMeshSkins(const std::function& cbInformNodes);
+ bool updateMeshSkins(bool forceCPUSkinning,
+ const std::function& cbInformNodes);
void updateMeshAccelStructs();
void updateMeshMat(std::function setMat,
bool recursive);
@@ -310,7 +311,7 @@ class SLNode
SLfloat minLodCoverage() { return _minLodCoverage; }
SLubyte levelForSM() { return _levelForSM; }
- static SLuint numWMUpdates; //!< NO. of calls to updateWMRec per frame
+ static SLuint numWMUpdates; //!< NO. of calls to updateWMRec per frame
static unsigned int instanceIndex; //!< ???
@@ -335,9 +336,9 @@ class SLNode
SLbool findRecursive);
protected:
- SLNode* _parent; //!< pointer to the parent node
- SLVNode _children; //!< vector of children nodes
- SLMesh* _mesh; //!< pointer to a single mesh
+ SLNode* _parent; //!< pointer to the parent node
+ SLVNode _children; //!< vector of children nodes
+ SLMesh* _mesh; //!< pointer to a single mesh
SLint _depth; //!< depth of the node in a scene tree
SLint _entityID; //!< ID in the SLVEntity graph for Data Oriented Design
From 7427bcc31ed6c3ea75b28675be2b820d37bbe01d Mon Sep 17 00:00:00 2001
From: Marino von Wattenwyl
Date: Mon, 19 Jun 2023 15:03:11 +0200
Subject: [PATCH 04/29] [SL] Add draw bit for GPU skinning
---
apps/app_demo_slproject/source/AppDemoGui.cpp | 4 +++
.../app_demo_slproject/source/AppDemoLoad.cpp | 4 +++
modules/sl/source/SLDrawBits.h | 27 ++++++++++---------
modules/sl/source/SLSceneView.cpp | 2 +-
4 files changed, 23 insertions(+), 14 deletions(-)
diff --git a/apps/app_demo_slproject/source/AppDemoGui.cpp b/apps/app_demo_slproject/source/AppDemoGui.cpp
index e4d20e0d..20459536 100644
--- a/apps/app_demo_slproject/source/AppDemoGui.cpp
+++ b/apps/app_demo_slproject/source/AppDemoGui.cpp
@@ -2393,6 +2393,9 @@ void AppDemoGui::buildMenuBar(SLScene* s, SLSceneView* sv)
if (ImGui::MenuItem("Skeleton", "K", sv->drawBits()->get(SL_DB_SKELETON)))
sv->drawBits()->toggle(SL_DB_SKELETON);
+ if (ImGui::MenuItem("GPU Skinning", "G", sv->drawBits()->get(SL_DB_GPU_SKINNING)))
+ sv->drawBits()->toggle(SL_DB_GPU_SKINNING);
+
if (ImGui::MenuItem("All off"))
sv->drawBits()->allOff();
@@ -2407,6 +2410,7 @@ void AppDemoGui::buildMenuBar(SLScene* s, SLSceneView* sv)
sv->drawBits()->on(SL_DB_BBOX);
sv->drawBits()->on(SL_DB_SKELETON);
sv->drawBits()->on(SL_DB_CULLOFF);
+ sv->drawBits()->on(SL_DB_GPU_SKINNING);
}
ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f);
diff --git a/apps/app_demo_slproject/source/AppDemoLoad.cpp b/apps/app_demo_slproject/source/AppDemoLoad.cpp
index d8f0a7ec..66184142 100644
--- a/apps/app_demo_slproject/source/AppDemoLoad.cpp
+++ b/apps/app_demo_slproject/source/AppDemoLoad.cpp
@@ -3594,6 +3594,9 @@ resolution shadows near the camera and lower resolution shadows further away.");
scene->addChild(center);
scene->addChild(cam1);
+ std::uniform_real_distribution dist(0.0f, 1.0f);
+ std::default_random_engine randEngine;
+
// create astroboys around the center astroboy
SLint size = 4;
for (SLint iZ = -size; iZ <= size; ++iZ)
@@ -3607,6 +3610,7 @@ resolution shadows near the camera and lower resolution shadows further away.");
float zt = float(iZ) * 1.0f + ((shift) ? 0.5f : 0.0f);
SLNode* n = center->copyRec();
n->translate(xt, 0, zt, TS_object);
+ n->scale(0.75f + 0.5f * dist(randEngine));
scene->addChild(n);
}
}
diff --git a/modules/sl/source/SLDrawBits.h b/modules/sl/source/SLDrawBits.h
index 9bdf55eb..c6dbef7e 100644
--- a/modules/sl/source/SLDrawBits.h
+++ b/modules/sl/source/SLDrawBits.h
@@ -17,19 +17,20 @@
Drawing Bits control some visual states of the scene and are applied per scene
view or per single node object. Not all are used from the beginning
*/
-#define SL_DB_HIDDEN 1 //!< Flags an object as hidden
-#define SL_DB_NOTSELECTABLE 2 //!< Flags an object as selected
-#define SL_DB_MESHWIRED 4 //!< Draw polygons as wired mesh
-#define SL_DB_NORMALS 8 //!< Draw the vertex normals
-#define SL_DB_BBOX 16 //!< Draw the bounding boxes of a node
-#define SL_DB_AXIS 32 //!< Draw the coordinate axis of a node
-#define SL_DB_VOXELS 64 //!< Draw the voxels of the uniform grid
-#define SL_DB_SKELETON 128 //!< Draw the skeletons joints
-#define SL_DB_CULLOFF 256 //!< Turn off face culling
-#define SL_DB_OVERDRAW 512 //!< Draw node over all other nodes
-#define SL_DB_WITHEDGES 1024 //!< Draw faces with hard edges
-#define SL_DB_ONLYEDGES 2048 //!< Draw only hard edges
-#define SL_DB_BRECT 4096 //!< Draw the bounding rectangle of a node
+#define SL_DB_HIDDEN 1 //!< Flags an object as hidden
+#define SL_DB_NOTSELECTABLE 2 //!< Flags an object as selected
+#define SL_DB_MESHWIRED 4 //!< Draw polygons as wired mesh
+#define SL_DB_NORMALS 8 //!< Draw the vertex normals
+#define SL_DB_BBOX 16 //!< Draw the bounding boxes of a node
+#define SL_DB_AXIS 32 //!< Draw the coordinate axis of a node
+#define SL_DB_VOXELS 64 //!< Draw the voxels of the uniform grid
+#define SL_DB_SKELETON 128 //!< Draw the skeletons joints
+#define SL_DB_CULLOFF 256 //!< Turn off face culling
+#define SL_DB_OVERDRAW 512 //!< Draw node over all other nodes
+#define SL_DB_WITHEDGES 1024 //!< Draw faces with hard edges
+#define SL_DB_ONLYEDGES 2048 //!< Draw only hard edges
+#define SL_DB_BRECT 4096 //!< Draw the bounding rectangle of a node
+#define SL_DB_GPU_SKINNING 8192 //!< Perform skinning on the GPU
//-----------------------------------------------------------------------------
//! Drawing states stored in the bits of an unsigned int
diff --git a/modules/sl/source/SLSceneView.cpp b/modules/sl/source/SLSceneView.cpp
index fdf264b6..d58af6cf 100644
--- a/modules/sl/source/SLSceneView.cpp
+++ b/modules/sl/source/SLSceneView.cpp
@@ -514,7 +514,7 @@ SLbool SLSceneView::onPaint()
// update current scene
sceneHasChanged = _s->onUpdate((_renderType == RT_rt),
drawBit(SL_DB_VOXELS),
- drawBit(SL_DB_WITHEDGES));
+ !drawBit(SL_DB_GPU_SKINNING) || drawBit(SL_DB_WITHEDGES));
}
SLbool camUpdated = false;
From e2731d738ce0a82c5df10153e5fd5e1266e761c9 Mon Sep 17 00:00:00 2001
From: Marino von Wattenwyl
Date: Mon, 19 Jun 2023 15:06:23 +0200
Subject: [PATCH 05/29] [SL] Remove updateAccelStruct debug printing
---
modules/sl/source/mesh/SLMesh.cpp | 2 --
1 file changed, 2 deletions(-)
diff --git a/modules/sl/source/mesh/SLMesh.cpp b/modules/sl/source/mesh/SLMesh.cpp
index 6bc4d7d4..bc64ad6a 100644
--- a/modules/sl/source/mesh/SLMesh.cpp
+++ b/modules/sl/source/mesh/SLMesh.cpp
@@ -1110,8 +1110,6 @@ flag is set. This can happen for mesh animations.
*/
void SLMesh::updateAccelStruct()
{
- SL_LOG(".");
-
calcMinMax();
// Add half a percent in each direction to avoid zero size dimensions
From 3575143985d5707ad10bdafd1e3689f19d5a15bb Mon Sep 17 00:00:00 2001
From: Marcus Hudritsch
Date: Mon, 19 Jun 2023 16:36:58 +0200
Subject: [PATCH 06/29] Update SLMesh.cpp
---
modules/sl/source/mesh/SLMesh.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/modules/sl/source/mesh/SLMesh.cpp b/modules/sl/source/mesh/SLMesh.cpp
index bc64ad6a..48ebb2aa 100644
--- a/modules/sl/source/mesh/SLMesh.cpp
+++ b/modules/sl/source/mesh/SLMesh.cpp
@@ -449,7 +449,7 @@ void SLMesh::draw(SLSceneView* sv, SLNode* node)
SLbool skinningEnabled = !_isCPUSkinned && !Ji.empty();
sp->uniform1i("u_skinningEnabled", skinningEnabled);
- if (skinningEnabled)
+ if (skinningEnabled && !_jointMatrices.empty())
sp->uniformMatrix4fv("u_jointMatrices", 100, (SLfloat*)&_jointMatrices[0]);
}
From 851d931476d2c5e9b08b27e94d0fc1e7faa050ba Mon Sep 17 00:00:00 2001
From: Marino von Wattenwyl
Date: Mon, 19 Jun 2023 16:43:02 +0200
Subject: [PATCH 07/29] [SL] Rename useGPUSkinning to supportsGPUSkinning
---
apps/app_demo_slproject/source/AppDemoGui.cpp | 2 +-
modules/sl/source/SLMaterial.h | 44 +++++++++----------
modules/sl/source/gl/SLGLProgramGenerated.cpp | 4 +-
modules/sl/source/input/SLAssimpImporter.cpp | 2 +-
modules/sl/source/mesh/SLMesh.cpp | 23 +++++-----
5 files changed, 36 insertions(+), 39 deletions(-)
diff --git a/apps/app_demo_slproject/source/AppDemoGui.cpp b/apps/app_demo_slproject/source/AppDemoGui.cpp
index 20459536..30b69b5b 100644
--- a/apps/app_demo_slproject/source/AppDemoGui.cpp
+++ b/apps/app_demo_slproject/source/AppDemoGui.cpp
@@ -2393,7 +2393,7 @@ void AppDemoGui::buildMenuBar(SLScene* s, SLSceneView* sv)
if (ImGui::MenuItem("Skeleton", "K", sv->drawBits()->get(SL_DB_SKELETON)))
sv->drawBits()->toggle(SL_DB_SKELETON);
- if (ImGui::MenuItem("GPU Skinning", "G", sv->drawBits()->get(SL_DB_GPU_SKINNING)))
+ if (ImGui::MenuItem("GPU Skinning", nullptr, sv->drawBits()->get(SL_DB_GPU_SKINNING)))
sv->drawBits()->toggle(SL_DB_GPU_SKINNING);
if (ImGui::MenuItem("All off"))
diff --git a/modules/sl/source/SLMaterial.h b/modules/sl/source/SLMaterial.h
index 2a4d6f2f..e1ea9bde 100644
--- a/modules/sl/source/SLMaterial.h
+++ b/modules/sl/source/SLMaterial.h
@@ -198,7 +198,7 @@ class SLMaterial : public SLObject
void program(SLGLProgram* sp) { _program = sp; }
void programTF(SLGLProgram* sp) { _programTF = sp; }
void skybox(SLSkybox* sb) { _skybox = sb; }
- void useGPUSkinning(SLbool useGPUSkinning) { _useGPUSkinning = useGPUSkinning; }
+ void supportsGPUSkinning(SLbool supportsGPUSkinning) { _supportsGPUSkinning = supportsGPUSkinning; }
void ps(SLParticleSystem* ps) { _ps = ps; }
// Getters
@@ -221,7 +221,7 @@ class SLMaterial : public SLObject
SLGLProgram* program() { return _program; }
SLGLProgram* programTF() { return _programTF; }
SLSkybox* skybox() { return _skybox; }
- SLbool useGPUSkinning() { return _useGPUSkinning; }
+ SLbool supportsGPUSkinning() { return _supportsGPUSkinning; }
SLParticleSystem* ps() { return _ps; }
SLVNode& nodesVisible2D() { return _nodesVisible2D; }
SLVNode& nodesVisible3D() { return _nodesVisible3D; }
@@ -233,26 +233,26 @@ class SLMaterial : public SLObject
static SLfloat PERFECT; //!< PM: shininess/translucency limit
protected:
- SLAssetManager* _assetManager; //!< pointer to the asset manager (the owner) if available
- SLReflectionModel _reflectionModel; //!< reflection model (RM_BlinnPhong or RM_CookTorrance)
- SLCol4f _ambient; //!< ambient color (RGB reflection coefficients)
- SLCol4f _diffuse; //!< diffuse color (RGB reflection coefficients)
- SLCol4f _specular; //!< specular color (RGB reflection coefficients)
- SLCol4f _emissive; //!< emissive color coefficients
- SLfloat _shininess; //!< shininess exponent in Blinn-Phong model
- SLfloat _roughness; //!< roughness property (0-1) in Cook-Torrance model
- SLfloat _metalness; //!< metallic property (0-1) in Cook-Torrance model
- SLCol4f _transmissive; //!< transmissive color (RGB reflection coefficients) for path tracing
- SLfloat _translucency; //!< translucency exponent for light refraction for path tracing
- SLfloat _kr{}; //!< reflection coefficient 0.0 - 1.0 used for ray and path tracing
- SLfloat _kt{}; //!< transmission coefficient 0.0 - 1.0 used for ray and path tracing
- SLfloat _kn{}; //!< refraction index
- SLbool _getsShadows; //!< true if shadows are visible on this material
- SLGLProgram* _program{}; //!< pointer to a GLSL shader program
- 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 _useGPUSkinning = false; //!< whether skinning is performed on the GPU or on the CPU
+ SLAssetManager* _assetManager; //!< pointer to the asset manager (the owner) if available
+ SLReflectionModel _reflectionModel; //!< reflection model (RM_BlinnPhong or RM_CookTorrance)
+ SLCol4f _ambient; //!< ambient color (RGB reflection coefficients)
+ SLCol4f _diffuse; //!< diffuse color (RGB reflection coefficients)
+ SLCol4f _specular; //!< specular color (RGB reflection coefficients)
+ SLCol4f _emissive; //!< emissive color coefficients
+ SLfloat _shininess; //!< shininess exponent in Blinn-Phong model
+ SLfloat _roughness; //!< roughness property (0-1) in Cook-Torrance model
+ SLfloat _metalness; //!< metallic property (0-1) in Cook-Torrance model
+ SLCol4f _transmissive; //!< transmissive color (RGB reflection coefficients) for path tracing
+ SLfloat _translucency; //!< translucency exponent for light refraction for path tracing
+ SLfloat _kr{}; //!< reflection coefficient 0.0 - 1.0 used for ray and path tracing
+ SLfloat _kt{}; //!< transmission coefficient 0.0 - 1.0 used for ray and path tracing
+ SLfloat _kn{}; //!< refraction index
+ SLbool _getsShadows; //!< true if shadows are visible on this material
+ SLGLProgram* _program{}; //!< pointer to a GLSL shader program
+ 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
diff --git a/modules/sl/source/gl/SLGLProgramGenerated.cpp b/modules/sl/source/gl/SLGLProgramGenerated.cpp
index 6142ffc2..465c9670 100644
--- a/modules/sl/source/gl/SLGLProgramGenerated.cpp
+++ b/modules/sl/source/gl/SLGLProgramGenerated.cpp
@@ -1635,7 +1635,7 @@ void SLGLProgramGenerated::buildProgramName(SLMaterial* mat,
programName += "s"; // Creates shadows
}
- if (mat->useGPUSkinning())
+ if (mat->supportsGPUSkinning())
programName += "-S";
}
//-----------------------------------------------------------------------------
@@ -1936,7 +1936,7 @@ void SLGLProgramGenerated::buildPerPixBlinn(SLMaterial* mat, SLVLight* lights)
bool uv1 = mat->usesUVIndex(1);
// Check if we use GPU skinning
- bool skinning = mat->useGPUSkinning();
+ bool skinning = mat->supportsGPUSkinning();
// Assemble vertex shader code
string vertCode;
diff --git a/modules/sl/source/input/SLAssimpImporter.cpp b/modules/sl/source/input/SLAssimpImporter.cpp
index 823e7bca..12930a22 100644
--- a/modules/sl/source/input/SLAssimpImporter.cpp
+++ b/modules/sl/source/input/SLAssimpImporter.cpp
@@ -691,7 +691,7 @@ 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->useGPUSkinning(true);
+ 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)
diff --git a/modules/sl/source/mesh/SLMesh.cpp b/modules/sl/source/mesh/SLMesh.cpp
index 48ebb2aa..8de969d2 100644
--- a/modules/sl/source/mesh/SLMesh.cpp
+++ b/modules/sl/source/mesh/SLMesh.cpp
@@ -443,7 +443,7 @@ void SLMesh::draw(SLSceneView* sv, SLNode* node)
sp->uniformMatrix4fv("u_pMatrix", 1, (SLfloat*)&stateGL->projectionMatrix);
// Pass skeleton joint matrices to the shader program
- if (_mat->useGPUSkinning())
+ if (_mat->supportsGPUSkinning())
{
// Only perform skinning in the shader if we haven't performed CPU skinning and if there are joint IDs
SLbool skinningEnabled = !_isCPUSkinned && !Ji.empty();
@@ -746,14 +746,11 @@ void SLMesh::generateVAO(SLGLVertexArray& vao)
}
}
- bool useCPUSkinning = !Ji.empty() && !_mat->useGPUSkinning();
- bool useGPUSkinning = _mat->useGPUSkinning();
-
- SLVVec4i gpuIndices(P.size(), SLVec4i(0, 0, 0, 0));
- SLVVec4f gpuWeights(P.size(), SLVec4f(1.0f, 0.0f, 0.0f, 0.0f));
-
if (!Ji.empty())
{
+ SLVVec4i gpuIndices(P.size(), SLVec4i(0, 0, 0, 0));
+ SLVVec4f gpuWeights(P.size(), SLVec4f(1.0f, 0.0f, 0.0f, 0.0f));
+
for (unsigned i = 0; i < P.size(); i++)
{
const SLVuchar& indices = Ji[i];
@@ -777,13 +774,13 @@ void SLMesh::generateVAO(SLGLVertexArray& vao)
gpuWeights[i] = SLVec4f(w0, w1, w2, w3);
}
- }
- vao.setAttrib(AT_jointIndex, AT_jointIndex, &gpuIndices);
- vao.setAttrib(AT_jointWeight, AT_jointWeight, &gpuWeights);
+ vao.setAttrib(AT_jointIndex, AT_jointIndex, &gpuIndices);
+ vao.setAttrib(AT_jointWeight, AT_jointWeight, &gpuWeights);
+ }
vao.generate((SLuint)P.size(),
- useCPUSkinning ? BU_stream : BU_static,
+ !Ji.empty() && !_mat->supportsGPUSkinning() ? BU_stream : BU_static,
Ji.empty());
}
//-----------------------------------------------------------------------------
@@ -900,7 +897,7 @@ SLbool SLMesh::hit(SLRay* ray, SLNode* node)
// Force the mesh to be skinned in software even if it would be normally skinned on the GPU.
// We need the results from the skinning on the CPU to perform the ray-triangle intersection.
- if (_skeleton && _mat && _mat->useGPUSkinning() && !_isCPUSkinned)
+ if (_skeleton && _mat && _mat->supportsGPUSkinning() && !_isCPUSkinned)
transformSkin(true, [](SLMesh*) {});
if (_accelStruct)
@@ -1589,7 +1586,7 @@ void SLMesh::transformSkin(bool forceCPUSkinning,
// Perform software skinning if the material doesn't support CPU skinning or
// if the results of the skinning process are required somewehere else.
- if (!_mat->useGPUSkinning() || forceCPUSkinning)
+ if (!_mat->supportsGPUSkinning() || forceCPUSkinning)
{
_finalP = &skinnedP;
_finalN = &skinnedN;
From d518217916d6eb67d4464204b7107367c510ab6c Mon Sep 17 00:00:00 2001
From: Marino von Wattenwyl
Date: Mon, 19 Jun 2023 16:56:14 +0200
Subject: [PATCH 08/29] [SL] Add GUI text for GPU skinning
The text shows whether a material shader has support
for GPU skinning.
---
apps/app_demo_slproject/source/AppDemoGui.cpp | 4 ++++
modules/sl/source/mesh/SLMesh.cpp | 2 +-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/apps/app_demo_slproject/source/AppDemoGui.cpp b/apps/app_demo_slproject/source/AppDemoGui.cpp
index 30b69b5b..d2724752 100644
--- a/apps/app_demo_slproject/source/AppDemoGui.cpp
+++ b/apps/app_demo_slproject/source/AppDemoGui.cpp
@@ -4337,6 +4337,7 @@ void AppDemoGui::buildProperties(SLScene* s, SLSceneView* sv)
ImGui::TreePop();
}
+
if (m->program() != nullptr)
{
for (auto* shd : m->program()->shaders())
@@ -4371,6 +4372,9 @@ void AppDemoGui::buildProperties(SLScene* s, SLSceneView* sv)
}
}
}
+
+ ImGui::Text("Supports GPU skinning: %s", m->supportsGPUSkinning() ? "Yes" : "No");
+
ImGui::TreePop();
}
}
diff --git a/modules/sl/source/mesh/SLMesh.cpp b/modules/sl/source/mesh/SLMesh.cpp
index 8de969d2..2ecef129 100644
--- a/modules/sl/source/mesh/SLMesh.cpp
+++ b/modules/sl/source/mesh/SLMesh.cpp
@@ -749,7 +749,7 @@ void SLMesh::generateVAO(SLGLVertexArray& vao)
if (!Ji.empty())
{
SLVVec4i gpuIndices(P.size(), SLVec4i(0, 0, 0, 0));
- SLVVec4f gpuWeights(P.size(), SLVec4f(1.0f, 0.0f, 0.0f, 0.0f));
+ SLVVec4f gpuWeights(P.size(), SLVec4f(0.0f, 0.0f, 0.0f, 0.0f));
for (unsigned i = 0; i < P.size(); i++)
{
From 5291a44a50978879eecc1031fa99d8e900374850 Mon Sep 17 00:00:00 2001
From: Marino von Wattenwyl
Date: Mon, 19 Jun 2023 17:08:15 +0200
Subject: [PATCH 09/29] [SL] Only create as many joint matrices as required
---
modules/sl/source/mesh/SLMesh.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/modules/sl/source/mesh/SLMesh.cpp b/modules/sl/source/mesh/SLMesh.cpp
index 2ecef129..6791934e 100644
--- a/modules/sl/source/mesh/SLMesh.cpp
+++ b/modules/sl/source/mesh/SLMesh.cpp
@@ -450,7 +450,7 @@ void SLMesh::draw(SLSceneView* sv, SLNode* node)
sp->uniform1i("u_skinningEnabled", skinningEnabled);
if (skinningEnabled && !_jointMatrices.empty())
- sp->uniformMatrix4fv("u_jointMatrices", 100, (SLfloat*)&_jointMatrices[0]);
+ sp->uniformMatrix4fv("u_jointMatrices", _jointMatrices.size(), (SLfloat*)&_jointMatrices[0]);
}
SLint locTM = sp->getUniformLocation("u_tMatrix");
@@ -1569,7 +1569,7 @@ void SLMesh::transformSkin(bool forceCPUSkinning,
if (_jointMatrices.empty())
{
_jointMatrices.clear();
- _jointMatrices.resize(100);
+ _jointMatrices.resize((SLuint)_skeleton->numJoints());
}
// update the joint matrix array
From 29adf5b785386ea306b9b6fbd2279b6ec292cf8a Mon Sep 17 00:00:00 2001
From: Marino von Wattenwyl
Date: Wed, 21 Jun 2023 09:04:26 +0200
Subject: [PATCH 10/29] [SL] Add some comments for GPU skinning
---
modules/sl/source/gl/SLGLProgramGenerated.cpp | 10 +++++
modules/sl/source/mesh/SLMesh.cpp | 39 ++++++++++---------
2 files changed, 30 insertions(+), 19 deletions(-)
diff --git a/modules/sl/source/gl/SLGLProgramGenerated.cpp b/modules/sl/source/gl/SLGLProgramGenerated.cpp
index 465c9670..43185814 100644
--- a/modules/sl/source/gl/SLGLProgramGenerated.cpp
+++ b/modules/sl/source/gl/SLGLProgramGenerated.cpp
@@ -205,12 +205,22 @@ const string vertMain_skinning = R"(
if (u_skinningEnabled)
{
+ // In skinned skeleton animation, every vertex of a mesh is transformed by
+ // max. four joints (bones) of a skeleton identified by indices. The
+ // joint matrices represent this transformation and can change per frame
+ // to animate the mesh. The effect that a joint has on a vertex is
+ // specified by the four weights passed along with the joint indices.
+
totalPosition = vec4(0.0);
totalNormal = vec3(0.0);
+ // iterate over all joints that are transforming this vertex.
for (int i = 0; i < 4; i++)
{
+ // get the transformation of this joint.
mat4 jointMatrix = u_jointMatrices[a_jointIds[i]];
+
+ // apply the weighted transformation to the position and normal of the vertex.
totalPosition += a_jointWeights[i] * jointMatrix * a_position;
totalNormal += a_jointWeights[i] * mat3(jointMatrix) * a_normal;
}
diff --git a/modules/sl/source/mesh/SLMesh.cpp b/modules/sl/source/mesh/SLMesh.cpp
index 6791934e..16d193a3 100644
--- a/modules/sl/source/mesh/SLMesh.cpp
+++ b/modules/sl/source/mesh/SLMesh.cpp
@@ -748,35 +748,36 @@ void SLMesh::generateVAO(SLGLVertexArray& vao)
if (!Ji.empty())
{
- SLVVec4i gpuIndices(P.size(), SLVec4i(0, 0, 0, 0));
- SLVVec4f gpuWeights(P.size(), SLVec4f(0.0f, 0.0f, 0.0f, 0.0f));
+ // indices are passed to the shader as ivec4s
+ SLVVec4i indicesData(P.size(), SLVec4i(0, 0, 0, 0));
+ // weights are passed to the shader as vec4s
+ SLVVec4f indicesWeights(P.size(), SLVec4f(0.0f, 0.0f, 0.0f, 0.0f));
+
+ // create the vec4 of indices for all points
for (unsigned i = 0; i < P.size(); i++)
{
- const SLVuchar& indices = Ji[i];
-
- SLint i0 = indices.size() >= 1 ? indices[0] : 0;
- SLint i1 = indices.size() >= 2 ? indices[1] : 0;
- SLint i2 = indices.size() >= 3 ? indices[2] : 0;
- SLint i3 = indices.size() >= 4 ? indices[3] : 0;
+ const SLVuchar& curIndices = Ji[i];
- gpuIndices[i] = SLVec4i(i0, i1, i2, i3);
+ indicesData[i] = SLVec4i(curIndices.size() >= 1 ? curIndices[0] : 0,
+ curIndices.size() >= 2 ? curIndices[1] : 0,
+ curIndices.size() >= 3 ? curIndices[2] : 0,
+ curIndices.size() >= 4 ? curIndices[3] : 0);
}
+ // create the vec4 of weights for all points
for (unsigned i = 0; i < P.size(); i++)
{
- const SLVfloat& weights = Jw[i];
-
- SLfloat w0 = weights.size() >= 1 ? weights[0] : 0.0f;
- SLfloat w1 = weights.size() >= 2 ? weights[1] : 0.0f;
- SLfloat w2 = weights.size() >= 3 ? weights[2] : 0.0f;
- SLfloat w3 = weights.size() >= 4 ? weights[3] : 0.0f;
+ const SLVfloat& curWeights = Jw[i];
- gpuWeights[i] = SLVec4f(w0, w1, w2, w3);
+ indicesWeights[i] = SLVec4f(curWeights.size() >= 1 ? curWeights[0] : 0.0f,
+ curWeights.size() >= 2 ? curWeights[1] : 0.0f,
+ curWeights.size() >= 3 ? curWeights[2] : 0.0f,
+ curWeights.size() >= 4 ? curWeights[3] : 0.0f);
}
- vao.setAttrib(AT_jointIndex, AT_jointIndex, &gpuIndices);
- vao.setAttrib(AT_jointWeight, AT_jointWeight, &gpuWeights);
+ vao.setAttrib(AT_jointIndex, AT_jointIndex, &indicesData);
+ vao.setAttrib(AT_jointWeight, AT_jointWeight, &indicesWeights);
}
vao.generate((SLuint)P.size(),
@@ -1621,7 +1622,7 @@ void SLMesh::transformSkin(bool forceCPUSkinning,
else
{
_finalP = &P;
- _finalN = &N;
+ _finalN = &N;
}
// update or create buffers
From 8cf8955579a9c08b6d7380d1dd455ae937a88703 Mon Sep 17 00:00:00 2001
From: Marino von Wattenwyl
Date: Wed, 21 Jun 2023 15:24:03 +0200
Subject: [PATCH 11/29] [SL] Fix GPU skinning UB in generateVAO
---
modules/sl/source/mesh/SLMesh.cpp | 32 +++++++++++++++++--------------
1 file changed, 18 insertions(+), 14 deletions(-)
diff --git a/modules/sl/source/mesh/SLMesh.cpp b/modules/sl/source/mesh/SLMesh.cpp
index 16d193a3..d3398093 100644
--- a/modules/sl/source/mesh/SLMesh.cpp
+++ b/modules/sl/source/mesh/SLMesh.cpp
@@ -746,20 +746,24 @@ void SLMesh::generateVAO(SLGLVertexArray& vao)
}
}
- if (!Ji.empty())
+ SLVVec4i jointIndicesData; // indices are passed to the shader as ivec4s
+ SLVVec4f jointWeightsData; // weights are passed to the shader as vec4s
+
+ if (!Ji.empty() && _mat->supportsGPUSkinning())
{
- // indices are passed to the shader as ivec4s
- SLVVec4i indicesData(P.size(), SLVec4i(0, 0, 0, 0));
+ assert(Ji.size() == P.size());
+ assert(Jw.size() == P.size());
- // weights are passed to the shader as vec4s
- SLVVec4f indicesWeights(P.size(), SLVec4f(0.0f, 0.0f, 0.0f, 0.0f));
+ jointIndicesData = SLVVec4i(P.size(), SLVec4i(0, 0, 0, 0));
+ jointWeightsData = SLVVec4f(P.size(), SLVec4f(0.0f, 0.0f, 0.0f, 0.0f));
// create the vec4 of indices for all points
for (unsigned i = 0; i < P.size(); i++)
{
const SLVuchar& curIndices = Ji[i];
+ assert(!curIndices.empty());
- indicesData[i] = SLVec4i(curIndices.size() >= 1 ? curIndices[0] : 0,
+ jointIndicesData[i] = SLVec4i(curIndices.size() >= 1 ? curIndices[0] : 0,
curIndices.size() >= 2 ? curIndices[1] : 0,
curIndices.size() >= 3 ? curIndices[2] : 0,
curIndices.size() >= 4 ? curIndices[3] : 0);
@@ -769,19 +773,19 @@ void SLMesh::generateVAO(SLGLVertexArray& vao)
for (unsigned i = 0; i < P.size(); i++)
{
const SLVfloat& curWeights = Jw[i];
+ assert(curWeights.size() == Ji[i].size());
- indicesWeights[i] = SLVec4f(curWeights.size() >= 1 ? curWeights[0] : 0.0f,
- curWeights.size() >= 2 ? curWeights[1] : 0.0f,
- curWeights.size() >= 3 ? curWeights[2] : 0.0f,
- curWeights.size() >= 4 ? curWeights[3] : 0.0f);
+ jointWeightsData[i] = SLVec4f(curWeights.size() >= 1 ? curWeights[0] : 0.0f,
+ curWeights.size() >= 2 ? curWeights[1] : 0.0f,
+ curWeights.size() >= 3 ? curWeights[2] : 0.0f,
+ curWeights.size() >= 4 ? curWeights[3] : 0.0f);
}
-
- vao.setAttrib(AT_jointIndex, AT_jointIndex, &indicesData);
- vao.setAttrib(AT_jointWeight, AT_jointWeight, &indicesWeights);
+ vao.setAttrib(AT_jointIndex, AT_jointIndex, &jointIndicesData);
+ vao.setAttrib(AT_jointWeight, AT_jointWeight, &jointWeightsData);
}
vao.generate((SLuint)P.size(),
- !Ji.empty() && !_mat->supportsGPUSkinning() ? BU_stream : BU_static,
+ !Ji.empty() ? BU_stream : BU_static,
Ji.empty());
}
//-----------------------------------------------------------------------------
From a49729fa5db46de3dd0529c43d3bb193588c81b8 Mon Sep 17 00:00:00 2001
From: Marino von Wattenwyl
Date: Wed, 28 Jun 2023 10:17:55 +0200
Subject: [PATCH 12/29] [SL] Add support for variables to shader generator
---
modules/sl/source/gl/SLGLProgramGenerated.cpp | 59 ++++++++++++-------
modules/sl/source/gl/SLGLProgramGenerated.h | 4 ++
2 files changed, 43 insertions(+), 20 deletions(-)
diff --git a/modules/sl/source/gl/SLGLProgramGenerated.cpp b/modules/sl/source/gl/SLGLProgramGenerated.cpp
index 43185814..6d630fe4 100644
--- a/modules/sl/source/gl/SLGLProgramGenerated.cpp
+++ b/modules/sl/source/gl/SLGLProgramGenerated.cpp
@@ -200,8 +200,8 @@ const string vertMain_v_uv1 = R"(
v_uv1 = a_uv1; // pass diffuse color tex.coord. 1 for interpolation)";
const string vertMain_skinning = R"(
- vec4 totalPosition;
- vec3 totalNormal;
+ vec4 skinnedPosition;
+ vec3 skinnedNormal;
if (u_skinningEnabled)
{
@@ -211,8 +211,8 @@ const string vertMain_skinning = R"(
// to animate the mesh. The effect that a joint has on a vertex is
// specified by the four weights passed along with the joint indices.
- totalPosition = vec4(0.0);
- totalNormal = vec3(0.0);
+ skinnedPosition = vec4(0.0);
+ skinnedNormal = vec3(0.0);
// iterate over all joints that are transforming this vertex.
for (int i = 0; i < 4; i++)
@@ -221,17 +221,17 @@ const string vertMain_skinning = R"(
mat4 jointMatrix = u_jointMatrices[a_jointIds[i]];
// apply the weighted transformation to the position and normal of the vertex.
- totalPosition += a_jointWeights[i] * jointMatrix * a_position;
- totalNormal += a_jointWeights[i] * mat3(jointMatrix) * a_normal;
+ skinnedPosition += a_jointWeights[i] * jointMatrix * a_position;
+ skinnedNormal += a_jointWeights[i] * mat3(jointMatrix) * a_normal;
}
- v_P_VS = vec3(mvMatrix * totalPosition);
- v_N_VS = normalize(vec3(nMatrix * totalNormal));
+ v_P_VS = vec3(mvMatrix * skinnedPosition);
+ v_N_VS = normalize(vec3(nMatrix * skinnedNormal));
}
else
{
- totalPosition = a_position;
- totalNormal = a_normal;
+ skinnedPosition = a_position;
+ skinnedNormal = a_normal;
})";
const string vertMain_TBN_Nm = R"(
@@ -309,17 +309,9 @@ const string vertMain_PS_EndAll_VertBillboard = R"(
const string vertMain_EndAll = R"(
// pass the vertex w. the fix-function transform
- gl_Position = u_pMatrix * mvMatrix * a_position;
+ gl_Position = u_pMatrix * mvMatrix * ${localPosition};
}
)";
-
-const string vertMain_EndSkinned = R"(
-
- // pass the vertex w. the fix-function transform
- gl_Position = u_pMatrix * mvMatrix * totalPosition;
-}
-)";
-
//-----------------------------------------------------------------------------
const string vertMain_PS_U_Begin = R"(
@@ -1861,6 +1853,9 @@ void SLGLProgramGenerated::buildPerPixCook(SLMaterial* mat, SLVLight* lights)
if (Nm) vertCode += vertMain_TBN_Nm;
vertCode += vertMain_EndAll;
+ // Vertex shader variables
+ setVariable(vertCode, "localPosition", "a_position");
+
addCodeToShader(_shaders[0], vertCode, _name + ".vert");
// Assemble fragment shader code
@@ -1979,7 +1974,10 @@ void SLGLProgramGenerated::buildPerPixBlinn(SLMaterial* mat, SLVLight* lights)
if (uv1) vertCode += vertMain_v_uv1;
if (skinning) vertCode += vertMain_skinning;
if (Nm) vertCode += vertMain_TBN_Nm;
- vertCode += skinning ? vertMain_EndSkinned : vertMain_EndAll;
+ vertCode += vertMain_EndAll;
+
+ // Vertex shader variables
+ setVariable(vertCode, "localPosition", skinning ? "skinnedPosition" : "a_position");
addCodeToShader(_shaders[0], vertCode, _name + ".vert");
@@ -2291,6 +2289,10 @@ void SLGLProgramGenerated::buildPerPixVideoBkgdSm(SLVLight* lights)
vertCode += vertMain_v_P_WS_Sm;
vertCode += vertMain_v_N_VS;
vertCode += vertMain_EndAll;
+
+ // Vertex shader variables
+ setVariable(vertCode, "localPosition", "a_position");
+
addCodeToShader(_shaders[0], vertCode, _name + ".vert");
// Assemble fragment shader code
@@ -2680,6 +2682,23 @@ void SLGLProgramGenerated::addCodeToShader(SLGLShader* shader,
shader->file(generatedShaderPath + name);
}
//-----------------------------------------------------------------------------
+//! Builds unique program name that identifies shader program
+/*! A variable is specified in templates like this: ${variableName}.
+ */
+void SLGLProgramGenerated::setVariable(std::string& code,
+ const std::string& name,
+ const std::string& value)
+{
+ std::string placeholder = "${" + name + "}";
+
+ std::string::size_type pos = 0;
+ while ((pos = code.find(placeholder)) != std::string::npos)
+ {
+ code.replace(pos, placeholder.size(), value);
+ pos += value.size();
+ }
+}
+//-----------------------------------------------------------------------------
//! Adds shader header code
string SLGLProgramGenerated::shaderHeader(int numLights)
diff --git a/modules/sl/source/gl/SLGLProgramGenerated.h b/modules/sl/source/gl/SLGLProgramGenerated.h
index 93ebc1da..3ce56bd1 100644
--- a/modules/sl/source/gl/SLGLProgramGenerated.h
+++ b/modules/sl/source/gl/SLGLProgramGenerated.h
@@ -118,6 +118,10 @@ class SLGLProgramGenerated : public SLGLProgram
static void addCodeToShader(SLGLShader* shader,
const string& code,
const string& name);
+ static void setVariable(std::string& code,
+ const std::string& name,
+ const std::string& value);
+
static string generatedShaderPath; //! Path to write out generated shaders
};
//-----------------------------------------------------------------------------
From d4854bedac88a2279a64540952aaa0055da4dabc Mon Sep 17 00:00:00 2001
From: Marino von Wattenwyl
Date: Wed, 28 Jun 2023 11:26:26 +0200
Subject: [PATCH 13/29] [SL] GPU skinning in more complex shaders
GPU skinning should now work with the Cook-Torrance
reflection model and with normal mapping.
---
modules/sl/source/gl/SLGLProgramGenerated.cpp | 100 +++++++++++-------
1 file changed, 64 insertions(+), 36 deletions(-)
diff --git a/modules/sl/source/gl/SLGLProgramGenerated.cpp b/modules/sl/source/gl/SLGLProgramGenerated.cpp
index 6d630fe4..ae0cafed 100644
--- a/modules/sl/source/gl/SLGLProgramGenerated.cpp
+++ b/modules/sl/source/gl/SLGLProgramGenerated.cpp
@@ -63,7 +63,7 @@ uniform mat4 u_pMatrix; // Projection matrix (camera to normalize device coo
const string vertInput_u_matrix_vOmv = R"(
uniform mat4 u_vOmvMatrix; // view or modelview matrix)";
//-----------------------------------------------------------------------------
-const string vertInput_u_jointMatrices = R"(
+const string vertInput_u_skinning = R"(
uniform mat4 u_jointMatrices[100]; // Joint matrices for skinning
uniform bool u_skinningEnabled; // Flag if the shader should perform skinning
@@ -182,13 +182,13 @@ void main()
{)";
const string vertMain_v_P_VS = R"(
mat4 mvMatrix = u_vMatrix * u_mMatrix;
- v_P_VS = vec3(mvMatrix * a_position); // vertex position in view space)";
+ v_P_VS = vec3(mvMatrix * ${localPosition}); // vertex position in view space)";
const string vertMain_v_P_WS_Sm = R"(
- v_P_WS = vec3(u_mMatrix * a_position); // vertex position in world space)";
+ v_P_WS = vec3(u_mMatrix * ${localPosition}); // vertex position in world space)";
const string vertMain_v_N_VS = R"(
mat3 invMvMatrix = mat3(inverse(mvMatrix));
mat3 nMatrix = transpose(invMvMatrix);
- v_N_VS = vec3(nMatrix * a_normal); // vertex normal in view space)";
+ v_N_VS = vec3(nMatrix * ${localNormal}); // vertex normal in view space)";
const string vertMain_v_R_OS = R"(
vec3 I = normalize(v_P_VS);
vec3 N = normalize(v_N_VS);
@@ -199,47 +199,63 @@ const string vertMain_v_uv0 = R"(
const string vertMain_v_uv1 = R"(
v_uv1 = a_uv1; // pass diffuse color tex.coord. 1 for interpolation)";
const string vertMain_skinning = R"(
-
vec4 skinnedPosition;
vec3 skinnedNormal;
if (u_skinningEnabled)
{
// In skinned skeleton animation, every vertex of a mesh is transformed by
- // max. four joints (bones) of a skeleton identified by indices. The
- // joint matrices represent this transformation and can change per frame
- // to animate the mesh. The effect that a joint has on a vertex is
- // specified by the four weights passed along with the joint indices.
-
- skinnedPosition = vec4(0.0);
- skinnedNormal = vec3(0.0);
-
- // iterate over all joints that are transforming this vertex.
- for (int i = 0; i < 4; i++)
- {
- // get the transformation of this joint.
- mat4 jointMatrix = u_jointMatrices[a_jointIds[i]];
-
- // apply the weighted transformation to the position and normal of the vertex.
- skinnedPosition += a_jointWeights[i] * jointMatrix * a_position;
- skinnedNormal += a_jointWeights[i] * mat3(jointMatrix) * a_normal;
- }
+ // max. four joints (bones) of a skeleton identified by indices. The joint
+ // matrix is a weighted sum of four joint matrices and can change per frame
+ // to animate the mesh.
+ mat4 jm = u_jointMatrices[int(a_jointIds.x)] * a_jointWeights.x
+ + u_jointMatrices[int(a_jointIds.y)] * a_jointWeights.y
+ + u_jointMatrices[int(a_jointIds.z)] * a_jointWeights.z
+ + u_jointMatrices[int(a_jointIds.w)] * a_jointWeights.w;
+
+ skinnedPosition = jm * a_position;
+ skinnedNormal = mat3(jm) * a_normal;
+ }
+ else
+ {
+ skinnedPosition = a_position;
+ skinnedNormal = a_normal;
+ }
+)";
+const string vertMain_skinning_Nm = R"(
+ vec4 skinnedPosition;
+ vec3 skinnedNormal;
+ vec4 skinnedTangent;
- v_P_VS = vec3(mvMatrix * skinnedPosition);
- v_N_VS = normalize(vec3(nMatrix * skinnedNormal));
+ if (u_skinningEnabled)
+ {
+ // In skinned skeleton animation, every vertex of a mesh is transformed by
+ // max. four joints (bones) of a skeleton identified by indices. The joint
+ // matrix is a weighted sum of four joint matrices and can change per frame
+ // to animate the mesh.
+ mat4 jm = u_jointMatrices[int(a_jointIds.x)] * a_jointWeights.x
+ + u_jointMatrices[int(a_jointIds.y)] * a_jointWeights.y
+ + u_jointMatrices[int(a_jointIds.z)] * a_jointWeights.z
+ + u_jointMatrices[int(a_jointIds.w)] * a_jointWeights.w;
+
+ skinnedPosition = jm * a_position;
+ skinnedNormal = mat3(jm) * a_normal;
+ skinnedTangent = vec4(mat3(jm) * a_tangent.xyz, a_tangent.w);
}
else
{
skinnedPosition = a_position;
skinnedNormal = a_normal;
- })";
+ skinnedTangent = a_tangent;
+ }
+)";
const string vertMain_TBN_Nm = R"(
// Building the matrix Eye Space -> Tangent Space
// See the math behind at: http://www.terathon.com/code/tangent.html
- vec3 n = normalize(nMatrix * a_normal);
- vec3 t = normalize(nMatrix * a_tangent.xyz);
- vec3 b = cross(n, t) * a_tangent.w; // bitangent w. corrected handedness
+ vec3 n = normalize(nMatrix * ${localNormal});
+ vec3 t = normalize(nMatrix * ${localTangent}.xyz);
+ vec3 b = cross(n, t) * ${localTangent}.w; // bitangent w. corrected handedness
mat3 TBN = mat3(t,b,n);
// Transform vector to the eye into tangent space
@@ -1587,8 +1603,9 @@ void main()
The shader program gets a unique name with the following pattern:
- genCook-D00-N00-E00-O01-RM00-Sky-C4s
- | | | | | | | |
+ genCook-D00-N00-E00-O01-RM00-Sky-C4s-S
+ | | | | | | | | |
+ | | | | | | | | + Support for GPU skinning
| | | | | | | + Directional light w. 4 shadow cascades
| | | | | | + Ambient light from skybox
| | | | | + Roughness-metallic map with index 0 and uv 0
@@ -1823,6 +1840,9 @@ 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());
@@ -1831,9 +1851,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;
vertCode += vertInput_u_matrices_all;
// if (sky) vertCode += vertInput_u_matrix_invMv;
if (Nm) vertCode += vertInput_u_lightNm;
+ if (skinning) vertCode += vertInput_u_skinning;
// Vertex shader outputs
vertCode += vertOutput_v_P_VS;
@@ -1845,6 +1867,7 @@ void SLGLProgramGenerated::buildPerPixCook(SLMaterial* mat, SLVLight* lights)
// Vertex shader main loop
vertCode += vertMain_Begin;
+ if (skinning) 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;
@@ -1854,7 +1877,9 @@ void SLGLProgramGenerated::buildPerPixCook(SLMaterial* mat, SLVLight* lights)
vertCode += vertMain_EndAll;
// Vertex shader variables
- setVariable(vertCode, "localPosition", "a_position");
+ setVariable(vertCode, "localPosition", skinning ? "skinnedPosition" : "a_position");
+ setVariable(vertCode, "localNormal", skinning ? "skinnedNormal" : "a_normal");
+ if (Nm) setVariable(vertCode, "localTangent", skinning ? "skinnedTangent" : "a_tangent");
addCodeToShader(_shaders[0], vertCode, _name + ".vert");
@@ -1940,7 +1965,7 @@ void SLGLProgramGenerated::buildPerPixBlinn(SLMaterial* mat, SLVLight* lights)
bool uv0 = mat->usesUVIndex(0);
bool uv1 = mat->usesUVIndex(1);
- // Check if we use GPU skinning
+ // Check if the shader has to support skinning
bool skinning = mat->supportsGPUSkinning();
// Assemble vertex shader code
@@ -1954,8 +1979,8 @@ void SLGLProgramGenerated::buildPerPixBlinn(SLMaterial* mat, SLVLight* lights)
if (Nm) vertCode += vertInput_a_tangent;
if (skinning) vertCode += vertInput_a_skinning;
vertCode += vertInput_u_matrices_all;
- if (skinning) vertCode += vertInput_u_jointMatrices;
if (Nm) vertCode += vertInput_u_lightNm;
+ if (skinning) vertCode += vertInput_u_skinning;
// Vertex shader outputs
vertCode += vertOutput_v_P_VS;
@@ -1967,17 +1992,19 @@ void SLGLProgramGenerated::buildPerPixBlinn(SLMaterial* mat, SLVLight* lights)
// Vertex shader main loop
vertCode += vertMain_Begin;
+ if (skinning) 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;
if (uv0) vertCode += vertMain_v_uv0;
if (uv1) vertCode += vertMain_v_uv1;
- if (skinning) vertCode += vertMain_skinning;
if (Nm) vertCode += vertMain_TBN_Nm;
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");
addCodeToShader(_shaders[0], vertCode, _name + ".vert");
@@ -2292,6 +2319,7 @@ void SLGLProgramGenerated::buildPerPixVideoBkgdSm(SLVLight* lights)
// Vertex shader variables
setVariable(vertCode, "localPosition", "a_position");
+ setVariable(vertCode, "localNormal", "a_normal");
addCodeToShader(_shaders[0], vertCode, _name + ".vert");
@@ -2682,7 +2710,7 @@ void SLGLProgramGenerated::addCodeToShader(SLGLShader* shader,
shader->file(generatedShaderPath + name);
}
//-----------------------------------------------------------------------------
-//! Builds unique program name that identifies shader program
+//! Sets a variable in the shader code.
/*! A variable is specified in templates like this: ${variableName}.
*/
void SLGLProgramGenerated::setVariable(std::string& code,
From d890b770445be6892d9a045a9ff77ebbfe0740bc Mon Sep 17 00:00:00 2001
From: Marcus Hudritsch
Date: Tue, 11 Jul 2023 14:42:35 +0200
Subject: [PATCH 14/29] Silenced some Warnings and typos
---
.../ch00_new_cpp_features/ch00_NewCppFeatures.cpp | 2 +-
modules/cv/source/CVTrackedFeatures.cpp | 2 +-
modules/math/CMakeLists.txt | 7 ++-----
modules/math/externals/Shoemake/EulerAngles.cpp | 6 ------
modules/sl/source/gl/SLGLTexture.h | 4 ++--
modules/sl/source/input/SLAssimpImporter.cpp | 4 ++--
6 files changed, 8 insertions(+), 17 deletions(-)
diff --git a/apps/exercises/ch00_new_cpp_features/ch00_NewCppFeatures.cpp b/apps/exercises/ch00_new_cpp_features/ch00_NewCppFeatures.cpp
index d5d0cfd2..db3bf7d8 100644
--- a/apps/exercises/ch00_new_cpp_features/ch00_NewCppFeatures.cpp
+++ b/apps/exercises/ch00_new_cpp_features/ch00_NewCppFeatures.cpp
@@ -293,7 +293,7 @@ void new_rvalue_references()
const char* pb1 = b.c_str();
cout << "a before the move: " << std::hex << pa1 << ", " << pa1 << endl;
cout << "b before the move: " << std::hex << pb1 << ", " << pb1 << endl;
- b = move(a);
+ //b = move(a);
const char* pa2 = a.c_str();
const char* pb2 = b.c_str();
cout << "a after the move: " << std::hex << pa2 << ", " << pa2 << endl;
diff --git a/modules/cv/source/CVTrackedFeatures.cpp b/modules/cv/source/CVTrackedFeatures.cpp
index 329a9de1..6fb7ab1c 100644
--- a/modules/cv/source/CVTrackedFeatures.cpp
+++ b/modules/cv/source/CVTrackedFeatures.cpp
@@ -792,9 +792,9 @@ void CVTrackedFeatures::optimizeMatches()
#endif
}
-#if DO_FEATURE_BENCHMARKING
sum_reprojection_error += reprojectionError / _marker.keypoints3D.size();
+#if DO_FEATURE_BENCHMARKING
CVMat prevRmat, currRmat;
if (_prevFrame.foundPose)
{
diff --git a/modules/math/CMakeLists.txt b/modules/math/CMakeLists.txt
index 0bcf811c..168fbe0e 100644
--- a/modules/math/CMakeLists.txt
+++ b/modules/math/CMakeLists.txt
@@ -39,6 +39,8 @@ add_library(${target}
${headers}
${sources})
+add_definitions(-w)
+
add_library(${META_PROJECT_NAME}::${target}
ALIAS
${target}
@@ -46,11 +48,6 @@ add_library(${META_PROJECT_NAME}::${target}
enable_warnings(${target})
-set_target_properties(${target}
- PROPERTIES
- ${DEFAULT_PROJECT_OPTIONS}
- )
-
target_include_directories(${target}
PRIVATE
diff --git a/modules/math/externals/Shoemake/EulerAngles.cpp b/modules/math/externals/Shoemake/EulerAngles.cpp
index bde45d00..7ef1f215 100644
--- a/modules/math/externals/Shoemake/EulerAngles.cpp
+++ b/modules/math/externals/Shoemake/EulerAngles.cpp
@@ -12,8 +12,6 @@ EulerAngles Eul_(float ai, float aj, float ah, int order)
return (ea);
}
/* Construct quaternion from Euler angles (in radians). */
-#pragma warning(disable:4552)
-#pragma warning(disable:4244)
Quat Eul_ToQuat(EulerAngles ea)
{
Quat qu;
@@ -43,8 +41,6 @@ Quat Eul_ToQuat(EulerAngles ea)
}
/* Construct matrix from Euler angles (in radians). */
-#pragma warning(disable:4552)
-#pragma warning( disable:4244)
void Eul_ToHMatrix(EulerAngles ea, HMatrix M)
{ double ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
int i,j,k,h,n,s,f;
@@ -68,8 +64,6 @@ void Eul_ToHMatrix(EulerAngles ea, HMatrix M)
}
/* Convert matrix to Euler angles (in radians). */
-#pragma warning(disable:4552)
-#pragma warning( disable:4244)
EulerAngles Eul_FromHMatrix(HMatrix M, int order)
{
EulerAngles ea;
diff --git a/modules/sl/source/gl/SLGLTexture.h b/modules/sl/source/gl/SLGLTexture.h
index a9542069..546af1e6 100644
--- a/modules/sl/source/gl/SLGLTexture.h
+++ b/modules/sl/source/gl/SLGLTexture.h
@@ -220,8 +220,8 @@ class SLGLTexture : public SLObject
SLuint depth() { return _depth; }
SLbyte uvIndex() { return _uvIndex; }
SLint bytesPerPixel() { return _bytesPerPixel; }
- SLint bytesOnGPU() { return _bytesOnGPU; }
- SLint bytesInFile() { return _bytesInFile; }
+ SLint bytesOnGPU() { return (SLint)_bytesOnGPU; }
+ SLint bytesInFile() { return (SLint)_bytesInFile; }
CVVImage& images() { return _images; }
SLenum target() const { return _target; }
SLuint texID() const { return _texID; }
diff --git a/modules/sl/source/input/SLAssimpImporter.cpp b/modules/sl/source/input/SLAssimpImporter.cpp
index a031840e..a05de729 100644
--- a/modules/sl/source/input/SLAssimpImporter.cpp
+++ b/modules/sl/source/input/SLAssimpImporter.cpp
@@ -917,7 +917,7 @@ SLGLTexture* SLAssimpImporter::loadTexture(SLAssetManager* assetMgr,
minificationFilter,
GL_LINEAR,
texType);
- texture->uvIndex(uvIndex);
+ texture->uvIndex((SLbyte)uvIndex);
// if texture images get deleted after build you can't do ray tracing
if (deleteTexImgAfterBuild)
@@ -1274,7 +1274,7 @@ SLAnimation* SLAssimpImporter::loadAnimation(SLAnimManager& animManager, aiAnima
// exit if we didn't load a skeleton but have animations for one
if (!_skinnedMeshes.empty())
- assert(_skeleton != nullptr && "The skeleton wasn't impoted correctly.");
+ assert(_skeleton != nullptr && "The skeleton wasn't imported correctly.");
// create the animation
SLAnimation* result;
From be175660b2261a281d0ee3f5452df5fd3cdd756f Mon Sep 17 00:00:00 2001
From: Marcus Hudritsch
Date: Wed, 20 Sep 2023 08:16:32 +0200
Subject: [PATCH 15/29] Update README.md
---
README.md | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 1bbb2f7c..8ceebd4e 100644
--- a/README.md
+++ b/README.md
@@ -3,12 +3,13 @@
[![Build Windows](https://github.com/cpvrlab/SLProject4/actions/workflows/build-x86_64-windows.yml/badge.svg)](https://github.com/cpvrlab/SLProject4/actions/workflows/build-x86_64-windows.yml)
[![Build macOS](https://github.com/cpvrlab/SLProject4/actions/workflows/build-x86_64-macos.yml/badge.svg)](https://github.com/cpvrlab/SLProject4/actions/workflows/build-x86_64-macos.yml)
[![Build Emscripten](https://github.com/cpvrlab/SLProject4/actions/workflows/build-wasm-emscripten.yml/badge.svg)](https://github.com/cpvrlab/SLProject4/actions/workflows/build-wasm-emscripten.yml)
+[![Build Online Docs](https://github.com/cpvrlab/SLProject4/actions/workflows/build-docs.yml/badge.svg)](https://github.com/cpvrlab/SLProject4/actions/workflows/build-docs.yml)
-SL stands for Scene Library. It is developed at the Berne University of Applied Sciences (BFH) in Switzerland and is used for student projects in the cpvrLab. The various applications show what you can learn in three semesters about 3D computer graphics in real time rendering and ray tracing. The framework is built in C++ and OpenGL ES and can be built for Windows, Linux, macOS (Intel & arm64), Android, Apple iOS and for WebAssembly enabled browsers. The framework can render alternatively with Ray Tracing and Path Tracing which provides in addition high quality transparencies, reflections and soft shadows. For a complete feature list see the [SLProject4 wiki](https://github.com/cpvrlab/SLProject4/wiki).
+SL stands for Scene Library. It is developed at the Berne University of Applied Sciences (BFH) in Switzerland and is used for student projects in the cpvrLab. The various applications show what you can learn in three semesters about 3D computer graphics in real-time rendering and ray tracing. The framework is built in C++ and OpenGL ES and can be built for Windows, Linux, macOS (Intel & arm64), Android, Apple iOS, and WebAssembly-enabled browsers. The framework can render alternatively with Ray Tracing and Path Tracing, which provides high-quality transparencies, reflections, and soft shadows. For a complete feature list see the [SLProject4 wiki](https://github.com/cpvrlab/SLProject4/wiki).
## How to get the SLProject4
-The SLProject4 is hosted at GitHub as a GIT repository.
+The SLProject4 is hosted on GitHub as a GIT repository.
[GIT](http://git-scm.com/) is a distributed versioning control system.
To clone SLProject4, use the following command:
@@ -18,7 +19,7 @@ cd
git clone https://github.com/cpvrlab/SLProject4.git
```
-For people with an aversion to the command line, a GIT GUI tool, such as the [GitHub Desktop Client](https://desktop.github.com), can be used. To get the latest additions to SLProject4, please checkout the develop branch:
+For people with an aversion to the command line, a GIT GUI tool, such as the [GitHub Desktop Client](https://desktop.github.com), can be used. To get the latest additions to SLProject4, please check the develop branch:
```
git checkout develop
From af8fd9293c218e4b13cd65a05010b0c9b454319c Mon Sep 17 00:00:00 2001
From: Marcus Hudritsch
Date: Fri, 29 Sep 2023 12:44:09 +0200
Subject: [PATCH 16/29] Update ch08_BlinnPhongLighting.frag
---
data/shaders/ch08_BlinnPhongLighting.frag | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/data/shaders/ch08_BlinnPhongLighting.frag b/data/shaders/ch08_BlinnPhongLighting.frag
index adf344ee..4cc50e5e 100644
--- a/data/shaders/ch08_BlinnPhongLighting.frag
+++ b/data/shaders/ch08_BlinnPhongLighting.frag
@@ -27,7 +27,7 @@ uniform vec4 u_globalAmbi; // Global ambient scene color
uniform vec4 u_matAmbi; // ambient color reflection coefficient (ka)
uniform vec4 u_matDiff; // diffuse color reflection coefficient (kd)
uniform vec4 u_matSpec; // specular color reflection coefficient (ks)
-uniform vec4 u_matEmis; // emissive color for self-shining materials
+uniform vec4 u_matEmis; // emissive color for self-shining materials (ke)
uniform float u_matShin; // shininess exponent
out vec4 o_fragColor; // output fragment color
From 406e36972ce0a6b2011b91df8f86bfac1c1e91aa Mon Sep 17 00:00:00 2001
From: luc
Date: Thu, 26 Oct 2023 18:29:01 +0200
Subject: [PATCH 17/29] Add support for draw instanced and use of a shared VBO
in multiples VAO
---
modules/sl/source/gl/SLGLVertexArray.cpp | 78 +++++++++++-
modules/sl/source/gl/SLGLVertexArray.h | 39 ++++--
modules/sl/source/gl/SLGLVertexBuffer.cpp | 141 +++++++++-------------
modules/sl/source/gl/SLGLVertexBuffer.h | 2 +-
modules/sl/source/mesh/SLMesh.cpp | 7 +-
modules/sl/source/mesh/SLMesh.h | 2 +-
6 files changed, 169 insertions(+), 100 deletions(-)
diff --git a/modules/sl/source/gl/SLGLVertexArray.cpp b/modules/sl/source/gl/SLGLVertexArray.cpp
index 9738308f..79e4d8c2 100644
--- a/modules/sl/source/gl/SLGLVertexArray.cpp
+++ b/modules/sl/source/gl/SLGLVertexArray.cpp
@@ -29,6 +29,7 @@ SLGLVertexArray::SLGLVertexArray()
_numVertices = 0;
_indexDataElements = nullptr;
_indexDataEdges = nullptr;
+ _externalVBOf = nullptr;
}
//-----------------------------------------------------------------------------
/*! Deletes the OpenGL objects for the vertex array and the vertex buffer.
@@ -86,6 +87,14 @@ void SLGLVertexArray::setAttrib(SLGLAttributeType type,
_VBOf.attribs().push_back(va);
}
+
+//-----------------------------------------------------------------------------
+ void SLGLVertexArray::setExternalVBO(SLGLVertexBuffer* vbo, SLuint divisor)
+ {
+ _externalVBOf = vbo;
+ _externalDivisor = divisor;
+ }
+
//-----------------------------------------------------------------------------
/*! Defines the vertex indices for the element drawing. Without indices vertex
array can only be drawn with SLGLVertexArray::drawArrayAs.
@@ -140,6 +149,7 @@ void SLGLVertexArray::updateAttrib(SLGLAttributeType type,
glBindVertexArray(0);
GET_GL_ERROR;
}
+
//-----------------------------------------------------------------------------
/*! Generates the OpenGL objects for the vertex array and the vertex buffer
object. If the input data is an interleaved array (all attribute data pointer
@@ -174,7 +184,8 @@ void SLGLVertexArray::updateAttrib(SLGLAttributeType type,
*/
void SLGLVertexArray::generate(SLuint numVertices,
SLGLBufferUsage usage,
- SLbool outputInterleaved)
+ SLbool outputInterleaved,
+ SLuint divisor)
{
assert(numVertices);
@@ -193,7 +204,15 @@ void SLGLVertexArray::generate(SLuint numVertices,
// Generate the vertex buffer object for float attributes
if (_VBOf.attribs().size())
+ {
_VBOf.generate(numVertices, usage, outputInterleaved);
+ _VBOf.bindAndEnableAttrib(divisor);
+ }
+
+ if (_externalVBOf != nullptr)
+ {
+ _externalVBOf->bindAndEnableAttrib(_externalDivisor);
+ }
/////////////////////////////////////////////////////////////////
// Create Element Array Buffer for Indices for elements and edges
@@ -240,7 +259,8 @@ void SLGLVertexArray::generate(SLuint numVertices,
/*! Same as generate but with transform feedback */
void SLGLVertexArray::generateTF(SLuint numVertices,
SLGLBufferUsage usage,
- SLbool outputInterleaved)
+ SLbool outputInterleaved,
+ SLuint divisor)
{
assert(numVertices);
@@ -262,7 +282,15 @@ void SLGLVertexArray::generateTF(SLuint numVertices,
// Generate the vertex buffer object for float attributes
if (_VBOf.attribs().size())
+ {
_VBOf.generate(numVertices, usage, outputInterleaved);
+ _VBOf.bindAndEnableAttrib(divisor);
+ }
+
+ if (_externalVBOf != nullptr)
+ {
+ _externalVBOf->bindAndEnableAttrib(_externalDivisor);
+ }
///////////////////////////////
// Bind transform feedback
@@ -430,6 +458,52 @@ void SLGLVertexArray::drawArrayAs(SLGLPrimitiveType primitiveType,
GET_GL_ERROR;
}
+
+void SLGLVertexArray::drawElementsInstanced(SLGLPrimitiveType primitiveType,
+ SLsizei countInstance,
+ SLuint numIndexes,
+ SLuint indexOffset
+ )
+{
+ assert(_numIndicesElements && _idVBOIndices && "No index VBO generated for VAO");
+
+ // From OpenGL 3.0 on we have the OpenGL Vertex Arrays
+ // Binding the VAO saves all the commands after the else (per draw call!)
+ glBindVertexArray(_vaoID);
+ GET_GL_ERROR;
+
+ // Do the draw call with indices
+ if (numIndexes == 0)
+ numIndexes = _numIndicesElements;
+
+ SLuint indexTypeSize = SLGLVertexBuffer::sizeOfType(_indexDataType);
+
+ ////////////////////////////////////////////////////////
+ glDrawElementsInstanced(primitiveType, (SLsizei)numIndexes ,_indexDataType, (void*)(size_t)(indexOffset * (SLuint)indexTypeSize), countInstance);
+ //glDrawElements(primitiveType, (SLsizei)numIndexes ,_indexDataType, (void*)(size_t)(indexOffset * (SLuint)indexTypeSize));
+ ////////////////////////////////////////////////////////
+
+ GET_GL_ERROR;
+ // Update statistics
+ totalDrawCalls++;
+ switch (primitiveType)
+ {
+ case PT_triangles:
+ totalPrimitivesRendered += (numIndexes / 3);
+ break;
+ case PT_lines:
+ totalPrimitivesRendered += (numIndexes / 2);
+ break;
+ case PT_points:
+ totalPrimitivesRendered += numIndexes;
+ break;
+ default: break;
+ }
+ glBindVertexArray(0);
+
+ GET_GL_ERROR;
+}
+
//-----------------------------------------------------------------------------
/*! Draws the hard edges with the specified color.
The VAO has no or one active index buffer. For drawArrayAs no indices are needed.
diff --git a/modules/sl/source/gl/SLGLVertexArray.h b/modules/sl/source/gl/SLGLVertexArray.h
index 4b902f54..b0c0459d 100644
--- a/modules/sl/source/gl/SLGLVertexArray.h
+++ b/modules/sl/source/gl/SLGLVertexArray.h
@@ -130,6 +130,9 @@ class SLGLVertexArray
indicesEdges && indicesEdges->size() ? (void*)&indicesEdges->operator[](0) : nullptr);
}
+ //! Attach a VBO that has been created outside of this VAO
+ void setExternalVBO(SLGLVertexBuffer *vbo, SLuint divisor = 0);
+
//! Updates a specific vertex attribute in the VBO
void updateAttrib(SLGLAttributeType type,
SLint elementSize,
@@ -158,12 +161,14 @@ class SLGLVertexArray
//! Generates the VA & VB objects for a NO. of vertices
void generate(SLuint numVertices,
SLGLBufferUsage usage = BU_static,
- SLbool outputInterleaved = true);
+ SLbool outputInterleaved = true,
+ SLuint divisor = 0);
//! Generates the VA & VB & TF objects
void generateTF(SLuint numVertices,
SLGLBufferUsage usage = BU_static,
- SLbool outputInterleaved = true);
+ SLbool outputInterleaved = true,
+ SLuint divisor = 0);
//! Begin transform feedback
void beginTF(SLuint tfoID);
@@ -181,6 +186,12 @@ class SLGLVertexArray
SLint firstVertex = 0,
SLsizei countVertices = 0);
+ //! Draws the VAO as an array with instance primitive type
+ void drawElementsInstanced(SLGLPrimitiveType primitiveType,
+ SLsizei countInstance = 0,
+ SLuint numIndexes = 0,
+ SLuint indexOffset = 0);
+
//! Draws the hard edges of the VAO with the edge indices
void drawEdges(SLCol4f color, SLfloat lineWidth = 1.0f);
@@ -188,22 +199,26 @@ class SLGLVertexArray
SLuint numVertices() const { return _numVertices; }
SLuint numIndicesElements() const { return _numIndicesElements; }
SLuint numIndicesEdges() const { return _numIndicesEdges; }
+ SLGLVertexBuffer* vbo() { return &_VBOf; }
// Some statistics
static SLuint totalDrawCalls; //! static total no. of draw calls
static SLuint totalPrimitivesRendered; //! static total no. of primitives rendered
protected:
- SLuint _vaoID; //! OpenGL id of vertex array object
- SLuint _tfoID; //! OpenGL id of transform feedback object
- SLuint _numVertices; //! NO. of vertices in array
- SLGLVertexBuffer _VBOf; //! Vertex buffer object for float attributes
- SLuint _idVBOIndices; //! OpenGL id of index vbo
- SLuint _numIndicesElements; //! NO. of vertex indices in array for triangles, lines or points
- void* _indexDataElements; //! Pointer to index data for elements
- SLuint _numIndicesEdges; //! NO. of vertex indices in array for hard edges
- void* _indexDataEdges; //! Pointer to index data for hard edges
- SLGLBufferType _indexDataType; //! index data type (ubyte, ushort, uint)
+ SLuint _instances; //! Number of instances of drawing
+ SLuint _vaoID; //! OpenGL id of vertex array object
+ SLuint _tfoID; //! OpenGL id of transform feedback object
+ SLuint _numVertices; //! NO. of vertices in array
+ SLGLVertexBuffer _VBOf; //! Vertex buffer object for float attributes
+ SLGLVertexBuffer* _externalVBOf; //! Vertex buffer object that has beed created outside of this VAO
+ SLuint _externalDivisor; //! VBO attrib divisor for the external VBO
+ SLuint _idVBOIndices; //! OpenGL id of index vbo
+ SLuint _numIndicesElements; //! NO. of vertex indices in array for triangles, lines or points
+ void* _indexDataElements; //! Pointer to index data for elements
+ SLuint _numIndicesEdges; //! NO. of vertex indices in array for hard edges
+ void* _indexDataEdges; //! Pointer to index data for hard edges
+ SLGLBufferType _indexDataType; //! index data type (ubyte, ushort, uint)
};
//-----------------------------------------------------------------------------
diff --git a/modules/sl/source/gl/SLGLVertexBuffer.cpp b/modules/sl/source/gl/SLGLVertexBuffer.cpp
index 935f776d..d5bae373 100644
--- a/modules/sl/source/gl/SLGLVertexBuffer.cpp
+++ b/modules/sl/source/gl/SLGLVertexBuffer.cpp
@@ -195,33 +195,6 @@ void SLGLVertexBuffer::generate(SLuint numVertices,
if (inputIsInterleaved)
{
- for (auto a : _attribs)
- {
- if (a.location > -1)
- { // Sets the vertex attribute data pointer to its corresponding GLSL variable
- if (a.dataType == BT_uint)
- {
- glVertexAttribIPointer((SLuint)a.location,
- a.elementSize,
- a.dataType,
- (SLint)_strideBytes,
- (void*)(size_t)a.offsetBytes);
- }
- else
- {
- glVertexAttribPointer((SLuint)a.location,
- a.elementSize,
- a.dataType,
- GL_FALSE,
- (SLint)_strideBytes,
- (void*)(size_t)a.offsetBytes);
- }
-
- // Tell the attribute to be an array attribute instead of a state variable
- glEnableVertexAttribArray((SLuint)a.location);
- }
- }
-
// generate the interleaved VBO buffer on the GPU
glBufferData(GL_ARRAY_BUFFER, _sizeBytes, _attribs[0].dataPointer, _usage);
}
@@ -244,30 +217,6 @@ void SLGLVertexBuffer::generate(SLuint numVertices,
for (SLuint b = 0; b < elementSizeBytes; ++b)
data[iDst + b] = ((SLuchar*)a.dataPointer)[iSrc + b];
}
-
- if (a.location > -1)
- { // Sets the vertex attribute data pointer to its corresponding GLSL variable
- if (a.dataType == BT_uint)
- {
- glVertexAttribIPointer((SLuint)a.location,
- a.elementSize,
- a.dataType,
- (SLint)_strideBytes,
- (void*)(size_t)a.offsetBytes);
- }
- else
- {
- glVertexAttribPointer((SLuint)a.location,
- a.elementSize,
- a.dataType,
- GL_FALSE,
- (SLint)_strideBytes,
- (void*)(size_t)a.offsetBytes);
- }
-
- // Tell the attribute to be an array attribute instead of a state variable
- glEnableVertexAttribArray((SLuint)a.location);
- }
}
// generate the interleaved VBO buffer on the GPU
@@ -287,28 +236,6 @@ void SLGLVertexBuffer::generate(SLuint numVertices,
a.offsetBytes,
a.bufferSizeBytes,
a.dataPointer);
-
- // Sets the vertex attribute data pointer to its corresponding GLSL variable
- if (a.dataType == BT_uint)
- {
- glVertexAttribIPointer((SLuint)a.location,
- a.elementSize,
- a.dataType,
- 0,
- (void*)(size_t)a.offsetBytes);
- }
- else
- {
- glVertexAttribPointer((SLuint)a.location,
- a.elementSize,
- a.dataType,
- GL_FALSE,
- 0,
- (void*)(size_t)a.offsetBytes);
- }
-
- // Tell the attribute to be an array attribute instead of a state variable
- glEnableVertexAttribArray((SLuint)a.location);
}
}
}
@@ -318,34 +245,84 @@ void SLGLVertexBuffer::generate(SLuint numVertices,
totalBufferSize += _sizeBytes;
GET_GL_ERROR;
}
+
//-----------------------------------------------------------------------------
/*! This method is only used by SLGLVertexArray drawing methods for OpenGL
contexts prior to 3.0 where vertex array objects did not exist. This is the
additional overhead that had to be done per draw call.
*/
-void SLGLVertexBuffer::bindAndEnableAttrib()
+void SLGLVertexBuffer::bindAndEnableAttrib(SLuint divisor) const
{
- if (_attribs.size())
+ //////////////////////////////////////
+ // Associate VBO to Attribute location
+ //////////////////////////////////////
+
+ glBindBuffer(GL_ARRAY_BUFFER, _id);
+
+ if (_outputInterleaved) // Copy attribute data interleaved
{
- glBindBuffer(GL_ARRAY_BUFFER, _id);
+ for (auto a : _attribs)
+ {
+ if (a.location > -1)
+ { // Sets the vertex attribute data pointer to its corresponding GLSL variable
+ if (a.dataType == BT_uint)
+ {
+ glVertexAttribIPointer((SLuint)a.location,
+ a.elementSize,
+ a.dataType,
+ (SLint)_strideBytes,
+ (void*)(size_t)a.offsetBytes);
+ }
+ else
+ {
+ glVertexAttribPointer((SLuint)a.location,
+ a.elementSize,
+ a.dataType,
+ GL_FALSE,
+ (SLint)_strideBytes,
+ (void*)(size_t)a.offsetBytes);
+ }
+ // Tell the attribute to be an array attribute instead of a state variable
+ glEnableVertexAttribArray((SLuint)a.location);
+ if (divisor > 0)
+ glVertexAttribDivisor((SLuint)a.location, divisor);
+ }
+ }
+ }
+ else // copy attributes buffers sequentially
+ {
for (auto a : _attribs)
{
if (a.location > -1)
{
// Sets the vertex attribute data pointer to its corresponding GLSL variable
- glVertexAttribPointer((SLuint)a.location,
- a.elementSize,
- a.dataType,
- GL_FALSE,
- (SLsizei)_strideBytes,
- (void*)(size_t)a.offsetBytes);
+ if (a.dataType == BT_uint)
+ {
+ glVertexAttribIPointer((SLuint)a.location,
+ a.elementSize,
+ a.dataType,
+ 0,
+ (void*)(size_t)a.offsetBytes);
+ }
+ else
+ {
+ glVertexAttribPointer((SLuint)a.location,
+ a.elementSize,
+ a.dataType,
+ GL_FALSE,
+ 0,
+ (void*)(size_t)a.offsetBytes);
+ }
// Tell the attribute to be an array attribute instead of a state variable
glEnableVertexAttribArray((SLuint)a.location);
+ if (divisor > 0)
+ glVertexAttribDivisor((SLuint)a.location, divisor);
}
}
}
+ GET_GL_ERROR;
}
//-----------------------------------------------------------------------------
/*! This method is only used by SLGLVertexArray drawing methods for OpenGL
diff --git a/modules/sl/source/gl/SLGLVertexBuffer.h b/modules/sl/source/gl/SLGLVertexBuffer.h
index 7d6ec776..b6425fa3 100644
--- a/modules/sl/source/gl/SLGLVertexBuffer.h
+++ b/modules/sl/source/gl/SLGLVertexBuffer.h
@@ -87,7 +87,7 @@ class SLGLVertexBuffer
SLbool outputInterleaved = true);
//! Binds & enables the vertex attribute for OpenGL < 3.0
- void bindAndEnableAttrib();
+ void bindAndEnableAttrib(SLuint divisor = 0) const;
//! disables the vertex attribute for OpenGL < 3.0
void disableAttrib();
diff --git a/modules/sl/source/mesh/SLMesh.cpp b/modules/sl/source/mesh/SLMesh.cpp
index e2d0be05..c9c0b0ce 100644
--- a/modules/sl/source/mesh/SLMesh.cpp
+++ b/modules/sl/source/mesh/SLMesh.cpp
@@ -379,7 +379,7 @@ Optionally you can draw the normals and/or the uniform grid voxels.
Please view also the full process of rendering one frame
*/
-void SLMesh::draw(SLSceneView* sv, SLNode* node)
+void SLMesh::draw(SLSceneView* sv, SLNode* node, SLuint instances)
{
SLGLState* stateGL = SLGLState::instance();
@@ -469,7 +469,10 @@ void SLMesh::draw(SLSceneView* sv, SLNode* node)
_vao.drawArrayAs(PT_points);
else
{
- _vao.drawElementsAs(primitiveType);
+ if (instances > 1)
+ _vao.drawElementsInstanced(primitiveType, instances);
+ else
+ _vao.drawElementsAs(primitiveType);
if ((sv->drawBit(SL_DB_WITHEDGES) || node->drawBit(SL_DB_WITHEDGES)) &&
(!IE32.empty() || !IE16.empty()))
diff --git a/modules/sl/source/mesh/SLMesh.h b/modules/sl/source/mesh/SLMesh.h
index ff475e3f..957f2ad4 100644
--- a/modules/sl/source/mesh/SLMesh.h
+++ b/modules/sl/source/mesh/SLMesh.h
@@ -130,7 +130,7 @@ class SLMesh : public SLObject
~SLMesh() override;
virtual void init(SLNode* node);
- virtual void draw(SLSceneView* sv, SLNode* node);
+ virtual void draw(SLSceneView* sv, SLNode* node, SLuint intances = 0);
void drawIntoDepthBuffer(SLSceneView* sv,
SLNode* node,
SLMaterial* depthMat);
From 7618a51eb6b31906f245bb98927900eef2414be6 Mon Sep 17 00:00:00 2001
From: luc
Date: Thu, 2 Nov 2023 17:22:42 +0100
Subject: [PATCH 18/29] working version without finition
---
modules/sl/source/SLMaterial.cpp | 8 +-
modules/sl/source/SLMaterial.h | 2 +-
modules/sl/source/gl/SLGLProgramGenerated.cpp | 285 ++++++++++++++++--
modules/sl/source/gl/SLGLProgramGenerated.h | 13 +-
modules/sl/source/mesh/SLParticleSystem.cpp | 80 ++++-
modules/sl/source/mesh/SLParticleSystem.h | 6 +-
6 files changed, 360 insertions(+), 34 deletions(-)
diff --git a/modules/sl/source/SLMaterial.cpp b/modules/sl/source/SLMaterial.cpp
index 25719855..d26365a3 100644
--- a/modules/sl/source/SLMaterial.cpp
+++ b/modules/sl/source/SLMaterial.cpp
@@ -377,7 +377,7 @@ SLMaterial::~SLMaterial()
If this material has not yet a shader program assigned (SLMaterial::_program)
a suitable program will be generated with an instance of SLGLProgramGenerated.
*/
-void SLMaterial::generateProgramPS()
+void SLMaterial::generateProgramPS(bool renderInstanced)
{
// If no shader program is attached add a generated shader program
// A 3D object can be stored without material or shader program information.
@@ -395,11 +395,15 @@ void SLMaterial::generateProgramPS()
// If the program was not found by name generate a new one
if (!_program)
{
+ std::string geom = "";
+ if (!renderInstanced)
+ geom = "Geom";
+
_program = new SLGLProgramGenerated(_assetManager,
programNameDraw,
this,
true,
- "Geom");
+ geom);
}
}
diff --git a/modules/sl/source/SLMaterial.h b/modules/sl/source/SLMaterial.h
index 60dbbd97..983f2ff5 100644
--- a/modules/sl/source/SLMaterial.h
+++ b/modules/sl/source/SLMaterial.h
@@ -108,7 +108,7 @@ class SLMaterial : public SLObject
SLGLProgram* program);
~SLMaterial() override;
- void generateProgramPS();
+ void generateProgramPS(bool renderInstanced = false);
void activate(SLCamera* cam,
SLVLight* lights,
SLSkybox* skybox = nullptr);
diff --git a/modules/sl/source/gl/SLGLProgramGenerated.cpp b/modules/sl/source/gl/SLGLProgramGenerated.cpp
index bdb9aabf..9aee3ca3 100644
--- a/modules/sl/source/gl/SLGLProgramGenerated.cpp
+++ b/modules/sl/source/gl/SLGLProgramGenerated.cpp
@@ -44,6 +44,8 @@ const string vertInput_PS_a_texNum = R"(
layout (location = 6) in uint a_texNum; // Particle rotation attribute)";
const string vertInput_PS_a_initP = R"(
layout (location = 7) in vec3 a_initialPosition;// Particle initial position attribute)";
+const string vertInput_PS_a_positionP = R"(
+layout (location = 8) in vec3 a_positionP; // Particle position attribute)";
const string vertInput_a_uv0 = R"(
layout (location = 2) in vec2 a_uv0; // Vertex tex.coord. 1 for diffuse color)";
const string vertInput_a_uv1 = R"(
@@ -103,7 +105,6 @@ uniform int u_condFB; // Condition to update texNum)";
//-----------------------------------------------------------------------------
const string vertOutput_v_P_VS = R"(
-
out vec3 v_P_VS; // Point of illumination in view space (VS))";
const string vertOutput_v_P_WS = R"(
out vec3 v_P_WS; // Point of illumination in world space (WS))";
@@ -146,6 +147,46 @@ const string vertOutput_PS_struct_texNum = R"(
uint texNum; // Num of texture in flipbook)";
const string vertOutput_PS_struct_End = R"(
} vert; )";
+
+const string vertOutput_PS_instanced_texNum = R"(
+out uint texNum; // Num of texture in flipbook)";
+const string vertOutput_PS_instanced_transparency = R"(
+out float transparency; // transparency of a particle )";
+
+const string fragInput_PS_instanced_transparency = R"(
+in float transparency; // transparency of a particle )";
+const string fragInput_PS_instanced_texNum = R"(
+in uint texNum; // Num of texture in flipbook)";
+
+const string fragMain_PS_v_c = R"(
+ vec4 color = u_color; // Particle color)";
+const string fragMain_PS_v_doColorOverLT = R"(
+ vec4 color = vec4(vert[0].color, 1.0); // Particle color)";
+const string fragMain_PS_v_withoutColor = R"(
+ vec4 color = vec4( 0.0, 0.0, 0.0, 1.0); // Particle color)";
+const string fragMain_PS_instanced_c = R"(
+ vec4 color = u_color; // Particle color
+ color.w *= transparency; // Apply transparency
+ )";
+
+const string vertInput_u_matrix_p = R"(
+uniform mat4 u_pMatrix; // Projection matrix)";
+const string vertInput_u_matrix_vertBillboard = R"(
+uniform mat4 u_vYawPMatrix; // Projection matrix)";
+const string fragInput_PS_u_c = R"(
+uniform vec4 u_color; // Particle color)";
+const string vertInput_PS_u_ScaRa = R"(
+uniform float u_scale; // Particle scale
+uniform float u_radiusW; // Particle width radius)
+uniform float u_radiusH; // Particle height radius)";
+//-----------------------------------------------------------------------------
+
+const string vertOutput_PS_color = R"(
+out vec4 v_particleColor; // Size of a particle )";
+
+const string vertOutput_PS_texCoord = R"(
+out vec2 v_texCoord; // interpolated texture coordinateA)";
+
//-----------------------------------------------------------------------------
const string vertOutput_PS_tf_p = R"(
@@ -167,9 +208,15 @@ out vec3 tf_initialPosition; // To transform feedback)";
//-----------------------------------------------------------------------------
const string vertMain_Begin = R"(
-
void main()
{)";
+
+const string vertMain_instanced_Begin = R"(
+void main()
+{
+ vec3 position = a_positionP;
+)";
+
const string vertMain_v_P_VS = R"(
mat4 mvMatrix = u_vMatrix * u_mMatrix;
v_P_VS = vec3(mvMatrix * a_position); // vertex position in view space)";
@@ -213,8 +260,9 @@ const string vertMain_TBN_Nm = R"(
v_lightDirTS[i] *= TBN;
}
)";
-const string vertMain_PS_v_a = R"(
- float age = u_time - a_startTime; // Get the age of the particle)";
+
+//-----------------------------------------------------------------------------
+// Things that goes directly to geometry shader
const string vertMain_PS_v_t_default = R"(
if(age < 0.0)
vert.transparency = 0.0; // To be discard, because the particle is to be born
@@ -244,10 +292,82 @@ const string vertMain_PS_v_s_curve = R"(
pow(vert.size,2.0) * u_si_bernstein.y +
vert.size * u_si_bernstein.z +
u_si_bernstein.w; // Get transparency by bezier curve)";
+
+const string vertMain_PS_instanced_v_r = R"(
+ float rotation = a_rotation;)";
+
+const string vertMain_PS_instanced_v_s = R"(
+ float size = age / u_tTL;)";
+const string vertMain_PS_instanced_v_s_curve = R"(
+ size = pow(size,3.0) * u_si_bernstein.x +
+ pow(size,2.0) * u_si_bernstein.y +
+ size * u_si_bernstein.z +
+ u_si_bernstein.w; // Get transparency by bezier curve)";
+
+const string vertMain_PS_instanced_v_sS = R"(
+ position = size * position;
+ )";
+
const string vertMain_PS_v_doColorOverLT = R"(
vert.color = colorByAge(age/u_tTL);)";
+const string vertMain_PS_v_color = R"(
+ vert.color = u_color.rgb;)";
+
const string vertMain_PS_v_texNum = R"(
vert.texNum = a_texNum;)";
+
+const string vertMain_PS_v_a = R"(
+ float age = u_time - a_startTime; // Get the age of the particle)";
+
+const string vertMain_PS_v_tC = R"(
+ v_texCoord = 0.5 * (a_positionP.xy + vec2(1.0));)";
+
+const string vertMain_PS_instanced_v_t_default = R"(
+ if(age < 0.0)
+ transparency = 0.0; // To be discard, because the particle is to be born
+ else
+ transparency = 1.0;)";
+const string vertMain_PS_instanced_v_t_begin = R"(
+ if(age < 0.0)
+ transparency = 0.0; // To be discard, because the particle is to be born
+ else
+ {
+ transparency = age / u_tTL; // Get by the ratio age:lifetime)";
+const string vertMain_PS_instanced_v_t_linear = R"(
+ transparency = 1.0 - transparency; // Linear)";
+const string vertMain_PS_instanced_v_t_curve = R"(
+ transparency = pow(transparency,3.0) * u_al_bernstein.x +
+ pow(transparency,2.0) * u_al_bernstein.y +
+ transparency * u_al_bernstein.z +
+ u_al_bernstein.w; // Get transparency by bezier curve)";
+
+
+const string vertMain_PS_instanced_scale = R"(
+ position = vec3(u_radiusW * position.x, u_radiusH * position.y, position.z);
+ position = u_scale * position;
+ )";
+
+const string vertMain_PS_instanced_rotate = R"(
+ mat2 rot = mat2(cos(a_rotation),-sin(a_rotation),
+ sin(a_rotation), cos(a_rotation)); // Matrix of rotation
+ position = vec3(rot * position.xy, position.z);
+ )";
+
+const string vertMain_PS_instanced_EndAll = R"(
+
+ // Modelview matrix multiplication with (particle position + particle generator position)
+ // Calculate position in view space
+ gl_Position = u_pMatrix * (u_vOmvMatrix * vec4(a_position, 1) + vec4(position, 0.0));
+}
+)";
+
+const string vertMain_PS_instanced_EndAll_VertBillboard = R"(
+ gl_Position = vec4(position + a_positionP, 1);
+}
+)";
+
+
+
const string vertMain_PS_EndAll = R"(
// Modelview matrix multiplication with (particle position + particle generator position)
@@ -265,8 +385,7 @@ const string vertMain_EndAll = R"(
// pass the vertex w. the fix-function transform
gl_Position = u_pMatrix * mvMatrix * a_position;
-}
-)";
+})";
//-----------------------------------------------------------------------------
const string vertMain_PS_U_Begin = R"(
@@ -336,6 +455,9 @@ const string vertMain_PS_U_EndAll = R"(
}
}
})";
+
+
+
//-----------------------------------------------------------------------------
const string geomConfig_PS = R"(
layout (points) in; // Primitives that we received from vertex shader
@@ -361,7 +483,6 @@ uniform mat4 u_pMatrix; // Projection matrix)";
const string geomInput_u_matrix_vertBillboard = R"(
uniform mat4 u_vYawPMatrix; // Projection matrix)";
const string geomInput_PS_u_ScaRa = R"(
-
uniform float u_scale; // Particle scale
uniform float u_radiusW; // Particle width radius)
uniform float u_radiusH; // Particle height radius)";
@@ -373,10 +494,12 @@ const string geomInput_PS_u_row = R"(
uniform int u_row; // Number of row of flipbook texture)";
//-----------------------------------------------------------------------------
const string geomOutput_PS_v_pC = R"(
-
out vec4 v_particleColor; // The resulting color per vertex)";
const string geomOutput_PS_v_tC = R"(
out vec2 v_texCoord; // Texture coordinate at vertex)";
+
+const string vertOutput_PS_v_tC = R"(
+out vec2 v_texCoord; // Texture coordinate at vertex)";
//-----------------------------------------------------------------------------
const string geomMain_PS_Begin = R"(
@@ -633,7 +756,6 @@ const string fragInput_PS_u_wireFrame = R"(
uniform bool u_doWireFrame; // Boolean for wireFrame)";
//-----------------------------------------------------------------------------
const string fragMain_PS_TF = R"(
-
out vec4 o_fragColor; // output fragment color
void main()
@@ -643,7 +765,6 @@ void main()
)";
//-----------------------------------------------------------------------------
const string fragMain_PS = R"(
-
void main()
{
// Just set the interpolated color from the vertex shader
@@ -657,21 +778,36 @@ void main()
discard;
)";
-const string fragMain_PS_withoutColor = R"(
+
+const string fragMain_instanced_PS_begin = R"(
void main()
-{
+{
+)";
+
+const string fragMain_PS_withoutColor = R"(
// componentwise multiply w. texture color
if(!u_doWireFrame)
o_fragColor = texture(u_matTextureDiffuse0, v_texCoord);
else
o_fragColor = vec4(0,0,0,1.0);
- o_fragColor.a *= v_particleColor.a;
+ o_fragColor.a *= transparency;
if(o_fragColor.a < 0.001)
discard;
+)";
+
+const string fragMain_instanced_PS_end = R"(
+ // Just set the interpolated color from the vertex shader
+ o_fragColor = color;
+ // componentwise multiply w. texture color
+ if(!u_doWireFrame)
+ o_fragColor *= texture(u_matTextureDiffuse0, v_texCoord);
+ if(o_fragColor.a < 0.001)
+ discard;
)";
+
const string fragMain_PS_endAll = R"(
//Same color for each wireframe
if(u_doWireFrame)
@@ -1444,7 +1580,6 @@ const string fragMainCook_2_LightLoopNmSm = R"(
}
)";
const string fragMainCook_3_FragColor = R"(
-
// ambient lighting (note that the next IBL tutorial will replace
// this ambient lighting with environment lighting).
vec3 ambient = vec3(0.03) * matDiff.rgb * matOccl;
@@ -1459,7 +1594,6 @@ const string fragMainCook_3_FragColor = R"(
o_fragColor.a = matDiff.a;
)";
const string fragMainCook_3_FragColorSky = R"(
-
// Build diffuse reflection from environment light map
vec3 F = fresnelSchlickRoughness(max(dot(N, E), 0.0), F0, matRough);
vec3 kS = F;
@@ -1643,7 +1777,6 @@ void SLGLProgramGenerated::buildProgramNamePS(SLMaterial* mat,
bool rot = mat->ps()->doRotation(); // Rotation
programName += "-B" + std::to_string(billboardType);
if (rot) programName += "-RT";
-
if (AlOvLi) programName += "-AL";
if (AlOvLi && AlOvLiCu) programName += "cu";
if (SiOvLi) programName += "-SL";
@@ -1733,7 +1866,7 @@ void SLGLProgramGenerated::buildProgramCode(SLMaterial* mat,
* @param mat Parent material pointer
* @param isDrawProg Flag if program is for drawing instead of update
*/
-void SLGLProgramGenerated::buildProgramCodePS(SLMaterial* mat, bool isDrawProg)
+void SLGLProgramGenerated::buildProgramCodePS(SLMaterial* mat, bool isDrawProg, bool isRenderInstanced)
{
if (mat->name() == "IBLMat")
{
@@ -1745,7 +1878,12 @@ void SLGLProgramGenerated::buildProgramCodePS(SLMaterial* mat, bool isDrawProg)
_shaders[1]->type() == ST_fragment);
if (isDrawProg)
- buildPerPixParticle(mat);
+ {
+ if (isRenderInstanced)
+ buildPerPixParticleInstanced(mat);
+ else
+ buildPerPixParticle(mat);
+ }
else
buildPerPixParticleUpdate(mat);
}
@@ -1974,6 +2112,117 @@ void SLGLProgramGenerated::buildPerPixBlinn(SLMaterial* mat, SLVLight* lights)
addCodeToShader(_shaders[1], fragCode, _name + ".frag");
}
//-----------------------------------------------------------------------------
+void SLGLProgramGenerated::buildPerPixParticleInstanced(SLMaterial* mat)
+{
+ assert(_shaders.size() > 2 &&
+ _shaders[0]->type() == ST_vertex &&
+ _shaders[1]->type() == ST_fragment);
+
+ // Check what textures the material has
+ bool Dm = mat->hasTextureType(TT_diffuse);
+ GLint billboardType = mat->ps()->billboardType(); // Billboard type (0 -> default; 1 -> vertical billboard, 2 -> horizontal billboard)
+ bool rot = mat->ps()->doRotation(); // Rotation
+ bool AlOvLi = mat->ps()->doAlphaOverLT(); // Alpha over life
+ bool Co = mat->ps()->doColor(); // Color over life
+ bool CoOvLi = mat->ps()->doColorOverLT(); // Color over life
+ bool AlOvLiCu = mat->ps()->doAlphaOverLTCurve(); // Alpha over life curve
+ bool SiOvLi = mat->ps()->doSizeOverLT(); // Size over life
+ bool SiOvLiCu = mat->ps()->doSizeOverLTCurve(); // Size over life curve
+ bool FlBoTex = mat->ps()->doFlipBookTexture(); // Flipbook texture
+
+ //////////////////////////////
+ // Assemble vertex shader code
+ //////////////////////////////
+
+ string vertCode;
+ vertCode += shaderHeader();
+
+ // Vertex shader inputs
+ vertCode += vertInput_PS_a_positionP;
+ vertCode += vertInput_PS_a_p; //position
+ vertCode += vertInput_PS_a_st; // start time
+ if (rot) vertCode += vertInput_PS_a_r; //rotation as float
+ if (FlBoTex) vertCode += vertInput_PS_a_texNum; // per particle texture number
+
+ // Vertex shader uniforms
+ vertCode += vertInput_PS_u_ScaRa;
+ vertCode += vertInput_u_matrix_p;
+ vertCode += vertInput_PS_u_time;
+ vertCode += vertInput_u_matrix_vOmv;
+ if (AlOvLi && AlOvLiCu) vertCode += vertInput_PS_u_al_bernstein_alpha;
+ if (SiOvLi && SiOvLiCu) vertCode += vertInput_PS_u_al_bernstein_size;
+ if (Co && CoOvLi) vertCode += vertInput_PS_u_colorOvLF;
+
+ // Vertex shader outputs
+ if (FlBoTex) vertCode += vertOutput_PS_instanced_texNum;
+ vertCode += vertOutput_PS_instanced_transparency;
+ vertCode += vertOutput_PS_v_tC;
+
+ // Vertex shader functions
+ if (Co && CoOvLi) vertCode += vertFunction_PS_ColorOverLT;
+
+ // Vertex shader main loop
+ vertCode += vertMain_instanced_Begin;
+ vertCode += vertMain_PS_v_a;
+ vertCode += vertMain_PS_v_tC;
+ if (AlOvLi)
+ vertCode += vertMain_PS_instanced_v_t_begin;
+ else
+ vertCode += vertMain_PS_instanced_v_t_default;
+ if (AlOvLi) vertCode += AlOvLiCu ? vertMain_PS_instanced_v_t_curve : vertMain_PS_instanced_v_t_linear;
+ if (AlOvLi) vertCode += vertMain_PS_v_t_end;
+ //if (rot) vertCode += vertMain_PS_v_r;
+ vertCode += vertMain_PS_instanced_scale;
+ if (SiOvLi) vertCode += vertMain_PS_instanced_v_s;
+ if (SiOvLi && SiOvLiCu) vertCode += vertMain_PS_instanced_v_s_curve;
+ if (SiOvLi) vertCode += vertMain_PS_instanced_v_sS;
+ if (rot) vertCode += vertMain_PS_instanced_rotate;
+ if (Co && CoOvLi) vertCode += vertMain_PS_v_doColorOverLT;
+ if (FlBoTex) vertCode += vertMain_PS_v_texNum;
+ if (billboardType == BT_Vertical || billboardType == BT_Horizontal)
+ vertCode += vertMain_PS_EndAll_VertBillboard;
+ else
+ vertCode += vertMain_PS_instanced_EndAll;
+
+ addCodeToShader(_shaders[0], vertCode, _name + ".vert");
+
+ ////////////////////////////////
+ // Assemble fragment shader code
+ ////////////////////////////////
+
+ string fragCode;
+ fragCode += shaderHeader();
+
+ if (Co && !CoOvLi) vertCode += fragInput_PS_u_c;
+ // Fragment shader inputs
+ if (FlBoTex) fragCode += fragInput_PS_instanced_texNum;
+ fragCode += fragInput_PS_v_tC;
+ if (Co && !CoOvLi) fragCode += fragInput_PS_u_c;
+ fragCode += fragInput_PS_instanced_transparency;
+
+ // Fragment shader uniforms
+ if (Dm) fragCode += fragInput_u_matTexDm;
+ fragCode += fragInput_PS_u_overG;
+ fragCode += fragInput_PS_u_wireFrame;
+
+ // Fragment shader outputs
+ fragCode += fragOutputs_o_fragColor;
+
+ // Fragment shader main loop
+ fragCode += fragMain_instanced_PS_begin;
+ if (Co || CoOvLi)
+ {
+ fragCode += fragMain_PS_instanced_c;
+ fragCode += fragMain_instanced_PS_end;
+ }
+ else
+ fragCode += fragMain_PS_withoutColor;
+
+ fragCode += fragMain_PS_endAll;
+
+ addCodeToShader(_shaders[1], fragCode, _name + ".frag");
+}
+//-----------------------------------------------------------------------------
void SLGLProgramGenerated::buildPerPixParticle(SLMaterial* mat)
{
assert(_shaders.size() > 2 &&
diff --git a/modules/sl/source/gl/SLGLProgramGenerated.h b/modules/sl/source/gl/SLGLProgramGenerated.h
index 93ebc1da..22865155 100644
--- a/modules/sl/source/gl/SLGLProgramGenerated.h
+++ b/modules/sl/source/gl/SLGLProgramGenerated.h
@@ -81,7 +81,15 @@ class SLGLProgramGenerated : public SLGLProgram
geomShader,
programName)
{
- buildProgramCodePS(mat, isDrawProg);
+
+ if (geomShader != "")
+ {
+ buildProgramCodePS(mat, isDrawProg, false);
+ }
+ else
+ {
+ buildProgramCodePS(mat, isDrawProg, true);
+ }
}
static bool lightsDoShadowMapping(SLVLight* lights);
@@ -92,7 +100,7 @@ class SLGLProgramGenerated : public SLGLProgram
string& programName,
bool isDrawProg);
- void buildProgramCodePS(SLMaterial* mat, bool isDrawProg);
+ void buildProgramCodePS(SLMaterial* mat, bool isDrawProg, bool isRenderInstanced = false);
void buildProgramCode(SLMaterial* mat,
SLVLight* lights);
void beginShader(SLCamera* cam,
@@ -104,6 +112,7 @@ class SLGLProgramGenerated : public SLGLProgram
void buildPerPixCook(SLMaterial* mat, SLVLight* lights);
void buildPerPixBlinn(SLMaterial* mat, SLVLight* lights);
void buildPerPixParticle(SLMaterial* mat);
+ void buildPerPixParticleInstanced(SLMaterial* mat);
void buildPerPixParticleUpdate(SLMaterial* mat);
// Video background shader builder functions
diff --git a/modules/sl/source/mesh/SLParticleSystem.cpp b/modules/sl/source/mesh/SLParticleSystem.cpp
index c69dcefe..c5751e4c 100644
--- a/modules/sl/source/mesh/SLParticleSystem.cpp
+++ b/modules/sl/source/mesh/SLParticleSystem.cpp
@@ -33,7 +33,13 @@ SLParticleSystem::SLParticleSystem(SLAssetManager* assetMgr,
{
assert(!name.empty());
- _primitive = PT_points;
+ // To be added to constructor
+ _renderInstanced = true;
+
+ if (_renderInstanced)
+ _primitive = PT_triangles;
+ else
+ _primitive = PT_points;
if (amount > UINT_MAX) // Need to change for number of floats
SL_EXIT_MSG("SLParticleSystem supports max. 2^32 vertices.");
@@ -43,8 +49,6 @@ SLParticleSystem::SLParticleSystem(SLAssetManager* assetMgr,
_velocityRndMin = velocityRandomStart;
_velocityRndMax = velocityRandomEnd;
- P.resize(1); // To trick parent class
-
_textureFirst = texC;
_textureFlipbook = texFlipbook;
@@ -447,6 +451,39 @@ void SLParticleSystem::generate()
_vao2.setAttrib(AT_initialPosition, AT_initialPosition, &tempInitP);
_vao2.generateTF((SLuint)tempP.size());
+ if (_renderInstanced)
+ {
+ /* Generate for billboard (for drawing without geometry shader)*/
+ P.push_back(SLVec3f(-1, -1, 0));
+ P.push_back(SLVec3f(1, -1, 0));
+ P.push_back(SLVec3f(1, 1, 0));
+ P.push_back(SLVec3f(-1, 1, 0));
+
+ I32.push_back(0);
+ I32.push_back(1);
+ I32.push_back(2);
+ I32.push_back(2);
+ I32.push_back(3);
+ I32.push_back(0);
+
+ /* Generate vao for rendering with draw instanced */
+ _renderVao1.setAttrib(AT_custom0, AT_custom0, &P);
+ _renderVao1.setIndices(&I32);
+ _renderVao1.setExternalVBO(_vao1.vbo(), 2);
+
+ _renderVao2.setAttrib(AT_custom0, AT_custom0, &P);
+ _renderVao2.setIndices(&I32);
+ _renderVao2.setExternalVBO(_vao2.vbo(), 2);
+
+ _renderVao1.generate((SLuint)P.size());
+ _renderVao2.generate((SLuint)P.size());
+ }
+ else
+ {
+ P.push_back(SLVec3f(1, 1, 0));
+ I32.push_back(0);
+ }
+
_isGenerated = true;
}
//-----------------------------------------------------------------------------
@@ -542,7 +579,7 @@ void SLParticleSystem::pauseOrResume()
* user. After I update the particle in the update pass, then and finally I
* draw them.
*/
-void SLParticleSystem::draw(SLSceneView* sv, SLNode* node)
+void SLParticleSystem::draw(SLSceneView* sv, SLNode* node, SLuint instances)
{
/////////////////////////////////////
// Init particles vector and init VAO
@@ -556,7 +593,7 @@ void SLParticleSystem::draw(SLSceneView* sv, SLNode* node)
////////////////////
if (!_mat->program() || !_mat->programTF())
- _mat->generateProgramPS();
+ _mat->generateProgramPS(_renderInstanced);
////////////////////////////////////////////////
// Calculate time and paused and frustum culling
@@ -680,14 +717,20 @@ void SLParticleSystem::draw(SLSceneView* sv, SLNode* node)
_vao1.beginTF(_vao2.tfoID());
_vao1.drawArrayAs(PT_points);
_vao1.endTF();
- _vao = _vao2;
+ if (_renderInstanced)
+ _vao = _renderVao2;
+ else
+ _vao = _vao2;
}
else
{
_vao2.beginTF(_vao1.tfoID());
_vao2.drawArrayAs(PT_points);
_vao2.endTF();
- _vao = _vao1;
+ if (_renderInstanced)
+ _vao = _renderVao2;
+ else
+ _vao = _vao1;
}
_updateTime.set(GlobalTimer::timeMS() - _startUpdateTimeMS);
}
@@ -709,7 +752,6 @@ void SLParticleSystem::draw(SLSceneView* sv, SLNode* node)
// World space
if (_doWorldSpace)
{
-
if (_billboardType == BT_Vertical)
{
SLMat4f vMat = stateGL->viewMatrix; // Just view matrix because world space is enabled
@@ -728,7 +770,22 @@ void SLParticleSystem::draw(SLSceneView* sv, SLNode* node)
}
else
{
- spD->uniformMatrix4fv("u_vOmvMatrix", 1, (SLfloat*)&stateGL->viewMatrix);
+
+ SLMat4f vMat = stateGL->viewMatrix; // Just view matrix because world space is enabled
+ std::cout << "vMat" << std::endl;
+ vMat.m(0, 1.0f);
+ vMat.m(1, 0.0f);
+ vMat.m(2, 0.0f);
+
+ vMat.m(3, 1.0f);
+ vMat.m(4, 0.0f);
+ vMat.m(5, 0.0f);
+
+ vMat.m(6, 0.0f);
+ vMat.m(7, 0.0f);
+ vMat.m(8, 1.0f);
+ spD->uniformMatrix4fv("u_vOmvMatrix", 1, (SLfloat*)&vMat);
+ //spD->uniformMatrix4fv("u_vOmvMatrix", 1, (SLfloat*)&stateGL->viewMatrix);
}
}
else
@@ -822,7 +879,10 @@ void SLParticleSystem::draw(SLSceneView* sv, SLNode* node)
stateGL->blendFunc(GL_SRC_ALPHA, GL_ONE);
///////////////////////
- SLMesh::draw(sv, node);
+ if (_renderInstanced)
+ SLMesh::draw(sv, node, _amount*2);
+ else
+ SLMesh::draw(sv, node);
///////////////////////
if (_doColor && _doBlendBrightness)
diff --git a/modules/sl/source/mesh/SLParticleSystem.h b/modules/sl/source/mesh/SLParticleSystem.h
index fd1b5b9d..c3c1ec62 100644
--- a/modules/sl/source/mesh/SLParticleSystem.h
+++ b/modules/sl/source/mesh/SLParticleSystem.h
@@ -42,7 +42,7 @@ class SLParticleSystem : public SLMesh
const SLstring& name = "Particle system",
SLGLTexture* texFlipbook = nullptr);
- void draw(SLSceneView* sv, SLNode* node);
+ void draw(SLSceneView* sv, SLNode* node, SLuint instances = 1);
void deleteData();
void deleteDataGpu();
void buildAABB(SLAABBox& aabb, const SLMat4f& wmNode);
@@ -350,6 +350,9 @@ class SLParticleSystem : public SLMesh
SLGLVertexArray _vao1; //!< First OpenGL Vertex Array Object for swapping between updating/drawing
SLGLVertexArray _vao2; //!< Second OpenGL Vertex Array Object for swapping between updating/drawing
+ SLGLVertexArray _renderVao1; //!< First OpenGL Vertex Array Object for swapping between updating/drawing
+ SLGLVertexArray _renderVao2; //!< Second OpenGL Vertex Array Object for swapping between updating/drawing
+
// Boolean for generation/resume
SLbool _isVisibleInFrustum = true; //!< Boolean to set time since node not visible
SLbool _isPaused = false; //!< Boolean to stop updating
@@ -377,6 +380,7 @@ class SLParticleSystem : public SLMesh
SLbool _doSizeOverLT = true; //!< Boolean for size over life time
SLbool _doSizeOverLTCurve = false; //!< Boolean for size over life time curve
SLbool _doFlipBookTexture = false; //!< Boolean for flipbook texture
+ SLbool _renderInstanced = false; //!< Boolean for instanced rendering
};
//-----------------------------------------------------------------------------
#endif
From 68a6d9ffe70b54245c8a59df33cb3a06e6f732db Mon Sep 17 00:00:00 2001
From: luc
Date: Fri, 3 Nov 2023 18:32:16 +0100
Subject: [PATCH 19/29] Add option to swith particle rendering method in the
gui and fix some particles instanced rendering shaders
---
apps/app_demo_slproject/source/AppDemoGui.cpp | 8 ++
modules/sl/source/SLAssetManager.cpp | 16 +++
modules/sl/source/SLAssetManager.h | 3 +
modules/sl/source/SLMaterial.cpp | 18 ++-
modules/sl/source/SLMaterial.h | 3 +
modules/sl/source/gl/SLGLProgramGenerated.cpp | 133 +++++++++++++-----
modules/sl/source/gl/SLGLProgramGenerated.h | 3 +-
modules/sl/source/mesh/SLParticleSystem.cpp | 41 +++---
modules/sl/source/mesh/SLParticleSystem.h | 8 +-
9 files changed, 180 insertions(+), 53 deletions(-)
diff --git a/apps/app_demo_slproject/source/AppDemoGui.cpp b/apps/app_demo_slproject/source/AppDemoGui.cpp
index e4d20e0d..d943894d 100644
--- a/apps/app_demo_slproject/source/AppDemoGui.cpp
+++ b/apps/app_demo_slproject/source/AppDemoGui.cpp
@@ -2393,6 +2393,7 @@ void AppDemoGui::buildMenuBar(SLScene* s, SLSceneView* sv)
if (ImGui::MenuItem("Skeleton", "K", sv->drawBits()->get(SL_DB_SKELETON)))
sv->drawBits()->toggle(SL_DB_SKELETON);
+
if (ImGui::MenuItem("All off"))
sv->drawBits()->allOff();
@@ -3770,6 +3771,13 @@ void AppDemoGui::buildProperties(SLScene* s, SLSceneView* sv)
ps->isGenerated(false);
}
+ bool instanced = ps->renderInstanced();
+ if (ImGui::Checkbox("Instanced draw", &instanced))
+ {
+ ps->drawInstanced(instanced);
+ ps->isGenerated(false);
+ }
+
// TTL (Time to live)
if (ImGui::CollapsingHeader("Time to live"))
{
diff --git a/modules/sl/source/SLAssetManager.cpp b/modules/sl/source/SLAssetManager.cpp
index 020a6c99..1fedf31f 100644
--- a/modules/sl/source/SLAssetManager.cpp
+++ b/modules/sl/source/SLAssetManager.cpp
@@ -95,6 +95,21 @@ bool SLAssetManager::removeMesh(SLMesh* mesh)
}
return false;
}
+
+//! Removes the specified program from the meshes resource vector.
+bool SLAssetManager::removeProgram(SLGLProgram* program)
+{
+ assert(program);
+ for (SLulong i = 0; i < _programs.size(); ++i)
+ {
+ if (_programs[i] == program)
+ {
+ _programs.erase(_programs.begin() + i);
+ return true;
+ }
+ }
+ return false;
+}
//-----------------------------------------------------------------------------
//! Returns the pointer to shader program if found by name
SLGLProgram* SLAssetManager::getProgramByName(const string& programName)
@@ -104,6 +119,7 @@ SLGLProgram* SLAssetManager::getProgramByName(const string& programName)
return sp;
return nullptr;
}
+
//-----------------------------------------------------------------------------
//! merge other asset manager into this
void SLAssetManager::merge(SLAssetManager& other)
diff --git a/modules/sl/source/SLAssetManager.h b/modules/sl/source/SLAssetManager.h
index c261a6b2..773cde87 100644
--- a/modules/sl/source/SLAssetManager.h
+++ b/modules/sl/source/SLAssetManager.h
@@ -52,6 +52,9 @@ class SLAssetManager
//! Removes the specified mesh from the meshes resource vector.
bool removeMesh(SLMesh* mesh);
+ //! Removes the specified mesh from the meshes resource vector.
+ bool removeProgram(SLGLProgram* program);
+
//! Returns the pointer to shader program if found by name
SLGLProgram* getProgramByName(const string& programName);
diff --git a/modules/sl/source/SLMaterial.cpp b/modules/sl/source/SLMaterial.cpp
index d26365a3..3f8c0bab 100644
--- a/modules/sl/source/SLMaterial.cpp
+++ b/modules/sl/source/SLMaterial.cpp
@@ -372,6 +372,20 @@ SLMaterial::~SLMaterial()
_errorTexture = nullptr;
}
}
+
+
+void SLMaterial::deleteDataGpu()
+{
+ if (_program)
+ {
+ _assetManager->removeProgram(_program);
+ _program->deleteDataGpu();
+ delete _program;
+ _program = nullptr;
+ }
+}
+
+
//-----------------------------------------------------------------------------
/*!
If this material has not yet a shader program assigned (SLMaterial::_program)
@@ -389,7 +403,7 @@ void SLMaterial::generateProgramPS(bool renderInstanced)
// Check first the asset manager if the requested program type already exists
string programNameDraw;
- SLGLProgramGenerated::buildProgramNamePS(this, programNameDraw, true);
+ SLGLProgramGenerated::buildProgramNamePS(this, programNameDraw, true, renderInstanced);
_program = _assetManager->getProgramByName(programNameDraw);
// If the program was not found by name generate a new one
@@ -415,7 +429,7 @@ void SLMaterial::generateProgramPS(bool renderInstanced)
// Check first the asset manager if the requested programTF type already exists
string programNameUpdate;
- SLGLProgramGenerated::buildProgramNamePS(this, programNameUpdate, false);
+ SLGLProgramGenerated::buildProgramNamePS(this, programNameUpdate, false, renderInstanced);
_programTF = _assetManager->getProgramByName(programNameUpdate);
if (!_programTF)
{
diff --git a/modules/sl/source/SLMaterial.h b/modules/sl/source/SLMaterial.h
index 983f2ff5..9ae29fcb 100644
--- a/modules/sl/source/SLMaterial.h
+++ b/modules/sl/source/SLMaterial.h
@@ -114,6 +114,9 @@ class SLMaterial : public SLObject
SLSkybox* skybox = nullptr);
SLint passToUniforms(SLGLProgram* program, SLint nextTexUnit);
+
+ void deleteDataGpu();
+
//! Returns true if there is any transparency in diffuse alpha or textures
SLbool hasAlpha()
{
diff --git a/modules/sl/source/gl/SLGLProgramGenerated.cpp b/modules/sl/source/gl/SLGLProgramGenerated.cpp
index 9aee3ca3..81cec78c 100644
--- a/modules/sl/source/gl/SLGLProgramGenerated.cpp
+++ b/modules/sl/source/gl/SLGLProgramGenerated.cpp
@@ -74,16 +74,19 @@ const string vertConstant_PS_pi = R"(
)";
//-----------------------------------------------------------------------------
const string vertInput_PS_u_time = R"(
-
uniform float u_time; // Simulation time
uniform float u_difTime; // Simulation delta time after frustum culling
uniform float u_tTL; // Time to live of a particle)";
+const string fragInput_PS_u_tTL = R"(
+uniform float u_tTL; // Time to live of a particle)";
const string vertInput_PS_u_al_bernstein_alpha = R"(
uniform vec4 u_al_bernstein; // Bernstein polynomial for alpha over time)";
const string vertInput_PS_u_al_bernstein_size = R"(
uniform vec4 u_si_bernstein; // Bernstein polynomial for size over time)";
const string vertInput_PS_u_colorOvLF = R"(
uniform float u_colorArr[256 * 3]; // Array of color value (for color over life))";
+const string fragInput_PS_u_colorOvLF = R"(
+uniform float u_colorArr[256 * 3]; // Array of color value (for color over life))";
const string vertInput_PS_u_deltaTime = R"(
uniform float u_deltaTime; // Elapsed time between frames)";
const string vertInput_PS_u_pgPos = R"(
@@ -122,7 +125,14 @@ out vec3 v_lightDirTS[NUM_LIGHTS]; // Vector to the light 0 in tangent spac
out vec3 v_spotDirTS[NUM_LIGHTS]; // Spot direction in tangent space)";
//-----------------------------------------------------------------------------
const string vertFunction_PS_ColorOverLT = R"(
+vec3 colorByAge(float age)
+{
+ int cachePos = int(clamp(age, 0.0, 1.0) * 255.0) * 3;
+ vec3 color = vec3(u_colorArr[cachePos], u_colorArr[cachePos + 1], u_colorArr[cachePos + 2]);
+ return color;
+})";
+const string fragFunction_PS_ColorOverLT = R"(
vec3 colorByAge(float age)
{
int cachePos = int(clamp(age, 0.0, 1.0) * 255.0) * 3;
@@ -162,13 +172,14 @@ const string fragMain_PS_v_c = R"(
vec4 color = u_color; // Particle color)";
const string fragMain_PS_v_doColorOverLT = R"(
vec4 color = vec4(vert[0].color, 1.0); // Particle color)";
+const string fragMain_PS_instanced_v_doColorOverLT = R"(
+ vec4 color = vec4(colorByAge(v_age/u_tTL), 1.0); // Particle color)";
const string fragMain_PS_v_withoutColor = R"(
vec4 color = vec4( 0.0, 0.0, 0.0, 1.0); // Particle color)";
const string fragMain_PS_instanced_c = R"(
- vec4 color = u_color; // Particle color
- color.w *= transparency; // Apply transparency
- )";
-
+ vec4 color = u_color; // Particle color)";
+const string fragMain_PS_instanced_transparency = R"(
+ color.w *= transparency; // Apply transparency)";
const string vertInput_u_matrix_p = R"(
uniform mat4 u_pMatrix; // Projection matrix)";
const string vertInput_u_matrix_vertBillboard = R"(
@@ -231,7 +242,6 @@ const string vertMain_v_R_OS = R"(
vec3 N = normalize(v_N_VS);
v_R_OS = invMvMatrix * reflect(I, N); // R = I-2.0*dot(N,I)*N;)";
const string vertMain_v_uv0 = R"(
-
v_uv0 = a_uv0; // pass diffuse color tex.coord. 1 for interpolation)";
const string vertMain_v_uv1 = R"(
v_uv1 = a_uv1; // pass diffuse color tex.coord. 1 for interpolation)";
@@ -310,18 +320,38 @@ const string vertMain_PS_instanced_v_sS = R"(
const string vertMain_PS_v_doColorOverLT = R"(
vert.color = colorByAge(age/u_tTL);)";
+
+const string vertOutput_PS_age = R"(
+ out float v_age; // Age of a particle)";
+
+const string fragInput_PS_age = R"(
+ in float v_age; // Age of a particle)";
+
const string vertMain_PS_v_color = R"(
vert.color = u_color.rgb;)";
const string vertMain_PS_v_texNum = R"(
vert.texNum = a_texNum;)";
+const string vertMain_PS_instanced_v_texNum = R"(
+ texNum = a_texNum;)";
+
const string vertMain_PS_v_a = R"(
float age = u_time - a_startTime; // Get the age of the particle)";
const string vertMain_PS_v_tC = R"(
v_texCoord = 0.5 * (a_positionP.xy + vec2(1.0));)";
+const string vertMain_PS_v_tC_flipbook = R"(
+ uint actCI = uint(mod(float(a_texNum), float(u_col)));
+ uint actRI = (a_texNum - actCI) / u_col;
+ float actC = float(actCI);
+ float actR = float(actRI);
+
+ vec2 p = 0.5 * (a_positionP.xy + vec2(1.0));
+ v_texCoord = vec2((actC + p.x)/float(u_col), 1.0 - (actR - p.y)/float(u_row));
+)";
+
const string vertMain_PS_instanced_v_t_default = R"(
if(age < 0.0)
transparency = 0.0; // To be discard, because the particle is to be born
@@ -341,7 +371,6 @@ const string vertMain_PS_instanced_v_t_curve = R"(
transparency * u_al_bernstein.z +
u_al_bernstein.w; // Get transparency by bezier curve)";
-
const string vertMain_PS_instanced_scale = R"(
position = vec3(u_radiusW * position.x, u_radiusH * position.y, position.z);
position = u_scale * position;
@@ -362,12 +391,12 @@ const string vertMain_PS_instanced_EndAll = R"(
)";
const string vertMain_PS_instanced_EndAll_VertBillboard = R"(
- gl_Position = vec4(position + a_positionP, 1);
+ //gl_Position = vec4(a_position + a_positionP, 1);
+ gl_Position = u_pMatrix * u_vYawPMatrix * vec4(a_position + position, 1.0);
}
)";
-
const string vertMain_PS_EndAll = R"(
// Modelview matrix multiplication with (particle position + particle generator position)
@@ -377,7 +406,7 @@ const string vertMain_PS_EndAll = R"(
)";
const string vertMain_PS_EndAll_VertBillboard = R"(
- gl_Position = vec4(a_position, 1);
+ gl_Position = vec4(a_position, 1);
}
)";
@@ -765,8 +794,6 @@ void main()
)";
//-----------------------------------------------------------------------------
const string fragMain_PS = R"(
-void main()
-{
// Just set the interpolated color from the vertex shader
o_fragColor = v_particleColor;
@@ -776,10 +803,9 @@ void main()
if(o_fragColor.a < 0.001)
discard;
-
)";
-const string fragMain_instanced_PS_begin = R"(
+const string fragMain_PS_begin = R"(
void main()
{
)";
@@ -791,7 +817,20 @@ const string fragMain_PS_withoutColor = R"(
else
o_fragColor = vec4(0,0,0,1.0);
- o_fragColor.a *= transparency;
+ o_fragColor.a *= v_particleColor.a;
+
+ if(o_fragColor.a < 0.001)
+ discard;
+)";
+
+const string fragMain_PS_instanced_withoutColor = R"(
+ // componentwise multiply w. texture color
+ if(!u_doWireFrame)
+ o_fragColor = texture(u_matTextureDiffuse0, v_texCoord);
+ else
+ o_fragColor = vec4(0,0,0,1.0);
+
+ o_fragColor.a *= transparency;
if(o_fragColor.a < 0.001)
discard;
@@ -1750,7 +1789,8 @@ void SLGLProgramGenerated::buildProgramName(SLMaterial* mat,
*/
void SLGLProgramGenerated::buildProgramNamePS(SLMaterial* mat,
string& programName,
- bool isDrawProg)
+ bool isDrawProg,
+ bool instancedRendering)
{
assert(mat && "No material pointer passed!");
programName = "gen";
@@ -1764,6 +1804,10 @@ void SLGLProgramGenerated::buildProgramNamePS(SLMaterial* mat,
if (isDrawProg) // Drawing program
{
programName += "-Draw";
+
+ if (instancedRendering)
+ programName += "-Inst";
+
programName += mat->texturesString();
GLint billboardType = mat->ps()->billboardType(); // Billboard type (0 -> default; 1 -> vertical billboard, 2 -> horizontal billboard)
bool AlOvLi = mat->ps()->doAlphaOverLT(); // Alpha over life
@@ -2114,7 +2158,7 @@ void SLGLProgramGenerated::buildPerPixBlinn(SLMaterial* mat, SLVLight* lights)
//-----------------------------------------------------------------------------
void SLGLProgramGenerated::buildPerPixParticleInstanced(SLMaterial* mat)
{
- assert(_shaders.size() > 2 &&
+ assert(_shaders.size() == 2 &&
_shaders[0]->type() == ST_vertex &&
_shaders[1]->type() == ST_fragment);
@@ -2142,29 +2186,41 @@ void SLGLProgramGenerated::buildPerPixParticleInstanced(SLMaterial* mat)
vertCode += vertInput_PS_a_p; //position
vertCode += vertInput_PS_a_st; // start time
if (rot) vertCode += vertInput_PS_a_r; //rotation as float
- if (FlBoTex) vertCode += vertInput_PS_a_texNum; // per particle texture number
+ if (FlBoTex)
+ {
+ vertCode += vertInput_PS_u_col;
+ vertCode += vertInput_PS_u_row;
+ vertCode += vertInput_PS_a_texNum; // per particle texture number
+ }
// Vertex shader uniforms
vertCode += vertInput_PS_u_ScaRa;
vertCode += vertInput_u_matrix_p;
vertCode += vertInput_PS_u_time;
+
+ if (billboardType == BT_Vertical)
+ vertCode += vertInput_u_matrix_vertBillboard;
+
vertCode += vertInput_u_matrix_vOmv;
+
if (AlOvLi && AlOvLiCu) vertCode += vertInput_PS_u_al_bernstein_alpha;
if (SiOvLi && SiOvLiCu) vertCode += vertInput_PS_u_al_bernstein_size;
- if (Co && CoOvLi) vertCode += vertInput_PS_u_colorOvLF;
// Vertex shader outputs
- if (FlBoTex) vertCode += vertOutput_PS_instanced_texNum;
vertCode += vertOutput_PS_instanced_transparency;
vertCode += vertOutput_PS_v_tC;
- // Vertex shader functions
- if (Co && CoOvLi) vertCode += vertFunction_PS_ColorOverLT;
+ if (CoOvLi) vertCode += vertOutput_PS_age;
+ // Vertex shader functions
// Vertex shader main loop
vertCode += vertMain_instanced_Begin;
vertCode += vertMain_PS_v_a;
- vertCode += vertMain_PS_v_tC;
+ if (FlBoTex)
+ vertCode += vertMain_PS_v_tC_flipbook;
+ else
+ vertCode += vertMain_PS_v_tC;
+
if (AlOvLi)
vertCode += vertMain_PS_instanced_v_t_begin;
else
@@ -2177,10 +2233,9 @@ void SLGLProgramGenerated::buildPerPixParticleInstanced(SLMaterial* mat)
if (SiOvLi && SiOvLiCu) vertCode += vertMain_PS_instanced_v_s_curve;
if (SiOvLi) vertCode += vertMain_PS_instanced_v_sS;
if (rot) vertCode += vertMain_PS_instanced_rotate;
- if (Co && CoOvLi) vertCode += vertMain_PS_v_doColorOverLT;
- if (FlBoTex) vertCode += vertMain_PS_v_texNum;
+ //if (Co && CoOvLi) vertCode += vertMain_PS_v_doColorOverLT;
if (billboardType == BT_Vertical || billboardType == BT_Horizontal)
- vertCode += vertMain_PS_EndAll_VertBillboard;
+ vertCode += vertMain_PS_instanced_EndAll_VertBillboard;
else
vertCode += vertMain_PS_instanced_EndAll;
@@ -2193,11 +2248,15 @@ void SLGLProgramGenerated::buildPerPixParticleInstanced(SLMaterial* mat)
string fragCode;
fragCode += shaderHeader();
- if (Co && !CoOvLi) vertCode += fragInput_PS_u_c;
// Fragment shader inputs
if (FlBoTex) fragCode += fragInput_PS_instanced_texNum;
fragCode += fragInput_PS_v_tC;
if (Co && !CoOvLi) fragCode += fragInput_PS_u_c;
+ if (CoOvLi)
+ { fragCode += fragInput_PS_u_tTL;
+ fragCode += fragInput_PS_age;
+ fragCode += fragInput_PS_u_colorOvLF;
+ }
fragCode += fragInput_PS_instanced_transparency;
// Fragment shader uniforms
@@ -2208,15 +2267,23 @@ void SLGLProgramGenerated::buildPerPixParticleInstanced(SLMaterial* mat)
// Fragment shader outputs
fragCode += fragOutputs_o_fragColor;
+ if (CoOvLi) fragCode += fragFunction_PS_ColorOverLT;
+
// Fragment shader main loop
- fragCode += fragMain_instanced_PS_begin;
+ fragCode += fragMain_PS_begin;
+
+
+ if (Co && !CoOvLi) fragCode += fragMain_PS_instanced_c;
+
+ if (CoOvLi) fragCode += fragMain_PS_instanced_v_doColorOverLT;
+
if (Co || CoOvLi)
{
- fragCode += fragMain_PS_instanced_c;
+ fragCode += fragMain_PS_instanced_transparency;
fragCode += fragMain_instanced_PS_end;
}
else
- fragCode += fragMain_PS_withoutColor;
+ fragCode += fragMain_PS_instanced_withoutColor;
fragCode += fragMain_PS_endAll;
@@ -2281,6 +2348,7 @@ void SLGLProgramGenerated::buildPerPixParticle(SLMaterial* mat)
vertCode += vertMain_PS_v_t_begin;
else
vertCode += vertMain_PS_v_t_default;
+
if (AlOvLi) vertCode += AlOvLiCu ? vertMain_PS_v_t_curve : vertMain_PS_v_t_linear;
if (AlOvLi) vertCode += vertMain_PS_v_t_end;
if (rot) vertCode += vertMain_PS_v_r;
@@ -2292,7 +2360,7 @@ void SLGLProgramGenerated::buildPerPixParticle(SLMaterial* mat)
vertCode += vertMain_PS_EndAll_VertBillboard;
else
vertCode += vertMain_PS_EndAll;
-
+
addCodeToShader(_shaders[0], vertCode, _name + ".vert");
////////////////////////////////
@@ -2369,9 +2437,10 @@ void SLGLProgramGenerated::buildPerPixParticle(SLMaterial* mat)
fragCode += fragOutputs_o_fragColor;
// Fragment shader main loop
+ fragCode += fragMain_PS_begin;
fragCode += Co ? fragMain_PS : fragMain_PS_withoutColor;
fragCode += fragMain_PS_endAll;
-
+
addCodeToShader(_shaders[1], fragCode, _name + ".frag");
}
//-----------------------------------------------------------------------------
diff --git a/modules/sl/source/gl/SLGLProgramGenerated.h b/modules/sl/source/gl/SLGLProgramGenerated.h
index 22865155..b410bbc8 100644
--- a/modules/sl/source/gl/SLGLProgramGenerated.h
+++ b/modules/sl/source/gl/SLGLProgramGenerated.h
@@ -98,7 +98,8 @@ class SLGLProgramGenerated : public SLGLProgram
string& programName);
static void buildProgramNamePS(SLMaterial* mat,
string& programName,
- bool isDrawProg);
+ bool isDrawProg,
+ bool instancedRendering);
void buildProgramCodePS(SLMaterial* mat, bool isDrawProg, bool isRenderInstanced = false);
void buildProgramCode(SLMaterial* mat,
diff --git a/modules/sl/source/mesh/SLParticleSystem.cpp b/modules/sl/source/mesh/SLParticleSystem.cpp
index c5751e4c..52c9bb13 100644
--- a/modules/sl/source/mesh/SLParticleSystem.cpp
+++ b/modules/sl/source/mesh/SLParticleSystem.cpp
@@ -29,17 +29,17 @@ SLParticleSystem::SLParticleSystem(SLAssetManager* assetMgr,
const SLfloat& timeToLive,
SLGLTexture* texC,
const SLstring& name,
- SLGLTexture* texFlipbook) : SLMesh(assetMgr, name)
+ SLGLTexture* texFlipbook,
+ const bool renderInstanced) : SLMesh(assetMgr, name)
{
assert(!name.empty());
// To be added to constructor
- _renderInstanced = true;
+ _renderInstanced = renderInstanced;
+ _primitive = PT_points;
- if (_renderInstanced)
- _primitive = PT_triangles;
- else
- _primitive = PT_points;
+ P.push_back(SLVec3f(0, 0, 0)); // Trick SL project because it want mesh to have vertex
+ I32.push_back(0);
if (amount > UINT_MAX) // Need to change for number of floats
SL_EXIT_MSG("SLParticleSystem supports max. 2^32 vertices.");
@@ -58,6 +58,7 @@ SLParticleSystem::SLParticleSystem(SLAssetManager* assetMgr,
_updateTime.init(60, 0.0f);
_drawTime.init(60, 0.0f);
+
}
//-----------------------------------------------------------------------------
//! Function which return a position in a sphere
@@ -312,6 +313,13 @@ void SLParticleSystem::generate()
SLVuint tempTexNum;
SLVVec3f tempInitP;
+ if (_renderInstanced)
+ _primitive = PT_triangles;
+ else
+ _primitive = PT_points;
+
+ deleteDataGpu();
+
tempP.resize(_amount);
tempV.resize(_amount);
tempST.resize(_amount);
@@ -453,6 +461,8 @@ void SLParticleSystem::generate()
if (_renderInstanced)
{
+ P.clear();
+ I32.clear();
/* Generate for billboard (for drawing without geometry shader)*/
P.push_back(SLVec3f(-1, -1, 0));
P.push_back(SLVec3f(1, -1, 0));
@@ -478,11 +488,6 @@ void SLParticleSystem::generate()
_renderVao1.generate((SLuint)P.size());
_renderVao2.generate((SLuint)P.size());
}
- else
- {
- P.push_back(SLVec3f(1, 1, 0));
- I32.push_back(0);
- }
_isGenerated = true;
}
@@ -591,9 +596,10 @@ void SLParticleSystem::draw(SLSceneView* sv, SLNode* node, SLuint instances)
////////////////////
// Generate programs
////////////////////
-
if (!_mat->program() || !_mat->programTF())
+ {
_mat->generateProgramPS(_renderInstanced);
+ }
////////////////////////////////////////////////
// Calculate time and paused and frustum culling
@@ -718,7 +724,7 @@ void SLParticleSystem::draw(SLSceneView* sv, SLNode* node, SLuint instances)
_vao1.drawArrayAs(PT_points);
_vao1.endTF();
if (_renderInstanced)
- _vao = _renderVao2;
+ _vao = _renderVao1;
else
_vao = _vao2;
}
@@ -880,7 +886,7 @@ void SLParticleSystem::draw(SLSceneView* sv, SLNode* node, SLuint instances)
///////////////////////
if (_renderInstanced)
- SLMesh::draw(sv, node, _amount*2);
+ SLMesh::draw(sv, node, _amount);
else
SLMesh::draw(sv, node);
///////////////////////
@@ -898,9 +904,7 @@ void SLParticleSystem::draw(SLSceneView* sv, SLNode* node, SLuint instances)
//! deleteData deletes all mesh data and VAOs
void SLParticleSystem::deleteData()
{
- _vao1.deleteGL();
- _vao2.deleteGL();
- SLMesh::deleteData();
+ return;
}
//-----------------------------------------------------------------------------
//! deleteData deletes all mesh data and VAOs
@@ -908,7 +912,10 @@ void SLParticleSystem::deleteDataGpu()
{
_vao1.deleteGL();
_vao2.deleteGL();
+ _renderVao1.deleteGL();
+ _renderVao2.deleteGL();
SLMesh::deleteDataGpu();
+ _mat->deleteDataGpu();
}
//-----------------------------------------------------------------------------
/*! SLParticleSystem::buildAABB builds the passed axis-aligned bounding box in
diff --git a/modules/sl/source/mesh/SLParticleSystem.h b/modules/sl/source/mesh/SLParticleSystem.h
index c3c1ec62..d856e62f 100644
--- a/modules/sl/source/mesh/SLParticleSystem.h
+++ b/modules/sl/source/mesh/SLParticleSystem.h
@@ -40,7 +40,8 @@ class SLParticleSystem : public SLMesh
const SLfloat& timeToLive,
SLGLTexture* texC,
const SLstring& name = "Particle system",
- SLGLTexture* texFlipbook = nullptr);
+ SLGLTexture* texFlipbook = nullptr,
+ const bool renderInstanced = false);
void draw(SLSceneView* sv, SLNode* node, SLuint instances = 1);
void deleteData();
@@ -52,8 +53,12 @@ class SLParticleSystem : public SLMesh
void changeTexture();
void setNotVisibleInFrustum();
void pauseOrResume();
+ void calcNormals() { N.push_back(SLVec3f(0, 1, 0)); };
+
// Getters
+
+ SLbool renderInstanced() { return _renderInstanced; }
SLVec3f acceleration() { return _acceleration; }
SLfloat accelerationConst() { return _accelerationConst; }
SLint amount() { return _amount; }
@@ -117,6 +122,7 @@ class SLParticleSystem : public SLMesh
SLVec3f velocityRndMax() { return _velocityRndMax; }
// Setters
+ void drawInstanced(bool instanced) {_renderInstanced = instanced; }
void amount(SLint i) { _amount = i; }
void accConst(SLfloat f) { _accelerationConst = f; }
void acceleration(SLVec3f v) { _acceleration = v; }
From 7ffe7273215358b4ad9f059a01adb8c5e5da557e Mon Sep 17 00:00:00 2001
From: luc
Date: Fri, 3 Nov 2023 19:38:14 +0100
Subject: [PATCH 20/29] Fix color over life in instanced particle shader
---
modules/sl/source/gl/SLGLProgramGenerated.cpp | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/modules/sl/source/gl/SLGLProgramGenerated.cpp b/modules/sl/source/gl/SLGLProgramGenerated.cpp
index 81cec78c..1cd9a6ac 100644
--- a/modules/sl/source/gl/SLGLProgramGenerated.cpp
+++ b/modules/sl/source/gl/SLGLProgramGenerated.cpp
@@ -322,10 +322,10 @@ const string vertMain_PS_v_doColorOverLT = R"(
vert.color = colorByAge(age/u_tTL);)";
const string vertOutput_PS_age = R"(
- out float v_age; // Age of a particle)";
+out float v_age; // Age of a particle)";
const string fragInput_PS_age = R"(
- in float v_age; // Age of a particle)";
+in float v_age; // Age of a particle)";
const string vertMain_PS_v_color = R"(
vert.color = u_color.rgb;)";
@@ -333,15 +333,15 @@ const string vertMain_PS_v_color = R"(
const string vertMain_PS_v_texNum = R"(
vert.texNum = a_texNum;)";
-const string vertMain_PS_instanced_v_texNum = R"(
- texNum = a_texNum;)";
-
const string vertMain_PS_v_a = R"(
float age = u_time - a_startTime; // Get the age of the particle)";
const string vertMain_PS_v_tC = R"(
v_texCoord = 0.5 * (a_positionP.xy + vec2(1.0));)";
+const string vertMain_PS_v_age = R"(
+ v_age = age;)";
+
const string vertMain_PS_v_tC_flipbook = R"(
uint actCI = uint(mod(float(a_texNum), float(u_col)));
uint actRI = (a_texNum - actCI) / u_col;
@@ -2212,7 +2212,6 @@ void SLGLProgramGenerated::buildPerPixParticleInstanced(SLMaterial* mat)
if (CoOvLi) vertCode += vertOutput_PS_age;
- // Vertex shader functions
// Vertex shader main loop
vertCode += vertMain_instanced_Begin;
vertCode += vertMain_PS_v_a;
@@ -2227,13 +2226,13 @@ void SLGLProgramGenerated::buildPerPixParticleInstanced(SLMaterial* mat)
vertCode += vertMain_PS_instanced_v_t_default;
if (AlOvLi) vertCode += AlOvLiCu ? vertMain_PS_instanced_v_t_curve : vertMain_PS_instanced_v_t_linear;
if (AlOvLi) vertCode += vertMain_PS_v_t_end;
- //if (rot) vertCode += vertMain_PS_v_r;
vertCode += vertMain_PS_instanced_scale;
if (SiOvLi) vertCode += vertMain_PS_instanced_v_s;
if (SiOvLi && SiOvLiCu) vertCode += vertMain_PS_instanced_v_s_curve;
if (SiOvLi) vertCode += vertMain_PS_instanced_v_sS;
if (rot) vertCode += vertMain_PS_instanced_rotate;
- //if (Co && CoOvLi) vertCode += vertMain_PS_v_doColorOverLT;
+ if (CoOvLi) vertCode += vertMain_PS_v_age;
+
if (billboardType == BT_Vertical || billboardType == BT_Horizontal)
vertCode += vertMain_PS_instanced_EndAll_VertBillboard;
else
@@ -2360,7 +2359,7 @@ void SLGLProgramGenerated::buildPerPixParticle(SLMaterial* mat)
vertCode += vertMain_PS_EndAll_VertBillboard;
else
vertCode += vertMain_PS_EndAll;
-
+
addCodeToShader(_shaders[0], vertCode, _name + ".vert");
////////////////////////////////
@@ -2440,7 +2439,7 @@ void SLGLProgramGenerated::buildPerPixParticle(SLMaterial* mat)
fragCode += fragMain_PS_begin;
fragCode += Co ? fragMain_PS : fragMain_PS_withoutColor;
fragCode += fragMain_PS_endAll;
-
+
addCodeToShader(_shaders[1], fragCode, _name + ".frag");
}
//-----------------------------------------------------------------------------
From 77d7c2b077333751ef184a43d51230b096488d1f Mon Sep 17 00:00:00 2001
From: luc
Date: Mon, 6 Nov 2023 11:14:49 +0100
Subject: [PATCH 21/29] comment and small modif
---
modules/sl/source/mesh/SLParticleSystem.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/modules/sl/source/mesh/SLParticleSystem.cpp b/modules/sl/source/mesh/SLParticleSystem.cpp
index 52c9bb13..bef75869 100644
--- a/modules/sl/source/mesh/SLParticleSystem.cpp
+++ b/modules/sl/source/mesh/SLParticleSystem.cpp
@@ -886,7 +886,7 @@ void SLParticleSystem::draw(SLSceneView* sv, SLNode* node, SLuint instances)
///////////////////////
if (_renderInstanced)
- SLMesh::draw(sv, node, _amount);
+ SLMesh::draw(sv, node, 2*_amount); //2 triangles per particle
else
SLMesh::draw(sv, node);
///////////////////////
From e664fef40905a78f37581e24658b95c09181e89d Mon Sep 17 00:00:00 2001
From: luc
Date: Mon, 13 Nov 2023 17:51:13 +0100
Subject: [PATCH 22/29] Rename (renderInstanced, instanced, instancedRendering)
boolean to only renderInstanced for consistancy
---
apps/app_demo_slproject/source/AppDemoGui.cpp | 6 +++---
modules/sl/source/gl/SLGLProgramGenerated.cpp | 8 ++++----
modules/sl/source/gl/SLGLProgramGenerated.h | 4 ++--
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/apps/app_demo_slproject/source/AppDemoGui.cpp b/apps/app_demo_slproject/source/AppDemoGui.cpp
index 120b4584..32abad82 100644
--- a/apps/app_demo_slproject/source/AppDemoGui.cpp
+++ b/apps/app_demo_slproject/source/AppDemoGui.cpp
@@ -3774,10 +3774,10 @@ void AppDemoGui::buildProperties(SLScene* s, SLSceneView* sv)
ps->isGenerated(false);
}
- bool instanced = ps->renderInstanced();
- if (ImGui::Checkbox("Instanced draw", &instanced))
+ bool renderInstanced = ps->renderInstanced();
+ if (ImGui::Checkbox("Instanced draw", &renderInstanced))
{
- ps->drawInstanced(instanced);
+ ps->drawInstanced(renderInstanced);
ps->isGenerated(false);
}
diff --git a/modules/sl/source/gl/SLGLProgramGenerated.cpp b/modules/sl/source/gl/SLGLProgramGenerated.cpp
index 9ca65363..f191d48f 100644
--- a/modules/sl/source/gl/SLGLProgramGenerated.cpp
+++ b/modules/sl/source/gl/SLGLProgramGenerated.cpp
@@ -1856,7 +1856,7 @@ void SLGLProgramGenerated::buildProgramName(SLMaterial* mat,
void SLGLProgramGenerated::buildProgramNamePS(SLMaterial* mat,
string& programName,
bool isDrawProg,
- bool instancedRendering)
+ bool renderInstanced)
{
assert(mat && "No material pointer passed!");
programName = "gen";
@@ -1871,7 +1871,7 @@ void SLGLProgramGenerated::buildProgramNamePS(SLMaterial* mat,
{
programName += "-Draw";
- if (instancedRendering)
+ if (renderInstanced)
programName += "-Inst";
programName += mat->texturesString();
@@ -1976,7 +1976,7 @@ void SLGLProgramGenerated::buildProgramCode(SLMaterial* mat,
* @param mat Parent material pointer
* @param isDrawProg Flag if program is for drawing instead of update
*/
-void SLGLProgramGenerated::buildProgramCodePS(SLMaterial* mat, bool isDrawProg, bool isRenderInstanced)
+void SLGLProgramGenerated::buildProgramCodePS(SLMaterial* mat, bool isDrawProg, bool renderInstanced)
{
if (mat->name() == "IBLMat")
{
@@ -1989,7 +1989,7 @@ void SLGLProgramGenerated::buildProgramCodePS(SLMaterial* mat, bool isDrawProg,
if (isDrawProg)
{
- if (isRenderInstanced)
+ if (renderInstanced)
buildPerPixParticleInstanced(mat);
else
buildPerPixParticle(mat);
diff --git a/modules/sl/source/gl/SLGLProgramGenerated.h b/modules/sl/source/gl/SLGLProgramGenerated.h
index bd2fe05b..39738407 100644
--- a/modules/sl/source/gl/SLGLProgramGenerated.h
+++ b/modules/sl/source/gl/SLGLProgramGenerated.h
@@ -99,9 +99,9 @@ class SLGLProgramGenerated : public SLGLProgram
static void buildProgramNamePS(SLMaterial* mat,
string& programName,
bool isDrawProg,
- bool instancedRendering);
+ bool renderInstanced);
- void buildProgramCodePS(SLMaterial* mat, bool isDrawProg, bool isRenderInstanced = false);
+ void buildProgramCodePS(SLMaterial* mat, bool isDrawProg, bool renderInstanced = false);
void buildProgramCode(SLMaterial* mat,
SLVLight* lights);
void beginShader(SLCamera* cam,
From 32f7b049e0941bf4338b01f2962ea8056f089ce5 Mon Sep 17 00:00:00 2001
From: luc
Date: Mon, 13 Nov 2023 18:03:27 +0100
Subject: [PATCH 23/29] If geometry shader not supported, particle system
automatically use draw instanced
---
apps/app_demo_slproject/source/AppDemoGui.cpp | 46 +-
.../app_demo_slproject/source/AppDemoLoad.cpp | 722 +++++++++---------
modules/sl/source/mesh/SLParticleSystem.cpp | 10 +-
3 files changed, 379 insertions(+), 399 deletions(-)
diff --git a/apps/app_demo_slproject/source/AppDemoGui.cpp b/apps/app_demo_slproject/source/AppDemoGui.cpp
index 32abad82..7f18410b 100644
--- a/apps/app_demo_slproject/source/AppDemoGui.cpp
+++ b/apps/app_demo_slproject/source/AppDemoGui.cpp
@@ -1775,27 +1775,20 @@ void AppDemoGui::buildMenuBar(SLScene* s, SLSceneView* sv)
if (ImGui::BeginMenu("Particle Systems"))
{
- if (stateGL->glHasGeometryShaders())
- {
- if (ImGui::MenuItem("First Particle System", nullptr, sid == SID_ParticleSystem_First))
- s->onLoad(am, s, sv, SID_ParticleSystem_First);
- if (ImGui::MenuItem("Demo Particle System", nullptr, sid == SID_ParticleSystem_Demo))
- s->onLoad(am, s, sv, SID_ParticleSystem_Demo);
- if (ImGui::MenuItem("Dust Storm Particle System", nullptr, sid == SID_ParticleSystem_DustStorm))
- s->onLoad(am, s, sv, SID_ParticleSystem_DustStorm);
- if (ImGui::MenuItem("Fountain Particle System", nullptr, sid == SID_ParticleSystem_Fountain))
- s->onLoad(am, s, sv, SID_ParticleSystem_Fountain);
- if (ImGui::MenuItem("Sun Particle System", nullptr, sid == SID_ParticleSystem_Sun))
- s->onLoad(am, s, sv, SID_ParticleSystem_Sun);
- if (ImGui::MenuItem("Ring of Fire Particle System", nullptr, sid == SID_ParticleSystem_RingOfFire))
- s->onLoad(am, s, sv, SID_ParticleSystem_RingOfFire);
- if (ImGui::MenuItem("Complex Fire Particle System", nullptr, sid == SID_ParticleSystem_FireComplex))
- s->onLoad(am, s, sv, SID_ParticleSystem_FireComplex);
- }
- else
- {
- ImGui::MenuItem("Particles need OpenGL >= 4.0 or OpenGLES >= 3.1", nullptr, false, false);
- }
+ if (ImGui::MenuItem("First Particle System", nullptr, sid == SID_ParticleSystem_First))
+ s->onLoad(am, s, sv, SID_ParticleSystem_First);
+ if (ImGui::MenuItem("Demo Particle System", nullptr, sid == SID_ParticleSystem_Demo))
+ s->onLoad(am, s, sv, SID_ParticleSystem_Demo);
+ if (ImGui::MenuItem("Dust Storm Particle System", nullptr, sid == SID_ParticleSystem_DustStorm))
+ s->onLoad(am, s, sv, SID_ParticleSystem_DustStorm);
+ if (ImGui::MenuItem("Fountain Particle System", nullptr, sid == SID_ParticleSystem_Fountain))
+ s->onLoad(am, s, sv, SID_ParticleSystem_Fountain);
+ if (ImGui::MenuItem("Sun Particle System", nullptr, sid == SID_ParticleSystem_Sun))
+ s->onLoad(am, s, sv, SID_ParticleSystem_Sun);
+ if (ImGui::MenuItem("Ring of Fire Particle System", nullptr, sid == SID_ParticleSystem_RingOfFire))
+ s->onLoad(am, s, sv, SID_ParticleSystem_RingOfFire);
+ if (ImGui::MenuItem("Complex Fire Particle System", nullptr, sid == SID_ParticleSystem_FireComplex))
+ s->onLoad(am, s, sv, SID_ParticleSystem_FireComplex);
ImGui::EndMenu();
}
@@ -1964,13 +1957,10 @@ void AppDemoGui::buildMenuBar(SLScene* s, SLSceneView* sv)
s->onLoad(am, s, sv, SID_Benchmark6_ColumnsLOD);
if (ImGui::MenuItem("Jan's Universe", nullptr, sid == SID_Benchmark7_JansUniverse))
s->onLoad(am, s, sv, SID_Benchmark7_JansUniverse);
- if (stateGL->glHasGeometryShaders())
- {
- if (ImGui::MenuItem("Particle System lot of fire complex", nullptr, sid == SID_Benchmark8_ParticleSystemFireComplex))
- s->onLoad(am, s, sv, SID_Benchmark8_ParticleSystemFireComplex);
- if (ImGui::MenuItem("Particle System lot of particle", nullptr, sid == SID_Benchmark9_ParticleSystemManyParticles))
- s->onLoad(am, s, sv, SID_Benchmark9_ParticleSystemManyParticles);
- }
+ if (ImGui::MenuItem("Particle System lot of fire complex", nullptr, sid == SID_Benchmark8_ParticleSystemFireComplex))
+ s->onLoad(am, s, sv, SID_Benchmark8_ParticleSystemFireComplex);
+ if (ImGui::MenuItem("Particle System lot of particle", nullptr, sid == SID_Benchmark9_ParticleSystemManyParticles))
+ s->onLoad(am, s, sv, SID_Benchmark9_ParticleSystemManyParticles);
ImGui::EndMenu();
}
diff --git a/apps/app_demo_slproject/source/AppDemoLoad.cpp b/apps/app_demo_slproject/source/AppDemoLoad.cpp
index 34390c1b..d65088ca 100644
--- a/apps/app_demo_slproject/source/AppDemoLoad.cpp
+++ b/apps/app_demo_slproject/source/AppDemoLoad.cpp
@@ -5868,419 +5868,401 @@ resolution shadows near the camera and lower resolution shadows further away.");
}
else if (sceneID == SID_ParticleSystem_Demo) //................................................
{
- if (stateGL->glHasGeometryShaders())
- {
- // Set scene name and info string
- s->name("Simple Demo Particle System");
- s->info("This most simple single particle system is meant to be improved by adding more and more features in the properties list.");
+ // Set scene name and info string
+ s->name("Simple Demo Particle System");
+ s->info("This most simple single particle system is meant to be improved by adding more and more features in the properties list.");
- // Create a scene group node
- SLNode* scene = new SLNode("scene node");
- s->root3D(scene);
+ // Create a scene group node
+ SLNode* scene = new SLNode("scene node");
+ s->root3D(scene);
- // Create textures and materials
- SLGLTexture* texC = new SLGLTexture(am, texPath + "ParticleSmoke_08_C.png");
- SLGLTexture* texFlipbook = new SLGLTexture(am, texPath + "ParticleSmoke_03_8x8_C.png");
+ // Create textures and materials
+ SLGLTexture* texC = new SLGLTexture(am, texPath + "ParticleSmoke_08_C.png");
+ SLGLTexture* texFlipbook = new SLGLTexture(am, texPath + "ParticleSmoke_03_8x8_C.png");
- // Create meshes and nodes
- SLParticleSystem* ps = new SLParticleSystem(am,
- 1,
- SLVec3f(0.04f, 0.4f, 0.1f),
- SLVec3f(-0.11f, 0.7f, -0.1f),
- 4.0f,
- texC,
- "Particle System",
- texFlipbook);
- ps->doAlphaOverLT(false);
- ps->doSizeOverLT(false);
- ps->doRotation(false);
- ps->doColor(false);
- ps->acceleration(-0.5, 0.0, 0.0);
- ps->timeToLive(2.0f);
- SLMesh* pSMesh = ps;
- SLNode* pSNode = new SLNode(pSMesh, "Particle system node");
- scene->addChild(pSNode);
+ // Create meshes and nodes
+ SLParticleSystem* ps = new SLParticleSystem(am,
+ 1,
+ SLVec3f(0.04f, 0.4f, 0.1f),
+ SLVec3f(-0.11f, 0.7f, -0.1f),
+ 4.0f,
+ texC,
+ "Particle System",
+ texFlipbook);
+ ps->doAlphaOverLT(false);
+ ps->doSizeOverLT(false);
+ ps->doRotation(false);
+ ps->doColor(false);
+ ps->acceleration(-0.5, 0.0, 0.0);
+ ps->timeToLive(2.0f);
+ SLMesh* pSMesh = ps;
+ SLNode* pSNode = new SLNode(pSMesh, "Particle system node");
+ scene->addChild(pSNode);
- // Set background color and the root scene node
- sv->sceneViewCamera()->background().colors(SLCol4f(0.8f, 0.8f, 0.8f),
- SLCol4f(0.2f, 0.2f, 0.2f));
- // Save energy
- sv->doWaitOnIdle(false);
- }
+ // Set background color and the root scene node
+ sv->sceneViewCamera()->background().colors(SLCol4f(0.8f, 0.8f, 0.8f),
+ SLCol4f(0.2f, 0.2f, 0.2f));
+ // Save energy
+ sv->doWaitOnIdle(false);
}
else if (sceneID == SID_ParticleSystem_DustStorm) //...........................................
{
- if (stateGL->glHasGeometryShaders())
- {
- // Set scene name and info string
- s->name("Dust storm particle system");
- s->info("This dust storm particle system uses the box shape type for distribution.\n"
- "See the properties window for the detailed settings of the particles system");
-
- // Create a scene group node
- SLNode* scene = new SLNode("scene node");
- s->root3D(scene);
-
- // Create and add camera
- SLCamera* cam1 = new SLCamera("Camera 1");
- cam1->translation(0, 0, 55);
- cam1->lookAt(0, 0, 0);
- cam1->focalDist(55);
- scene->addChild(cam1);
- sv->camera(cam1);
+ // Set scene name and info string
+ s->name("Dust storm particle system");
+ s->info("This dust storm particle system uses the box shape type for distribution.\n"
+ "See the properties window for the detailed settings of the particles system");
- // Create textures and materials
- SLGLTexture* texC = new SLGLTexture(am, texPath + "ParticleSmoke_08_C.png");
- SLGLTexture* texFlipbookSmoke = new SLGLTexture(am, texPath + "ParticleSmoke_03_8x8_C.png");
+ // Create a scene group node
+ SLNode* scene = new SLNode("scene node");
+ s->root3D(scene);
- // Create meshes and nodes
- // Dust storm
- SLParticleSystem* ps = new SLParticleSystem(am,
- 500,
- SLVec3f(-0.1f, -0.5f, -5.0f),
- SLVec3f(0.1f, 0.5f, -2.5f),
- 3.5f,
- texC,
- "DustStorm",
- texFlipbookSmoke);
- ps->doShape(true);
- ps->shapeType(ST_Box);
- ps->shapeScale(50.0f, 1.0f, 50.0f);
- ps->scale(15.0f);
- ps->doSizeOverLT(false);
- ps->doAlphaOverLT(true);
- ps->doAlphaOverLTCurve(true);
- ps->bezierStartEndPointAlpha()[1] = 0.0f;
- ps->bezierControlPointAlpha()[1] = 0.5f;
- ps->bezierControlPointAlpha()[2] = 0.5f;
- ps->generateBernsteinPAlpha();
- ps->doRotRange(true);
- ps->color(SLCol4f(1.0f, 1.0f, 1.0f, 1.0f));
- ps->doBlendBrightness(false);
- ps->frameRateFB(16);
+ // Create and add camera
+ SLCamera* cam1 = new SLCamera("Camera 1");
+ cam1->translation(0, 0, 55);
+ cam1->lookAt(0, 0, 0);
+ cam1->focalDist(55);
+ scene->addChild(cam1);
+ sv->camera(cam1);
- SLMesh* pSMesh = ps;
- SLNode* pSNode = new SLNode(pSMesh, "Particle system node fire2");
- pSNode->translate(3.0f, -0.8f, 0.0f, TS_object);
+ // Create textures and materials
+ SLGLTexture* texC = new SLGLTexture(am, texPath + "ParticleSmoke_08_C.png");
+ SLGLTexture* texFlipbookSmoke = new SLGLTexture(am, texPath + "ParticleSmoke_03_8x8_C.png");
- scene->addChild(pSNode);
+ // Create meshes and nodes
+ // Dust storm
+ SLParticleSystem* ps = new SLParticleSystem(am,
+ 500,
+ SLVec3f(-0.1f, -0.5f, -5.0f),
+ SLVec3f(0.1f, 0.5f, -2.5f),
+ 3.5f,
+ texC,
+ "DustStorm",
+ texFlipbookSmoke);
+ ps->doShape(true);
+ ps->shapeType(ST_Box);
+ ps->shapeScale(50.0f, 1.0f, 50.0f);
+ ps->scale(15.0f);
+ ps->doSizeOverLT(false);
+ ps->doAlphaOverLT(true);
+ ps->doAlphaOverLTCurve(true);
+ ps->bezierStartEndPointAlpha()[1] = 0.0f;
+ ps->bezierControlPointAlpha()[1] = 0.5f;
+ ps->bezierControlPointAlpha()[2] = 0.5f;
+ ps->generateBernsteinPAlpha();
+ ps->doRotRange(true);
+ ps->color(SLCol4f(1.0f, 1.0f, 1.0f, 1.0f));
+ ps->doBlendBrightness(false);
+ ps->frameRateFB(16);
+
+ SLMesh* pSMesh = ps;
+ SLNode* pSNode = new SLNode(pSMesh, "Particle system node fire2");
+ pSNode->translate(3.0f, -0.8f, 0.0f, TS_object);
+
+ scene->addChild(pSNode);
- // Set background color and the root scene node
- sv->sceneViewCamera()->background().colors(SLCol4f(0.8f, 0.8f, 0.8f),
- SLCol4f(0.2f, 0.2f, 0.2f));
- // Save energy
- sv->doWaitOnIdle(false);
- }
+ // Set background color and the root scene node
+ sv->sceneViewCamera()->background().colors(SLCol4f(0.8f, 0.8f, 0.8f),
+ SLCol4f(0.2f, 0.2f, 0.2f));
+ // Save energy
+ sv->doWaitOnIdle(false);
}
else if (sceneID == SID_ParticleSystem_Fountain) //............................................
{
- if (stateGL->glHasGeometryShaders())
- {
- // Set scene name and info string
- s->name("Fountain particle system");
- s->info("This fountain particle system uses acceleration and gravity.\n"
- "See the properties window for the detailed settings of the particles system");
+ // Set scene name and info string
+ s->name("Fountain particle system");
+ s->info("This fountain particle system uses acceleration and gravity.\n"
+ "See the properties window for the detailed settings of the particles system");
- // Create a scene group node
- SLNode* scene = new SLNode("scene node");
- s->root3D(scene);
+ // Create a scene group node
+ SLNode* scene = new SLNode("scene node");
+ s->root3D(scene);
- // Create and add camera
- SLCamera* cam1 = new SLCamera("Camera 1");
- cam1->translation(0, -1, 55);
- cam1->lookAt(0, -1, 0);
- cam1->focalDist(55);
- scene->addChild(cam1);
- sv->camera(cam1);
+ // Create and add camera
+ SLCamera* cam1 = new SLCamera("Camera 1");
+ cam1->translation(0, -1, 55);
+ cam1->lookAt(0, -1, 0);
+ cam1->focalDist(55);
+ scene->addChild(cam1);
+ sv->camera(cam1);
- // Create textures and materials
- SLGLTexture* texC = new SLGLTexture(am, texPath + "ParticleCircle_05_C.png");
- SLGLTexture* texFlipbook = new SLGLTexture(am, texPath + "ParticleSmoke_03_8x8_C.png");
- // SLGLTexture* texFlipbook = new SLGLTexture(am, texPath + "ParticleSmoke_04_8x8_C.png");
+ // Create textures and materials
+ SLGLTexture* texC = new SLGLTexture(am, texPath + "ParticleCircle_05_C.png");
+ SLGLTexture* texFlipbook = new SLGLTexture(am, texPath + "ParticleSmoke_03_8x8_C.png");
+ // SLGLTexture* texFlipbook = new SLGLTexture(am, texPath + "ParticleSmoke_04_8x8_C.png");
- // Create a light source node
- SLLightSpot* light1 = new SLLightSpot(am, s, 0.3f);
- light1->translation(0, -1, 2);
- light1->name("light node");
- scene->addChild(light1);
+ // Create a light source node
+ SLLightSpot* light1 = new SLLightSpot(am, s, 0.3f);
+ light1->translation(0, -1, 2);
+ light1->name("light node");
+ scene->addChild(light1);
- // Create meshes and nodes
- SLParticleSystem* ps = new SLParticleSystem(am,
- 5000,
- SLVec3f(5.0f, 15.0f, 5.0f),
- SLVec3f(-5.0f, 17.0f, -5.0f),
- 5.0f,
- texC,
- "Fountain",
- texFlipbook);
- SLMesh* pSMesh = ps;
- ps->doGravity(true);
- ps->color(SLCol4f(0.0039f, 0.14f, 0.86f, 0.33f));
- ps->doSizeOverLT(false);
- ps->doAlphaOverLT(false);
- SLNode* pSNode = new SLNode(pSMesh, "Particle system node");
- scene->addChild(pSNode);
+ // Create meshes and nodes
+ SLParticleSystem* ps = new SLParticleSystem(am,
+ 5000,
+ SLVec3f(5.0f, 15.0f, 5.0f),
+ SLVec3f(-5.0f, 17.0f, -5.0f),
+ 5.0f,
+ texC,
+ "Fountain",
+ texFlipbook);
+ SLMesh* pSMesh = ps;
+ ps->doGravity(true);
+ ps->color(SLCol4f(0.0039f, 0.14f, 0.86f, 0.33f));
+ ps->doSizeOverLT(false);
+ ps->doAlphaOverLT(false);
+ SLNode* pSNode = new SLNode(pSMesh, "Particle system node");
+ scene->addChild(pSNode);
- // Set background color and the root scene node
- sv->sceneViewCamera()->background().colors(SLCol4f(0.8f, 0.8f, 0.8f),
- SLCol4f(0.2f, 0.2f, 0.2f));
- // Save energy
- sv->doWaitOnIdle(false);
- }
+ // Set background color and the root scene node
+ sv->sceneViewCamera()->background().colors(SLCol4f(0.8f, 0.8f, 0.8f),
+ SLCol4f(0.2f, 0.2f, 0.2f));
+ // Save energy
+ sv->doWaitOnIdle(false);
}
else if (sceneID == SID_ParticleSystem_Sun) //.................................................
{
- if (stateGL->glHasGeometryShaders())
- {
- // Set scene name and info string
- s->name("Sun particle system");
- s->info("This sun particle system uses the sphere shape type for distribution.\n"
- "See the properties window for the detailed settings of the particles system");
-
- // Create a scene group node
- SLNode* scene = new SLNode("scene node");
- s->root3D(scene);
-
- // Create textures and materials
- SLGLTexture* texC = new SLGLTexture(am, texPath + "ParticleSmoke_08_C.png");
- SLGLTexture* texFlipbook = new SLGLTexture(am, texPath + "ParticleSmoke_03_8x8_C.png");
+ // Set scene name and info string
+ s->name("Sun particle system");
+ s->info("This sun particle system uses the sphere shape type for distribution.\n"
+ "See the properties window for the detailed settings of the particles system");
- // Create meshes and nodes
- SLParticleSystem* ps = new SLParticleSystem(am,
- 10000,
- SLVec3f(0.0f, 0.0f, 0.0f),
- SLVec3f(0.0f, 0.0f, 0.0f),
- 4.0f,
- texC,
- "Sun Particle System",
- texFlipbook);
+ // Create a scene group node
+ SLNode* scene = new SLNode("scene node");
+ s->root3D(scene);
- ps->doShape(true);
- ps->shapeType(ST_Sphere);
- ps->shapeRadius(3.0f);
- ps->doBlendBrightness(true);
- ps->color(SLCol4f(0.925f, 0.238f, 0.097f, 0.199f));
+ // Create textures and materials
+ SLGLTexture* texC = new SLGLTexture(am, texPath + "ParticleSmoke_08_C.png");
+ SLGLTexture* texFlipbook = new SLGLTexture(am, texPath + "ParticleSmoke_03_8x8_C.png");
- SLMesh* pSMesh = ps;
- SLNode* pSNode = new SLNode(pSMesh, "Particle Sun node");
- scene->addChild(pSNode);
+ // Create meshes and nodes
+ SLParticleSystem* ps = new SLParticleSystem(am,
+ 10000,
+ SLVec3f(0.0f, 0.0f, 0.0f),
+ SLVec3f(0.0f, 0.0f, 0.0f),
+ 4.0f,
+ texC,
+ "Sun Particle System",
+ texFlipbook);
+
+ ps->doShape(true);
+ ps->shapeType(ST_Sphere);
+ ps->shapeRadius(3.0f);
+ ps->doBlendBrightness(true);
+ ps->color(SLCol4f(0.925f, 0.238f, 0.097f, 0.199f));
+
+ SLMesh* pSMesh = ps;
+ SLNode* pSNode = new SLNode(pSMesh, "Particle Sun node");
+ scene->addChild(pSNode);
- // Set background color and the root scene node
- sv->sceneViewCamera()->background().colors(SLCol4f(0.8f, 0.8f, 0.8f),
- SLCol4f(0.2f, 0.2f, 0.2f));
- // Save energy
- sv->doWaitOnIdle(false);
- }
+ // Set background color and the root scene node
+ sv->sceneViewCamera()->background().colors(SLCol4f(0.8f, 0.8f, 0.8f),
+ SLCol4f(0.2f, 0.2f, 0.2f));
+ // Save energy
+ sv->doWaitOnIdle(false);
}
else if (sceneID == SID_ParticleSystem_RingOfFire) //..........................................
{
- if (stateGL->glHasGeometryShaders())
- {
- // Set scene name and info string
- s->name("Ring of fire particle system");
- s->info("This ring particle system uses the cone shape type for distribution.\n"
- "See the properties window for the settings of the particles system");
-
- // Create a scene group node
- SLNode* scene = new SLNode("scene node");
- s->root3D(scene);
-
- // Create textures and materials
- SLGLTexture* texC = new SLGLTexture(am, texPath + "ParticleSmoke_08_C.png");
- SLGLTexture* texFlipbook = new SLGLTexture(am, texPath + "ParticleSmoke_03_8x8_C.png");
+ // Set scene name and info string
+ s->name("Ring of fire particle system");
+ s->info("This ring particle system uses the cone shape type for distribution.\n"
+ "See the properties window for the settings of the particles system");
- // Create meshes and nodes
- SLParticleSystem* ps = new SLParticleSystem(am,
- 1000,
- SLVec3f(0.0f, 0.0f, 0.0f),
- SLVec3f(0.0f, 0.0f, 0.0f),
- 4.0f,
- texC,
- "Ring of fire Particle System",
- texFlipbook);
+ // Create a scene group node
+ SLNode* scene = new SLNode("scene node");
+ s->root3D(scene);
- ps->doShape(true);
- ps->shapeType(ST_Cone);
- ps->doShapeSpawnBase(true);
- ps->doShapeSurface(true);
- ps->shapeRadius(1.0f);
- ps->doBlendBrightness(true);
- ps->color(SLCol4f(0.925f, 0.238f, 0.097f, 0.503f));
+ // Create textures and materials
+ SLGLTexture* texC = new SLGLTexture(am, texPath + "ParticleSmoke_08_C.png");
+ SLGLTexture* texFlipbook = new SLGLTexture(am, texPath + "ParticleSmoke_03_8x8_C.png");
- SLMesh* pSMesh = ps;
- SLNode* pSNode = new SLNode(pSMesh, "Particle Ring Fire node");
- pSNode->rotate(90, 1, 0, 0);
- scene->addChild(pSNode);
+ // Create meshes and nodes
+ SLParticleSystem* ps = new SLParticleSystem(am,
+ 1000,
+ SLVec3f(0.0f, 0.0f, 0.0f),
+ SLVec3f(0.0f, 0.0f, 0.0f),
+ 4.0f,
+ texC,
+ "Ring of fire Particle System",
+ texFlipbook);
+
+ ps->doShape(true);
+ ps->shapeType(ST_Cone);
+ ps->doShapeSpawnBase(true);
+ ps->doShapeSurface(true);
+ ps->shapeRadius(1.0f);
+ ps->doBlendBrightness(true);
+ ps->color(SLCol4f(0.925f, 0.238f, 0.097f, 0.503f));
+
+ SLMesh* pSMesh = ps;
+ SLNode* pSNode = new SLNode(pSMesh, "Particle Ring Fire node");
+ pSNode->rotate(90, 1, 0, 0);
+ scene->addChild(pSNode);
- // Set background color and the root scene node
- sv->sceneViewCamera()->background().colors(SLCol4f(0.8f, 0.8f, 0.8f),
- SLCol4f(0.2f, 0.2f, 0.2f));
- // Save energy
- sv->doWaitOnIdle(false);
- }
+ // Set background color and the root scene node
+ sv->sceneViewCamera()->background().colors(SLCol4f(0.8f, 0.8f, 0.8f),
+ SLCol4f(0.2f, 0.2f, 0.2f));
+ // Save energy
+ sv->doWaitOnIdle(false);
}
else if (sceneID == SID_ParticleSystem_FireComplex) //.........................................
{
- if (stateGL->glHasGeometryShaders())
- {
- // Set scene name and info string
- s->name("Fire Complex particle system");
- s->info("The fire particle systems contain each multiple sub particle systems.\n"
- "See the scenegraph window for the sub particles systems. "
- "See the properties window for the settings of the particles systems");
+ // Set scene name and info string
+ s->name("Fire Complex particle system");
+ s->info("The fire particle systems contain each multiple sub particle systems.\n"
+ "See the scenegraph window for the sub particles systems. "
+ "See the properties window for the settings of the particles systems");
- // Create a scene group node
- SLNode* scene = new SLNode("scene node");
- s->root3D(scene);
+ // Create a scene group node
+ SLNode* scene = new SLNode("scene node");
+ s->root3D(scene);
- // Create and add camera
- SLCamera* cam1 = new SLCamera("Camera 1");
- cam1->translation(0, 1.2f, 4.0f);
- cam1->lookAt(0, 1.2f, 0);
- cam1->focalDist(4.5f);
- cam1->setInitialState();
- scene->addChild(cam1);
- sv->camera(cam1);
+ // Create and add camera
+ SLCamera* cam1 = new SLCamera("Camera 1");
+ cam1->translation(0, 1.2f, 4.0f);
+ cam1->lookAt(0, 1.2f, 0);
+ cam1->focalDist(4.5f);
+ cam1->setInitialState();
+ scene->addChild(cam1);
+ sv->camera(cam1);
- // Create textures and materials
- SLGLTexture* texFireCld = new SLGLTexture(am, texPath + "ParticleFirecloudTransparent_C.png");
- SLGLTexture* texFireFlm = new SLGLTexture(am, texPath + "ParticleFlames_06_8x8_C.png");
- SLGLTexture* texCircle = new SLGLTexture(am, texPath + "ParticleCircle_05_C.png");
- SLGLTexture* texSmokeB = new SLGLTexture(am, texPath + "ParticleCloudBlack_C.png");
- SLGLTexture* texSmokeW = new SLGLTexture(am, texPath + "ParticleCloudWhite_C.png");
- SLGLTexture* texTorchFlm = new SLGLTexture(am, texPath + "ParticleFlames_04_16x4_C.png");
- SLGLTexture* texTorchSmk = new SLGLTexture(am, texPath + "ParticleSmoke_08_C.png");
-
- SLNode* complexFire = createComplexFire(am,
- s,
- true,
- texTorchSmk,
- texFireFlm,
- 8,
- 8,
- texCircle,
- texSmokeB,
- texSmokeW);
- scene->addChild(complexFire);
-
- // Room around
- {
- // Room parent node
- SLNode* room = new SLNode("Room");
- scene->addChild(room);
-
- // Back wall material
- SLGLTexture* texWallDIF = new SLGLTexture(am, texPath + "BrickLimestoneGray_1K_DIF.jpg", SL_ANISOTROPY_MAX, GL_LINEAR);
- SLGLTexture* texWallNRM = new SLGLTexture(am, texPath + "BrickLimestoneGray_1K_NRM.jpg", SL_ANISOTROPY_MAX, GL_LINEAR);
- SLMaterial* matWall = new SLMaterial(am, "mat3", texWallDIF, texWallNRM);
- matWall->specular(SLCol4f::BLACK);
- matWall->metalness(0);
- matWall->roughness(1);
- matWall->reflectionModel(RM_CookTorrance);
-
- // Room dimensions
- SLfloat pL = -2.0f, pR = 2.0f; // left/right
- SLfloat pB = -0.01f, pT = 4.0f; // bottom/top
- SLfloat pN = 2.0f, pF = -2.0f; // near/far
-
- // bottom rectangle
- SLNode* b = new SLNode(new SLRectangle(am, SLVec2f(pL, -pN), SLVec2f(pR, -pF), 10, 10, "Floor", matWall));
- b->rotate(90, -1, 0, 0);
- b->translate(0, 0, pB, TS_object);
- room->addChild(b);
-
- // far rectangle
- SLNode* f = new SLNode(new SLRectangle(am, SLVec2f(pL, pB), SLVec2f(pR, pT), 10, 10, "Wall far", matWall));
- f->translate(0, 0, pF, TS_object);
- room->addChild(f);
-
- // near rectangle
- SLNode* n = new SLNode(new SLRectangle(am, SLVec2f(pL, pB), SLVec2f(pR, pT), 10, 10, "Wall near", matWall));
- n->rotate(180, 0, 1, 0);
- n->translate(0, 0, pF, TS_object);
- room->addChild(n);
-
- // left rectangle
- SLNode* l = new SLNode(new SLRectangle(am, SLVec2f(-pN, pB), SLVec2f(-pF, pT), 10, 10, "Wall left", matWall));
- l->rotate(90, 0, 1, 0);
- l->translate(0, 0, pL, TS_object);
- room->addChild(l);
-
- // right rectangle
- SLNode* r = new SLNode(new SLRectangle(am, SLVec2f(pF, pB), SLVec2f(pN, pT), 10, 10, "Wall right", matWall));
- r->rotate(90, 0, -1, 0);
- r->translate(0, 0, -pR, TS_object);
- room->addChild(r);
- }
+ // Create textures and materials
+ SLGLTexture* texFireCld = new SLGLTexture(am, texPath + "ParticleFirecloudTransparent_C.png");
+ SLGLTexture* texFireFlm = new SLGLTexture(am, texPath + "ParticleFlames_06_8x8_C.png");
+ SLGLTexture* texCircle = new SLGLTexture(am, texPath + "ParticleCircle_05_C.png");
+ SLGLTexture* texSmokeB = new SLGLTexture(am, texPath + "ParticleCloudBlack_C.png");
+ SLGLTexture* texSmokeW = new SLGLTexture(am, texPath + "ParticleCloudWhite_C.png");
+ SLGLTexture* texTorchFlm = new SLGLTexture(am, texPath + "ParticleFlames_04_16x4_C.png");
+ SLGLTexture* texTorchSmk = new SLGLTexture(am, texPath + "ParticleSmoke_08_C.png");
+
+ SLNode* complexFire = createComplexFire(am,
+ s,
+ true,
+ texTorchSmk,
+ texFireFlm,
+ 8,
+ 8,
+ texCircle,
+ texSmokeB,
+ texSmokeW);
+ scene->addChild(complexFire);
+
+ // Room around
+ {
+ // Room parent node
+ SLNode* room = new SLNode("Room");
+ scene->addChild(room);
+
+ // Back wall material
+ SLGLTexture* texWallDIF = new SLGLTexture(am, texPath + "BrickLimestoneGray_1K_DIF.jpg", SL_ANISOTROPY_MAX, GL_LINEAR);
+ SLGLTexture* texWallNRM = new SLGLTexture(am, texPath + "BrickLimestoneGray_1K_NRM.jpg", SL_ANISOTROPY_MAX, GL_LINEAR);
+ SLMaterial* matWall = new SLMaterial(am, "mat3", texWallDIF, texWallNRM);
+ matWall->specular(SLCol4f::BLACK);
+ matWall->metalness(0);
+ matWall->roughness(1);
+ matWall->reflectionModel(RM_CookTorrance);
+
+ // Room dimensions
+ SLfloat pL = -2.0f, pR = 2.0f; // left/right
+ SLfloat pB = -0.01f, pT = 4.0f; // bottom/top
+ SLfloat pN = 2.0f, pF = -2.0f; // near/far
+
+ // bottom rectangle
+ SLNode* b = new SLNode(new SLRectangle(am, SLVec2f(pL, -pN), SLVec2f(pR, -pF), 10, 10, "Floor", matWall));
+ b->rotate(90, -1, 0, 0);
+ b->translate(0, 0, pB, TS_object);
+ room->addChild(b);
+
+ // far rectangle
+ SLNode* f = new SLNode(new SLRectangle(am, SLVec2f(pL, pB), SLVec2f(pR, pT), 10, 10, "Wall far", matWall));
+ f->translate(0, 0, pF, TS_object);
+ room->addChild(f);
+
+ // near rectangle
+ SLNode* n = new SLNode(new SLRectangle(am, SLVec2f(pL, pB), SLVec2f(pR, pT), 10, 10, "Wall near", matWall));
+ n->rotate(180, 0, 1, 0);
+ n->translate(0, 0, pF, TS_object);
+ room->addChild(n);
+
+ // left rectangle
+ SLNode* l = new SLNode(new SLRectangle(am, SLVec2f(-pN, pB), SLVec2f(-pF, pT), 10, 10, "Wall left", matWall));
+ l->rotate(90, 0, 1, 0);
+ l->translate(0, 0, pL, TS_object);
+ room->addChild(l);
+
+ // right rectangle
+ SLNode* r = new SLNode(new SLRectangle(am, SLVec2f(pF, pB), SLVec2f(pN, pT), 10, 10, "Wall right", matWall));
+ r->rotate(90, 0, -1, 0);
+ r->translate(0, 0, -pR, TS_object);
+ room->addChild(r);
+ }
- // Firewood
- SLAssimpImporter importer;
- SLNode* firewood = importer.load(s->animManager(),
- am,
- modelPath + "GLTF/Firewood/Firewood1.gltf",
- texPath,
- nullptr,
- false,
- true,
- nullptr,
- 0.3f,
- true);
- firewood->scale(2);
- scene->addChild(firewood);
-
- // Torch
- SLNode* torchL = importer.load(s->animManager(),
- am,
- modelPath + "GLTF/Torch/Torch.gltf",
- texPath,
- nullptr,
- false,
- true,
- nullptr,
- 0.3f,
- true);
- torchL->name("Torch Left");
- SLNode* torchR = torchL->copyRec();
- torchR->name("Torch Right");
- torchL->translate(-2, 1.5f, 0);
- torchL->rotate(90, 0, 1, 0);
- torchL->scale(2);
- scene->addChild(torchL);
- torchR->translate(2, 1.5f, 0);
- torchR->rotate(-90, 0, 1, 0);
- torchR->scale(2);
- scene->addChild(torchR);
-
- // Torch flame left
- SLNode* torchFlameNodeL = createTorchFire(am,
- s,
- true,
- texTorchSmk,
- texTorchFlm,
- 16,
- 4);
- torchFlameNodeL->translate(-1.6f, 2.25f, 0);
- torchFlameNodeL->name("Torch Fire Left");
- scene->addChild(torchFlameNodeL);
-
- // Torch flame right
- SLNode* torchFlameNodeR = createTorchFire(am,
- s,
- true,
- texTorchSmk,
- texTorchFlm,
- 16,
- 4);
- torchFlameNodeR->translate(1.6f, 2.25f, 0);
- torchFlameNodeR->name("Torch Fire Right");
- scene->addChild(torchFlameNodeR);
+ // Firewood
+ SLAssimpImporter importer;
+ SLNode* firewood = importer.load(s->animManager(),
+ am,
+ modelPath + "GLTF/Firewood/Firewood1.gltf",
+ texPath,
+ nullptr,
+ false,
+ true,
+ nullptr,
+ 0.3f,
+ true);
+ firewood->scale(2);
+ scene->addChild(firewood);
- // Set background color and the root scene node
- sv->sceneViewCamera()->background().colors(SLCol4f(0.8f, 0.8f, 0.8f),
- SLCol4f(0.2f, 0.2f, 0.2f));
- // Save energy
- sv->doWaitOnIdle(false);
- }
+ // Torch
+ SLNode* torchL = importer.load(s->animManager(),
+ am,
+ modelPath + "GLTF/Torch/Torch.gltf",
+ texPath,
+ nullptr,
+ false,
+ true,
+ nullptr,
+ 0.3f,
+ true);
+ torchL->name("Torch Left");
+ SLNode* torchR = torchL->copyRec();
+ torchR->name("Torch Right");
+ torchL->translate(-2, 1.5f, 0);
+ torchL->rotate(90, 0, 1, 0);
+ torchL->scale(2);
+ scene->addChild(torchL);
+ torchR->translate(2, 1.5f, 0);
+ torchR->rotate(-90, 0, 1, 0);
+ torchR->scale(2);
+ scene->addChild(torchR);
+
+ // Torch flame left
+ SLNode* torchFlameNodeL = createTorchFire(am,
+ s,
+ true,
+ texTorchSmk,
+ texTorchFlm,
+ 16,
+ 4);
+ torchFlameNodeL->translate(-1.6f, 2.25f, 0);
+ torchFlameNodeL->name("Torch Fire Left");
+ scene->addChild(torchFlameNodeL);
+
+ // Torch flame right
+ SLNode* torchFlameNodeR = createTorchFire(am,
+ s,
+ true,
+ texTorchSmk,
+ texTorchFlm,
+ 16,
+ 4);
+ torchFlameNodeR->translate(1.6f, 2.25f, 0);
+ torchFlameNodeR->name("Torch Fire Right");
+ scene->addChild(torchFlameNodeR);
+
+ // Set background color and the root scene node
+ sv->sceneViewCamera()->background().colors(SLCol4f(0.8f, 0.8f, 0.8f),
+ SLCol4f(0.2f, 0.2f, 0.2f));
+ // Save energy
+ sv->doWaitOnIdle(false);
}
else if (sceneID == SID_Benchmark1_LargeModel) //..............................................
diff --git a/modules/sl/source/mesh/SLParticleSystem.cpp b/modules/sl/source/mesh/SLParticleSystem.cpp
index bef75869..bc8a2886 100644
--- a/modules/sl/source/mesh/SLParticleSystem.cpp
+++ b/modules/sl/source/mesh/SLParticleSystem.cpp
@@ -35,7 +35,15 @@ SLParticleSystem::SLParticleSystem(SLAssetManager* assetMgr,
assert(!name.empty());
// To be added to constructor
- _renderInstanced = renderInstanced;
+
+ if (SLGLState::instance()->glHasGeometryShaders())
+ {
+ _renderInstanced = renderInstanced;
+ }
+ else
+ {
+ _renderInstanced = true;
+ }
_primitive = PT_points;
P.push_back(SLVec3f(0, 0, 0)); // Trick SL project because it want mesh to have vertex
From d21a4e174da68fd7b7b2e5508a297f6ecbc68ea9 Mon Sep 17 00:00:00 2001
From: luc
Date: Mon, 13 Nov 2023 19:11:56 +0100
Subject: [PATCH 24/29] fix particle system error with material destruction
---
.../app_demo_slproject/source/AppDemoLoad.cpp | 2 -
modules/sl/source/mesh/SLParticleSystem.cpp | 67 +++++++++++--------
modules/sl/source/mesh/SLParticleSystem.h | 3 +
3 files changed, 42 insertions(+), 30 deletions(-)
diff --git a/apps/app_demo_slproject/source/AppDemoLoad.cpp b/apps/app_demo_slproject/source/AppDemoLoad.cpp
index d65088ca..bcc9f6ff 100644
--- a/apps/app_demo_slproject/source/AppDemoLoad.cpp
+++ b/apps/app_demo_slproject/source/AppDemoLoad.cpp
@@ -499,7 +499,6 @@ SLNode* createComplexFire(SLAssetManager* am,
fireFlameMesh->flipbookRows(flipbookRows);
fireFlameMesh->doFlipBookTexture(true);
fireFlameMesh->doCounterGap(false); // We don't want to have flickering
- fireFlameMesh->changeTexture(); // Switch texture, need to be done, to have flipbook texture as active
fireFlameMesh->doAlphaOverLT(false);
fireFlameMesh->doSizeOverLT(false);
@@ -708,7 +707,6 @@ SLNode* createTorchFire(SLAssetManager* am,
torchFlame->flipbookRows(flipbookRows);
torchFlame->doFlipBookTexture(true);
torchFlame->doCounterGap(false); // We don't want to have flickering
- torchFlame->changeTexture(); // Switch texture, need to be done, to have flipbook texture as active
torchFlame->doAlphaOverLT(false);
torchFlame->doSizeOverLT(false);
torchFlame->doRotation(false);
diff --git a/modules/sl/source/mesh/SLParticleSystem.cpp b/modules/sl/source/mesh/SLParticleSystem.cpp
index bc8a2886..07bcb9a5 100644
--- a/modules/sl/source/mesh/SLParticleSystem.cpp
+++ b/modules/sl/source/mesh/SLParticleSystem.cpp
@@ -36,6 +36,8 @@ SLParticleSystem::SLParticleSystem(SLAssetManager* assetMgr,
// To be added to constructor
+ _assetManager = assetMgr;
+
if (SLGLState::instance()->glHasGeometryShaders())
{
_renderInstanced = renderInstanced;
@@ -60,10 +62,6 @@ SLParticleSystem::SLParticleSystem(SLAssetManager* assetMgr,
_textureFirst = texC;
_textureFlipbook = texFlipbook;
- // Initialize the drawing:
- SLMaterial* mDraw = new SLMaterial(assetMgr, "Drawing-Material", this, texC);
- mat(mDraw);
-
_updateTime.init(60, 0.0f);
_drawTime.init(60, 0.0f);
@@ -328,6 +326,18 @@ void SLParticleSystem::generate()
deleteDataGpu();
+ // Initialize the drawing:
+ if (_doFlipBookTexture)
+ {
+ SLMaterial* mDraw = new SLMaterial(_assetManager, "Drawing-Material", this, _textureFlipbook);
+ mat(mDraw);
+ }
+ else
+ {
+ SLMaterial* mDraw = new SLMaterial(_assetManager, "Drawing-Material", this, _textureFirst);
+ mat(mDraw);
+ }
+
tempP.resize(_amount);
tempV.resize(_amount);
tempST.resize(_amount);
@@ -484,6 +494,9 @@ void SLParticleSystem::generate()
I32.push_back(3);
I32.push_back(0);
+
+ _renderVao1.deleteGL();
+ _renderVao2.deleteGL();
/* Generate vao for rendering with draw instanced */
_renderVao1.setAttrib(AT_custom0, AT_custom0, &P);
_renderVao1.setIndices(&I32);
@@ -539,24 +552,7 @@ void SLParticleSystem::generateBernsteinPSize()
// 1
_bernsteinPYSize.w = StaEnd[1];
}
-//-----------------------------------------------------------------------------
-/*!
-Change the current use texture, this will switch between the normal texture and
-the flipbook texture (and vice versa)
-*/
-void SLParticleSystem::changeTexture()
-{
- if (_doFlipBookTexture)
- {
- mat()->removeTextureType(TT_diffuse);
- mat()->addTexture(_textureFlipbook);
- }
- else
- {
- mat()->removeTextureType(TT_diffuse);
- mat()->addTexture(_textureFirst);
- }
-}
+
//-----------------------------------------------------------------------------
/*! Function called inside SLNode cull3DRec(..) which flags the particle system
to be not visible in the view frustum. This is needed to correct later the
@@ -597,7 +593,6 @@ void SLParticleSystem::draw(SLSceneView* sv, SLNode* node, SLuint instances)
/////////////////////////////////////
// Init particles vector and init VAO
/////////////////////////////////////
-
if (!_isGenerated)
generate();
@@ -908,6 +903,27 @@ void SLParticleSystem::draw(SLSceneView* sv, SLNode* node, SLuint instances)
// Swap buffer
_drawBuf = 1 - _drawBuf;
}
+
+
+/*!
+Change the current use texture, this will switch between the normal texture and
+the flipbook texture (and vice versa)
+*/
+void SLParticleSystem::changeTexture()
+{
+ if (_doFlipBookTexture)
+ {
+ mat()->removeTextureType(TT_diffuse);
+ mat()->addTexture(_textureFlipbook);
+ }
+ else
+ {
+ mat()->removeTextureType(TT_diffuse);
+ mat()->addTexture(_textureFirst);
+ }
+}
+
+
//-----------------------------------------------------------------------------
//! deleteData deletes all mesh data and VAOs
void SLParticleSystem::deleteData()
@@ -918,12 +934,7 @@ void SLParticleSystem::deleteData()
//! deleteData deletes all mesh data and VAOs
void SLParticleSystem::deleteDataGpu()
{
- _vao1.deleteGL();
- _vao2.deleteGL();
- _renderVao1.deleteGL();
- _renderVao2.deleteGL();
SLMesh::deleteDataGpu();
- _mat->deleteDataGpu();
}
//-----------------------------------------------------------------------------
/*! SLParticleSystem::buildAABB builds the passed axis-aligned bounding box in
diff --git a/modules/sl/source/mesh/SLParticleSystem.h b/modules/sl/source/mesh/SLParticleSystem.h
index d856e62f..17fcb340 100644
--- a/modules/sl/source/mesh/SLParticleSystem.h
+++ b/modules/sl/source/mesh/SLParticleSystem.h
@@ -273,6 +273,9 @@ class SLParticleSystem : public SLMesh
SLVec3f getPointOnPyramid();
SLVec3f getDirectionPyramid(SLVec3f position);
+ // Use to recreate material (the shader change depending if the PS is instanced or not)
+ SLAssetManager* _assetManager; //!< pointer to the asset manager (the owner) if available
+
// Core values
SLint _amount; //!< Amount of a particle
SLVec3f _emitterPos; //!< Position of the particle emitter
From ce1ae04729d79269025ae2694205ac23e3218a72 Mon Sep 17 00:00:00 2001
From: Marcus Hudritsch
Date: Mon, 20 Nov 2023 10:25:02 +0100
Subject: [PATCH 25/29] Update SLGLState.cpp
---
modules/sl/source/gl/SLGLState.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/modules/sl/source/gl/SLGLState.cpp b/modules/sl/source/gl/SLGLState.cpp
index 724bcdcd..d50cb31f 100644
--- a/modules/sl/source/gl/SLGLState.cpp
+++ b/modules/sl/source/gl/SLGLState.cpp
@@ -409,10 +409,10 @@ void SLGLState::useProgram(SLuint progID)
*/
void SLGLState::bindTexture(SLenum target, SLuint textureID)
{
- // (luc) If there we call glActiveTexture and glBindTexture from outside,
+ // (luc) If we call glActiveTexture and glBindTexture from outside,
// This will lead to problems as the global state in SLGLState will not be
// equivalent to the OpenGL state.
- // We should solve this by querying opengl for the last binded texture.
+ // We should solve this by querying opengl for the last bound texture.
// glGetIntegeriv(GL_ACTIVE_TEXTURE, active_texture)
// glGetIntegeriv(GL_TEXTURE_BINDING_2D, textureID)
From 72c4cdf192fc35354daaddd8194b293a998a6d24 Mon Sep 17 00:00:00 2001
From: Marcus Hudritsch
Date: Mon, 20 Nov 2023 16:59:34 +0100
Subject: [PATCH 26/29] Cosmetics
---
modules/sl/source/SLAssetManager.cpp | 2 +-
modules/sl/source/SLMaterial.cpp | 18 ++++++++++--------
2 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/modules/sl/source/SLAssetManager.cpp b/modules/sl/source/SLAssetManager.cpp
index 1fedf31f..05498ce2 100644
--- a/modules/sl/source/SLAssetManager.cpp
+++ b/modules/sl/source/SLAssetManager.cpp
@@ -95,7 +95,7 @@ bool SLAssetManager::removeMesh(SLMesh* mesh)
}
return false;
}
-
+//-----------------------------------------------------------------------------
//! Removes the specified program from the meshes resource vector.
bool SLAssetManager::removeProgram(SLGLProgram* program)
{
diff --git a/modules/sl/source/SLMaterial.cpp b/modules/sl/source/SLMaterial.cpp
index 3f8c0bab..25674510 100644
--- a/modules/sl/source/SLMaterial.cpp
+++ b/modules/sl/source/SLMaterial.cpp
@@ -150,7 +150,7 @@ SLMaterial::SLMaterial(SLAssetManager* am,
SLGLProgram* program) : SLObject(name)
{
_assetManager = am;
- _ambient.set(0, 0, 0); // not used in Cook-Torrance
+ _ambient.set(0, 0, 0); // not used in Cook-Torrance
_diffuse = diffuse;
_specular.set(1, 1, 1); // not used in Cook-Torrance
_emissive.set(0, 0, 0, 0); // not used in Cook-Torrance
@@ -372,8 +372,7 @@ SLMaterial::~SLMaterial()
_errorTexture = nullptr;
}
}
-
-
+//------------------------------------------------------------------------------
void SLMaterial::deleteDataGpu()
{
if (_program)
@@ -384,8 +383,6 @@ void SLMaterial::deleteDataGpu()
_program = nullptr;
}
}
-
-
//-----------------------------------------------------------------------------
/*!
If this material has not yet a shader program assigned (SLMaterial::_program)
@@ -403,7 +400,10 @@ void SLMaterial::generateProgramPS(bool renderInstanced)
// Check first the asset manager if the requested program type already exists
string programNameDraw;
- SLGLProgramGenerated::buildProgramNamePS(this, programNameDraw, true, renderInstanced);
+ SLGLProgramGenerated::buildProgramNamePS(this,
+ programNameDraw,
+ true,
+ renderInstanced);
_program = _assetManager->getProgramByName(programNameDraw);
// If the program was not found by name generate a new one
@@ -478,7 +478,8 @@ void SLMaterial::generateProgramPS(bool renderInstanced)
for (int i = 0; i < TT_numTextureType; i++)
_textures[i].clear();
if (!_errorTexture && !_compileErrorTexFilePath.empty())
- _errorTexture = new SLGLTexture(nullptr, _compileErrorTexFilePath);
+ _errorTexture = new SLGLTexture(nullptr,
+ _compileErrorTexFilePath);
_textures[TT_diffuse].push_back(_errorTexture);
}
@@ -487,7 +488,8 @@ void SLMaterial::generateProgramPS(bool renderInstanced)
for (int i = 0; i < TT_numTextureType; i++)
_textures[i].clear();
if (!_errorTexture && !_compileErrorTexFilePath.empty())
- _errorTexture = new SLGLTexture(nullptr, _compileErrorTexFilePath);
+ _errorTexture = new SLGLTexture(nullptr,
+ _compileErrorTexFilePath);
_textures[TT_diffuse].push_back(_errorTexture);
}
}
From 373ea04fea7889b3d9747095f7582b5d11fad0e5 Mon Sep 17 00:00:00 2001
From: Marcus Hudritsch
Date: Tue, 21 Nov 2023 09:23:01 +0100
Subject: [PATCH 27/29] Fixed SL_EXIT_MSG again
No we see shader compile errors again.
---
modules/sl/source/SL.h | 2 +-
modules/sl/source/gl/SLGLShader.cpp | 1 +
modules/utils/source/Utils.cpp | 6 +++---
3 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/modules/sl/source/SL.h b/modules/sl/source/SL.h
index 8165192f..48708e1a 100644
--- a/modules/sl/source/SL.h
+++ b/modules/sl/source/SL.h
@@ -235,7 +235,7 @@ SL_sizeOfVector(const T& vector)
//-----------------------------------------------------------------------------
// Some debugging and error handling macros
#define SL_LOG(...) Utils::log("SLProject", __VA_ARGS__)
-#define SL_EXIT_MSG(message) Utils::log("SLProject Error", (message))
+#define SL_EXIT_MSG(message) Utils::exitMsg("SLProject", (message), __LINE__, __FILE__)
#define SL_WARN_MSG(message) Utils::warnMsg("SLProject", (message), __LINE__, __FILE__)
//-----------------------------------------------------------------------------
#endif
diff --git a/modules/sl/source/gl/SLGLShader.cpp b/modules/sl/source/gl/SLGLShader.cpp
index eaa87438..7602a311 100644
--- a/modules/sl/source/gl/SLGLShader.cpp
+++ b/modules/sl/source/gl/SLGLShader.cpp
@@ -149,6 +149,7 @@ SLbool SLGLShader::createAndCompile(SLVLight* lights)
SLint lineNum = 1;
for (string& line : lines)
SL_LOG("%4d: %s", lineNum++, line.c_str());
+ SL_LOG("\n");
return false;
}
diff --git a/modules/utils/source/Utils.cpp b/modules/utils/source/Utils.cpp
index 80889202..2f06388b 100644
--- a/modules/utils/source/Utils.cpp
+++ b/modules/utils/source/Utils.cpp
@@ -201,10 +201,10 @@ vector getStringLines(const string& multiLineString)
{
std::string line;
std::getline(stream, line);
- if (!stream.good())
- break;
line = Utils::trimString(line, "\r");
res.push_back(line);
+ if (!stream.good())
+ break;
}
return res;
}
@@ -1391,7 +1391,7 @@ std::string ComputerInfos::get()
// model = model;
# endif
-#elif defined(ANDROID) //................................................
+#elif defined(ANDROID) //................................................
os = "Android";
From 28df38ba5cd3d1331b5bcfa0e0dcc4516679b2e6 Mon Sep 17 00:00:00 2001
From: luc
Date: Mon, 27 Nov 2023 10:11:45 +0100
Subject: [PATCH 28/29] remove useless and non GLSL compilant texNum in
fragshader
---
modules/sl/source/gl/SLGLProgramGenerated.cpp | 5 -----
1 file changed, 5 deletions(-)
diff --git a/modules/sl/source/gl/SLGLProgramGenerated.cpp b/modules/sl/source/gl/SLGLProgramGenerated.cpp
index f191d48f..2eee9230 100644
--- a/modules/sl/source/gl/SLGLProgramGenerated.cpp
+++ b/modules/sl/source/gl/SLGLProgramGenerated.cpp
@@ -168,15 +168,11 @@ const string vertOutput_PS_struct_texNum = R"(
const string vertOutput_PS_struct_End = R"(
} vert; )";
-const string vertOutput_PS_instanced_texNum = R"(
-out uint texNum; // Num of texture in flipbook)";
const string vertOutput_PS_instanced_transparency = R"(
out float transparency; // transparency of a particle )";
const string fragInput_PS_instanced_transparency = R"(
in float transparency; // transparency of a particle )";
-const string fragInput_PS_instanced_texNum = R"(
-in uint texNum; // Num of texture in flipbook)";
const string fragMain_PS_v_c = R"(
vec4 color = u_color; // Particle color)";
@@ -2336,7 +2332,6 @@ void SLGLProgramGenerated::buildPerPixParticleInstanced(SLMaterial* mat)
fragCode += shaderHeader();
// Fragment shader inputs
- if (FlBoTex) fragCode += fragInput_PS_instanced_texNum;
fragCode += fragInput_PS_v_tC;
if (Co && !CoOvLi) fragCode += fragInput_PS_u_c;
if (CoOvLi)
From 7122373bc7fe221bb9e0866b3105238bc4a1c1bb Mon Sep 17 00:00:00 2001
From: Marcus Hudritsch
Date: Mon, 27 Nov 2023 10:51:46 +0100
Subject: [PATCH 29/29] Update AppDemoGui.cpp
---
apps/app_demo_slproject/source/AppDemoGui.cpp | 2 --
1 file changed, 2 deletions(-)
diff --git a/apps/app_demo_slproject/source/AppDemoGui.cpp b/apps/app_demo_slproject/source/AppDemoGui.cpp
index 7f18410b..55d5f5bd 100644
--- a/apps/app_demo_slproject/source/AppDemoGui.cpp
+++ b/apps/app_demo_slproject/source/AppDemoGui.cpp
@@ -4370,8 +4370,6 @@ void AppDemoGui::buildProperties(SLScene* s, SLSceneView* sv)
}
}
- ImGui::Text("Supports GPU skinning: %s", m->supportsGPUSkinning() ? "Yes" : "No");
-
ImGui::TreePop();
}
}