先記錄下,免得時間久了忘了。
對于光照,光源有點光源,聚光燈,方向光。每種光源又有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;
}
運行結果如下:
總結
以上是生活随笔為你收集整理的osg+shader光照半透明的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。