Created
July 13, 2016 20:09
-
-
Save vicrucann/3575301f46ee9702ff7f5af8e4959f56 to your computer and use it in GitHub Desktop.
Similar to the osg-shader-polyline, but with round caps (in development)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Windows.h> | |
#include <osg/Camera> | |
#include <osg/Drawable> | |
#include <osg/Geode> | |
#include <osg/Geometry> | |
#include <osg/Group> | |
#include <osg/Node> | |
#include <osg/NodeVisitor> | |
#include <osg/Object> | |
#include <osg/PrimitiveSet> | |
#include <osg/Program> | |
#include <osg/Shader> | |
#include <osg/StateSet> | |
#include <osg/Transform> | |
#include <osg/Uniform> | |
#include <osgViewer/Viewer> | |
#include <osg/LineWidth> | |
#include <osg/Point> | |
#include <osg/BlendFunc> | |
#include <osgDB/ReadFile> | |
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; | |
}; | |
const int OSG_WIDTH = 1280; | |
const int OSG_HEIGHT = 960; | |
osg::Node* createTestScene() | |
{ | |
osg::Vec3Array* vertices = new osg::Vec3Array; | |
osg::Vec4Array* colors = new osg::Vec4Array; | |
vertices->setName("Vertex"); | |
vertices->push_back(osg::Vec3f(0,1,0)); | |
vertices->push_back(osg::Vec3f(1,1,0)); | |
vertices->push_back(osg::Vec3f(1,1,1)); | |
vertices->push_back(osg::Vec3f(0,1,1)); | |
vertices->push_back(osg::Vec3f(0.5,1,1.5)); | |
vertices->push_back(osg::Vec3f(0.5,1,2)); | |
colors->push_back(osg::Vec4(1,0.3,0,1)); | |
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry; | |
geom->addPrimitiveSet(new osg::DrawArrays(GL_LINE_STRIP, 0, vertices->size())); | |
geom->setUseDisplayList(false); | |
geom->setVertexArray(vertices); | |
geom->setColorArray(colors, osg::Array::BIND_OVERALL); | |
osg::ref_ptr<osg::Geode> geode = new osg::Geode; | |
geode->addDrawable(geom.get()); | |
osg::StateSet* state = geode->getOrCreateStateSet(); | |
state->setMode(GL_LIGHTING, osg::StateAttribute::OFF); | |
state->setMode(GL_BLEND, osg::StateAttribute::ON); | |
state->setMode(GL_LINE_SMOOTH, osg::StateAttribute::ON); | |
osg::LineWidth* lw = new osg::LineWidth; | |
lw->setWidth(10.f); | |
state->setAttribute(lw, osg::StateAttribute::ON); | |
osg::BlendFunc* blendfunc = new osg::BlendFunc(); | |
state->setAttributeAndModes(blendfunc, osg::StateAttribute::ON); | |
return geode.release(); | |
} | |
int main(int, char**) | |
{ | |
::SetProcessDPIAware(); | |
osgViewer::Viewer viewer; | |
osg::Camera* camera = viewer.getCamera(); | |
osg::ref_ptr<osg::Group> root = new osg::Group(); | |
osg::Vec3Array* vertices = new osg::Vec3Array; | |
osg::Vec4Array* colors = new osg::Vec4Array; | |
vertices->setName("Vertex"); | |
vertices->push_back(osg::Vec3f(-1,0,0)); | |
vertices->push_back(osg::Vec3f(0,0,0)); | |
vertices->push_back(osg::Vec3f(1,0,0)); | |
vertices->push_back(osg::Vec3f(1,0,1)); | |
vertices->push_back(osg::Vec3f(0,0,0)); | |
vertices->push_back(osg::Vec3f(1,0,0)); | |
vertices->push_back(osg::Vec3f(1,0,1)); | |
vertices->push_back(osg::Vec3f(0,0,1)); | |
vertices->push_back(osg::Vec3f(1,0,0)); | |
vertices->push_back(osg::Vec3f(1,0,1)); | |
vertices->push_back(osg::Vec3f(0,0,1)); | |
vertices->push_back(osg::Vec3f(0.5,0,1.5)); | |
vertices->push_back(osg::Vec3f(1,0,1)); | |
vertices->push_back(osg::Vec3f(0,0,1)); | |
vertices->push_back(osg::Vec3f(0.5,0,1.5)); | |
vertices->push_back(osg::Vec3f(0.5,0,2)); | |
vertices->push_back(osg::Vec3f(0,0,1)); | |
vertices->push_back(osg::Vec3f(0.5,0,1.5)); | |
vertices->push_back(osg::Vec3f(0.5,0,2)); | |
vertices->push_back(osg::Vec3f(0.5,0,3)); | |
colors->setName("Color"); | |
colors->push_back(osg::Vec4f(0.2, 0.9, 1.0, 1)); | |
colors->push_back(osg::Vec4f(0.8, 0.2, 1.0, 1)); | |
colors->push_back(osg::Vec4f(0.0, 0.7, 1.0, 1)); | |
colors->push_back(osg::Vec4f(0.8, 0.1, 1.0, 1)); | |
colors->push_back(osg::Vec4f(0.8, 0.2, 1.0, 1)); | |
colors->push_back(osg::Vec4f(0.0, 0.7, 1.0, 1)); | |
colors->push_back(osg::Vec4f(0.8, 0.1, 1.0, 1)); | |
colors->push_back(osg::Vec4f(0.2, 0.9, 1.0, 1)); | |
colors->push_back(osg::Vec4f(0.0, 0.7, 1.0, 1)); | |
colors->push_back(osg::Vec4f(0.8, 0.1, 1.0, 1)); | |
colors->push_back(osg::Vec4f(0.2, 0.9, 1.0, 1)); | |
colors->push_back(osg::Vec4f(0.2, 0.9, 1.0, 1)); | |
colors->push_back(osg::Vec4f(0.8, 0.2, 1.0, 1)); | |
colors->push_back(osg::Vec4f(0.0, 0.7, 1.0, 1)); | |
colors->push_back(osg::Vec4f(0.8, 0.1, 1.0, 1)); | |
colors->push_back(osg::Vec4f(0.2, 0.9, 1.0, 1)); | |
colors->push_back(osg::Vec4f(0.8, 0.2, 1.0, 1)); | |
colors->push_back(osg::Vec4f(0.0, 0.7, 1.0, 1)); | |
colors->push_back(osg::Vec4f(0.8, 0.1, 1.0, 1)); | |
colors->push_back(osg::Vec4f(0.2, 0.9, 1.0, 1)); | |
// create geometry | |
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry; | |
geom->addPrimitiveSet(new osg::DrawArrays(GL_LINES_ADJACENCY_EXT, 0, vertices->size())); | |
geom->setUseDisplayList(false); | |
// defaults | |
geom->setVertexArray(vertices); | |
geom->setColorArray(colors, osg::Array::BIND_PER_VERTEX); | |
// set attributes | |
geom->setVertexAttribArray(0, vertices, osg::Array::BIND_PER_VERTEX); | |
geom->setVertexAttribArray(1, colors, osg::Array::BIND_PER_VERTEX); | |
// create shader | |
osg::ref_ptr<osg::Program> program = new osg::Program; | |
program->setName("shader"); | |
// program->addShader(new osg::Shader(osg::Shader::VERTEX, vertSource)); | |
osg::ref_ptr<osg::Shader> vertShader = new osg::Shader(osg::Shader::VERTEX); | |
if (!vertShader->loadShaderSourceFromFile("../osg-shader/polyline.vert")) | |
std::cerr << "Could not read VERTEX shader from file" << std::endl; | |
program->addShader(vertShader); | |
osg::ref_ptr<osg::Shader> geomShader = new osg::Shader(osg::Shader::GEOMETRY); | |
if (!geomShader->loadShaderSourceFromFile("../osg-shader/stroke.geom")) | |
std::cerr << "Could not read GEOMETRY shader from file" << std::endl; | |
program->addShader(geomShader); | |
osg::ref_ptr<osg::Shader> fragShader = new osg::Shader(osg::Shader::FRAGMENT); | |
if (!fragShader->loadShaderSourceFromFile("../osg-shader/polyline.frag")) | |
std::cerr << "Could not read FRAGMENT shader from file" << std::endl; | |
program->addShader(fragShader); | |
// program->addShader(new osg::Shader(osg::Shader::FRAGMENT, fragSource)); | |
// geode | |
osg::ref_ptr<osg::Geode> geode = new osg::Geode; | |
geode->addDrawable(geom.get()); | |
osg::StateSet* state = geode->getOrCreateStateSet(); | |
state->setAttributeAndModes(program.get(), osg::StateAttribute::ON); | |
// add uniforms | |
osg::Uniform* modelViewProjectionMatrix = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "ModelViewProjectionMatrix"); | |
modelViewProjectionMatrix->setUpdateCallback(new ModelViewProjectionMatrixCallback(camera)); | |
state->addUniform(modelViewProjectionMatrix); | |
float Thickness = 7.0; | |
float miterLimit = 0.75; | |
float baseWidth = 0.008; | |
float widthAmplitude = 0.005; | |
state->addUniform(new osg::Uniform("Thickness", Thickness)); | |
osg::Vec2f viewport = osg::Vec2f(OSG_WIDTH, OSG_HEIGHT); | |
state->addUniform(new osg::Uniform("Viewport", viewport)); | |
state->addUniform(new osg::Uniform("MiterLimit", miterLimit)); | |
state->addUniform(new osg::Uniform("BaseWidth", baseWidth)); | |
state->addUniform(new osg::Uniform("WidthAplitude", widthAmplitude)); | |
// state settings | |
state->setMode(GL_LIGHTING, osg::StateAttribute::OFF); | |
state->setMode(GL_BLEND, osg::StateAttribute::ON); | |
state->setMode(GL_LINE_SMOOTH, osg::StateAttribute::ON); | |
osg::LineWidth* lw = new osg::LineWidth; | |
lw->setWidth(10.f); | |
state->setAttribute(lw, osg::StateAttribute::ON); | |
osg::BlendFunc* blendfunc = new osg::BlendFunc(); | |
state->setAttributeAndModes(blendfunc, osg::StateAttribute::ON); | |
// scene state run | |
root->addChild(geode.get()); | |
root->addChild(createTestScene()); | |
viewer.setSceneData(root.get()); | |
viewer.setUpViewInWindow(100,100,OSG_WIDTH, OSG_HEIGHT); | |
// viewer.setUpViewOnSingleScreen(0); | |
return viewer.run(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#version 330 | |
in VertexData{ | |
vec2 mTexCoord; | |
vec4 mColor; | |
} VertexIn; | |
const vec4 testColor = vec4(0.3,1,0,1); | |
void main(void) | |
{ | |
gl_FragColor = vec4(VertexIn.mColor.xy, 0.2, 1); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#version 330 | |
uniform mat4 ModelViewProjectionMatrix; | |
uniform float Thickness; | |
uniform vec2 Viewport; | |
uniform float MiterLimit; | |
uniform float BaseWidth; | |
uniform float WidthAmplitude; | |
const float pi = 3.14159265; | |
const float epsilon = 0.0001; | |
layout(lines_adjacency) in; | |
layout(triangle_strip, max_vertices = 32) out; | |
in VertexData{ | |
vec4 mColor; | |
} VertexIn[4]; | |
out VertexData{ | |
vec2 mTexCoord; | |
vec4 mColor; | |
} VertexOut; | |
void ClipLineSegmentToNearPlane(mat4 MVP, vec4 P0, vec4 P1, vec4 P2, vec4 P3, | |
out vec4 p0, out vec4 p1, out vec4 p2, out vec4 p3, out bool isCulled) | |
{ | |
const float nearPlaneDistance = 0.5; | |
p1 = MVP * P1; | |
p2 = MVP * P2; | |
isCulled = false; | |
float distanceToP1 = p1.z + nearPlaneDistance; | |
float distanceToP2 = p2.z + nearPlaneDistance; | |
if ((distanceToP1 * distanceToP2) < 0.0) { | |
float t = distanceToP1 / (distanceToP1 - distanceToP2); | |
vec3 modelV = vec3(P1) + t * (vec3(P2) - vec3(P1)); | |
vec4 clipV = MVP * vec4(modelV, 1); | |
if (distanceToP1 < 0.0) { | |
p1 = clipV; | |
p0 = p1; | |
p3 = MVP * P3; | |
} | |
else { | |
p2 = clipV; | |
p3 = p2; | |
p0 = MVP * P0; | |
} | |
} | |
else if (distanceToP1 < 0.0){ | |
isCulled = true; | |
} | |
else { | |
p0 = MVP * P0; | |
p3 = MVP * P3; | |
} | |
} | |
void halfDiscStrip(vec2 dir, float sign, vec3 center, float radius, vec4 color) | |
{ | |
const int divs = 8; | |
const int nps = divs+1; | |
vec2 ps[nps]; | |
float da = sign*pi/divs; | |
vec2 rot_x = vec2(cos(da), -sin(da)); | |
vec2 rot_y = vec2(sin(da), cos(da)); | |
int i; | |
ps[0] = dir; | |
for(i=1; i<nps; ++i) { | |
ps[i] = vec2(dot(ps[i-1], rot_x), dot(ps[i-1], rot_y)); | |
} | |
int j; | |
for(i=0, j=(nps-1); i<(nps/2); ++i, --j) { | |
vec2 this_pos = ps[i]; | |
this_pos *= radius; | |
this_pos += center.xy; | |
gl_Position = vec4( this_pos, center.z, 1.0); | |
VertexOut.mColor = color; | |
EmitVertex(); | |
this_pos = ps[j]; | |
this_pos *= radius; | |
this_pos += center.xy; | |
gl_Position = vec4(this_pos, center.z, 1.0); | |
VertexOut.mColor = color; | |
EmitVertex(); | |
} | |
if(nps % 2 == 1) { | |
vec2 this_pos = ps[nps/2]; | |
this_pos *= radius; | |
this_pos += center.xy; | |
gl_Position = vec4(this_pos, center.z, 1.0); | |
VertexOut.mColor = color; | |
EmitVertex(); | |
} | |
} | |
void main(void) | |
{ | |
// 4 points | |
vec4 P0 = gl_in[0].gl_Position; | |
vec4 P1 = gl_in[1].gl_Position; | |
vec4 P2 = gl_in[2].gl_Position; | |
vec4 P3 = gl_in[3].gl_Position; | |
int i; | |
vec4 p0; | |
vec4 p1; | |
vec4 p2; | |
vec4 p3; | |
bool isCulled; | |
ClipLineSegmentToNearPlane(ModelViewProjectionMatrix, P0, P1, P2, P3, p0, p1, p2, p3, isCulled); | |
if (isCulled) return; | |
p0.xyz /= p0.w; | |
p1.xyz /= p1.w; | |
p2.xyz /= p2.w; | |
p3.xyz /= p3.w; | |
float length_a = BaseWidth + WidthAmplitude * VertexIn[1].mColor.a; | |
float length_b = BaseWidth + WidthAmplitude * VertexIn[2].mColor.a; | |
if(p1 == p2){ | |
halfDiscStrip(vec2(1.0, 0.0), 1.0, p2.xyz, length_a, VertexIn[1].mColor); | |
EndPrimitive(); | |
halfDiscStrip(vec2(1.0, 0.0), -1.0, p2.xyz, length_a, VertexIn[1].mColor); | |
} | |
else { | |
vec2 direction = normalize(p2.xy - p1.xy); | |
vec2 normal = vec2(direction.y, -direction.x); | |
vec2 direction_before, direction_after, normal_after; | |
float a_before, sign_before, recul_before, a_after, sign_after, recul_after; | |
bool start = false; | |
bool end = false; | |
bool u_turn_before = false; | |
bool u_turn_after = false; | |
if(p1 != p0) | |
{ | |
direction_before = normalize(p1.xy - p0.xy); | |
a_before = acos(clamp(dot(direction, direction_before), -1.0, 1.0)); | |
sign_before = sign(dot(normal, direction_before)); | |
if(sign_before != -1.0 && sign_before != 1.0) sign_before = 1.0; | |
if(a_before < epsilon) | |
{ | |
recul_before = 0.0; | |
} | |
else if(a_before > pi/2.0) | |
{ | |
recul_before = 0.0; | |
u_turn_before = true; | |
} | |
else | |
recul_before = length_a/tan((pi-a_before)/2.0); | |
} | |
else | |
{ | |
direction_before = vec2(0.0, 0.0); | |
a_before = 0.0; | |
sign_before = 1.0; | |
recul_before = 0.0; | |
start = true; | |
} | |
if(p2 != p3) | |
{ | |
direction_after = normalize(p3.xy - p2.xy); | |
normal_after = vec2(direction_after.y, -direction_after.x); | |
a_after = acos(clamp(dot(direction, direction_after), -1.0, 1.0)); | |
sign_after = sign(dot(normal, direction_after)); | |
if(sign_after != -1.0 && sign_after != 1.0) sign_after = 1.0; | |
if(a_after < epsilon) | |
{ | |
recul_after = 0.0; | |
} | |
else if(a_after > pi/2.0) //u turn | |
{ | |
u_turn_after = true; | |
recul_after = 0.0; | |
} | |
else | |
recul_after = length_b/tan((pi-a_after)/2.0); | |
} | |
else | |
{ | |
direction_after = vec2(0.0, 0.0); | |
normal_after = vec2(0.0, 0.0); | |
a_after = 0.0; | |
sign_after = 1.0; | |
recul_after = 0.0; | |
end = true; | |
} | |
if(start == true) | |
{ | |
halfDiscStrip(normal, -1.0, p1.xyz, length_a, VertexIn[1].mColor); | |
EndPrimitive(); | |
gl_Position = vec4(p1.xy - (normal * length_a * sign_after), p1.z, 1.0); | |
VertexOut.mColor = VertexIn[1].mColor; | |
EmitVertex(); | |
gl_Position = vec4(p1.xy + (normal * length_a * sign_after), p1.z, 1.0); | |
VertexOut.mColor = VertexIn[1].mColor; | |
EmitVertex(); | |
} | |
else if(u_turn_before == true) | |
{ | |
gl_Position = vec4(p1.xy - (normal * length_a * sign_after), p1.z, 1.0); | |
VertexOut.mColor = VertexIn[1].mColor; | |
EmitVertex(); | |
gl_Position = vec4(p1.xy + (normal * length_a * sign_after), p1.z, 1.0); | |
VertexOut.mColor = VertexIn[1].mColor; | |
EmitVertex(); | |
} | |
else | |
{ | |
if(recul_before != 0.0) | |
{ | |
gl_Position = vec4(p1.xy, p1.z, 1.0); | |
VertexOut.mColor = VertexIn[1].mColor; | |
EmitVertex(); | |
} | |
if(sign_before != sign_after) | |
{ | |
gl_Position = vec4(p1.xy + (normal * length_a * sign_before), p1.z, 1.0); | |
VertexOut.mColor = VertexIn[1].mColor; | |
EmitVertex(); | |
gl_Position = vec4(p1.xy - (normal * length_a * sign_before) + direction * recul_before, p1.z, 1.0); | |
VertexOut.mColor = VertexIn[1].mColor; | |
EmitVertex(); | |
} | |
else | |
{ | |
gl_Position = vec4(p1.xy - (normal * length_a * sign_before) + direction * recul_before, p1.z, 1.0); | |
VertexOut.mColor = VertexIn[1].mColor; | |
EmitVertex(); | |
gl_Position = vec4(p1.xy + (normal * length_a * sign_before), p1.z, 1.0); | |
VertexOut.mColor = VertexIn[1].mColor; | |
EmitVertex(); | |
} | |
} | |
if(end == true) | |
{ | |
gl_Position = vec4(p2.xy - (normal * length_b * sign_after), p2.z, 1.0); | |
VertexOut.mColor = VertexIn[2].mColor; | |
EmitVertex(); | |
gl_Position = vec4(p2.xy + (normal * length_b * sign_after), p2.z, 1.0); | |
VertexOut.mColor = VertexIn[2].mColor; | |
EmitVertex(); | |
EndPrimitive(); | |
halfDiscStrip(normal, 1.0, p2.xyz, length_b, VertexIn[2].mColor); | |
} | |
else if(u_turn_after == true) | |
{ | |
gl_Position = vec4(p2.xy - (normal * length_b * sign_after), p2.z, 1.0); | |
VertexOut.mColor = VertexIn[2].mColor; | |
EmitVertex(); | |
gl_Position = vec4(p2.xy + (normal * length_b * sign_after), p2.z, 1.0); | |
VertexOut.mColor = VertexIn[2].mColor; | |
EmitVertex(); | |
} | |
else | |
{ | |
gl_Position = vec4(p2.xy - (normal * length_b * sign_after), p2.z, 1.0); | |
VertexOut.mColor = VertexIn[2].mColor; | |
EmitVertex(); | |
gl_Position = vec4(p2.xy + (normal * length_b * sign_after) - (direction * recul_after), p2.z, 1.0); | |
VertexOut.mColor = VertexIn[2].mColor; | |
EmitVertex(); | |
if(recul_after != 0.0) | |
{ | |
gl_Position = vec4(p2.xy, p2.z, 1.0); | |
VertexOut.mColor = VertexIn[2].mColor; | |
EmitVertex(); | |
} | |
} | |
if(recul_after != 0.0 || u_turn_after) | |
{ | |
EndPrimitive(); | |
gl_Position = vec4(p2.xy - (normal * length_b * sign_after), p2.z, 1.0); | |
VertexOut.mColor = VertexIn[2].mColor; | |
EmitVertex(); | |
float da = -sign_after*a_after/3.0; | |
vec2 rot_x = vec2(cos(da), -sin(da)); | |
vec2 rot_y = vec2(sin(da), cos(da)); | |
vec2 new_normal1 = vec2(dot((-normal*sign_after), rot_x), dot((-normal*sign_after), rot_y)); | |
gl_Position = vec4(p2.xy + (new_normal1 * length_b), p2.z, 1.0); | |
VertexOut.mColor = VertexIn[2].mColor; | |
EmitVertex(); | |
gl_Position = vec4(p2.xy, p2.z, 1.0); | |
VertexOut.mColor = VertexIn[2].mColor; | |
EmitVertex(); | |
vec2 new_normal2 = vec2(dot(new_normal1, rot_x), dot(new_normal1, rot_y)); | |
gl_Position = vec4(p2.xy + (new_normal2 * length_b), p2.z, 1.0); | |
VertexOut.mColor = VertexIn[2].mColor; | |
EmitVertex(); | |
gl_Position = vec4(p2.xy - (normal_after * length_b * sign_after), p2.z, 1.0); | |
VertexOut.mColor = VertexIn[2].mColor; | |
EmitVertex(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#version 330 | |
uniform mat4 ModelViewProjectionMatrix; | |
layout(location = 0) in vec4 Vertex; | |
layout(location = 1) in vec4 Color; | |
out VertexData{ | |
vec4 mColor; | |
} VertexOut; | |
void main(void) | |
{ | |
VertexOut.mColor = Color; | |
gl_Position = ModelViewProjectionMatrix * Vertex; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment