Merge branch 'master' of github.com:supertuxkart/stk-code

This commit is contained in:
hiker 2014-08-25 10:30:12 +10:00
commit aef5b3aaea
28 changed files with 720 additions and 256 deletions

View File

@ -368,10 +368,8 @@ install(DIRECTORY ${STK_DATA_DIR} DESTINATION ${STK_INSTALL_DATA_DIR} PATTERN ".
if(STK_ASSETS_DIR AND CHECK_ASSETS)
install(DIRECTORY ${STK_ASSETS_DIR} DESTINATION ${STK_INSTALL_DATA_DIR}/data PATTERN ".svn" EXCLUDE PATTERN ".git" EXCLUDE)
endif()
install(FILES ${PROJECT_BINARY_DIR}/supertuxkart.desktop DESTINATION share/applications)
install(FILES ${STK_DATA_DIR}/supertuxkart.desktop DESTINATION share/applications)
install(FILES data/supertuxkart_32.png DESTINATION share/icons/hicolor/32x32 RENAME supertuxkart.png)
install(FILES data/supertuxkart_128.png DESTINATION share/icons/hicolor/128x128 RENAME supertuxkart.png)
install(FILES data/supertuxkart_32.png data/supertuxkart_128.png DESTINATION share/pixmaps)
install(FILES data/supertuxkart.appdata DESTINATION share/appdata)
set(PREFIX ${CMAKE_INSTALL_PREFIX})
configure_file(data/supertuxkart_desktop.template supertuxkart.desktop)
add_dependencies(supertuxkart supertuxkart.desktop)

View File

@ -9,6 +9,10 @@ layout(location = 3) in vec2 Texcoord;
layout(location = 7) in vec3 Origin;
layout(location = 8) in vec3 Orientation;
layout(location = 9) in vec3 Scale;
#ifdef GL_ARB_bindless_texture
layout(location = 10) in sampler2D Handle;
#endif
#else
in vec3 Position;
in vec3 Normal;
@ -22,6 +26,9 @@ in vec3 Scale;
out vec3 nor;
out vec2 uv;
#ifdef GL_ARB_bindless_texture
flat out sampler2D handle;
#endif
mat4 getWorldMatrix(vec3 translation, vec3 rotation, vec3 scale);
mat4 getInverseWorldMatrix(vec3 translation, vec3 rotation, vec3 scale);
@ -33,4 +40,7 @@ void main()
gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * vec4(Position, 1.);
nor = (TransposeInverseModelView * vec4(Normal, 0.)).xyz;
uv = Texcoord;
#ifdef GL_ARB_bindless_texture
handle = Handle;
#endif
}

View File

@ -0,0 +1,45 @@
#ifdef GL_ARB_bindless_texture
layout(bindless_sampler) uniform sampler2D dtex;
#else
uniform sampler2D Albedo;
uniform sampler2D dtex;
#endif
uniform vec3 SunDir;
#ifdef GL_ARB_bindless_texture
flat in sampler2D handle;
#endif
in vec3 nor;
in vec2 uv;
out vec4 FragColor;
vec3 getLightFactor(float specMapValue);
void main(void)
{
vec2 texc = gl_FragCoord.xy / screen;
float z = texture(dtex, texc).x;
vec4 xpos = 2.0 * vec4(texc, z, 1.0) - 1.0f;
xpos = InverseProjectionMatrix * xpos;
xpos /= xpos.w;
vec3 eyedir = normalize(xpos.xyz);
// Inspired from http://http.developer.nvidia.com/GPUGems3/gpugems3_ch16.html
float fEdotL = max(0., dot(SunDir, eyedir));
float fPowEdotL = pow(fEdotL, 4.);
float fLdotNBack = max(0., - dot(nor, SunDir) * 0.6 + 0.4);
float scattering = mix(fPowEdotL, fLdotNBack, .5);
#ifdef GL_ARB_bindless_texture
vec4 color = texture(handle, uv);
color.xyz = pow(color.xyz, vec3(2.2));
#else
vec4 color = texture(Albedo, uv);
#endif
if (color.a < 0.5) discard;
vec3 LightFactor = (scattering * 0.3) + getLightFactor(1.);
FragColor = vec4(color.xyz * LightFactor, 1.);
}

View File

@ -0,0 +1,35 @@
#ifndef GL_ARB_bindless_texture
uniform sampler2D normalMap;
uniform sampler2D DiffuseForAlpha;
#endif
#ifdef GL_ARB_bindless_texture
flat in sampler2D handle;
flat in sampler2D secondhandle;
#endif
in vec3 tangent;
in vec3 bitangent;
in vec2 uv;
out vec3 EncodedNormal;
vec2 EncodeNormal(vec3 n);
void main()
{
// normal in Tangent Space
#ifdef GL_ARB_bindless_texture
vec3 TS_normal = 2.0 * texture(secondhandle, uv).rgb - 1.0;
float alpha = texture(handle, uv).a;
#else
vec3 TS_normal = 2.0 * texture(normalMap, uv).rgb - 1.0;
float alpha = texture(DiffuseForAlpha, uv).a;
#endif
// Because of interpolation, we need to renormalize
vec3 Frag_tangent = normalize(tangent);
vec3 Frag_normal = normalize(cross(Frag_tangent, bitangent));
vec3 Frag_bitangent = cross(Frag_normal, Frag_tangent);
vec3 FragmentNormal = TS_normal.x * Frag_tangent + TS_normal.y * Frag_bitangent - TS_normal.z * Frag_normal;
EncodedNormal.xy = 0.5 * EncodeNormal(normalize(FragmentNormal)) + 0.5;
EncodedNormal.z = exp2(10. * (1. - alpha) + 1.);
}

View File

@ -9,6 +9,11 @@ layout(location = 6) in vec3 Bitangent;
layout(location = 7) in vec3 Origin;
layout(location = 8) in vec3 Orientation;
layout(location = 9) in vec3 Scale;
#ifdef GL_ARB_bindless_texture
layout(location = 10) in sampler2D Handle;
layout(location = 11) in sampler2D SecondHandle;
#endif
#else
in vec3 Position;
in vec3 Normal;
@ -27,6 +32,10 @@ out vec3 tangent;
out vec3 bitangent;
out vec2 uv;
out vec4 color;
#ifdef GL_ARB_bindless_texture
flat out sampler2D handle;
flat out sampler2D secondhandle;
#endif
mat4 getWorldMatrix(vec3 translation, vec3 rotation, vec3 scale);
mat4 getInverseWorldMatrix(vec3 translation, vec3 rotation, vec3 scale);
@ -41,4 +50,8 @@ void main(void)
bitangent = (TransposeInverseModelView * vec4(Bitangent, 1.)).xyz;
uv = Texcoord;
color = Color.zyxw;
#ifdef GL_ARB_bindless_texture
handle = Handle;
secondhandle = SecondHandle;
#endif
}

View File

@ -0,0 +1,23 @@
#ifndef GL_ARB_bindless_texture
uniform sampler2D tex;
#endif
#ifdef GL_ARB_bindless_texture
flat in sampler2D handle;
#endif
in vec3 nor;
in vec2 uv;
out vec3 EncodedNormal;
vec2 EncodeNormal(vec3 n);
void main(void)
{
#ifdef GL_ARB_bindless_texture
vec4 col = texture(handle, uv);
#else
vec4 col = texture(tex, uv);
#endif
EncodedNormal.xy = 0.5 * EncodeNormal(normalize(nor)) + 0.5;
EncodedNormal.z = exp2(10. * (1. - col.a) + 1.);
}

View File

@ -0,0 +1,24 @@
#ifndef GL_ARB_bindless_texture
uniform sampler2D Albedo;
#endif
#ifdef GL_ARB_bindless_texture
flat in sampler2D handle;
#endif
in vec2 uv;
in vec4 color;
out vec4 FragColor;
vec3 getLightFactor(float specMapValue);
void main(void)
{
#ifdef GL_ARB_bindless_texture
vec4 col = pow(texture(handle, uv), vec4(2.2));
#else
vec4 col = texture(Albedo, uv);
#endif
col.xyz *= pow(color.xyz, vec3(2.2));
vec3 LightFactor = getLightFactor(1.);
FragColor = vec4(col.xyz * LightFactor, 1.);
}

View File

@ -0,0 +1,25 @@
#ifndef GL_ARB_bindless_texture
uniform sampler2D tex;
#endif
#ifdef GL_ARB_bindless_texture
flat in sampler2D handle;
#endif
in vec3 nor;
in vec2 uv;
out vec3 EncodedNormal;
vec2 EncodeNormal(vec3 n);
void main() {
#ifdef GL_ARB_bindless_texture
vec4 col = texture(handle, uv);
#else
vec4 col = texture(tex, uv);
#endif
if (col.a < 0.5)
discard;
EncodedNormal.xy = 0.5 * EncodeNormal(normalize(nor)) + 0.5;
EncodedNormal.z = 1.;
}

View File

@ -0,0 +1,26 @@
#ifndef GL_ARB_bindless_texture
uniform sampler2D Albedo;
#endif
#ifdef GL_ARB_bindless_texture
flat in sampler2D handle;
#endif
in vec2 uv;
in vec4 color;
out vec4 FragColor;
vec3 getLightFactor(float specMapValue);
void main(void)
{
#ifdef GL_ARB_bindless_texture
vec4 col = texture(handle, uv);
col.xyz = pow(col.xyz, vec3(2.2));
#else
vec4 col = texture(Albedo, uv);
#endif
col.xyz *= pow(color.xyz, vec3(2.2));
if (col.a * color.a < 0.5) discard;
vec3 LightFactor = getLightFactor(1.);
FragColor = vec4(col.xyz * LightFactor, 1.);
}

View File

@ -0,0 +1,28 @@
layout(triangles) in;
layout(triangle_strip, max_vertices=3) out;
#ifdef GL_ARB_bindless_texture
flat in sampler2D hdle[3];
#endif
in vec2 tc[3];
in int layerId[3];
out vec2 uv;
#ifdef GL_ARB_bindless_texture
out flat sampler2D handle;
#endif
void main(void)
{
gl_Layer = layerId[0];
#ifdef GL_ARB_bindless_texture
handle = hdle[0];
#endif
for(int i=0; i<3; i++)
{
uv = tc[i];
gl_Position = gl_in[i].gl_Position;
EmitVertex();
}
EndPrimitive();
}

View File

@ -0,0 +1,21 @@
#ifndef GL_ARB_bindless_texture
uniform sampler2D tex;
#endif
#ifdef GL_ARB_bindless_texture
flat in sampler2D handle;
#endif
in vec2 uv;
in vec4 color;
out vec4 FragColor;
void main(void)
{
#ifdef GL_ARB_bindless_texture
vec4 col = texture(handle, uv);
#else
vec4 col = texture(tex, uv);
#endif
if (col.a < 0.5) discard;
FragColor = vec4(1.);
}

View File

@ -7,6 +7,10 @@ layout(location = 3) in vec2 Texcoord;
layout(location = 7) in vec3 Origin;
layout(location = 8) in vec3 Orientation;
layout(location = 9) in vec3 Scale;
#ifdef GL_ARB_bindless_texture
layout(location = 10) in sampler2D Handle;
#endif
#else
in vec3 Position;
in vec4 Color;
@ -19,9 +23,15 @@ in vec3 Scale;
#ifdef VSLayer
out vec2 uv;
#ifdef GL_ARB_bindless_texture
flat out sampler2D handle;
#endif
#else
out vec2 tc;
out int layerId;
#ifdef GL_ARB_bindless_texture
flat out sampler2D hdle;
#endif
#endif
mat4 getWorldMatrix(vec3 translation, vec3 rotation, vec3 scale);
@ -34,9 +44,15 @@ void main(void)
gl_Layer = gl_InstanceID & 3;
gl_Position = ShadowViewProjMatrixes[gl_Layer] * ModelMatrix * vec4(Position + windDir * Color.r, 1.);
uv = Texcoord;
#ifdef GL_ARB_bindless_texture
handle = Handle;
#endif
#else
layerId = gl_InstanceID & 3;
gl_Position = ShadowViewProjMatrixes[layerId] * ModelMatrix * vec4(Position + windDir * Color.r, 1.);
tc = Texcoord;
#ifdef GL_ARB_bindless_texture
hdle = Handle;
#endif
#endif
}

View File

@ -5,6 +5,10 @@ layout(location = 3) in vec2 Texcoord;
layout(location = 7) in vec3 Origin;
layout(location = 8) in vec3 Orientation;
layout(location = 9) in vec3 Scale;
#ifdef GL_ARB_bindless_texture
layout(location = 10) in sampler2D Handle;
#endif
#else
in vec3 Position;
in vec2 Texcoord;
@ -16,9 +20,15 @@ in vec3 Scale;
#ifdef VSLayer
out vec2 uv;
#ifdef GL_ARB_bindless_texture
flat out sampler2D handle;
#endif
#else
out vec2 tc;
out int layerId;
#ifdef GL_ARB_bindless_texture
flat out sampler2D hdle;
#endif
#endif
mat4 getWorldMatrix(vec3 translation, vec3 rotation, vec3 scale);
@ -31,9 +41,15 @@ void main(void)
gl_Layer = gl_InstanceID & 3;
gl_Position = ShadowViewProjMatrixes[gl_Layer] * ModelMatrix * vec4(Position, 1.);
uv = Texcoord;
#ifdef GL_ARB_bindless_texture
handle = Handle;
#endif
#else
layerId = gl_InstanceID & 3;
gl_Position = ShadowViewProjMatrixes[layerId] * ModelMatrix * vec4(Position, 1.);
tc = Texcoord;
#ifdef GL_ARB_bindless_texture
hdle = Handle;
#endif
#endif
}

View File

@ -1,15 +1,14 @@
[Desktop Entry]
Name=SuperTuxKart
Icon=@PREFIX@/share/pixmaps/supertuxkart_128.png
Icon=supertuxkart
GenericName=A kart racing game
GenericName[de]=Ein Kart-Rennspiel
GenericName[fr]=Un jeu de karting
GenericName[gl]=Xogo de carreiras con karts
GenericName[pl]=Wyścigi gokartów
GenericName[ro]=Un joc de curse cu carturi
Exec=@PREFIX@/@STK_INSTALL_BINARY_DIR@/supertuxkart --no-console
Exec=supertuxkart
Terminal=false
StartupNotify=false
Type=Application
TryExec=@PREFIX@/@STK_INSTALL_BINARY_DIR@/supertuxkart
Categories=Game;ArcadeGame;

View File

@ -251,12 +251,10 @@ bool CIrrDeviceLinux::restoreResolution()
if (UseXRandR && CreationParams.Fullscreen && old_mode != BadRRMode)
{
XRRScreenResources* res = XRRGetScreenResources(display, DefaultRootWindow(display));
if (!res)
return false;
XRROutputInfo* output = XRRGetOutputInfo(display, res, output_id);
if (!output || !output->crtc || output->connection == RR_Disconnected)
{
XRRFreeOutputInfo(output);
@ -264,10 +262,8 @@ bool CIrrDeviceLinux::restoreResolution()
}
XRRCrtcInfo* crtc = XRRGetCrtcInfo(display, res, output->crtc);
if (!crtc)
{
XRRFreeCrtcInfo(crtc);
XRRFreeOutputInfo(output);
return false;
}
@ -288,7 +284,7 @@ bool CIrrDeviceLinux::restoreResolution()
}
bool CIrrDeviceLinux::switchToFullscreen()
bool CIrrDeviceLinux::changeResolution()
{
if (!CreationParams.Fullscreen)
return true;
@ -356,22 +352,33 @@ bool CIrrDeviceLinux::switchToFullscreen()
XFree(modes);
}
else
#endif
#ifdef _IRR_LINUX_X11_RANDR_
if (XRRQueryExtension(display, &eventbase, &errorbase))
while (XRRQueryExtension(display, &eventbase, &errorbase))
{
XRRScreenResources* res = XRRGetScreenResources(display, DefaultRootWindow(display));
if (output_id == BadRROutput)
break;
if (!res || output_id == BadRROutput)
{
os::Printer::log("Could not get video output. Try to run in windowed mode.", ELL_WARNING);
CreationParams.Fullscreen = false;
return CreationParams.Fullscreen;
}
XRRScreenResources* res = XRRGetScreenResources(display, DefaultRootWindow(display));
if (!res)
break;
XRROutputInfo* output = XRRGetOutputInfo(display, res, output_id);
if (!output || !output->crtc || output->connection == RR_Disconnected)
{
XRRFreeOutputInfo(output);
XRRFreeScreenResources(res);
break;
}
XRRCrtcInfo* crtc = XRRGetCrtcInfo(display, res, output->crtc);
if (!crtc)
{
XRRFreeOutputInfo(output);
XRRFreeScreenResources(res);
break;
}
float refresh_rate, refresh_rate_new;
core::dimension2d<u32> mode0_size = core::dimension2d<u32>(0, 0);
@ -436,26 +443,22 @@ bool CIrrDeviceLinux::switchToFullscreen()
Status s = XRRSetCrtcConfig(display, res, output->crtc, CurrentTime,
crtc->x, crtc->y, output->modes[bestMode],
crtc->rotation, &output_id, 1);
if (s == Success)
UseXRandR = true;
XRRFreeCrtcInfo(crtc);
XRRFreeOutputInfo(output);
XRRFreeScreenResources(res);
if (s != Success)
{
CreationParams.Fullscreen = false;
return CreationParams.Fullscreen;
}
UseXRandR=true;
break;
}
else
#endif
if (UseXRandR == false)
{
os::Printer::log("VidMode or RandR extension must be installed to allow Irrlicht "
"to switch to fullscreen mode. Running in windowed mode instead.", ELL_WARNING);
os::Printer::log("Could not get video output. Try to run in windowed mode.", ELL_WARNING);
CreationParams.Fullscreen = false;
}
#endif
return CreationParams.Fullscreen;
}
@ -570,7 +573,7 @@ bool CIrrDeviceLinux::createWindow()
screennr = DefaultScreen(display);
switchToFullscreen();
changeResolution();
#ifdef _IRR_COMPILE_WITH_OPENGL_
@ -1625,7 +1628,6 @@ video::IVideoModeList* CIrrDeviceLinux::getVideoModeList()
crtc_x = crtc_y = -1;
XRRScreenResources* res = XRRGetScreenResources(display, DefaultRootWindow(display));
if (!res)
break;
@ -1633,49 +1635,39 @@ video::IVideoModeList* CIrrDeviceLinux::getVideoModeList()
for (int i = 0; i < res->noutput; i++)
{
output = XRRGetOutputInfo(display, res, res->outputs[i]);
if (!output || !output->crtc || output->connection == RR_Disconnected)
XRROutputInfo* output_tmp = XRRGetOutputInfo(display, res, res->outputs[i]);
if (!output_tmp || !output_tmp->crtc || output_tmp->connection == RR_Disconnected)
{
XRRFreeOutputInfo(output);
XRRFreeOutputInfo(output_tmp);
continue;
}
crtc = XRRGetCrtcInfo(display, res, output->crtc);
if (!crtc)
XRRCrtcInfo* crtc_tmp = XRRGetCrtcInfo(display, res, output_tmp->crtc);
if (!crtc_tmp)
{
XRRFreeOutputInfo(output_tmp);
continue;
}
if (res->outputs[i] == primary_id ||
output_id == BadRROutput || crtc_tmp->x < crtc->x ||
(crtc_tmp->x == crtc->x && crtc_tmp->y < crtc->y))
{
XRRFreeCrtcInfo(crtc);
XRRFreeOutputInfo(output);
continue;
XRRFreeOutputInfo(output);
output = output_tmp;
crtc = crtc_tmp;
output_id = res->outputs[i];
}
else
{
XRRFreeCrtcInfo(crtc_tmp);
XRRFreeOutputInfo(output_tmp);
}
if (res->outputs[i] == primary_id)
{
crtc_x = crtc->x;
crtc_y = crtc->y;
output_id = res->outputs[i];
XRRFreeCrtcInfo(crtc);
XRRFreeOutputInfo(output);
break;
}
if (crtc_x == -1 || crtc->x < crtc_x)
{
crtc_x = crtc->x;
crtc_y = crtc->y;
output_id = res->outputs[i];
}
else if (crtc_x == crtc->x && crtc->y < crtc_y)
{
crtc_x = crtc->x;
crtc_y = crtc->y;
output_id = res->outputs[i];
}
XRRFreeCrtcInfo(crtc);
XRRFreeOutputInfo(output);
}
if (output_id == BadRROutput)
@ -1683,9 +1675,9 @@ video::IVideoModeList* CIrrDeviceLinux::getVideoModeList()
os::Printer::log("Could not get video output.", ELL_WARNING);
break;
}
output = XRRGetOutputInfo(display, res, output_id);
crtc = XRRGetCrtcInfo(display, res, output->crtc);
crtc_x = crtc->x;
crtc_y = crtc->y;
for (int i = 0; i < res->nmode; i++)
{
@ -1719,8 +1711,7 @@ video::IVideoModeList* CIrrDeviceLinux::getVideoModeList()
XRRFreeCrtcInfo(crtc);
XRRFreeOutputInfo(output);
XRRFreeScreenResources(res);
XRRFreeScreenResources(res);
break;
}
#endif

View File

@ -151,7 +151,7 @@ namespace irr
void initXAtoms();
bool restoreResolution();
bool switchToFullscreen();
bool changeResolution();
//! Implementation of the linux cursor control
class CCursorControl : public gui::ICursorControl

View File

@ -128,6 +128,7 @@ extern PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB;
#ifdef WIN32
#define Bindless_Texture_Support
#define Base_Instance_Support
#endif
#endif

View File

@ -4,6 +4,7 @@
#include "config/user_config.hpp"
#include "utils/profiler.hpp"
#include "utils/cpp2011.hpp"
#include "graphics/stkmesh.hpp"
#ifdef _IRR_WINDOWS_API_
#define IRR_OGL_LOAD_EXTENSION(X) wglGetProcAddress(reinterpret_cast<const char*>(X))
@ -107,7 +108,7 @@ PFNGLVERTEXATTRIBLPOINTERPROC glVertexAttribLPointer;
static bool is_gl_init = false;
#ifdef DEBUG
#ifdef WIN32
#if !defined(__APPLE__)
#define ARB_DEBUG_OUTPUT
#endif
#endif
@ -592,10 +593,33 @@ VAOManager::VAOManager()
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;
glGenBuffers(1, &instance_vbo[0]);
glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[0]);
glBufferData(GL_ARRAY_BUFFER, 10000 * sizeof(float)* 9, 0, GL_STATIC_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);
cleanVAOMap(ShadowInstanceVAO);
InstanceVAO.clear();
ShadowInstanceVAO.clear();
}
VAOManager::~VAOManager()
{
cleanInstanceVAOs();
for (unsigned i = 0; i < 3; i++)
{
if (vtx_mirror[i])
@ -609,7 +633,7 @@ VAOManager::~VAOManager()
if (vao[i])
glDeleteVertexArrays(1, &vao[i]);
}
glDeleteBuffers(1, &instance_vbo[0]);
}
void VAOManager::regenerateBuffer(enum VTXTYPE tp)
@ -697,6 +721,65 @@ void VAOManager::regenerateVAO(enum VTXTYPE 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++)
{
for (unsigned j = 0; j < InstanceTypeCount; j++)
{
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[j]);
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, (InstanceType) j)] = vao;
GLuint shadow_vao = createVAO(vbo[tp], ibo[tp], tp);
glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[j]);
glEnableVertexAttribArray(7);
glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), 0);
glVertexAttribDivisor(7, 4);
glEnableVertexAttribArray(8);
glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(3 * sizeof(float)));
glVertexAttribDivisor(8, 4);
glEnableVertexAttribArray(9);
glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(6 * sizeof(float)));
glVertexAttribDivisor(9, 4);
glEnableVertexAttribArray(10);
glVertexAttribIPointer(10, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float)));
glVertexAttribDivisor(10, 4);
glEnableVertexAttribArray(11);
glVertexAttribIPointer(11, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float)+2 * sizeof(unsigned)));
glVertexAttribDivisor(11, 1);
ShadowInstanceVAO[std::pair<video::E_VERTEX_TYPE, InstanceType>(tp, (InstanceType)j)] = shadow_vao;
glBindVertexArray(0);
}
}
}
size_t VAOManager::getVertexPitch(enum VTXTYPE tp) const
{
switch (tp)
@ -756,6 +839,7 @@ std::pair<unsigned, unsigned> VAOManager::getBase(scene::IMeshBuffer *mb)
append(mb, tp);
regenerateBuffer(tp);
regenerateVAO(tp);
regenerateInstancedVAO();
}
std::map<scene::IMeshBuffer*, unsigned>::iterator It;
@ -767,6 +851,15 @@ std::pair<unsigned, unsigned> VAOManager::getBase(scene::IMeshBuffer *mb)
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 &timer)
{
if (!UserConfigParams::m_profiler_enabled) return;

View File

@ -139,25 +139,71 @@ 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,
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
};
#pragma pack(pop)
#else
} __attribute__((packed));
#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[1];
size_t instance_count[1];
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, ShadowInstanceVAO;
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);
unsigned getVBO(video::E_VERTEX_TYPE type) { return vbo[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)]; }
unsigned getShadowInstanceVAO(video::E_VERTEX_TYPE vt, enum InstanceType it) { return ShadowInstanceVAO[std::pair<video::E_VERTEX_TYPE, InstanceType>(vt, it)]; }
~VAOManager();
};

View File

@ -483,12 +483,20 @@ void IrrDriver::initDevice()
// Parse extensions
hasVSLayer = false;
hasBaseInstance = false;
// Default false value for hasVSLayer if --no-graphics argument is used
if (!ProfileWorld::isNoGraphics())
{
if (hasGLExtension("GL_AMD_vertex_shader_layer")) {
hasVSLayer = true;
Log::info("GLDriver", "AMD Vertex Shader Layer enabled");
}
#ifdef Base_Instance_Support
if (hasGLExtension("GL_ARB_base_instance")) {
hasBaseInstance = true;
Log::info("GLDriver", "ARB Instance enabled");
}
#endif
}

View File

@ -199,6 +199,7 @@ class IrrDriver : public IEventReceiver, public NoCopy
private:
int GLMajorVersion, GLMinorVersion;
bool hasVSLayer;
bool hasBaseInstance;
bool m_need_ubo_workaround;
bool m_need_rh_workaround;
/** The irrlicht device. */
@ -293,6 +294,11 @@ public:
return m_need_rh_workaround;
}
bool hasARB_base_instance() const
{
return hasBaseInstance;
}
bool hasVSLayerExtension() const
{
return hasVSLayer;

View File

@ -176,7 +176,12 @@ struct instanced_custom_unroll_args<>
size_t count = mesh->IndexCount;
Shader->setUniforms(args...);
glDrawElementsInstanced(ptype, count, itype, 0, instance_count);
#ifdef Base_Instance_Support
if (irr_driver->hasARB_base_instance())
glDrawElementsInstancedBaseVertexBaseInstance(ptype, count, itype, (const void*)mesh->vaoOffset, instance_count, mesh->vaoBaseVertex, mesh->vaoBaseInstance);
else
#endif
glDrawElementsInstanced(ptype, count, itype, 0, instance_count);
}
};
@ -196,36 +201,25 @@ void renderInstancedMeshes1stPass(const std::vector<TexUnit> &TexUnits, std::vec
glUseProgram(Shader::getInstance()->Program);
for (unsigned i = 0; i < meshes->size(); i++)
{
std::vector<uint64_t> Handles;
std::vector<GLuint> Textures;
GLMesh &mesh = *(STK::tuple_get<0>(meshes->at(i)));
#ifdef DEBUG
if (mesh.VAOType != VertexType)
Log::error("RenderGeometry", "Wrong instanced vertex format");
#endif
glBindVertexArray(mesh.vao);
for (unsigned j = 0; j < TexUnits.size(); j++)
if (!irr_driver->hasARB_base_instance())
glBindVertexArray(mesh.vao);
if (!UserConfigParams::m_bindless_textures)
{
if (!mesh.textures[TexUnits[j].m_id])
mesh.textures[j] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
compressTexture(mesh.textures[TexUnits[j].m_id], TexUnits[j].m_premul_alpha);
if (UserConfigParams::m_bindless_textures)
for (unsigned j = 0; j < TexUnits.size(); j++)
{
#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[j]);
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
if (!mesh.textures[TexUnits[j].m_id])
mesh.textures[j] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
compressTexture(mesh.textures[TexUnits[j].m_id], TexUnits[j].m_premul_alpha);
Textures.push_back(getTextureGLuint(mesh.textures[TexUnits[j].m_id]));
}
if (UserConfigParams::m_bindless_textures)
Shader::getInstance()->SetTextureHandles(Handles);
else
}
Shader::getInstance()->SetTextureUnits(Textures);
}
instanced_custom_unroll_args<List...>::template exec(Shader::getInstance(), meshes->at(i));
}
}
@ -306,15 +300,23 @@ void IrrDriver::renderSolidFirstPass()
renderMeshes1stPass<MeshShader::ObjectPass1Shader, video::EVT_2TCOORDS, 2, 1>(TexUnits(TexUnit(0, true)), AnimatedListMatDetails::getInstance());
renderMeshes1stPass<MeshShader::ObjectRefPass1Shader, video::EVT_STANDARD, 3, 2, 1>(TexUnits(TexUnit(0, true)), AnimatedListMatUnlit::getInstance());
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault));
renderInstancedMeshes1stPass<MeshShader::InstancedObjectPass1Shader, video::EVT_STANDARD>(
TexUnits(TexUnit(0, true)),
ListInstancedMatDefault::getInstance());
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault));
renderInstancedMeshes1stPass<MeshShader::InstancedObjectRefPass1Shader, video::EVT_STANDARD>(
TexUnits(TexUnit(0, true)),
ListInstancedMatAlphaRef::getInstance());
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault));
renderInstancedMeshes1stPass<MeshShader::InstancedGrassPass1Shader, video::EVT_STANDARD, 2>(
TexUnits(TexUnit(0, true)),
ListInstancedMatGrass::getInstance());
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_TANGENTS, InstanceTypeDefault));
renderInstancedMeshes1stPass<MeshShader::InstancedNormalMapShader, video::EVT_TANGENTS>(
TexUnits(TexUnit(1, false), TexUnit(0, true)),
ListInstancedMatNormalMap::getInstance());
@ -349,16 +351,6 @@ void renderMeshes2ndPass(const std::vector<TexUnit> &TexUnits, std::vector<STK::
}
else
Textures.push_back(getTextureGLuint(mesh.textures[TexUnits[j].m_id]));
/* if (irr_driver->getLightViz())
{
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
else
{
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}*/
}
if (mesh.VAOType != VertexType)
@ -385,42 +377,28 @@ void renderInstancedMeshes2ndPass(const std::vector<TexUnit> &TexUnits, std::vec
for (unsigned i = 0; i < meshes->size(); i++)
{
GLMesh &mesh = *(STK::tuple_get<0>(meshes->at(i)));
glBindVertexArray(mesh.vao);
std::vector<GLuint> Textures(Prefilled_tex);
std::vector<uint64_t> Handles(Prefilled_Handles);
for (unsigned j = 0; j < TexUnits.size(); j++)
{
if (!mesh.textures[TexUnits[j].m_id])
mesh.textures[TexUnits[j].m_id] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
compressTexture(mesh.textures[TexUnits[j].m_id], TexUnits[j].m_premul_alpha);
#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
if (UserConfigParams::m_bindless_textures)
Handles.push_back(mesh.TextureHandles[TexUnits[j].m_id]);
else
Textures.push_back(getTextureGLuint(mesh.textures[TexUnits[j].m_id]));
/* if (irr_driver->getLightViz())
{
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
else
{
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}*/
}
if (!irr_driver->hasARB_base_instance())
glBindVertexArray(mesh.vao);
if (UserConfigParams::m_bindless_textures)
{
std::vector<uint64_t> Handles(Prefilled_Handles);
for (unsigned i = 0; i < TexUnits.size(); i++)
Handles.push_back(0);
Shader::getInstance()->SetTextureHandles(Handles);
}
else
Shader::getInstance()->SetTextureUnits(Textures);
{
std::vector<GLuint> Textures(Prefilled_tex);
for (unsigned j = 0; j < TexUnits.size(); j++)
{
if (!mesh.textures[TexUnits[j].m_id])
mesh.textures[TexUnits[j].m_id] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
compressTexture(mesh.textures[TexUnits[j].m_id], TexUnits[j].m_premul_alpha);
Textures.push_back(getTextureGLuint(mesh.textures[TexUnits[j].m_id]));
Shader::getInstance()->SetTextureUnits(Textures);
}
}
instanced_custom_unroll_args<List...>::template exec(Shader::getInstance(), meshes->at(i));
}
@ -529,15 +507,23 @@ void IrrDriver::renderSolidSecondPass()
TexUnit(0, true)
), ListMatNormalMap::getInstance(), createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex);
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault));
renderInstancedMeshes2ndPass<MeshShader::InstancedObjectPass2Shader>(
TexUnits(TexUnit(0, true)),
ListInstancedMatDefault::getInstance(), createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex);
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_TANGENTS, InstanceTypeDefault));
renderInstancedMeshes2ndPass<MeshShader::InstancedObjectPass2Shader>(
TexUnits(TexUnit(0, true)),
ListInstancedMatNormalMap::getInstance(), createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex);
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault));
renderInstancedMeshes2ndPass<MeshShader::InstancedObjectRefPass2Shader>(
TexUnits(TexUnit(0, true)),
ListInstancedMatAlphaRef::getInstance(), createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex);
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault));
DiffSpecSSAOTex.push_back(irr_driver->getDepthStencilTexture());
renderInstancedMeshes2ndPass<MeshShader::InstancedGrassPass2Shader, 3, 2>(
TexUnits(TexUnit(0, true)),
@ -788,7 +774,12 @@ struct instanced_shadow_custom_unroll_args<>
size_t count = mesh->IndexCount;
Shader->setUniforms(args...);
glDrawElementsInstanced(ptype, count, itype, 0, 4 * instance_count);
#ifdef Base_Instance_Support
if (irr_driver->hasARB_base_instance())
glDrawElementsInstancedBaseVertexBaseInstance(ptype, count, itype, (const void*) mesh->vaoOffset, 4 * instance_count, mesh->vaoBaseVertex, mesh->vaoBaseInstance);
else
#endif
glDrawElementsInstanced(ptype, count, itype, 0, 4 * instance_count);
}
};
@ -811,27 +802,17 @@ void renderInstancedShadow(const std::vector<GLuint> TextureUnits, const std::ve
std::vector<uint64_t> Handles;
std::vector<GLuint> Textures;
GLMesh *mesh = STK::tuple_get<0>(t->at(i));
glBindVertexArray(mesh->vao_shadow_pass);
for (unsigned j = 0; j < TextureUnits.size(); j++)
if (!irr_driver->hasARB_base_instance())
glBindVertexArray(mesh->vao_shadow_pass);
if (!UserConfigParams::m_bindless_textures)
{
compressTexture(mesh->textures[TextureUnits[j]], true);
if (UserConfigParams::m_bindless_textures)
for (unsigned j = 0; j < TextureUnits.size(); j++)
{
#ifdef Bindless_Texture_Support
if (!mesh->TextureHandles[TextureUnits[j]])
mesh->TextureHandles[TextureUnits[j]] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh->textures[TextureUnits[j]]), T::getInstance()->SamplersId[j]);
if (!glIsTextureHandleResidentARB(mesh->TextureHandles[TextureUnits[j]]))
glMakeTextureHandleResidentARB(mesh->TextureHandles[TextureUnits[j]]);
#endif
Handles.push_back(mesh->TextureHandles[TextureUnits[j]]);
}
else
compressTexture(mesh->textures[TextureUnits[j]], true);
Textures.push_back(getTextureGLuint(mesh->textures[TextureUnits[j]]));
T::getInstance()->SetTextureUnits(Textures);
}
}
if (UserConfigParams::m_bindless_textures)
T::getInstance()->SetTextureHandles(Handles);
else
T::getInstance()->SetTextureUnits(Textures);
instanced_shadow_custom_unroll_args<List...>::template exec<T>(T::getInstance(), t->at(i));
}
}
@ -883,9 +864,17 @@ void IrrDriver::renderShadows()
renderShadow<MeshShader::RefShadowShader, EVT_STANDARD, 1>(std::vector<GLuint>{ 0 }, AnimatedListMatUnlit::getInstance());
renderShadow<MeshShader::ShadowShader, EVT_2TCOORDS, 1>(noTexUnits, AnimatedListMatDetails::getInstance());
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getShadowInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault));
renderInstancedShadow<MeshShader::InstancedShadowShader>(noTexUnits, ListInstancedMatDefault::getInstance());
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getShadowInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault));
renderInstancedShadow<MeshShader::InstancedRefShadowShader>(std::vector<GLuint>{ 0 }, ListInstancedMatAlphaRef::getInstance());
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getShadowInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault));
renderInstancedShadow<MeshShader::InstancedGrassShadowShader, 2>(std::vector<GLuint>{ 0 }, ListInstancedMatGrass::getInstance());
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getShadowInstanceVAO(video::EVT_TANGENTS, InstanceTypeDefault));
renderInstancedShadow<MeshShader::InstancedShadowShader>(noTexUnits, ListInstancedMatNormalMap::getInstance());
glDisable(GL_POLYGON_OFFSET_FILL);

View File

@ -818,7 +818,7 @@ namespace MeshShader
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_pass1.frag").c_str());
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_object_pass1.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "tex");
@ -833,7 +833,7 @@ namespace MeshShader
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass1.frag").c_str());
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_objectref_pass1.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "tex");
@ -848,7 +848,7 @@ namespace MeshShader
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_grass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass1.frag").c_str());
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_objectref_pass1.frag").c_str());
AssignUniforms("windDir");
AssignSamplerNames(Program, 0, "tex");
@ -863,7 +863,7 @@ namespace MeshShader
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/normalmap.frag").c_str());
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_normalmap.frag").c_str());
AssignUniforms();
GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData");
@ -893,7 +893,7 @@ namespace MeshShader
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_pass2.frag").c_str());
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_object_pass2.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "Albedo");
@ -909,7 +909,7 @@ namespace MeshShader
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass2.frag").c_str());
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_objectref_pass2.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "Albedo");
@ -975,7 +975,7 @@ namespace MeshShader
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_grass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/grass_pass2.frag").c_str());
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_grass_pass2.frag").c_str());
AssignUniforms("windDir", "SunDir");
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "dtex", 4, "Albedo");
@ -1158,7 +1158,7 @@ namespace MeshShader
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanciedshadow.vert").c_str(),
GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/shadow.geom").c_str(),
GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/instanced_shadow.geom").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/white.frag").c_str());
}
GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData");
@ -1200,15 +1200,15 @@ namespace MeshShader
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanciedshadow.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_unlit.frag").c_str());
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_shadowref.frag").c_str());
}
else
{
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanciedshadow.vert").c_str(),
GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/shadow.geom").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_unlit.frag").c_str());
GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/instanced_shadow.geom").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_shadowref.frag").c_str());
}
AssignSamplerNames(Program, 0, "tex");
@ -1251,15 +1251,15 @@ namespace MeshShader
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanciedgrassshadow.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_unlit.frag").c_str());
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_shadowref.frag").c_str());
}
else
{
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanciedgrassshadow.vert").c_str(),
GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/shadow.geom").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_unlit.frag").c_str());
GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/instanced_shadow.geom").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_shadowref.frag").c_str());
}
AssignSamplerNames(Program, 0, "tex");

View File

@ -439,10 +439,12 @@ public:
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
glUniformHandleui64ARB(TextureLocation[i], args[i]);
if (args[i])
glUniformHandleui64ARB(TextureLocation[i], args[i]);
#endif
}
}

View File

