Reduce shader attribute usage by packing floats

Previously we required 6 shader attributes to pass
in all the required information for the building shader.
By using packing techniques this has been reduced to 4.

This should improve support for integrated graphics cards.
This commit is contained in:
Stuart Buchanan 2020-03-26 22:09:04 +00:00
parent ec315bf26d
commit 454df4872a
2 changed files with 37 additions and 20 deletions

View File

@ -27,6 +27,7 @@
#include <vector>
#include <string>
#include <map>
#include <math.h>
#include <boost/foreach.hpp>
#include <boost/tuple/tuple_comparison.hpp>
@ -329,10 +330,8 @@ struct MakeBuildingLeaf
geom->setVertexAttribArray(BUILDING_POSITION_ATTR, new osg::Vec3Array, Array::BIND_PER_VERTEX);
geom->setVertexAttribArray(BUILDING_SCALE_ATTR, new osg::Vec3Array, Array::BIND_PER_VERTEX);
geom->setVertexAttribArray(BUILDING_ROT_PITCH_TEX0X_ATTR, new osg::Vec3Array, Array::BIND_PER_VERTEX);
geom->setVertexAttribArray(BUILDING_TEX0Y_TEX1X_TEX1Y_ATTR, new osg::Vec3Array, Array::BIND_PER_VERTEX);
geom->setVertexAttribArray(BUILDING_RTEX0X_RTEX0Y_ATTR, new osg::Vec3Array, Array::BIND_PER_VERTEX);
geom->setVertexAttribArray(BUILDING_ROFFTOPSCALE_ATTR, new osg::Vec3Array, Array::BIND_PER_VERTEX);
geom->setVertexAttribArray(BUILDING_ATTR1, new osg::Vec3Array, Array::BIND_PER_VERTEX);
geom->setVertexAttribArray(BUILDING_ATTR2, new osg::Vec3Array, Array::BIND_PER_VERTEX);
//geom->addPrimitiveSet( new osg::DrawArrays( GL_QUADS, 0, 48, 0) );
geom->addPrimitiveSet( new osg::DrawArrays( GL_QUADS, 0, 52, 0) );
@ -344,10 +343,8 @@ struct MakeBuildingLeaf
StateSet* ss = geode->getOrCreateStateSet();
ss->setAttributeAndModes(new osg::VertexAttribDivisor(BUILDING_POSITION_ATTR, 1));
ss->setAttributeAndModes(new osg::VertexAttribDivisor(BUILDING_SCALE_ATTR, 1));
ss->setAttributeAndModes(new osg::VertexAttribDivisor(BUILDING_ROT_PITCH_TEX0X_ATTR, 1));
ss->setAttributeAndModes(new osg::VertexAttribDivisor(BUILDING_TEX0Y_TEX1X_TEX1Y_ATTR, 1));
ss->setAttributeAndModes(new osg::VertexAttribDivisor(BUILDING_RTEX0X_RTEX0Y_ATTR, 1));
ss->setAttributeAndModes(new osg::VertexAttribDivisor(BUILDING_ROFFTOPSCALE_ATTR, 1));
ss->setAttributeAndModes(new osg::VertexAttribDivisor(BUILDING_ATTR1, 1));
ss->setAttributeAndModes(new osg::VertexAttribDivisor(BUILDING_ATTR2, 1));
LOD* result = new LOD;
result->addChild(geode, 0, _range);
@ -359,6 +356,15 @@ struct MakeBuildingLeaf
bool _fade_out;
};
const float pack_precision = 128.0;
const float pack_precision1 = pack_precision+1.0;
float pack8bit(float a, float b, float c) {
return floor(a * pack_precision + 0.5)
+ floor(b * pack_precision + 0.5) * pack_precision1
+ floor(c * pack_precision + 0.5) * pack_precision1 * pack_precision1;
};
struct AddBuildingLeafObject
{
void operator() (LOD* lod, const SGBuildingBin::BuildingInstance building) const
@ -370,18 +376,29 @@ struct AddBuildingLeafObject
osg::Vec3Array* positions = static_cast<osg::Vec3Array*> (geom->getVertexAttribArray(BUILDING_POSITION_ATTR)); // (x,y,z)
osg::Vec3Array* scale = static_cast<osg::Vec3Array*> (geom->getVertexAttribArray(BUILDING_SCALE_ATTR)); // (width, depth, height)
osg::Vec3Array* rot = static_cast<osg::Vec3Array*> (geom->getVertexAttribArray(BUILDING_ROT_PITCH_TEX0X_ATTR)); // (rotation, pitch height, wall texture x0)
osg::Vec3Array* tex = static_cast<osg::Vec3Array*> (geom->getVertexAttribArray(BUILDING_TEX0Y_TEX1X_TEX1Y_ATTR)); // (wall texture y0, front/roof texture x1, front/side/roof texture y1)
osg::Vec3Array* rtex = static_cast<osg::Vec3Array*> (geom->getVertexAttribArray(BUILDING_RTEX0X_RTEX0Y_ATTR)); // (roof texture x0, roof texture y0, side texture x1)
osg::Vec3Array* rooftops = static_cast<osg::Vec3Array*> (geom->getVertexAttribArray(BUILDING_ROFFTOPSCALE_ATTR)); // (rooftop scale x, rooftop scale y, unused)
osg::Vec3Array* attrib1 = static_cast<osg::Vec3Array*> (geom->getVertexAttribArray(BUILDING_ATTR1));
osg::Vec3Array* attrib2 = static_cast<osg::Vec3Array*> (geom->getVertexAttribArray(BUILDING_ATTR2));
positions->push_back(building.position);
// Depth is the x-axis, width is the y-axis
scale->push_back(osg::Vec3f(building.depth, building.width, building.height));
rot->push_back(osg::Vec3f(building.rotation, building.pitch_height, building.walltex0.x()));
tex->push_back(osg::Vec3f(building.walltex0.y(), building.tex1.x(), building.tex1.y()));
rtex->push_back(osg::Vec3f(building.rooftex0.x(), building.rooftex0.y(), building.tex1.z()));
rooftops->push_back(osg::Vec3f(building.rooftop_scale.x(), building.rooftop_scale.y(), 0.0f));
attrib1->push_back(osg::Vec3d(
pack8bit(building.rotation, // attr1 in shader
building.walltex0.x(),
building.walltex0.y()),
building.pitch_height,
pack8bit(building.tex1.x(), // attr2 in shader
building.tex1.y(),
building.rooftex0.x())
));
attrib2->push_back(osg::Vec3f(
pack8bit( // attr3 in shader
building.rooftex0.y(),
building.tex1.z(),
building.rooftop_scale.x()),
building.rooftop_scale.y(),
0.0f
));
DrawArrays* primSet = static_cast<DrawArrays*>(geom->getPrimitiveSet(0));
primSet->setNumInstances(positions->size());

View File

@ -54,10 +54,10 @@
// these correspond to building.eff
const int BUILDING_POSITION_ATTR = 10; // (x,y,z)
const int BUILDING_SCALE_ATTR = 11; // (width, depth, height)
const int BUILDING_ROT_PITCH_TEX0X_ATTR = 12; // (rotation, pitch height, wall texture x offset)
const int BUILDING_TEX0Y_TEX1X_TEX1Y_ATTR = 13; // (wall texture y offset, texture x gain, texture y gain)
const int BUILDING_RTEX0X_RTEX0Y_ATTR = 14; // (roof texture x offset, roof texture y offset, unused)
const int BUILDING_ROFFTOPSCALE_ATTR = 15; // (roof texture x offset, roof texture y offset, unused)
const int BUILDING_ATTR1 = 12;
const int BUILDING_ATTR2 = 13;
const int BUILDING_ATTR3 = 14;
const int BUILDING_ATTR4 = 15;
using namespace osg;