Added support for subsititing $VAR_NAME entries in shaders to enable writing shaders that work across GLSL versions.

This commit is contained in:
Robert Osfield
2017-09-18 18:09:15 +01:00
parent 5ade852172
commit cc7cf54353
5 changed files with 179 additions and 21 deletions

View File

@@ -118,7 +118,8 @@ void DisplaySettings::setDisplaySettings(const DisplaySettings& vs)
_swapMethod = vs._swapMethod;
_vertexBufferHint = vs._vertexBufferHint;
_shaderHint = vs._shaderHint;
setShaderHint(_shaderHint);
_keystoneHint = vs._keystoneHint;
_keystoneFileNames = vs._keystoneFileNames;
@@ -250,23 +251,17 @@ void DisplaySettings::setDefaults()
// _vertexBufferHint = VERTEX_ARRAY_OBJECT;
#if defined(OSG_GLES3_AVAILABLE)
_shaderHint = SHADER_GLES3;
OSG_INFO<<"DisplaySettings::SHADER_GLES3"<<std::endl;
setShaderHint(SHADER_GLES3);
#elif defined(OSG_GLES2_AVAILABLE)
_shaderHint = SHADER_GLES2;
OSG_INFO<<"DisplaySettings::SHADER_GLES2"<<std::endl;
setShaderHint(SHADER_GLES2);
#elif defined(OSG_GL3_AVAILABLE)
_shaderHint = SHADER_GL3;
OSG_INFO<<"DisplaySettings::SHADER_GL3"<<std::endl;
setShaderHint(SHADER_GL3);
#elif defined(OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE)
OSG_INFO<<"DisplaySettings::SHADER_NONE"<<std::endl;
_shaderHint = SHADER_NONE;
setShaderHint(SHADER_NONE);
#else
OSG_INFO<<"DisplaySettings::SHADER_GL2"<<std::endl;
_shaderHint = SHADER_GL2;
setShaderHint(SHADER_GL2);
#endif
_keystoneHint = false;
_OSXMenubarBehavior = MENUBAR_AUTO_HIDE;
@@ -725,23 +720,23 @@ void DisplaySettings::readEnvironmentalVariables()
{
if (strcmp(ptr,"GL2")==0)
{
_shaderHint = SHADER_GL2;
setShaderHint(SHADER_GL2);
}
else if (strcmp(ptr,"GL3")==0)
{
_shaderHint = SHADER_GL3;
setShaderHint(SHADER_GL3);
}
else if (strcmp(ptr,"GLES2")==0)
{
_shaderHint = SHADER_GLES2;
setShaderHint(SHADER_GLES2);
}
else if (strcmp(ptr,"GLES3")==0)
{
_shaderHint = SHADER_GLES3;
setShaderHint(SHADER_GLES3);
}
else if (strcmp(ptr,"NONE")==0)
{
_shaderHint = SHADER_NONE;
setShaderHint(SHADER_NONE);
}
}
@@ -1098,3 +1093,84 @@ osg::Matrixd DisplaySettings::computeRightEyeViewImplementation(const osg::Matri
0.0,0.0,1.0,0.0,
-es,0.0,0.0,1.0);
}
void DisplaySettings::setShaderHint(ShaderHint hint, bool setShaderValues)
{
_shaderHint = hint;
if (setShaderValues)
{
switch(_shaderHint)
{
case(SHADER_GLES3) :
setValue("OSG_GLSL_VERSION", "#version 300 es");
setValue("OSG_PRECISION_FLOAT", "precision highp float;");
setValue("OSG_VARYING_IN", "in");
setValue("OSG_VARYING_OUT", "out");
OSG_NOTICE<<"DisplaySettings::SHADER_GLES3"<<std::endl;
break;
case(SHADER_GLES2) :
setValue("OSG_GLSL_VERSION", "");
setValue("OSG_PRECISION_FLOAT", "precision highp float;");
setValue("OSG_VARYING_IN", "varying");
setValue("OSG_VARYING_OUT", "varying");
OSG_NOTICE<<"DisplaySettings::SHADER_GLES2"<<std::endl;
break;
case(SHADER_GL3) :
setValue("OSG_GLSL_VERSION", "#version 330");
setValue("OSG_PRECISION_FLOAT", "");
setValue("OSG_VARYING_IN", "in");
setValue("OSG_VARYING_OUT", "out");
OSG_NOTICE<<"DisplaySettings::SHADER_GL3"<<std::endl;
break;
case(SHADER_GL2) :
setValue("OSG_GLSL_VERSION", "");
setValue("OSG_PRECISION_FLOAT", "");
setValue("OSG_VARYING_IN", "varying");
setValue("OSG_VARYING_OUT", "varying");
OSG_NOTICE<<"DisplaySettings::SHADER_GL2"<<std::endl;
break;
case(SHADER_NONE) :
setValue("OSG_GLSL_VERSION", "");
setValue("OSG_PRECISION_FLOAT", "");
setValue("OSG_VARYING_IN", "varying");
setValue("OSG_VARYING_OUT", "varying");
OSG_NOTICE<<"DisplaySettings::NONE"<<std::endl;
break;
}
}
}
void DisplaySettings::setValue(const std::string& name, const std::string& value)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_valueMapMutex);
_valueMap[name] = value;
}
bool DisplaySettings::getValue(const std::string& name, std::string& value, bool use_getenv_fallback) const
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_valueMapMutex);
ValueMap::iterator itr = _valueMap.find(name);
if (itr!=_valueMap.end())
{
value = itr->second;
OSG_NOTICE<<"DisplaySettings::getValue("<<name<<") found existing value = ["<<value<<"]"<<std::endl;
return true;
}
if (!use_getenv_fallback) return false;
const char* str = getenv(name.c_str());
if (str)
{
OSG_NOTICE<<"DisplaySettings::getValue("<<name<<") found getenv value = ["<<value<<"]"<<std::endl;
_valueMap[name] = value = str;
return true;
}
else
{
return false;
}
}