@ -50,41 +50,54 @@ void STKInstancedSceneNode::createGLMeshes()
{
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
GLmeshes.push_back(allocateMeshBuffer(mb));
fillLocalBuffer(GLmeshes.back(), mb);
GLMesh &mesh = GLmeshes.back();
if (irr_driver->hasARB_base_instance())
{
std::pair<unsigned, unsigned> p = VAOManager::getInstance()->getBase(mb);
mesh.vaoBaseVertex = p.first;
mesh.vaoOffset = p.second;
mesh.VAOType = mb->getVertexType();
}
else
fillLocalBuffer(mesh, mb);
instanceData.push_back(std::vector<InstanceData>());
}
isMaterialInitialized = false;
}
void STKInstancedSceneNode::initinstancedvaostate(GLMesh &mesh)
void STKInstancedSceneNode::initinstancedvaostate(GLMesh &mesh, const std::vector<InstanceData> &instances)
{
mesh.vao = createVAO(mesh.vertex_buffer, mesh.index_buffer, getVTXTYPEFromStride(mesh.Stride));
glGenBuffers(1, &instances_vbo);
glBindBuffer(GL_ARRAY_BUFFER, instances_vbo);
glBufferData(GL_ARRAY_BUFFER, instance_pos.size() * sizeof(float), instance_pos.data(), GL_STATIC_DRAW);
if (!irr_driver->hasARB_base_instance())
{
mesh.vao = createVAO(mesh.vertex_buffer, mesh.index_buffer, getVTXTYPEFromStride(mesh.Stride));
glGenBuffers(1, &instances_vbo);
glBindBuffer(GL_ARRAY_BUFFER, instances_vbo);
glBufferData(GL_ARRAY_BUFFER, instances.size() * sizeof(InstanceData), instances.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(7);
glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), 0);
glVertexAttribDivisor(7, 1);
glEnableVertexAttribArray(8);
glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (GLvoid*)(3 * sizeof(float)));
glVertexAttribDivisor(8, 1);
glEnableVertexAttribArray(9);
glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (GLvoid*)(6 * sizeof(float)));
glVertexAttribDivisor(9, 1);
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);
mesh.vao_shadow_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, getVTXTYPEFromStride(mesh.Stride));
glBindBuffer(GL_ARRAY_BUFFER, instances_vbo);
glEnableVertexAttribArray(7);
glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), 0);
glVertexAttribDivisor(7, 4);
glEnableVertexAttribArray(8);
glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (GLvoid*)(3 * sizeof(float)));
glVertexAttribDivisor(8, 4);
glEnableVertexAttribArray(9);
glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (GLvoid*)(6 * sizeof(float)));
glVertexAttribDivisor(9, 4);
mesh.vao_shadow_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, getVTXTYPEFromStride(mesh.Stride));
glBindBuffer(GL_ARRAY_BUFFER, instances_vbo);
glEnableVertexAttribArray(7);
glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), 0);
glVertexAttribDivisor(7, 4);
glEnableVertexAttribArray(8);
glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(3 * sizeof(float)));
glVertexAttribDivisor(8, 4);
glEnableVertexAttribArray(9);
glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(6 * sizeof(float)));
glVertexAttribDivisor(9, 4);
glBindVertexArray(0);
glBindVertexArray(0);
}
}
void STKInstancedSceneNode::setFirstTimeMaterial()
@ -100,7 +113,9 @@ void STKInstancedSceneNode::setFirstTimeMaterial()
GLMesh &mesh = GLmeshes[i];
MeshMaterial MatType = MaterialTypeToMeshMaterial(type, mb->getVertexType());
initinstancedvaostate(mesh);
initinstancedvaostate(mesh, instanceData[i]);
if (irr_driver->hasARB_base_instance())
mesh.vaoBaseInstance = VAOManager::getInstance()->appendInstance(InstanceTypeDefault, instanceData[i]);
MeshSolidMaterial[MatType].push_back(&mesh);
}
isMaterialInitialized = true;
@ -108,34 +123,65 @@ void STKInstancedSceneNode::setFirstTimeMaterial()
void STKInstancedSceneNode::addInstance(const core::vector3df &origin, const core::vector3df &orientation, const core::vector3df &scale)
{
instance_pos.push_back(origin.X);
instance_pos.push_back(origin.Y);
instance_pos.push_back(origin.Z);
instance_pos.push_back(orientation.X);
instance_pos.push_back(orientation.Y);
instance_pos.push_back(orientation.Z);
instance_pos.push_back(scale.X);
instance_pos.push_back(scale.Y);
instance_pos.push_back(scale.Z);
for (unsigned i = 0; i < GLmeshes.size(); i++)
{
GLMesh &mesh = GLmeshes[i];
#ifdef Bindless_Texture_Support
if (UserConfigParams::m_bindless_textures)
{
for (unsigned j = 0; j < 2; j++)
{
if (!mesh.textures[j])
mesh.textures[j] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
compressTexture(mesh.textures[j], true);
if (!mesh.TextureHandles[j])
mesh.TextureHandles[j] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh.textures[j]), MeshShader::InstancedNormalMapShader::getInstance()->SamplersId[j]);
if (!glIsTextureHandleResidentARB(mesh.TextureHandles[j]))
glMakeTextureHandleResidentARB(mesh.TextureHandles[j]);
}
}
#endif
InstanceData instance = {
{
origin.X,
origin.Y,
origin.Z
},
{
orientation.X,
orientation.Y,
orientation.Z
},
{
scale.X,
scale.Y,
scale.Z
},
mesh.TextureHandles[0],
mesh.TextureHandles[1]
};
instanceData[i].push_back(instance);
}
}
core::matrix4 STKInstancedSceneNode::getInstanceTransform(int id)
{
core::matrix4 mat;
int offset = id * 9;
const InstanceData &instance = instanceData[0][id];
mat.setTranslation(core::vector3df(
instance_pos[offset],
instance_pos[offset + 1],
instance_pos[offset + 2]));
instance.Origin.X,
instance.Origin.Y,
instance.Origin.Z));
mat.setRotationDegrees(core::vector3df(
instance_pos[offset + 3],
instance_pos[offset + 4],
instance_pos[offset + 5]));
instance.Orientation.X,
instance.Orientation.Y,
instance.Orientation.Z));
mat.setScale(core::vector3df(
instance_pos[offset + 6],
instance_pos[offset + 7],
instance_pos[offset + 8]));
instance.Scale.X,
instance.Scale.Y,
instance.Scale.Z));
return mat;
}
@ -150,30 +196,32 @@ void STKInstancedSceneNode::render()
setFirstTimeMaterial();
for(unsigned i = 0; i < MeshSolidMaterial[MAT_DEFAULT].size(); i++)
if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS || irr_driver->getPhase() == SHADOW_PASS)
{
GLMesh *mesh = MeshSolidMaterial[MAT_DEFAULT][i];
ListInstancedMatDefault::getInstance()->push_back(STK::make_tuple(mesh, instance_pos.size() / 9));
}
for (unsigned i = 0; i < MeshSolidMaterial[MAT_DEFAULT].size(); i++)
{
GLMesh *mesh = MeshSolidMaterial[MAT_DEFAULT][i];
ListInstancedMatDefault::getInstance()->push_back(STK::make_tuple(mesh, instanceData[0].size()));
}
for(unsigned i = 0; i < MeshSolidMaterial[MAT_ALPHA_REF].size(); i++)
{
GLMesh *mesh = MeshSolidMaterial[MAT_ALPHA_REF][i];
ListInstancedMatAlphaRef::getInstance()->push_back(STK::make_tuple(mesh, instance_pos.size() / 9));
}
for (unsigned i = 0; i < MeshSolidMaterial[MAT_ALPHA_REF].size(); i++)
{
GLMesh *mesh = MeshSolidMaterial[MAT_ALPHA_REF][i];
ListInstancedMatAlphaRef::getInstance()->push_back(STK::make_tuple(mesh, instanceData[0].size()));
}
windDir = getWind();
SunLightProvider * const cb = (SunLightProvider *)irr_driver->getCallback(ES_SUNLIGHT);
for(unsigned i = 0; i < MeshSolidMaterial[MAT_GRASS].size(); i++)
{
GLMesh *mesh = MeshSolidMaterial[MAT_GRASS][i];
ListInstancedMatGrass::getInstance()->push_back(STK::make_tuple(mesh, instance_pos.size() / 9, windDir, cb->getPosition()));
}
windDir = getWind();
SunLightProvider * const cb = (SunLightProvider *)irr_driver->getCallback(ES_SUNLIGHT);
for (unsigned i = 0; i < MeshSolidMaterial[MAT_GRASS].size(); i++)
{
GLMesh *mesh = MeshSolidMaterial[MAT_GRASS][i];
ListInstancedMatGrass::getInstance()->push_back(STK::make_tuple(mesh, instanceData[0].size(), windDir, cb->getPosition()));
}
for(unsigned i = 0; i < MeshSolidMaterial[MAT_NORMAL_MAP].size(); i++)
{
GLMesh *mesh = MeshSolidMaterial[MAT_NORMAL_MAP][i];
ListInstancedMatNormalMap::getInstance()->push_back(STK::make_tuple(mesh, instance_pos.size() / 9));
for (unsigned i = 0; i < MeshSolidMaterial[MAT_NORMAL_MAP].size(); i++)
{
GLMesh *mesh = MeshSolidMaterial[MAT_NORMAL_MAP][i];
ListInstancedMatNormalMap::getInstance()->push_back(STK::make_tuple(mesh, instanceData[0].size()));
}
}
}

