Merge branch 'master' of https://github.com/openscenegraph/OpenSceneGraph into fix_installExamplesPDB
This commit is contained in:
commit
bcd2adf977
@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgDB/WriteFile>
|
||||
#include <osgUtil/ShaderGen>
|
||||
|
||||
#include <osgViewer/Viewer>
|
||||
@ -26,31 +27,6 @@
|
||||
#include <iostream>
|
||||
|
||||
|
||||
class ShaderGenReadFileCallback : public osgDB::Registry::ReadFileCallback
|
||||
{
|
||||
public:
|
||||
ShaderGenReadFileCallback()
|
||||
{
|
||||
}
|
||||
|
||||
virtual osgDB::ReaderWriter::ReadResult readNode(const std::string& filename, const osgDB::ReaderWriter::Options* options)
|
||||
{
|
||||
osgDB::ReaderWriter::ReadResult result = osgDB::Registry::ReadFileCallback::readNode(filename, options);
|
||||
if (osg::Node *node = result.getNode())
|
||||
{
|
||||
_visitor.reset();
|
||||
node->accept(_visitor);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void setRootStateSet(osg::StateSet *stateSet) { _visitor.setRootStateSet(stateSet); }
|
||||
osg::StateSet *getRootStateSet() const { return _visitor.getRootStateSet(); }
|
||||
|
||||
protected:
|
||||
osgUtil::ShaderGenVisitor _visitor;
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
@ -64,6 +40,8 @@ int main(int argc, char** argv)
|
||||
|
||||
osgViewer::Viewer viewer(arguments);
|
||||
|
||||
|
||||
|
||||
unsigned int helpType = 0;
|
||||
if ((helpType = arguments.readHelpType()))
|
||||
{
|
||||
@ -134,11 +112,10 @@ int main(int argc, char** argv)
|
||||
// add the screen capture handler
|
||||
viewer.addEventHandler(new osgViewer::ScreenCaptureHandler);
|
||||
|
||||
// Register shader generator callback
|
||||
ShaderGenReadFileCallback *readFileCallback = new ShaderGenReadFileCallback;
|
||||
// All read nodes will inherit root state set.
|
||||
readFileCallback->setRootStateSet(viewer.getCamera()->getStateSet());
|
||||
osgDB::Registry::instance()->setReadFileCallback(readFileCallback);
|
||||
|
||||
|
||||
std::string outputFilename;
|
||||
if (arguments.read("-o", outputFilename)) {}
|
||||
|
||||
// load the data
|
||||
osg::ref_ptr<osg::Node> loadedModel = osgDB::readRefNodeFiles(arguments);
|
||||
@ -148,6 +125,20 @@ int main(int argc, char** argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// run the shadergen on the loaded scene graph, and assign the uber shader
|
||||
osgUtil::ShaderGenVisitor shadergen;
|
||||
shadergen.assignUberProgram(viewer.getCamera()->getStateSet());
|
||||
//shadergen.assignUberProgram(loadedModel->getOrCreateStateSet());
|
||||
loadedModel->accept(shadergen);
|
||||
|
||||
if (!outputFilename.empty())
|
||||
{
|
||||
osgDB::writeNodeFile(*loadedModel, outputFilename);
|
||||
osgDB::writeObjectFile(*(viewer.getCamera()->getStateSet()),"rootStateSet.osgt");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
|
||||
|
@ -26,57 +26,19 @@
|
||||
namespace osgUtil
|
||||
{
|
||||
|
||||
class OSGUTIL_EXPORT ShaderGenCache : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
enum StateMask
|
||||
{
|
||||
BLEND = 1,
|
||||
LIGHTING = 2,
|
||||
FOG = 4,
|
||||
DIFFUSE_MAP = 8, //< Texture in unit 0
|
||||
NORMAL_MAP = 16 //< Texture in unit 1 and vertex attribute array 6
|
||||
};
|
||||
|
||||
typedef std::map<int, osg::ref_ptr<osg::StateSet> > StateSetMap;
|
||||
|
||||
ShaderGenCache() {};
|
||||
|
||||
void setStateSet(int stateMask, osg::StateSet *program);
|
||||
osg::StateSet *getStateSet(int stateMask) const;
|
||||
osg::StateSet *getOrCreateStateSet(int stateMask);
|
||||
|
||||
protected:
|
||||
osg::StateSet *createStateSet(int stateMask) const;
|
||||
mutable OpenThreads::Mutex _mutex;
|
||||
StateSetMap _stateSetMap;
|
||||
|
||||
};
|
||||
|
||||
class OSGUTIL_EXPORT ShaderGenVisitor : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
ShaderGenVisitor();
|
||||
ShaderGenVisitor(ShaderGenCache *stateCache);
|
||||
|
||||
void setStateCache(ShaderGenCache *stateCache) { _stateCache = stateCache; }
|
||||
ShaderGenCache *getStateCache() const { return _stateCache.get(); }
|
||||
/// assign default uber program to specified StateSet - typically the root node of the scene graph or the view's Camera
|
||||
void assignUberProgram(osg::StateSet *stateSet);
|
||||
|
||||
/// Top level state set applied as the first one.
|
||||
void setRootStateSet(osg::StateSet *stateSet);
|
||||
osg::StateSet *getRootStateSet() const { return _rootStateSet.get(); }
|
||||
void apply(osg::Node& node);
|
||||
|
||||
void apply(osg::Node &node);
|
||||
void apply(osg::Drawable &drawable);
|
||||
|
||||
void reset();
|
||||
void remapStateSet(osg::StateSet* stateSet);
|
||||
|
||||
protected:
|
||||
void update(osg::Drawable *drawable);
|
||||
|
||||
osg::ref_ptr<ShaderGenCache> _stateCache;
|
||||
osg::ref_ptr<osg::State> _state;
|
||||
osg::ref_ptr<osg::StateSet> _rootStateSet;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -241,7 +241,7 @@ Image::Image(const Image& image,const CopyOp& copyop):
|
||||
{
|
||||
unsigned int size = image.getTotalSizeInBytesIncludingMipmaps();
|
||||
setData(new unsigned char [size],USE_NEW_DELETE);
|
||||
if (unsigned char* dest_ptr = _data)
|
||||
if (unsigned char* dest_ptr = _data)
|
||||
{
|
||||
for(DataIterator itr(&image); itr.valid(); ++itr)
|
||||
{
|
||||
@ -805,15 +805,16 @@ unsigned int Image::computePixelSizeInBits(GLenum format,GLenum type)
|
||||
|
||||
}
|
||||
|
||||
osg::Vec3i Image::computeBlockFootprint(GLenum pixelFormat) {
|
||||
osg::Vec3i Image::computeBlockFootprint(GLenum pixelFormat)
|
||||
{
|
||||
switch (pixelFormat)
|
||||
{
|
||||
case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT) :
|
||||
case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) :
|
||||
case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) :
|
||||
case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) :
|
||||
return osg::Vec3i(4,4,4);//opengl 3d dxt: r value means (max)4 consecutive blocks in r direction packed into a slab.
|
||||
|
||||
return osg::Vec3i(4,4,4);//opengl 3d dxt: r value means (max)4 consecutive blocks in r direction packed into a slab.
|
||||
|
||||
case(GL_COMPRESSED_SIGNED_RED_RGTC1_EXT) :
|
||||
case(GL_COMPRESSED_RED_RGTC1_EXT) :
|
||||
case(GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT) :
|
||||
@ -863,7 +864,7 @@ osg::Vec3i Image::computeBlockFootprint(GLenum pixelFormat) {
|
||||
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR) : return osg::Vec3i(10, 10, 1);
|
||||
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR) : return osg::Vec3i(12, 10, 1);
|
||||
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR) : return osg::Vec3i(12, 12, 1);
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1611,13 +1612,16 @@ void Image::copySubImage(int s_offset, int t_offset, int r_offset, const osg::Im
|
||||
if (isCompressed())
|
||||
{
|
||||
osg::Vec3i footprint = computeBlockFootprint(_pixelFormat);
|
||||
if (footprint.x() == 4 && footprint.y() == 4) {
|
||||
if ((source->s() & 0x3) || (source->t() & 0x3) || (s_offset & 0x3) || (t_offset & 0x3))
|
||||
if (footprint.x() == 4 && footprint.y() == 4)
|
||||
{
|
||||
OSG_WARN << "Error Image::copySubImage() did not succeed : size " << source->s() << "x" << source->t() << " or offset " << s_offset<< "," << t_offset << " not multiple of 4." << std::endl;
|
||||
return;
|
||||
if ((source->s() & 0x3) || (source->t() & 0x3) || (s_offset & 0x3) || (t_offset & 0x3))
|
||||
{
|
||||
OSG_WARN << "Error Image::copySubImage() did not succeed : size " << source->s() << "x" << source->t() << " or offset " << s_offset<< "," << t_offset << " not multiple of 4." << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
else
|
||||
{
|
||||
if ((source->s() % footprint.x()) || (source->t() % footprint.y()) || (s_offset % footprint.x()) || (t_offset% footprint.y()))
|
||||
{
|
||||
OSG_WARN << "Error Image::copySubImage() did not succeed : size " << source->s() << "x" << source->t() << " or offset " << s_offset << "," << t_offset << " not multiple of footprint " << footprint.x() << "x" << footprint.y() << std::endl;
|
||||
|
@ -656,7 +656,15 @@ Program::PerContextProgram::PerContextProgram(const Program* program, unsigned i
|
||||
{
|
||||
_extensions = GLExtensions::Get( _contextID, true );
|
||||
_glProgramHandle = _extensions->glCreateProgram();
|
||||
_ownsProgramHandle = true;
|
||||
|
||||
if (_glProgramHandle)
|
||||
{
|
||||
_ownsProgramHandle = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
OSG_WARN << "Unable to create osg::Program \"" << _program->getName() << "\"" << " contextID=" << _contextID << std::endl;
|
||||
}
|
||||
}
|
||||
requestLink();
|
||||
}
|
||||
@ -682,6 +690,8 @@ void Program::PerContextProgram::linkProgram(osg::State& state)
|
||||
if( ! _needsLink ) return;
|
||||
_needsLink = false;
|
||||
|
||||
if (!_glProgramHandle) return;
|
||||
|
||||
OSG_INFO << "Linking osg::Program \"" << _program->getName() << "\""
|
||||
<< " id=" << _glProgramHandle
|
||||
<< " contextID=" << _contextID
|
||||
@ -709,7 +719,7 @@ void Program::PerContextProgram::linkProgram(osg::State& state)
|
||||
if (!_loadedBinary)
|
||||
{
|
||||
const GLsizei shaderMaxCount = 20;
|
||||
GLsizei shadersCount;
|
||||
GLsizei shadersCount = 0;
|
||||
GLuint shaderObjectHandle[shaderMaxCount];
|
||||
_extensions->glGetAttachedShaders(_glProgramHandle, shaderMaxCount, &shadersCount, shaderObjectHandle);
|
||||
|
||||
@ -1035,6 +1045,8 @@ void Program::PerContextProgram::linkProgram(osg::State& state)
|
||||
|
||||
bool Program::PerContextProgram::validateProgram()
|
||||
{
|
||||
if (!_glProgramHandle) return false;
|
||||
|
||||
GLint validated = GL_FALSE;
|
||||
_extensions->glValidateProgram( _glProgramHandle );
|
||||
_extensions->glGetProgramiv( _glProgramHandle, GL_VALIDATE_STATUS, &validated );
|
||||
@ -1057,11 +1069,15 @@ bool Program::PerContextProgram::validateProgram()
|
||||
|
||||
bool Program::PerContextProgram::getInfoLog( std::string& infoLog ) const
|
||||
{
|
||||
if (!_glProgramHandle) return false;
|
||||
|
||||
return _extensions->getProgramInfoLog( _glProgramHandle, infoLog );
|
||||
}
|
||||
|
||||
Program::ProgramBinary* Program::PerContextProgram::compileProgramBinary(osg::State& state)
|
||||
{
|
||||
if (!_glProgramHandle) return 0;
|
||||
|
||||
linkProgram(state);
|
||||
GLint binaryLength = 0;
|
||||
_extensions->glGetProgramiv( _glProgramHandle, GL_PROGRAM_BINARY_LENGTH, &binaryLength );
|
||||
@ -1079,5 +1095,7 @@ Program::ProgramBinary* Program::PerContextProgram::compileProgramBinary(osg::St
|
||||
|
||||
void Program::PerContextProgram::useProgram() const
|
||||
{
|
||||
if (!_glProgramHandle) return;
|
||||
|
||||
_extensions->glUseProgram( _glProgramHandle );
|
||||
}
|
||||
|
@ -725,7 +725,7 @@ void Texture2DArray::allocateMipmap(State& state) const
|
||||
getCompressedSize( _internalFormat, width, height, textureDepth, blockSize, size);
|
||||
|
||||
extensions->glCompressedTexImage3D( GL_TEXTURE_2D_ARRAY, k, _internalFormat,
|
||||
width, height, _textureDepth, _borderWidth,
|
||||
width, height, textureDepth, _borderWidth,
|
||||
size,
|
||||
NULL);
|
||||
}
|
||||
|
@ -1250,9 +1250,13 @@ void Text::drawImplementation(osg::State& state, const osg::Vec4& colorMultiplie
|
||||
|
||||
void Text::accept(osg::Drawable::ConstAttributeFunctor& af) const
|
||||
{
|
||||
if (_coords.valid() )
|
||||
if (_coords.valid() && !_coords->empty())
|
||||
{
|
||||
af.apply(osg::Drawable::VERTICES, _coords->size(), &(_coords->front()));
|
||||
}
|
||||
|
||||
if (_texcoords.valid() && !_texcoords->empty())
|
||||
{
|
||||
af.apply(osg::Drawable::TEXTURE_COORDS_0, _texcoords->size(), &(_texcoords->front()));
|
||||
}
|
||||
}
|
||||
@ -1285,14 +1289,14 @@ void Text::accept(osg::PrimitiveFunctor& pf) const
|
||||
if (glyphquad._primitives.valid())
|
||||
{
|
||||
const osg::DrawElementsUShort* drawElementsUShort = dynamic_cast<const osg::DrawElementsUShort*>(glyphquad._primitives.get());
|
||||
if (drawElementsUShort)
|
||||
if (drawElementsUShort && drawElementsUShort->size() > 0)
|
||||
{
|
||||
pf.drawElements(GL_TRIANGLES, drawElementsUShort->size(), &(drawElementsUShort->front()));
|
||||
}
|
||||
else
|
||||
{
|
||||
const osg::DrawElementsUInt* drawElementsUInt = dynamic_cast<const osg::DrawElementsUInt*>(glyphquad._primitives.get());
|
||||
if (drawElementsUInt)
|
||||
if (drawElementsUInt && drawElementsUInt->size() > 0)
|
||||
{
|
||||
pf.drawElements(GL_TRIANGLES, drawElementsUInt->size(), &(drawElementsUInt->front()));
|
||||
}
|
||||
@ -1303,7 +1307,7 @@ void Text::accept(osg::PrimitiveFunctor& pf) const
|
||||
|
||||
bool Text::getCharacterCorners(unsigned int index, osg::Vec3& bottomLeft, osg::Vec3& bottomRight, osg::Vec3& topLeft, osg::Vec3& topRight) const
|
||||
{
|
||||
if (_coords) return false;
|
||||
if (!_coords.valid()) return false;
|
||||
|
||||
if ((index*4+4)>static_cast<unsigned int>(_coords->size())) return false;
|
||||
|
||||
|
@ -22,379 +22,93 @@
|
||||
#include <osg/Fog>
|
||||
#include <sstream>
|
||||
|
||||
#include "shaders/shadergen_vert.cpp"
|
||||
#include "shaders/shadergen_frag.cpp"
|
||||
|
||||
using namespace osgUtil;
|
||||
|
||||
namespace osgUtil
|
||||
{
|
||||
|
||||
/// State extended by mode/attribute accessors
|
||||
class StateEx : public osg::State
|
||||
osg::ref_ptr<osg::Program> s_UberProgram;
|
||||
|
||||
struct UberProgramConstructor
|
||||
{
|
||||
public:
|
||||
StateEx() : State() {}
|
||||
|
||||
osg::StateAttribute::GLModeValue getMode(osg::StateAttribute::GLMode mode,
|
||||
osg::StateAttribute::GLModeValue def = osg::StateAttribute::INHERIT) const
|
||||
UberProgramConstructor()
|
||||
{
|
||||
return getMode(_modeMap, mode, def);
|
||||
}
|
||||
|
||||
osg::StateAttribute *getAttribute(osg::StateAttribute::Type type, unsigned int member = 0) const
|
||||
{
|
||||
return getAttribute(_attributeMap, type, member);
|
||||
}
|
||||
|
||||
osg::StateAttribute::GLModeValue getTextureMode(unsigned int unit,
|
||||
osg::StateAttribute::GLMode mode,
|
||||
osg::StateAttribute::GLModeValue def = osg::StateAttribute::INHERIT) const
|
||||
{
|
||||
return unit < _textureModeMapList.size() ? getMode(_textureModeMapList[unit], mode, def) : def;
|
||||
}
|
||||
|
||||
osg::StateAttribute *getTextureAttribute(unsigned int unit, osg::StateAttribute::Type type) const
|
||||
{
|
||||
return unit < _textureAttributeMapList.size() ? getAttribute(_textureAttributeMapList[unit], type, 0) : 0;
|
||||
}
|
||||
|
||||
osg::Uniform *getUniform(const std::string& name) const
|
||||
{
|
||||
UniformMap::const_iterator it = _uniformMap.find(name);
|
||||
return it != _uniformMap.end() ?
|
||||
const_cast<osg::Uniform *>(it->second.uniformVec.back().first) : 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
osg::StateAttribute::GLModeValue getMode(const ModeMap &modeMap,
|
||||
osg::StateAttribute::GLMode mode,
|
||||
osg::StateAttribute::GLModeValue def = osg::StateAttribute::INHERIT) const
|
||||
{
|
||||
ModeMap::const_iterator it = modeMap.find(mode);
|
||||
return (it != modeMap.end() && it->second.valueVec.size()) ? it->second.valueVec.back() : def;
|
||||
}
|
||||
|
||||
osg::StateAttribute *getAttribute(const AttributeMap &attributeMap,
|
||||
osg::StateAttribute::Type type, unsigned int member = 0) const
|
||||
{
|
||||
AttributeMap::const_iterator it = attributeMap.find(std::make_pair(type, member));
|
||||
return (it != attributeMap.end() && it->second.attributeVec.size()) ?
|
||||
const_cast<osg::StateAttribute*>(it->second.attributeVec.back().first) : 0;
|
||||
s_UberProgram = new osg::Program;
|
||||
s_UberProgram->addShader(new osg::Shader(osg::Shader::VERTEX, shadergen_vert));
|
||||
s_UberProgram->addShader(new osg::Shader(osg::Shader::FRAGMENT, shadergen_frag));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void ShaderGenCache::setStateSet(int stateMask, osg::StateSet *stateSet)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
||||
_stateSetMap[stateMask] = stateSet;
|
||||
}
|
||||
|
||||
osg::StateSet *ShaderGenCache::getStateSet(int stateMask) const
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
||||
StateSetMap::const_iterator it = _stateSetMap.find(stateMask);
|
||||
return (it != _stateSetMap.end()) ? it->second.get() : 0;
|
||||
}
|
||||
|
||||
osg::StateSet *ShaderGenCache::getOrCreateStateSet(int stateMask)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
||||
StateSetMap::iterator it = _stateSetMap.find(stateMask);
|
||||
if (it == _stateSetMap.end())
|
||||
{
|
||||
osg::StateSet *stateSet = createStateSet(stateMask);
|
||||
_stateSetMap.insert(it, StateSetMap::value_type(stateMask, stateSet));
|
||||
return stateSet;
|
||||
}
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
osg::StateSet *ShaderGenCache::createStateSet(int stateMask) const
|
||||
{
|
||||
osg::StateSet *stateSet = new osg::StateSet;
|
||||
osg::Program *program = new osg::Program;
|
||||
stateSet->setAttribute(program);
|
||||
|
||||
std::ostringstream vert_frag;
|
||||
|
||||
vert_frag << "// ShaderGen shader\n";
|
||||
vert_frag << "#ifdef GL_ES\n"
|
||||
" precision highp float;\n"
|
||||
"#endif\n";
|
||||
|
||||
// write varyings
|
||||
if ((stateMask & LIGHTING) && !(stateMask & NORMAL_MAP))
|
||||
{
|
||||
vert_frag << "varying vec3 normalDir;\n";
|
||||
}
|
||||
|
||||
if (stateMask & (LIGHTING | NORMAL_MAP))
|
||||
{
|
||||
vert_frag << "varying vec3 lightDir;\n";
|
||||
}
|
||||
|
||||
if (stateMask & (LIGHTING | NORMAL_MAP | FOG))
|
||||
{
|
||||
vert_frag << "varying vec3 viewDir;\n";
|
||||
}
|
||||
|
||||
vert_frag << "varying vec4 vertexColor;\n";
|
||||
|
||||
std::ostringstream vert;
|
||||
std::ostringstream frag;
|
||||
|
||||
// copy varying to vertex ad fragment shader
|
||||
vert << vert_frag.str();
|
||||
frag << vert_frag.str();
|
||||
|
||||
// write uniforms and attributes
|
||||
int unit = 0;
|
||||
if (stateMask & DIFFUSE_MAP)
|
||||
{
|
||||
osg::Uniform *diffuseMap = new osg::Uniform("diffuseMap", unit++);
|
||||
stateSet->addUniform(diffuseMap);
|
||||
frag << "uniform sampler2D diffuseMap;\n";
|
||||
}
|
||||
|
||||
if (stateMask & NORMAL_MAP)
|
||||
{
|
||||
osg::Uniform *normalMap = new osg::Uniform("normalMap", unit++);
|
||||
stateSet->addUniform(normalMap);
|
||||
frag << "uniform sampler2D normalMap;\n";
|
||||
program->addBindAttribLocation("tangent", 6);
|
||||
vert << "attribute vec3 tangent;\n";
|
||||
}
|
||||
|
||||
vert << "\n"\
|
||||
"void main()\n"\
|
||||
"{\n"\
|
||||
" gl_Position = ftransform();\n";
|
||||
|
||||
if (stateMask & (DIFFUSE_MAP | NORMAL_MAP))
|
||||
{
|
||||
vert << " gl_TexCoord[0] = gl_MultiTexCoord0;\n";
|
||||
}
|
||||
|
||||
if (stateMask & NORMAL_MAP)
|
||||
{
|
||||
vert <<
|
||||
" vec3 n = gl_NormalMatrix * gl_Normal;\n"\
|
||||
" vec3 t = gl_NormalMatrix * tangent;\n"\
|
||||
" vec3 b = cross(n, t);\n"\
|
||||
" vec3 dir = -vec3(gl_ModelViewMatrix * gl_Vertex);\n"\
|
||||
" viewDir.x = dot(dir, t);\n"\
|
||||
" viewDir.y = dot(dir, b);\n"\
|
||||
" viewDir.z = dot(dir, n);\n"\
|
||||
" vec4 lpos = gl_LightSource[0].position;\n"\
|
||||
" if (lpos.w == 0.0)\n"\
|
||||
" dir = lpos.xyz;\n"\
|
||||
" else\n"\
|
||||
" dir += lpos.xyz;\n"\
|
||||
" lightDir.x = dot(dir, t);\n"\
|
||||
" lightDir.y = dot(dir, b);\n"\
|
||||
" lightDir.z = dot(dir, n);\n";
|
||||
}
|
||||
#if !OSG_GLES2_FEATURES && !OSG_GLES3_FEATURES && !OSG_GL2_FEATURES
|
||||
else if (stateMask & LIGHTING)
|
||||
{
|
||||
vert <<
|
||||
" normalDir = gl_NormalMatrix * gl_Normal;\n"\
|
||||
" vec3 dir = -vec3(gl_ModelViewMatrix * gl_Vertex);\n"\
|
||||
" viewDir = dir;\n"\
|
||||
" vec4 lpos = gl_LightSource[0].position;\n"\
|
||||
" if (lpos.w == 0.0)\n"\
|
||||
" lightDir = lpos.xyz;\n"\
|
||||
" else\n"\
|
||||
" lightDir = lpos.xyz + dir;\n";
|
||||
}
|
||||
else if (stateMask & FOG)
|
||||
{
|
||||
vert <<
|
||||
" viewDir = -vec3(gl_ModelViewMatrix * gl_Vertex);\n"\
|
||||
" vertexColor = gl_Color;\n";
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
vert << " vertexColor = gl_Color;\n";
|
||||
}
|
||||
|
||||
vert << "}\n";
|
||||
|
||||
frag << "\n"\
|
||||
"void main()\n"\
|
||||
"{\n";
|
||||
|
||||
if (stateMask & DIFFUSE_MAP)
|
||||
{
|
||||
frag << " vec4 base = vertexColor * texture2D(diffuseMap, gl_TexCoord[0].st);\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
frag << " vec4 base = vertexColor;\n";
|
||||
}
|
||||
|
||||
if (stateMask & NORMAL_MAP)
|
||||
{
|
||||
frag << " vec3 normalDir = texture2D(normalMap, gl_TexCoord[0].st).xyz*2.0-1.0;\n";
|
||||
}
|
||||
|
||||
#if !OSG_GLES2_FEATURES && !OSG_GLES3_FEATURES && !OSG_GL2_FEATURES
|
||||
if (stateMask & (LIGHTING | NORMAL_MAP))
|
||||
{
|
||||
frag <<
|
||||
" vec3 nd = normalize(normalDir);\n"\
|
||||
" vec3 ld = normalize(lightDir);\n"\
|
||||
" vec3 vd = normalize(viewDir);\n"\
|
||||
" vec4 color = gl_FrontLightModelProduct.sceneColor;\n"\
|
||||
" color += gl_FrontLightProduct[0].ambient;\n"\
|
||||
" float diff = max(dot(ld, nd), 0.0);\n"\
|
||||
" color += gl_FrontLightProduct[0].diffuse * diff;\n"\
|
||||
" color *= base;\n"\
|
||||
" if (diff > 0.0)\n"\
|
||||
" {\n"\
|
||||
" vec3 halfDir = normalize(ld+vd);\n"\
|
||||
" color.rgb += base.a * gl_FrontLightProduct[0].specular.rgb * \n"\
|
||||
" pow(max(dot(halfDir, nd), 0.0), gl_FrontMaterial.shininess);\n"\
|
||||
" }\n";
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
frag << " vec4 color = base;\n";
|
||||
}
|
||||
UberProgramConstructor s_UberProgramConstructor;
|
||||
|
||||
|
||||
#if !OSG_GLES2_FEATURES && !OSG_GLES3_FEATURES && !OSG_GL2_FEATURES
|
||||
if (stateMask & FOG)
|
||||
{
|
||||
frag <<
|
||||
" float d2 = dot(viewDir, viewDir);//gl_FragCoord.z/gl_FragCoord.w;\n"\
|
||||
" float f = exp2(-1.442695*gl_Fog.density*gl_Fog.density*d2);\n"\
|
||||
" color.rgb = mix(gl_Fog.color.rgb, color.rgb, clamp(f, 0.0, 1.0));\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
frag << " gl_FragColor = color;\n";
|
||||
frag << "}\n";
|
||||
|
||||
std::string vertstr = vert.str();
|
||||
std::string fragstr = frag.str();
|
||||
|
||||
OSG_DEBUG << "ShaderGenCache Vertex shader:\n" << vertstr << std::endl;
|
||||
OSG_DEBUG << "ShaderGenCache Fragment shader:\n" << fragstr << std::endl;
|
||||
|
||||
program->addShader(new osg::Shader(osg::Shader::VERTEX, vertstr));
|
||||
program->addShader(new osg::Shader(osg::Shader::FRAGMENT, fragstr));
|
||||
|
||||
return stateSet;
|
||||
}
|
||||
|
||||
ShaderGenVisitor::ShaderGenVisitor() :
|
||||
NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
||||
_stateCache(new ShaderGenCache),
|
||||
_state(new StateEx)
|
||||
ShaderGenVisitor::ShaderGenVisitor():
|
||||
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
|
||||
{
|
||||
}
|
||||
|
||||
ShaderGenVisitor::ShaderGenVisitor(ShaderGenCache *stateCache) :
|
||||
NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
||||
_stateCache(stateCache),
|
||||
_state(new StateEx)
|
||||
void ShaderGenVisitor::assignUberProgram(osg::StateSet *stateSet)
|
||||
{
|
||||
}
|
||||
if (stateSet)
|
||||
{
|
||||
stateSet->setAttribute(s_UberProgram.get());
|
||||
stateSet->addUniform(new osg::Uniform("diffuseMap", 0));
|
||||
|
||||
void ShaderGenVisitor::setRootStateSet(osg::StateSet *stateSet)
|
||||
{
|
||||
if (_rootStateSet.valid())
|
||||
_state->removeStateSet(0);
|
||||
_rootStateSet = stateSet;
|
||||
if (_rootStateSet.valid())
|
||||
_state->pushStateSet(_rootStateSet.get());
|
||||
}
|
||||
|
||||
void ShaderGenVisitor::reset()
|
||||
{
|
||||
_state->popAllStateSets();
|
||||
if (_rootStateSet.valid())
|
||||
_state->pushStateSet(_rootStateSet.get());
|
||||
remapStateSet(stateSet);
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderGenVisitor::apply(osg::Node &node)
|
||||
{
|
||||
osg::StateSet *stateSet = node.getStateSet();
|
||||
|
||||
if (stateSet)
|
||||
_state->pushStateSet(stateSet);
|
||||
osg::StateSet* stateSet = node.getStateSet();
|
||||
if (stateSet) remapStateSet(stateSet);
|
||||
|
||||
traverse(node);
|
||||
|
||||
if (stateSet)
|
||||
_state->popStateSet();
|
||||
}
|
||||
|
||||
void ShaderGenVisitor::apply(osg::Drawable &drawable)
|
||||
|
||||
void ShaderGenVisitor::remapStateSet(osg::StateSet* stateSet)
|
||||
{
|
||||
osg::StateSet *stateSet = drawable.getStateSet();
|
||||
if (stateSet)
|
||||
_state->pushStateSet(stateSet);
|
||||
if (!stateSet) return;
|
||||
|
||||
update(&drawable);
|
||||
// remove any modes that won't be appropriate when using shaders, and remap them to the apppropriate Uniform/Define combination
|
||||
|
||||
if (stateSet)
|
||||
_state->popStateSet();
|
||||
|
||||
osg::StateSet::ModeList& modes = stateSet->getModeList();
|
||||
|
||||
if (modes.count(GL_LIGHTING)>0)
|
||||
{
|
||||
osg::StateAttribute::GLModeValue lightingMode =modes[GL_LIGHTING];
|
||||
|
||||
stateSet->removeMode(GL_LIGHTING);
|
||||
stateSet->removeMode(GL_LIGHT0);
|
||||
|
||||
stateSet->setDefine("GL_LIGHTING", lightingMode);
|
||||
}
|
||||
|
||||
|
||||
if (modes.count(GL_FOG)>0)
|
||||
{
|
||||
osg::StateAttribute::GLModeValue fogMode = modes[GL_FOG];
|
||||
stateSet->removeMode(GL_FOG);
|
||||
stateSet->setDefine("GL_FOG", fogMode);
|
||||
}
|
||||
|
||||
|
||||
if (!stateSet->getTextureModeList().empty())
|
||||
{
|
||||
osg::StateSet::ModeList& textureModes = stateSet->getTextureModeList()[0];
|
||||
|
||||
if (textureModes.count(GL_TEXTURE_2D)>0)
|
||||
{
|
||||
osg::StateAttribute::GLModeValue textureMode = textureModes[GL_TEXTURE_2D];
|
||||
stateSet->removeTextureMode(0, GL_TEXTURE_2D);
|
||||
stateSet->setDefine("GL_TEXTURE_2D", textureMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderGenVisitor::update(osg::Drawable *drawable)
|
||||
{
|
||||
// update only geometry due to compatibility issues with user defined drawables
|
||||
osg::Geometry *geometry = drawable->asGeometry();
|
||||
#if 0
|
||||
if (!geometry)
|
||||
return;
|
||||
#endif
|
||||
|
||||
StateEx *state = static_cast<StateEx *>(_state.get());
|
||||
// skip nodes without state sets
|
||||
if (state->getStateSetStackSize() == (_rootStateSet.valid() ? 1u : 0u))
|
||||
return;
|
||||
|
||||
// skip state sets with already attached programs
|
||||
if (state->getAttribute(osg::StateAttribute::PROGRAM))
|
||||
return;
|
||||
|
||||
int stateMask = 0;
|
||||
//if (state->getMode(GL_BLEND) & osg::StateAttribute::ON)
|
||||
// stateMask |= ShaderGen::BLEND;
|
||||
if (state->getMode(GL_LIGHTING) & osg::StateAttribute::ON)
|
||||
stateMask |= ShaderGenCache::LIGHTING;
|
||||
if (state->getMode(GL_FOG) & osg::StateAttribute::ON)
|
||||
stateMask |= ShaderGenCache::FOG;
|
||||
if (state->getTextureAttribute(0, osg::StateAttribute::TEXTURE))
|
||||
stateMask |= ShaderGenCache::DIFFUSE_MAP;
|
||||
|
||||
if (state->getTextureAttribute(1, osg::StateAttribute::TEXTURE) && geometry!=0 &&
|
||||
geometry->getVertexAttribArray(6)) //tangent
|
||||
stateMask |= ShaderGenCache::NORMAL_MAP;
|
||||
|
||||
// Get program and uniforms for accumulated state.
|
||||
osg::StateSet *progss = _stateCache->getOrCreateStateSet(stateMask);
|
||||
// Set program and uniforms to the last state set.
|
||||
osg::StateSet *ss = const_cast<osg::StateSet *>(state->getStateSetStack().back());
|
||||
ss->setAttribute(progss->getAttribute(osg::StateAttribute::PROGRAM));
|
||||
ss->setUniformList(progss->getUniformList());
|
||||
|
||||
// remove any modes that won't be appropriate when using shaders
|
||||
if ((stateMask&ShaderGenCache::LIGHTING)!=0)
|
||||
{
|
||||
ss->removeMode(GL_LIGHTING);
|
||||
ss->removeMode(GL_LIGHT0);
|
||||
}
|
||||
if ((stateMask&ShaderGenCache::FOG)!=0)
|
||||
{
|
||||
ss->removeMode(GL_FOG);
|
||||
}
|
||||
if ((stateMask&ShaderGenCache::DIFFUSE_MAP)!=0) ss->removeTextureMode(0, GL_TEXTURE_2D);
|
||||
if ((stateMask&ShaderGenCache::NORMAL_MAP)!=0) ss->removeTextureMode(1, GL_TEXTURE_2D);
|
||||
}
|
||||
} // namespace osgUtil
|
35
src/osgUtil/shaders/shadergen_frag.cpp
Normal file
35
src/osgUtil/shaders/shadergen_frag.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
char shadergen_frag[] = "// ShaderGen shader\n"
|
||||
"// new version\n"
|
||||
"#ifdef GL_ES\n"
|
||||
" precision highp float;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"#pragma import_defines(GL_LIGHTING, GL_TEXTURE_2D, GL_FOG)\n"
|
||||
"\n"
|
||||
"#if defined(GL_LIGHTING)\n"
|
||||
"varying vec3 normalDir;\n"
|
||||
"varying vec3 lightDir;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"#if defined(GL_LIGHTING) || defined(GL_FOG)\n"
|
||||
"varying vec3 viewDir;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"varying vec4 vertexColor;\n"
|
||||
"\n"
|
||||
"#if defined(GL_TEXTURE_2D)\n"
|
||||
"uniform sampler2D diffuseMap;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" vec4 color = vertexColor;\n"
|
||||
"\n"
|
||||
"#if defined(GL_TEXTURE_2D)\n"
|
||||
" color = color * texture2D(diffuseMap, gl_TexCoord[0].st);\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" gl_FragColor = color;\n"
|
||||
"}\n"
|
||||
"\n";
|
44
src/osgUtil/shaders/shadergen_vert.cpp
Normal file
44
src/osgUtil/shaders/shadergen_vert.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
char shadergen_vert[] = "// ShaderGen shader\n"
|
||||
"// new version\n"
|
||||
"#ifdef GL_ES\n"
|
||||
" precision highp float;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"#pragma import_defines(GL_LIGHTING, GL_TEXTURE_2D, GL_FOG)\n"
|
||||
"\n"
|
||||
"#if defined(GL_LIGHTING)\n"
|
||||
"varying vec3 normalDir;\n"
|
||||
"varying vec3 lightDir;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"#if defined(GL_LIGHTING) || defined(GL_FOG)\n"
|
||||
"varying vec3 viewDir;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"varying vec4 vertexColor;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = ftransform();\n"
|
||||
"\n"
|
||||
"#if defined(GL_TEXTURE_2D)\n"
|
||||
" gl_TexCoord[0] = gl_MultiTexCoord0;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"#if defined(GL_LIGHTING) || defined(GL_FOG)\n"
|
||||
" viewDir = -vec3(gl_ModelViewMatrix * gl_Vertex);\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"#if defined(GL_LIGHTING)\n"
|
||||
" normalDir = gl_NormalMatrix * gl_Normal;\n"
|
||||
" vec4 lpos = gl_LightSource[0].position;\n"
|
||||
" if (lpos.w == 0.0)\n"
|
||||
" lightDir = lpos.xyz;\n"
|
||||
" else\n"
|
||||
" lightDir = lpos.xyz + viewDir;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
" vertexColor = gl_Color;\n"
|
||||
"}\n"
|
||||
"\n";
|
Loading…
Reference in New Issue
Block a user