Skip to content

Instantly share code, notes, and snippets.

@bkmeneguello
Created July 21, 2013 00:49
Show Gist options
  • Save bkmeneguello/6047028 to your computer and use it in GitHub Desktop.
Save bkmeneguello/6047028 to your computer and use it in GitHub Desktop.
OpenSceneGraph Shader 4.00
#include <osg/ArgumentParser>
#include <osg/Array>
#include <osg/Camera>
#include <osg/Drawable>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Group>
#include <osg/Light>
#include <osg/Matrixd>
#include <osg/MixinVector>
#include <osg/Node>
#include <osg/NodeVisitor>
#include <osg/Object>
#include <osg/PrimitiveSet>
#include <osg/Program>
#include <osg/Shader>
#include <osg/StateAttribute>
#include <osg/StateSet>
#include <osg/Transform>
#include <osg/Uniform>
#include <osg/Vec3f>
#include <osg/Vec4f>
#include <osg/View>
#include <osgDB/ReadFile>
#include <osgGA/OrbitManipulator>
#include <osgGA/StateSetManipulator>
#include <osgViewer/View>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
struct ModelViewMatrixCallback: public osg::Uniform::Callback {
ModelViewMatrixCallback(osg::Camera* camera) :
_camera(camera) {
}
virtual void operator()(osg::Uniform* uniform, osg::NodeVisitor* nv) {
osg::Matrixd viewMatrix = _camera->getViewMatrix();
osg::Matrixd modelMatrix = osg::computeLocalToWorld(nv->getNodePath());
uniform->set(modelMatrix * viewMatrix);
}
osg::Camera* _camera;
};
struct NormalMatrixCallback: public osg::Uniform::Callback {
NormalMatrixCallback(osg::Camera* camera) :
_camera(camera) {
}
virtual void operator()(osg::Uniform* uniform, osg::NodeVisitor* nv) {
osg::Matrixd viewMatrix = _camera->getViewMatrix();
osg::Matrixd modelMatrix = osg::computeLocalToWorld(nv->getNodePath());
osg::Matrixd modelViewMatrix = modelMatrix * viewMatrix;
modelViewMatrix.setTrans(0.0, 0.0, 0.0);
osg::Matrixd inverse;
inverse.invert(modelViewMatrix);
osg::Matrix3 normalMatrix(
inverse(0,0), inverse(1,0), inverse(2,0),
inverse(0,1), inverse(1,1), inverse(2,1),
inverse(0,2), inverse(1,2), inverse(2,2));
uniform->set(normalMatrix);
}
osg::Camera* _camera;
};
struct ModelViewProjectionMatrixCallback: public osg::Uniform::Callback {
ModelViewProjectionMatrixCallback(osg::Camera* camera) :
_camera(camera) {
}
virtual void operator()(osg::Uniform* uniform, osg::NodeVisitor* nv) {
osg::Matrixd viewMatrix = _camera->getViewMatrix();
osg::Matrixd modelMatrix = osg::computeLocalToWorld(nv->getNodePath());
osg::Matrixd modelViewProjectionMatrix = modelMatrix * viewMatrix * _camera->getProjectionMatrix();
uniform->set(modelViewProjectionMatrix);
}
osg::Camera* _camera;
};
int main(int argc, char** argv) {
osg::ArgumentParser arguments(&argc, argv);
osgViewer::Viewer* viewer = new osgViewer::Viewer(arguments);
osg::Camera* camera = viewer->getCamera();
viewer->setCameraManipulator(new osgGA::OrbitManipulator());
osgGA::StateSetManipulator* stateSet = new osgGA::StateSetManipulator(camera->getOrCreateStateSet());
viewer->addEventHandler(stateSet);
viewer->addEventHandler(new osgViewer::StatsHandler);
viewer->addEventHandler(new osgViewer::WindowSizeHandler);
osg::Group* root = new osg::Group();
osg::Vec3Array& vertex = *(new osg::Vec3Array(4));
osg::Vec3Array& normal = *(new osg::Vec3Array(1));
osg::Vec4Array& color = *(new osg::Vec4Array(4));
vertex.setName("Vertex");
vertex[0].set(0,0,0);
vertex[1].set(1,0,0);
vertex[2].set(1,0,1);
vertex[3].set(0,0,1);
normal.setName("Normal");
normal[0].set(0,-1,0);
color.setName("Color");
color[0].set(1,0,0,1);
color[1].set(0,1,0,1);
color[2].set(0,0,1,1);
color[3].set(1,0,1,1);
osg::Geometry *geom = new osg::Geometry;
geom->setUseDisplayList(false);
geom->setVertexAttribArray(0, &vertex);
geom->setVertexAttribNormalize(0, false);
geom->setVertexAttribBinding(0, osg::Geometry::BIND_PER_VERTEX);
geom->setVertexAttribArray(1, &normal);
geom->setVertexAttribNormalize(1, true);
geom->setVertexAttribBinding(1, osg::Geometry::BIND_OVERALL);
geom->setVertexAttribArray(2, &color);
geom->setVertexAttribNormalize(2, false);
geom->setVertexAttribBinding(2, osg::Geometry::BIND_PER_VERTEX);
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
osg::Program* program = new osg::Program;
program->setName("shader");
program->addShader(osgDB::readShaderFile(osg::Shader::VERTEX, "test.vert"));
program->addShader(osgDB::readShaderFile(osg::Shader::FRAGMENT, "test.frag"));
osg::Geode* geode = new osg::Geode;
geode->addDrawable(geom);
osg::StateSet* state = geode->getOrCreateStateSet();
state->setAttributeAndModes(program, osg::StateAttribute::ON);
osg::Uniform* modelViewMatrix = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "ModelViewMatrix");
modelViewMatrix->setUpdateCallback(new ModelViewMatrixCallback(camera));
state->addUniform(modelViewMatrix);
osg::Uniform* normalMatrix = new osg::Uniform(osg::Uniform::FLOAT_MAT3, "NormalMatrix");
normalMatrix->setUpdateCallback(new NormalMatrixCallback(camera));
state->addUniform(normalMatrix);
state->addUniform(new osg::Uniform("ProjectionMatrix", camera->getProjectionMatrix()));
osg::Uniform* modelViewProjectionMatrix = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "ModelViewProjectionMatrix");
modelViewProjectionMatrix->setUpdateCallback(new ModelViewProjectionMatrixCallback(camera));
state->addUniform(modelViewProjectionMatrix);
state->addUniform(new osg::Uniform("LightPosition", viewer->getLight()->getPosition()));
state->addUniform(new osg::Uniform("DiffuseColor", osg::Vec3f(1, 1, 0)));
state->addUniform(new osg::Uniform("LightIntensity", osg::Vec3f(.5, .5, 0)));
root->addChild(geode);
viewer->setSceneData(root);
while(!viewer->done()) {
viewer->frame();
}
return 0;
}
#version 400
in vec3 EyeLightIntensity;
layout(location = 0) out vec4 FragColor;
void main(void) {
FragColor = vec4(EyeLightIntensity, 1.0);
}
#version 400
uniform mat4 ModelViewMatrix;
uniform mat3 NormalMatrix;
uniform mat4 ProjectionMatrix;
uniform mat4 ModelViewProjectionMatrix;
uniform vec4 LightPosition; // Light position in eye coords.
uniform vec3 DiffuseColor; // Diffuse reflectivity
uniform vec3 LightIntensity; // Light source intensity
layout(location = 0) in vec4 Vertex;
layout(location = 1) in vec3 Normal;
layout(location = 2) in vec4 Color;
out vec3 EyeLightIntensity;
void main(void) {
// Convert normal and position to eye coords
vec3 tnorm = normalize(NormalMatrix * Normal);
vec4 eyeCoords = ModelViewMatrix * Vertex;
vec3 s = normalize(vec3(LightPosition - eyeCoords));
// The diffuse shading equation
EyeLightIntensity = LightIntensity * DiffuseColor * max(dot(s, tnorm), 0);
//LightIntensity = vec3(1,0,1) * vec3(1,1,1) * max(dot(s, tnorm), 0);
//LightIntensity = Color * max(dot(s, tnorm), 0);
// Convert position to clip coordinates and pass along
gl_Position = ModelViewProjectionMatrix * Vertex;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment