Create per fragment lighting using Openscenegraph



Result



Callback for updating the camera position assuming that light direction is from camera

class LightPosCallbackPerFragment : public osg::Uniform::Callback
{
osg::ref_ptr<osg::Camera> _cam;
public:

LightPosCallbackPerFragment(osg::Camera* cam)
{
_cam = cam;
}

virtual void operator()(osg::Uniform* uniform,
osg::NodeVisitor* nv)
{
osg::Vec3 eye, center, up;
_cam->getViewMatrixAsLookAt(eye, center, up);

uniform->set(osg::Vec3(eye.x(), eye.y(), eye.z()));
}
};



below method will apply shader for particular node
void SetShader(osg::Node* inst, osg::Camera* camera)
{


                 static const char* vertSource =
{
"uniform vec3 lightPosition;\n"
"varying vec3 normal, eyeVec, lightDir;\n"
"void main()\n"
"{\n"
"vec4 vertexInEye = gl_ModelViewMatrix * gl_Vertex;\n"
"eyeVec = -vertexInEye.xyz;\n"
"lightDir = vec3(lightPosition - vertexInEye.xyz);\n"
"normal = gl_NormalMatrix * gl_Normal;\n"
"gl_Position = ftransform();\n"
"}\n"
};

static const char* fragSource =
{
"uniform vec4 lightDiffuse;\n"
"uniform vec4 lightSpecular;\n"
"uniform float shininess;\n"
"varying vec3 normal, eyeVec, lightDir;\n"
"void main (void)\n"
"{\n"
"vec4 finalColor = gl_FrontLightModelProduct.sceneColor;\n"
"vec3 N = normalize(normal);\n"
"vec3 L = normalize(lightDir);\n"
"float lambert = dot(N,L);\n"
"if (lambert > 0.0)\n"
"{\n"
"finalColor += lightDiffuse * lambert;\n"
"vec3 E = normalize(eyeVec);\n"
"vec3 R = reflect(-L, N);\n"
"float specular = pow(max(dot(R, E), 0.0), shininess);\n"
"finalColor += lightSpecular * specular;\n"
"}\n"
"gl_FragColor = finalColor;\n"
"}\n"
};
osg::ref_ptr<osg::Program> program = new osg::Program;
program->addShader(new osg::Shader(osg::Shader::VERTEX,
vertSource));
program->addShader(new osg::Shader(osg::Shader::FRAGMENT,
fragSource));
osg::StateSet* stateset = inst->getOrCreateStateSet();  // replace inst with your osg::node
stateset->setAttributeAndModes(program.get());
stateset->addUniform(new osg::Uniform("lightDiffuse",
osg::Vec4(0.8f, 0.8f, 0.8f, 1.0f)));
stateset->addUniform(new osg::Uniform("lightSpecular",
osg::Vec4(1.0f, 1.0f, 0.4f, 1.0f)));
stateset->addUniform(new osg::Uniform("shininess", 64.0f));
osg::ref_ptr<osg::Uniform> lightPos = new osg::Uniform(
"lightPosition", osg::Vec3());
lightPos->setUpdateCallback(new LightPosCallbackPerFragment(camera));

stateset->addUniform(lightPos.get());

}


Create model from file

osg::Node* CreateModel(osg::Camera* camera)
{
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
osg::ref_ptr<osg::Node> sphereGeom = osgDB::readNodeFile("models/3d-model.obj");
if (sphereGeom.valid())
geode->addChild(sphereGeom);

osg::StateSet* state = geode->getOrCreateStateSet();

SetShader(geode, camera);

return geode.release();
}


main method
int main()
{
#ifdef _WIN32
::SetProcessDPIAware(); // if Windows
#endif // _WIN32

osgViewer::Viewer viewer;
osg::DisplaySettings::instance()->setNumMultiSamples(4);

osg::ref_ptr<osg::Group> root = new osg::Group();
root->addChild(CreateModel(viewer.getCamera()));

viewer.setSceneData(root.get());
root->addChild(GetGridAndAxis1());
viewer.setUpViewInWindow(100, 100, OSG_WIDTH, OSG_HEIGHT);

/* depth settings */
osg::StateSet* state = root->getOrCreateStateSet();
state->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);

camera = viewer.getCamera();
camera->setClearColor(FOG_COLOR);
camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

auto manip = new osgGA::TrackballManipulator();
manip->setVerticalAxisFixed(true);
manip->setAllowThrow(false);
manip->setHomePosition(osg::Vec3d(300, 300, 300), osg::Vec3d(0, 0, 0), osg::Vec3d(0, 0, 1));

viewer.setCameraManipulator(manip);
viewer.addEventHandler(new osgViewer::StatsHandler);
osg::ref_ptr<osgGA::StateSetManipulator> statesetManipulator = new osgGA::StateSetManipulator(viewer.getCamera()->getStateSet());
viewer.addEventHandler(statesetManipulator.get());
viewer.realize();
while (!viewer.done()) {
//camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
viewer.frame();
}

