void CNumbersAttribute::setColor(video::SColor color)
		{
			reset();
			if (IsFloat)
			{
				if (Count > 0)
					ValueF[0] = (f32) color.getRed() / 255.0f;
				if (Count > 1)
					ValueF[1] = (f32) color.getGreen() / 255.0f;
				if (Count > 2)
					ValueF[2] = (f32) color.getBlue() / 255.0f;
				if (Count > 3)
					ValueF[3] = (f32) color.getAlpha() / 255.0f;
			}
			else
			{
				if (Count > 0)
					ValueI[0] = color.getRed();
				if (Count > 1)
					ValueI[1] = color.getGreen();
				if (Count > 2)
					ValueI[2] = color.getBlue();
				if (Count > 3)
					ValueI[3] = color.getAlpha();
			}
		}
Beispiel #2
0
void drawTransparentFogObject(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix)
{
    GLenum ptype = mesh.PrimitiveType;
    GLenum itype = mesh.IndexType;
    size_t count = mesh.IndexCount;

    const Track * const track = World::getWorld()->getTrack();

    // This function is only called once per frame - thus no need for setters.
    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();

    core::vector3df col(tmpcol.getRed() / 255.0f,
        tmpcol.getGreen() / 255.0f,
        tmpcol.getBlue() / 255.0f);

    setTexture(0, mesh.textures[0], GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);

    glUseProgram(MeshShader::TransparentFogShader::Program);
    MeshShader::TransparentFogShader::setUniforms(ModelViewProjectionMatrix, TextureMatrix, irr_driver->getInvProjMatrix(), fogmax, startH, endH, start, end, col, Camera::getCamera(0)->getCameraSceneNode()->getAbsolutePosition(), 0);

    glBindVertexArray(mesh.vao_first_pass);
    glDrawElements(ptype, count, itype, 0);
}
		//! Default constructor for color list
		CNumbersAttribute::CNumbersAttribute(const c8* name,
				video::SColor value) :
				ValueI(), ValueF(), Count(4), IsFloat(false)
		{
			Name = name;
			ValueI.pushBack(value.getRed());
			ValueI.pushBack(value.getGreen());
			ValueI.pushBack(value.getBlue());
			ValueI.pushBack(value.getAlpha());
		}
Beispiel #4
0
void COBJMeshWriter::getColorAsStringLine(const video::SColor& color, const c8* const prefix, core::stringc& s) const
{
	s = prefix;
	s += " ";
	s += core::stringc(color.getRed()/255.f);
	s += " ";
	s += core::stringc(color.getGreen()/255.f);
	s += " ";
	s += core::stringc(color.getBlue()/255.f);
	s += "\n";
}
Beispiel #5
0
void push_ARGB8(lua_State *L, video::SColor color)
{
	lua_newtable(L);
	lua_pushnumber(L, color.getAlpha());
	lua_setfield(L, -2, "a");
	lua_pushnumber(L, color.getRed());
	lua_setfield(L, -2, "r");
	lua_pushnumber(L, color.getGreen());
	lua_setfield(L, -2, "g");
	lua_pushnumber(L, color.getBlue());
	lua_setfield(L, -2, "b");
}
Beispiel #6
0
// Fill the editfields with the value for the given color
void CColorControl::setEditsFromColor(video::SColor col)
{
	DirtyFlag = true;
	if ( EditAlpha )
		EditAlpha->setText( core::stringw(col.getAlpha()).c_str() );
	if ( EditRed )
		EditRed->setText( core::stringw(col.getRed()).c_str() );
	if ( EditGreen )
		EditGreen->setText( core::stringw(col.getGreen()).c_str() );
	if ( EditBlue )
		EditBlue->setText( core::stringw(col.getBlue()).c_str() );
	if ( ColorStatic )
		ColorStatic->setBackgroundColor(col);
}
void IrrDriver::renderLightsScatter(unsigned pointlightcount)
{
    getFBO(FBO_HALF1).Bind();
    glClearColor(0., 0., 0., 0.);
    glClear(GL_COLOR_BUFFER_BIT);

    const Track * const track = World::getWorld()->getTrack();

    // This function is only called once per frame - thus no need for setters.
    float start = track->getFogStart() + .001;
    const video::SColor tmpcol = track->getFogColor();

    core::vector3df col(tmpcol.getRed() / 255.0f,
        tmpcol.getGreen() / 255.0f,
        tmpcol.getBlue() / 255.0f);

    glDisable(GL_DEPTH_TEST);
    glDepthMask(GL_FALSE);
    glEnable(GL_BLEND);
    glBlendEquation(GL_FUNC_ADD);
    glBlendFunc(GL_ONE, GL_ONE);

    FullScreenShader::FogShader::getInstance()->SetTextureUnits(irr_driver->getDepthStencilTexture());
    DrawFullScreenEffect<FullScreenShader::FogShader>(1.f / (40.f * start), col);

    glEnable(GL_DEPTH_TEST);
    core::vector3df col2(1., 1., 1.);

    glUseProgram(LightShader::PointLightScatterShader::getInstance()->Program);
    glBindVertexArray(LightShader::PointLightScatterShader::getInstance()->vao);

    LightShader::PointLightScatterShader::getInstance()->SetTextureUnits(irr_driver->getDepthStencilTexture());
    LightShader::PointLightScatterShader::getInstance()->setUniforms(1.f / (40.f * start), col2);

    glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, MIN2(pointlightcount, MAXLIGHT));

    glDisable(GL_BLEND);
    m_post_processing->renderGaussian6Blur(getFBO(FBO_HALF1), getFBO(FBO_HALF2), 5., 5.);
    glEnable(GL_BLEND);

    glDisable(GL_DEPTH_TEST);
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    getFBO(FBO_COLORS).Bind();
    m_post_processing->renderPassThrough(getRenderTargetTexture(RTT_HALF1));
}
Beispiel #8
0
/** Compute spherical harmonics coefficients from ambient light */
void SphericalHarmonics::setAmbientLight(const video::SColor &ambient)
{
    //do not recompute SH coefficients if we already use the same ambient light
    if((m_spherical_harmonics_textures.size() != 6) && (ambient == m_ambient))
        return;

    m_spherical_harmonics_textures.clear();
    m_ambient = ambient;

    unsigned char *sh_rgba[6];
    unsigned sh_w = 16;
    unsigned sh_h = 16;

    for (unsigned i = 0; i < 6; i++)
    {
        sh_rgba[i] = new unsigned char[sh_w * sh_h * 4];

        for (unsigned j = 0; j < sh_w * sh_h * 4; j += 4)
        {
            sh_rgba[i][j] = ambient.getBlue();
            sh_rgba[i][j + 1] = ambient.getGreen();
            sh_rgba[i][j + 2] = ambient.getRed();
            sh_rgba[i][j + 3] = 255;
        }
    }

    Color *float_tex_cube[6];
    convertToFloatTexture(sh_rgba, sh_w, sh_h, float_tex_cube);
    generateSphericalHarmonics(float_tex_cube, sh_w);

    for (unsigned i = 0; i < 6; i++)
    {
        delete[] sh_rgba[i];
        delete[] float_tex_cube[i];
    }

    // Diffuse env map is x 0.25, compensate
    for (unsigned i = 0; i < 9; i++)
    {
        m_blue_SH_coeff[i] *= 4;
        m_green_SH_coeff[i] *= 4;
        m_red_SH_coeff[i] *= 4;
    }
} //setAmbientLight
Beispiel #9
0
void WieldMeshSceneNode::setColor(video::SColor c)
{
	assert(!m_lighting);
	scene::IMesh *mesh = m_meshnode->getMesh();
	if (!mesh)
		return;

	u8 red = c.getRed();
	u8 green = c.getGreen();
	u8 blue = c.getBlue();
	u32 mc = mesh->getMeshBufferCount();
	for (u32 j = 0; j < mc; j++) {
		video::SColor bc(m_base_color);
		if ((m_colors.size() > j) && (m_colors[j].override_base))
			bc = m_colors[j].color;
		video::SColor buffercolor(255,
			bc.getRed() * red / 255,
			bc.getGreen() * green / 255,
			bc.getBlue() * blue / 255);
		scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
		colorizeMeshBuffer(buf, &buffercolor);
	}
}
Beispiel #10
0
static void applyFacesShading(video::SColor& color, float factor)
{
	color.setRed(core::clamp(core::round32(color.getRed()*factor), 0, 255));
	color.setGreen(core::clamp(core::round32(color.getGreen()*factor), 0, 255));
	color.setBlue(core::clamp(core::round32(color.getBlue()*factor), 0, 255));
}
void STKMeshSceneNode::render()
{
    irr::video::IVideoDriver* driver = irr_driver->getVideoDriver();

    if (!Mesh || !driver)
        return;

    ++PassCount;

    updateNoGL();
    updateGL();

    bool isTransparent;

    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;
        video::IMaterialRenderer* rnd = driver->getMaterialRenderer(type);

        isTransparent = rnd->isTransparent();
        break;
    }

    if ((irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS) && immediate_draw && !isTransparent)
    {
        core::matrix4 invmodel;
        AbsoluteTransformation.getInverse(invmodel);

        glDisable(GL_CULL_FACE);
        if (update_each_frame)
            updatevbo();
        glUseProgram(MeshShader::ObjectPass1Shader::getInstance()->Program);
        // Only untextured
        for (unsigned i = 0; i < GLmeshes.size(); i++)
        {
            irr_driver->IncreaseObjectCount();
            GLMesh &mesh = GLmeshes[i];
            GLenum ptype = mesh.PrimitiveType;
            GLenum itype = mesh.IndexType;
            size_t count = mesh.IndexCount;

            compressTexture(mesh.textures[0], true);
            if (UserConfigParams::m_azdo)
            {
                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]));
            }
            else
                MeshShader::ObjectPass1Shader::getInstance()->SetTextureUnits(std::vector < GLuint > { getTextureGLuint(mesh.textures[0]) });
            MeshShader::ObjectPass1Shader::getInstance()->setUniforms(AbsoluteTransformation, invmodel);
            assert(mesh.vao);
            glBindVertexArray(mesh.vao);
            glDrawElements(ptype, count, itype, 0);
            glBindVertexArray(0);
        }
        glEnable(GL_CULL_FACE);
        return;
    }

    if (irr_driver->getPhase() == SOLID_LIT_PASS  && immediate_draw && !isTransparent)
    {
        core::matrix4 invmodel;
        AbsoluteTransformation.getInverse(invmodel);

        glDisable(GL_CULL_FACE);
        if (update_each_frame && !UserConfigParams::m_dynamic_lights)
            updatevbo();
        glUseProgram(MeshShader::ObjectPass2Shader::getInstance()->Program);
        // Only untextured
        for (unsigned i = 0; i < GLmeshes.size(); i++)
        {
            irr_driver->IncreaseObjectCount();
            GLMesh &mesh = GLmeshes[i];
            GLenum ptype = mesh.PrimitiveType;
            GLenum itype = mesh.IndexType;
            size_t count = mesh.IndexCount;

            if (UserConfigParams::m_azdo)
            {
                GLuint64 DiffuseHandle = glGetTextureSamplerHandleARB(irr_driver->getRenderTargetTexture(RTT_DIFFUSE), MeshShader::ObjectPass2Shader::getInstance()->SamplersId[0]);
                if (!glIsTextureHandleResidentARB(DiffuseHandle))
                    glMakeTextureHandleResidentARB(DiffuseHandle);

                GLuint64 SpecularHandle = glGetTextureSamplerHandleARB(irr_driver->getRenderTargetTexture(RTT_SPECULAR), MeshShader::ObjectPass2Shader::getInstance()->SamplersId[1]);
                if (!glIsTextureHandleResidentARB(SpecularHandle))
                    glMakeTextureHandleResidentARB(SpecularHandle);

                GLuint64 SSAOHandle = glGetTextureSamplerHandleARB(irr_driver->getRenderTargetTexture(RTT_HALF1_R), MeshShader::ObjectPass2Shader::getInstance()->SamplersId[2]);
                if (!glIsTextureHandleResidentARB(SSAOHandle))
                    glMakeTextureHandleResidentARB(SSAOHandle);

                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::ObjectPass2Shader::getInstance()->SetTextureHandles(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, mesh.TextureHandles[0]));
            }
            else
                MeshShader::ObjectPass2Shader::getInstance()->SetTextureUnits(createVector<GLuint>(
                irr_driver->getRenderTargetTexture(RTT_DIFFUSE),
                irr_driver->getRenderTargetTexture(RTT_SPECULAR),
                irr_driver->getRenderTargetTexture(RTT_HALF1_R),
                getTextureGLuint(mesh.textures[0])));
            MeshShader::ObjectPass2Shader::getInstance()->setUniforms(AbsoluteTransformation, mesh.TextureMatrix);
            assert(mesh.vao);
            glBindVertexArray(mesh.vao);
            glDrawElements(ptype, count, itype, 0);
            glBindVertexArray(0);
        }
        glEnable(GL_CULL_FACE);
        return;
    }

    if (irr_driver->getPhase() == GLOW_PASS)
    {
        glUseProgram(MeshShader::ColorizeShader::getInstance()->Program);
        for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i)
        {
            scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
            if (!mb)
                continue;
            if (irr_driver->hasARB_base_instance())
                glBindVertexArray(VAOManager::getInstance()->getVAO(video::EVT_STANDARD));
            else
                glBindVertexArray(GLmeshes[i].vao);
            drawGlow(GLmeshes[i]);
        }
    }

    if (irr_driver->getPhase() == TRANSPARENT_PASS && isTransparent)
    {
        ModelViewProjectionMatrix = computeMVP(AbsoluteTransformation);

        if (immediate_draw)
        {
            if (update_each_frame)
                updatevbo();
            glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

            if (World::getWorld() && World::getWorld()->isFogEnabled())
            {
                glUseProgram(MeshShader::TransparentFogShader::getInstance()->Program);
                for (unsigned i = 0; i < GLmeshes.size(); i++)
                {
                    GLMesh &mesh = GLmeshes[i];
                    irr_driver->IncreaseObjectCount();
                    GLenum ptype = mesh.PrimitiveType;
                    GLenum itype = mesh.IndexType;
                    size_t count = mesh.IndexCount;

                    const Track * const track = World::getWorld()->getTrack();

                    // This function is only called once per frame - thus no need for setters.
                    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);

                    compressTexture(mesh.textures[0], true);
                    if (UserConfigParams::m_azdo)
                    {
                        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]));
                    }
                    else
                        MeshShader::TransparentFogShader::getInstance()->SetTextureUnits(std::vector<GLuint>{ getTextureGLuint(mesh.textures[0]) });
                    MeshShader::TransparentFogShader::getInstance()->setUniforms(AbsoluteTransformation, mesh.TextureMatrix, fogmax, startH, endH, start, end, col);

                    assert(mesh.vao);
                    glBindVertexArray(mesh.vao);
                    glDrawElements(ptype, count, itype, 0);
                    glBindVertexArray(0);
                }
            }
            else
            {
                glUseProgram(MeshShader::TransparentShader::getInstance()->Program);
                for (unsigned i = 0; i < GLmeshes.size(); i++)
                {
                    irr_driver->IncreaseObjectCount();
                    GLMesh &mesh = GLmeshes[i];
                    GLenum ptype = mesh.PrimitiveType;
                    GLenum itype = mesh.IndexType;
                    size_t count = mesh.IndexCount;

                    compressTexture(mesh.textures[0], true);
                    if (UserConfigParams::m_azdo)
                    {
                        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]));
                    }
                    else
                        MeshShader::TransparentShader::getInstance()->SetTextureUnits(std::vector<GLuint>{ getTextureGLuint(mesh.textures[0]) });

                    MeshShader::TransparentShader::getInstance()->setUniforms(AbsoluteTransformation, mesh.TextureMatrix);
                    assert(mesh.vao);
                    glBindVertexArray(mesh.vao);
                    glDrawElements(ptype, count, itype, 0);
                    glBindVertexArray(0);
                }
            }
            return;
        }
    }
}
Beispiel #12
0
aiColor3D IrrToAssimpColor(video::SColor color)
{
    return aiColor3D(color.getRed() / 255.f, color.getGreen() / 255.f, color.getBlue() / 255.f);
}
Beispiel #13
0
// ----------------------------------------------------------------------------
void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
                                std::vector<scene::ISceneNode *> *ImmediateDraw,
                                const scene::ICameraSceneNode *cam,
                                ShadowMatrices& shadow_matrices)
{
    STKMeshCommon* node = dynamic_cast<STKMeshCommon*>(Node);
    if (!node)
        return;
    node->updateNoGL();
    m_deferred_update.push_back(node);

    if (node->isImmediateDraw())
    {
        ImmediateDraw->push_back(Node);
        return;
    }

    bool culled_for_cams[6] = { true, true, true, true, true, true };
    culled_for_cams[0] = isCulledPrecise(cam, Node,
        irr_driver->getBoundingBoxesViz());

    if (UserConfigParams::m_gi && !shadow_matrices.isRSMMapAvail())
    {
        culled_for_cams[1] = isCulledPrecise(shadow_matrices.getSunCam(), Node);
    }

    if (CVS->isShadowEnabled())
    {
        for (unsigned i = 0; i < 4; i++)
        {
            culled_for_cams[i + 2] =
                isCulledPrecise(shadow_matrices.getShadowCamNodes()[i], Node);
        }
    }

    // Transparent
    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 (GLMesh *mesh : node->TransparentMesh[TM_DEFAULT])
            pushVector(ListBlendTransparentFog::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->texture_trans,
            fogmax, startH, endH, start, end, col);
        for (GLMesh *mesh : node->TransparentMesh[TM_ADDITIVE])
            pushVector(ListAdditiveTransparentFog::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->texture_trans,
            fogmax, startH, endH, start, end, col);
    }
    else
    {
        for (GLMesh *mesh : node->TransparentMesh[TM_DEFAULT])
            pushVector(ListBlendTransparent::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->texture_trans, 1.0f);
        for (GLMesh *mesh : node->TransparentMesh[TM_ADDITIVE])
            pushVector(ListAdditiveTransparent::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->texture_trans, 1.0f);
    }

    // Use sun color to determine custom alpha for ghost karts
    float custom_alpha = 1.0f;
    if (World::getWorld())
    {
        const video::SColor& c = World::getWorld()->getTrack()->getSunColor();
        float y = 0.2126f * c.getRed() + 0.7152f * c.getGreen() + 0.0722f * c.getBlue();
        custom_alpha = y > 128.0f ? 0.5f : 0.35f;
    }

    for (GLMesh *mesh : node->TransparentMesh[TM_TRANSLUCENT_STD])
        pushVector(ListTranslucentStandard::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->texture_trans, custom_alpha);
    for (GLMesh *mesh : node->TransparentMesh[TM_TRANSLUCENT_TAN])
        pushVector(ListTranslucentTangents::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->texture_trans, custom_alpha);
    for (GLMesh *mesh : node->TransparentMesh[TM_TRANSLUCENT_2TC])
        pushVector(ListTranslucent2TCoords::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->texture_trans, custom_alpha);
    for (GLMesh *mesh : node->TransparentMesh[TM_DISPLACEMENT])
        pushVector(ListDisplacement::getInstance(), mesh, Node->getAbsoluteTransformation());

    if (!culled_for_cams[0])
    {
        for (unsigned Mat = 0; Mat < Material::SHADERTYPE_COUNT; ++Mat)
        {
            if (CVS->supportsIndirectInstancingRendering())
            {
                for (GLMesh *mesh : node->MeshSolidMaterial[Mat])
                {
                    if (node->glow())
                    {
                        m_glow_pass_mesh[mesh->mb].m_mesh = mesh;
                        m_glow_pass_mesh[mesh->mb].m_instance_settings
                            .emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f));
                    }
                    if (Mat == Material::SHADERTYPE_SPLATTING)
                    {
                        // Notice: splatting will be drawn using non-instanced shader only
                        // It's only used one place (in overworld) and may be removed eventually
                        core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
                        ModelMatrix.getInverse(InvModelMatrix);
                        ListMatSplatting::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix);
                    }
                    else
                    {
                        // Only take render info into account if the node is not static (animated)
                        // So they can have different animation
                        std::pair<scene::IMeshBuffer*, RenderInfo*> mesh_render_info(mesh->mb,
                            dynamic_cast<STKMeshSceneNode*>(Node) == NULL ? mesh->m_render_info : NULL);
                        m_solid_pass_mesh[Mat][mesh_render_info].m_mesh = mesh;
                        m_solid_pass_mesh[Mat][mesh_render_info].m_instance_settings.emplace_back(Node, mesh->texture_trans,
                            (mesh->m_render_info && mesh->m_material ?
                            core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) :
                            core::vector2df(0.0f, 0.0f)));
                    }
                }
            }
            else
            {
                core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
                ModelMatrix.getInverse(InvModelMatrix);

                for (GLMesh *mesh : node->MeshSolidMaterial[Mat])
                {
                    switch (Mat)
                    {
                    case Material::SHADERTYPE_SOLID:
                        ListMatDefault::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans,
                            (mesh->m_render_info && mesh->m_material ?
                            core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) :
                            core::vector2df(0.0f, 0.0f)));
                        break;
                    case Material::SHADERTYPE_ALPHA_TEST:
                        ListMatAlphaRef::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans,
                            (mesh->m_render_info && mesh->m_material ?
                            core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) :
                            core::vector2df(0.0f, 0.0f)));
                        break;
                    case Material::SHADERTYPE_NORMAL_MAP:
                        ListMatNormalMap::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans,
                            (mesh->m_render_info && mesh->m_material ?
                            core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) :
                            core::vector2df(0.0f, 0.0f)));
                        break;
                    case Material::SHADERTYPE_DETAIL_MAP:
                        ListMatDetails::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans);
                        break;
                    case Material::SHADERTYPE_SOLID_UNLIT:
                        ListMatUnlit::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans);
                        break;
                    case Material::SHADERTYPE_SPHERE_MAP:
                        ListMatSphereMap::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans);
                        break;
                    case Material::SHADERTYPE_SPLATTING:
                        ListMatSplatting::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix);
                        break;
                    case Material::SHADERTYPE_VEGETATION:
                        ListMatGrass::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, m_wind_dir,
                            (mesh->m_render_info && mesh->m_material ?
                            core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) :
                            core::vector2df(0.0f, 0.0f)));
                        break;
                    case Material::SHADERTYPE_ALPHA_BLEND:
                        break;
                    case Material::SHADERTYPE_ADDITIVE:
                        break;
                    case Material::SHADERTYPE_WATER:
                        break;
                    default:
                        Log::warn("DrawCalls", "Unknown material type: %d", Mat);
                    }
                }
            }
        }
    }
    if (!CVS->isShadowEnabled())
        return;
    for (unsigned cascade = 0; cascade < 4; ++cascade)
    {
        if (culled_for_cams[cascade + 2])
            continue;
        for (unsigned Mat = 0; Mat < Material::SHADERTYPE_COUNT; ++Mat)
        {
            if (CVS->supportsIndirectInstancingRendering())
            {
                for (GLMesh *mesh : node->MeshSolidMaterial[Mat])
                {
                    m_shadow_pass_mesh[cascade * Material::SHADERTYPE_COUNT + Mat][mesh->mb].m_mesh = mesh;
                    m_shadow_pass_mesh[cascade * Material::SHADERTYPE_COUNT + Mat][mesh->mb].m_instance_settings
                        .emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f));
                }
            }
            else
            {
                core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
                ModelMatrix.getInverse(InvModelMatrix);

                for (GLMesh *mesh : node->MeshSolidMaterial[Mat])
                {
                    switch (Mat)
                    {
                    case Material::SHADERTYPE_SOLID:
                        ListMatDefault::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, core::vector2df(0.0f, 0.0f));
                        break;
                    case Material::SHADERTYPE_ALPHA_TEST:
                        ListMatAlphaRef::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, core::vector2df(0.0f, 0.0f));
                        break;
                    case Material::SHADERTYPE_NORMAL_MAP:
                        ListMatNormalMap::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, core::vector2df(0.0f, 0.0f));
                        break;
                    case Material::SHADERTYPE_DETAIL_MAP:
                        ListMatDetails::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans);
                        break;
                    case Material::SHADERTYPE_SOLID_UNLIT:
                        ListMatUnlit::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans);
                        break;
                    case Material::SHADERTYPE_SPHERE_MAP:
                        ListMatSphereMap::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans);
                        break;
                    case Material::SHADERTYPE_SPLATTING:
                        ListMatSplatting::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix);
                        break;
                    case Material::SHADERTYPE_VEGETATION:
                        ListMatGrass::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, m_wind_dir,
                            (mesh->m_render_info && mesh->m_material ?
                            core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) :
                            core::vector2df(0.0f, 0.0f)));
                    case Material::SHADERTYPE_ALPHA_BLEND:
                        break;
                    case Material::SHADERTYPE_ADDITIVE:
                        break;
                    case Material::SHADERTYPE_WATER:
                        break;
                    default:
                        Log::warn("DrawCalls", "Unknown material type: %d", Mat);
                    }
                }
            }
        }
    }
    if (!UserConfigParams::m_gi || shadow_matrices.isRSMMapAvail())
        return;
    if (!culled_for_cams[1])
    {
        for (unsigned Mat = 0; Mat < Material::SHADERTYPE_COUNT; ++Mat)
        {
            if (CVS->supportsIndirectInstancingRendering())
            {
                for (GLMesh *mesh : node->MeshSolidMaterial[Mat])
                {
                    if (Mat == Material::SHADERTYPE_SPLATTING)
                    {
                        core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
                        ModelMatrix.getInverse(InvModelMatrix);
                        ListMatSplatting::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix);
                    }
                    else
                    {
                        m_reflective_shadow_map_mesh[Mat][mesh->mb].m_mesh = mesh;
                        m_reflective_shadow_map_mesh[Mat][mesh->mb].m_instance_settings
                            .emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f));
                    }
                }
            }
            else
            {
                core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
                ModelMatrix.getInverse(InvModelMatrix);

                for (GLMesh *mesh : node->MeshSolidMaterial[Mat])
                {
                    switch (Mat)
                    {
                    case Material::SHADERTYPE_SOLID:
                        ListMatDefault::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, core::vector2df(0.0f, 0.0f));
                        break;
                    case Material::SHADERTYPE_ALPHA_TEST:
                        ListMatAlphaRef::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, core::vector2df(0.0f, 0.0f));
                        break;
                    case Material::SHADERTYPE_NORMAL_MAP:
                        ListMatNormalMap::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, core::vector2df(0.0f, 0.0f));
                        break;
                    case Material::SHADERTYPE_DETAIL_MAP:
                        ListMatDetails::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans);
                        break;
                    case Material::SHADERTYPE_SOLID_UNLIT:
                        ListMatUnlit::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans);
                        break;
                    case Material::SHADERTYPE_SPHERE_MAP:
                        ListMatSphereMap::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans);
                        break;
                    case Material::SHADERTYPE_SPLATTING:
                        ListMatSplatting::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix);
                        break;
                    case Material::SHADERTYPE_VEGETATION:
                        ListMatGrass::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, m_wind_dir,
                            (mesh->m_render_info && mesh->m_material ?
                            core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) :
                            core::vector2df(0.0f, 0.0f)));
                        break;
                    case Material::SHADERTYPE_ALPHA_BLEND:
                        break;
                    case Material::SHADERTYPE_ADDITIVE:
                        break;
                    case Material::SHADERTYPE_WATER:
                        break;
                    default:
                        Log::warn("DrawCalls", "Unknown material type: %d", Mat);
                    }
                }
            }
        }
    }
}
bool drawLine(

	video::IImage* dst,

	s32 x0,

	s32 y0,

	s32 x1,

	s32 y1,

	const video::SColor& color_a,

	const video::SColor& color_b,

	bool blend )

