Merge branch 'master' of https://github.com/supertuxkart/stk-code into ScriptEngine
This commit is contained in:
commit
b6a9e5be9c
@ -19,7 +19,7 @@
|
||||
I18N="Difficulty" text="SuperTux"/>
|
||||
</ribbon>
|
||||
</box>
|
||||
<spacer height="5%"" width="25"/>
|
||||
<spacer height="5%" width="25"/>
|
||||
|
||||
<box width="95%" height="40%" padding="10" layout="vertical-row">
|
||||
<bright width="100%" text="Select a game mode" align="center" text_align="left" />
|
||||
|
@ -1,12 +1,21 @@
|
||||
uniform vec3 color_from;
|
||||
uniform vec3 color_to;
|
||||
|
||||
#if __VERSION__ >= 330
|
||||
layout(location=0) in vec3 Position;
|
||||
layout(location = 1) in float lifetime;
|
||||
layout(location = 2) in float size;
|
||||
|
||||
layout(location=3) in vec2 Texcoord;
|
||||
layout(location = 4) in vec2 quadcorner;
|
||||
#else
|
||||
in vec3 Position;
|
||||
in float lifetime;
|
||||
in float size;
|
||||
|
||||
in vec2 Texcoord;
|
||||
in vec2 quadcorner;
|
||||
#endif
|
||||
|
||||
out float lf;
|
||||
out vec2 tc;
|
||||
|
@ -9,6 +9,7 @@ uniform float track_x_len;
|
||||
uniform float track_z_len;
|
||||
uniform samplerBuffer heightmap;
|
||||
|
||||
#if __VERSION__ >= 330
|
||||
layout (location = 4) in vec3 particle_position_initial;
|
||||
layout (location = 5) in float lifetime_initial;
|
||||
layout (location = 6) in vec3 particle_velocity_initial;
|
||||
@ -18,6 +19,17 @@ layout (location = 0) in vec3 particle_position;
|
||||
layout (location = 1) in float lifetime;
|
||||
layout (location = 2) in vec3 particle_velocity;
|
||||
layout (location = 3) in float size;
|
||||
#else
|
||||
in vec3 particle_position_initial;
|
||||
in float lifetime_initial;
|
||||
in vec3 particle_velocity_initial;
|
||||
in float size_initial;
|
||||
|
||||
in vec3 particle_position;
|
||||
in float lifetime;
|
||||
in vec3 particle_velocity;
|
||||
in float size;
|
||||
#endif
|
||||
|
||||
out vec3 new_particle_position;
|
||||
out float new_lifetime;
|
||||
|
@ -3,6 +3,7 @@ uniform mat4 sourcematrix;
|
||||
uniform int level;
|
||||
uniform float size_increase_factor;
|
||||
|
||||
#if __VERSION__ >= 330
|
||||
layout (location = 4) in vec3 particle_position_initial;
|
||||
layout (location = 5) in float lifetime_initial;
|
||||
layout (location = 6) in vec3 particle_velocity_initial;
|
||||
@ -12,6 +13,17 @@ layout (location = 0) in vec3 particle_position;
|
||||
layout (location = 1) in float lifetime;
|
||||
layout (location = 2) in vec3 particle_velocity;
|
||||
layout (location = 3) in float size;
|
||||
#else
|
||||
in vec3 particle_position_initial;
|
||||
in float lifetime_initial;
|
||||
in vec3 particle_velocity_initial;
|
||||
in float size_initial;
|
||||
|
||||
in vec3 particle_position;
|
||||
in float lifetime;
|
||||
in vec3 particle_velocity;
|
||||
in float size;
|
||||
#endif
|
||||
|
||||
out vec3 new_particle_position;
|
||||
out float new_lifetime;
|
||||
|
@ -3,6 +3,8 @@
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
extern bool GLContextDebugBit;
|
||||
|
||||
#include "CIrrDeviceLinux.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_X11_DEVICE_
|
||||
@ -497,7 +499,7 @@ void IrrPrintXGrabError(int grabResult, const c8 * grabCommand )
|
||||
static GLXContext getMeAGLContext(Display *display, GLXFBConfig glxFBConfig)
|
||||
{
|
||||
GLXContext Context;
|
||||
int compat33ctx[] =
|
||||
int compat33ctxdebug[] =
|
||||
{
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, 3,
|
||||
@ -505,7 +507,14 @@ static GLXContext getMeAGLContext(Display *display, GLXFBConfig glxFBConfig)
|
||||
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB,
|
||||
None
|
||||
};
|
||||
int core33ctx[] =
|
||||
int compat33ctx[] =
|
||||
{
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, 3,
|
||||
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
||||
None
|
||||
};
|
||||
int core33ctxdebug[] =
|
||||
{
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, 3,
|
||||
@ -513,12 +522,26 @@ static GLXContext getMeAGLContext(Display *display, GLXFBConfig glxFBConfig)
|
||||
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB,
|
||||
None
|
||||
};
|
||||
int core33ctx[] =
|
||||
{
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, 3,
|
||||
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
|
||||
None
|
||||
};
|
||||
int core31ctxdebug[] =
|
||||
{
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, 1,
|
||||
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
|
||||
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB,
|
||||
None
|
||||
};
|
||||
int core31ctx[] =
|
||||
{
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, 1,
|
||||
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
|
||||
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB,
|
||||
None
|
||||
};
|
||||
int legacyctx[] =
|
||||
@ -532,19 +555,19 @@ static GLXContext getMeAGLContext(Display *display, GLXFBConfig glxFBConfig)
|
||||
glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
|
||||
|
||||
// create compat 3.3 context (for proprietary drivers)
|
||||
Context = glXCreateContextAttribsARB(display, glxFBConfig, 0, True, compat33ctx);
|
||||
Context = glXCreateContextAttribsARB(display, glxFBConfig, 0, True, GLContextDebugBit ? compat33ctxdebug : compat33ctx);
|
||||
if (!XErrorSignaled)
|
||||
return Context;
|
||||
|
||||
XErrorSignaled = false;
|
||||
// create core 3.3 context (for mesa)
|
||||
Context = glXCreateContextAttribsARB(display, glxFBConfig, 0, True, core33ctx);
|
||||
Context = glXCreateContextAttribsARB(display, glxFBConfig, 0, True, GLContextDebugBit ? core33ctxdebug : core33ctx);
|
||||
if (!XErrorSignaled)
|
||||
return Context;
|
||||
|
||||
XErrorSignaled = false;
|
||||
// create core 3.1 context (for older mesa)
|
||||
Context = glXCreateContextAttribsARB(display, glxFBConfig, 0, True, core31ctx);
|
||||
Context = glXCreateContextAttribsARB(display, glxFBConfig, 0, True, GLContextDebugBit ? core31ctxdebug : core31ctx);
|
||||
if (!XErrorSignaled)
|
||||
return Context;
|
||||
|
||||
|
@ -2,6 +2,9 @@
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
|
||||
extern bool GLContextDebugBit;
|
||||
|
||||
#include "COpenGLDriver.h"
|
||||
// needed here also because of the create methods' parameters
|
||||
#include "CNullDriver.h"
|
||||
@ -89,7 +92,7 @@ static PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs_ARB;
|
||||
static HGLRC getMeAGLContext(HDC HDc)
|
||||
{
|
||||
HGLRC hrc = 0;
|
||||
int ctx44[] =
|
||||
int ctx44debug[] =
|
||||
{
|
||||
WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
|
||||
WGL_CONTEXT_MINOR_VERSION_ARB, 3,
|
||||
@ -98,11 +101,19 @@ static HGLRC getMeAGLContext(HDC HDc)
|
||||
0
|
||||
};
|
||||
|
||||
hrc = wglCreateContextAttribs_ARB(HDc, 0, ctx44);
|
||||
int ctx44[] =
|
||||
{
|
||||
WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
|
||||
WGL_CONTEXT_MINOR_VERSION_ARB, 3,
|
||||
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
||||
0
|
||||
};
|
||||
|
||||
hrc = wglCreateContextAttribs_ARB(HDc, 0, GLContextDebugBit ? ctx44debug : ctx44);
|
||||
if (hrc)
|
||||
return hrc;
|
||||
|
||||
int ctx40[] =
|
||||
int ctx40debug[] =
|
||||
{
|
||||
WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
|
||||
WGL_CONTEXT_MINOR_VERSION_ARB, 0,
|
||||
@ -111,11 +122,19 @@ static HGLRC getMeAGLContext(HDC HDc)
|
||||
0
|
||||
};
|
||||
|
||||
hrc = wglCreateContextAttribs_ARB(HDc, 0, ctx40);
|
||||
int ctx40[] =
|
||||
{
|
||||
WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
|
||||
WGL_CONTEXT_MINOR_VERSION_ARB, 0,
|
||||
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
||||
0
|
||||
};
|
||||
|
||||
hrc = wglCreateContextAttribs_ARB(HDc, 0, GLContextDebugBit ? ctx40debug : ctx40);
|
||||
if (hrc)
|
||||
return hrc;
|
||||
|
||||
int ctx33[] =
|
||||
int ctx33debug[] =
|
||||
{
|
||||
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
|
||||
WGL_CONTEXT_MINOR_VERSION_ARB, 3,
|
||||
@ -124,11 +143,19 @@ static HGLRC getMeAGLContext(HDC HDc)
|
||||
0
|
||||
};
|
||||
|
||||
hrc = wglCreateContextAttribs_ARB(HDc, 0, ctx33);
|
||||
int ctx33[] =
|
||||
{
|
||||
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
|
||||
WGL_CONTEXT_MINOR_VERSION_ARB, 3,
|
||||
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
||||
0
|
||||
};
|
||||
|
||||
hrc = wglCreateContextAttribs_ARB(HDc, 0, GLContextDebugBit ? ctx33debug : ctx33);
|
||||
if (hrc)
|
||||
return hrc;
|
||||
|
||||
int ctx31[] =
|
||||
int ctx31debug[] =
|
||||
{
|
||||
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
|
||||
WGL_CONTEXT_MINOR_VERSION_ARB, 1,
|
||||
@ -136,7 +163,15 @@ static HGLRC getMeAGLContext(HDC HDc)
|
||||
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
||||
0
|
||||
};
|
||||
hrc = wglCreateContextAttribs_ARB(HDc, 0, ctx31);
|
||||
|
||||
int ctx31[] =
|
||||
{
|
||||
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
|
||||
WGL_CONTEXT_MINOR_VERSION_ARB, 1,
|
||||
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
||||
0
|
||||
};
|
||||
hrc = wglCreateContextAttribs_ARB(HDc, 0, GLContextDebugBit ? ctx31debug : ctx31);
|
||||
if (hrc)
|
||||
return hrc;
|
||||
|
||||
|
@ -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>
|
||||
}
|
||||
@ -29,12 +35,6 @@ extern "C" {
|
||||
# include <GL/glext.h>
|
||||
#endif
|
||||
|
||||
#define Bindless_Texture_Support
|
||||
#define Base_Instance_Support
|
||||
#define Buffer_Storage
|
||||
#define Multi_Draw_Indirect
|
||||
#define Draw_Indirect
|
||||
|
||||
struct DrawElementsIndirectCommand{
|
||||
GLuint count;
|
||||
GLuint instanceCount;
|
||||
@ -43,4 +43,4 @@ struct DrawElementsIndirectCommand{
|
||||
GLuint baseInstance;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -11,6 +11,12 @@
|
||||
|
||||
static bool is_gl_init = false;
|
||||
|
||||
#if DEBUG
|
||||
bool GLContextDebugBit = true;
|
||||
#else
|
||||
bool GLContextDebugBit = false;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#if !defined(__APPLE__)
|
||||
#define ARB_DEBUG_OUTPUT
|
||||
@ -181,10 +187,46 @@ GLuint LoadShader(const char * file, unsigned type)
|
||||
return Id;
|
||||
}
|
||||
|
||||
void setAttribute(AttributeType Tp, GLuint ProgramID)
|
||||
{
|
||||
switch (Tp)
|
||||
{
|
||||
case OBJECT:
|
||||
glBindAttribLocation(ProgramID, 0, "Position");
|
||||
glBindAttribLocation(ProgramID, 1, "Normal");
|
||||
glBindAttribLocation(ProgramID, 2, "Color");
|
||||
glBindAttribLocation(ProgramID, 3, "Texcoord");
|
||||
glBindAttribLocation(ProgramID, 4, "SecondTexcoord");
|
||||
glBindAttribLocation(ProgramID, 5, "Tangent");
|
||||
glBindAttribLocation(ProgramID, 6, "Bitangent");
|
||||
glBindAttribLocation(ProgramID, 7, "Origin");
|
||||
glBindAttribLocation(ProgramID, 8, "Orientation");
|
||||
glBindAttribLocation(ProgramID, 9, "Scale");
|
||||
break;
|
||||
case PARTICLES_SIM:
|
||||
glBindAttribLocation(ProgramID, 0, "particle_position");
|
||||
glBindAttribLocation(ProgramID, 1, "lifetime");
|
||||
glBindAttribLocation(ProgramID, 2, "particle_velocity");
|
||||
glBindAttribLocation(ProgramID, 3, "size");
|
||||
glBindAttribLocation(ProgramID, 4, "particle_position_initial");
|
||||
glBindAttribLocation(ProgramID, 5, "lifetime_initial");
|
||||
glBindAttribLocation(ProgramID, 6, "particle_velocity_initial");
|
||||
glBindAttribLocation(ProgramID, 7, "size_initial");
|
||||
break;
|
||||
case PARTICLES_RENDERING:
|
||||
glBindAttribLocation(ProgramID, 1, "lifetime");
|
||||
glBindAttribLocation(ProgramID, 2, "size");
|
||||
glBindAttribLocation(ProgramID, 4, "quadcorner");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount)
|
||||
{
|
||||
GLuint Program = glCreateProgram();
|
||||
loadAndAttach(Program, GL_VERTEX_SHADER, vertex_file_path);
|
||||
if (irr_driver->getGLSLVersion() < 330)
|
||||
setAttribute(PARTICLES_SIM, Program);
|
||||
glTransformFeedbackVaryings(Program, varyingscount, varyings, GL_INTERLEAVED_ATTRIBS);
|
||||
glLinkProgram(Program);
|
||||
|
||||
@ -397,340 +439,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);
|
||||
@ -42,24 +42,22 @@ void printFileList(GLint ShaderType, const char *filepath, Types ... args)
|
||||
printFileList(args...);
|
||||
}
|
||||
|
||||
enum AttributeType
|
||||
{
|
||||
OBJECT,
|
||||
PARTICLES_SIM,
|
||||
PARTICLES_RENDERING,
|
||||
};
|
||||
|
||||
void setAttribute(AttributeType Tp, GLuint ProgramID);
|
||||
|
||||
template<typename ... Types>
|
||||
GLint LoadProgram(Types ... args)
|
||||
GLint LoadProgram(AttributeType Tp, Types ... args)
|
||||
{
|
||||
GLint ProgramID = glCreateProgram();
|
||||
loadAndAttach(ProgramID, args...);
|
||||
if (irr_driver->getGLSLVersion() < 330)
|
||||
{
|
||||
glBindAttribLocation(ProgramID, 0, "Position");
|
||||
glBindAttribLocation(ProgramID, 1, "Normal");
|
||||
glBindAttribLocation(ProgramID, 2, "Color");
|
||||
glBindAttribLocation(ProgramID, 3, "Texcoord");
|
||||
glBindAttribLocation(ProgramID, 4, "SecondTexcoord");
|
||||
glBindAttribLocation(ProgramID, 5, "Tangent");
|
||||
glBindAttribLocation(ProgramID, 6, "Bitangent");
|
||||
glBindAttribLocation(ProgramID, 7, "Origin");
|
||||
glBindAttribLocation(ProgramID, 8, "Orientation");
|
||||
glBindAttribLocation(ProgramID, 9, "Scale");
|
||||
}
|
||||
setAttribute(Tp, ProgramID);
|
||||
glLinkProgram(ProgramID);
|
||||
|
||||
GLint Result = GL_FALSE;
|
||||
@ -139,110 +137,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);
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/glwrap.hpp"
|
||||
#include "gpuparticles.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
|
@ -1,8 +1,6 @@
|
||||
#ifndef GPUPARTICLES_H
|
||||
#define GPUPARTICLES_H
|
||||
|
||||
#include "graphics/glwrap.hpp"
|
||||
|
||||
#include "../lib/irrlicht/source/Irrlicht/CParticleSystemSceneNode.h"
|
||||
#include <ISceneManager.h>
|
||||
#include <IParticleSystemSceneNode.h>
|
||||
|
@ -504,34 +504,35 @@ void IrrDriver::initDevice()
|
||||
hasComputeShaders = false;
|
||||
hasTextureStorage = false;
|
||||
// Default false value for hasVSLayer if --no-graphics argument is used
|
||||
#if !defined(__APPLE__)
|
||||
if (!ProfileWorld::isNoGraphics())
|
||||
{
|
||||
if (GLEW_AMD_vertex_shader_layer) {
|
||||
if (hasGLExtension("GL_AMD_vertex_shader_layer")) {
|
||||
hasVSLayer = true;
|
||||
Log::info("GLDriver", "AMD Vertex Shader Layer enabled");
|
||||
}
|
||||
if (GLEW_ARB_buffer_storage) {
|
||||
if (hasGLExtension("GL_ARB_buffer_storage")) {
|
||||
hasBuffserStorage = true;
|
||||
Log::info("GLDriver", "ARB Buffer Storage enabled");
|
||||
}
|
||||
if (GLEW_ARB_base_instance) {
|
||||
if (hasGLExtension("GL_ARB_base_instance")) {
|
||||
hasBaseInstance = true;
|
||||
Log::info("GLDriver", "ARB Base Instance enabled");
|
||||
}
|
||||
if (GLEW_ARB_draw_indirect) {
|
||||
if (hasGLExtension("GL_ARB_draw_indirect")) {
|
||||
hasDrawIndirect = true;
|
||||
Log::info("GLDriver", "ARB Draw Indirect enabled");
|
||||
}
|
||||
if (GLEW_ARB_compute_shader) {
|
||||
if (hasGLExtension("GL_ARB_compute_shader")) {
|
||||
hasComputeShaders = true;
|
||||
Log::info("GLDriver", "ARB Compute Shader enabled");
|
||||
}
|
||||
if (GLEW_ARB_texture_storage) {
|
||||
if (hasGLExtension("GL_ARB_texture_storage")) {
|
||||
hasTextureStorage = true;
|
||||
Log::info("GLDriver", "ARB Texture Storage enabled");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// This remaps the window, so it has to be done before the clear to avoid flicker
|
||||
@ -1742,17 +1743,12 @@ 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 = StringUtils::insertValues(_("FPS: %d/%d/%d - PolyCount: %d Solid, %d Shadows - LightDist : %d"),
|
||||
min, fps, max, poly_count[SOLID_NORMAL_AND_DEPTH_PASS], poly_count[SHADOW_PASS], 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;
|
||||
@ -1760,12 +1756,7 @@ void IrrDriver::displayFPS()
|
||||
object_count[TRANSPARENT_PASS] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(buffer, "FPS: %i/%i/%i - %i KTris", min, fps, max,
|
||||
(int)roundf(kilotris));
|
||||
}
|
||||
|
||||
core::stringw fpsString = buffer;
|
||||
fpsString = StringUtils::insertValues(_("FPS: %d/%d/%d - %d KTris"), min, fps, max, (int)roundf(kilotris));
|
||||
|
||||
static video::SColor fpsColor = video::SColor(255, 0, 0, 0);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -68,6 +68,9 @@ void LODNode::render()
|
||||
*/
|
||||
int LODNode::getLevel()
|
||||
{
|
||||
if (m_nodes.size() == 0)
|
||||
return -1;
|
||||
|
||||
// If a level is forced, use it
|
||||
if(m_forced_lod>-1)
|
||||
return m_forced_lod;
|
||||
@ -79,14 +82,13 @@ int LODNode::getLevel()
|
||||
AbstractKart* kart = camera->getKart();
|
||||
const Vec3 &pos = kart->getFrontXYZ();
|
||||
|
||||
// Assumes all children are at the same location
|
||||
const int dist =
|
||||
(int)((getPosition() + m_nodes[0]->getPosition()).getDistanceFromSQ( core::vector3df(pos.getX(), pos.getY(), pos.getZ())));
|
||||
(int)((m_nodes[0]->getAbsolutePosition()).getDistanceFromSQ( core::vector3df(pos.getX(), pos.getY(), pos.getZ())));
|
||||
|
||||
for (unsigned int n=0; n<m_detail.size(); n++)
|
||||
{
|
||||
if (dist < m_detail[n])
|
||||
return n;
|
||||
return n;
|
||||
}
|
||||
|
||||
// If it's the shadow pass, and we would have otherwise hidden the item, show the min one
|
||||
@ -108,7 +110,7 @@ void LODNode::forceLevelOfDetail(int n)
|
||||
// ----------------------------------------------------------------------------
|
||||
void LODNode::OnAnimate(u32 timeMs)
|
||||
{
|
||||
if (isVisible())
|
||||
if (isVisible() && m_nodes.size() > 0)
|
||||
{
|
||||
// update absolute position
|
||||
updateAbsolutePosition();
|
||||
|
@ -337,7 +337,7 @@ void PostProcessing::renderGaussian17TapBlur(FrameBuffer &in_fbo, FrameBuffer &a
|
||||
assert(in_fbo.getWidth() == auxiliary.getWidth() && in_fbo.getHeight() == auxiliary.getHeight());
|
||||
float inv_width = 1.0f / in_fbo.getWidth(), inv_height = 1.0f / in_fbo.getHeight();
|
||||
{
|
||||
if (irr_driver->hasARBComputeShaders())
|
||||
if (!irr_driver->hasARBComputeShaders())
|
||||
{
|
||||
auxiliary.Bind();
|
||||
FullScreenShader::Gaussian17TapHShader::getInstance()->SetTextureUnits(createVector<GLuint>(in_fbo.getRTT()[0], irr_driver->getFBO(FBO_LINEAR_DEPTH).getRTT()[0]));
|
||||
@ -355,7 +355,7 @@ void PostProcessing::renderGaussian17TapBlur(FrameBuffer &in_fbo, FrameBuffer &a
|
||||
}
|
||||
}
|
||||
{
|
||||
if (irr_driver->hasARBComputeShaders())
|
||||
if (!irr_driver->hasARBComputeShaders())
|
||||
{
|
||||
in_fbo.Bind();
|
||||
|
||||
|
@ -22,7 +22,8 @@
|
||||
#include "S3DVertex.h"
|
||||
#include "SMaterial.h"
|
||||
#include "graphics/camera.hpp"
|
||||
#include "graphics/glwrap.hpp"
|
||||
|
||||
class FrameBuffer;
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
@ -47,6 +47,9 @@
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/profiler.hpp"
|
||||
#include "stkscenemanager.hpp"
|
||||
#include "items/powerup_manager.hpp"
|
||||
#include "../../lib/irrlicht/source/Irrlicht/CSceneManager.h"
|
||||
#include "../../lib/irrlicht/source/Irrlicht/os.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
@ -60,6 +63,27 @@ void IrrDriver::renderGLSL(float dt)
|
||||
|
||||
Track *track = world->getTrack();
|
||||
|
||||
for (unsigned i = 0; i < PowerupManager::POWERUP_MAX; i++)
|
||||
{
|
||||
scene::IMesh *mesh = powerup_manager->m_all_meshes[i];
|
||||
if (!mesh)
|
||||
continue;
|
||||
for (unsigned j = 0; j < mesh->getMeshBufferCount(); j++)
|
||||
{
|
||||
scene::IMeshBuffer *mb = mesh->getMeshBuffer(j);
|
||||
if (!mb)
|
||||
continue;
|
||||
for (unsigned k = 0; k < 4; k++)
|
||||
{
|
||||
video::ITexture *tex = mb->getMaterial().getTexture(k);
|
||||
if (!tex)
|
||||
continue;
|
||||
compressTexture(tex, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Overrides
|
||||
video::SOverrideMaterial &overridemat = m_video_driver->getOverrideMaterial();
|
||||
overridemat.EnablePasses = scene::ESNRP_SOLID | scene::ESNRP_TRANSPARENT;
|
||||
@ -311,7 +335,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();
|
||||
}
|
||||
|
||||
@ -572,7 +596,8 @@ core::matrix4 getTighestFitOrthoProj(const core::matrix4 &transform, const std::
|
||||
|
||||
void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, size_t width, size_t height)
|
||||
{
|
||||
m_scene_manager->drawAll(scene::ESNRP_CAMERA);
|
||||
static_cast<scene::CSceneManager *>(m_scene_manager)->OnAnimate(os::Timer::getTime());
|
||||
camnode->render();
|
||||
irr_driver->setProjMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION));
|
||||
irr_driver->setViewMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW));
|
||||
irr_driver->genProjViewMatrix();
|
||||
|
@ -32,6 +32,51 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
/**
|
||||
\page render_geometry Geometry Rendering Overview
|
||||
|
||||
/**
|
||||
\section adding_material Adding a solid material
|
||||
|
||||
You need to consider twice before adding a new material : in the worst case a material requires 8 shaders :
|
||||
one for each solid pass, one for shadow pass, one for RSM pass, and you need to double that for instanced version.
|
||||
|
||||
You need to declare a new enum in MeshMaterial and to write the corresponding dispatch code in MaterialTypeToMeshMaterial
|
||||
and to create 2 new List* structures (one for standard and one for instanced version).
|
||||
|
||||
Then you need to write the code in stkscenemanager.cpp that will add any mesh with the new material to their corresponding
|
||||
lists : in handleSTKCommon for the standard version and in the body of PrepareDrawCalls for instanced version.
|
||||
|
||||
\section vertex_layout Available Vertex Layout
|
||||
|
||||
There are 3 different layout that comes from Irrlicht loading routines :
|
||||
EVT_STANDARD, EVT_2TCOORDS, EVT_TANGENT.
|
||||
|
||||
Below are the attributes for each vertex layout and their predefined location.
|
||||
|
||||
\subsection EVT_STANDARD
|
||||
layout(location = 0) in vec3 Position;
|
||||
layout(location = 1) in vec3 Normal;
|
||||
layout(location = 2) in vec4 Color;
|
||||
layout(location = 3) in vec2 Texcoord;
|
||||
|
||||
\subsection EVT_2TCOORDS
|
||||
layout(location = 0) in vec3 Position;
|
||||
layout(location = 1) in vec3 Normal;
|
||||
layout(location = 2) in vec4 Color;
|
||||
layout(location = 3) in vec2 Texcoord;
|
||||
layout(location = 4) in vec2 SecondTexcoord;
|
||||
|
||||
\subsection EVT_TANGENT
|
||||
layout(location = 0) in vec3 Position;
|
||||
layout(location = 1) in vec3 Normal;
|
||||
layout(location = 2) in vec4 Color;
|
||||
layout(location = 3) in vec2 Texcoord;
|
||||
layout(location = 5) in vec3 Tangent;
|
||||
layout(location = 6) in vec3 Bitangent;
|
||||
|
||||
*/
|
||||
|
||||
namespace RenderGeometry
|
||||
{
|
||||
struct TexUnit
|
||||
@ -151,7 +196,6 @@ void renderMeshes1stPass(const std::vector<TexUnit> &TexUnits, std::vector<STK::
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef Draw_Indirect
|
||||
template<typename Shader, MeshMaterial Mat, video::E_VERTEX_TYPE VT, typename...Args>
|
||||
void renderInstancedMeshes1stPass(const std::vector<TexUnit> &TexUnits, std::vector<GLMesh *> &meshes, Args...args)
|
||||
{
|
||||
@ -173,9 +217,7 @@ void renderInstancedMeshes1stPass(const std::vector<TexUnit> &TexUnits, std::vec
|
||||
glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((SolidPassCmd::getInstance()->Offset[Mat] + i) * sizeof(DrawElementsIndirectCommand)));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef Multi_Draw_Indirect
|
||||
template<typename Shader, MeshMaterial Mat, video::E_VERTEX_TYPE VT, typename...Args>
|
||||
void multidraw1stPass(Args...args)
|
||||
{
|
||||
@ -190,7 +232,6 @@ void multidraw1stPass(Args...args)
|
||||
sizeof(DrawElementsIndirectCommand));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static core::vector3df windDir;
|
||||
|
||||
@ -208,6 +249,9 @@ void IrrDriver::renderSolidFirstPass()
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
if (irr_driver->hasARB_draw_indirect())
|
||||
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, SolidPassCmd::getInstance()->drawindirectcmd);
|
||||
|
||||
if (!UserConfigParams::m_dynamic_lights)
|
||||
return;
|
||||
|
||||
@ -231,12 +275,8 @@ void IrrDriver::renderSolidFirstPass()
|
||||
renderMeshes1stPass<MeshShader::ObjectPass1Shader, video::EVT_STANDARD, 2, 1>(object_pass1_texunits, ListMatSphereMap::getInstance()->SolidPass);
|
||||
renderMeshes1stPass<MeshShader::ObjectPass1Shader, video::EVT_2TCOORDS, 2, 1>(object_pass1_texunits, ListMatDetails::getInstance()->SolidPass);
|
||||
|
||||
if (irr_driver->hasARB_draw_indirect())
|
||||
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, SolidPassCmd::getInstance()->drawindirectcmd);
|
||||
|
||||
if (UserConfigParams::m_azdo)
|
||||
{
|
||||
#ifdef Multi_Draw_Indirect
|
||||
multidraw1stPass<MeshShader::InstancedObjectPass1Shader, MAT_DEFAULT, video::EVT_STANDARD>();
|
||||
multidraw1stPass<MeshShader::InstancedObjectRefPass1Shader, MAT_ALPHA_REF, video::EVT_STANDARD>();
|
||||
multidraw1stPass<MeshShader::InstancedNormalMapShader, MAT_NORMAL_MAP, video::EVT_TANGENTS>();
|
||||
@ -244,9 +284,7 @@ void IrrDriver::renderSolidFirstPass()
|
||||
multidraw1stPass<MeshShader::InstancedObjectPass1Shader, MAT_DETAIL, video::EVT_2TCOORDS>();
|
||||
multidraw1stPass<MeshShader::InstancedObjectRefPass1Shader, MAT_UNLIT, video::EVT_STANDARD>();
|
||||
multidraw1stPass<MeshShader::InstancedGrassPass1Shader, MAT_GRASS, video::EVT_STANDARD>(windDir);
|
||||
#endif
|
||||
}
|
||||
#ifdef Draw_Indirect
|
||||
else if (irr_driver->hasARB_draw_indirect())
|
||||
{
|
||||
// Default
|
||||
@ -273,7 +311,6 @@ void IrrDriver::renderSolidFirstPass()
|
||||
renderInstancedMeshes1stPass<MeshShader::InstancedNormalMapShader, MAT_NORMAL_MAP, video::EVT_TANGENTS>(
|
||||
TexUnits(TexUnit(1, false), TexUnit(0, true)), ListInstancedMatNormalMap::getInstance()->SolidPass);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -315,7 +352,6 @@ void renderMeshes2ndPass(const std::vector<TexUnit> &TexUnits, std::vector<STK::
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef Draw_Indirect
|
||||
template<typename Shader, MeshMaterial Mat, video::E_VERTEX_TYPE VT, typename...Args>
|
||||
void renderInstancedMeshes2ndPass(const std::vector<TexUnit> &TexUnits, const std::vector<GLuint> &Prefilled_tex, std::vector<GLMesh *> &meshes, Args...args)
|
||||
{
|
||||
@ -332,9 +368,7 @@ void renderInstancedMeshes2ndPass(const std::vector<TexUnit> &TexUnits, const st
|
||||
glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((SolidPassCmd::getInstance()->Offset[Mat] + i) * sizeof(DrawElementsIndirectCommand)));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef Multi_Draw_Indirect
|
||||
template<typename Shader, MeshMaterial Mat, video::E_VERTEX_TYPE VT, typename...Args>
|
||||
void multidraw2ndPass(const std::vector<uint64_t> &Handles, Args... args)
|
||||
{
|
||||
@ -350,7 +384,6 @@ void multidraw2ndPass(const std::vector<uint64_t> &Handles, Args... args)
|
||||
sizeof(DrawElementsIndirectCommand));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void IrrDriver::renderSolidSecondPass()
|
||||
{
|
||||
@ -379,7 +412,6 @@ void IrrDriver::renderSolidSecondPass()
|
||||
|
||||
if (UserConfigParams::m_azdo)
|
||||
{
|
||||
#ifdef Bindless_Texture_Support
|
||||
DiffuseHandle = glGetTextureSamplerHandleARB(m_rtts->getRenderTarget(RTT_DIFFUSE), MeshShader::ObjectPass2Shader::getInstance()->SamplersId[0]);
|
||||
if (!glIsTextureHandleResidentARB(DiffuseHandle))
|
||||
glMakeTextureHandleResidentARB(DiffuseHandle);
|
||||
@ -395,7 +427,6 @@ void IrrDriver::renderSolidSecondPass()
|
||||
DepthHandle = glGetTextureSamplerHandleARB(getDepthStencilTexture(), MeshShader::ObjectPass2Shader::getInstance()->SamplersId[3]);
|
||||
if (!glIsTextureHandleResidentARB(DepthHandle))
|
||||
glMakeTextureHandleResidentARB(DepthHandle);
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
@ -441,7 +472,6 @@ void IrrDriver::renderSolidSecondPass()
|
||||
|
||||
if (UserConfigParams::m_azdo)
|
||||
{
|
||||
#ifdef Multi_Draw_Indirect
|
||||
multidraw2ndPass<MeshShader::InstancedObjectPass2Shader, MAT_DEFAULT, video::EVT_STANDARD>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0));
|
||||
multidraw2ndPass<MeshShader::InstancedObjectPass2Shader, MAT_NORMAL_MAP, video::EVT_TANGENTS>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0));
|
||||
multidraw2ndPass<MeshShader::InstancedObjectRefPass2Shader, MAT_ALPHA_REF, video::EVT_STANDARD>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0));
|
||||
@ -450,9 +480,7 @@ void IrrDriver::renderSolidSecondPass()
|
||||
multidraw2ndPass<MeshShader::InstancedObjectUnlitShader, MAT_UNLIT, video::EVT_STANDARD>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0));
|
||||
SunLightProvider * const cb = (SunLightProvider *)irr_driver->getCallback(ES_SUNLIGHT);
|
||||
multidraw2ndPass<MeshShader::InstancedGrassPass2Shader, MAT_GRASS, video::EVT_STANDARD>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, DepthHandle, 0), windDir, cb->getPosition());
|
||||
#endif
|
||||
}
|
||||
#ifdef Draw_Indirect
|
||||
else if (irr_driver->hasARB_draw_indirect())
|
||||
{
|
||||
// Default
|
||||
@ -481,7 +509,6 @@ void IrrDriver::renderSolidSecondPass()
|
||||
renderInstancedMeshes2ndPass<MeshShader::InstancedGrassPass2Shader, MAT_GRASS, video::EVT_STANDARD>(
|
||||
TexUnits(TexUnit(0, true)), DiffSpecSSAOTex, ListInstancedMatGrass::getInstance()->SolidPass, windDir, cb->getPosition());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -537,12 +564,10 @@ void renderTransparenPass(const std::vector<TexUnit> &TexUnits, std::vector<STK:
|
||||
compressTexture(mesh.textures[TexUnits[j].m_id], TexUnits[j].m_premul_alpha);
|
||||
if (UserConfigParams::m_azdo)
|
||||
{
|
||||
#ifdef Bindless_Texture_Support
|
||||
if (!mesh.TextureHandles[TexUnits[j].m_id])
|
||||
mesh.TextureHandles[TexUnits[j].m_id] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh.textures[TexUnits[j].m_id]), Shader::getInstance()->SamplersId[Handles.size()]);
|
||||
if (!glIsTextureHandleResidentARB(mesh.TextureHandles[TexUnits[j].m_id]))
|
||||
glMakeTextureHandleResidentARB(mesh.TextureHandles[TexUnits[j].m_id]);
|
||||
#endif
|
||||
Handles.push_back(mesh.TextureHandles[TexUnits[j].m_id]);
|
||||
}
|
||||
else
|
||||
@ -752,7 +777,6 @@ void renderShadow(const std::vector<GLuint> TextureUnits, unsigned cascade, cons
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef Draw_Indirect
|
||||
template<typename Shader, MeshMaterial Mat, video::E_VERTEX_TYPE VT, typename...Args>
|
||||
void renderInstancedShadow(const std::vector<GLuint> TextureUnits, unsigned cascade, const std::vector<GLMesh *> &t, Args ...args)
|
||||
{
|
||||
@ -773,9 +797,7 @@ void renderInstancedShadow(const std::vector<GLuint> TextureUnits, unsigned casc
|
||||
glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((tmp) * sizeof(DrawElementsIndirectCommand)));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef Multi_Draw_Indirect
|
||||
template<typename Shader, MeshMaterial Mat, video::E_VERTEX_TYPE VT, typename...Args>
|
||||
static void multidrawShadow(unsigned i, Args ...args)
|
||||
{
|
||||
@ -787,7 +809,6 @@ static void multidrawShadow(unsigned i, Args ...args)
|
||||
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)(ShadowPassCmd::getInstance()->Offset[i][Mat] * sizeof(DrawElementsIndirectCommand)), ShadowPassCmd::getInstance()->Size[i][Mat], sizeof(DrawElementsIndirectCommand));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void IrrDriver::renderShadows()
|
||||
{
|
||||
@ -824,16 +845,13 @@ void IrrDriver::renderShadows()
|
||||
|
||||
if (UserConfigParams::m_azdo)
|
||||
{
|
||||
#ifdef Multi_Draw_Indirect
|
||||
multidrawShadow<MeshShader::InstancedShadowShader, MAT_DEFAULT, video::EVT_STANDARD>(cascade);
|
||||
multidrawShadow<MeshShader::InstancedShadowShader, MAT_DETAIL, video::EVT_2TCOORDS>(cascade);
|
||||
multidrawShadow<MeshShader::InstancedShadowShader, MAT_NORMAL_MAP, video::EVT_TANGENTS>(cascade);
|
||||
multidrawShadow<MeshShader::InstancedRefShadowShader, MAT_ALPHA_REF, video::EVT_STANDARD>(cascade);
|
||||
multidrawShadow<MeshShader::InstancedRefShadowShader, MAT_UNLIT, video::EVT_STANDARD>(cascade);
|
||||
multidrawShadow<MeshShader::InstancedGrassShadowShader, MAT_GRASS, video::EVT_STANDARD>(cascade, windDir);
|
||||
#endif
|
||||
}
|
||||
#ifdef Draw_Indirect
|
||||
else if (irr_driver->hasARB_draw_indirect())
|
||||
{
|
||||
renderInstancedShadow<MeshShader::InstancedShadowShader, MAT_DEFAULT, video::EVT_STANDARD>(noTexUnits, cascade, ListInstancedMatDefault::getInstance()->Shadows[cascade]);
|
||||
@ -843,7 +861,6 @@ void IrrDriver::renderShadows()
|
||||
renderInstancedShadow<MeshShader::InstancedGrassShadowShader, MAT_GRASS, video::EVT_STANDARD>(std::vector < GLuint > { 0 }, cascade, ListInstancedMatGrass::getInstance()->Shadows[cascade], windDir);
|
||||
renderInstancedShadow<MeshShader::InstancedShadowShader, MAT_NORMAL_MAP, video::EVT_TANGENTS>(noTexUnits, cascade, ListInstancedMatNormalMap::getInstance()->Shadows[cascade]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
@ -893,7 +910,6 @@ void drawRSM(const core::matrix4 & rsm_matrix, const std::vector<GLuint> &Textur
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef Draw_Indirect
|
||||
template<typename Shader, MeshMaterial Mat, video::E_VERTEX_TYPE VT, typename...Args>
|
||||
void renderRSMShadow(const std::vector<GLuint> TextureUnits, const std::vector<GLMesh *> &t, Args ...args)
|
||||
{
|
||||
@ -913,9 +929,7 @@ void renderRSMShadow(const std::vector<GLuint> TextureUnits, const std::vector<G
|
||||
glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((RSMPassCmd::getInstance()->Offset[Mat] + i)* sizeof(DrawElementsIndirectCommand)));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef Multi_Draw_Indirect
|
||||
template<typename Shader, MeshMaterial Mat, enum E_VERTEX_TYPE VertexType, typename... Args>
|
||||
void multidrawRSM(Args...args)
|
||||
{
|
||||
@ -927,7 +941,6 @@ void multidrawRSM(Args...args)
|
||||
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)(RSMPassCmd::getInstance()->Offset[Mat] * sizeof(DrawElementsIndirectCommand)), RSMPassCmd::getInstance()->Size[Mat], sizeof(DrawElementsIndirectCommand));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void IrrDriver::renderRSM()
|
||||
{
|
||||
@ -947,15 +960,12 @@ void IrrDriver::renderRSM()
|
||||
|
||||
if (UserConfigParams::m_azdo)
|
||||
{
|
||||
#ifdef Multi_Draw_Indirect
|
||||
multidrawRSM<MeshShader::InstancedRSMShader, MAT_DEFAULT, video::EVT_STANDARD>(rsm_matrix);
|
||||
multidrawRSM<MeshShader::InstancedRSMShader, MAT_NORMAL_MAP, video::EVT_TANGENTS>(rsm_matrix);
|
||||
multidrawRSM<MeshShader::InstancedRSMShader, MAT_ALPHA_REF, video::EVT_STANDARD>(rsm_matrix);
|
||||
multidrawRSM<MeshShader::InstancedRSMShader, MAT_UNLIT, video::EVT_STANDARD>(rsm_matrix);
|
||||
multidrawRSM<MeshShader::InstancedRSMShader, MAT_DETAIL, video::EVT_2TCOORDS>(rsm_matrix);
|
||||
#endif
|
||||
}
|
||||
#ifdef Draw_Indirect
|
||||
else if (irr_driver->hasARB_draw_indirect())
|
||||
{
|
||||
renderRSMShadow<MeshShader::InstancedRSMShader, MAT_DEFAULT, video::EVT_STANDARD>(std::vector < GLuint > { 0 }, ListInstancedMatDefault::getInstance()->RSM, rsm_matrix);
|
||||
@ -964,5 +974,4 @@ void IrrDriver::renderRSM()
|
||||
renderRSMShadow<MeshShader::InstancedRSMShader, MAT_NORMAL_MAP, video::EVT_TANGENTS>(std::vector < GLuint > { 0 }, ListInstancedMatNormalMap::getInstance()->RSM, rsm_matrix);
|
||||
renderRSMShadow<MeshShader::InstancedRSMShader, MAT_DETAIL, video::EVT_2TCOORDS>(std::vector < GLuint > { 0 }, ListInstancedMatDetails::getInstance()->RSM, rsm_matrix);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -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]);
|
||||
|
@ -439,7 +439,7 @@ GLuint generateCubeMapFromTextures(const std::vector<video::ITexture *> &texture
|
||||
swapPixels(tmp, rgba[i], size, x, y, (size - y - 1), x);
|
||||
}
|
||||
}
|
||||
free(tmp);
|
||||
delete[] tmp;
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, result);
|
||||
@ -574,4 +574,4 @@ void IrrDriver::renderSkybox(const scene::ICameraSceneNode *camera)
|
||||
|
||||
glDrawElements(GL_TRIANGLES, 6 * 6, GL_UNSIGNED_INT, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
}
|
||||
|
@ -17,15 +17,19 @@
|
||||
#ifndef HEADER_RTTS_HPP
|
||||
#define HEADER_RTTS_HPP
|
||||
|
||||
#include "graphics/glwrap.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "utils/ptr_vector.hpp"
|
||||
#include "utils/leak_check.hpp"
|
||||
|
||||
class FrameBuffer;
|
||||
|
||||
namespace irr {
|
||||
namespace video {
|
||||
class ITexture;
|
||||
};
|
||||
namespace scene {
|
||||
class ICameraSceneNode;
|
||||
}
|
||||
};
|
||||
|
||||
using irr::video::ITexture;
|
||||
@ -46,7 +50,7 @@ public:
|
||||
unsigned getRenderTarget(enum TypeRTT target) const { return RenderTargetTextures[target]; }
|
||||
FrameBuffer& getFBO(enum TypeFBO fbo) { return FrameBuffers[fbo]; }
|
||||
|
||||
FrameBuffer* render(scene::ICameraSceneNode* camera, float dt);
|
||||
FrameBuffer* render(irr::scene::ICameraSceneNode* camera, float dt);
|
||||
|
||||
private:
|
||||
unsigned RenderTargetTextures[RTT_COUNT];
|
||||
|
@ -17,8 +17,6 @@
|
||||
#ifndef HEADER_SCREENQUAD_H
|
||||
#define HEADER_SCREENQUAD_H
|
||||
|
||||
#include "graphics/glwrap.hpp"
|
||||
|
||||
#include <SMaterial.h>
|
||||
#include <IVideoDriver.h>
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -19,11 +19,9 @@
|
||||
|
||||
#include <IShaderConstantSetCallBack.h>
|
||||
#include <IMeshSceneNode.h>
|
||||
#include <vector>
|
||||
#include "config/user_config.hpp"
|
||||
#include "utils/singleton.hpp"
|
||||
|
||||
#include "gl_headers.hpp"
|
||||
#include "shaders_util.hpp"
|
||||
|
||||
using namespace irr;
|
||||
class ParticleSystemProxy;
|
||||
@ -52,429 +50,6 @@ public:
|
||||
};
|
||||
}
|
||||
|
||||
bool needsUBO();
|
||||
|
||||
unsigned getGLSLVersion();
|
||||
|
||||
struct UniformHelper
|
||||
{
|
||||
template<unsigned N = 0>
|
||||
static void setUniformsHelper(const std::vector<GLuint> &uniforms)
|
||||
{
|
||||
}
|
||||
|
||||
template<unsigned N = 0, typename... Args>
|
||||
static void setUniformsHelper(const std::vector<GLuint> &uniforms, const core::matrix4 &mat, Args... arg)
|
||||
{
|
||||
glUniformMatrix4fv(uniforms[N], 1, GL_FALSE, mat.pointer());
|
||||
setUniformsHelper<N + 1>(uniforms, arg...);
|
||||
}
|
||||
|
||||
template<unsigned N = 0, typename... Args>
|
||||
static void setUniformsHelper(const std::vector<GLuint> &uniforms, const video::SColorf &col, Args... arg)
|
||||
{
|
||||
glUniform3f(uniforms[N], col.r, col.g, col.b);
|
||||
setUniformsHelper<N + 1>(uniforms, arg...);
|
||||
}
|
||||
|
||||
template<unsigned N = 0, typename... Args>
|
||||
static void setUniformsHelper(const std::vector<GLuint> &uniforms, const video::SColor &col, Args... arg)
|
||||
{
|
||||
glUniform4i(uniforms[N], col.getRed(), col.getGreen(), col.getBlue(), col.getAlpha());
|
||||
setUniformsHelper<N + 1>(uniforms, arg...);
|
||||
}
|
||||
|
||||
template<unsigned N = 0, typename... Args>
|
||||
static void setUniformsHelper(const std::vector<GLuint> &uniforms, const core::vector3df &v, Args... arg)
|
||||
{
|
||||
glUniform3f(uniforms[N], v.X, v.Y, v.Z);
|
||||
setUniformsHelper<N + 1>(uniforms, arg...);
|
||||
}
|
||||
|
||||
|
||||
template<unsigned N = 0, typename... Args>
|
||||
static void setUniformsHelper(const std::vector<GLuint> &uniforms, const core::vector2df &v, Args... arg)
|
||||
{
|
||||
glUniform2f(uniforms[N], v.X, v.Y);
|
||||
setUniformsHelper<N + 1>(uniforms, arg...);
|
||||
}
|
||||
|
||||
template<unsigned N = 0, typename... Args>
|
||||
static void setUniformsHelper(const std::vector<GLuint> &uniforms, const core::dimension2df &v, Args... arg)
|
||||
{
|
||||
glUniform2f(uniforms[N], v.Width, v.Height);
|
||||
setUniformsHelper<N + 1>(uniforms, arg...);
|
||||
}
|
||||
|
||||
template<unsigned N = 0, typename... Args>
|
||||
static void setUniformsHelper(const std::vector<GLuint> &uniforms, float f, Args... arg)
|
||||
{
|
||||
glUniform1f(uniforms[N], f);
|
||||
setUniformsHelper<N + 1>(uniforms, arg...);
|
||||
}
|
||||
|
||||
template<unsigned N = 0, typename... Args>
|
||||
static void setUniformsHelper(const std::vector<GLuint> &uniforms, int f, Args... arg)
|
||||
{
|
||||
glUniform1i(uniforms[N], f);
|
||||
setUniformsHelper<N + 1>(uniforms, arg...);
|
||||
}
|
||||
|
||||
template<unsigned N = 0, typename... Args>
|
||||
static void setUniformsHelper(const std::vector<GLuint> &uniforms, const std::vector<float> &v, Args... arg)
|
||||
{
|
||||
glUniform1fv(uniforms[N], v.size(), v.data());
|
||||
setUniformsHelper<N + 1>(uniforms, arg...);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void bypassUBO(GLuint Program);
|
||||
|
||||
extern std::vector<void(*)()> CleanTable;
|
||||
|
||||
template<typename T, typename... Args>
|
||||
class ShaderHelperSingleton : public Singleton<T>
|
||||
{
|
||||
protected:
|
||||
std::vector<GLuint> uniforms;
|
||||
|
||||
void AssignUniforms_impl()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename... U>
|
||||
void AssignUniforms_impl(const char* name, U... rest)
|
||||
{
|
||||
uniforms.push_back(glGetUniformLocation(Program, name));
|
||||
AssignUniforms_impl(rest...);
|
||||
}
|
||||
|
||||
template<typename... U>
|
||||
void AssignUniforms(U... rest)
|
||||
{
|
||||
static_assert(sizeof...(rest) == sizeof...(Args), "Count of Uniform's name mismatch");
|
||||
AssignUniforms_impl(rest...);
|
||||
}
|
||||
|
||||
public:
|
||||
GLuint Program;
|
||||
|
||||
ShaderHelperSingleton()
|
||||
{
|
||||
CleanTable.push_back(this->kill);
|
||||
}
|
||||
|
||||
~ShaderHelperSingleton()
|
||||
{
|
||||
glDeleteProgram(Program);
|
||||
}
|
||||
|
||||
void setUniforms(const Args & ... args) const
|
||||
{
|
||||
if (needsUBO())
|
||||
bypassUBO(Program);
|
||||
UniformHelper::setUniformsHelper(uniforms, args...);
|
||||
}
|
||||
};
|
||||
|
||||
enum SamplerType {
|
||||
Trilinear_Anisotropic_Filtered,
|
||||
Semi_trilinear,
|
||||
Bilinear_Filtered,
|
||||
Bilinear_Clamped_Filtered,
|
||||
Nearest_Filtered,
|
||||
Shadow_Sampler,
|
||||
Volume_Linear_Filtered,
|
||||
Trilinear_cubemap,
|
||||
};
|
||||
|
||||
void setTextureSampler(GLenum, GLuint, GLuint, GLuint);
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct CreateSamplers;
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct BindTexture;
|
||||
|
||||
template<>
|
||||
struct CreateSamplers<>
|
||||
{
|
||||
static void exec(std::vector<unsigned> &, std::vector<GLenum> &e)
|
||||
{}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct BindTexture<>
|
||||
{
|
||||
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
|
||||
{}
|
||||
};
|
||||
|
||||
GLuint createNearestSampler();
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct CreateSamplers<Nearest_Filtered, tp...>
|
||||
{
|
||||
static void exec(std::vector<unsigned> &v, std::vector<GLenum> &e)
|
||||
{
|
||||
v.push_back(createNearestSampler());
|
||||
e.push_back(GL_TEXTURE_2D);
|
||||
CreateSamplers<tp...>::exec(v, e);
|
||||
}
|
||||
};
|
||||
|
||||
void BindTextureNearest(unsigned TU, unsigned tid);
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct BindTexture<Nearest_Filtered, tp...>
|
||||
{
|
||||
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
|
||||
{
|
||||
BindTextureNearest(TU[N], TexId[N]);
|
||||
BindTexture<tp...>::exec(TU, TexId, N + 1);
|
||||
}
|
||||
};
|
||||
|
||||
GLuint createBilinearSampler();
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct CreateSamplers<Bilinear_Filtered, tp...>
|
||||
{
|
||||
static void exec(std::vector<unsigned> &v, std::vector<GLenum> &e)
|
||||
{
|
||||
v.push_back(createBilinearSampler());
|
||||
e.push_back(GL_TEXTURE_2D);
|
||||
CreateSamplers<tp...>::exec(v, e);
|
||||
}
|
||||
};
|
||||
|
||||
void BindTextureBilinear(unsigned TU, unsigned tex);
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct BindTexture<Bilinear_Filtered, tp...>
|
||||
{
|
||||
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
|
||||
{
|
||||
BindTextureBilinear(TU[N], TexId[N]);
|
||||
BindTexture<tp...>::exec(TU, TexId, N + 1);
|
||||
}
|
||||
};
|
||||
|
||||
GLuint createBilinearClampedSampler();
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct CreateSamplers<Bilinear_Clamped_Filtered, tp...>
|
||||
{
|
||||
static void exec(std::vector<unsigned> &v, std::vector<GLenum> &e)
|
||||
{
|
||||
v.push_back(createBilinearClampedSampler());
|
||||
e.push_back(GL_TEXTURE_2D);
|
||||
CreateSamplers<tp...>::exec(v, e);
|
||||
}
|
||||
};
|
||||
|
||||
void BindTextureBilinearClamped(unsigned TU, unsigned tex);
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct BindTexture<Bilinear_Clamped_Filtered, tp...>
|
||||
{
|
||||
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
|
||||
{
|
||||
BindTextureBilinearClamped(TU[N], TexId[N]);
|
||||
BindTexture<tp...>::exec(TU, TexId, N + 1);
|
||||
}
|
||||
};
|
||||
|
||||
GLuint createSemiTrilinearSampler();
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct CreateSamplers<Semi_trilinear, tp...>
|
||||
{
|
||||
static void exec(std::vector<unsigned> &v, std::vector<GLenum> &e)
|
||||
{
|
||||
v.push_back(createSemiTrilinearSampler());
|
||||
e.push_back(GL_TEXTURE_2D);
|
||||
CreateSamplers<tp...>::exec(v, e);
|
||||
}
|
||||
};
|
||||
|
||||
void BindTextureSemiTrilinear(unsigned TU, unsigned tex);
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct BindTexture<Semi_trilinear, tp...>
|
||||
{
|
||||
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
|
||||
{
|
||||
BindTextureSemiTrilinear(TU[N], TexId[N]);
|
||||
BindTexture<tp...>::exec(TU, TexId, N + 1);
|
||||
}
|
||||
};
|
||||
|
||||
GLuint createTrilinearSampler();
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct CreateSamplers<Trilinear_Anisotropic_Filtered, tp...>
|
||||
{
|
||||
static void exec(std::vector<unsigned> &v, std::vector<GLenum> &e)
|
||||
{
|
||||
v.push_back(createTrilinearSampler());
|
||||
e.push_back(GL_TEXTURE_2D);
|
||||
CreateSamplers<tp...>::exec(v, e);
|
||||
}
|
||||
};
|
||||
|
||||
void BindTextureTrilinearAnisotropic(unsigned TU, unsigned tex);
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct CreateSamplers<Trilinear_cubemap, tp...>
|
||||
{
|
||||
static void exec(std::vector<unsigned> &v, std::vector<GLenum> &e)
|
||||
{
|
||||
v.push_back(createTrilinearSampler());
|
||||
e.push_back(GL_TEXTURE_CUBE_MAP);
|
||||
CreateSamplers<tp...>::exec(v, e);
|
||||
}
|
||||
};
|
||||
|
||||
void BindCubemapTrilinear(unsigned TU, unsigned tex);
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct BindTexture<Trilinear_cubemap, tp...>
|
||||
{
|
||||
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
|
||||
{
|
||||
BindCubemapTrilinear(TU[N], TexId[N]);
|
||||
BindTexture<tp...>::exec(TU, TexId, N + 1);
|
||||
}
|
||||
};
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct BindTexture<Trilinear_Anisotropic_Filtered, tp...>
|
||||
{
|
||||
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
|
||||
{
|
||||
BindTextureTrilinearAnisotropic(TU[N], TexId[N]);
|
||||
BindTexture<tp...>::exec(TU, TexId, N + 1);
|
||||
}
|
||||
};
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct CreateSamplers<Volume_Linear_Filtered, tp...>
|
||||
{
|
||||
static void exec(std::vector<unsigned> &v, std::vector<GLenum> &e)
|
||||
{
|
||||
v.push_back(createBilinearSampler());
|
||||
e.push_back(GL_TEXTURE_3D);
|
||||
CreateSamplers<tp...>::exec(v, e);
|
||||
}
|
||||
};
|
||||
|
||||
void BindTextureVolume(unsigned TU, unsigned tex);
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct BindTexture<Volume_Linear_Filtered, tp...>
|
||||
{
|
||||
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
|
||||
{
|
||||
BindTextureVolume(TU[N], TexId[N]);
|
||||
BindTexture<tp...>::exec(TU, TexId, N + 1);
|
||||
}
|
||||
};
|
||||
|
||||
GLuint createShadowSampler();
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct CreateSamplers<Shadow_Sampler, tp...>
|
||||
{
|
||||
static void exec(std::vector<unsigned> &v, std::vector<GLenum> &e)
|
||||
{
|
||||
v.push_back(createShadowSampler());
|
||||
e.push_back(GL_TEXTURE_2D_ARRAY);
|
||||
CreateSamplers<tp...>::exec(v, e);
|
||||
}
|
||||
};
|
||||
|
||||
void BindTextureShadow(unsigned TU, unsigned tex);
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct BindTexture<Shadow_Sampler, tp...>
|
||||
{
|
||||
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
|
||||
{
|
||||
BindTextureShadow(TU[N], TexId[N]);
|
||||
BindTexture<tp...>::exec(TU, TexId, N + 1);
|
||||
}
|
||||
};
|
||||
|
||||
template<SamplerType...tp>
|
||||
class TextureRead
|
||||
{
|
||||
private:
|
||||
template<unsigned N, typename...Args>
|
||||
void AssignTextureNames_impl(GLuint)
|
||||
{
|
||||
static_assert(N == sizeof...(tp), "Wrong number of texture name");
|
||||
}
|
||||
|
||||
template<unsigned N, typename...Args>
|
||||
void AssignTextureNames_impl(GLuint Program, GLuint TexUnit, const char *name, Args...args)
|
||||
{
|
||||
GLuint location = glGetUniformLocation(Program, name);
|
||||
TextureLocation.push_back(location);
|
||||
glUniform1i(location, TexUnit);
|
||||
TextureUnits.push_back(TexUnit);
|
||||
AssignTextureNames_impl<N + 1>(Program, args...);
|
||||
}
|
||||
|
||||
protected:
|
||||
std::vector<GLuint> TextureUnits;
|
||||
std::vector<GLenum> TextureType;
|
||||
std::vector<GLenum> TextureLocation;
|
||||
template<typename...Args>
|
||||
void AssignSamplerNames(GLuint Program, Args...args)
|
||||
{
|
||||
CreateSamplers<tp...>::exec(SamplersId, TextureType);
|
||||
|
||||
glUseProgram(Program);
|
||||
AssignTextureNames_impl<0>(Program, args...);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
public:
|
||||
std::vector<GLuint> SamplersId;
|
||||
void SetTextureUnits(const std::vector<GLuint> &args)
|
||||
{
|
||||
assert(args.size() == sizeof...(tp) && "Too much texture unit provided");
|
||||
if (getGLSLVersion() >= 330)
|
||||
{
|
||||
for (unsigned i = 0; i < args.size(); i++)
|
||||
{
|
||||
setTextureSampler(TextureType[i], TextureUnits[i], args[i], SamplersId[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
BindTexture<tp...>::exec(TextureUnits, args, 0);
|
||||
}
|
||||
|
||||
~TextureRead()
|
||||
{
|
||||
for (unsigned i = 0; i < SamplersId.size(); i++)
|
||||
glDeleteSamplers(1, &SamplersId[i]);
|
||||
}
|
||||
|
||||
void SetTextureHandles(const std::vector<uint64_t> &args)
|
||||
{
|
||||
assert(args.size() == TextureLocation.size() && "Wrong Handle count");
|
||||
for (unsigned i = 0; i < args.size(); i++)
|
||||
{
|
||||
#ifdef Bindless_Texture_Support
|
||||
if (args[i])
|
||||
glUniformHandleui64ARB(TextureLocation[i], args[i]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
namespace MeshShader
|
||||
{
|
||||
|
435
src/graphics/shaders_util.hpp
Normal file
435
src/graphics/shaders_util.hpp
Normal file
@ -0,0 +1,435 @@
|
||||
#ifndef SHADERS_UTIL_HPP
|
||||
#define SHADERS_UTIL_HPP
|
||||
|
||||
#include "utils/singleton.hpp"
|
||||
#include <vector>
|
||||
#include <matrix4.h>
|
||||
#include <SColor.h>
|
||||
#include <vector3d.h>
|
||||
#include "gl_headers.hpp"
|
||||
|
||||
bool needsUBO();
|
||||
|
||||
unsigned getGLSLVersion();
|
||||
|
||||
struct UniformHelper
|
||||
{
|
||||
template<unsigned N = 0>
|
||||
static void setUniformsHelper(const std::vector<GLuint> &uniforms)
|
||||
{
|
||||
}
|
||||
|
||||
template<unsigned N = 0, typename... Args>
|
||||
static void setUniformsHelper(const std::vector<GLuint> &uniforms, const irr::core::matrix4 &mat, Args... arg)
|
||||
{
|
||||
glUniformMatrix4fv(uniforms[N], 1, GL_FALSE, mat.pointer());
|
||||
setUniformsHelper<N + 1>(uniforms, arg...);
|
||||
}
|
||||
|
||||
template<unsigned N = 0, typename... Args>
|
||||
static void setUniformsHelper(const std::vector<GLuint> &uniforms, const irr::video::SColorf &col, Args... arg)
|
||||
{
|
||||
glUniform3f(uniforms[N], col.r, col.g, col.b);
|
||||
setUniformsHelper<N + 1>(uniforms, arg...);
|
||||
}
|
||||
|
||||
template<unsigned N = 0, typename... Args>
|
||||
static void setUniformsHelper(const std::vector<GLuint> &uniforms, const irr::video::SColor &col, Args... arg)
|
||||
{
|
||||
glUniform4i(uniforms[N], col.getRed(), col.getGreen(), col.getBlue(), col.getAlpha());
|
||||
setUniformsHelper<N + 1>(uniforms, arg...);
|
||||
}
|
||||
|
||||
template<unsigned N = 0, typename... Args>
|
||||
static void setUniformsHelper(const std::vector<GLuint> &uniforms, const irr::core::vector3df &v, Args... arg)
|
||||
{
|
||||
glUniform3f(uniforms[N], v.X, v.Y, v.Z);
|
||||
setUniformsHelper<N + 1>(uniforms, arg...);
|
||||
}
|
||||
|
||||
|
||||
template<unsigned N = 0, typename... Args>
|
||||
static void setUniformsHelper(const std::vector<GLuint> &uniforms, const irr::core::vector2df &v, Args... arg)
|
||||
{
|
||||
glUniform2f(uniforms[N], v.X, v.Y);
|
||||
setUniformsHelper<N + 1>(uniforms, arg...);
|
||||
}
|
||||
|
||||
template<unsigned N = 0, typename... Args>
|
||||
static void setUniformsHelper(const std::vector<GLuint> &uniforms, const irr::core::dimension2df &v, Args... arg)
|
||||
{
|
||||
glUniform2f(uniforms[N], v.Width, v.Height);
|
||||
setUniformsHelper<N + 1>(uniforms, arg...);
|
||||
}
|
||||
|
||||
template<unsigned N = 0, typename... Args>
|
||||
static void setUniformsHelper(const std::vector<GLuint> &uniforms, float f, Args... arg)
|
||||
{
|
||||
glUniform1f(uniforms[N], f);
|
||||
setUniformsHelper<N + 1>(uniforms, arg...);
|
||||
}
|
||||
|
||||
template<unsigned N = 0, typename... Args>
|
||||
static void setUniformsHelper(const std::vector<GLuint> &uniforms, int f, Args... arg)
|
||||
{
|
||||
glUniform1i(uniforms[N], f);
|
||||
setUniformsHelper<N + 1>(uniforms, arg...);
|
||||
}
|
||||
|
||||
template<unsigned N = 0, typename... Args>
|
||||
static void setUniformsHelper(const std::vector<GLuint> &uniforms, const std::vector<float> &v, Args... arg)
|
||||
{
|
||||
glUniform1fv(uniforms[N], v.size(), v.data());
|
||||
setUniformsHelper<N + 1>(uniforms, arg...);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void bypassUBO(GLuint Program);
|
||||
|
||||
extern std::vector<void(*)()> CleanTable;
|
||||
|
||||
template<typename T, typename... Args>
|
||||
class ShaderHelperSingleton : public Singleton<T>
|
||||
{
|
||||
protected:
|
||||
std::vector<GLuint> uniforms;
|
||||
|
||||
void AssignUniforms_impl()
|
||||
{
|
||||
GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData");
|
||||
if (uniform_ViewProjectionMatrixesUBO != GL_INVALID_INDEX)
|
||||
glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0);
|
||||
}
|
||||
|
||||
template<typename... U>
|
||||
void AssignUniforms_impl(const char* name, U... rest)
|
||||
{
|
||||
uniforms.push_back(glGetUniformLocation(Program, name));
|
||||
AssignUniforms_impl(rest...);
|
||||
}
|
||||
|
||||
template<typename... U>
|
||||
void AssignUniforms(U... rest)
|
||||
{
|
||||
static_assert(sizeof...(rest) == sizeof...(Args), "Count of Uniform's name mismatch");
|
||||
AssignUniforms_impl(rest...);
|
||||
}
|
||||
|
||||
public:
|
||||
GLuint Program;
|
||||
|
||||
ShaderHelperSingleton()
|
||||
{
|
||||
CleanTable.push_back(this->kill);
|
||||
}
|
||||
|
||||
~ShaderHelperSingleton()
|
||||
{
|
||||
glDeleteProgram(Program);
|
||||
}
|
||||
|
||||
void setUniforms(const Args & ... args) const
|
||||
{
|
||||
if (needsUBO())
|
||||
bypassUBO(Program);
|
||||
UniformHelper::setUniformsHelper(uniforms, args...);
|
||||
}
|
||||
};
|
||||
|
||||
enum SamplerType {
|
||||
Trilinear_Anisotropic_Filtered,
|
||||
Semi_trilinear,
|
||||
Bilinear_Filtered,
|
||||
Bilinear_Clamped_Filtered,
|
||||
Nearest_Filtered,
|
||||
Shadow_Sampler,
|
||||
Volume_Linear_Filtered,
|
||||
Trilinear_cubemap,
|
||||
};
|
||||
|
||||
void setTextureSampler(GLenum, GLuint, GLuint, GLuint);
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct CreateSamplers;
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct BindTexture;
|
||||
|
||||
template<>
|
||||
struct CreateSamplers<>
|
||||
{
|
||||
static void exec(std::vector<unsigned> &, std::vector<GLenum> &e)
|
||||
{}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct BindTexture<>
|
||||
{
|
||||
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
|
||||
{}
|
||||
};
|
||||
|
||||
GLuint createNearestSampler();
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct CreateSamplers<Nearest_Filtered, tp...>
|
||||
{
|
||||
static void exec(std::vector<unsigned> &v, std::vector<GLenum> &e)
|
||||
{
|
||||
v.push_back(createNearestSampler());
|
||||
e.push_back(GL_TEXTURE_2D);
|
||||
CreateSamplers<tp...>::exec(v, e);
|
||||
}
|
||||
};
|
||||
|
||||
void BindTextureNearest(unsigned TU, unsigned tid);
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct BindTexture<Nearest_Filtered, tp...>
|
||||
{
|
||||
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
|
||||
{
|
||||
BindTextureNearest(TU[N], TexId[N]);
|
||||
BindTexture<tp...>::exec(TU, TexId, N + 1);
|
||||
}
|
||||
};
|
||||
|
||||
GLuint createBilinearSampler();
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct CreateSamplers<Bilinear_Filtered, tp...>
|
||||
{
|
||||
static void exec(std::vector<unsigned> &v, std::vector<GLenum> &e)
|
||||
{
|
||||
v.push_back(createBilinearSampler());
|
||||
e.push_back(GL_TEXTURE_2D);
|
||||
CreateSamplers<tp...>::exec(v, e);
|
||||
}
|
||||
};
|
||||
|
||||
void BindTextureBilinear(unsigned TU, unsigned tex);
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct BindTexture<Bilinear_Filtered, tp...>
|
||||
{
|
||||
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
|
||||
{
|
||||
BindTextureBilinear(TU[N], TexId[N]);
|
||||
BindTexture<tp...>::exec(TU, TexId, N + 1);
|
||||
}
|
||||
};
|
||||
|
||||
GLuint createBilinearClampedSampler();
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct CreateSamplers<Bilinear_Clamped_Filtered, tp...>
|
||||
{
|
||||
static void exec(std::vector<unsigned> &v, std::vector<GLenum> &e)
|
||||
{
|
||||
v.push_back(createBilinearClampedSampler());
|
||||
e.push_back(GL_TEXTURE_2D);
|
||||
CreateSamplers<tp...>::exec(v, e);
|
||||
}
|
||||
};
|
||||
|
||||
void BindTextureBilinearClamped(unsigned TU, unsigned tex);
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct BindTexture<Bilinear_Clamped_Filtered, tp...>
|
||||
{
|
||||
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
|
||||
{
|
||||
BindTextureBilinearClamped(TU[N], TexId[N]);
|
||||
BindTexture<tp...>::exec(TU, TexId, N + 1);
|
||||
}
|
||||
};
|
||||
|
||||
GLuint createSemiTrilinearSampler();
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct CreateSamplers<Semi_trilinear, tp...>
|
||||
{
|
||||
static void exec(std::vector<unsigned> &v, std::vector<GLenum> &e)
|
||||
{
|
||||
v.push_back(createSemiTrilinearSampler());
|
||||
e.push_back(GL_TEXTURE_2D);
|
||||
CreateSamplers<tp...>::exec(v, e);
|
||||
}
|
||||
};
|
||||
|
||||
void BindTextureSemiTrilinear(unsigned TU, unsigned tex);
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct BindTexture<Semi_trilinear, tp...>
|
||||
{
|
||||
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
|
||||
{
|
||||
BindTextureSemiTrilinear(TU[N], TexId[N]);
|
||||
BindTexture<tp...>::exec(TU, TexId, N + 1);
|
||||
}
|
||||
};
|
||||
|
||||
GLuint createTrilinearSampler();
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct CreateSamplers<Trilinear_Anisotropic_Filtered, tp...>
|
||||
{
|
||||
static void exec(std::vector<unsigned> &v, std::vector<GLenum> &e)
|
||||
{
|
||||
v.push_back(createTrilinearSampler());
|
||||
e.push_back(GL_TEXTURE_2D);
|
||||
CreateSamplers<tp...>::exec(v, e);
|
||||
}
|
||||
};
|
||||
|
||||
void BindTextureTrilinearAnisotropic(unsigned TU, unsigned tex);
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct CreateSamplers<Trilinear_cubemap, tp...>
|
||||
{
|
||||
static void exec(std::vector<unsigned> &v, std::vector<GLenum> &e)
|
||||
{
|
||||
v.push_back(createTrilinearSampler());
|
||||
e.push_back(GL_TEXTURE_CUBE_MAP);
|
||||
CreateSamplers<tp...>::exec(v, e);
|
||||
}
|
||||
};
|
||||
|
||||
void BindCubemapTrilinear(unsigned TU, unsigned tex);
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct BindTexture<Trilinear_cubemap, tp...>
|
||||
{
|
||||
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
|
||||
{
|
||||
BindCubemapTrilinear(TU[N], TexId[N]);
|
||||
BindTexture<tp...>::exec(TU, TexId, N + 1);
|
||||
}
|
||||
};
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct BindTexture<Trilinear_Anisotropic_Filtered, tp...>
|
||||
{
|
||||
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
|
||||
{
|
||||
BindTextureTrilinearAnisotropic(TU[N], TexId[N]);
|
||||
BindTexture<tp...>::exec(TU, TexId, N + 1);
|
||||
}
|
||||
};
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct CreateSamplers<Volume_Linear_Filtered, tp...>
|
||||
{
|
||||
static void exec(std::vector<unsigned> &v, std::vector<GLenum> &e)
|
||||
{
|
||||
v.push_back(createBilinearSampler());
|
||||
e.push_back(GL_TEXTURE_3D);
|
||||
CreateSamplers<tp...>::exec(v, e);
|
||||
}
|
||||
};
|
||||
|
||||
void BindTextureVolume(unsigned TU, unsigned tex);
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct BindTexture<Volume_Linear_Filtered, tp...>
|
||||
{
|
||||
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
|
||||
{
|
||||
BindTextureVolume(TU[N], TexId[N]);
|
||||
BindTexture<tp...>::exec(TU, TexId, N + 1);
|
||||
}
|
||||
};
|
||||
|
||||
GLuint createShadowSampler();
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct CreateSamplers<Shadow_Sampler, tp...>
|
||||
{
|
||||
static void exec(std::vector<unsigned> &v, std::vector<GLenum> &e)
|
||||
{
|
||||
v.push_back(createShadowSampler());
|
||||
e.push_back(GL_TEXTURE_2D_ARRAY);
|
||||
CreateSamplers<tp...>::exec(v, e);
|
||||
}
|
||||
};
|
||||
|
||||
void BindTextureShadow(unsigned TU, unsigned tex);
|
||||
|
||||
template<SamplerType...tp>
|
||||
struct BindTexture<Shadow_Sampler, tp...>
|
||||
{
|
||||
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
|
||||
{
|
||||
BindTextureShadow(TU[N], TexId[N]);
|
||||
BindTexture<tp...>::exec(TU, TexId, N + 1);
|
||||
}
|
||||
};
|
||||
|
||||
template<SamplerType...tp>
|
||||
class TextureRead
|
||||
{
|
||||
private:
|
||||
template<unsigned N, typename...Args>
|
||||
void AssignTextureNames_impl(GLuint)
|
||||
{
|
||||
static_assert(N == sizeof...(tp), "Wrong number of texture name");
|
||||
}
|
||||
|
||||
template<unsigned N, typename...Args>
|
||||
void AssignTextureNames_impl(GLuint Program, GLuint TexUnit, const char *name, Args...args)
|
||||
{
|
||||
GLuint location = glGetUniformLocation(Program, name);
|
||||
TextureLocation.push_back(location);
|
||||
glUniform1i(location, TexUnit);
|
||||
TextureUnits.push_back(TexUnit);
|
||||
AssignTextureNames_impl<N + 1>(Program, args...);
|
||||
}
|
||||
|
||||
protected:
|
||||
std::vector<GLuint> TextureUnits;
|
||||
std::vector<GLenum> TextureType;
|
||||
std::vector<GLenum> TextureLocation;
|
||||
template<typename...Args>
|
||||
void AssignSamplerNames(GLuint Program, Args...args)
|
||||
{
|
||||
CreateSamplers<tp...>::exec(SamplersId, TextureType);
|
||||
|
||||
glUseProgram(Program);
|
||||
AssignTextureNames_impl<0>(Program, args...);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
public:
|
||||
std::vector<GLuint> SamplersId;
|
||||
void SetTextureUnits(const std::vector<GLuint> &args)
|
||||
{
|
||||
assert(args.size() == sizeof...(tp) && "Too much texture unit provided");
|
||||
if (getGLSLVersion() >= 330)
|
||||
{
|
||||
for (unsigned i = 0; i < args.size(); i++)
|
||||
{
|
||||
setTextureSampler(TextureType[i], TextureUnits[i], args[i], SamplersId[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
BindTexture<tp...>::exec(TextureUnits, args, 0);
|
||||
}
|
||||
|
||||
~TextureRead()
|
||||
{
|
||||
for (unsigned i = 0; i < SamplersId.size(); i++)
|
||||
glDeleteSamplers(1, &SamplersId[i]);
|
||||
}
|
||||
|
||||
void SetTextureHandles(const std::vector<uint64_t> &args)
|
||||
{
|
||||
assert(args.size() == TextureLocation.size() && "Wrong Handle count");
|
||||
for (unsigned i = 0; i < args.size(); i++)
|
||||
{
|
||||
if (args[i])
|
||||
glUniformHandleui64ARB(TextureLocation[i], args[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
@ -1,3 +1,4 @@
|
||||
#include "graphics/glwrap.hpp"
|
||||
#include "graphics/stkanimatedmesh.hpp"
|
||||
#include <ISceneManager.h>
|
||||
#include <IMaterialRenderer.h>
|
||||
@ -19,7 +20,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()
|
||||
@ -31,32 +33,25 @@ void STKAnimatedMesh::cleanGLMeshes()
|
||||
continue;
|
||||
if (mesh.vao)
|
||||
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++)
|
||||
{
|
||||
if (mesh.TextureHandles[j] && glIsTextureHandleResidentARB(mesh.TextureHandles[j]))
|
||||
glMakeTextureHandleNonResidentARB(mesh.TextureHandles[j]);
|
||||
}
|
||||
#endif
|
||||
if (mesh.vertex_buffer)
|
||||
glDeleteBuffers(1, &(mesh.vertex_buffer));
|
||||
if (mesh.index_buffer)
|
||||
glDeleteBuffers(1, &(mesh.index_buffer));
|
||||
}
|
||||
}
|
||||
|
||||
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 +62,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 +96,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 +138,8 @@ void STKAnimatedMesh::update()
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
}
|
||||
isGLInitialized = true;
|
||||
}
|
||||
firstTime = false;
|
||||
|
||||
for (u32 i = 0; i<m->getMeshBufferCount(); ++i)
|
||||
{
|
||||
@ -163,71 +185,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),
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "stkmesh.hpp"
|
||||
#include "graphics/glwrap.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/stkmesh.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include <ISceneManager.h>
|
||||
#include <IMaterialRenderer.h>
|
||||
@ -302,7 +303,6 @@ SetTexture(GLMesh &mesh, unsigned i, bool isSrgb)
|
||||
if (!mesh.textures[i])
|
||||
mesh.textures[i] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
|
||||
compressTexture(mesh.textures[i], isSrgb);
|
||||
#ifdef Bindless_Texture_Support
|
||||
if (UserConfigParams::m_azdo)
|
||||
{
|
||||
if (!mesh.TextureHandles[i])
|
||||
@ -310,7 +310,6 @@ SetTexture(GLMesh &mesh, unsigned i, bool isSrgb)
|
||||
if (!glIsTextureHandleResidentARB(mesh.TextureHandles[i]))
|
||||
glMakeTextureHandleResidentARB(mesh.TextureHandles[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void InitTextures(GLMesh &mesh, MeshMaterial Mat)
|
||||
|
@ -1,7 +1,6 @@
|
||||
#ifndef STKMESH_H
|
||||
#define STKMESH_H
|
||||
|
||||
#include "graphics/glwrap.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "utils/tuple.hpp"
|
||||
|
||||
@ -37,7 +36,6 @@ struct GLMesh {
|
||||
GLuint vao;
|
||||
GLuint vertex_buffer;
|
||||
GLuint index_buffer;
|
||||
GLuint instance_buffer;
|
||||
video::ITexture *textures[6];
|
||||
GLenum PrimitiveType;
|
||||
GLenum IndexType;
|
||||
@ -70,7 +68,8 @@ protected:
|
||||
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; }
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "stkmeshscenenode.hpp"
|
||||
#include "stkmesh.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/glwrap.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include <ISceneManager.h>
|
||||
#include <IMaterialRenderer.h>
|
||||
@ -42,63 +43,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,15 +59,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++)
|
||||
{
|
||||
if (mesh.TextureHandles[j] && glIsTextureHandleResidentARB(mesh.TextureHandles[j]))
|
||||
glMakeTextureHandleNonResidentARB(mesh.TextureHandles[j]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
GLmeshes.clear();
|
||||
for (unsigned i = 0; i < MAT_COUNT; i++)
|
||||
@ -169,11 +105,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 +156,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 +215,8 @@ void STKMeshSceneNode::render()
|
||||
|
||||
++PassCount;
|
||||
|
||||
update();
|
||||
updateNoGL();
|
||||
updateGL();
|
||||
|
||||
bool isTransparent;
|
||||
|
||||
@ -244,13 +256,11 @@ void STKMeshSceneNode::render()
|
||||
compressTexture(mesh.textures[0], true);
|
||||
if (UserConfigParams::m_azdo)
|
||||
{
|
||||
#ifdef Bindless_Texture_Support
|
||||
if (!mesh.TextureHandles[0])
|
||||
mesh.TextureHandles[0] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh.textures[0]), MeshShader::TransparentFogShader::getInstance()->SamplersId[0]);
|
||||
if (!glIsTextureHandleResidentARB(mesh.TextureHandles[0]))
|
||||
glMakeTextureHandleResidentARB(mesh.TextureHandles[0]);
|
||||
MeshShader::ObjectPass1Shader::getInstance()->SetTextureHandles(createVector<uint64_t>(mesh.TextureHandles[0]));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
MeshShader::ObjectPass1Shader::getInstance()->SetTextureUnits(std::vector < GLuint > { getTextureGLuint(mesh.textures[0]) });
|
||||
@ -292,7 +302,6 @@ void STKMeshSceneNode::render()
|
||||
|
||||
if (UserConfigParams::m_azdo)
|
||||
{
|
||||
#ifdef Bindless_Texture_Support
|
||||
GLuint64 DiffuseHandle = glGetTextureSamplerHandleARB(irr_driver->getRenderTargetTexture(RTT_DIFFUSE), MeshShader::ObjectPass2Shader::getInstance()->SamplersId[0]);
|
||||
if (!glIsTextureHandleResidentARB(DiffuseHandle))
|
||||
glMakeTextureHandleResidentARB(DiffuseHandle);
|
||||
@ -310,7 +319,6 @@ void STKMeshSceneNode::render()
|
||||
if (!glIsTextureHandleResidentARB(mesh.TextureHandles[0]))
|
||||
glMakeTextureHandleResidentARB(mesh.TextureHandles[0]);
|
||||
MeshShader::ObjectPass2Shader::getInstance()->SetTextureHandles(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, mesh.TextureHandles[0]));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
MeshShader::ObjectPass2Shader::getInstance()->SetTextureUnits(createVector<GLuint>(
|
||||
@ -397,13 +405,11 @@ void STKMeshSceneNode::render()
|
||||
compressTexture(mesh.textures[0], true);
|
||||
if (UserConfigParams::m_azdo)
|
||||
{
|
||||
#ifdef Bindless_Texture_Support
|
||||
if (!mesh.TextureHandles[0])
|
||||
mesh.TextureHandles[0] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh.textures[0]), MeshShader::TransparentFogShader::getInstance()->SamplersId[0]);
|
||||
if (!glIsTextureHandleResidentARB(mesh.TextureHandles[0]))
|
||||
glMakeTextureHandleResidentARB(mesh.TextureHandles[0]);
|
||||
MeshShader::TransparentFogShader::getInstance()->SetTextureHandles(createVector<uint64_t>(mesh.TextureHandles[0]));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
MeshShader::TransparentFogShader::getInstance()->SetTextureUnits(std::vector<GLuint>{ getTextureGLuint(mesh.textures[0]) });
|
||||
@ -430,13 +436,11 @@ void STKMeshSceneNode::render()
|
||||
compressTexture(mesh.textures[0], true);
|
||||
if (UserConfigParams::m_azdo)
|
||||
{
|
||||
#ifdef Bindless_Texture_Support
|
||||
if (!mesh.TextureHandles[0])
|
||||
mesh.TextureHandles[0] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh.textures[0]), MeshShader::TransparentShader::getInstance()->SamplersId[0]);
|
||||
if (!glIsTextureHandleResidentARB(mesh.TextureHandles[0]))
|
||||
glMakeTextureHandleResidentARB(mesh.TextureHandles[0]);
|
||||
MeshShader::TransparentShader::getInstance()->SetTextureHandles(createVector<uint64_t>(mesh.TextureHandles[0]));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
MeshShader::TransparentShader::getInstance()->SetTextureUnits(std::vector<GLuint>{ getTextureGLuint(mesh.textures[0]) });
|
||||
|
@ -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),
|
||||
|
@ -1,8 +1,7 @@
|
||||
#include "stkscenemanager.hpp"
|
||||
#include "stkmesh.hpp"
|
||||
#include "irr_driver.hpp"
|
||||
#include <ISceneManager.h>
|
||||
#include <ISceneNode.h>
|
||||
#include "graphics/glwrap.hpp"
|
||||
#include "graphics/stkscenemanager.hpp"
|
||||
#include "graphics/stkmesh.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "stkanimatedmesh.hpp"
|
||||
#include "stkmeshscenenode.hpp"
|
||||
#include "utils/ptr_vector.hpp"
|
||||
@ -10,11 +9,14 @@
|
||||
#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 <ISceneManager.h>
|
||||
#include <ISceneNode.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <SViewFrustum.h>
|
||||
#include <functional>
|
||||
@ -176,6 +178,7 @@ handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *Immed
|
||||
STKMeshCommon *node = dynamic_cast<STKMeshCommon*>(Node);
|
||||
if (!node)
|
||||
return;
|
||||
node->updateNoGL();
|
||||
DeferredUpdate.push_back(node);
|
||||
|
||||
if (node->isImmediateDraw())
|
||||
@ -183,9 +186,45 @@ handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *Immed
|
||||
ImmediateDraw->push_back(Node);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Transparent
|
||||
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, 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 (unsigned Mat = 0; Mat < MAT_COUNT; ++Mat)
|
||||
{
|
||||
GLMesh *mesh;
|
||||
if (irr_driver->hasARB_draw_indirect())
|
||||
{
|
||||
for_in(mesh, node->MeshSolidMaterial[Mat])
|
||||
@ -253,8 +292,11 @@ handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *Immed
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!UserConfigParams::m_shadows)
|
||||
return;
|
||||
}
|
||||
if (!UserConfigParams::m_shadows)
|
||||
return;
|
||||
for (unsigned Mat = 0; Mat < MAT_COUNT; ++Mat)
|
||||
{
|
||||
for (unsigned cascade = 0; cascade < 4; ++cascade)
|
||||
{
|
||||
if (irr_driver->hasARB_draw_indirect())
|
||||
@ -298,8 +340,11 @@ handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *Immed
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!UserConfigParams::m_gi)
|
||||
return;
|
||||
}
|
||||
if (!UserConfigParams::m_gi)
|
||||
return;
|
||||
for (unsigned Mat = 0; Mat < MAT_COUNT; ++Mat)
|
||||
{
|
||||
if (irr_driver->hasARB_draw_indirect())
|
||||
{
|
||||
for_in(mesh, node->MeshSolidMaterial[Mat])
|
||||
@ -349,40 +394,6 @@ handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *Immed
|
||||
}
|
||||
}
|
||||
}
|
||||
// Transparent
|
||||
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, 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
|
||||
@ -503,8 +514,10 @@ void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
||||
printf("Wait Failed\n");
|
||||
break;
|
||||
}*/
|
||||
PROFILER_PUSH_CPU_MARKER("- Animations/Buffer upload", 0x0, 0x0, 0x0);
|
||||
for (unsigned i = 0; i < DeferredUpdate.size(); i++)
|
||||
DeferredUpdate[i]->update();
|
||||
DeferredUpdate[i]->updateGL();
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
if (!irr_driver->hasARB_draw_indirect())
|
||||
return;
|
||||
@ -706,5 +719,6 @@ void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
||||
poly_count[SOLID_NORMAL_AND_DEPTH_PASS] += SolidPoly;
|
||||
poly_count[SHADOW_PASS] += ShadowPoly;
|
||||
|
||||
glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
|
||||
if (irr_driver->hasBufferStorageExtension())
|
||||
glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
|
||||
}
|
@ -19,14 +19,12 @@ public:
|
||||
{
|
||||
glGenBuffers(1, &drawindirectcmd);
|
||||
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, drawindirectcmd);
|
||||
#ifdef Buffer_Storage
|
||||
if (irr_driver->hasBufferStorageExtension())
|
||||
{
|
||||
glBufferStorage(GL_DRAW_INDIRECT_BUFFER, 10000 * sizeof(DrawElementsIndirectCommand), 0, GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT);
|
||||
Ptr = (DrawElementsIndirectCommand *)glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, 10000 * sizeof(DrawElementsIndirectCommand), GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
glBufferData(GL_DRAW_INDIRECT_BUFFER, 10000 * sizeof(DrawElementsIndirectCommand), 0, GL_STREAM_DRAW);
|
||||
}
|
||||
|
355
src/graphics/vaomanager.cpp
Normal file
355
src/graphics/vaomanager.cpp
Normal file
@ -0,0 +1,355 @@
|
||||
#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;
|
||||
last_vertex[0] = last_vertex[1] = last_vertex[2] = 0;
|
||||
last_index[0] = last_index[1] = last_index[2] = 0;
|
||||
RealVBOSize[0] = RealVBOSize[1] = RealVBOSize[2] = 0;
|
||||
RealIBOSize[0] = RealIBOSize[1] = RealIBOSize[2] = 0;
|
||||
|
||||
for (unsigned i = 0; i < InstanceTypeCount; i++)
|
||||
{
|
||||
glGenBuffers(1, &instance_vbo[i]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[i]);
|
||||
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
|
||||
{
|
||||
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 (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, size_t newlastvertex, size_t newlastindex)
|
||||
{
|
||||
glBindVertexArray(0);
|
||||
|
||||
if (newlastindex >= RealVBOSize[tp])
|
||||
{
|
||||
while (newlastindex >= RealVBOSize[tp])
|
||||
RealVBOSize[tp] = 2 * RealVBOSize[tp] + 1;
|
||||
GLuint newVBO;
|
||||
glGenBuffers(1, &newVBO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, newVBO);
|
||||
if (irr_driver->hasBufferStorageExtension())
|
||||
{
|
||||
glBufferStorage(GL_ARRAY_BUFFER, RealVBOSize[tp] * getVertexPitch(tp), 0, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT);
|
||||
VBOPtr[tp] = glMapBufferRange(GL_ARRAY_BUFFER, 0, RealVBOSize[tp] * getVertexPitch(tp), GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT);
|
||||
}
|
||||
else
|
||||
glBufferData(GL_ARRAY_BUFFER, RealVBOSize[tp] * getVertexPitch(tp), 0, GL_DYNAMIC_DRAW);
|
||||
|
||||
if (vbo[tp])
|
||||
{
|
||||
GLuint oldVBO = vbo[tp];
|
||||
glBindBuffer(GL_COPY_WRITE_BUFFER, newVBO);
|
||||
glBindBuffer(GL_COPY_READ_BUFFER, oldVBO);
|
||||
glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, last_vertex[tp] * getVertexPitch(tp));
|
||||
glDeleteBuffers(1, &oldVBO);
|
||||
}
|
||||
vbo[tp] = newVBO;
|
||||
}
|
||||
last_vertex[tp] = newlastvertex;
|
||||
|
||||
if (newlastindex >= RealIBOSize[tp])
|
||||
{
|
||||
while (newlastindex >= RealIBOSize[tp])
|
||||
RealIBOSize[tp] = 2 * RealIBOSize[tp] + 1;
|
||||
GLuint newIBO;
|
||||
glGenBuffers(1, &newIBO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, newIBO);
|
||||
if (irr_driver->hasBufferStorageExtension())
|
||||
{
|
||||
glBufferStorage(GL_ELEMENT_ARRAY_BUFFER, RealIBOSize[tp] * sizeof(u16), 0, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT);
|
||||
IBOPtr[tp] = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, RealIBOSize[tp] * sizeof(u16), GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT);
|
||||
}
|
||||
else
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, RealIBOSize[tp] * sizeof(u16), 0, GL_STATIC_DRAW);
|
||||
|
||||
if (ibo[tp])
|
||||
{
|
||||
GLuint oldIBO = ibo[tp];
|
||||
glBindBuffer(GL_COPY_WRITE_BUFFER, newIBO);
|
||||
glBindBuffer(GL_COPY_READ_BUFFER, oldIBO);
|
||||
glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, last_index[tp] * sizeof(u16));
|
||||
glDeleteBuffers(1, &oldIBO);
|
||||
}
|
||||
ibo[tp] = newIBO;
|
||||
}
|
||||
last_index[tp] = newlastindex;
|
||||
}
|
||||
|
||||
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 = last_vertex[tp];
|
||||
size_t old_idx_cnt = last_index[tp];
|
||||
|
||||
regenerateBuffer(tp, old_vtx_cnt + mb->getVertexCount(), old_idx_cnt + mb->getIndexCount());
|
||||
if (irr_driver->hasBufferStorageExtension())
|
||||
{
|
||||
void *tmp = (char*)VBOPtr[tp] + old_vtx_cnt * getVertexPitch(tp);
|
||||
memcpy(tmp, mb->getVertices(), mb->getVertexCount() * getVertexPitch(tp));
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo[tp]);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, old_vtx_cnt * getVertexPitch(tp), mb->getVertexCount() * getVertexPitch(tp), mb->getVertices());
|
||||
}
|
||||
if (irr_driver->hasBufferStorageExtension())
|
||||
{
|
||||
void *tmp = (char*)IBOPtr[tp] + old_idx_cnt * sizeof(u16);
|
||||
memcpy(tmp, mb->getIndices(), mb->getIndexCount() * sizeof(u16));
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[tp]);
|
||||
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, old_idx_cnt * sizeof(u16), mb->getIndexCount() * sizeof(u16), mb->getIndices());
|
||||
}
|
||||
|
||||
mappedBaseVertex[tp][mb] = old_vtx_cnt;
|
||||
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());
|
||||
append(mb, 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);
|
||||
}
|
112
src/graphics/vaomanager.hpp
Normal file
112
src/graphics/vaomanager.hpp
Normal file
@ -0,0 +1,112 @@
|
||||
#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];
|
||||
void *Ptr[InstanceTypeCount];
|
||||
void *VBOPtr[VTXTYPE_COUNT], *IBOPtr[VTXTYPE_COUNT];
|
||||
size_t RealVBOSize[VTXTYPE_COUNT], RealIBOSize[VTXTYPE_COUNT];
|
||||
size_t last_vertex[VTXTYPE_COUNT], last_index[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, size_t, size_t);
|
||||
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
|
@ -423,7 +423,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();
|
||||
@ -792,7 +792,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))
|
||||
{
|
||||
|
@ -115,9 +115,11 @@ private:
|
||||
/** Last time the bouncing ball was collected */
|
||||
float m_rubber_ball_collect_time;
|
||||
|
||||
public:
|
||||
/** The mesh for each model (if the powerup has a model), e.g. a switch
|
||||
has none. */
|
||||
irr::scene::IMesh *m_all_meshes[POWERUP_MAX];
|
||||
private:
|
||||
|
||||
/** Size of the corresponding mesh. */
|
||||
btVector3 m_all_extends[POWERUP_MAX];
|
||||
|
@ -914,35 +914,45 @@ void World::update(float dt)
|
||||
}
|
||||
#endif
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("World::update (sub-updates)", 0x20, 0x7F, 0x00);
|
||||
history->update(dt);
|
||||
if(ReplayRecorder::get()) ReplayRecorder::get()->update(dt);
|
||||
if(ReplayPlay::get()) ReplayPlay::get()->update(dt);
|
||||
if(history->replayHistory()) dt=history->getNextDelta();
|
||||
WorldStatus::update(dt);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
if (!history->dontDoPhysics())
|
||||
{
|
||||
m_physics->update(dt);
|
||||
}
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("World::update (AI)", 0x40, 0x7F, 0x00);
|
||||
const int kart_amount = m_karts.size();
|
||||
for (int i = 0 ; i < kart_amount; ++i)
|
||||
{
|
||||
// Update all karts that are not eliminated
|
||||
if(!m_karts[i]->isEliminated()) m_karts[i]->update(dt) ;
|
||||
}
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("World::update (camera)", 0x60, 0x7F, 0x00);
|
||||
for(unsigned int i=0; i<Camera::getNumCameras(); i++)
|
||||
{
|
||||
Camera::getCamera(i)->update(dt);
|
||||
}
|
||||
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("World::update (weather)", 0x80, 0x7F, 0x00);
|
||||
if (UserConfigParams::m_graphical_effects && m_weather)
|
||||
{
|
||||
m_weather->update(dt);
|
||||
}
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("World::update (projectiles)", 0xa0, 0x7F, 0x00);
|
||||
projectile_manager->update(dt);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
|
@ -117,6 +117,12 @@ void TrackInfoScreen::init()
|
||||
ITexture* screenshot = irr_driver->getTexture(m_track->getScreenshotFile(),
|
||||
"While loading screenshot for track '%s':",
|
||||
m_track->getFilename() );
|
||||
if(!screenshot)
|
||||
{
|
||||
screenshot = irr_driver->getTexture("main_help.png",
|
||||
"While loading screenshot for track '%s':",
|
||||
m_track->getFilename());
|
||||
}
|
||||
if (screenshot != NULL)
|
||||
m_screenshot->setImage(screenshot);
|
||||
|
||||
@ -193,6 +199,9 @@ void TrackInfoScreen::init()
|
||||
getWidget<LabelWidget>("highscore2")->setVisible(false);
|
||||
getWidget<LabelWidget>("highscore3")->setVisible(false);
|
||||
}
|
||||
|
||||
RibbonWidget* bt_start = getWidget<GUIEngine::RibbonWidget>("buttons");
|
||||
bt_start->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
|
||||
|
||||
} // init
|
||||
|
||||
@ -325,3 +334,37 @@ void TrackInfoScreen::eventCallback(Widget* widget, const std::string& name,
|
||||
} // eventCallback
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
GUIEngine::EventPropagation TrackInfoScreen::filterActions(PlayerAction action,
|
||||
int deviceID,
|
||||
const unsigned int value,
|
||||
Input::InputType type,
|
||||
int playerId)
|
||||
{
|
||||
GUIEngine::EventPropagation result = EVENT_LET;
|
||||
RibbonWidget* bt_start = getWidget<GUIEngine::RibbonWidget>("buttons");
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case PA_MENU_LEFT:
|
||||
case PA_MENU_RIGHT:
|
||||
{
|
||||
if (bt_start->isFocusedForPlayer(playerId))
|
||||
{
|
||||
result = EVENT_BLOCK;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case PA_MENU_UP:
|
||||
case PA_MENU_DOWN:
|
||||
case PA_MENU_SELECT:
|
||||
case PA_MENU_CANCEL:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
} // filterActions
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -74,6 +74,14 @@ public:
|
||||
virtual void loadedFromFile();
|
||||
virtual void eventCallback(GUIEngine::Widget *,const std::string &name ,
|
||||
const int player_id);
|
||||
|
||||
/** \brief implement callback from parent class GUIEngine::Screen */
|
||||
virtual GUIEngine::EventPropagation filterActions( PlayerAction action,
|
||||
int deviceID,
|
||||
const unsigned int value,
|
||||
Input::InputType type,
|
||||
int playerId) OVERRIDE;
|
||||
|
||||
void onEnterPressedInternal();
|
||||
void setTrack(Track *track);
|
||||
};
|
||||
|
@ -612,37 +612,59 @@ public:
|
||||
/** Returns true if the normals of this track can be smoothed. */
|
||||
bool smoothNormals() const { return m_smooth_normals; }
|
||||
// ------------------------------------------------------------------------
|
||||
TrackObjectManager* getTrackObjectManager() const {return m_track_object_manager;}
|
||||
/** Returns the track object manager. */
|
||||
TrackObjectManager* getTrackObjectManager() const
|
||||
{
|
||||
return m_track_object_manager;
|
||||
} // getTrackObjectManager
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Get list of challenges placed on that world. Works only for overworld. */
|
||||
const std::vector<OverworldChallenge>& getChallengeList() const
|
||||
{ return m_challenges; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
const std::vector<Subtitle>& getSubtitles() const { return m_subtitles; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
bool hasClouds() const { return m_clouds; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
bool getBloom() const { return m_bloom; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
float getBloomThreshold() const { return m_bloom_threshold; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return the color levels for color correction shader */
|
||||
core::vector3df getColorLevelIn() const { return m_color_inlevel; }
|
||||
// ------------------------------------------------------------------------
|
||||
core::vector2df getColorLevelOut() const { return m_color_outlevel; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
bool hasLensFlare() const { return m_lensflare; }
|
||||
// ------------------------------------------------------------------------
|
||||
bool hasGodRays() const { return m_godrays; }
|
||||
// ------------------------------------------------------------------------
|
||||
core::vector3df getGodRaysPosition() const { return m_godrays_position; }
|
||||
// ------------------------------------------------------------------------
|
||||
float getGodRaysOpacity() const { return m_godrays_opacity; }
|
||||
// ------------------------------------------------------------------------
|
||||
video::SColor getGodRaysColor() const { return m_godrays_color; }
|
||||
// ------------------------------------------------------------------------
|
||||
bool hasShadows() const { return m_shadows; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
void addNode(scene::ISceneNode* node) { m_all_nodes.push_back(node); }
|
||||
|
||||
float getDisplacementSpeed() const { return m_displacement_speed; }
|
||||
float getCausticsSpeed() const { return m_caustics_speed; }
|
||||
// ------------------------------------------------------------------------
|
||||
float getDisplacementSpeed() const { return m_displacement_speed; }
|
||||
// ------------------------------------------------------------------------
|
||||
float getCausticsSpeed() const { return m_caustics_speed; }
|
||||
// ------------------------------------------------------------------------
|
||||
const int getDefaultNumberOfLaps() const { return m_default_number_of_laps;}
|
||||
const int getActualNumberOfLap() const { return m_actual_number_of_laps; }
|
||||
void setActualNumberOfLaps(unsigned int laps)
|
||||
// ------------------------------------------------------------------------
|
||||
const int getActualNumberOfLap() const { return m_actual_number_of_laps; }
|
||||
// ------------------------------------------------------------------------
|
||||
void setActualNumberOfLaps(unsigned int laps)
|
||||
{ m_actual_number_of_laps = laps; }
|
||||
bool operator<(const Track &other) const;
|
||||
}; // class Track
|
||||
|
@ -250,88 +250,27 @@ namespace StringUtils
|
||||
} // insertValues(s, v1)
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Intermediate struct to fill a vector using variadic templates */
|
||||
struct __FillStringwVector
|
||||
{
|
||||
template<typename T, typename...Args>
|
||||
static void __Fill(std::vector<irr::core::stringw> &all_vals, T&& v, Args &&...args)
|
||||
{
|
||||
all_vals.push_back(irr::core::stringw(std::forward<T>(v)));
|
||||
__Fill(all_vals, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
static void __Fill(std::vector<irr::core::stringw>&) {}
|
||||
};
|
||||
|
||||
/** Like the other ones above but for wide strings */
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6>
|
||||
irr::core::stringw insertValues(const irr::core::stringw &s, const T1 &v1,
|
||||
const T2 &v2, const T3 &v3, const T4 &v4,
|
||||
const T5 &v5, const T6 &v6)
|
||||
template <typename...Args>
|
||||
irr::core::stringw insertValues(const irr::core::stringw &s, Args ...args)
|
||||
{
|
||||
std::vector<irr::core::stringw> all_vals;
|
||||
all_vals.push_back( irr::core::stringw(v1) );
|
||||
all_vals.push_back( irr::core::stringw(v2) );
|
||||
all_vals.push_back( irr::core::stringw(v3) );
|
||||
all_vals.push_back( irr::core::stringw(v4) );
|
||||
all_vals.push_back( irr::core::stringw(v5) );
|
||||
all_vals.push_back( irr::core::stringw(v6) );
|
||||
__FillStringwVector::__Fill(all_vals, std::forward<Args>(args)...);
|
||||
return insertValues(s, all_vals);
|
||||
} // insertValues(s, v1, ..., v6)
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Like the other ones above but for wide strings */
|
||||
template <class T1, class T2, class T3, class T4, class T5>
|
||||
irr::core::stringw insertValues(const irr::core::stringw &s, const T1 &v1,
|
||||
const T2 &v2, const T3 &v3, const T4 &v4,
|
||||
const T5 &v5)
|
||||
{
|
||||
std::vector<irr::core::stringw> all_vals;
|
||||
all_vals.push_back( irr::core::stringw(v1) );
|
||||
all_vals.push_back( irr::core::stringw(v2) );
|
||||
all_vals.push_back( irr::core::stringw(v3) );
|
||||
all_vals.push_back( irr::core::stringw(v4) );
|
||||
all_vals.push_back( irr::core::stringw(v5) );
|
||||
return insertValues(s, all_vals);
|
||||
} // insertValues(s, v1, ..., v5)
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Like the other ones above but for wide strings */
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
irr::core::stringw insertValues(const irr::core::stringw &s, const T1 &v1,
|
||||
const T2 &v2, const T3 &v3, const T4 &v4)
|
||||
{
|
||||
std::vector<irr::core::stringw> all_vals;
|
||||
all_vals.push_back( irr::core::stringw(v1) );
|
||||
all_vals.push_back( irr::core::stringw(v2) );
|
||||
all_vals.push_back( irr::core::stringw(v3) );
|
||||
all_vals.push_back( irr::core::stringw(v4) );
|
||||
return insertValues(s, all_vals);
|
||||
} // insertValues(s, v1, ..., v4)
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Like the other ones above but for wide strings */
|
||||
template <class T1, class T2, class T3>
|
||||
irr::core::stringw insertValues(const irr::core::stringw &s, const T1 &v1,
|
||||
const T2 &v2, const T3 &v3)
|
||||
{
|
||||
std::vector<irr::core::stringw> all_vals;
|
||||
irr::core::stringw dummy;
|
||||
all_vals.push_back( irr::core::stringw(v1) );
|
||||
all_vals.push_back( irr::core::stringw(v2) );
|
||||
all_vals.push_back( irr::core::stringw(v3) );
|
||||
return insertValues(s, all_vals);
|
||||
} // insertValues(s, v1, ..., v3)
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Like the other ones above but for wide strings */
|
||||
template <class T1, class T2>
|
||||
irr::core::stringw insertValues(const irr::core::stringw &s, const T1 &v1,
|
||||
const T2 &v2)
|
||||
{
|
||||
std::vector<irr::core::stringw> all_vals;
|
||||
all_vals.push_back( irr::core::stringw(v1) );
|
||||
all_vals.push_back( irr::core::stringw(v2) );
|
||||
return insertValues(s, all_vals);
|
||||
} // insertValues(s, v1, v2)
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Like the other ones above but for wide strings */
|
||||
template <class T1>
|
||||
irr::core::stringw insertValues(const irr::core::stringw &s, const T1 &v1)
|
||||
{
|
||||
std::vector<irr::core::stringw> all_vals;
|
||||
all_vals.push_back( irr::core::stringw(v1) );
|
||||
return insertValues(s, all_vals);
|
||||
} // insertValues(s, v1)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Like the other ones above but for wide strings */
|
||||
|
Loading…
x
Reference in New Issue
Block a user