View File

@@ -618,7 +618,7 @@ void Shader::PerContextShader::compileShader(osg::State& state)
#endif
std::string source = _shader->getShaderSource();
if (_shader->getType()==osg::Shader::VERTEX && (state.getUseVertexAttributeAliasing() || state.getUseModelViewAndProjectionUniforms()))
// if (_shader->getType()==osg::Shader::VERTEX && (state.getUseVertexAttributeAliasing() || state.getUseModelViewAndProjectionUniforms()))
{
state.convertVertexShaderSourceToOsgBuiltIns(source);
}

View File

@@ -1216,6 +1216,68 @@ namespace State_Utils
source.insert(declPos, qualifier + declarationPrefix + newStr + std::string(";\n"));
}
}
void replaceVar(const osg::State& state, std::string& str, std::string::size_type start_pos, std::string::size_type num_chars)
{
std::string var_str(str.substr(start_pos+1, num_chars-1));
std::string value;
OSG_NOTICE<<" Need to replace : ["<<var_str<<"] ds="<<state.getDisplaySettings()<< std::endl;
if (state.getActiveDisplaySettings()->getValue(var_str, value))
{
OSG_NOTICE<<" Value : "<<value<<std::endl;
str.replace(start_pos, num_chars, value);
}
else
{
OSG_NOTICE<<" No value assignd, ereasing "<<std::endl;
str.erase(start_pos, num_chars);
}
}
void substitudeEnvVars(const osg::State& state, std::string& str)
{
OSG_NOTICE<<"substitudeEnvVars()"<<std::endl;
std::string::size_type pos = 0;
while (pos<str.size() && ((pos=str.find_first_of("$'\"", pos)) != std::string::npos))
{
if (pos==str.size())
{
OSG_NOTICE<<" Found "<<str[pos]<<" but it's the last character"<<std::endl;
break;
}
if (str[pos]=='"' || str[pos]=='\'')
{
std::string::size_type start_quote = pos;
++pos;
pos = str.find(str[start_quote], pos);
if (pos != std::string::npos) { OSG_NOTICE<<" Found ending string : "<<str.substr(start_quote, pos-start_quote+1)<<std::endl; ++pos; }
else { OSG_NOTICE<<" Found middle string : "<<str.substr(start_quote, std::string::npos)<<std::endl; break; }
}
else
{
std::string::size_type start_var = pos;
++pos;
pos = str.find_first_not_of("ABCDEFGHIJKLMNOPQRTSUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_", pos);
std::string var_str;
if (pos != std::string::npos)
{
OSG_NOTICE<<" Found $ : "<<str.substr(start_var, pos-start_var)<<" "<<pos<<std::endl;
replaceVar(state, str, start_var, pos-start_var);
pos = start_var;
}
else
{
OSG_NOTICE<<" Found $ at end of string : "<<str.substr(start_var, std::string::npos)<<" "<<pos<<std::endl;
replaceVar(state, str, start_var, str.size()-start_var);
pos = start_var;
}
}
}
}
}
bool State::convertVertexShaderSourceToOsgBuiltIns(std::string& source) const
@@ -1224,6 +1286,10 @@ bool State::convertVertexShaderSourceToOsgBuiltIns(std::string& source) const
OSG_INFO<<"++Before Converted source "<<std::endl<<source<<std::endl<<"++++++++"<<std::endl;
State_Utils::substitudeEnvVars(*this, source);
std::string attributeQualifier("attribute ");
// find the first legal insertion point for replacement declarations. GLSL requires that nothing
@@ -1279,7 +1345,7 @@ bool State::convertVertexShaderSourceToOsgBuiltIns(std::string& source) const
}
}
OSG_INFO<<"-------- Converted source "<<std::endl<<source<<std::endl<<"----------------"<<std::endl;
OSG_NOTICE<<"-------- Converted source "<<std::endl<<source<<std::endl<<"----------------"<<std::endl;
return true;
}