Merge remote-tracking branch 'upstream/master' into perPlayerDifficulties
This commit is contained in:
commit
f7b22cd97c
@ -3,6 +3,7 @@ uniform mat4 ViewMatrix;
|
||||
uniform mat4 ProjectionMatrix;
|
||||
uniform mat4 InverseViewMatrix;
|
||||
uniform mat4 InverseProjectionMatrix;
|
||||
uniform mat4 ProjectionViewMatrix;
|
||||
uniform vec2 screen;
|
||||
#else
|
||||
layout (std140) uniform MatrixesData
|
||||
@ -11,6 +12,7 @@ layout (std140) uniform MatrixesData
|
||||
mat4 ProjectionMatrix;
|
||||
mat4 InverseViewMatrix;
|
||||
mat4 InverseProjectionMatrix;
|
||||
mat4 ProjectionViewMatrix;
|
||||
mat4 ShadowViewProjMatrixes[4];
|
||||
vec2 screen;
|
||||
};
|
||||
|
@ -37,7 +37,7 @@ void main()
|
||||
{
|
||||
mat4 ModelMatrix = getWorldMatrix(Origin + windDir * Color.r, Orientation, Scale);
|
||||
mat4 TransposeInverseModelView = transpose(getInverseWorldMatrix(Origin + windDir * Color.r, Orientation, Scale) * InverseViewMatrix);
|
||||
gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * vec4(Position, 1.);
|
||||
gl_Position = ProjectionViewMatrix * ModelMatrix * vec4(Position, 1.);
|
||||
nor = (TransposeInverseModelView * vec4(Normal, 0.)).xyz;
|
||||
uv = Texcoord;
|
||||
#ifdef GL_ARB_bindless_texture
|
||||
|
@ -44,7 +44,7 @@ void main(void)
|
||||
{
|
||||
mat4 ModelMatrix = getWorldMatrix(Origin, Orientation, Scale);
|
||||
mat4 TransposeInverseModelView = transpose(getInverseWorldMatrix(Origin, Orientation, Scale) * InverseViewMatrix);
|
||||
gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * vec4(Position, 1.);
|
||||
gl_Position = ProjectionViewMatrix * ModelMatrix * vec4(Position, 1.);
|
||||
nor = (TransposeInverseModelView * vec4(Normal, 0.)).xyz;
|
||||
tangent = (TransposeInverseModelView * vec4(Tangent, 1.)).xyz;
|
||||
bitangent = (TransposeInverseModelView * vec4(Bitangent, 1.)).xyz;
|
||||
|
@ -45,6 +45,6 @@ mat4 getInverseWorldMatrix(vec3 translation, vec3 rotation, vec3 scale)
|
||||
{
|
||||
mat4 result = transpose(getMatrixFromRotation(rotation));
|
||||
// FIXME: it's wrong but the fourth column is not used
|
||||
result[3].xyz -= translation;
|
||||
// result[3].xyz -= translation;
|
||||
return getScaleMatrix(1. / scale) * result;
|
||||
}
|
@ -47,6 +47,10 @@ namespace core
|
||||
template <class T>
|
||||
class CMatrix4
|
||||
{
|
||||
private:
|
||||
#if defined(WIN32) && (defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86))
|
||||
float M_raw[24];
|
||||
#endif
|
||||
public:
|
||||
|
||||
//! Constructor Flags
|
||||
@ -405,8 +409,12 @@ namespace core
|
||||
bool equals(const core::CMatrix4<T>& other, const T tolerance=(T)ROUNDING_ERROR_f64) const;
|
||||
|
||||
private:
|
||||
#if defined(WIN32) && (defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86))
|
||||
//! Matrix data, stored in row-major order
|
||||
T M[16];
|
||||
T* M = (T*)((uintptr_t)&M_raw[4] & ~0xF);
|
||||
#else
|
||||
T M[16];
|
||||
#endif
|
||||
#if defined ( USE_MATRIX_TEST )
|
||||
//! Flag is this matrix is identity matrix
|
||||
mutable u32 definitelyIdentityMatrix;
|
||||
@ -661,6 +669,58 @@ namespace core
|
||||
const T *m1 = other_a.M;
|
||||
const T *m2 = other_b.M;
|
||||
|
||||
#if defined(WIN32) && (defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86))
|
||||
// From http://drrobsjournal.blogspot.fr/2012/10/fast-simd-4x4-matrix-multiplication.html
|
||||
// Use unaligned load/store
|
||||
|
||||
const float *matA = other_a.pointer();
|
||||
|
||||
const __m128 a = _mm_load_ps(matA); // First row
|
||||
const __m128 b = _mm_load_ps(&matA[4]); // Second row
|
||||
const __m128 c = _mm_load_ps(&matA[8]); // Third row
|
||||
const __m128 d = _mm_load_ps(&matA[12]); // Fourth row
|
||||
|
||||
__m128 t1 = _mm_set1_ps(m2[0]);
|
||||
__m128 t2 = _mm_mul_ps(a, t1);
|
||||
t1 = _mm_set1_ps(m2[1]);
|
||||
t2 = _mm_add_ps(_mm_mul_ps(b, t1), t2);
|
||||
t1 = _mm_set1_ps(m2[2]);
|
||||
t2 = _mm_add_ps(_mm_mul_ps(c, t1), t2);
|
||||
t1 = _mm_set1_ps(m2[3]);
|
||||
t2 = _mm_add_ps(_mm_mul_ps(d, t1), t2);
|
||||
_mm_store_ps(&M[0], t2);
|
||||
|
||||
t1 = _mm_set1_ps(m2[4]);
|
||||
t2 = _mm_mul_ps(a, t1);
|
||||
t1 = _mm_set1_ps(m2[5]);
|
||||
t2 = _mm_add_ps(_mm_mul_ps(b, t1), t2);
|
||||
t1 = _mm_set1_ps(m2[6]);
|
||||
t2 = _mm_add_ps(_mm_mul_ps(c, t1), t2);
|
||||
t1 = _mm_set1_ps(m2[7]);
|
||||
t2 = _mm_add_ps(_mm_mul_ps(d, t1), t2);
|
||||
_mm_store_ps(&M[4], t2);
|
||||
|
||||
t1 = _mm_set1_ps(m2[8]);
|
||||
t2 = _mm_mul_ps(a, t1);
|
||||
t1 = _mm_set1_ps(m2[9]);
|
||||
t2 = _mm_add_ps(_mm_mul_ps(b, t1), t2);
|
||||
t1 = _mm_set1_ps(m2[10]);
|
||||
t2 = _mm_add_ps(_mm_mul_ps(c, t1), t2);
|
||||
t1 = _mm_set1_ps(m2[11]);
|
||||
t2 = _mm_add_ps(_mm_mul_ps(d, t1), t2);
|
||||
_mm_store_ps(&M[8], t2);
|
||||
|
||||
t1 = _mm_set1_ps(m2[12]);
|
||||
t2 = _mm_mul_ps(a, t1);
|
||||
t1 = _mm_set1_ps(m2[13]);
|
||||
t2 = _mm_add_ps(_mm_mul_ps(b, t1), t2);
|
||||
t1 = _mm_set1_ps(m2[14]);
|
||||
t2 = _mm_add_ps(_mm_mul_ps(c, t1), t2);
|
||||
t1 = _mm_set1_ps(m2[15]);
|
||||
t2 = _mm_add_ps(_mm_mul_ps(d, t1), t2);
|
||||
_mm_store_ps(&M[12], t2);
|
||||
#else
|
||||
|
||||
M[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3];
|
||||
M[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3];
|
||||
M[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3];
|
||||
@ -682,6 +742,7 @@ namespace core
|
||||
M[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15];
|
||||
#if defined ( USE_MATRIX_TEST )
|
||||
definitelyIdentityMatrix=false;
|
||||
#endif
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
@ -1329,9 +1390,9 @@ namespace core
|
||||
float *dst = (float*)out.pointer();
|
||||
// from http://www.intel.com/design/pentiumiii/sml/245043.htm
|
||||
{
|
||||
__m128 minor0, minor1, minor2, minor3;
|
||||
__m128 row0, row1, row2, row3;
|
||||
__m128 det, tmp1;
|
||||
__m128 minor0 = {}, minor1 = {}, minor2 = {}, minor3 = {};
|
||||
__m128 row0 = {}, row1 = {}, row2 = {}, row3 = {};
|
||||
__m128 det = {}, tmp1 = {};
|
||||
tmp1 = _mm_loadh_pi(_mm_loadl_pi(tmp1, (__m64*)(src)), (__m64*)(src + 4));
|
||||
row1 = _mm_loadh_pi(_mm_loadl_pi(row1, (__m64*)(src + 8)), (__m64*)(src + 12));
|
||||
row0 = _mm_shuffle_ps(tmp1, row1, 0x88);
|
||||
|
@ -1,7 +1,13 @@
|
||||
#ifndef GL_HEADER_HPP
|
||||
#define GL_HEADER_HPP
|
||||
|
||||
#define GLEW_STATIC
|
||||
#if defined(WIN32) && !defined(__CYGWIN__)
|
||||
// glew in the binary distribution only comes as dynamic library.
|
||||
# undef GLEW_STATIC
|
||||
#else
|
||||
# define GLEW_STATIC
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include <GL/glew.h>
|
||||
}
|
||||
|
@ -98,7 +98,10 @@ void initGL()
|
||||
if (is_gl_init)
|
||||
return;
|
||||
is_gl_init = true;
|
||||
glewInit();
|
||||
glewExperimental = GL_TRUE;
|
||||
GLenum err = glewInit();
|
||||
if (GLEW_OK != err)
|
||||
Log::fatal("GLEW", "Glew initialisation failed with error %s", glewGetErrorString(err));
|
||||
#ifdef ARB_DEBUG_OUTPUT
|
||||
if (glDebugMessageCallbackARB)
|
||||
glDebugMessageCallbackARB((GLDEBUGPROCARB)debugCallback, NULL);
|
||||
@ -394,340 +397,6 @@ void setTexture(unsigned TextureUnit, GLuint TextureId, GLenum MagFilter, GLenum
|
||||
glGetError();
|
||||
}
|
||||
|
||||
VAOManager::VAOManager()
|
||||
{
|
||||
vao[0] = vao[1] = vao[2] = 0;
|
||||
vbo[0] = vbo[1] = vbo[2] = 0;
|
||||
ibo[0] = ibo[1] = ibo[2] = 0;
|
||||
vtx_cnt[0] = vtx_cnt[1] = vtx_cnt[2] = 0;
|
||||
idx_cnt[0] = idx_cnt[1] = idx_cnt[2] = 0;
|
||||
vtx_mirror[0] = vtx_mirror[1] = vtx_mirror[2] = NULL;
|
||||
idx_mirror[0] = idx_mirror[1] = idx_mirror[2] = NULL;
|
||||
instance_count[0] = 0;
|
||||
|
||||
for (unsigned i = 0; i < InstanceTypeCount; i++)
|
||||
{
|
||||
glGenBuffers(1, &instance_vbo[i]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[i]);
|
||||
#ifdef Buffer_Storage
|
||||
if (irr_driver->hasBufferStorageExtension())
|
||||
{
|
||||
glBufferStorage(GL_ARRAY_BUFFER, 10000 * sizeof(InstanceData), 0, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT);
|
||||
Ptr[i] = glMapBufferRange(GL_ARRAY_BUFFER, 0, 10000 * sizeof(InstanceData), GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
glBufferData(GL_ARRAY_BUFFER, 10000 * sizeof(InstanceData), 0, GL_STREAM_DRAW);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cleanVAOMap(std::map<std::pair<video::E_VERTEX_TYPE, InstanceType>, GLuint> Map)
|
||||
{
|
||||
std::map<std::pair<video::E_VERTEX_TYPE, InstanceType>, GLuint>::iterator It = Map.begin(), E = Map.end();
|
||||
for (; It != E; It++)
|
||||
{
|
||||
glDeleteVertexArrays(1, &(It->second));
|
||||
}
|
||||
}
|
||||
|
||||
void VAOManager::cleanInstanceVAOs()
|
||||
{
|
||||
cleanVAOMap(InstanceVAO);
|
||||
InstanceVAO.clear();
|
||||
}
|
||||
|
||||
VAOManager::~VAOManager()
|
||||
{
|
||||
cleanInstanceVAOs();
|
||||
for (unsigned i = 0; i < 3; i++)
|
||||
{
|
||||
if (vtx_mirror[i])
|
||||
free(vtx_mirror[i]);
|
||||
if (idx_mirror[i])
|
||||
free(idx_mirror[i]);
|
||||
if (vbo[i])
|
||||
glDeleteBuffers(1, &vbo[i]);
|
||||
if (ibo[i])
|
||||
glDeleteBuffers(1, &ibo[i]);
|
||||
if (vao[i])
|
||||
glDeleteVertexArrays(1, &vao[i]);
|
||||
}
|
||||
for (unsigned i = 0; i < InstanceTypeCount; i++)
|
||||
{
|
||||
glDeleteBuffers(1, &instance_vbo[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void VAOManager::regenerateBuffer(enum VTXTYPE tp)
|
||||
{
|
||||
glBindVertexArray(0);
|
||||
if (vbo[tp])
|
||||
glDeleteBuffers(1, &vbo[tp]);
|
||||
glGenBuffers(1, &vbo[tp]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo[tp]);
|
||||
#ifdef Buffer_Storage
|
||||
if (irr_driver->hasBufferStorageExtension())
|
||||
{
|
||||
glBufferStorage(GL_ARRAY_BUFFER, vtx_cnt[tp] * getVertexPitch(tp), vtx_mirror[tp], GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT);
|
||||
VBOPtr[tp] = glMapBufferRange(GL_ARRAY_BUFFER, 0, vtx_cnt[tp] * getVertexPitch(tp), GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
glBufferData(GL_ARRAY_BUFFER, vtx_cnt[tp] * getVertexPitch(tp), vtx_mirror[tp], GL_DYNAMIC_DRAW);
|
||||
|
||||
|
||||
if (ibo[tp])
|
||||
glDeleteBuffers(1, &ibo[tp]);
|
||||
glGenBuffers(1, &ibo[tp]);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[tp]);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(u16)* idx_cnt[tp], idx_mirror[tp], GL_DYNAMIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
void VAOManager::regenerateVAO(enum VTXTYPE tp)
|
||||
{
|
||||
if (vao[tp])
|
||||
glDeleteVertexArrays(1, &vao[tp]);
|
||||
glGenVertexArrays(1, &vao[tp]);
|
||||
glBindVertexArray(vao[tp]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo[tp]);
|
||||
switch (tp)
|
||||
{
|
||||
case VTXTYPE_STANDARD:
|
||||
// Position
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0);
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12);
|
||||
// Color
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24);
|
||||
// Texcoord
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28);
|
||||
break;
|
||||
case VTXTYPE_TCOORD:
|
||||
// Position
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0);
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12);
|
||||
// Color
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24);
|
||||
// Texcoord
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28);
|
||||
// SecondTexcoord
|
||||
glEnableVertexAttribArray(4);
|
||||
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)36);
|
||||
break;
|
||||
case VTXTYPE_TANGENT:
|
||||
// Position
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0);
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12);
|
||||
// Color
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24);
|
||||
// Texcoord
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28);
|
||||
// Tangent
|
||||
glEnableVertexAttribArray(5);
|
||||
glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)36);
|
||||
// Bitangent
|
||||
glEnableVertexAttribArray(6);
|
||||
glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)48);
|
||||
break;
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[tp]);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void VAOManager::regenerateInstancedVAO()
|
||||
{
|
||||
cleanInstanceVAOs();
|
||||
|
||||
enum video::E_VERTEX_TYPE IrrVT[] = { video::EVT_STANDARD, video::EVT_2TCOORDS, video::EVT_TANGENTS };
|
||||
for (unsigned i = 0; i < VTXTYPE_COUNT; i++)
|
||||
{
|
||||
video::E_VERTEX_TYPE tp = IrrVT[i];
|
||||
if (!vbo[tp] || !ibo[tp])
|
||||
continue;
|
||||
GLuint vao = createVAO(vbo[tp], ibo[tp], tp);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeDefault]);
|
||||
|
||||
glEnableVertexAttribArray(7);
|
||||
glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), 0);
|
||||
glVertexAttribDivisor(7, 1);
|
||||
glEnableVertexAttribArray(8);
|
||||
glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(3 * sizeof(float)));
|
||||
glVertexAttribDivisor(8, 1);
|
||||
glEnableVertexAttribArray(9);
|
||||
glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(6 * sizeof(float)));
|
||||
glVertexAttribDivisor(9, 1);
|
||||
glEnableVertexAttribArray(10);
|
||||
glVertexAttribIPointer(10, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float)));
|
||||
glVertexAttribDivisor(10, 1);
|
||||
glEnableVertexAttribArray(11);
|
||||
glVertexAttribIPointer(11, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float) + 2 * sizeof(unsigned)));
|
||||
glVertexAttribDivisor(11, 1);
|
||||
InstanceVAO[std::pair<video::E_VERTEX_TYPE, InstanceType>(tp, InstanceTypeDefault)] = vao;
|
||||
|
||||
vao = createVAO(vbo[tp], ibo[tp], tp);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeShadow]);
|
||||
|
||||
glEnableVertexAttribArray(7);
|
||||
glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), 0);
|
||||
glVertexAttribDivisor(7, 1);
|
||||
glEnableVertexAttribArray(8);
|
||||
glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(3 * sizeof(float)));
|
||||
glVertexAttribDivisor(8, 1);
|
||||
glEnableVertexAttribArray(9);
|
||||
glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(6 * sizeof(float)));
|
||||
glVertexAttribDivisor(9, 1);
|
||||
glEnableVertexAttribArray(10);
|
||||
glVertexAttribIPointer(10, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float)));
|
||||
glVertexAttribDivisor(10, 1);
|
||||
glEnableVertexAttribArray(11);
|
||||
glVertexAttribIPointer(11, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float) + 2 * sizeof(unsigned)));
|
||||
glVertexAttribDivisor(11, 1);
|
||||
InstanceVAO[std::pair<video::E_VERTEX_TYPE, InstanceType>(tp, InstanceTypeShadow)] = vao;
|
||||
|
||||
vao = createVAO(vbo[tp], ibo[tp], tp);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeRSM]);
|
||||
|
||||
glEnableVertexAttribArray(7);
|
||||
glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), 0);
|
||||
glVertexAttribDivisor(7, 1);
|
||||
glEnableVertexAttribArray(8);
|
||||
glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(3 * sizeof(float)));
|
||||
glVertexAttribDivisor(8, 1);
|
||||
glEnableVertexAttribArray(9);
|
||||
glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(6 * sizeof(float)));
|
||||
glVertexAttribDivisor(9, 1);
|
||||
glEnableVertexAttribArray(10);
|
||||
glVertexAttribIPointer(10, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float)));
|
||||
glVertexAttribDivisor(10, 1);
|
||||
glEnableVertexAttribArray(11);
|
||||
glVertexAttribIPointer(11, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float) + 2 * sizeof(unsigned)));
|
||||
glVertexAttribDivisor(11, 1);
|
||||
InstanceVAO[std::pair<video::E_VERTEX_TYPE, InstanceType>(tp, InstanceTypeRSM)] = vao;
|
||||
|
||||
vao = createVAO(vbo[tp], ibo[tp], tp);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeGlow]);
|
||||
|
||||
glEnableVertexAttribArray(7);
|
||||
glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(GlowInstanceData), 0);
|
||||
glVertexAttribDivisor(7, 1);
|
||||
glEnableVertexAttribArray(8);
|
||||
glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(GlowInstanceData), (GLvoid*)(3 * sizeof(float)));
|
||||
glVertexAttribDivisor(8, 1);
|
||||
glEnableVertexAttribArray(9);
|
||||
glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(GlowInstanceData), (GLvoid*)(6 * sizeof(float)));
|
||||
glVertexAttribDivisor(9, 1);
|
||||
glEnableVertexAttribArray(12);
|
||||
glVertexAttribPointer(12, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(GlowInstanceData), (GLvoid*)(9 * sizeof(float)));
|
||||
glVertexAttribDivisor(12, 1);
|
||||
InstanceVAO[std::pair<video::E_VERTEX_TYPE, InstanceType>(tp, InstanceTypeGlow)] = vao;
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
size_t VAOManager::getVertexPitch(enum VTXTYPE tp) const
|
||||
{
|
||||
switch (tp)
|
||||
{
|
||||
case VTXTYPE_STANDARD:
|
||||
return getVertexPitchFromType(video::EVT_STANDARD);
|
||||
case VTXTYPE_TCOORD:
|
||||
return getVertexPitchFromType(video::EVT_2TCOORDS);
|
||||
case VTXTYPE_TANGENT:
|
||||
return getVertexPitchFromType(video::EVT_TANGENTS);
|
||||
default:
|
||||
assert(0 && "Wrong vtxtype");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
VAOManager::VTXTYPE VAOManager::getVTXTYPE(video::E_VERTEX_TYPE type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
default:
|
||||
assert(0 && "Wrong vtxtype");
|
||||
case video::EVT_STANDARD:
|
||||
return VTXTYPE_STANDARD;
|
||||
case video::EVT_2TCOORDS:
|
||||
return VTXTYPE_TCOORD;
|
||||
case video::EVT_TANGENTS:
|
||||
return VTXTYPE_TANGENT;
|
||||
}
|
||||
};
|
||||
|
||||
void VAOManager::append(scene::IMeshBuffer *mb, VTXTYPE tp)
|
||||
{
|
||||
size_t old_vtx_cnt = vtx_cnt[tp];
|
||||
vtx_cnt[tp] += mb->getVertexCount();
|
||||
vtx_mirror[tp] = realloc(vtx_mirror[tp], vtx_cnt[tp] * getVertexPitch(tp));
|
||||
intptr_t dstptr = (intptr_t)vtx_mirror[tp] + (old_vtx_cnt * getVertexPitch(tp));
|
||||
memcpy((void *)dstptr, mb->getVertices(), mb->getVertexCount() * getVertexPitch(tp));
|
||||
mappedBaseVertex[tp][mb] = old_vtx_cnt;
|
||||
|
||||
size_t old_idx_cnt = idx_cnt[tp];
|
||||
idx_cnt[tp] += mb->getIndexCount();
|
||||
idx_mirror[tp] = realloc(idx_mirror[tp], idx_cnt[tp] * sizeof(u16));
|
||||
|
||||
dstptr = (intptr_t)idx_mirror[tp] + (old_idx_cnt * sizeof(u16));
|
||||
memcpy((void *)dstptr, mb->getIndices(), mb->getIndexCount() * sizeof(u16));
|
||||
mappedBaseIndex[tp][mb] = old_idx_cnt * sizeof(u16);
|
||||
}
|
||||
|
||||
std::pair<unsigned, unsigned> VAOManager::getBase(scene::IMeshBuffer *mb)
|
||||
{
|
||||
VTXTYPE tp = getVTXTYPE(mb->getVertexType());
|
||||
if (mappedBaseVertex[tp].find(mb) == mappedBaseVertex[tp].end())
|
||||
{
|
||||
assert(mappedBaseIndex[tp].find(mb) == mappedBaseIndex[tp].end());
|
||||
storedCPUBuffer[tp].push_back(mb);
|
||||
append(mb, tp);
|
||||
regenerateBuffer(tp);
|
||||
regenerateVAO(tp);
|
||||
regenerateInstancedVAO();
|
||||
}
|
||||
|
||||
std::map<scene::IMeshBuffer*, unsigned>::iterator It;
|
||||
It = mappedBaseVertex[tp].find(mb);
|
||||
assert(It != mappedBaseVertex[tp].end());
|
||||
unsigned vtx = It->second;
|
||||
It = mappedBaseIndex[tp].find(mb);
|
||||
assert(It != mappedBaseIndex[tp].end());
|
||||
return std::pair<unsigned, unsigned>(vtx, It->second);
|
||||
}
|
||||
|
||||
size_t VAOManager::appendInstance(enum InstanceType, const std::vector<InstanceData> &instance_data)
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[0]);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, instance_count[0] * sizeof(InstanceData), instance_data.size() * sizeof(InstanceData), instance_data.data());
|
||||
size_t result = instance_count[0];
|
||||
instance_count[0] += instance_data.size();
|
||||
return result;
|
||||
}
|
||||
|
||||
ScopedGPUTimer::ScopedGPUTimer(GPUTimer &t) : timer(t)
|
||||
{
|
||||
if (!UserConfigParams::m_profiler_enabled) return;
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <vector>
|
||||
#include "irr_driver.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
#include "vaomanager.hpp"
|
||||
|
||||
void initGL();
|
||||
GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount);
|
||||
@ -139,110 +139,6 @@ void compressTexture(irr::video::ITexture *tex, bool srgb, bool premul_alpha = f
|
||||
bool loadCompressedTexture(const std::string& compressed_tex);
|
||||
void saveCompressedTexture(const std::string& compressed_tex);
|
||||
|
||||
enum InstanceType
|
||||
{
|
||||
InstanceTypeDefault,
|
||||
InstanceTypeShadow,
|
||||
InstanceTypeRSM,
|
||||
InstanceTypeGlow,
|
||||
InstanceTypeCount,
|
||||
};
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma pack(push, 1)
|
||||
#endif
|
||||
struct InstanceData
|
||||
{
|
||||
struct
|
||||
{
|
||||
float X;
|
||||
float Y;
|
||||
float Z;
|
||||
} Origin;
|
||||
struct
|
||||
{
|
||||
float X;
|
||||
float Y;
|
||||
float Z;
|
||||
} Orientation;
|
||||
struct
|
||||
{
|
||||
float X;
|
||||
float Y;
|
||||
float Z;
|
||||
} Scale;
|
||||
uint64_t Texture;
|
||||
uint64_t SecondTexture;
|
||||
#ifdef WIN32
|
||||
};
|
||||
#else
|
||||
} __attribute__((packed));
|
||||
#endif
|
||||
|
||||
struct GlowInstanceData
|
||||
{
|
||||
struct
|
||||
{
|
||||
float X;
|
||||
float Y;
|
||||
float Z;
|
||||
} Origin;
|
||||
struct
|
||||
{
|
||||
float X;
|
||||
float Y;
|
||||
float Z;
|
||||
} Orientation;
|
||||
struct
|
||||
{
|
||||
float X;
|
||||
float Y;
|
||||
float Z;
|
||||
} Scale;
|
||||
unsigned Color;
|
||||
#ifdef WIN32
|
||||
};
|
||||
#else
|
||||
} __attribute__((packed));
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
class VAOManager : public Singleton<VAOManager>
|
||||
{
|
||||
enum VTXTYPE { VTXTYPE_STANDARD, VTXTYPE_TCOORD, VTXTYPE_TANGENT, VTXTYPE_COUNT };
|
||||
GLuint vbo[VTXTYPE_COUNT], ibo[VTXTYPE_COUNT], vao[VTXTYPE_COUNT];
|
||||
GLuint instance_vbo[InstanceTypeCount];
|
||||
size_t instance_count[InstanceTypeCount];
|
||||
void *Ptr[InstanceTypeCount];
|
||||
void *VBOPtr[VTXTYPE_COUNT];
|
||||
std::vector<scene::IMeshBuffer *> storedCPUBuffer[VTXTYPE_COUNT];
|
||||
void *vtx_mirror[VTXTYPE_COUNT], *idx_mirror[VTXTYPE_COUNT];
|
||||
size_t vtx_cnt[VTXTYPE_COUNT], idx_cnt[VTXTYPE_COUNT];
|
||||
std::map<scene::IMeshBuffer*, unsigned> mappedBaseVertex[VTXTYPE_COUNT], mappedBaseIndex[VTXTYPE_COUNT];
|
||||
std::map<std::pair<video::E_VERTEX_TYPE, InstanceType>, GLuint> InstanceVAO;
|
||||
|
||||
void cleanInstanceVAOs();
|
||||
void regenerateBuffer(enum VTXTYPE);
|
||||
void regenerateVAO(enum VTXTYPE);
|
||||
void regenerateInstancedVAO();
|
||||
size_t getVertexPitch(enum VTXTYPE) const;
|
||||
VTXTYPE getVTXTYPE(video::E_VERTEX_TYPE type);
|
||||
void append(scene::IMeshBuffer *, VTXTYPE tp);
|
||||
public:
|
||||
VAOManager();
|
||||
std::pair<unsigned, unsigned> getBase(scene::IMeshBuffer *);
|
||||
size_t appendInstance(enum InstanceType, const std::vector<InstanceData> &instance_data);
|
||||
GLuint getInstanceBuffer(InstanceType it) { return instance_vbo[it]; }
|
||||
void *getInstanceBufferPtr(InstanceType it) { return Ptr[it]; }
|
||||
unsigned getVBO(video::E_VERTEX_TYPE type) { return vbo[getVTXTYPE(type)]; }
|
||||
void *getVBOPtr(video::E_VERTEX_TYPE type) { return VBOPtr[getVTXTYPE(type)]; }
|
||||
unsigned getVAO(video::E_VERTEX_TYPE type) { return vao[getVTXTYPE(type)]; }
|
||||
unsigned getInstanceVAO(video::E_VERTEX_TYPE vt, enum InstanceType it) { return InstanceVAO[std::pair<video::E_VERTEX_TYPE, InstanceType>(vt, it)]; }
|
||||
~VAOManager();
|
||||
};
|
||||
|
||||
void draw3DLine(const core::vector3df& start,
|
||||
const core::vector3df& end, irr::video::SColor color);
|
||||
|
||||
|
@ -112,6 +112,10 @@ IrrDriver::IrrDriver()
|
||||
m_mipviz = m_wireframe = m_normals = m_ssaoviz = \
|
||||
m_lightviz = m_shadowviz = m_distortviz = m_rsm = m_rh = m_gi = false;
|
||||
SkyboxCubeMap = m_last_light_bucket_distance = 0;
|
||||
m_shadow_camnodes[0] = NULL;
|
||||
m_shadow_camnodes[1] = NULL;
|
||||
m_shadow_camnodes[2] = NULL;
|
||||
m_shadow_camnodes[3] = NULL;
|
||||
memset(object_count, 0, sizeof(object_count));
|
||||
} // IrrDriver
|
||||
|
||||
@ -1738,17 +1742,23 @@ void IrrDriver::displayFPS()
|
||||
if (low > kilotris) low = kilotris;
|
||||
if (high < kilotris) high = kilotris;
|
||||
|
||||
static char buffer[128];
|
||||
core::stringw fpsString;
|
||||
|
||||
if (UserConfigParams::m_artist_debug_mode)
|
||||
{
|
||||
sprintf(
|
||||
buffer, "FPS: %i/%i/%i - PolyCount (Solid:%d Shadows:%d) - LightDst : ~%d",
|
||||
min, fps, max,
|
||||
poly_count[SOLID_NORMAL_AND_DEPTH_PASS],
|
||||
poly_count[SHADOW_PASS],
|
||||
m_last_light_bucket_distance
|
||||
);
|
||||
fpsString += _("FPS: ");
|
||||
fpsString += core::stringw(min);
|
||||
fpsString += _("/");
|
||||
fpsString += core::stringw(fps);
|
||||
fpsString += _("/");
|
||||
fpsString += core::stringw(max);
|
||||
fpsString += _(" PolyCount: ");
|
||||
fpsString += _(" (Solid) ");
|
||||
fpsString += core::stringw(poly_count[SOLID_NORMAL_AND_DEPTH_PASS]);
|
||||
fpsString += _(" (Shadows) ");
|
||||
fpsString += core::stringw(poly_count[SHADOW_PASS]);
|
||||
fpsString += _(" LightDist: ");
|
||||
fpsString += core::stringw(m_last_light_bucket_distance);
|
||||
poly_count[SOLID_NORMAL_AND_DEPTH_PASS] = 0;
|
||||
poly_count[SHADOW_PASS] = 0;
|
||||
object_count[SOLID_NORMAL_AND_DEPTH_PASS] = 0;
|
||||
@ -1757,12 +1767,17 @@ void IrrDriver::displayFPS()
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(buffer, "FPS: %i/%i/%i - %i KTris", min, fps, max,
|
||||
(int)roundf(kilotris));
|
||||
fpsString += _("FPS: ");
|
||||
fpsString += core::stringw(min);
|
||||
fpsString += _("/");
|
||||
fpsString += core::stringw(fps);
|
||||
fpsString += _("/");
|
||||
fpsString += core::stringw(max);
|
||||
fpsString += _(" - ");
|
||||
fpsString += core::stringw((int)roundf(kilotris));
|
||||
fpsString += _("KTris");
|
||||
}
|
||||
|
||||
core::stringw fpsString = buffer;
|
||||
|
||||
static video::SColor fpsColor = video::SColor(255, 0, 0, 0);
|
||||
|
||||
font->draw( fpsString.c_str(), core::rect< s32 >(100,0,400,50), fpsColor, false );
|
||||
|
@ -419,7 +419,7 @@ private:
|
||||
void renderRSM();
|
||||
void renderGlow(std::vector<GlowData>& glows);
|
||||
void renderSSAO();
|
||||
void renderLights(unsigned pointlightCount);
|
||||
void renderLights(unsigned pointlightCount, bool hasShadow);
|
||||
void renderShadowsDebug();
|
||||
void doScreenShot();
|
||||
void PrepareDrawCalls(scene::ICameraSceneNode *camnode);
|
||||
|
@ -143,11 +143,11 @@ void LODNode::updateVisibility(bool* shown)
|
||||
if (m_nodes.size() == 0) return;
|
||||
|
||||
int level = getLevel();
|
||||
for (int i = 0; i < m_nodes.size(); i++)
|
||||
for (size_t i = 0; i < m_nodes.size(); i++)
|
||||
{
|
||||
m_nodes[i]->setVisible(i == level);
|
||||
if (i == level && shown != NULL)
|
||||
*shown = level;
|
||||
*shown = (i > 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -311,7 +311,7 @@ void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned po
|
||||
// Lights
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- Light", 0x00, 0xFF, 0x00);
|
||||
renderLights(pointlightcount);
|
||||
renderLights(pointlightcount, hasShadow);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
|
||||
@ -597,11 +597,12 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz
|
||||
};
|
||||
|
||||
|
||||
float tmp[16 * 8 + 2];
|
||||
float tmp[16 * 9 + 2];
|
||||
memcpy(tmp, irr_driver->getViewMatrix().pointer(), 16 * sizeof(float));
|
||||
memcpy(&tmp[16], irr_driver->getProjMatrix().pointer(), 16 * sizeof(float));
|
||||
memcpy(&tmp[32], irr_driver->getInvViewMatrix().pointer(), 16 * sizeof(float));
|
||||
memcpy(&tmp[48], irr_driver->getInvProjMatrix().pointer(), 16 * sizeof(float));
|
||||
memcpy(&tmp[64], irr_driver->getProjViewMatrix().pointer(), 16 * sizeof(float));
|
||||
|
||||
const core::matrix4 &SunCamViewMatrix = m_suncam->getViewMatrix();
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
@ -723,13 +724,13 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz
|
||||
|
||||
size_t size = irr_driver->getShadowViewProj().size();
|
||||
for (unsigned i = 0; i < size; i++)
|
||||
memcpy(&tmp[16 * i + 64], irr_driver->getShadowViewProj()[i].pointer(), 16 * sizeof(float));
|
||||
memcpy(&tmp[16 * i + 80], irr_driver->getShadowViewProj()[i].pointer(), 16 * sizeof(float));
|
||||
}
|
||||
|
||||
tmp[128] = float(width);
|
||||
tmp[129] = float(height);
|
||||
tmp[144] = float(width);
|
||||
tmp[145] = float(height);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, SharedObject::ViewProjectionMatrixesUBO);
|
||||
glBufferSubData(GL_UNIFORM_BUFFER, 0, (16 * 8 + 2) * sizeof(float), tmp);
|
||||
glBufferSubData(GL_UNIFORM_BUFFER, 0, (16 * 9 + 2) * sizeof(float), tmp);
|
||||
}
|
||||
|
||||
|
||||
|
@ -423,7 +423,7 @@ void IrrDriver::renderSolidSecondPass()
|
||||
TexUnit(2, true),
|
||||
TexUnit(3, true),
|
||||
TexUnit(4, true),
|
||||
TexUnit(5, true)
|
||||
TexUnit(0, true)
|
||||
), ListMatSplatting::getInstance()->SolidPass, createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex);
|
||||
renderMeshes2ndPass<MeshShader::SphereMapShader, video::EVT_STANDARD, 2, 1>(TexUnits(
|
||||
TexUnit(0, true)
|
||||
|
@ -126,10 +126,10 @@ unsigned IrrDriver::UpdateLightsInfo(scene::ICameraSceneNode * const camnode, fl
|
||||
return lightnum;
|
||||
}
|
||||
|
||||
void IrrDriver::renderLights(unsigned pointlightcount)
|
||||
void IrrDriver::renderLights(unsigned pointlightcount, bool hasShadow)
|
||||
{
|
||||
//RH
|
||||
if (UserConfigParams::m_gi)
|
||||
if (UserConfigParams::m_gi && UserConfigParams::m_shadows && hasShadow)
|
||||
{
|
||||
ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_RH));
|
||||
glDisable(GL_BLEND);
|
||||
@ -171,7 +171,7 @@ void IrrDriver::renderLights(unsigned pointlightcount)
|
||||
return;
|
||||
|
||||
m_rtts->getFBO(FBO_DIFFUSE).Bind();
|
||||
if (UserConfigParams::m_gi)
|
||||
if (UserConfigParams::m_gi && UserConfigParams::m_shadows && hasShadow)
|
||||
{
|
||||
ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_GI));
|
||||
m_post_processing->renderGI(rh_matrix, rh_extend, m_rtts->getRH().getRTT()[0], m_rtts->getRH().getRTT()[1], m_rtts->getRH().getRTT()[2]);
|
||||
|
@ -291,7 +291,7 @@ static void initShadowVPMUBO()
|
||||
{
|
||||
glGenBuffers(1, &SharedObject::ViewProjectionMatrixesUBO);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, SharedObject::ViewProjectionMatrixesUBO);
|
||||
glBufferData(GL_UNIFORM_BUFFER, (16 * 8 + 2) * sizeof(float), 0, GL_STREAM_DRAW);
|
||||
glBufferData(GL_UNIFORM_BUFFER, (16 * 9 + 2) * sizeof(float), 0, GL_STREAM_DRAW);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,8 @@ const core::vector3df& rotation,
|
||||
const core::vector3df& scale) :
|
||||
CAnimatedMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale)
|
||||
{
|
||||
firstTime = true;
|
||||
isGLInitialized = false;
|
||||
isMaterialInitialized = false;
|
||||
}
|
||||
|
||||
void STKAnimatedMesh::cleanGLMeshes()
|
||||
@ -33,8 +34,6 @@ void STKAnimatedMesh::cleanGLMeshes()
|
||||
glDeleteVertexArrays(1, &(mesh.vao));
|
||||
glDeleteBuffers(1, &(mesh.vertex_buffer));
|
||||
glDeleteBuffers(1, &(mesh.index_buffer));
|
||||
if (mesh.instance_buffer)
|
||||
glDeleteBuffers(1, &(mesh.instance_buffer));
|
||||
#ifdef Bindless_Texture_Support
|
||||
for (unsigned j = 0; j < 6; j++)
|
||||
{
|
||||
@ -47,16 +46,16 @@ void STKAnimatedMesh::cleanGLMeshes()
|
||||
|
||||
void STKAnimatedMesh::setMesh(scene::IAnimatedMesh* mesh)
|
||||
{
|
||||
firstTime = true;
|
||||
isGLInitialized = false;
|
||||
isMaterialInitialized = false;
|
||||
GLmeshes.clear();
|
||||
for (unsigned i = 0; i < MAT_COUNT; i++)
|
||||
MeshSolidMaterial[i].clearWithoutDeleting();
|
||||
CAnimatedMeshSceneNode::setMesh(mesh);
|
||||
}
|
||||
|
||||
void STKAnimatedMesh::update()
|
||||
void STKAnimatedMesh::updateNoGL()
|
||||
{
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
scene::IMesh* m = getMeshForCurrentFrame();
|
||||
|
||||
if (m)
|
||||
@ -67,8 +66,9 @@ void STKAnimatedMesh::update()
|
||||
return;
|
||||
}
|
||||
|
||||
if (firstTime)
|
||||
if (!isMaterialInitialized)
|
||||
{
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
for (u32 i = 0; i < m->getMeshBufferCount(); ++i)
|
||||
{
|
||||
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
|
||||
@ -100,6 +100,32 @@ void STKAnimatedMesh::update()
|
||||
{
|
||||
MeshMaterial MatType = MaterialTypeToMeshMaterial(type, mb->getVertexType());
|
||||
MeshSolidMaterial[MatType].push_back(&mesh);
|
||||
}
|
||||
}
|
||||
isMaterialInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
void STKAnimatedMesh::updateGL()
|
||||
{
|
||||
|
||||
scene::IMesh* m = getMeshForCurrentFrame();
|
||||
|
||||
if (!isGLInitialized)
|
||||
{
|
||||
for (u32 i = 0; i < m->getMeshBufferCount(); ++i)
|
||||
{
|
||||
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
|
||||
if (!mb)
|
||||
continue;
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
video::E_MATERIAL_TYPE type = mb->getMaterial().MaterialType;
|
||||
video::IMaterialRenderer* rnd = driver->getMaterialRenderer(type);
|
||||
GLMesh &mesh = GLmeshes[i];
|
||||
|
||||
if (!rnd->isTransparent())
|
||||
{
|
||||
MeshMaterial MatType = MaterialTypeToMeshMaterial(type, mb->getVertexType());
|
||||
InitTextures(mesh, MatType);
|
||||
}
|
||||
|
||||
@ -116,8 +142,8 @@ void STKAnimatedMesh::update()
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
}
|
||||
isGLInitialized = true;
|
||||
}
|
||||
firstTime = false;
|
||||
|
||||
for (u32 i = 0; i<m->getMeshBufferCount(); ++i)
|
||||
{
|
||||
@ -163,71 +189,6 @@ void STKAnimatedMesh::render()
|
||||
|
||||
++PassCount;
|
||||
|
||||
update();
|
||||
|
||||
/* if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS || irr_driver->getPhase() == SHADOW_PASS)
|
||||
{
|
||||
ModelViewProjectionMatrix = computeMVP(AbsoluteTransformation);
|
||||
core::matrix4 invmodel;
|
||||
AbsoluteTransformation.getInverse(invmodel);
|
||||
|
||||
GLMesh* mesh;
|
||||
for_in(mesh, MeshSolidMaterial[MAT_DEFAULT])
|
||||
pushVector(ListMatDefault::getInstance(), mesh, AbsoluteTransformation, invmodel, mesh->TextureMatrix);
|
||||
|
||||
for_in(mesh, MeshSolidMaterial[MAT_ALPHA_REF])
|
||||
pushVector(ListMatAlphaRef::getInstance(), mesh, AbsoluteTransformation, invmodel, mesh->TextureMatrix);
|
||||
|
||||
for_in(mesh, MeshSolidMaterial[MAT_DETAIL])
|
||||
pushVector(ListMatDetails::getInstance(), mesh, AbsoluteTransformation, invmodel, mesh->TextureMatrix);
|
||||
|
||||
for_in(mesh, MeshSolidMaterial[MAT_UNLIT])
|
||||
pushVector(ListMatUnlit::getInstance(), mesh, AbsoluteTransformation, core::matrix4::EM4CONST_IDENTITY, mesh->TextureMatrix);
|
||||
|
||||
return;
|
||||
}*/
|
||||
|
||||
if (irr_driver->getPhase() == TRANSPARENT_PASS)
|
||||
{
|
||||
ModelViewProjectionMatrix = computeMVP(AbsoluteTransformation);
|
||||
|
||||
if (!TransparentMesh[TM_BUBBLE].empty())
|
||||
glUseProgram(MeshShader::BubbleShader::Program);
|
||||
|
||||
GLMesh* mesh;
|
||||
if (World::getWorld() && World::getWorld()->isFogEnabled())
|
||||
{
|
||||
const Track * const track = World::getWorld()->getTrack();
|
||||
|
||||
// Todo : put everything in a ubo
|
||||
const float fogmax = track->getFogMax();
|
||||
const float startH = track->getFogStartHeight();
|
||||
const float endH = track->getFogEndHeight();
|
||||
const float start = track->getFogStart();
|
||||
const float end = track->getFogEnd();
|
||||
const video::SColor tmpcol = track->getFogColor();
|
||||
|
||||
video::SColorf col(tmpcol.getRed() / 255.0f,
|
||||
tmpcol.getGreen() / 255.0f,
|
||||
tmpcol.getBlue() / 255.0f);
|
||||
|
||||
for_in(mesh, TransparentMesh[TM_DEFAULT])
|
||||
ListBlendTransparentFog::getInstance()->push_back(
|
||||
STK::make_tuple(mesh, AbsoluteTransformation, mesh->TextureMatrix,
|
||||
fogmax, startH, endH, start, end, col));
|
||||
for_in(mesh, TransparentMesh[TM_ADDITIVE])
|
||||
ListAdditiveTransparentFog::getInstance()->push_back(
|
||||
STK::make_tuple(mesh, AbsoluteTransformation, mesh->TextureMatrix,
|
||||
fogmax, startH, endH, start, end, col));
|
||||
}
|
||||
else
|
||||
{
|
||||
for_in(mesh, TransparentMesh[TM_DEFAULT])
|
||||
pushVector(ListBlendTransparent::getInstance(), mesh, AbsoluteTransformation, mesh->TextureMatrix);
|
||||
|
||||
for_in(mesh, TransparentMesh[TM_ADDITIVE])
|
||||
pushVector(ListAdditiveTransparent::getInstance(), mesh, AbsoluteTransformation, mesh->TextureMatrix);
|
||||
}
|
||||
return;
|
||||
}
|
||||
updateNoGL();
|
||||
updateGL();
|
||||
}
|
||||
|
@ -10,12 +10,14 @@
|
||||
class STKAnimatedMesh : public irr::scene::CAnimatedMeshSceneNode, public STKMeshCommon
|
||||
{
|
||||
protected:
|
||||
bool firstTime;
|
||||
bool isMaterialInitialized;
|
||||
bool isGLInitialized;
|
||||
std::vector<GLMesh> GLmeshes;
|
||||
core::matrix4 ModelViewProjectionMatrix;
|
||||
void cleanGLMeshes();
|
||||
public:
|
||||
virtual void update();
|
||||
virtual void updateNoGL();
|
||||
virtual void updateGL();
|
||||
STKAnimatedMesh(irr::scene::IAnimatedMesh* mesh, irr::scene::ISceneNode* parent,
|
||||
irr::scene::ISceneManager* mgr, irr::s32 id,
|
||||
const irr::core::vector3df& position = irr::core::vector3df(0,0,0),
|
||||
|
@ -37,7 +37,6 @@ struct GLMesh {
|
||||
GLuint vao;
|
||||
GLuint vertex_buffer;
|
||||
GLuint index_buffer;
|
||||
GLuint instance_buffer;
|
||||
video::ITexture *textures[6];
|
||||
GLenum PrimitiveType;
|
||||
GLenum IndexType;
|
||||
@ -63,12 +62,23 @@ core::vector3df getWindDir();
|
||||
|
||||
class STKMeshCommon
|
||||
{
|
||||
protected:
|
||||
bool m_culledForPlayerCam;
|
||||
bool m_culledForShadowCam[4];
|
||||
bool m_culledForRSMCam;
|
||||
public:
|
||||
PtrVector<GLMesh, REF> MeshSolidMaterial[MAT_COUNT];
|
||||
PtrVector<GLMesh, REF> TransparentMesh[TM_COUNT];
|
||||
virtual void update() = 0;
|
||||
virtual void updateNoGL() = 0;
|
||||
virtual void updateGL() = 0;
|
||||
virtual bool glow() const = 0;
|
||||
virtual bool isImmediateDraw() const { return false; }
|
||||
bool isCulledForPlayerCam() const { return m_culledForPlayerCam; }
|
||||
void setCulledForPlayerCam(bool v) { m_culledForPlayerCam = v; }
|
||||
bool isCulledForShadowCam(unsigned cascade) const { return m_culledForShadowCam[cascade]; }
|
||||
void setCulledForShadowCam(unsigned cascade, bool v) { m_culledForShadowCam[cascade] = v; }
|
||||
bool isCulledForRSMCam() const { return m_culledForRSMCam; }
|
||||
void setCulledForRSMCam(bool v) { m_culledForRSMCam = v; }
|
||||
};
|
||||
|
||||
template<typename T, typename... Args>
|
||||
|
@ -42,63 +42,7 @@ void STKMeshSceneNode::createGLMeshes()
|
||||
GLmeshes.push_back(allocateMeshBuffer(mb));
|
||||
}
|
||||
isMaterialInitialized = false;
|
||||
}
|
||||
|
||||
void STKMeshSceneNode::setFirstTimeMaterial()
|
||||
{
|
||||
if (isMaterialInitialized)
|
||||
return;
|
||||
irr::video::IVideoDriver* driver = irr_driver->getVideoDriver();
|
||||
for (u32 i = 0; i<Mesh->getMeshBufferCount(); ++i)
|
||||
{
|
||||
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
|
||||
if (!mb)
|
||||
continue;
|
||||
|
||||
video::E_MATERIAL_TYPE type = mb->getMaterial().MaterialType;
|
||||
f32 MaterialTypeParam = mb->getMaterial().MaterialTypeParam;
|
||||
video::IMaterialRenderer* rnd = driver->getMaterialRenderer(type);
|
||||
if (!isObject(type))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Log::warn("material", "Unhandled (static) material type : %d", type);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
GLMesh &mesh = GLmeshes[i];
|
||||
if (rnd->isTransparent())
|
||||
{
|
||||
TransparentMaterial TranspMat = MaterialTypeToTransparentMaterial(type, MaterialTypeParam);
|
||||
if (!immediate_draw)
|
||||
TransparentMesh[TranspMat].push_back(&mesh);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(!isDisplacement);
|
||||
MeshMaterial MatType = MaterialTypeToMeshMaterial(type, mb->getVertexType());
|
||||
if (!immediate_draw)
|
||||
{
|
||||
InitTextures(mesh, MatType);
|
||||
MeshSolidMaterial[MatType].push_back(&mesh);
|
||||
}
|
||||
}
|
||||
|
||||
if (!immediate_draw && irr_driver->hasARB_base_instance())
|
||||
{
|
||||
std::pair<unsigned, unsigned> p = VAOManager::getInstance()->getBase(mb);
|
||||
mesh.vaoBaseVertex = p.first;
|
||||
mesh.vaoOffset = p.second;
|
||||
}
|
||||
else
|
||||
{
|
||||
fillLocalBuffer(mesh, mb);
|
||||
mesh.vao = createVAO(mesh.vertex_buffer, mesh.index_buffer, mb->getVertexType());
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
}
|
||||
isMaterialInitialized = true;
|
||||
isGLInitialized = false;
|
||||
}
|
||||
|
||||
void STKMeshSceneNode::cleanGLMeshes()
|
||||
@ -114,8 +58,6 @@ void STKMeshSceneNode::cleanGLMeshes()
|
||||
glDeleteBuffers(1, &(mesh.vertex_buffer));
|
||||
if (mesh.index_buffer)
|
||||
glDeleteBuffers(1, &(mesh.index_buffer));
|
||||
if (mesh.instance_buffer)
|
||||
glDeleteBuffers(1, &(mesh.instance_buffer));
|
||||
#ifdef Bindless_Texture_Support
|
||||
for (unsigned j = 0; j < 6; j++)
|
||||
{
|
||||
@ -169,11 +111,47 @@ void STKMeshSceneNode::updatevbo()
|
||||
}
|
||||
}
|
||||
|
||||
void STKMeshSceneNode::update()
|
||||
void STKMeshSceneNode::updateNoGL()
|
||||
{
|
||||
Box = Mesh->getBoundingBox();
|
||||
|
||||
setFirstTimeMaterial();
|
||||
if (!isMaterialInitialized)
|
||||
{
|
||||
irr::video::IVideoDriver* driver = irr_driver->getVideoDriver();
|
||||
for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i)
|
||||
{
|
||||
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
|
||||
if (!mb)
|
||||
continue;
|
||||
|
||||
video::E_MATERIAL_TYPE type = mb->getMaterial().MaterialType;
|
||||
f32 MaterialTypeParam = mb->getMaterial().MaterialTypeParam;
|
||||
video::IMaterialRenderer* rnd = driver->getMaterialRenderer(type);
|
||||
if (!isObject(type))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Log::warn("material", "Unhandled (static) material type : %d", type);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
GLMesh &mesh = GLmeshes[i];
|
||||
if (rnd->isTransparent())
|
||||
{
|
||||
TransparentMaterial TranspMat = MaterialTypeToTransparentMaterial(type, MaterialTypeParam);
|
||||
if (!immediate_draw)
|
||||
TransparentMesh[TranspMat].push_back(&mesh);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(!isDisplacement);
|
||||
MeshMaterial MatType = MaterialTypeToMeshMaterial(type, mb->getVertexType());
|
||||
if (!immediate_draw)
|
||||
MeshSolidMaterial[MatType].push_back(&mesh);
|
||||
}
|
||||
}
|
||||
isMaterialInitialized = true;
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i)
|
||||
{
|
||||
@ -184,6 +162,45 @@ void STKMeshSceneNode::update()
|
||||
}
|
||||
}
|
||||
|
||||
void STKMeshSceneNode::updateGL()
|
||||
{
|
||||
if (isGLInitialized)
|
||||
return;
|
||||
for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i)
|
||||
{
|
||||
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
|
||||
if (!mb)
|
||||
continue;
|
||||
GLMesh &mesh = GLmeshes[i];
|
||||
|
||||
irr::video::IVideoDriver* driver = irr_driver->getVideoDriver();
|
||||
video::E_MATERIAL_TYPE type = mb->getMaterial().MaterialType;
|
||||
f32 MaterialTypeParam = mb->getMaterial().MaterialTypeParam;
|
||||
video::IMaterialRenderer* rnd = driver->getMaterialRenderer(type);
|
||||
|
||||
|
||||
if (!rnd->isTransparent())
|
||||
{
|
||||
MeshMaterial MatType = MaterialTypeToMeshMaterial(type, mb->getVertexType());
|
||||
if (!immediate_draw)
|
||||
InitTextures(mesh, MatType);
|
||||
}
|
||||
|
||||
if (!immediate_draw && irr_driver->hasARB_base_instance())
|
||||
{
|
||||
std::pair<unsigned, unsigned> p = VAOManager::getInstance()->getBase(mb);
|
||||
mesh.vaoBaseVertex = p.first;
|
||||
mesh.vaoOffset = p.second;
|
||||
}
|
||||
else
|
||||
{
|
||||
fillLocalBuffer(mesh, mb);
|
||||
mesh.vao = createVAO(mesh.vertex_buffer, mesh.index_buffer, mb->getVertexType());
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
}
|
||||
isGLInitialized = true;
|
||||
}
|
||||
|
||||
void STKMeshSceneNode::OnRegisterSceneNode()
|
||||
{
|
||||
@ -204,7 +221,8 @@ void STKMeshSceneNode::render()
|
||||
|
||||
++PassCount;
|
||||
|
||||
update();
|
||||
updateNoGL();
|
||||
updateGL();
|
||||
|
||||
bool isTransparent;
|
||||
|
||||
|
@ -19,13 +19,15 @@ protected:
|
||||
void setFirstTimeMaterial();
|
||||
void updatevbo();
|
||||
bool isMaterialInitialized;
|
||||
bool isGLInitialized;
|
||||
bool immediate_draw;
|
||||
bool update_each_frame;
|
||||
bool isDisplacement;
|
||||
bool isGlow;
|
||||
video::SColor glowcolor;
|
||||
public:
|
||||
virtual void update();
|
||||
virtual void updateNoGL();
|
||||
virtual void updateGL();
|
||||
void setReloadEachFrame(bool);
|
||||
STKMeshSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id,
|
||||
const irr::core::vector3df& position = irr::core::vector3df(0, 0, 0),
|
||||
|
@ -10,34 +10,29 @@
|
||||
#include <SViewFrustum.h>
|
||||
#include "callbacks.hpp"
|
||||
#include "utils/cpp2011.hpp"
|
||||
#include <omp.h>
|
||||
#include "modes/world.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "lod_node.hpp"
|
||||
#include "utils/profiler.hpp"
|
||||
#include <unordered_map>
|
||||
#include <SViewFrustum.h>
|
||||
#include <functional>
|
||||
|
||||
static void
|
||||
FillInstances_impl(std::vector<std::pair<GLMesh *, scene::ISceneNode *> > InstanceList, InstanceData * InstanceBuffer, DrawElementsIndirectCommand *CommandBuffer,
|
||||
size_t &InstanceBufferOffset, size_t &CommandBufferOffset, size_t &PolyCount)
|
||||
size_t &InstanceBufferOffset, size_t &CommandBufferOffset, size_t &PolyCount, std::function<bool (const scene::ISceneNode *)> cull_func)
|
||||
{
|
||||
// Should never be empty
|
||||
GLMesh *mesh = InstanceList.front().first;
|
||||
|
||||
DrawElementsIndirectCommand &CurrentCommand = CommandBuffer[CommandBufferOffset++];
|
||||
CurrentCommand.baseVertex = mesh->vaoBaseVertex;
|
||||
CurrentCommand.count = mesh->IndexCount;
|
||||
CurrentCommand.firstIndex = mesh->vaoOffset / 2;
|
||||
CurrentCommand.baseInstance = InstanceBufferOffset;
|
||||
CurrentCommand.instanceCount = InstanceList.size();
|
||||
|
||||
PolyCount += InstanceList.size() * mesh->IndexCount / 3;
|
||||
size_t InitialOffset = InstanceBufferOffset;
|
||||
|
||||
for (unsigned i = 0; i < InstanceList.size(); i++)
|
||||
{
|
||||
auto &Tp = InstanceList[i];
|
||||
InstanceData &Instance = InstanceBuffer[InstanceBufferOffset++];
|
||||
scene::ISceneNode *node = Tp.second;
|
||||
if (cull_func(node))
|
||||
continue;
|
||||
InstanceData &Instance = InstanceBuffer[InstanceBufferOffset++];
|
||||
const core::matrix4 &mat = node->getAbsoluteTransformation();
|
||||
const core::vector3df &Origin = mat.getTranslation();
|
||||
const core::vector3df &Orientation = mat.getRotationDegrees();
|
||||
@ -54,26 +49,31 @@ FillInstances_impl(std::vector<std::pair<GLMesh *, scene::ISceneNode *> > Instan
|
||||
Instance.Texture = mesh->TextureHandles[0];
|
||||
Instance.SecondTexture = mesh->TextureHandles[1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
FillInstancesGlow_impl(std::vector<std::pair<GLMesh *, STKMeshCommon *> > InstanceList, GlowInstanceData * InstanceBuffer, DrawElementsIndirectCommand *CommandBuffer,
|
||||
size_t &InstanceBufferOffset, size_t &CommandBufferOffset)
|
||||
{
|
||||
// Should never be empty
|
||||
GLMesh *mesh = InstanceList.front().first;
|
||||
|
||||
DrawElementsIndirectCommand &CurrentCommand = CommandBuffer[CommandBufferOffset++];
|
||||
CurrentCommand.baseVertex = mesh->vaoBaseVertex;
|
||||
CurrentCommand.count = mesh->IndexCount;
|
||||
CurrentCommand.firstIndex = mesh->vaoOffset / 2;
|
||||
CurrentCommand.baseInstance = InstanceBufferOffset;
|
||||
CurrentCommand.instanceCount = InstanceList.size();
|
||||
CurrentCommand.baseInstance = InitialOffset;
|
||||
CurrentCommand.instanceCount = InstanceBufferOffset - InitialOffset;
|
||||
|
||||
PolyCount += (InstanceBufferOffset - InitialOffset) * mesh->IndexCount / 3;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
FillInstancesGlow_impl(std::vector<std::pair<GLMesh *, STKMeshCommon *> > InstanceList, GlowInstanceData * InstanceBuffer, DrawElementsIndirectCommand *CommandBuffer,
|
||||
size_t &InstanceBufferOffset, size_t &CommandBufferOffset, std::function<bool (const scene::ISceneNode *)> cull_func)
|
||||
{
|
||||
// Should never be empty
|
||||
GLMesh *mesh = InstanceList.front().first;
|
||||
size_t InitialOffset = InstanceBufferOffset;
|
||||
|
||||
for (unsigned i = 0; i < InstanceList.size(); i++)
|
||||
{
|
||||
STKMeshSceneNode *node = dynamic_cast<STKMeshSceneNode*>(InstanceList[i].second);
|
||||
if (cull_func(node))
|
||||
continue;
|
||||
GlowInstanceData &Instance = InstanceBuffer[InstanceBufferOffset++];
|
||||
const core::matrix4 &mat = node->getAbsoluteTransformation();
|
||||
const core::vector3df &Origin = mat.getTranslation();
|
||||
@ -90,17 +90,25 @@ size_t &InstanceBufferOffset, size_t &CommandBufferOffset)
|
||||
Instance.Scale.Y = Scale.Y;
|
||||
Instance.Scale.Z = Scale.Z;
|
||||
}
|
||||
|
||||
DrawElementsIndirectCommand &CurrentCommand = CommandBuffer[CommandBufferOffset++];
|
||||
CurrentCommand.baseVertex = mesh->vaoBaseVertex;
|
||||
CurrentCommand.count = mesh->IndexCount;
|
||||
CurrentCommand.firstIndex = mesh->vaoOffset / 2;
|
||||
CurrentCommand.baseInstance = InitialOffset;
|
||||
CurrentCommand.instanceCount = InstanceBufferOffset - InitialOffset;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
void FillInstances(const std::unordered_map<scene::IMeshBuffer *, std::vector<std::pair<GLMesh *, scene::ISceneNode*> > > &GatheredGLMesh, std::vector<GLMesh *> &InstancedList,
|
||||
InstanceData *InstanceBuffer, DrawElementsIndirectCommand *CommandBuffer, size_t &InstanceBufferOffset, size_t &CommandBufferOffset, size_t &Polycount)
|
||||
InstanceData *InstanceBuffer, DrawElementsIndirectCommand *CommandBuffer, size_t &InstanceBufferOffset, size_t &CommandBufferOffset, size_t &Polycount,
|
||||
std::function<bool (const scene::ISceneNode *)> cull_func)
|
||||
{
|
||||
auto It = GatheredGLMesh.begin(), E = GatheredGLMesh.end();
|
||||
for (; It != E; ++It)
|
||||
{
|
||||
FillInstances_impl(It->second, InstanceBuffer, CommandBuffer, InstanceBufferOffset, CommandBufferOffset, Polycount);
|
||||
FillInstances_impl(It->second, InstanceBuffer, CommandBuffer, InstanceBufferOffset, CommandBufferOffset, Polycount, cull_func);
|
||||
if (!UserConfigParams::m_azdo)
|
||||
InstancedList.push_back(It->second.front().first);
|
||||
}
|
||||
@ -108,13 +116,14 @@ void FillInstances(const std::unordered_map<scene::IMeshBuffer *, std::vector<st
|
||||
|
||||
static
|
||||
void FillInstancesGrass(const std::unordered_map<scene::IMeshBuffer *, std::vector<std::pair<GLMesh *, scene::ISceneNode*> > > &GatheredGLMesh, std::vector<GLMesh *> &InstancedList,
|
||||
InstanceData *InstanceBuffer, DrawElementsIndirectCommand *CommandBuffer, size_t &InstanceBufferOffset, size_t &CommandBufferOffset, const core::vector3df &dir, size_t &PolyCount)
|
||||
InstanceData *InstanceBuffer, DrawElementsIndirectCommand *CommandBuffer, size_t &InstanceBufferOffset, size_t &CommandBufferOffset, const core::vector3df &dir, size_t &PolyCount,
|
||||
std::function<bool (const scene::ISceneNode *)> cull_func)
|
||||
{
|
||||
auto It = GatheredGLMesh.begin(), E = GatheredGLMesh.end();
|
||||
SunLightProvider * const cb = (SunLightProvider *)irr_driver->getCallback(ES_SUNLIGHT);
|
||||
for (; It != E; ++It)
|
||||
{
|
||||
FillInstances_impl(It->second, InstanceBuffer, CommandBuffer, InstanceBufferOffset, CommandBufferOffset, PolyCount);
|
||||
FillInstances_impl(It->second, InstanceBuffer, CommandBuffer, InstanceBufferOffset, CommandBufferOffset, PolyCount, cull_func);
|
||||
if (!UserConfigParams::m_azdo)
|
||||
InstancedList.push_back(It->second.front().first);
|
||||
}
|
||||
@ -124,16 +133,50 @@ static std::unordered_map <scene::IMeshBuffer *, std::vector<std::pair<GLMesh *,
|
||||
static std::unordered_map <scene::IMeshBuffer *, std::vector<std::pair<GLMesh *, scene::ISceneNode*> > > MeshForShadowPass[4][MAT_COUNT];
|
||||
static std::unordered_map <scene::IMeshBuffer *, std::vector<std::pair<GLMesh *, scene::ISceneNode*> > > MeshForRSMPass[MAT_COUNT];
|
||||
static std::unordered_map <scene::IMeshBuffer *, std::vector<std::pair<GLMesh *, STKMeshCommon *> > > MeshForGlowPass;
|
||||
static std::vector <STKMeshCommon *> DeferredUpdate;
|
||||
|
||||
static core::vector3df windDir;
|
||||
|
||||
// From irrlicht code
|
||||
static
|
||||
bool isBoxInFrontOfPlane(const core::plane3df &plane, const core::vector3df edges[8])
|
||||
{
|
||||
for (u32 j = 0; j<8; ++j)
|
||||
if (plane.classifyPointRelation(edges[j]) != core::ISREL3D_FRONT)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool isCulled(const scene::ICameraSceneNode *cam, const scene::ISceneNode *node)
|
||||
{
|
||||
if (!node->getAutomaticCulling())
|
||||
return false;
|
||||
|
||||
scene::SViewFrustum frust = *cam->getViewFrustum();
|
||||
|
||||
//transform the frustum to the node's current absolute transformation
|
||||
core::matrix4 invTrans(node->getAbsoluteTransformation(), core::matrix4::EM4CONST_INVERSE);
|
||||
//invTrans.makeInverse();
|
||||
frust.transform(invTrans);
|
||||
|
||||
core::vector3df edges[8];
|
||||
node->getBoundingBox().getEdges(edges);
|
||||
|
||||
for (s32 i = 0; i < scene::SViewFrustum::VF_PLANE_COUNT; ++i)
|
||||
if (isBoxInFrontOfPlane(frust.planes[i], edges))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *ImmediateDraw, bool IsCulledForSolid, bool IsCulledForShadow[4], bool IsCulledForRSM)
|
||||
handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *ImmediateDraw)
|
||||
{
|
||||
STKMeshCommon *node = dynamic_cast<STKMeshCommon*>(Node);
|
||||
if (!node)
|
||||
return;
|
||||
node->update();
|
||||
node->updateNoGL();
|
||||
DeferredUpdate.push_back(node);
|
||||
|
||||
if (node->isImmediateDraw())
|
||||
{
|
||||
@ -143,44 +186,19 @@ handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *Immed
|
||||
for (unsigned Mat = 0; Mat < MAT_COUNT; ++Mat)
|
||||
{
|
||||
GLMesh *mesh;
|
||||
if (!IsCulledForSolid)
|
||||
if (irr_driver->hasARB_draw_indirect())
|
||||
{
|
||||
if (irr_driver->hasARB_draw_indirect())
|
||||
for_in(mesh, node->MeshSolidMaterial[Mat])
|
||||
{
|
||||
for_in(mesh, node->MeshSolidMaterial[Mat])
|
||||
{
|
||||
if (node->glow())
|
||||
MeshForGlowPass[mesh->mb].emplace_back(mesh, node);
|
||||
|
||||
|
||||
if (mesh->TextureMatrix.isIdentity())
|
||||
MeshForSolidPass[Mat][mesh->mb].emplace_back(mesh, Node);
|
||||
else
|
||||
{
|
||||
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
|
||||
ModelMatrix.getInverse(InvModelMatrix);
|
||||
switch (Mat)
|
||||
{
|
||||
case MAT_DEFAULT:
|
||||
ListMatDefault::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_ALPHA_REF:
|
||||
ListMatAlphaRef::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_UNLIT:
|
||||
ListMatUnlit::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
|
||||
ModelMatrix.getInverse(InvModelMatrix);
|
||||
|
||||
for_in(mesh, node->MeshSolidMaterial[Mat])
|
||||
if (node->glow())
|
||||
MeshForGlowPass[mesh->mb].emplace_back(mesh, node);
|
||||
|
||||
if (Mat != MAT_SPLATTING && mesh->TextureMatrix.isIdentity())
|
||||
MeshForSolidPass[Mat][mesh->mb].emplace_back(mesh, Node);
|
||||
else
|
||||
{
|
||||
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
|
||||
ModelMatrix.getInverse(InvModelMatrix);
|
||||
switch (Mat)
|
||||
{
|
||||
case MAT_DEFAULT:
|
||||
@ -189,84 +207,60 @@ handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *Immed
|
||||
case MAT_ALPHA_REF:
|
||||
ListMatAlphaRef::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_NORMAL_MAP:
|
||||
ListMatNormalMap::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_DETAIL:
|
||||
ListMatDetails::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_UNLIT:
|
||||
ListMatUnlit::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_SPHEREMAP:
|
||||
ListMatSphereMap::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_SPLATTING:
|
||||
ListMatSplatting::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix);
|
||||
break;
|
||||
case MAT_GRASS:
|
||||
ListMatGrass::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, windDir);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
|
||||
ModelMatrix.getInverse(InvModelMatrix);
|
||||
|
||||
for_in(mesh, node->MeshSolidMaterial[Mat])
|
||||
{
|
||||
switch (Mat)
|
||||
{
|
||||
case MAT_DEFAULT:
|
||||
ListMatDefault::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_ALPHA_REF:
|
||||
ListMatAlphaRef::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_NORMAL_MAP:
|
||||
ListMatNormalMap::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_DETAIL:
|
||||
ListMatDetails::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_UNLIT:
|
||||
ListMatUnlit::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_SPHEREMAP:
|
||||
ListMatSphereMap::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_SPLATTING:
|
||||
ListMatSplatting::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix);
|
||||
break;
|
||||
case MAT_GRASS:
|
||||
ListMatGrass::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, windDir);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!UserConfigParams::m_shadows)
|
||||
return;
|
||||
for (unsigned cascade = 0; cascade < 4; ++cascade)
|
||||
{
|
||||
if (!IsCulledForShadow[cascade])
|
||||
{
|
||||
if (irr_driver->hasARB_draw_indirect())
|
||||
{
|
||||
for_in(mesh, node->MeshSolidMaterial[Mat])
|
||||
MeshForShadowPass[cascade][Mat][mesh->mb].emplace_back(mesh, Node);
|
||||
}
|
||||
else
|
||||
{
|
||||
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
|
||||
ModelMatrix.getInverse(InvModelMatrix);
|
||||
|
||||
for_in(mesh, node->MeshSolidMaterial[Mat])
|
||||
{
|
||||
switch (Mat)
|
||||
{
|
||||
case MAT_DEFAULT:
|
||||
ListMatDefault::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_ALPHA_REF:
|
||||
ListMatAlphaRef::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_NORMAL_MAP:
|
||||
ListMatNormalMap::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_DETAIL:
|
||||
ListMatDetails::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_UNLIT:
|
||||
ListMatUnlit::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_SPHEREMAP:
|
||||
ListMatSphereMap::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_SPLATTING:
|
||||
ListMatSplatting::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix);
|
||||
break;
|
||||
case MAT_GRASS:
|
||||
ListMatGrass::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, windDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!UserConfigParams::m_gi)
|
||||
return;
|
||||
if (!IsCulledForRSM)
|
||||
{
|
||||
if (irr_driver->hasARB_draw_indirect())
|
||||
{
|
||||
for_in(mesh, node->MeshSolidMaterial[Mat])
|
||||
MeshForRSMPass[Mat][mesh->mb].emplace_back(mesh, Node);
|
||||
MeshForShadowPass[cascade][Mat][mesh->mb].emplace_back(mesh, Node);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -278,76 +272,122 @@ handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *Immed
|
||||
switch (Mat)
|
||||
{
|
||||
case MAT_DEFAULT:
|
||||
ListMatDefault::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
ListMatDefault::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_ALPHA_REF:
|
||||
ListMatAlphaRef::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
ListMatAlphaRef::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_NORMAL_MAP:
|
||||
ListMatNormalMap::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
ListMatNormalMap::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_DETAIL:
|
||||
ListMatDetails::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
ListMatDetails::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_UNLIT:
|
||||
ListMatUnlit::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
ListMatUnlit::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_SPHEREMAP:
|
||||
ListMatSphereMap::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
ListMatSphereMap::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_SPLATTING:
|
||||
ListMatSplatting::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix);
|
||||
ListMatSplatting::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix);
|
||||
break;
|
||||
case MAT_GRASS:
|
||||
ListMatGrass::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, windDir);
|
||||
break;
|
||||
ListMatGrass::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, windDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!UserConfigParams::m_gi)
|
||||
return;
|
||||
if (irr_driver->hasARB_draw_indirect())
|
||||
{
|
||||
for_in(mesh, node->MeshSolidMaterial[Mat])
|
||||
if (Mat != MAT_SPLATTING)
|
||||
MeshForRSMPass[Mat][mesh->mb].emplace_back(mesh, Node);
|
||||
else
|
||||
{
|
||||
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
|
||||
ModelMatrix.getInverse(InvModelMatrix);
|
||||
ListMatSplatting::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
|
||||
ModelMatrix.getInverse(InvModelMatrix);
|
||||
|
||||
for_in(mesh, node->MeshSolidMaterial[Mat])
|
||||
{
|
||||
switch (Mat)
|
||||
{
|
||||
case MAT_DEFAULT:
|
||||
ListMatDefault::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_ALPHA_REF:
|
||||
ListMatAlphaRef::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_NORMAL_MAP:
|
||||
ListMatNormalMap::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_DETAIL:
|
||||
ListMatDetails::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_UNLIT:
|
||||
ListMatUnlit::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_SPHEREMAP:
|
||||
ListMatSphereMap::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case MAT_SPLATTING:
|
||||
ListMatSplatting::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix);
|
||||
break;
|
||||
case MAT_GRASS:
|
||||
ListMatGrass::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, windDir);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Transparent
|
||||
if (!IsCulledForSolid)
|
||||
GLMesh *mesh;
|
||||
if (World::getWorld() && World::getWorld()->isFogEnabled())
|
||||
{
|
||||
GLMesh *mesh;
|
||||
if (World::getWorld() && World::getWorld()->isFogEnabled())
|
||||
{
|
||||
const Track * const track = World::getWorld()->getTrack();
|
||||
const Track * const track = World::getWorld()->getTrack();
|
||||
|
||||
// Todo : put everything in a ubo
|
||||
const float fogmax = track->getFogMax();
|
||||
const float startH = track->getFogStartHeight();
|
||||
const float endH = track->getFogEndHeight();
|
||||
const float start = track->getFogStart();
|
||||
const float end = track->getFogEnd();
|
||||
const video::SColor tmpcol = track->getFogColor();
|
||||
// Todo : put everything in a ubo
|
||||
const float fogmax = track->getFogMax();
|
||||
const float startH = track->getFogStartHeight();
|
||||
const float endH = track->getFogEndHeight();
|
||||
const float start = track->getFogStart();
|
||||
const float end = track->getFogEnd();
|
||||
const video::SColor tmpcol = track->getFogColor();
|
||||
|
||||
video::SColorf col(tmpcol.getRed() / 255.0f,
|
||||
tmpcol.getGreen() / 255.0f,
|
||||
tmpcol.getBlue() / 255.0f);
|
||||
video::SColorf col(tmpcol.getRed() / 255.0f,
|
||||
tmpcol.getGreen() / 255.0f,
|
||||
tmpcol.getBlue() / 255.0f);
|
||||
|
||||
for_in(mesh, node->TransparentMesh[TM_DEFAULT])
|
||||
pushVector(ListBlendTransparentFog::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->TextureMatrix,
|
||||
fogmax, startH, endH, start, end, col);
|
||||
for_in(mesh, node->TransparentMesh[TM_ADDITIVE])
|
||||
pushVector(ListAdditiveTransparentFog::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->TextureMatrix,
|
||||
fogmax, startH, endH, start, end, col);
|
||||
}
|
||||
else
|
||||
{
|
||||
for_in(mesh, node->TransparentMesh[TM_DEFAULT])
|
||||
pushVector(ListBlendTransparent::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->TextureMatrix);
|
||||
for_in(mesh, node->TransparentMesh[TM_ADDITIVE])
|
||||
pushVector(ListAdditiveTransparent::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->TextureMatrix);
|
||||
}
|
||||
for_in(mesh, node->TransparentMesh[TM_DISPLACEMENT])
|
||||
pushVector(ListDisplacement::getInstance(), mesh, Node->getAbsoluteTransformation());
|
||||
for_in(mesh, node->TransparentMesh[TM_DEFAULT])
|
||||
pushVector(ListBlendTransparentFog::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->TextureMatrix,
|
||||
fogmax, startH, endH, start, end, col);
|
||||
for_in(mesh, node->TransparentMesh[TM_ADDITIVE])
|
||||
pushVector(ListAdditiveTransparentFog::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->TextureMatrix,
|
||||
fogmax, startH, endH, start, end, col);
|
||||
}
|
||||
else
|
||||
{
|
||||
for_in(mesh, node->TransparentMesh[TM_DEFAULT])
|
||||
pushVector(ListBlendTransparent::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->TextureMatrix);
|
||||
for_in(mesh, node->TransparentMesh[TM_ADDITIVE])
|
||||
pushVector(ListAdditiveTransparent::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->TextureMatrix);
|
||||
}
|
||||
for_in(mesh, node->TransparentMesh[TM_DISPLACEMENT])
|
||||
pushVector(ListDisplacement::getInstance(), mesh, Node->getAbsoluteTransformation());
|
||||
}
|
||||
|
||||
static void
|
||||
parseSceneManager(core::list<scene::ISceneNode*> List, std::vector<scene::ISceneNode *> *ImmediateDraw,
|
||||
scene::ICameraSceneNode* cam, scene::ICameraSceneNode *shadowCams[4], scene::ICameraSceneNode *RSM_cam)
|
||||
scene::ICameraSceneNode* cam)
|
||||
{
|
||||
core::list<scene::ISceneNode*>::Iterator I = List.begin(), E = List.end();
|
||||
for (; I != E; ++I)
|
||||
@ -358,30 +398,16 @@ parseSceneManager(core::list<scene::ISceneNode*> List, std::vector<scene::IScene
|
||||
continue;
|
||||
(*I)->updateAbsolutePosition();
|
||||
|
||||
core::aabbox3d<f32> tbox = (*I)->getBoundingBox();
|
||||
(*I)->getAbsoluteTransformation().transformBoxEx(tbox);
|
||||
|
||||
bool IsCulledForSolid = !(tbox.intersectsWithBox(cam->getViewFrustum()->getBoundingBox()));
|
||||
|
||||
bool IsCulledForShadow[4];
|
||||
for (unsigned i = 0; i < 4; ++i)
|
||||
IsCulledForShadow[i] = !(tbox.intersectsWithBox(shadowCams[i]->getViewFrustum()->getBoundingBox()));
|
||||
|
||||
bool IsCulledForRSM = !(tbox.intersectsWithBox(RSM_cam->getViewFrustum()->getBoundingBox()));
|
||||
|
||||
if (!IsCulledForSolid)
|
||||
if (ParticleSystemProxy *node = dynamic_cast<ParticleSystemProxy *>(*I))
|
||||
{
|
||||
if (ParticleSystemProxy *node = dynamic_cast<ParticleSystemProxy *>(*I))
|
||||
{
|
||||
if (node->update())
|
||||
ParticlesList::getInstance()->push_back(node);
|
||||
continue;
|
||||
}
|
||||
if (!isCulled(cam, *I) && node->update())
|
||||
ParticlesList::getInstance()->push_back(node);
|
||||
continue;
|
||||
}
|
||||
|
||||
handleSTKCommon(*I, ImmediateDraw, IsCulledForSolid, IsCulledForShadow, IsCulledForRSM);
|
||||
handleSTKCommon(*I, ImmediateDraw);
|
||||
|
||||
parseSceneManager((*I)->getChildren(), ImmediateDraw, cam, shadowCams, RSM_cam);
|
||||
parseSceneManager((*I)->getChildren(), ImmediateDraw, cam);
|
||||
}
|
||||
}
|
||||
|
||||
@ -389,9 +415,10 @@ template<MeshMaterial Mat> static void
|
||||
GenDrawCalls(unsigned cascade, std::vector<GLMesh *> &InstancedList,
|
||||
InstanceData *InstanceBuffer, DrawElementsIndirectCommand *CommandBuffer, size_t &InstanceBufferOffset, size_t &CommandBufferOffset, size_t &PolyCount)
|
||||
{
|
||||
std::function<bool(const scene::ISceneNode *)> shadowculling = [&](const scene::ISceneNode *nd) {return dynamic_cast<const STKMeshCommon*>(nd)->isCulledForShadowCam(cascade); };
|
||||
if (irr_driver->hasARB_draw_indirect())
|
||||
ShadowPassCmd::getInstance()->Offset[cascade][Mat] = CommandBufferOffset; // Store command buffer offset
|
||||
FillInstances(MeshForShadowPass[cascade][Mat], InstancedList, InstanceBuffer, CommandBuffer, InstanceBufferOffset, CommandBufferOffset, PolyCount);
|
||||
FillInstances(MeshForShadowPass[cascade][Mat], InstancedList, InstanceBuffer, CommandBuffer, InstanceBufferOffset, CommandBufferOffset, PolyCount, shadowculling);
|
||||
if (UserConfigParams::m_azdo)
|
||||
ShadowPassCmd::getInstance()->Size[cascade][Mat] = CommandBufferOffset - ShadowPassCmd::getInstance()->Offset[cascade][Mat];
|
||||
}
|
||||
@ -400,9 +427,10 @@ template<MeshMaterial Mat> static void
|
||||
GenDrawCallsGrass(unsigned cascade, std::vector<GLMesh *> &InstancedList,
|
||||
InstanceData *InstanceBuffer, DrawElementsIndirectCommand *CommandBuffer, size_t &InstanceBufferOffset, size_t &CommandBufferOffset, const core::vector3df &dir, size_t &PolyCount)
|
||||
{
|
||||
std::function<bool(const scene::ISceneNode *)> shadowculling = [&](const scene::ISceneNode *nd) {return dynamic_cast<const STKMeshCommon*>(nd)->isCulledForShadowCam(cascade); };
|
||||
if (irr_driver->hasARB_draw_indirect())
|
||||
ShadowPassCmd::getInstance()->Offset[cascade][Mat] = CommandBufferOffset; // Store command buffer offset
|
||||
FillInstancesGrass(MeshForShadowPass[cascade][Mat], InstancedList, InstanceBuffer, CommandBuffer, InstanceBufferOffset, CommandBufferOffset, dir, PolyCount);
|
||||
FillInstancesGrass(MeshForShadowPass[cascade][Mat], InstancedList, InstanceBuffer, CommandBuffer, InstanceBufferOffset, CommandBufferOffset, dir, PolyCount, shadowculling);
|
||||
if (UserConfigParams::m_azdo)
|
||||
ShadowPassCmd::getInstance()->Size[cascade][Mat] = CommandBufferOffset - ShadowPassCmd::getInstance()->Offset[cascade][Mat];
|
||||
}
|
||||
@ -437,14 +465,29 @@ void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
||||
MeshForShadowPass[cascade][Mat].clear();
|
||||
}
|
||||
MeshForGlowPass.clear();
|
||||
DeferredUpdate.clear();
|
||||
core::list<scene::ISceneNode*> List = m_scene_manager->getRootSceneNode()->getChildren();
|
||||
|
||||
bool isCulled[4] = {};
|
||||
parseSceneManager(List, ImmediateDrawList::getInstance(), camnode);
|
||||
|
||||
// Add a 20 ms timeout
|
||||
#pragma omp parallel for
|
||||
for (int i = 0; i < (int)DeferredUpdate.size(); i++)
|
||||
{
|
||||
scene::ISceneNode *node = dynamic_cast<scene::ISceneNode *>(DeferredUpdate[i]);
|
||||
DeferredUpdate[i]->setCulledForPlayerCam(isCulled(camnode, node));
|
||||
DeferredUpdate[i]->setCulledForRSMCam(isCulled(m_suncam, node));
|
||||
DeferredUpdate[i]->setCulledForShadowCam(0, isCulled(m_shadow_camnodes[0], node));
|
||||
DeferredUpdate[i]->setCulledForShadowCam(1, isCulled(m_shadow_camnodes[1], node));
|
||||
DeferredUpdate[i]->setCulledForShadowCam(2, isCulled(m_shadow_camnodes[2], node));
|
||||
DeferredUpdate[i]->setCulledForShadowCam(3, isCulled(m_shadow_camnodes[3], node));
|
||||
}
|
||||
|
||||
// Add a 1 s timeout
|
||||
if (!m_sync)
|
||||
m_sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
PROFILER_PUSH_CPU_MARKER("- Sync Stall", 0xFF, 0x0, 0x0);
|
||||
GLenum reason = glClientWaitSync(m_sync, GL_SYNC_FLUSH_COMMANDS_BIT, 1000000000);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
/* switch (reason)
|
||||
{
|
||||
case GL_ALREADY_SIGNALED:
|
||||
@ -460,7 +503,9 @@ void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
||||
printf("Wait Failed\n");
|
||||
break;
|
||||
}*/
|
||||
parseSceneManager(List, ImmediateDrawList::getInstance(), camnode, m_shadow_camnodes, m_suncam);
|
||||
for (unsigned i = 0; i < DeferredUpdate.size(); i++)
|
||||
DeferredUpdate[i]->updateGL();
|
||||
|
||||
if (!irr_driver->hasARB_draw_indirect())
|
||||
return;
|
||||
|
||||
@ -496,6 +541,8 @@ void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
||||
size_t SolidPoly = 0, ShadowPoly = 0, MiscPoly = 0;
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("- Draw Command upload", 0xFF, 0x0, 0xFF);
|
||||
|
||||
auto playercamculling = [](const scene::ISceneNode *nd) {return dynamic_cast<const STKMeshCommon*>(nd)->isCulledForPlayerCam(); };
|
||||
#pragma omp parallel sections
|
||||
{
|
||||
#pragma omp section
|
||||
@ -509,34 +556,35 @@ void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
||||
CmdBuffer = (DrawElementsIndirectCommand*)glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, 10000 * sizeof(DrawElementsIndirectCommand), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
|
||||
}
|
||||
|
||||
|
||||
// Default Material
|
||||
SolidPassCmd::getInstance()->Offset[MAT_DEFAULT] = current_cmd;
|
||||
FillInstances(MeshForSolidPass[MAT_DEFAULT], ListInstancedMatDefault::getInstance()->SolidPass, InstanceBuffer, CmdBuffer, offset, current_cmd, SolidPoly);
|
||||
FillInstances(MeshForSolidPass[MAT_DEFAULT], ListInstancedMatDefault::getInstance()->SolidPass, InstanceBuffer, CmdBuffer, offset, current_cmd, SolidPoly, playercamculling);
|
||||
SolidPassCmd::getInstance()->Size[MAT_DEFAULT] = current_cmd - SolidPassCmd::getInstance()->Offset[MAT_DEFAULT];
|
||||
// Alpha Ref
|
||||
SolidPassCmd::getInstance()->Offset[MAT_ALPHA_REF] = current_cmd;
|
||||
FillInstances(MeshForSolidPass[MAT_ALPHA_REF], ListInstancedMatAlphaRef::getInstance()->SolidPass, InstanceBuffer, CmdBuffer, offset, current_cmd, SolidPoly);
|
||||
FillInstances(MeshForSolidPass[MAT_ALPHA_REF], ListInstancedMatAlphaRef::getInstance()->SolidPass, InstanceBuffer, CmdBuffer, offset, current_cmd, SolidPoly, playercamculling);
|
||||
SolidPassCmd::getInstance()->Size[MAT_ALPHA_REF] = current_cmd - SolidPassCmd::getInstance()->Offset[MAT_ALPHA_REF];
|
||||
// Unlit
|
||||
SolidPassCmd::getInstance()->Offset[MAT_UNLIT] = current_cmd;
|
||||
FillInstances(MeshForSolidPass[MAT_UNLIT], ListInstancedMatUnlit::getInstance()->SolidPass, InstanceBuffer, CmdBuffer, offset, current_cmd, SolidPoly);
|
||||
FillInstances(MeshForSolidPass[MAT_UNLIT], ListInstancedMatUnlit::getInstance()->SolidPass, InstanceBuffer, CmdBuffer, offset, current_cmd, SolidPoly, playercamculling);
|
||||
SolidPassCmd::getInstance()->Size[MAT_UNLIT] = current_cmd - SolidPassCmd::getInstance()->Offset[MAT_UNLIT];
|
||||
// Spheremap
|
||||
SolidPassCmd::getInstance()->Offset[MAT_SPHEREMAP] = current_cmd;
|
||||
FillInstances(MeshForSolidPass[MAT_SPHEREMAP], ListInstancedMatSphereMap::getInstance()->SolidPass, InstanceBuffer, CmdBuffer, offset, current_cmd, SolidPoly);
|
||||
FillInstances(MeshForSolidPass[MAT_SPHEREMAP], ListInstancedMatSphereMap::getInstance()->SolidPass, InstanceBuffer, CmdBuffer, offset, current_cmd, SolidPoly, playercamculling);
|
||||
SolidPassCmd::getInstance()->Size[MAT_SPHEREMAP] = current_cmd - SolidPassCmd::getInstance()->Offset[MAT_SPHEREMAP];
|
||||
// Detail
|
||||
SolidPassCmd::getInstance()->Offset[MAT_DETAIL] = current_cmd;
|
||||
FillInstances(MeshForSolidPass[MAT_DETAIL], ListInstancedMatDetails::getInstance()->SolidPass, InstanceBuffer, CmdBuffer, offset, current_cmd, SolidPoly);
|
||||
FillInstances(MeshForSolidPass[MAT_DETAIL], ListInstancedMatDetails::getInstance()->SolidPass, InstanceBuffer, CmdBuffer, offset, current_cmd, SolidPoly, playercamculling);
|
||||
SolidPassCmd::getInstance()->Size[MAT_DETAIL] = current_cmd - SolidPassCmd::getInstance()->Offset[MAT_DETAIL];
|
||||
// Normal Map
|
||||
SolidPassCmd::getInstance()->Offset[MAT_NORMAL_MAP] = current_cmd;
|
||||
FillInstances(MeshForSolidPass[MAT_NORMAL_MAP], ListInstancedMatNormalMap::getInstance()->SolidPass, InstanceBuffer, CmdBuffer, offset, current_cmd, SolidPoly);
|
||||
FillInstances(MeshForSolidPass[MAT_NORMAL_MAP], ListInstancedMatNormalMap::getInstance()->SolidPass, InstanceBuffer, CmdBuffer, offset, current_cmd, SolidPoly, playercamculling);
|
||||
SolidPassCmd::getInstance()->Size[MAT_NORMAL_MAP] = current_cmd - SolidPassCmd::getInstance()->Offset[MAT_NORMAL_MAP];
|
||||
|
||||
// Grass
|
||||
SolidPassCmd::getInstance()->Offset[MAT_GRASS] = current_cmd;
|
||||
FillInstancesGrass(MeshForSolidPass[MAT_GRASS], ListInstancedMatGrass::getInstance()->SolidPass, InstanceBuffer, CmdBuffer, offset, current_cmd, windDir, SolidPoly);
|
||||
FillInstancesGrass(MeshForSolidPass[MAT_GRASS], ListInstancedMatGrass::getInstance()->SolidPass, InstanceBuffer, CmdBuffer, offset, current_cmd, windDir, SolidPoly, playercamculling);
|
||||
SolidPassCmd::getInstance()->Size[MAT_GRASS] = current_cmd - SolidPassCmd::getInstance()->Offset[MAT_GRASS];
|
||||
|
||||
if (!irr_driver->hasBufferStorageExtension())
|
||||
@ -564,7 +612,7 @@ void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
||||
auto It = MeshForGlowPass.begin(), E = MeshForGlowPass.end();
|
||||
for (; It != E; ++It)
|
||||
{
|
||||
FillInstancesGlow_impl(It->second, GlowInstanceBuffer, GlowCmdBuffer, offset, current_cmd);
|
||||
FillInstancesGlow_impl(It->second, GlowInstanceBuffer, GlowCmdBuffer, offset, current_cmd, playercamculling);
|
||||
if (!UserConfigParams::m_azdo)
|
||||
ListInstancedGlow::getInstance()->push_back(It->second.front().first);
|
||||
}
|
||||
@ -616,6 +664,7 @@ void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
||||
}
|
||||
#pragma omp section
|
||||
{
|
||||
auto rsmcamculling = [](const scene::ISceneNode *nd) {return dynamic_cast<const STKMeshCommon*>(nd)->isCulledForRSMCam(); };
|
||||
size_t offset = 0, current_cmd = 0;
|
||||
if (!irr_driver->hasBufferStorageExtension())
|
||||
{
|
||||
@ -627,23 +676,23 @@ void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
||||
|
||||
// Default Material
|
||||
RSMPassCmd::getInstance()->Offset[MAT_DEFAULT] = current_cmd;
|
||||
FillInstances(MeshForRSMPass[MAT_DEFAULT], ListInstancedMatDefault::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly);
|
||||
FillInstances(MeshForRSMPass[MAT_DEFAULT], ListInstancedMatDefault::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly, rsmcamculling);
|
||||
RSMPassCmd::getInstance()->Size[MAT_DEFAULT] = current_cmd - RSMPassCmd::getInstance()->Offset[MAT_DEFAULT];
|
||||
// Alpha Ref
|
||||
RSMPassCmd::getInstance()->Offset[MAT_ALPHA_REF] = current_cmd;
|
||||
FillInstances(MeshForRSMPass[MAT_ALPHA_REF], ListInstancedMatAlphaRef::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly);
|
||||
FillInstances(MeshForRSMPass[MAT_ALPHA_REF], ListInstancedMatAlphaRef::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly, rsmcamculling);
|
||||
RSMPassCmd::getInstance()->Size[MAT_ALPHA_REF] = current_cmd - RSMPassCmd::getInstance()->Offset[MAT_ALPHA_REF];
|
||||
// Unlit
|
||||
RSMPassCmd::getInstance()->Offset[MAT_UNLIT] = current_cmd;
|
||||
FillInstances(MeshForRSMPass[MAT_UNLIT], ListInstancedMatUnlit::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly);
|
||||
FillInstances(MeshForRSMPass[MAT_UNLIT], ListInstancedMatUnlit::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly, rsmcamculling);
|
||||
RSMPassCmd::getInstance()->Size[MAT_UNLIT] = current_cmd - RSMPassCmd::getInstance()->Offset[MAT_UNLIT];
|
||||
// Detail
|
||||
RSMPassCmd::getInstance()->Offset[MAT_DETAIL] = current_cmd;
|
||||
FillInstances(MeshForRSMPass[MAT_DETAIL], ListInstancedMatDetails::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly);
|
||||
FillInstances(MeshForRSMPass[MAT_DETAIL], ListInstancedMatDetails::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly, rsmcamculling);
|
||||
RSMPassCmd::getInstance()->Size[MAT_DETAIL] = current_cmd - RSMPassCmd::getInstance()->Offset[MAT_DETAIL];
|
||||
// Normal Map
|
||||
RSMPassCmd::getInstance()->Offset[MAT_NORMAL_MAP] = current_cmd;
|
||||
FillInstances(MeshForRSMPass[MAT_NORMAL_MAP], ListInstancedMatNormalMap::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly);
|
||||
FillInstances(MeshForRSMPass[MAT_NORMAL_MAP], ListInstancedMatNormalMap::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly, rsmcamculling);
|
||||
RSMPassCmd::getInstance()->Size[MAT_NORMAL_MAP] = current_cmd - RSMPassCmd::getInstance()->Offset[MAT_NORMAL_MAP];
|
||||
|
||||
if (!irr_driver->hasBufferStorageExtension())
|
||||
|
320
src/graphics/vaomanager.cpp
Normal file
320
src/graphics/vaomanager.cpp
Normal file
@ -0,0 +1,320 @@
|
||||
#include "vaomanager.hpp"
|
||||
#include "stkmesh.hpp"
|
||||
|
||||
VAOManager::VAOManager()
|
||||
{
|
||||
vao[0] = vao[1] = vao[2] = 0;
|
||||
vbo[0] = vbo[1] = vbo[2] = 0;
|
||||
ibo[0] = ibo[1] = ibo[2] = 0;
|
||||
vtx_cnt[0] = vtx_cnt[1] = vtx_cnt[2] = 0;
|
||||
idx_cnt[0] = idx_cnt[1] = idx_cnt[2] = 0;
|
||||
vtx_mirror[0] = vtx_mirror[1] = vtx_mirror[2] = NULL;
|
||||
idx_mirror[0] = idx_mirror[1] = idx_mirror[2] = NULL;
|
||||
instance_count[0] = 0;
|
||||
|
||||
for (unsigned i = 0; i < InstanceTypeCount; i++)
|
||||
{
|
||||
glGenBuffers(1, &instance_vbo[i]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[i]);
|
||||
#ifdef Buffer_Storage
|
||||
if (irr_driver->hasBufferStorageExtension())
|
||||
{
|
||||
glBufferStorage(GL_ARRAY_BUFFER, 10000 * sizeof(InstanceData), 0, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT);
|
||||
Ptr[i] = glMapBufferRange(GL_ARRAY_BUFFER, 0, 10000 * sizeof(InstanceData), GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
glBufferData(GL_ARRAY_BUFFER, 10000 * sizeof(InstanceData), 0, GL_STREAM_DRAW);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VAOManager::cleanInstanceVAOs()
|
||||
{
|
||||
std::map<std::pair<video::E_VERTEX_TYPE, InstanceType>, GLuint>::iterator It = InstanceVAO.begin(), E = InstanceVAO.end();
|
||||
for (; It != E; It++)
|
||||
glDeleteVertexArrays(1, &(It->second));
|
||||
InstanceVAO.clear();
|
||||
}
|
||||
|
||||
VAOManager::~VAOManager()
|
||||
{
|
||||
cleanInstanceVAOs();
|
||||
for (unsigned i = 0; i < 3; i++)
|
||||
{
|
||||
if (vtx_mirror[i])
|
||||
free(vtx_mirror[i]);
|
||||
if (idx_mirror[i])
|
||||
free(idx_mirror[i]);
|
||||
if (vbo[i])
|
||||
glDeleteBuffers(1, &vbo[i]);
|
||||
if (ibo[i])
|
||||
glDeleteBuffers(1, &ibo[i]);
|
||||
if (vao[i])
|
||||
glDeleteVertexArrays(1, &vao[i]);
|
||||
}
|
||||
for (unsigned i = 0; i < InstanceTypeCount; i++)
|
||||
{
|
||||
glDeleteBuffers(1, &instance_vbo[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void VAOManager::regenerateBuffer(enum VTXTYPE tp)
|
||||
{
|
||||
glBindVertexArray(0);
|
||||
if (vbo[tp])
|
||||
glDeleteBuffers(1, &vbo[tp]);
|
||||
glGenBuffers(1, &vbo[tp]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo[tp]);
|
||||
#ifdef Buffer_Storage
|
||||
if (irr_driver->hasBufferStorageExtension())
|
||||
{
|
||||
glBufferStorage(GL_ARRAY_BUFFER, vtx_cnt[tp] * getVertexPitch(tp), vtx_mirror[tp], GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT);
|
||||
VBOPtr[tp] = glMapBufferRange(GL_ARRAY_BUFFER, 0, vtx_cnt[tp] * getVertexPitch(tp), GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
glBufferData(GL_ARRAY_BUFFER, vtx_cnt[tp] * getVertexPitch(tp), vtx_mirror[tp], GL_DYNAMIC_DRAW);
|
||||
|
||||
|
||||
if (ibo[tp])
|
||||
glDeleteBuffers(1, &ibo[tp]);
|
||||
glGenBuffers(1, &ibo[tp]);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[tp]);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(u16)* idx_cnt[tp], idx_mirror[tp], GL_DYNAMIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
void VAOManager::regenerateVAO(enum VTXTYPE tp)
|
||||
{
|
||||
if (vao[tp])
|
||||
glDeleteVertexArrays(1, &vao[tp]);
|
||||
glGenVertexArrays(1, &vao[tp]);
|
||||
glBindVertexArray(vao[tp]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo[tp]);
|
||||
switch (tp)
|
||||
{
|
||||
case VTXTYPE_STANDARD:
|
||||
// Position
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0);
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12);
|
||||
// Color
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24);
|
||||
// Texcoord
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28);
|
||||
break;
|
||||
case VTXTYPE_TCOORD:
|
||||
// Position
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0);
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12);
|
||||
// Color
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24);
|
||||
// Texcoord
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28);
|
||||
// SecondTexcoord
|
||||
glEnableVertexAttribArray(4);
|
||||
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)36);
|
||||
break;
|
||||
case VTXTYPE_TANGENT:
|
||||
// Position
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0);
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12);
|
||||
// Color
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24);
|
||||
// Texcoord
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28);
|
||||
// Tangent
|
||||
glEnableVertexAttribArray(5);
|
||||
glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)36);
|
||||
// Bitangent
|
||||
glEnableVertexAttribArray(6);
|
||||
glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)48);
|
||||
break;
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[tp]);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void VAOManager::regenerateInstancedVAO()
|
||||
{
|
||||
cleanInstanceVAOs();
|
||||
|
||||
enum video::E_VERTEX_TYPE IrrVT[] = { video::EVT_STANDARD, video::EVT_2TCOORDS, video::EVT_TANGENTS };
|
||||
for (unsigned i = 0; i < VTXTYPE_COUNT; i++)
|
||||
{
|
||||
video::E_VERTEX_TYPE tp = IrrVT[i];
|
||||
if (!vbo[tp] || !ibo[tp])
|
||||
continue;
|
||||
GLuint vao = createVAO(vbo[tp], ibo[tp], tp);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeDefault]);
|
||||
|
||||
glEnableVertexAttribArray(7);
|
||||
glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), 0);
|
||||
glVertexAttribDivisor(7, 1);
|
||||
glEnableVertexAttribArray(8);
|
||||
glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(3 * sizeof(float)));
|
||||
glVertexAttribDivisor(8, 1);
|
||||
glEnableVertexAttribArray(9);
|
||||
glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(6 * sizeof(float)));
|
||||
glVertexAttribDivisor(9, 1);
|
||||
glEnableVertexAttribArray(10);
|
||||
glVertexAttribIPointer(10, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float)));
|
||||
glVertexAttribDivisor(10, 1);
|
||||
glEnableVertexAttribArray(11);
|
||||
glVertexAttribIPointer(11, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float) + 2 * sizeof(unsigned)));
|
||||
glVertexAttribDivisor(11, 1);
|
||||
InstanceVAO[std::pair<video::E_VERTEX_TYPE, InstanceType>(tp, InstanceTypeDefault)] = vao;
|
||||
|
||||
vao = createVAO(vbo[tp], ibo[tp], tp);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeShadow]);
|
||||
|
||||
glEnableVertexAttribArray(7);
|
||||
glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), 0);
|
||||
glVertexAttribDivisor(7, 1);
|
||||
glEnableVertexAttribArray(8);
|
||||
glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(3 * sizeof(float)));
|
||||
glVertexAttribDivisor(8, 1);
|
||||
glEnableVertexAttribArray(9);
|
||||
glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(6 * sizeof(float)));
|
||||
glVertexAttribDivisor(9, 1);
|
||||
glEnableVertexAttribArray(10);
|
||||
glVertexAttribIPointer(10, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float)));
|
||||
glVertexAttribDivisor(10, 1);
|
||||
glEnableVertexAttribArray(11);
|
||||
glVertexAttribIPointer(11, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float) + 2 * sizeof(unsigned)));
|
||||
glVertexAttribDivisor(11, 1);
|
||||
InstanceVAO[std::pair<video::E_VERTEX_TYPE, InstanceType>(tp, InstanceTypeShadow)] = vao;
|
||||
|
||||
vao = createVAO(vbo[tp], ibo[tp], tp);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeRSM]);
|
||||
|
||||
glEnableVertexAttribArray(7);
|
||||
glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), 0);
|
||||
glVertexAttribDivisor(7, 1);
|
||||
glEnableVertexAttribArray(8);
|
||||
glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(3 * sizeof(float)));
|
||||
glVertexAttribDivisor(8, 1);
|
||||
glEnableVertexAttribArray(9);
|
||||
glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(6 * sizeof(float)));
|
||||
glVertexAttribDivisor(9, 1);
|
||||
glEnableVertexAttribArray(10);
|
||||
glVertexAttribIPointer(10, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float)));
|
||||
glVertexAttribDivisor(10, 1);
|
||||
glEnableVertexAttribArray(11);
|
||||
glVertexAttribIPointer(11, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float) + 2 * sizeof(unsigned)));
|
||||
glVertexAttribDivisor(11, 1);
|
||||
InstanceVAO[std::pair<video::E_VERTEX_TYPE, InstanceType>(tp, InstanceTypeRSM)] = vao;
|
||||
|
||||
vao = createVAO(vbo[tp], ibo[tp], tp);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeGlow]);
|
||||
|
||||
glEnableVertexAttribArray(7);
|
||||
glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(GlowInstanceData), 0);
|
||||
glVertexAttribDivisor(7, 1);
|
||||
glEnableVertexAttribArray(8);
|
||||
glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(GlowInstanceData), (GLvoid*)(3 * sizeof(float)));
|
||||
glVertexAttribDivisor(8, 1);
|
||||
glEnableVertexAttribArray(9);
|
||||
glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(GlowInstanceData), (GLvoid*)(6 * sizeof(float)));
|
||||
glVertexAttribDivisor(9, 1);
|
||||
glEnableVertexAttribArray(12);
|
||||
glVertexAttribPointer(12, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(GlowInstanceData), (GLvoid*)(9 * sizeof(float)));
|
||||
glVertexAttribDivisor(12, 1);
|
||||
InstanceVAO[std::pair<video::E_VERTEX_TYPE, InstanceType>(tp, InstanceTypeGlow)] = vao;
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
size_t VAOManager::getVertexPitch(enum VTXTYPE tp) const
|
||||
{
|
||||
switch (tp)
|
||||
{
|
||||
case VTXTYPE_STANDARD:
|
||||
return getVertexPitchFromType(video::EVT_STANDARD);
|
||||
case VTXTYPE_TCOORD:
|
||||
return getVertexPitchFromType(video::EVT_2TCOORDS);
|
||||
case VTXTYPE_TANGENT:
|
||||
return getVertexPitchFromType(video::EVT_TANGENTS);
|
||||
default:
|
||||
assert(0 && "Wrong vtxtype");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
VAOManager::VTXTYPE VAOManager::getVTXTYPE(video::E_VERTEX_TYPE type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
default:
|
||||
assert(0 && "Wrong vtxtype");
|
||||
case video::EVT_STANDARD:
|
||||
return VTXTYPE_STANDARD;
|
||||
case video::EVT_2TCOORDS:
|
||||
return VTXTYPE_TCOORD;
|
||||
case video::EVT_TANGENTS:
|
||||
return VTXTYPE_TANGENT;
|
||||
}
|
||||
};
|
||||
|
||||
void VAOManager::append(scene::IMeshBuffer *mb, VTXTYPE tp)
|
||||
{
|
||||
size_t old_vtx_cnt = vtx_cnt[tp];
|
||||
vtx_cnt[tp] += mb->getVertexCount();
|
||||
vtx_mirror[tp] = realloc(vtx_mirror[tp], vtx_cnt[tp] * getVertexPitch(tp));
|
||||
intptr_t dstptr = (intptr_t)vtx_mirror[tp] + (old_vtx_cnt * getVertexPitch(tp));
|
||||
memcpy((void *)dstptr, mb->getVertices(), mb->getVertexCount() * getVertexPitch(tp));
|
||||
mappedBaseVertex[tp][mb] = old_vtx_cnt;
|
||||
|
||||
size_t old_idx_cnt = idx_cnt[tp];
|
||||
idx_cnt[tp] += mb->getIndexCount();
|
||||
idx_mirror[tp] = realloc(idx_mirror[tp], idx_cnt[tp] * sizeof(u16));
|
||||
|
||||
dstptr = (intptr_t)idx_mirror[tp] + (old_idx_cnt * sizeof(u16));
|
||||
memcpy((void *)dstptr, mb->getIndices(), mb->getIndexCount() * sizeof(u16));
|
||||
mappedBaseIndex[tp][mb] = old_idx_cnt * sizeof(u16);
|
||||
}
|
||||
|
||||
std::pair<unsigned, unsigned> VAOManager::getBase(scene::IMeshBuffer *mb)
|
||||
{
|
||||
VTXTYPE tp = getVTXTYPE(mb->getVertexType());
|
||||
if (mappedBaseVertex[tp].find(mb) == mappedBaseVertex[tp].end())
|
||||
{
|
||||
assert(mappedBaseIndex[tp].find(mb) == mappedBaseIndex[tp].end());
|
||||
storedCPUBuffer[tp].push_back(mb);
|
||||
append(mb, tp);
|
||||
regenerateBuffer(tp);
|
||||
regenerateVAO(tp);
|
||||
regenerateInstancedVAO();
|
||||
}
|
||||
|
||||
std::unordered_map<scene::IMeshBuffer*, unsigned>::iterator It;
|
||||
It = mappedBaseVertex[tp].find(mb);
|
||||
assert(It != mappedBaseVertex[tp].end());
|
||||
unsigned vtx = It->second;
|
||||
It = mappedBaseIndex[tp].find(mb);
|
||||
assert(It != mappedBaseIndex[tp].end());
|
||||
return std::pair<unsigned, unsigned>(vtx, It->second);
|
||||
}
|
114
src/graphics/vaomanager.hpp
Normal file
114
src/graphics/vaomanager.hpp
Normal file
@ -0,0 +1,114 @@
|
||||
#ifndef VAOMANAGER_HPP
|
||||
#define VAOMANAGER_HPP
|
||||
|
||||
#include "gl_headers.hpp"
|
||||
#include "utils/singleton.hpp"
|
||||
#include "irr_driver.hpp"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
enum InstanceType
|
||||
{
|
||||
InstanceTypeDefault,
|
||||
InstanceTypeShadow,
|
||||
InstanceTypeRSM,
|
||||
InstanceTypeGlow,
|
||||
InstanceTypeCount,
|
||||
};
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma pack(push, 1)
|
||||
#endif
|
||||
struct InstanceData
|
||||
{
|
||||
struct
|
||||
{
|
||||
float X;
|
||||
float Y;
|
||||
float Z;
|
||||
} Origin;
|
||||
struct
|
||||
{
|
||||
float X;
|
||||
float Y;
|
||||
float Z;
|
||||
} Orientation;
|
||||
struct
|
||||
{
|
||||
float X;
|
||||
float Y;
|
||||
float Z;
|
||||
} Scale;
|
||||
uint64_t Texture;
|
||||
uint64_t SecondTexture;
|
||||
#ifdef WIN32
|
||||
};
|
||||
#else
|
||||
} __attribute__((packed));
|
||||
#endif
|
||||
|
||||
struct GlowInstanceData
|
||||
{
|
||||
struct
|
||||
{
|
||||
float X;
|
||||
float Y;
|
||||
float Z;
|
||||
} Origin;
|
||||
struct
|
||||
{
|
||||
float X;
|
||||
float Y;
|
||||
float Z;
|
||||
} Orientation;
|
||||
struct
|
||||
{
|
||||
float X;
|
||||
float Y;
|
||||
float Z;
|
||||
} Scale;
|
||||
unsigned Color;
|
||||
#ifdef WIN32
|
||||
};
|
||||
#else
|
||||
} __attribute__((packed));
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
class VAOManager : public Singleton<VAOManager>
|
||||
{
|
||||
enum VTXTYPE { VTXTYPE_STANDARD, VTXTYPE_TCOORD, VTXTYPE_TANGENT, VTXTYPE_COUNT };
|
||||
GLuint vbo[VTXTYPE_COUNT], ibo[VTXTYPE_COUNT], vao[VTXTYPE_COUNT];
|
||||
GLuint instance_vbo[InstanceTypeCount];
|
||||
size_t instance_count[InstanceTypeCount];
|
||||
void *Ptr[InstanceTypeCount];
|
||||
void *VBOPtr[VTXTYPE_COUNT];
|
||||
std::vector<scene::IMeshBuffer *> storedCPUBuffer[VTXTYPE_COUNT];
|
||||
void *vtx_mirror[VTXTYPE_COUNT], *idx_mirror[VTXTYPE_COUNT];
|
||||
size_t vtx_cnt[VTXTYPE_COUNT], idx_cnt[VTXTYPE_COUNT];
|
||||
std::unordered_map<scene::IMeshBuffer*, unsigned> mappedBaseVertex[VTXTYPE_COUNT], mappedBaseIndex[VTXTYPE_COUNT];
|
||||
std::map<std::pair<video::E_VERTEX_TYPE, InstanceType>, GLuint> InstanceVAO;
|
||||
|
||||
void cleanInstanceVAOs();
|
||||
void regenerateBuffer(enum VTXTYPE);
|
||||
void regenerateVAO(enum VTXTYPE);
|
||||
void regenerateInstancedVAO();
|
||||
size_t getVertexPitch(enum VTXTYPE) const;
|
||||
VTXTYPE getVTXTYPE(video::E_VERTEX_TYPE type);
|
||||
void append(scene::IMeshBuffer *, VTXTYPE tp);
|
||||
public:
|
||||
VAOManager();
|
||||
std::pair<unsigned, unsigned> getBase(scene::IMeshBuffer *);
|
||||
GLuint getInstanceBuffer(InstanceType it) { return instance_vbo[it]; }
|
||||
void *getInstanceBufferPtr(InstanceType it) { return Ptr[it]; }
|
||||
unsigned getVBO(video::E_VERTEX_TYPE type) { return vbo[getVTXTYPE(type)]; }
|
||||
void *getVBOPtr(video::E_VERTEX_TYPE type) { return VBOPtr[getVTXTYPE(type)]; }
|
||||
unsigned getVAO(video::E_VERTEX_TYPE type) { return vao[getVTXTYPE(type)]; }
|
||||
unsigned getInstanceVAO(video::E_VERTEX_TYPE vt, enum InstanceType it) { return InstanceVAO[std::pair<video::E_VERTEX_TYPE, InstanceType>(vt, it)]; }
|
||||
~VAOManager();
|
||||
};
|
||||
|
||||
#endif
|
@ -722,16 +722,34 @@ EventPropagation RibbonWidget::transmitEvent(Widget* w,
|
||||
// ----------------------------------------------------------------------------
|
||||
void RibbonWidget::setLabel(const unsigned int id, irr::core::stringw new_name)
|
||||
{
|
||||
// This method should only be called AFTER a widget is added
|
||||
assert(m_element != NULL);
|
||||
if (m_element == NULL)
|
||||
{
|
||||
// before adding
|
||||
m_children[id].setText(new_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
// after adding
|
||||
// ignore this call for ribbons without labels
|
||||
if (m_labels.size() == 0) return;
|
||||
|
||||
assert(id < m_labels.size());
|
||||
m_labels[id].setText(new_name.c_str());
|
||||
//m_text = new_name;
|
||||
}
|
||||
} // setLabel
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void RibbonWidget::setItemVisible(const unsigned int id, bool visible)
|
||||
{
|
||||
m_children[id].setVisible(visible);
|
||||
|
||||
// ignore this call for ribbons without labels
|
||||
if (m_labels.size() == 0) return;
|
||||
|
||||
assert(id < m_labels.size());
|
||||
m_labels[id].setText( new_name.c_str() );
|
||||
m_text = new_name;
|
||||
} // setLabel
|
||||
m_labels[id].setVisible(visible);
|
||||
} // RibbonWidget
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
int RibbonWidget::findItemNamed(const char* internalName)
|
||||
|
@ -152,6 +152,8 @@ namespace GUIEngine
|
||||
*/
|
||||
void setLabel(const unsigned int id, irr::core::stringw new_name);
|
||||
|
||||
void setItemVisible(const unsigned int id, bool visible);
|
||||
|
||||
/** Returns the ID of the item, or -1 if not found */
|
||||
int findItemNamed(const char* internalName);
|
||||
|
||||
|
@ -422,7 +422,7 @@ XMLNode *FileManager::createXMLTreeFromString(const std::string & content)
|
||||
{
|
||||
char *b = new char[content.size()];
|
||||
memcpy(b, content.c_str(), content.size());
|
||||
io::IReadFile * ireadfile = m_file_system->createMemoryReadFile(b, strlen(b), "tempfile", true);
|
||||
io::IReadFile * ireadfile = m_file_system->createMemoryReadFile(b, content.size(), "tempfile", true);
|
||||
io::IXMLReader * reader = m_file_system->createXMLReader(ireadfile);
|
||||
XMLNode* node = new XMLNode(reader);
|
||||
reader->drop();
|
||||
@ -791,7 +791,7 @@ void FileManager::checkAndCreateConfigDir()
|
||||
{
|
||||
m_user_config_dir = getenv("HOME");
|
||||
checkAndCreateDirectory(m_user_config_dir);
|
||||
|
||||
|
||||
m_user_config_dir += "/.config";
|
||||
if(!checkAndCreateDirectory(m_user_config_dir))
|
||||
{
|
||||
|
@ -70,7 +70,6 @@ void GPInfoScreen::loadedFromFile()
|
||||
// The group spinner is filled in init every time the screen is shown
|
||||
// (since the groups can change if addons are added/deleted).
|
||||
m_group_spinner = getWidget<SpinnerWidget>("group-spinner");
|
||||
m_continue_button = getWidget<IconButtonWidget>("continue");
|
||||
m_reverse_spinner = getWidget<SpinnerWidget>("reverse-spinner");
|
||||
m_reverse_spinner->addLabel(_("No"));
|
||||
m_reverse_spinner->addLabel(_("Yes"));
|
||||
@ -118,6 +117,33 @@ GrandPrixData::GPReverseType GPInfoScreen::getReverse() const
|
||||
// Avoid compiler warning
|
||||
return GrandPrixData::GP_NO_REVERSE;
|
||||
} // getReverse
|
||||
// ----------------------------------------------------------------------------
|
||||
void GPInfoScreen::beforeAddingWidget()
|
||||
{
|
||||
bool random = m_gp.isRandomGP();
|
||||
if (!random)
|
||||
{
|
||||
// Check if there is a saved GP:
|
||||
SavedGrandPrix* saved_gp = SavedGrandPrix::getSavedGP(
|
||||
StateManager::get()->getActivePlayerProfile(0)->getUniqueID(),
|
||||
m_gp.getId(),
|
||||
race_manager->getDifficulty(),
|
||||
race_manager->getNumberOfKarts(),
|
||||
race_manager->getNumLocalPlayers());
|
||||
|
||||
RibbonWidget* ribbonButtons = getWidget<RibbonWidget>("buttons");
|
||||
int id_continue_button = ribbonButtons->findItemNamed("continue");
|
||||
ribbonButtons->setItemVisible(id_continue_button, saved_gp != NULL);
|
||||
ribbonButtons->setLabel(id_continue_button, _("Continue saved GP"));
|
||||
}
|
||||
else
|
||||
{
|
||||
RibbonWidget* ribbonButtons = getWidget<RibbonWidget>("buttons");
|
||||
int id_continue_button = ribbonButtons->findItemNamed("continue");
|
||||
ribbonButtons->setItemVisible(id_continue_button, true);
|
||||
ribbonButtons->setLabel(id_continue_button, _("Reload"));
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Called before the screen is shown. It adds the screenshot icon, and
|
||||
@ -144,8 +170,6 @@ void GPInfoScreen::init()
|
||||
rb->setLabel(1,_(L"Reload") );
|
||||
getWidget<LabelWidget>("name")->setText(_("Random Grand Prix"), false);
|
||||
std::string restart = file_manager->getAsset(FileManager::GUI, "restart.png");
|
||||
m_continue_button->setImage(restart, IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);
|
||||
m_continue_button->setVisible(true);
|
||||
|
||||
// We have to recreate the group spinner, but a new group might have
|
||||
// been added or deleted since the last time this screen was shown.
|
||||
@ -188,19 +212,6 @@ void GPInfoScreen::init()
|
||||
{
|
||||
getWidget<LabelWidget>("name")->setText(m_gp.getName(), false);
|
||||
m_gp.checkConsistency();
|
||||
|
||||
// Check if there is a saved GP:
|
||||
SavedGrandPrix* saved_gp =
|
||||
SavedGrandPrix::getSavedGP(StateManager::get()
|
||||
->getActivePlayerProfile(0)->getUniqueID(),
|
||||
m_gp.getId(),
|
||||
race_manager->getDifficulty(),
|
||||
race_manager->getNumberOfKarts(),
|
||||
race_manager->getNumLocalPlayers());
|
||||
|
||||
//I18N: Continue a previously saved Grand Prix.
|
||||
m_continue_button->setText(_(L"Continue saved GP"));
|
||||
m_continue_button->setVisible(saved_gp != NULL);
|
||||
}
|
||||
|
||||
addTracks();
|
||||
|
@ -48,9 +48,6 @@ private:
|
||||
/** Spinner for number of tracks (in case of random GP). */
|
||||
GUIEngine::SpinnerWidget *m_num_tracks_spinner;
|
||||
|
||||
/** The continue/reload (in case of random GP) icon. */
|
||||
GUIEngine::IconButtonWidget *m_continue_button;
|
||||
|
||||
/** The currently selected group name. */
|
||||
std::string m_group_name;
|
||||
|
||||
@ -79,8 +76,9 @@ public:
|
||||
void onEnterPressedInternal();
|
||||
virtual void eventCallback(GUIEngine::Widget *, const std::string &name,
|
||||
const int player_id);
|
||||
virtual void loadedFromFile();
|
||||
virtual void init();
|
||||
virtual void loadedFromFile() OVERRIDE;
|
||||
virtual void init() OVERRIDE;
|
||||
virtual void beforeAddingWidget() OVERRIDE;
|
||||
|
||||
virtual void onUpdate(float dt);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user