Commit ff8e5073 authored by nadro's avatar nadro

- Finally improved active texture handling in OpenGL.

- Optimized rendering with ARB shaders in OpenGL.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@4410 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 7afcfbd1
......@@ -99,9 +99,6 @@ void COpenGLCgMaterialRenderer::OnSetMaterial(const SMaterial& material, const S
if (CallBack)
CallBack->OnSetMaterial(material);
for (u32 i=0; i<MATERIAL_MAX_TEXTURES; ++i)
Driver->setActiveTexture(i, material.getTexture(i));
Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
}
......
......@@ -807,19 +807,19 @@ void COpenGLDriver::createMaterialRenderers()
// add normal map renderers
s32 tmp = 0;
video::IMaterialRenderer* renderer = 0;
renderer = new COpenGLNormalMapRenderer(this, tmp, MaterialRenderers[EMT_SOLID].Renderer);
renderer = new COpenGLNormalMapRenderer(this, tmp, EMT_SOLID);
renderer->drop();
renderer = new COpenGLNormalMapRenderer(this, tmp, MaterialRenderers[EMT_TRANSPARENT_ADD_COLOR].Renderer);
renderer = new COpenGLNormalMapRenderer(this, tmp, EMT_TRANSPARENT_ADD_COLOR);
renderer->drop();
renderer = new COpenGLNormalMapRenderer(this, tmp, MaterialRenderers[EMT_TRANSPARENT_VERTEX_ALPHA].Renderer);
renderer = new COpenGLNormalMapRenderer(this, tmp, EMT_TRANSPARENT_VERTEX_ALPHA);
renderer->drop();
// add parallax map renderers
renderer = new COpenGLParallaxMapRenderer(this, tmp, MaterialRenderers[EMT_SOLID].Renderer);
renderer = new COpenGLParallaxMapRenderer(this, tmp, EMT_SOLID);
renderer->drop();
renderer = new COpenGLParallaxMapRenderer(this, tmp, MaterialRenderers[EMT_TRANSPARENT_ADD_COLOR].Renderer);
renderer = new COpenGLParallaxMapRenderer(this, tmp, EMT_TRANSPARENT_ADD_COLOR);
renderer->drop();
renderer = new COpenGLParallaxMapRenderer(this, tmp, MaterialRenderers[EMT_TRANSPARENT_VERTEX_ALPHA].Renderer);
renderer = new COpenGLParallaxMapRenderer(this, tmp, EMT_TRANSPARENT_VERTEX_ALPHA);
renderer->drop();
// add basic 1 texture blending
......@@ -986,8 +986,7 @@ void COpenGLDriver::setTransform(E_TRANSFORMATION_STATE state, const core::matri
const bool isRTT = Material.getTexture(i) && Material.getTexture(i)->isRenderTarget();
if (MultiTextureExtension)
setGlActiveTexture(GL_TEXTURE0_ARB + i);
setGlActiveTexture(GL_TEXTURE0_ARB + i);
setGlMatrixMode(GL_TEXTURE);
if (!isRTT && mat.isIdentity() )
......@@ -2209,7 +2208,8 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::rect
const video::SColor* const useColor = colors ? colors : temp;
disableTextures(1);
setActiveTexture(0, texture);
if (!setActiveTexture(0, texture))
return;
setRenderStates2DMode(useColor[0].getAlpha()<255 || useColor[1].getAlpha()<255 ||
useColor[2].getAlpha()<255 || useColor[3].getAlpha()<255,
true, useAlphaChannelOfTexture);
......@@ -2461,7 +2461,19 @@ bool COpenGLDriver::disableTextures(u32 fromStage)
{
bool result=true;
for (u32 i=fromStage; i<MaxSupportedTextures; ++i)
{
result &= setActiveTexture(i, 0);
if(DriverStage.getTexture(i) != 0 || !DriverStage.getTextureFixedPipeline(i))
{
setGlActiveTexture(GL_TEXTURE0_ARB + i);
glDisable(GL_TEXTURE_2D);
DriverStage.setTexture(i, 0);
DriverStage.setTextureFixedPipeline(i, true);
}
}
return result;
}
......@@ -2858,20 +2870,31 @@ void COpenGLDriver::setBasicRenderStates(const SMaterial& material, const SMater
if (!CurrentTexture[i])
{
if (MultiTextureExtension)
if(DriverStage.getTexture(i) != 0 || !DriverStage.getTextureFixedPipeline(i))
{
setGlActiveTexture(GL_TEXTURE0_ARB + i);
glDisable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_2D);
DriverStage.setTexture(i, 0);
DriverStage.setTextureFixedPipeline(i, true);
}
continue;
}
else
{
if (MultiTextureExtension)
if(DriverStage.getTexture(i) != CurrentTexture[i] || !DriverStage.getTextureFixedPipeline(i))
{
setGlActiveTexture(GL_TEXTURE0_ARB + i);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tmpTexture->getOpenGLTextureName());
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tmpTexture->getOpenGLTextureName());
DriverStage.setTexture(i, CurrentTexture[i]);
DriverStage.setTextureFixedPipeline(i, true);
}
setTransform ((E_TRANSFORMATION_STATE) (ETS_TEXTURE_0 + i), material.getTextureMatrix(i));
}
}
......@@ -2879,8 +2902,14 @@ void COpenGLDriver::setBasicRenderStates(const SMaterial& material, const SMater
{
if (CurrentTexture[i])
{
setGlActiveTexture(GL_TEXTURE0_ARB + i);
glBindTexture(GL_TEXTURE_2D, tmpTexture->getOpenGLTextureName());
if(DriverStage.getTexture(i) != CurrentTexture[i])
{
setGlActiveTexture(GL_TEXTURE0_ARB + i);
glBindTexture(GL_TEXTURE_2D, tmpTexture->getOpenGLTextureName());
DriverStage.setTexture(i, CurrentTexture[i]);
DriverStage.setTextureFixedPipeline(i, false);
}
}
else
continue;
......@@ -3331,7 +3360,7 @@ void COpenGLDriver::setBasicRenderStates(const SMaterial& material, const SMater
}
// be sure to leave in texture stage 0
if (fixedPipeline && MultiTextureExtension)
if (fixedPipeline)
setGlActiveTexture(GL_TEXTURE0_ARB);
}
......@@ -3348,6 +3377,10 @@ void COpenGLDriver::enableMaterial2D(bool enable)
//! sets the needed renderstates
void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel)
{
bool BindedTexture = false;
setGlActiveTexture(GL_TEXTURE0_ARB);
if (CurrentRenderMode != ERM_2D || Transformation3DChanged)
{
// unset last 3d material
......@@ -3371,14 +3404,14 @@ void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaCh
glTranslatef(0.375f, 0.375f, 0.0f);
// Make sure we set first texture matrix
if (MultiTextureExtension)
setGlActiveTexture(GL_TEXTURE0_ARB);
setGlActiveTexture(GL_TEXTURE0_ARB);
Transformation3DChanged = false;
}
if (!OverrideMaterial2DEnabled)
{
setBasicRenderStates(InitMaterial2D, LastMaterial, true);
BindedTexture = true;
LastMaterial = InitMaterial2D;
}
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
......@@ -3392,6 +3425,7 @@ void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaCh
{
OverrideMaterial2D.Lighting=false;
setBasicRenderStates(OverrideMaterial2D, LastMaterial, false);
BindedTexture = true;
LastMaterial = OverrideMaterial2D;
}
......@@ -3412,6 +3446,20 @@ void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaCh
if (texture)
{
if(!BindedTexture && CurrentTexture[0])
{
if(DriverStage.getTexture(0) != CurrentTexture[0] || !DriverStage.getTextureFixedPipeline(0))
{
setGlActiveTexture(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, static_cast<const COpenGLTexture*>(CurrentTexture[0])->getOpenGLTextureName());
DriverStage.setTexture(0, CurrentTexture[0]);
DriverStage.setTextureFixedPipeline(0, true);
}
}
if (!OverrideMaterial2DEnabled)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
......@@ -4072,7 +4120,7 @@ s32 COpenGLDriver::addShaderMaterial(const c8* vertexShaderProgram,
s32 nr = -1;
COpenGLShaderMaterialRenderer* r = new COpenGLShaderMaterialRenderer(
this, nr, vertexShaderProgram, pixelShaderProgram,
callback, getMaterialRenderer(baseMaterial), userData);
callback, baseMaterial, userData);
r->drop();
return nr;
......@@ -4889,7 +4937,7 @@ void COpenGLDriver::setGlMatrixMode(GLenum mode)
void COpenGLDriver::setGlActiveTexture(GLenum texture)
{
if (CurrentActiveTexture != texture)
if (MultiTextureExtension && CurrentActiveTexture != texture)
{
extGlActiveTexture(texture);
CurrentActiveTexture = texture;
......
......@@ -425,6 +425,8 @@ namespace video
private:
//! clears the zbuffer and color buffer
void clearBuffers(bool backBuffer, bool zBuffer, bool stencilBuffer, SColor color);
......@@ -489,6 +491,7 @@ namespace video
SMaterial Material, LastMaterial;
COpenGLTexture* RenderTargetTexture;
core::array<video::IRenderTarget> MRTargets;
class STextureStageCache
{
const ITexture* CurrentTexture[MATERIAL_MAX_TEXTURES];
......@@ -553,6 +556,57 @@ namespace video
}
};
STextureStageCache CurrentTexture;
class SDriverStageCache
{
public:
SDriverStageCache()
{
for (u32 i=0; i<MATERIAL_MAX_TEXTURES; ++i)
{
CurrentTexture[i] = 0;
CurrentTextureFixedPipeline[i] = true;
}
}
~SDriverStageCache()
{
}
const ITexture* getTexture(u32 stage) const
{
if ((u32)stage < MATERIAL_MAX_TEXTURES)
return CurrentTexture[stage];
else
return 0;
}
void setTexture(u32 stage, const ITexture* tex)
{
if (stage < MATERIAL_MAX_TEXTURES)
CurrentTexture[stage] = tex;
}
bool getTextureFixedPipeline(u32 stage) const
{
if ((u32)stage < MATERIAL_MAX_TEXTURES)
return CurrentTextureFixedPipeline[stage];
else
return true;
}
void setTextureFixedPipeline(u32 stage, bool texFixedPipeline)
{
if (stage < MATERIAL_MAX_TEXTURES)
CurrentTextureFixedPipeline[stage] = texFixedPipeline;
}
private:
const ITexture* CurrentTexture[MATERIAL_MAX_TEXTURES];
bool CurrentTextureFixedPipeline[MATERIAL_MAX_TEXTURES];
};
SDriverStageCache DriverStage;
core::array<ITexture*> DepthTextures;
struct SUserClipPlane
{
......
......@@ -153,7 +153,7 @@ const char OPENGL_NORMAL_MAP_PSH[] =
//! Constructor
COpenGLNormalMapRenderer::COpenGLNormalMapRenderer(video::COpenGLDriver* driver,
s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial)
s32& outMaterialTypeNr, E_MATERIAL_TYPE baseMaterial)
: COpenGLShaderMaterialRenderer(driver, 0, baseMaterial), CompiledShaders(true)
{
......
......@@ -23,7 +23,7 @@ public:
//! Constructor
COpenGLNormalMapRenderer(video::COpenGLDriver* driver,
s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial);
s32& outMaterialTypeNr, E_MATERIAL_TYPE baseMaterial);
//! Destructor
~COpenGLNormalMapRenderer();
......
......@@ -187,7 +187,7 @@ const char OPENGL_PARALLAX_MAP_PSH[] =
//! Constructor
COpenGLParallaxMapRenderer::COpenGLParallaxMapRenderer(video::COpenGLDriver* driver,
s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial)
s32& outMaterialTypeNr, E_MATERIAL_TYPE baseMaterial)
: COpenGLShaderMaterialRenderer(driver, 0, baseMaterial), CompiledShaders(true)
{
......
......@@ -23,7 +23,7 @@ public:
//! Constructor
COpenGLParallaxMapRenderer(video::COpenGLDriver* driver,
s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial);
s32& outMaterialTypeNr, E_MATERIAL_TYPE baseMaterial);
//! Destructor
~COpenGLParallaxMapRenderer();
......
......@@ -11,6 +11,7 @@
#include "IVideoDriver.h"
#include "os.h"
#include "COpenGLDriver.h"
#include "COpenGLMaterialRenderer.h"
namespace irr
{
......@@ -21,8 +22,8 @@ namespace video
//! Constructor
COpenGLShaderMaterialRenderer::COpenGLShaderMaterialRenderer(video::COpenGLDriver* driver,
s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram,
IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData)
: Driver(driver), CallBack(callback), BaseMaterial(baseMaterial),
IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData)
: Driver(driver), CallBack(callback), BaseMaterial(0),
VertexShader(0), UserData(userData)
{
#ifdef _DEBUG
......@@ -35,6 +36,12 @@ COpenGLShaderMaterialRenderer::COpenGLShaderMaterialRenderer(video::COpenGLDrive
PixelShader[i]=0;
}
if (baseMaterial == EMT_ONETEXTURE_BLEND || baseMaterial == EMT_TRANSPARENT_ADD_COLOR || baseMaterial == EMT_TRANSPARENT_VERTEX_ALPHA ||
baseMaterial == EMT_TRANSPARENT_ALPHA_CHANNEL || baseMaterial == EMT_TRANSPARENT_ALPHA_CHANNEL_REF)
{
BaseMaterial = static_cast<COpenGLMaterialRenderer*>(Driver->getMaterialRenderer(baseMaterial));
}
if (BaseMaterial)
BaseMaterial->grab();
......@@ -49,8 +56,8 @@ COpenGLShaderMaterialRenderer::COpenGLShaderMaterialRenderer(video::COpenGLDrive
//! create a fall back material for example.
COpenGLShaderMaterialRenderer::COpenGLShaderMaterialRenderer(COpenGLDriver* driver,
IShaderConstantSetCallBack* callback,
IMaterialRenderer* baseMaterial, s32 userData)
: Driver(driver), CallBack(callback), BaseMaterial(baseMaterial),
E_MATERIAL_TYPE baseMaterial, s32 userData)
: Driver(driver), CallBack(callback), BaseMaterial(0),
VertexShader(0), UserData(userData)
{
PixelShader.set_used(4);
......@@ -59,6 +66,12 @@ COpenGLShaderMaterialRenderer::COpenGLShaderMaterialRenderer(COpenGLDriver* driv
PixelShader[i]=0;
}
if (baseMaterial == EMT_ONETEXTURE_BLEND || baseMaterial == EMT_TRANSPARENT_ADD_COLOR || baseMaterial == EMT_TRANSPARENT_VERTEX_ALPHA ||
baseMaterial == EMT_TRANSPARENT_ALPHA_CHANNEL || baseMaterial == EMT_TRANSPARENT_ALPHA_CHANNEL_REF)
{
BaseMaterial = static_cast<COpenGLMaterialRenderer*>(Driver->getMaterialRenderer(baseMaterial));
}
if (BaseMaterial)
BaseMaterial->grab();
......@@ -159,15 +172,13 @@ void COpenGLShaderMaterialRenderer::OnSetMaterial(const video::SMaterial& materi
}
if (BaseMaterial)
BaseMaterial->OnSetMaterial(material, lastMaterial, resetAllRenderstates, services);
BaseMaterial->OnSetBaseMaterial(material);
}
//let callback know used material
if (CallBack)
CallBack->OnSetMaterial(material);
for (u32 i=0; i<MATERIAL_MAX_TEXTURES; ++i)
Driver->setActiveTexture(i, material.getTexture(i));
Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
}
......@@ -192,7 +203,7 @@ void COpenGLShaderMaterialRenderer::OnUnsetMaterial()
#endif
if (BaseMaterial)
BaseMaterial->OnUnsetMaterial();
BaseMaterial->OnUnsetBaseMaterial();
}
......
......@@ -35,8 +35,8 @@ namespace video
{
class COpenGLDriver;
class COpenGLMaterialRenderer;
class IShaderConstantSetCallBack;
class IMaterialRenderer;
//! Class for using vertex and pixel shaders with OpenGL
class COpenGLShaderMaterialRenderer : public IMaterialRenderer
......@@ -46,7 +46,7 @@ public:
//! Constructor
COpenGLShaderMaterialRenderer(COpenGLDriver* driver,
s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram,
IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData);
IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData);
//! Destructor
virtual ~COpenGLShaderMaterialRenderer();
......@@ -67,7 +67,7 @@ protected:
//! create a fall back material for example.
COpenGLShaderMaterialRenderer(COpenGLDriver* driver,
IShaderConstantSetCallBack* callback,
IMaterialRenderer* baseMaterial, s32 userData=0);
E_MATERIAL_TYPE baseMaterial, s32 userData=0);
// must not be called more than once!
void init(s32& outMaterialTypeNr, const c8* vertexShaderProgram,
......@@ -79,7 +79,7 @@ protected:
COpenGLDriver* Driver;
IShaderConstantSetCallBack* CallBack;
IMaterialRenderer* BaseMaterial;
COpenGLMaterialRenderer* BaseMaterial;
GLuint VertexShader;
// We have 4 values here, [0] is the non-fog version, the other three are
......
......@@ -316,10 +316,7 @@ void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData, u32 level)
if (!newTexture)
InternalFormat=oldInternalFormat;
Driver->setActiveTexture(0, this);
if (Driver->MultiTextureExtension)
Driver->setGlActiveTexture(GL_TEXTURE0_ARB);
Driver->setGlActiveTexture(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, TextureName);
......@@ -657,10 +654,7 @@ void COpenGLTexture::bindRTT()
//! Unbind Render Target Texture
void COpenGLTexture::unbindRTT()
{
Driver->setActiveTexture(0, this);
if (Driver->MultiTextureExtension)
Driver->setGlActiveTexture(GL_TEXTURE0_ARB);
Driver->setGlActiveTexture(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, TextureName);
......@@ -713,10 +707,8 @@ COpenGLFBOTexture::COpenGLFBOTexture(const core::dimension2d<u32>& size,
// generate color texture
glGenTextures(1, &TextureName);
Driver->setActiveTexture(0, this);
if (Driver->MultiTextureExtension)
Driver->setGlActiveTexture(GL_TEXTURE0_ARB);
Driver->setGlActiveTexture(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, TextureName);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment