Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Line Stipple Shader #68

Open
wants to merge 14 commits into
base: develop
Choose a base branch
from
6 changes: 5 additions & 1 deletion src/material.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ RenderableMaterial::RenderableMaterial(Qt3DCore::QNode *parent, VertexShaderType
shader3->setFragmentShaderCode(
Qt3DRender::QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/shaders/monochrome.frag"))));
break;
case (FragmentShaderType::LineStipple):
shader3->setFragmentShaderCode(
Qt3DRender::QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/shaders/line_stipple.frag"))));
break;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the line stipple is to be a fragment shader then we would have to have a version for each type of colouring (e.g. Phong) we want to be "stipplable". Do we think this is the best approach?

Copy link
Collaborator Author

@Pranavya-Vivek Pranavya-Vivek Jul 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay yes! I think I can implement a similar approach to the line stippling code, but using a geometry shader instead. Then we would only need one geometry shader, regardless of how the lines are coloured. I'll add the updated commit here;

case (FragmentShaderType::Phong):
shader3->setFragmentShaderCode(
Qt3DRender::QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/shaders/phong.frag"))));
Expand Down Expand Up @@ -122,4 +126,4 @@ void RenderableMaterial::setSpecular(QColor specular)
{
specular_ = specular;
specularParameter_->setValue(specular_);
}
}
5 changes: 3 additions & 2 deletions src/material.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ class RenderableMaterial : public Qt3DRender::QMaterial
{
Monochrome,
Phong,
PerVertexPhong
PerVertexPhong,
LineStipple
};
explicit RenderableMaterial(Qt3DCore::QNode *parent, VertexShaderType vertexShader, GeometryShaderType geometryShader,
FragmentShaderType fragmentShader);
Expand Down Expand Up @@ -56,4 +57,4 @@ class RenderableMaterial : public Qt3DRender::QMaterial
// Set specular colour component
void setSpecular(QColor specular);
};
} // namespace Mildred
} // namespace Mildred
1 change: 1 addition & 0 deletions src/shaders.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<file>shaders/phong.frag</file>
<file>shaders/phongpervertex.frag</file>
<file>shaders/monochrome.frag</file>
<file>shaders/line_stipple.frag</file>
<file>shaders/line_tesselator.geom</file>
</qresource>
</RCC>
35 changes: 35 additions & 0 deletions src/shaders/line_stipple.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#version 330 core

layout (location = 0) in vec3 position;
out vec4 color;

uniform float line_width;
uniform float line_stipple_factor;
uniform float line_stipple_pattern;


void main() {
float step = 1.0 / line_stipple_factor;
float pattern = mod(position.x * step, line_stipple_pattern);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Relying on the x-coordinate alone will surely break things for completely vertical lines, no?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I see! I can add a second mod() function to check the modulo of the y-coordinate of the position vector with the line stipple pattern. So by changing the condition on line 14, it will allow stippling for vertical lines too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I don't think even that will be enough! We have to think in terms of stippling along the vector of the line we're drawing, rather than a cardinal (screen) direction, otherwise our results won't be consistent.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I’ve come up with a good way to do this using dot products, and by letting the shader take vertex position and texture coordinates as inputs, while outputting the fragment texture coordinates. I'll send you my idea as a commit once I run some tests.

if (pattern > 0.5) {
discard;
}
gl_Position = vec4(position, 1.0);
color = vec4(1.0, 0.0, 0.0, 1.0);
}

// Compile the shader
GLuint shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(shader,1, &shader_source, NULL);
glCompileShader(shader);

// Bind the shader to the current OpenGl context
glUseProgram(shader);

// Set the uniforms
glUniform1f(glGetUniformLocation(shader, "line_width"), 1.0f);
glUniform1i(glGetUniformLocation(shader, "line_stipple_factor"), 1);
glUniform1ui(glGetUniformLocation(shader, "line_stipple_pattern"), 0xFFFF);

// Draw the line
glDrawArrays(GL_LINE_STRIP, 0, 4);