View File

@ -22,13 +22,13 @@ protected:
int m_ref_count;
std::vector<GLMesh *> MeshSolidMaterial[MAT_COUNT];
std::vector<GLMesh> GLmeshes;
std::vector<float> instance_pos;
std::vector<std::vector<InstanceData> > instanceData;
core::matrix4 ModelViewProjectionMatrix, TransposeInverseModelView;
GLuint instances_vbo;
void createGLMeshes();
bool isMaterialInitialized;
void setFirstTimeMaterial();
void initinstancedvaostate(GLMesh &mesh);
void initinstancedvaostate(GLMesh &mesh, const std::vector<InstanceData> &);
void cleanGL();
core::vector3df windDir;
public:
@ -40,7 +40,7 @@ public:
virtual void render();
void addInstance(const core::vector3df &origin, const core::vector3df &orientation, const core::vector3df &scale);
int getInstanceCount() const { return instance_pos.size() / 9; }
int getInstanceCount() const { return instanceData[0].size(); }
core::matrix4 getInstanceTransform(int id);

View File

@ -46,6 +46,7 @@ struct GLMesh {
core::matrix4 TextureMatrix;
size_t vaoBaseVertex;
size_t vaoOffset;
size_t vaoBaseInstance;
video::E_VERTEX_TYPE VAOType;
uint64_t TextureHandles[6];
};

View File

@ -439,32 +439,32 @@ bool onEvent(const SEvent &event)
{
#if !defined(__APPLE__)
DebugSliderDialog *dsd = new DebugSliderDialog();
dsd->setSliderHook( "red_slider", 0, 255, [](){ return irr_driver->getAmbientLight().r * 255.; },
dsd->setSliderHook( "red_slider", 0, 255, [](){ return irr_driver->getAmbientLight().r * 255.f; },
[](int v){
video::SColorf ambient = irr_driver->getAmbientLight();
ambient.setColorComponentValue(0, v / 255.);
ambient.setColorComponentValue(0, v / 255.f);
irr_driver->setAmbientLight(ambient); }
);
dsd->setSliderHook("green_slider", 0, 255, [](){ return irr_driver->getAmbientLight().g * 255.; },
dsd->setSliderHook("green_slider", 0, 255, [](){ return irr_driver->getAmbientLight().g * 255.f; },
[](int v){
video::SColorf ambient = irr_driver->getAmbientLight();
ambient.setColorComponentValue(1, v / 255.);
ambient.setColorComponentValue(1, v / 255.f);
irr_driver->setAmbientLight(ambient); }
);
dsd->setSliderHook("blue_slider", 0, 255, [](){ return irr_driver->getAmbientLight().b * 255.; },
dsd->setSliderHook("blue_slider", 0, 255, [](){ return irr_driver->getAmbientLight().b * 255.f; },
[](int v){
video::SColorf ambient = irr_driver->getAmbientLight();
ambient.setColorComponentValue(2, v / 255.);
ambient.setColorComponentValue(2, v / 255.f);
irr_driver->setAmbientLight(ambient); }
);
dsd->setSliderHook("ssao_radius", 0, 100, [](){ return irr_driver->getSSAORadius() * 10; },
[](int v){irr_driver->setSSAORadius(v / 10.); }
dsd->setSliderHook("ssao_radius", 0, 100, [](){ return irr_driver->getSSAORadius() * 10.f; },
[](int v){irr_driver->setSSAORadius(v / 10.f); }
);
dsd->setSliderHook("ssao_k", 0, 100, [](){ return irr_driver->getSSAOK() * 10; },
[](int v){irr_driver->setSSAOK(v / 10.); }
dsd->setSliderHook("ssao_k", 0, 100, [](){ return irr_driver->getSSAOK() * 10.f; },
[](int v){irr_driver->setSSAOK(v / 10.f); }
);
dsd->setSliderHook("ssao_sigma", 0, 100, [](){ return irr_driver->getSSAOSigma() * 10; },
[](int v){irr_driver->setSSAOSigma(v / 10.); }
dsd->setSliderHook("ssao_sigma", 0, 100, [](){ return irr_driver->getSSAOSigma() * 10.f; },
[](int v){irr_driver->setSSAOSigma(v / 10.f); }
);
#endif
}