the model renderer now uses the map of renderPIpeline and the pipeline object of gpu, yeah. fixed the state to do the basics glState stuff correctly

This commit is contained in:
Sam Gateau 2015-03-25 10:16:18 -07:00
parent 6284159892
commit c9377d0811
8 changed files with 198 additions and 97 deletions

View file

@ -80,7 +80,7 @@ public:
class Command {
public:
virtual void run() = 0;
virtual void run(GLBackend* backend) = 0;
Command() {}
virtual ~Command() {};
@ -88,9 +88,9 @@ public:
template <class T> class Command1 : public Command {
public:
typedef void (*GLFunction)(typename T);
typedef void (GLBackend::*GLFunction)(typename T);
void run() { (_func)(_param); }
void run(GLBackend* backend) { (backend->*(_func))(_param); }
Command1(GLFunction func, T param) : _func(func), _param(param) {};
@ -101,7 +101,7 @@ public:
public:
typedef void (*GLFunction)(typename T, typename U);
void run() { (_func)(_param0, _param1); }
void run(GLBackend* backend) { (_func)(_param0, _param1); }
Command2(GLFunction func, T param0, U param1) : _func(func), _param0(param0), _param1(param1) {};
@ -114,7 +114,7 @@ public:
public:
typedef void (*GLFunction)(typename T, typename U, typename V, typename W);
void run() { (_func)(_param0, _param1, _param2, _param3); }
void run(GLBackend* backend) { (_func)(_param0, _param1, _param2, _param3); }
Command4(GLFunction func, T param0, U param1, V param2, W param3) :
_func(func),
@ -155,6 +155,24 @@ public:
uint32 getNumInputBuffers() const { return _input._buffersState.size(); }
void do_setStateFillMode(int32 mode);
void do_setStateCullMode(int32 mode);
void do_setStateFrontClockwise(int32 isFrontClockwise);
void do_setStateDepthClipEnable(int32 enable);
void do_setStateScissorEnable(int32 enable);
void do_setStateMultisampleEnable(int32 enable);
void do_setStateAntialiasedLineEnable(int32 enable);
void do_setStateDepthTest(State::DepthTest test);
void do_setStateStencilEnable(int32 enable);
void do_setStateAlphaToCoverageEnable(int32 enable);
void do_setStateBlendEnable(int32 enable);
protected:
// Draw Stage

View file

@ -79,6 +79,13 @@ void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) {
_pipeline._stateCommands = pipelineObject->_state->_commands;
_pipeline._invalidState = true;
// THis should be done on Pipeline::update...
if (_pipeline._invalidProgram) {
glUseProgram(_pipeline._program);
CHECK_GL_ERROR();
_pipeline._invalidProgram = false;
}
}
void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) {
@ -115,6 +122,7 @@ void GLBackend::do_setUniformTexture(Batch& batch, uint32 paramOffset) {
void GLBackend::updatePipeline() {
if (_pipeline._invalidProgram) {
// doing it here is aproblem for calls to glUniform.... so will do it on assing...
glUseProgram(_pipeline._program);
CHECK_GL_ERROR();
_pipeline._invalidProgram = false;
@ -122,7 +130,7 @@ void GLBackend::updatePipeline() {
if (_pipeline._invalidState) {
for (auto command: _pipeline._stateCommands) {
command->run();
command->run(this);
}
CHECK_GL_ERROR();
_pipeline._invalidState = false;

View file

@ -23,6 +23,8 @@ GLBackend::GLState::~GLState() {
typedef GLBackend::GLState::Command Command;
typedef GLBackend::GLState::CommandPointer CommandPointer;
typedef GLBackend::GLState::Command1<int32> Command1I;
typedef GLBackend::GLState::Command1<State::DepthTest> Command1DT;
typedef GLBackend::GLState::Command1<GLenum> Command1E;
typedef GLBackend::GLState::Command2<GLenum, GLenum> Command2E;
typedef GLBackend::GLState::Command2<GLfloat, GLfloat> Command2F;
@ -40,27 +42,16 @@ static GLenum GL_COMPARISON_FUNCTIONS[] = {
GL_GEQUAL,
GL_ALWAYS };
void glBackend_glPolygonMode(GLenum fillMode) {
glPolygonMode(GL_FRONT_AND_BACK, fillMode);
}
void generateFillMode(GLBackend::GLState::Commands& commands, State::FillMode fillMode) {
static GLenum GL_FILL_MODES[] = { GL_POINT, GL_LINE, GL_FILL };
commands.push_back(CommandPointer(new Command1E(glBackend_glPolygonMode, GL_FILL_MODES[fillMode])));
void generateFillMode(GLBackend::GLState::Commands& commands, State::FillMode fillMode) {
commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateFillMode, int32(fillMode))));
}
void generateCullMode(GLBackend::GLState::Commands& commands, State::CullMode cullMode) {
static GLenum CULL_MODES[] = { GL_FRONT_AND_BACK, GL_FRONT, GL_BACK };
if (cullMode == State::CULL_NONE) {
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDisable, GLenum(GL_CULL_FACE))));
} else {
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glEnable, GLenum(GL_CULL_FACE))));
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glCullFace, CULL_MODES[cullMode])));
}
commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateCullMode, int32(cullMode))));
}
void generateDepthBias(GLBackend::GLState::Commands& commands, const State& state) {
if ((state.getDepthBias() == 0) && (state.getDepthBiasSlopeScale() == 0.0f)) {
/* if ((state.getDepthBias() == 0) && (state.getDepthBiasSlopeScale() == 0.0f)) {
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDisable, GLenum(GL_POLYGON_OFFSET_FILL))));
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDisable, GLenum(GL_POLYGON_OFFSET_LINE))));
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDisable, GLenum(GL_POLYGON_OFFSET_POINT))));
@ -71,53 +62,39 @@ void generateDepthBias(GLBackend::GLState::Commands& commands, const State& stat
commands.push_back(CommandPointer(new Command2F((Command2F::GLFunction)glPolygonOffset,
state.getDepthBiasSlopeScale(),
state.getDepthBias())));
}
}*/
}
void generateFrontClockwise(GLBackend::GLState::Commands& commands, bool frontClockwise) {
static GLenum GL_FRONT_FACES[] = { GL_CCW, GL_CW };
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glFrontFace, GL_FRONT_FACES[frontClockwise])));
commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateFrontClockwise, int32(frontClockwise))));
}
#define ADD_ENABLE_DISABLE_COMMAND( NAME ) if (enable) {\
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glEnable, NAME)));\
} else {\
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDisable, NAME)));\
}
void generateDepthClipEnable(GLBackend::GLState::Commands& commands, bool enable) {
ADD_ENABLE_DISABLE_COMMAND(GL_DEPTH_CLAMP);
commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateDepthClipEnable, int32(enable))));
}
void generateScissorEnable(GLBackend::GLState::Commands& commands, bool enable) {
ADD_ENABLE_DISABLE_COMMAND(GL_SCISSOR_TEST);
commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateScissorEnable, int32(enable))));
}
void generateMultisampleEnable(GLBackend::GLState::Commands& commands, bool enable) {
ADD_ENABLE_DISABLE_COMMAND(GL_MULTISAMPLE);
commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateMultisampleEnable, int32(enable))));
}
void generateAntialiasedLineEnable(GLBackend::GLState::Commands& commands, bool enable) {
ADD_ENABLE_DISABLE_COMMAND(GL_POINT_SMOOTH);
ADD_ENABLE_DISABLE_COMMAND(GL_LINE_SMOOTH);
commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateAntialiasedLineEnable, int32(enable))));
}
void generateDepthTest(GLBackend::GLState::Commands& commands, State::DepthTest& test) {
if (!test._enabled) {
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDisable, GLenum(GL_DEPTH_TEST))));
} else {
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glEnable, GLenum(GL_DEPTH_TEST))));
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDepthMask, test._writeMask)));
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDepthFunc, GL_COMPARISON_FUNCTIONS[test._function])));
}
commands.push_back(CommandPointer(new Command1DT(&GLBackend::do_setStateDepthTest, int32(test.getRaw()))));
}
void generateStencilEnable(GLBackend::GLState::Commands& commands, bool enable) {
ADD_ENABLE_DISABLE_COMMAND(GL_STENCIL_TEST);
commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateStencilEnable, int32(enable))));
}
void generateStencilWriteMask(GLBackend::GLState::Commands& commands, uint32 mask) {
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glStencilMask, mask)));
// commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glStencilMask, mask)));
}
void generateStencilState(GLBackend::GLState::Commands& commands, const State& state) {
@ -146,11 +123,11 @@ void generateStencilState(GLBackend::GLState::Commands& commands, const State& s
}
void generateAlphaToCoverageEnable(GLBackend::GLState::Commands& commands, bool enable) {
ADD_ENABLE_DISABLE_COMMAND(GL_SAMPLE_ALPHA_TO_COVERAGE);
commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateAlphaToCoverageEnable, int32(enable))));
}
void generateBlendEnable(GLBackend::GLState::Commands& commands, bool enable) {
ADD_ENABLE_DISABLE_COMMAND(GL_BLEND);
commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateBlendEnable, int32(enable))));
}
void generateBlendFunction(GLBackend::GLState::Commands& commands, const State& state) {
@ -209,9 +186,7 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) {
// If GPU object already created then good
if (object) {
if (object->_stamp == state.getStamp()) {
return object;
}
return object;
}
// Else allocate and create the GLState
@ -269,7 +244,6 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) {
generateAntialiasedLineEnable(object->_commands, bool(field.second._integer));
break;
}
case State::DEPTH_TEST: {
generateDepthTest(object->_commands, State::DepthTest(field.second._integer));
break;
@ -337,5 +311,105 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) {
generateBlendFactor(object->_commands, state.getBlendFactor());
}
return nullptr;
return object;
}
void GLBackend::do_setStateFillMode(int32 mode) {
static GLenum GL_FILL_MODES[] = { GL_POINT, GL_LINE, GL_FILL };
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL_MODES[mode]);
CHECK_GL_ERROR();
}
void GLBackend::do_setStateCullMode(int32 mode) {
static GLenum GL_CULL_MODES[] = { GL_FRONT_AND_BACK, GL_FRONT, GL_BACK };
if (mode == State::CULL_NONE) {
glDisable(GL_CULL_FACE);
glCullFace(GL_FRONT_AND_BACK);
} else {
glEnable(GL_CULL_FACE);
glCullFace(GL_CULL_MODES[mode]);
}
}
void GLBackend::do_setStateFrontClockwise(int32 isFrontClockwise) {
static GLenum GL_FRONT_FACES[] = { GL_CCW, GL_CW };
glFrontFace(GL_FRONT_FACES[isFrontClockwise]);
}
void GLBackend::do_setStateDepthClipEnable(int32 enable) {
if (enable) {
glEnable(GL_DEPTH_CLAMP);
} else {
glDisable(GL_DEPTH_CLAMP);
}
CHECK_GL_ERROR();
}
void GLBackend::do_setStateScissorEnable(int32 enable) {
if (enable) {
glEnable(GL_SCISSOR_TEST);
} else {
glDisable(GL_SCISSOR_TEST);
}
CHECK_GL_ERROR();
}
void GLBackend::do_setStateMultisampleEnable(int32 enable) {
if (enable) {
glEnable(GL_MULTISAMPLE);
} else {
glDisable(GL_MULTISAMPLE);
}
CHECK_GL_ERROR();
}
void GLBackend::do_setStateAntialiasedLineEnable(int32 enable) {
if (enable) {
glEnable(GL_POINT_SMOOTH);
glEnable(GL_LINE_SMOOTH);
} else {
glDisable(GL_POINT_SMOOTH);
glDisable(GL_LINE_SMOOTH);
}
CHECK_GL_ERROR();
}
void GLBackend::do_setStateDepthTest(State::DepthTest test) {
if (test._enabled) {
glEnable(GL_DEPTH_TEST);
glDepthMask(test._writeMask);
glDepthFunc(GL_COMPARISON_FUNCTIONS[test._function]);
} else {
glDisable(GL_DEPTH_TEST);
}
CHECK_GL_ERROR();
}
void GLBackend::do_setStateStencilEnable(int32 enable) {
if (enable) {
glEnable(GL_STENCIL_TEST);
} else {
glDisable(GL_STENCIL_TEST);
}
CHECK_GL_ERROR();
}
void GLBackend::do_setStateAlphaToCoverageEnable(int32 enable) {
if (enable) {
glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
} else {
glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
}
CHECK_GL_ERROR();
}
void GLBackend::do_setStateBlendEnable(int32 enable) {
if (enable) {
glEnable(GL_BLEND);
} else {
glDisable(GL_BLEND);
}
CHECK_GL_ERROR();
}

