mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2024-12-25 06:05:45 +00:00
Fixes & enhancements to shader interface code
This commit is contained in:
parent
c62d9f2370
commit
2ac3ad9fb1
5 changed files with 221 additions and 56 deletions
|
@ -38,6 +38,7 @@ static const char *scriptObjTypeNames[] =
|
||||||
/* (1 <<10) */ "Quad",
|
/* (1 <<10) */ "Quad",
|
||||||
/* (1 <<11) */ "Text",
|
/* (1 <<11) */ "Text",
|
||||||
/* (1 <<12) */ "PauseQuad",
|
/* (1 <<12) */ "PauseQuad",
|
||||||
|
/* (1 <<13) */ "Shader",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ enum ScriptObjectType
|
||||||
SCO_QUAD = 0x0400,
|
SCO_QUAD = 0x0400,
|
||||||
SCO_TEXT = 0x0800,
|
SCO_TEXT = 0x0800,
|
||||||
SCO_PAUSEQUAD = 0x1000,
|
SCO_PAUSEQUAD = 0x1000,
|
||||||
|
SCO_SHADER = 0x2000,
|
||||||
|
|
||||||
SCO_FORCE_32BIT = 0xFFFFFFFF
|
SCO_FORCE_32BIT = 0xFFFFFFFF
|
||||||
};
|
};
|
||||||
|
|
193
BBGE/Shader.cpp
193
BBGE/Shader.cpp
|
@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Shader.h"
|
#include "Shader.h"
|
||||||
|
#include "algorithmx.h"
|
||||||
|
|
||||||
#ifdef BBGE_BUILD_SHADERS
|
#ifdef BBGE_BUILD_SHADERS
|
||||||
// GL_ARB_shader_objects
|
// GL_ARB_shader_objects
|
||||||
|
@ -34,9 +35,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
PFNGLGETINFOLOGARBPROC glGetInfoLogARB = NULL;
|
PFNGLGETINFOLOGARBPROC glGetInfoLogARB = NULL;
|
||||||
PFNGLLINKPROGRAMARBPROC glLinkProgramARB = NULL;
|
PFNGLLINKPROGRAMARBPROC glLinkProgramARB = NULL;
|
||||||
PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB = NULL;
|
PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB = NULL;
|
||||||
PFNGLUNIFORM4FARBPROC glUniform4fARB = NULL;
|
PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB = NULL;
|
||||||
PFNGLUNIFORM1IARBPROC glUniform1iARB = NULL;
|
PFNGLUNIFORM1FVARBPROC glUniform1fvARB = NULL;
|
||||||
PFNGLUNIFORM1FARBPROC glUniform1fARB = NULL;
|
PFNGLUNIFORM2FVARBPROC glUniform2fvARB = NULL;
|
||||||
|
PFNGLUNIFORM3FVARBPROC glUniform3fvARB = NULL;
|
||||||
|
PFNGLUNIFORM4FVARBPROC glUniform4fvARB = NULL;
|
||||||
|
PFNGLUNIFORM1IVARBPROC glUniform1ivARB = NULL;
|
||||||
|
PFNGLUNIFORM2IVARBPROC glUniform2ivARB = NULL;
|
||||||
|
PFNGLUNIFORM3IVARBPROC glUniform3ivARB = NULL;
|
||||||
|
PFNGLUNIFORM4IVARBPROC glUniform4ivARB = NULL;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool Shader::_wasInited = false;
|
bool Shader::_wasInited = false;
|
||||||
|
@ -84,16 +92,23 @@ void Shader::staticInit()
|
||||||
glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)SDL_GL_GetProcAddress("glGetInfoLogARB");
|
glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)SDL_GL_GetProcAddress("glGetInfoLogARB");
|
||||||
glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)SDL_GL_GetProcAddress("glLinkProgramARB");
|
glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)SDL_GL_GetProcAddress("glLinkProgramARB");
|
||||||
glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)SDL_GL_GetProcAddress("glGetUniformLocationARB");
|
glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)SDL_GL_GetProcAddress("glGetUniformLocationARB");
|
||||||
glUniform4fARB = (PFNGLUNIFORM4FARBPROC)SDL_GL_GetProcAddress("glUniform4fARB");
|
glGetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC)SDL_GL_GetProcAddress("glGetActiveUniformARB");
|
||||||
glUniform1iARB = (PFNGLUNIFORM1IARBPROC)SDL_GL_GetProcAddress("glUniform1iARB");
|
glUniform1fvARB = (PFNGLUNIFORM1FVARBPROC)SDL_GL_GetProcAddress("glUniform1fvARB");
|
||||||
glUniform1fARB = (PFNGLUNIFORM1FARBPROC)SDL_GL_GetProcAddress("glUniform1fARB");
|
glUniform2fvARB = (PFNGLUNIFORM2FVARBPROC)SDL_GL_GetProcAddress("glUniform2fvARB");
|
||||||
|
glUniform3fvARB = (PFNGLUNIFORM3FVARBPROC)SDL_GL_GetProcAddress("glUniform3fvARB");
|
||||||
|
glUniform4fvARB = (PFNGLUNIFORM4FVARBPROC)SDL_GL_GetProcAddress("glUniform4fvARB");
|
||||||
|
glUniform1ivARB = (PFNGLUNIFORM1IVARBPROC)SDL_GL_GetProcAddress("glUniform1ivARB");
|
||||||
|
glUniform2ivARB = (PFNGLUNIFORM2IVARBPROC)SDL_GL_GetProcAddress("glUniform2ivARB");
|
||||||
|
glUniform3ivARB = (PFNGLUNIFORM3IVARBPROC)SDL_GL_GetProcAddress("glUniform3ivARB");
|
||||||
|
glUniform4ivARB = (PFNGLUNIFORM4IVARBPROC)SDL_GL_GetProcAddress("glUniform4ivARB");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if( !glCreateProgramObjectARB || !glDeleteObjectARB || !glUseProgramObjectARB ||
|
if( !glCreateProgramObjectARB || !glDeleteObjectARB || !glUseProgramObjectARB ||
|
||||||
!glCreateShaderObjectARB || !glCreateShaderObjectARB || !glCompileShaderARB ||
|
!glCreateShaderObjectARB || !glCreateShaderObjectARB || !glCompileShaderARB ||
|
||||||
!glGetObjectParameterivARB || !glAttachObjectARB || !glGetInfoLogARB ||
|
!glGetObjectParameterivARB || !glAttachObjectARB || !glGetInfoLogARB ||
|
||||||
!glLinkProgramARB || !glGetUniformLocationARB || !glUniform4fARB ||
|
!glLinkProgramARB || !glGetUniformLocationARB || !glGetActiveUniformARB ||
|
||||||
!glUniform1iARB || !glUniform1fARB )
|
!glUniform1fvARB || !glUniform2fvARB || !glUniform3fvARB || !glUniform4fvARB ||
|
||||||
|
!glUniform1ivARB || !glUniform2ivARB || !glUniform3ivARB || !glUniform4ivARB)
|
||||||
{
|
{
|
||||||
glCreateProgramObjectARB = 0;
|
glCreateProgramObjectARB = 0;
|
||||||
debugLog("One or more GL_ARB_shader_objects functions were not found");
|
debugLog("One or more GL_ARB_shader_objects functions were not found");
|
||||||
|
@ -116,6 +131,10 @@ end:
|
||||||
|
|
||||||
Shader::Shader()
|
Shader::Shader()
|
||||||
{
|
{
|
||||||
|
addType(SCO_SHADER);
|
||||||
|
numUniforms = -1;
|
||||||
|
uniformsDirty = false;
|
||||||
|
|
||||||
#ifdef BBGE_BUILD_OPENGL
|
#ifdef BBGE_BUILD_OPENGL
|
||||||
g_programObj = 0;
|
g_programObj = 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -139,7 +158,7 @@ void Shader::unload()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Shader::isLoaded()
|
bool Shader::isLoaded() const
|
||||||
{
|
{
|
||||||
return g_programObj != 0;
|
return g_programObj != 0;
|
||||||
}
|
}
|
||||||
|
@ -155,6 +174,7 @@ void Shader::bind()
|
||||||
if (!_useShaders)
|
if (!_useShaders)
|
||||||
return;
|
return;
|
||||||
glUseProgramObjectARB(g_programObj);
|
glUseProgramObjectARB(g_programObj);
|
||||||
|
_flushUniforms();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,6 +237,7 @@ void Shader::load(const std::string &file, const std::string &fragFile)
|
||||||
|
|
||||||
void Shader::loadSrc(const char *vertCode, const char *fragCode)
|
void Shader::loadSrc(const char *vertCode, const char *fragCode)
|
||||||
{
|
{
|
||||||
|
staticInit();
|
||||||
unload();
|
unload();
|
||||||
|
|
||||||
if(!_useShaders)
|
if(!_useShaders)
|
||||||
|
@ -232,7 +253,7 @@ void Shader::loadSrc(const char *vertCode, const char *fragCode)
|
||||||
//
|
//
|
||||||
// Create the vertex shader...
|
// Create the vertex shader...
|
||||||
//
|
//
|
||||||
if(vertCode && !(vertexShader = _compileShader(GL_VERTEX_SHADER_ARB, vertCode, str, sizeof(str))))
|
if(vertCode && *vertCode && !(vertexShader = _compileShader(GL_VERTEX_SHADER_ARB, vertCode, str, sizeof(str))))
|
||||||
{
|
{
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
os << "Vertex Shader Compile Error [" << vertFile << "]:\n" << str;
|
os << "Vertex Shader Compile Error [" << vertFile << "]:\n" << str;
|
||||||
|
@ -243,7 +264,7 @@ void Shader::loadSrc(const char *vertCode, const char *fragCode)
|
||||||
//
|
//
|
||||||
// Create the fragment shader...
|
// Create the fragment shader...
|
||||||
//
|
//
|
||||||
if(fragCode && !(fragmentShader = _compileShader(GL_FRAGMENT_SHADER_ARB, fragCode, str, sizeof(str))))
|
if(fragCode && *fragCode && !(fragmentShader = _compileShader(GL_FRAGMENT_SHADER_ARB, fragCode, str, sizeof(str))))
|
||||||
{
|
{
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
os << "Fragment Shader Compile Error [" << fragFile << "]:\n" << str;
|
os << "Fragment Shader Compile Error [" << fragFile << "]:\n" << str;
|
||||||
|
@ -294,59 +315,131 @@ void Shader::loadSrc(const char *vertCode, const char *fragCode)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_queryUniforms();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: I'm not quite sure but i bet this sucks.
|
void Shader::_setUniform(Uniform *u)
|
||||||
// Design a good caching policy and simplify the implementation,
|
|
||||||
// but keep shader dynamism and shaders generated at runtime in mind.
|
|
||||||
// No idea if and how much runtime performance it costs
|
|
||||||
// to query the uniform locations everytime.
|
|
||||||
// -- FG
|
|
||||||
|
|
||||||
static void shaderUniformError(const char *func, const char *var)
|
|
||||||
{
|
{
|
||||||
GLint err = glGetError();
|
/*if(u->location == -1)
|
||||||
/*std::ostringstream os;
|
{
|
||||||
os << "Shader::" << func << "(" << var << ") -- undef uniform (Error: " << err << ")";
|
u->location = glGetUniformLocationARB(g_programObj, u->name);
|
||||||
debugLog(os.str());*/
|
if(u->location == -1)
|
||||||
|
{
|
||||||
|
u->dirty = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
switch(u->type)
|
||||||
|
{
|
||||||
|
case GL_FLOAT: glUniform1fvARB(u->location, 1, u->data.f); break;
|
||||||
|
case GL_FLOAT_VEC2_ARB: glUniform2fvARB(u->location, 1, u->data.f); break;
|
||||||
|
case GL_FLOAT_VEC3_ARB: glUniform3fvARB(u->location, 1, u->data.f); break;
|
||||||
|
case GL_FLOAT_VEC4_ARB: glUniform4fvARB(u->location, 1, u->data.f); break;
|
||||||
|
case GL_INT: glUniform1ivARB(u->location, 1, u->data.i); break;
|
||||||
|
case GL_INT_VEC2_ARB: glUniform2ivARB(u->location, 1, u->data.i); break;
|
||||||
|
case GL_INT_VEC3_ARB: glUniform3ivARB(u->location, 1, u->data.i); break;
|
||||||
|
case GL_INT_VEC4_ARB: glUniform4ivARB(u->location, 1, u->data.i); break;
|
||||||
|
}
|
||||||
|
u->dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::setInt(const char *name, int x)
|
void Shader::_flushUniforms()
|
||||||
|
{
|
||||||
|
if(!uniformsDirty)
|
||||||
|
return;
|
||||||
|
uniformsDirty = false;
|
||||||
|
|
||||||
|
for(size_t i = 0; i < uniforms.size(); ++i)
|
||||||
|
{
|
||||||
|
Uniform &u = uniforms[i];
|
||||||
|
if(u.dirty)
|
||||||
|
_setUniform(&u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// for sorting
|
||||||
|
bool Shader::_sortUniform(const Uniform& a, const char *bname)
|
||||||
|
{
|
||||||
|
return strcmp(a.name, bname) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Shader::Uniform::operator< (const Uniform& b) const
|
||||||
|
{
|
||||||
|
return Shader::_sortUniform(*this, &b.name[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::_queryUniforms()
|
||||||
|
{
|
||||||
|
glGetObjectParameterivARB(g_programObj, GL_OBJECT_ACTIVE_UNIFORMS_ARB , &numUniforms);
|
||||||
|
|
||||||
|
if (numUniforms <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uniforms.reserve(numUniforms);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < numUniforms; ++i)
|
||||||
|
{
|
||||||
|
Uniform u;
|
||||||
|
GLint size = 0;
|
||||||
|
GLenum type = 0;
|
||||||
|
glGetActiveUniformARB(g_programObj, i, sizeof(u.name), NULL, &size, &type, &u.name[0]);
|
||||||
|
if(!type || !size)
|
||||||
|
continue;
|
||||||
|
u.location = glGetUniformLocationARB(g_programObj, u.name);
|
||||||
|
if(u.location == -1)
|
||||||
|
continue;
|
||||||
|
u.dirty = false;
|
||||||
|
u.type = type;
|
||||||
|
memset(&u.data, 0, sizeof(u.data));
|
||||||
|
|
||||||
|
uniforms.push_back(u);
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort to be able to do binary search later
|
||||||
|
std::sort(uniforms.begin(), uniforms.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
int Shader::_getUniformIndex(const char *name)
|
||||||
|
{
|
||||||
|
// binary search
|
||||||
|
UniformVec::iterator it = stdx_fg::lower_bound(uniforms.begin(), uniforms.end(), name, _sortUniform);
|
||||||
|
return int(it - uniforms.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::setInt(const char *name, int x, int y /* = 0 */, int z /* = 0 */, int w /* = 0 */)
|
||||||
{
|
{
|
||||||
#if BBGE_BUILD_SHADERS
|
#if BBGE_BUILD_SHADERS
|
||||||
if(!g_programObj)
|
if(!g_programObj || numUniforms <= 0)
|
||||||
return;
|
return;
|
||||||
GLint loc = glGetUniformLocationARB(g_programObj, name);
|
int idx = _getUniformIndex(name);
|
||||||
if(loc != -1)
|
if(unsigned(idx) >= uniforms.size())
|
||||||
glUniform1iARB(loc, x);
|
return;
|
||||||
else
|
Uniform& u = uniforms[idx];
|
||||||
shaderUniformError("setInt", name);
|
u.data.i[0] = x;
|
||||||
|
u.data.i[1] = y;
|
||||||
|
u.data.i[2] = z;
|
||||||
|
u.data.i[3] = w;
|
||||||
|
u.dirty = true;
|
||||||
|
uniformsDirty = true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::setFloat(const char *name, float x)
|
void Shader::setFloat(const char *name, float x, float y /* = 0 */, float z /* = 0 */, float w /* = 0 */)
|
||||||
{
|
{
|
||||||
#if BBGE_BUILD_SHADERS
|
#if BBGE_BUILD_SHADERS
|
||||||
if(!g_programObj)
|
if(!g_programObj || numUniforms <= 0)
|
||||||
return;
|
return;
|
||||||
GLint loc = glGetUniformLocationARB(g_programObj, name);
|
int idx = _getUniformIndex(name);
|
||||||
if(loc != -1)
|
if(unsigned(idx) >= uniforms.size())
|
||||||
glUniform1fARB(loc, x);
|
return;
|
||||||
else
|
Uniform& u = uniforms[idx];
|
||||||
shaderUniformError("setFloat", name);
|
u.data.f[0] = x;
|
||||||
#endif
|
u.data.f[1] = y;
|
||||||
}
|
u.data.f[2] = z;
|
||||||
|
u.data.f[3] = w;
|
||||||
void Shader::setFloat4(const char *name, float x, float y, float z, float w)
|
u.dirty = true;
|
||||||
{
|
uniformsDirty = true;
|
||||||
#if BBGE_BUILD_SHADERS
|
|
||||||
if(!g_programObj)
|
|
||||||
return;
|
|
||||||
GLint loc = glGetUniformLocationARB(g_programObj, name);
|
|
||||||
if(loc != -1)
|
|
||||||
glUniform4fARB(loc, x, y, z, w);
|
|
||||||
else
|
|
||||||
shaderUniformError("setFloat4", name);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,13 +22,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#define BBGE_SHADER_H
|
#define BBGE_SHADER_H
|
||||||
|
|
||||||
#include "Base.h"
|
#include "Base.h"
|
||||||
|
#include "ScriptObject.h"
|
||||||
|
|
||||||
class Shader
|
class Shader : public ScriptObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Shader();
|
Shader();
|
||||||
~Shader();
|
~Shader();
|
||||||
bool isLoaded();
|
bool isLoaded() const;
|
||||||
void load(const std::string &file, const std::string &fragFile);
|
void load(const std::string &file, const std::string &fragFile);
|
||||||
void loadSrc(const char *vertCode, const char *fragCode);
|
void loadSrc(const char *vertCode, const char *fragCode);
|
||||||
void reload();
|
void reload();
|
||||||
|
@ -36,16 +37,16 @@ public:
|
||||||
void bind();
|
void bind();
|
||||||
void unbind();
|
void unbind();
|
||||||
|
|
||||||
// TODO: design a good API for this...
|
void setInt(const char *name, int x, int y = 0, int z = 0, int w = 0);
|
||||||
void setInt(const char *name, int x);
|
void setFloat(const char *name, float x, float y = 0, float z = 0, float w = 0);
|
||||||
void setFloat(const char *name, float x);
|
// TODO: other setters needed?
|
||||||
void setFloat4(const char *name, float x, float y, float z, float w);
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::string vertFile, fragFile;
|
std::string vertFile, fragFile;
|
||||||
#ifdef BBGE_BUILD_OPENGL
|
#ifdef BBGE_BUILD_OPENGL
|
||||||
GLuint g_programObj;
|
GLuint g_programObj;
|
||||||
|
int numUniforms;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -54,6 +55,41 @@ private:
|
||||||
static bool _useShaders;
|
static bool _useShaders;
|
||||||
|
|
||||||
static unsigned int _compileShader(int type, const char *src, char *errbuf, size_t errbufsize);
|
static unsigned int _compileShader(int type, const char *src, char *errbuf, size_t errbufsize);
|
||||||
|
|
||||||
|
struct Uniform
|
||||||
|
{
|
||||||
|
int location; // GL location variable
|
||||||
|
int type;
|
||||||
|
bool dirty; // need to flush if true
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int i[4];
|
||||||
|
};
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
float f[4];
|
||||||
|
};
|
||||||
|
} data;
|
||||||
|
char name[32];
|
||||||
|
|
||||||
|
bool operator< (const Uniform&) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool _sortUniform(const Uniform& a, const char *bname);
|
||||||
|
|
||||||
|
void _queryUniforms();
|
||||||
|
void _flushUniforms();
|
||||||
|
void _registerUniform();
|
||||||
|
|
||||||
|
void _setUniform(Uniform *u);
|
||||||
|
int _getUniformIndex(const char *name);
|
||||||
|
|
||||||
|
typedef std::vector<Uniform> UniformVec;
|
||||||
|
UniformVec uniforms;
|
||||||
|
|
||||||
|
bool uniformsDirty;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
34
ExternalLibs/algorithmx.h
Normal file
34
ExternalLibs/algorithmx.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef STDXfg_ALGORITHMX_H
|
||||||
|
#define STDXfg_ALGORITHMX_H
|
||||||
|
|
||||||
|
// Some std:: namespace enhancements
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace stdx_fg {
|
||||||
|
|
||||||
|
template <class ForwardIterator, class T, class Compare>
|
||||||
|
ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& val, Compare comp)
|
||||||
|
{
|
||||||
|
ForwardIterator it;
|
||||||
|
typename std::iterator_traits<ForwardIterator>::difference_type count, step;
|
||||||
|
count = std::distance(first,last);
|
||||||
|
while(count > 0)
|
||||||
|
{
|
||||||
|
it = first;
|
||||||
|
step = count/2;
|
||||||
|
std::advance (it,step);
|
||||||
|
if (comp(*it, val))
|
||||||
|
{
|
||||||
|
first= ++it;
|
||||||
|
count -= step+1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
count = step;
|
||||||
|
}
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end namespace stdx_fg
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue