DiscussionsIssue archiveVisualization and 3D Viewer

Archived discussion

Custom shader for selection

Visualization and 3D ViewerFri, 04/05/2024 - 16:396 replies

Browse this forum
QuestionAuthor

Hello here.
I'm trying to write a custom shader to display selected faces of drawn shapes through the drawer retrieved by myInteractiveContext->HighlightStyle(Prs3d_TypeOfHighlight_LocalSelected).

I want to draw some kind of hatch pattern on selected faces through a shader program.
I'd like to draw diagonal lines that doesn't depends on the view orientation / zoom ...
I need to be able to change the hatch pattern color at any time.

In the "selface.png" attached picture, you can see what I'd like to achieve with the black color.

What I'm actually able to do can be seen in the "selface2.png" attached picture.

Here is how I could achieve this result.

public: void SetSelectionColor(float r, float g, float b)
{
    Graphic3d_ShaderObject vertexShader = Graphic3d_ShaderObject::CreateFromFile(Graphic3d_TypeOfShaderObject::Graphic3d_TOS_VERTEX, "D:\\vshader.glsl");
    Graphic3d_ShaderObject fragmentShader = Graphic3d_ShaderObject::CreateFromFile(Graphic3d_TypeOfShaderObject::Graphic3d_TOS_FRAGMENT, "D:\\fshader.glsl");

    Handle(Graphic3d_ShaderProgram) shaderProgram = new Graphic3d_ShaderProgram();
    shaderProgram->AttachShader(vertexShader);
    shaderProgram->AttachShader(fragmentShader );	
    shaderProgram->PushVariableVec4("selectionColor", Graphic3d_Vec4(r, g, b, 1));

    Handle(Prs3d_Drawer) drawer = myInteractiveContext->HighlightStyle(Prs3d_TypeOfHighlight_LocalSelected).
    drawer->ShadingAspect()->Aspect()->SetShaderProgram(shaderProgram);
}

The vertex shader file:

varying vec4 vertexPos;

void main()
{
    vertexPos = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;
    gl_Position = vertexPos;
}

The fragment shader file:

varying vec4 vertexPos;
uniform vec4 selectionColor;

void main()
{
    if (floor(mod(aPosition.x * 1000, 10)) == 1)
    {
        occFragColor = selectionColor;
    }
    else
    {
        discard;
    }
}

The problems I encounter here is that:

1 - I need to pass the vertexPos variable from the vertex shader to the fragment shader because, I don't know why, I can't access to any "occ" variables (occVertex / occProjectionMatrix ...). Is there something I'm missing ?

1 - I don't know how to retrieve screen coordinates of each vertex to draw lines correctly and regardless of the camera eye. Do anyone has a tip for me ?

2 - If I call the method, then select a face, the selection performs like in the "selface2.png", OK, but if I enter the method to change the selection color, the lines color are not updated and, whereas I unselect and reselect this face, it will always be filled using the previous color. If a select another face, NP, the color is effective in the shader program. What am I missing here ?

Thank you for those who can answer to me :)

Discussion

6 archived replies

Posts are displayed in their archived order.

01Author

sorry, I went to fast to post the message. in the fragment shader, it's not aPosition but vertexPos.
In fact, I'm really near of what I want to do, the only thing is the update color problem...

02Author

nevermind, everything is now working perfectly ^^

03Commenter-1

Hi Author,
I tried the same code you shared in the thread, Even i changed "if (floor(mod(vertexPos.x * 1000, 10)) == 1)." fragment shader.
But unfortunately it does not work. I don't see any changes in both selection and highlight. Am i missing anything ?

04Author

Hi Commenter-1.

Try something like this (I changed to use a string program instead of loading a file):

SelectionController.h

class SelectionController
{
    private:
    Handle(Graphic3d_ShaderProgram) selectionShaderProgram;
    Handle(Graphic3d_ShaderObject) vertexShaderObject;
    Handle(Graphic3d_ShaderObject) fragmentShaderObject;

    TCollection_AsciiString vertexShader;
    TCollection_AsciiString fragmentShader;

    public:
    void InitSelectionShaders();
    void SetSelectionColor(double r, double g, double b, Handle(AIS_InteractiveContext) interactiveContext);
}

SelectionController.cpp

void SelectionController::InitSelectionShaders()
{
    this->selectionShaderProgram = new Graphic3d_ShaderProgram();
    this->selectionShaderProgram->SetAlphaTest(true);

    this->vertexShader =
        EOL"void main()"
        EOL"{"
        EOL"    gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
        EOL"}";

    this->fragmentShader =
        EOL"uniform vec4 selectionColor;"
        EOL"void main()"
        EOL"{"
        EOL"    float modResult = mod(gl_FragCoord.x, 10);"
        EOL"    if (modResult >= 0 && modResult < 2)"
        EOL"    {"
        EOL"        occFragColor = selectionColor;"
        EOL"    }"
        EOL"    else"
        EOL"    {"
        EOL"        discard;"
        EOL"    }"
        EOL"}";

    this->vertexShaderObject = Graphic3d_ShaderObject::CreateFromSource(Graphic3d_TypeOfShaderObject::Graphic3d_TOS_VERTEX, this->vertexShader);
    this->fragmentShaderObject = Graphic3d_ShaderObject::CreateFromSource(Graphic3d_TypeOfShaderObject::Graphic3d_TOS_FRAGMENT, this->fragmentShader);

    this->selectionShaderProgram->AttachShader(this->vertexShaderObject);
    this->selectionShaderProgram->AttachShader(this->fragmentShaderObject);
}

void SelectionController::SetSelectionColor(double r, double g, double b, Handle(AIS_InteractiveContext) interactiveContext)
{
    Quantity_Color selectionColor = Quantity_Color(r, g, b, Quantity_TypeOfColor::Quantity_TOC_sRGB);
    const Handle(Prs3d_Drawer) selectionStyle = interactiveContext->HighlightStyle(Prs3d_TypeOfHighlight_Selected);
    selectionStyle->SetColor(selectionColor);

    interactiveContext->SetHighlightStyle(Prs3d_TypeOfHighlight_Selected, selectionStyle);

    const Handle(Prs3d_Drawer) selectionStyleLocal = interactiveContext->HighlightStyle(Prs3d_TypeOfHighlight_LocalSelected);
    selectionStyleLocal->SetDisplayMode(AIS_DisplayMode::AIS_Shaded);
    selectionStyleLocal->SetColor(selectionColor);

    this->selectionShaderProgram->ClearVariables();
    this->selectionShaderProgram->PushVariableVec4("selectionColor", Graphic3d_Vec4(r, g, b, 1));

    selectionStyleLocal->ShadingAspect()->Aspect()->SetShaderProgram(this->selectionShaderProgram);
    selectionStyleLocal->ShadingAspect()->Aspect()->SetFaceCulling(Graphic3d_TypeOfBackfacingModel::Graphic3d_TypeOfBackfacingModel_BackCulled);

    interactiveContext->SetHighlightStyle(Prs3d_TypeOfHighlight_LocalSelected, selectionStyleLocal);
}

Note: You will have to add needed includes

05Commenter-1

Hi Author,
Thanks a lot for sharing detailed code. It works.

06Author

Cool, I was not sure it would work so well at first try xD