View file

@ -38,7 +38,7 @@ protected:
Pipeline& operator=(const Pipeline& pipeline); // deep copy of the sysmem texture
// This shouldn't be used by anything else than the Backend class with the proper casting.
mutable GPUObject* _gpuObject = NULL;
mutable GPUObject* _gpuObject = nullptr;
void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; }
GPUObject* getGPUObject() const { return _gpuObject; }
friend class Backend;

View file

@ -20,26 +20,22 @@ State::~State()
}
void State::set(Field field, bool value) {
auto found = _fields[field];
found._integer = value;
_fields[field]._integer = value;
_stamp++;
}
void State::set(Field field, uint32 value) {
auto found = _fields[field];
found._unsigned_integer = value;
_fields[field]._unsigned_integer = value;
_stamp++;
}
void State::set(Field field, int32 value) {
auto found = _fields[field];
found._integer = value;
_fields[field]._integer = value;
_stamp++;
}
void State::set(Field field, float value) {
auto found = _fields[field];
found._float = value;
_fields[field]._float = value;
_stamp++;
}
@ -49,4 +45,4 @@ State::Value State::get(Field field) const {
return (*found).second;
}
return Value();
}
}

View file

@ -149,11 +149,13 @@ public:
class DepthTest {
public:
uint8 _function = LESS;
bool _writeMask = true;
bool _enabled = false;
DepthTest(bool enable, bool writeMask, ComparisonFunction func) :
_function(func), _writeMask(writeMask), _enabled(enable) {}
uint8 _function = ALWAYS;
bool _writeMask = false;
bool _enabled = false;
int32 getRaw() const { return *(reinterpret_cast<const int32*>(this)); }
DepthTest(int32 raw) { *(reinterpret_cast<int32*>(this)) = raw; }
@ -190,7 +192,7 @@ public:
class Value {
public:
union {
uint32 _unsigned_integer;
uint32 _unsigned_integer = 0;
int32 _integer;
float _float;
};
@ -207,17 +209,20 @@ public:
Value get(Field field) const;
void setFillMode(FillMode fill) { set(FILL_MODE, uint32(fill)); }
void setCullMode(CullMode cull) { set(FILL_MODE, uint32(cull)); }
FillMode getFillMode() const { return FillMode(get(FILL_MODE)._integer); }
void setCullMode(CullMode cull) { set(CULL_MODE, uint32(cull)); }
CullMode getCullMode() const { return CullMode(get(CULL_MODE)._integer); }
void setFrontClockwise(bool enable) { set(FRONT_CLOCKWISE, enable); }
void setDepthClipEnable(bool enable) { set(DEPTH_CLIP_ENABLE, enable); }
void setDepthBias(float bias) { set(DEPTH_BIAS, bias); }
void setDepthBiasSlopeScale(float scale) { set(DEPTH_BIAS_SLOPE_SCALE, scale); }
float getDepthBias() const { return get(DEPTH_BIAS)._integer; }
float getDepthBiasSlopeScale() const { return get(DEPTH_BIAS_SLOPE_SCALE)._float; }
void setFrontClockwise(bool enable) { set(FRONT_CLOCKWISE, enable); }
void setDepthClipEnable(bool enable) { set(DEPTH_CLIP_ENABLE, enable); }
void setScissorEnable(bool enable) { set(SCISSOR_ENABLE, enable); }
void setMultisampleEnable(bool enable) { set(MULTISAMPLE_ENABLE, enable); }
void setAntialiasedLineEnable(bool enable) { set(ANTIALISED_LINE_ENABLE, enable); }
@ -278,7 +283,7 @@ protected:
Stamp _stamp;
// This shouldn't be used by anything else than the Backend class with the proper casting.
mutable GPUObject* _gpuObject = NULL;
mutable GPUObject* _gpuObject = nullptr;
void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; }
GPUObject* getGPUObject() const { return _gpuObject; }
friend class Backend;

View file

@ -116,26 +116,19 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey& key,
initLocations(program, *locations);
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
// Backface on shadow
if (key.isShadow()) {
state->setCullMode(gpu::State::CULL_FRONT);
} else {
state->setCullMode(gpu::State::CULL_BACK);
}
if (key.isTranslucent()) {
} else {
state->setBlendEnable(false);
}
/*
GLBATCH(glDisable)(GL_BLEND);
GLBATCH(glEnable)(GL_ALPHA_TEST);
if (mode == SHADOW_RENDER_MODE) {
GLBATCH(glAlphaFunc)(GL_EQUAL, 0.0f);
}
*/
// Z test depends if transparent or not
state->setDepthTest(true, !key.isTranslucent(), gpu::State::LESS_EQUAL);
// Blend on transparent
state->setBlendEnable(key.isTranslucent());
auto it = insert(value_type(key.getRaw(),
RenderPipeline(
@ -285,7 +278,7 @@ void Model::init() {
modelVertex, modelTranslucentPixel);
_renderPipelineLib.addRenderPipeline(
RenderKey(RenderKey::IS_DEPTH_ONLY),
RenderKey(RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW),
modelShadowVertex, modelShadowPixel);
_renderPipelineLib.addRenderPipeline(
@ -320,7 +313,7 @@ void Model::init() {
skinModelNormalMapVertex, modelNormalSpecularMapPixel);
_renderPipelineLib.addRenderPipeline(
RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_DEPTH_ONLY),
RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW),
skinModelShadowVertex, modelShadowPixel);
_renderPipelineLib.addRenderPipeline(
@ -684,7 +677,8 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
GLBATCH(glDisable)(GL_COLOR_MATERIAL);
if (mode == DIFFUSE_RENDER_MODE || mode == NORMAL_RENDER_MODE) {
// taking care of by the state?
/* if (mode == DIFFUSE_RENDER_MODE || mode == NORMAL_RENDER_MODE) {
GLBATCH(glDisable)(GL_CULL_FACE);
} else {
GLBATCH(glEnable)(GL_CULL_FACE);
@ -692,10 +686,11 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
GLBATCH(glCullFace)(GL_FRONT);
}
}
*/
// render opaque meshes with alpha testing
GLBATCH(glDisable)(GL_BLEND);
// GLBATCH(glDisable)(GL_BLEND);
GLBATCH(glEnable)(GL_ALPHA_TEST);
if (mode == SHADOW_RENDER_MODE) {
@ -764,10 +759,10 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args);
GLBATCH(glDisable)(GL_ALPHA_TEST);
GLBATCH(glEnable)(GL_BLEND);
/* GLBATCH(glEnable)(GL_BLEND);
GLBATCH(glDepthMask)(false);
GLBATCH(glDepthFunc)(GL_LEQUAL);
*/
//DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true);
{
GLenum buffers[1];
@ -1740,18 +1735,18 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
GLBATCH(glDisable)(GL_COLOR_MATERIAL);
if (mode == DIFFUSE_RENDER_MODE || mode == NORMAL_RENDER_MODE) {
/* if (mode == DIFFUSE_RENDER_MODE || mode == NORMAL_RENDER_MODE) {
GLBATCH(glDisable)(GL_CULL_FACE);
} else {
GLBATCH(glEnable)(GL_CULL_FACE);
if (mode == SHADOW_RENDER_MODE) {
GLBATCH(glCullFace)(GL_FRONT);
}
}
}*/
// render opaque meshes with alpha testing
GLBATCH(glDisable)(GL_BLEND);
// GLBATCH(glDisable)(GL_BLEND);
GLBATCH(glEnable)(GL_ALPHA_TEST);
if (mode == SHADOW_RENDER_MODE) {
@ -1820,10 +1815,10 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args);
GLBATCH(glDisable)(GL_ALPHA_TEST);
GLBATCH(glEnable)(GL_BLEND);
/* GLBATCH(glEnable)(GL_BLEND);
GLBATCH(glDepthMask)(false);
GLBATCH(glDepthFunc)(GL_LEQUAL);
*/
//DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true);
{
GLenum buffers[1];
@ -2262,9 +2257,11 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f
gpu::ShaderPointer program = (*pipeline).second._pipeline->getProgram();
locations = (*pipeline).second._locations.get();
GLuint glprogram = gpu::GLBackend::getShaderID(program);
GLBATCH(glUseProgram)(glprogram);
//GLuint glprogram = gpu::GLBackend::getShaderID(program);
//GLBATCH(glUseProgram)(glprogram);
// dare!
batch.setPipeline((*pipeline).second._pipeline);
if ((locations->alphaThreshold > -1) && (mode != SHADOW_RENDER_MODE)) {
GLBATCH(glUniform1f)(locations->alphaThreshold, alphaThreshold);

View file

@ -373,6 +373,9 @@ private:
QMap<QString, int> _unsortedMeshesOpaqueLightmapTangents;
QMap<QString, int> _unsortedMeshesOpaqueLightmapTangentsSpecular;
QMap<QString, int> _unsortedMeshesOpaqueLightmapSpecular;
typedef std::unordered_map<int, QVector<int>> MeshListMap;
MeshListMap _sortedMeshes;
QVector<int> _meshesTranslucent;
QVector<int> _meshesTranslucentTangents;
@ -486,7 +489,7 @@ private:
RenderKey(RenderMode mode,
bool translucent, float alphaThreshold, bool hasLightmap,
bool hasTangents, bool hasSpecular, bool isSkinned) :
RenderKey( ((translucent && (alphaThreshold == 0.0f)) ? IS_TRANSLUCENT : 0)
RenderKey( ((translucent && (alphaThreshold == 0.0f) && (mode != SHADOW_RENDER_MODE)) ? IS_TRANSLUCENT : 0)
| (hasLightmap && (mode != SHADOW_RENDER_MODE) ? HAS_LIGHTMAP : 0) // Lightmap, tangents and specular don't matter for depthOnly
| (hasTangents && (mode != SHADOW_RENDER_MODE) ? HAS_TANGENTS : 0)
| (hasSpecular && (mode != SHADOW_RENDER_MODE) ? HAS_SPECULAR : 0)