{
	if (!dst) return false;

	const core::dimension2du img_size = dst->getDimension();

	if ((img_size.Width == 0) || (img_size.Height == 0))
		return false;

	const s32 dx = core::abs_<s32>( x1 - x0 );
	const s32 dy = core::abs_<s32>( y1 - y0 );

	if ((dx==0) && (dy==0)) return false;

	s32 sx = 1; // sign
	s32 sy = 1; // sign

	if (x0 > x1) sx = -1;
	if (y0 > y1) sy = -1;

	s32 err = dx-dy;
	s32 e2 = 0;
	s32 x = x0;
	s32 y = y0;

	s32 numpixels = 0;

	// count pixels
	while (1)
	{
		numpixels++;

		if ((x==x1) && (y==y1)) break;

		e2 = err << 1;
		if (e2 > -dy) { err -= dy;	x += sx; }
		if (e2 < dx) { err += dx; y += sy; }
	}

	// reset vars;
	err = dx-dy;
	e2 = 0;
	x = x0;
	y = y0;

	// values for linear color interpolation
	const f32 A1=(f32)color_a.getAlpha();
	const f32 R1=(f32)color_a.getRed();
	const f32 G1=(f32)color_a.getGreen();
	const f32 B1=(f32)color_a.getBlue();
	const f32 dA=(f32)color_b.getAlpha()-A1;
	const f32 dR=(f32)color_b.getRed()-R1;
	const f32 dG=(f32)color_b.getGreen()-G1;
	const f32 dB=(f32)color_b.getBlue()-B1;

	// actual drawing
	f32 f=0.f;
	s32 k=0;
	u32 cR=0, cG=0, cB=0, cA=0;
	while (1)
	{
		f = (f32)k/(f32)numpixels;
		k++;

		cA=A1;
		cR=R1;
		cG=G1;
		cB=B1;

		// maybe faster under the assumption that colors have most likely same alpha value
		if (dA>0) cA = (u32)core::clamp( core::round32(A1+dA*f), 0, 255);
		if (dR>0) cR = (u32)core::clamp( core::round32(R1+dR*f), 0, 255);
		if (dG>0) cG = (u32)core::clamp( core::round32(G1+dG*f), 0, 255);
		if (dB>0) cB = (u32)core::clamp( core::round32(B1+dB*f), 0, 255);

		drawPixel( dst, x, y, video::SColor( cA, cR, cG, cB), blend );

		if (x == x1 && y == y1) break;

		e2 = err << 1;
		if (e2 > -dy)	{	err -= dy;	x += sx; }
		if (e2 < dx)	{	err += dx;	y += sy; }
	}

	return true;
}