return 0;
}


result


for better results used shader program from learnopengl.com as below

enable uniforms from OSG

viewer.getCamera()->getGraphicsContext()->getState()->setUseModelViewAndProjectionUniforms(true);



void AddShaders(osg::ref_ptr<Geode> geode, osg::Camera* camera)
{

std::string vertSource = get_file_string("Vertex.shader"); // reads file to string
std::string fragSource = get_file_string("Fragment.shader");

osg::ref_ptr<osg::Program> program = new osg::Program;

program->addShader(new osg::Shader(osg::Shader::VERTEX,
vertSource));

program->addShader(new osg::Shader(osg::Shader::FRAGMENT,
fragSource));

osg::StateSet* stateset = geode->getOrCreateStateSet();  // replace inst with your osg::node

stateset->setAttributeAndModes(program.get());


osg::Vec3 eye, center, up;
camera->getViewMatrixAsLookAt(eye, center, up);


stateset->addUniform(new osg::Uniform("objectColor",osg::Vec3(1.0f, 0.5f, 0.31f)));
stateset->addUniform(new osg::Uniform("lightColor", osg::Vec3(1.0f, 1.0f, 1.0f)));
stateset->addUniform(new osg::Uniform("lightPos", osg::Vec3(150, 150, 150)));

osg::ref_ptr<osg::Uniform> viewPos = new osg::Uniform(
"viewPos", eye);
viewPos->setUpdateCallback(new ViewPosCB(camera));
stateset->addUniform(viewPos.get());


stateset->addUniform(new osg::Uniform("model", osg::Matrixd::identity()));

osg::ref_ptr<osg::Uniform> view = new osg::Uniform(
"view", camera->getViewMatrix());
view->setUpdateCallback(new ViewMatCB(camera));
stateset->addUniform(view.get());

osg::ref_ptr<osg::Uniform> projection = new osg::Uniform(
"projection", camera->getProjectionMatrix());
projection->setUpdateCallback(new ProjMatCB(camera));
stateset->addUniform(projection.get());

}


Call backs

class ViewPosCB : public osg::Uniform::Callback
{
osg::ref_ptr<osg::Camera> _cam;
public:

ViewPosCB(osg::Camera* cam)
{
_cam = cam;
}

virtual void operator()(osg::Uniform* uniform,
osg::NodeVisitor* nv)
{
osg::Vec3 eye, center, up;
_cam->getViewMatrixAsLookAt(eye, center, up);

uniform->set(osg::Vec3(eye.x(), eye.y(), eye.z()));
}
};

class ViewMatCB : public osg::Uniform::Callback
{
osg::ref_ptr<osg::Camera> _cam;
public:

ViewMatCB(osg::Camera* cam)
{
_cam = cam;
}

virtual void operator()(osg::Uniform* uniform,
osg::NodeVisitor* nv)
{
auto mat = _cam->getViewMatrix();
uniform->set(mat);
}
};

class ProjMatCB : public osg::Uniform::Callback
{
osg::ref_ptr<osg::Camera> _cam;
public:

ProjMatCB(osg::Camera* cam)
{
_cam = cam;
}

virtual void operator()(osg::Uniform* uniform,
osg::NodeVisitor* nv)
{
auto mat = _cam->getProjectionMatrix();
uniform->set(mat);
}
};


Vertex shader file

#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aNormal;

out vec3 FragPos;
out vec3 Normal;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

uniform mat4 osg_ModelViewProjectionMatrix;
uniform mat4 osg_ModelViewMatrix;
uniform mat4 osg_ViewMatrixInverse;
uniform mat3 osg_NormalMatrix;
uniform mat4 osg_ViewMatrix;



void main()
{

mat4 newModel = osg_ModelViewMatrix * osg_ViewMatrixInverse;
FragPos = vec3(newModel * vec4(aPos, 1.0));
Normal = mat3(transpose(inverse(newModel))) * aNormal;

gl_Position = osg_ModelViewProjectionMatrix * vec4(aPos, 1.0);
}


fragment shader file

#version 330 core
out vec4 FragColor;

in vec3 Normal;
in vec3 FragPos;

uniform vec3 lightPos;
uniform vec3 viewPos;
uniform vec3 lightColor;
uniform vec3 objectColor;

void main()
{

// ambient
float ambientStrength = 0.1;
vec3 ambient = ambientStrength * lightColor;

// diffuse
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(lightPos - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * lightColor;

// specular
float specularStrength = 0.5;
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
vec3 specular = specularStrength * spec * lightColor;

vec3 result = (ambient + diffuse + specular) * objectColor;

FragColor = vec4(result, 1.0);
}




No comments:

Post a Comment

frndz giv ur commentz..

Be helpful to others..!!!! Designed by Templateism.com Copyright © 2014

Powered by Blogger.