Use a trick to make skinned mesh shader branchless
This commit is contained in:
parent
7252a38da1
commit
fc2e05c0a6
@ -63,34 +63,17 @@ void main(void)
|
||||
vec4 skinned_normal = vec4(0.);
|
||||
vec4 skinned_tangent = vec4(0.);
|
||||
vec4 skinned_bitangent = vec4(0.);
|
||||
if (Weight[0] < 0.01)
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
skinned_position = idle_position;
|
||||
skinned_normal = idle_normal;
|
||||
skinned_tangent = idle_tangent;
|
||||
skinned_bitangent = idle_bitangent;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
// Logically we should break if the weight is (almost) zero
|
||||
// given the fact that it's sorted from high to low,
|
||||
// but GT240 will cause glitches
|
||||
//if (Weight[i] < 0.01)
|
||||
//{
|
||||
// break;
|
||||
//}
|
||||
mat4 joint_matrix = mat4(
|
||||
texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4),
|
||||
texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4 + 1),
|
||||
texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4 + 2),
|
||||
texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4 + 3));
|
||||
skinned_position += Weight[i] * joint_matrix * idle_position;
|
||||
skinned_normal += Weight[i] * joint_matrix * idle_normal;
|
||||
skinned_tangent += Weight[i] * joint_matrix * idle_tangent;
|
||||
skinned_bitangent += Weight[i] * joint_matrix * idle_bitangent;
|
||||
}
|
||||
mat4 joint_matrix = mat4(
|
||||
texelFetch(skinning_tex, clamp(Joint[i] + skinning_offset, 0, MAX_BONES) * 4),
|
||||
texelFetch(skinning_tex, clamp(Joint[i] + skinning_offset, 0, MAX_BONES) * 4 + 1),
|
||||
texelFetch(skinning_tex, clamp(Joint[i] + skinning_offset, 0, MAX_BONES) * 4 + 2),
|
||||
texelFetch(skinning_tex, clamp(Joint[i] + skinning_offset, 0, MAX_BONES) * 4 + 3));
|
||||
skinned_position += Weight[i] * joint_matrix * idle_position;
|
||||
skinned_normal += Weight[i] * joint_matrix * idle_normal;
|
||||
skinned_tangent += Weight[i] * joint_matrix * idle_tangent;
|
||||
skinned_bitangent += Weight[i] * joint_matrix * idle_bitangent;
|
||||
}
|
||||
|
||||
gl_Position = ProjectionViewMatrix * ModelMatrix * skinned_position;
|
||||
|
@ -45,28 +45,14 @@ void main(void)
|
||||
mat4 ModelMatrix = getWorldMatrix(Origin, Orientation, Scale);
|
||||
vec4 idle_position = vec4(Position, 1.);
|
||||
vec4 skinned_position = vec4(0.);
|
||||
if (Weight[0] < 0.01)
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
skinned_position = idle_position;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
// Logically we should break if the weight is (almost) zero
|
||||
// given the fact that it's sorted from high to low,
|
||||
// but GT240 will cause glitches
|
||||
//if (Weight[i] < 0.01)
|
||||
//{
|
||||
// break;
|
||||
//}
|
||||
mat4 joint_matrix = mat4(
|
||||
texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4),
|
||||
texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4 + 1),
|
||||
texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4 + 2),
|
||||
texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4 + 3));
|
||||
skinned_position += Weight[i] * joint_matrix * idle_position;
|
||||
}
|
||||
mat4 joint_matrix = mat4(
|
||||
texelFetch(skinning_tex, clamp(Joint[i] + skinning_offset, 0, MAX_BONES) * 4),
|
||||
texelFetch(skinning_tex, clamp(Joint[i] + skinning_offset, 0, MAX_BONES) * 4 + 1),
|
||||
texelFetch(skinning_tex, clamp(Joint[i] + skinning_offset, 0, MAX_BONES) * 4 + 2),
|
||||
texelFetch(skinning_tex, clamp(Joint[i] + skinning_offset, 0, MAX_BONES) * 4 + 3));
|
||||
skinned_position += Weight[i] * joint_matrix * idle_position;
|
||||
}
|
||||
|
||||
#ifdef VSLayer
|
||||
|
@ -60,42 +60,26 @@ void main(void)
|
||||
vec4 skinned_normal = vec4(0.);
|
||||
vec4 skinned_tangent = vec4(0.);
|
||||
vec4 skinned_bitangent = vec4(0.);
|
||||
if (Weight[0] < 0.01)
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
skinned_position = idle_position;
|
||||
skinned_normal = idle_normal;
|
||||
skinned_tangent = idle_tangent;
|
||||
skinned_bitangent = idle_bitangent;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
// Logically we should break if the weight is (almost) zero
|
||||
// given the fact that it's sorted from high to low,
|
||||
// but GT240 will cause glitches
|
||||
//if (Weight[i] < 0.01)
|
||||
//{
|
||||
// break;
|
||||
//}
|
||||
#ifdef GL_ES
|
||||
mat4 joint_matrix = mat4(
|
||||
texelFetch(skinning_tex, ivec2(0, skinning_offset + Joint[i]), 0),
|
||||
texelFetch(skinning_tex, ivec2(1, skinning_offset + Joint[i]), 0),
|
||||
texelFetch(skinning_tex, ivec2(2, skinning_offset + Joint[i]), 0),
|
||||
texelFetch(skinning_tex, ivec2(3, skinning_offset + Joint[i]), 0));
|
||||
mat4 joint_matrix = mat4(
|
||||
texelFetch(skinning_tex, ivec2(0, clamp(Joint[i] + skinning_offset, 0, MAX_BONES)), 0),
|
||||
texelFetch(skinning_tex, ivec2(1, clamp(Joint[i] + skinning_offset, 0, MAX_BONES)), 0),
|
||||
texelFetch(skinning_tex, ivec2(2, clamp(Joint[i] + skinning_offset, 0, MAX_BONES)), 0),
|
||||
texelFetch(skinning_tex, ivec2(3, clamp(Joint[i] + skinning_offset, 0, MAX_BONES)), 0));
|
||||
#else
|
||||
mat4 joint_matrix = mat4(
|
||||
texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4),
|
||||
texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4 + 1),
|
||||
texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4 + 2),
|
||||
texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4 + 3));
|
||||
mat4 joint_matrix = mat4(
|
||||
texelFetch(skinning_tex, clamp(Joint[i] + skinning_offset, 0, MAX_BONES) * 4),
|
||||
texelFetch(skinning_tex, clamp(Joint[i] + skinning_offset, 0, MAX_BONES) * 4 + 1),
|
||||
texelFetch(skinning_tex, clamp(Joint[i] + skinning_offset, 0, MAX_BONES) * 4 + 2),
|
||||
texelFetch(skinning_tex, clamp(Joint[i] + skinning_offset, 0, MAX_BONES) * 4 + 3));
|
||||
#endif
|
||||
skinned_position += Weight[i] * joint_matrix * idle_position;
|
||||
skinned_normal += Weight[i] * joint_matrix * idle_normal;
|
||||
skinned_tangent += Weight[i] * joint_matrix * idle_tangent;
|
||||
skinned_bitangent += Weight[i] * joint_matrix * idle_bitangent;
|
||||
}
|
||||
skinned_position += Weight[i] * joint_matrix * idle_position;
|
||||
skinned_normal += Weight[i] * joint_matrix * idle_normal;
|
||||
skinned_tangent += Weight[i] * joint_matrix * idle_tangent;
|
||||
skinned_bitangent += Weight[i] * joint_matrix * idle_bitangent;
|
||||
}
|
||||
|
||||
gl_Position = ProjectionViewMatrix * ModelMatrix * skinned_position;
|
||||
|
@ -30,36 +30,23 @@ void main(void)
|
||||
{
|
||||
vec4 idle_position = vec4(Position, 1.);
|
||||
vec4 skinned_position = vec4(0.);
|
||||
if (Weight[0] < 0.01)
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
skinned_position = idle_position;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
// Logically we should break if the weight is (almost) zero
|
||||
// given the fact that it's sorted from high to low,
|
||||
// but GT240 will cause glitches
|
||||
//if (Weight[i] < 0.01)
|
||||
//{
|
||||
// break;
|
||||
//}
|
||||
#ifdef GL_ES
|
||||
mat4 joint_matrix = mat4(
|
||||
texelFetch(skinning_tex, ivec2(0, skinning_offset + Joint[i]), 0),
|
||||
texelFetch(skinning_tex, ivec2(1, skinning_offset + Joint[i]), 0),
|
||||
texelFetch(skinning_tex, ivec2(2, skinning_offset + Joint[i]), 0),
|
||||
texelFetch(skinning_tex, ivec2(3, skinning_offset + Joint[i]), 0));
|
||||
mat4 joint_matrix = mat4(
|
||||
texelFetch(skinning_tex, ivec2(0, clamp(Joint[i] + skinning_offset, 0, MAX_BONES)), 0),
|
||||
texelFetch(skinning_tex, ivec2(1, clamp(Joint[i] + skinning_offset, 0, MAX_BONES)), 0),
|
||||
texelFetch(skinning_tex, ivec2(2, clamp(Joint[i] + skinning_offset, 0, MAX_BONES)), 0),
|
||||
texelFetch(skinning_tex, ivec2(3, clamp(Joint[i] + skinning_offset, 0, MAX_BONES)), 0));
|
||||
#else
|
||||
mat4 joint_matrix = mat4(
|
||||
texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4),
|
||||
texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4 + 1),
|
||||
texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4 + 2),
|
||||
texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4 + 3));
|
||||
mat4 joint_matrix = mat4(
|
||||
texelFetch(skinning_tex, clamp(Joint[i] + skinning_offset, 0, MAX_BONES) * 4),
|
||||
texelFetch(skinning_tex, clamp(Joint[i] + skinning_offset, 0, MAX_BONES) * 4 + 1),
|
||||
texelFetch(skinning_tex, clamp(Joint[i] + skinning_offset, 0, MAX_BONES) * 4 + 2),
|
||||
texelFetch(skinning_tex, clamp(Joint[i] + skinning_offset, 0, MAX_BONES) * 4 + 3));
|
||||
#endif
|
||||
skinned_position += Weight[i] * joint_matrix * idle_position;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef VSLayer
|
||||
|
@ -1502,8 +1502,8 @@ void CSkinnedMesh::convertForSkinning()
|
||||
for (u32 j = 0; j < 4; j++)
|
||||
{
|
||||
JointInfluence influence;
|
||||
influence.joint_idx = 0;
|
||||
influence.weight = 0.0f;
|
||||
influence.joint_idx = -32768;
|
||||
influence.weight = j == 0 ? 1.0f : 0.0f;
|
||||
this_influence.push_back(influence);
|
||||
}
|
||||
float total_weight = 0.0f;
|
||||
|
@ -259,7 +259,7 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
|
||||
(!culled_for_cams[0] || !culled_for_cams[1] || !culled_for_cams[2] ||
|
||||
!culled_for_cams[3] || !culled_for_cams[4] || !culled_for_cams[5]))
|
||||
{
|
||||
skinning_offset = getSkinningOffset();
|
||||
skinning_offset = getSkinningOffset() + 1/*reserved identity matrix*/;
|
||||
if (skinning_offset + am->getTotalJoints() >
|
||||
(int)stk_config->m_max_skinning_bones)
|
||||
{
|
||||
|
@ -35,6 +35,8 @@ GLuint SharedGPUObjects::m_skinning_tex;
|
||||
GLuint SharedGPUObjects::m_skinning_buf;
|
||||
bool SharedGPUObjects::m_has_been_initialised = false;
|
||||
|
||||
#include "matrix4.h"
|
||||
|
||||
/** Initialises m_full_screen_quad_vbo.
|
||||
*/
|
||||
void SharedGPUObjects::initQuadVBO()
|
||||
@ -159,6 +161,8 @@ void SharedGPUObjects::initLightingDataUBO()
|
||||
void SharedGPUObjects::initSkinning()
|
||||
{
|
||||
glGenTextures(1, &m_skinning_tex);
|
||||
// Reserve 1 identity matrix for non-weighted vertices
|
||||
const irr::core::matrix4 m;
|
||||
int max_size = 0;
|
||||
#ifdef USE_GLES2
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_size);
|
||||
@ -180,6 +184,8 @@ void SharedGPUObjects::initSkinning()
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 16,
|
||||
stk_config->m_max_skinning_bones, 0, GL_RGBA, GL_FLOAT, NULL);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 1, GL_RGBA, GL_FLOAT,
|
||||
m.pointer());
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
#else
|
||||
|
||||
@ -195,8 +201,9 @@ void SharedGPUObjects::initSkinning()
|
||||
"max bones: %u", stk_config->m_max_skinning_bones);
|
||||
|
||||
glBindBuffer(GL_TEXTURE_BUFFER, m_skinning_buf);
|
||||
glBufferData(GL_TEXTURE_BUFFER, stk_config->m_max_skinning_bones * 64, NULL,
|
||||
GL_DYNAMIC_DRAW);
|
||||
glBufferData(GL_TEXTURE_BUFFER, stk_config->m_max_skinning_bones * 64,
|
||||
NULL, GL_DYNAMIC_DRAW);
|
||||
glBufferSubData(GL_TEXTURE_BUFFER, 0, 16 * sizeof(float), m.pointer());
|
||||
glBindTexture(GL_TEXTURE_BUFFER, m_skinning_tex);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_skinning_buf);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, 0);
|
||||
|
Loading…
Reference in New Issue
Block a user