diff --git a/src/material.cpp b/src/material.cpp index 61f28a5..c2070e2 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -62,6 +62,10 @@ RenderableMaterial::RenderableMaterial(Qt3DCore::QNode *parent, VertexShaderType shader3->setGeometryShaderCode( Qt3DRender::QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/shaders/line_tesselator.geom")))); break; + case (GeometryShaderType::LineStipple): + shader3->setGeometryShaderCode( + Qt3DRender::QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/shaders/line_stipple.geom")))); + break; default: throw(std::runtime_error("Unhandled geometry shader type.\n")); } @@ -122,4 +126,4 @@ void RenderableMaterial::setSpecular(QColor specular) { specular_ = specular; specularParameter_->setValue(specular_); -} \ No newline at end of file +} diff --git a/src/material.h b/src/material.h index 04977de..e593118 100644 --- a/src/material.h +++ b/src/material.h @@ -19,7 +19,8 @@ class RenderableMaterial : public Qt3DRender::QMaterial enum class GeometryShaderType { None, - LineTesselator + LineTesselator, + LineStipple }; // Fragment Shader Types enum class FragmentShaderType @@ -56,4 +57,4 @@ class RenderableMaterial : public Qt3DRender::QMaterial // Set specular colour component void setSpecular(QColor specular); }; -} // namespace Mildred \ No newline at end of file +} // namespace Mildred diff --git a/src/shaders.qrc b/src/shaders.qrc index ac06ea9..7663dd7 100644 --- a/src/shaders.qrc +++ b/src/shaders.qrc @@ -6,5 +6,6 @@ shaders/phongpervertex.frag shaders/monochrome.frag shaders/line_tesselator.geom + shaders/line_stipple.geom diff --git a/src/shaders/line_stipple.geom b/src/shaders/line_stipple.geom new file mode 100644 index 0000000..38f942c --- /dev/null +++ b/src/shaders/line_stipple.geom @@ -0,0 +1,79 @@ +#version 330 + +layout(lines) in; +layout(triangle_strip, max_vertices = 4) out; + +// Input Vertex Data +in worldData +{ + vec3 position; + vec3 normal; + vec4 color; +} +vertices[]; + +// Output Fragment Data +out fragData +{ + vec3 position; + vec3 normal; + vec4 color; +} +frag; + +uniform vec2 viewportSize; +uniform float lineWidth = 1.5; + +// Copy clip distances for specified input vertex +void applyClipping(int inVertexID) +{ + gl_ClipDistance[0] = gl_in[inVertexID].gl_ClipDistance[0]; + gl_ClipDistance[1] = gl_in[inVertexID].gl_ClipDistance[1]; + gl_ClipDistance[2] = gl_in[inVertexID].gl_ClipDistance[2]; + gl_ClipDistance[3] = gl_in[inVertexID].gl_ClipDistance[3]; + gl_ClipDistance[4] = gl_in[inVertexID].gl_ClipDistance[4]; + gl_ClipDistance[5] = gl_in[inVertexID].gl_ClipDistance[5]; +} + +void main() +{ + vec4 p1 = gl_in[0].gl_Position; + vec4 p2 = gl_in[1].gl_Position; + + vec2 dir = normalize((p2.xy - p1.xy) * viewportSize); + vec2 offset = vec2(-dir.y, dir.x) * lineWidth / viewportSize; + + // Emit the four corners of our two triangles + gl_Position = p1 + vec4(offset.xy * p1.w, 0.0, 0.0); + applyClipping(0); + frag.position = vec3(gl_Position); + frag.color = vertices[0].color; + frag.normal = vertices[1].normal; + EmitVertex(); + gl_Position = p1 - vec4(offset.xy * p1.w, 0.0, 0.0); + applyClipping(0); + frag.position = vec3(gl_Position); + frag.color = vertices[0].color; + frag.normal = vertices[0].normal; + EmitVertex(); + gl_Position = p2 + vec4(offset.xy * p2.w, 0.0, 0.0); + applyClipping(1); + frag.position = vec3(gl_Position); + frag.color = vertices[1].color; + frag.normal = vertices[1].normal; + EmitVertex(); + gl_Position = p2 - vec4(offset.xy * p2.w, 0.0, 0.0); + applyClipping(1); + frag.position = vec3(gl_Position); + frag.color = vertices[1].color; + frag.normal = vertices[1].normal; + + // To view line-stipple output, remove comment bars (//) from the following two lines + //gl_Position = p1 + vec4(offset.xy * p1.w, 0.0, 0.0); + //applyClipping(0); + + EmitVertex(); + + EndPrimitive(); + +} diff --git a/src/widget.cpp b/src/widget.cpp index bde20f9..fbe1df9 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -195,7 +195,7 @@ Data1DEntity *MildredWidget::addData1D(std::string_view tag) // Add a material auto *material = createMaterial(entity, RenderableMaterial::VertexShaderType::ClippedToDataVolume, - RenderableMaterial::GeometryShaderType::LineTesselator, + RenderableMaterial::GeometryShaderType::LineStipple, RenderableMaterial::FragmentShaderType::PerVertexPhong); entity->setDataMaterial(material); entity->setErrorMaterial(material); @@ -214,4 +214,4 @@ DisplayGroup *MildredWidget::addDisplayGroup() auto newGroup = displayGroups_.emplace_back(std::make_shared()); return newGroup.get(); -} \ No newline at end of file +}