先记录下,免得时间久了忘了。
对于光照,光源有点光源,聚光灯,方向光。每种光源又有ambient,diffuse,specular,emission几个属性。
这里用点光源(不考虑衰减)
1,diffuse是入射光与物体法线之间的余弦起作用
2,specular是半矢量与物体法线之间的余弦起作用。
3,在learn opengl中,是在逆转置矩阵乘以法线转换到投影坐标系;而osg中,也可以使用摄像机坐标系下的法线,转换到摄像机坐标系。本质都是一样的。同理,点光源的位置,也可以转换到投影坐标系或者摄像机坐标系。
4,这里考虑到点云可能是黑色的(0,0,0,0),相乘也是0,所以做了些处理。
代码如下:
//通过Liblas读取.las文件,并在osg中显示出来,用shader
#include <liblas/liblas.hpp>
#include
#include
#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>
#include <osg/CoordinateSystemNode>
#include <osg/Switch>
#include <osg/Types>
#include <osgText/Text>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TerrainManipulator>
#include <osgGA/SphericalManipulator>
#include <osgGA/Device>
#include
#include <osg/Shader>
osg::ref_ptrosg::Geode getGeodeFromLas(std::string strLasFileName)
{
std::ifstream ifs;
ifs.open(strLasFileName, std::ios::in | std::ios::binary);
liblas::ReaderFactory f;
liblas::Reader reader = f.CreateWithStream(ifs);
liblas::Header const& header = reader.GetHeader();
int pointCount = header.GetPointRecordsCount();
std::cout << "pointCount:" << pointCount << std::endl;
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
for (int i = 0; i < pointCount; i++)
{
bool readSuccess = reader.ReadPointAt(i);
if (!readSuccess)
{
continue;
}
liblas::Point const& p = reader.GetPoint();
float red = p.GetColor().GetRed() * 1.0 / 65535;
float green = p.GetColor().GetGreen()* 1.0 / 65535;
//float green = 1.0;
float blue = p.GetColor().GetBlue()* 1.0 / 65535;
// std::cout << "red =" << red << ";green=" << green << ";blue=" << blue << std::endl;
colors->push_back(osg::Vec4(red, green, blue, 1.0));
double x = p.GetX();
double y = p.GetY();
double z = p.GetZ();
// std::cout << "x =" << x << ";y=" << y << ";z=" << z << std::endl;
vertices->push_back(osg::Vec3(x, y, z));
}
geom->setVertexAttribArray(10, colors, osg::Array::BIND_PER_VERTEX);
geom->setColorArray(colors, osg::Array::BIND_PER_VERTEX);
geom->setVertexArray(vertices);
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, vertices->size()));
geode->addDrawable(geom);
return geode.release();
}
static const char * vertexShader =
{
“uniform vec3 lightWorldPos; \n”
“in vec4 colors;\n”
“varying float NdotL;\n”
“varying float NdotHV;\n”
“varying vec3 ReflectVec;\n”
“varying vec3 ViewVec;\n”
“varying vec4 outColors;”
“void main(void)\n”
“{\n”
“vec3 ecPos = vec3 (gl_ModelViewMatrix * gl_Vertex);\n”
“vec3 tnorm = normalize(gl_NormalMatrix * gl_Normal);\n”
“vec4 lightViewPos = gl_ModelViewMatrix * vec4(lightWorldPos,1.0);”
“vec3 lightVec = normalize(lightViewPos.xyz - ecPos);\n”
“ReflectVec = normalize(reflect(-lightVec, tnorm));\n”
“ViewVec = normalize(-ecPos);\n”
“NdotL = max(dot(lightVec, tnorm),0.0);\n”
“vec3 halfVector = normalize(ViewVec + lightVec);”
"NdotHV = max(0,dot(tnorm, halfVector)); "
“outColors = colors;”
“gl_Position = ftransform();\n”
“}\n”
};
static const char *psShader =
{
“uniform float alpha;”
“uniform float shinessValue;”
“uniform float ambientStrength;”
“uniform vec4 ambientLightColor;”
“uniform vec4 diffuseLightColor;”
“uniform vec4 specularLightColor;”
“varying float NdotL;\n”
“varying float NdotHV;\n”
“varying vec3 ReflectVec;\n”
“varying vec3 ViewVec;\n”
“varying vec4 outColors;”
“void main(void)\n”
“{\n”
“vec4 specular = vec4(0.0,0.0,0.0,0.0);”
“if ( NdotL * NdotHV > 0.0 )”
“{”
“specular = specularLightColor * pow( NdotHV, shinessValue);”
“}”
“vec4 diffuse = NdotL * diffuseLightColor;”
“vec4 ambient = ambientStrength * ambientLightColor;”
“vec4 totalLightColor = diffuse + specular + ambient;”
“gl_FragColor = totalLightColor * outColors;\n”
“if(outColors.xyz == vec3(0.0,0.0,0.0))”
“{”
“gl_FragColor = min(totalLightColor,vec4(1.0,1.0,1.0,1.0)) ;\n”
“}”
"gl_FragColor.a = alpha;\n"
"}\n"
};
int main()
{
//std::string strLasFileName = “d:/ddss.las”;
std::string strLasFileName = “d:/test.las”;
osg::ref_ptr<osg::Group> grp = new osg::Group;
osg::ref_ptr<osg::Geode> geode = getGeodeFromLas(strLasFileName);
grp->addChild(geode);
//获取geode中心点,在向上走,罩住整个场景,当做点光源位置
osg::Vec3 center = geode->getBound().center();
center.z() += geode->getBound().radius() *0.5;
osg::ref_ptr<osg::StateSet> stateset = geode->getOrCreateStateSet();
stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
osg::ref_ptr<osg::Shader> vs = new osg::Shader(osg::Shader::VERTEX, vertexShader);
osg::ref_ptr<osg::Shader> ps = new osg::Shader(osg::Shader::FRAGMENT, psShader);
osg::ref_ptr<osg::Program> program = new osg::Program;
program->addShader(vs);
program->addShader(ps);
program->addBindAttribLocation("colors", 10);
osg::ref_ptr<osg::Uniform> alphaValue = new osg::Uniform("alpha", 0.2f);
osg::ref_ptr<osg::Uniform> shinessValue = new osg::Uniform("shinessValue", 64.0f);
osg::ref_ptr<osg::Uniform> ambientLength = new osg::Uniform("ambientStrength", 0.3f);
osg::ref_ptr<osg::Uniform> ambientLightColor = new osg::Uniform("ambientLightColor", osg::Vec4(0.1f, 0.1f, 0.1f, 0.1f));
osg::ref_ptr<osg::Uniform> diffuseLightColor = new osg::Uniform("diffuseLightColor", osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
osg::ref_ptr<osg::Uniform> specularLightColor = new osg::Uniform("specularLightColor", osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
osg::ref_ptr<osg::Uniform> lightWorldPos = new osg::Uniform("lightWorldPos", center);
stateset->addUniform(alphaValue);
stateset->addUniform(shinessValue);
stateset->addUniform(ambientLength);
stateset->addUniform(ambientLightColor);
stateset->addUniform(diffuseLightColor);
stateset->addUniform(specularLightColor);
stateset->addUniform(lightWorldPos);
stateset->setAttribute(program, osg::StateAttribute::ON);
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
viewer->getCamera()->setClearColor(osg::Vec4(0, 0, 0, 1.0));
viewer->setSceneData(grp);
viewer->run();
return 0;
}
运行结果如下: