Понизьте фрагментный шейдер GLSL до минимально возможной версии (по крайней мере, GLSL 3.3) - PullRequest
1 голос
/ 30 января 2020

Добрый день для всех.

Я пытаюсь сделать Node Based Editor, для конкретной c цели. Поэтому для начала я позаимствовал стиль сетки ortographi c, используемый Unreal Engine 4 Blueprint Editor. И написать для этого простой фрагментный шейдер. Поскольку мне действительно не нужна информация о вершинах из сетки, она просто рисуется в центральной точке, поэтому я двигаюсь правой кнопкой мыши и передаю ее в шейдер. Как я могу понизить этот шейдер до минимально возможной версии по причинам совместимости, по крайней мере, до GLSL 3.3? Я использую C# и OpenTK для этого.

Помогите пожалуйста. Буду рад любым советам о том, как сделать этот шейдер более эффективным.

Рисование четырехугольника для сетки и использование шейдера:

GL.UseProgram(BasicProgramID);
GL.Uniform1(0, 16); //x cell size
GL.Uniform1(1, 16); //y cell size
// center point that controlled by mouse, invert y - axis, because shader draw from left bottom, idk why=(
GL.Uniform2(2, CenterPos.X , glControl1.Height - CenterPos.Y); 

//prevent screen quad to move by other transformations
GL.MatrixMode(MatrixMode.Modelview); 
GL.PushMatrix();
GL.LoadIdentity();

GL.Begin(PrimitiveType.Quads); //sorry for that deprecated method=) that's simplier to test app 
     GL.Color3(0, 0, 0);
     GL.Vertex2(0.0f, 0.0f);
     GL.Vertex2(glControl1.Width, 0.0f);
     GL.Vertex2(glControl1.Width, glControl1.Height);
     GL.Vertex2(0.0f, glControl1.Height);
GL.End();
GL.PopMatrix();

GL.UseProgram(0);

Фрагмент сетки Шейдер:

#version 430

layout(location = 0) uniform int grid_dx;
layout(location = 1) uniform int grid_dy;
layout(location = 2) uniform vec2 grid_center;

out vec4 frag_color;

vec4 CenterAxisColor = vec4(0.0, 0.0, 0.0, 1.0);
vec4 BackgroundColor = vec4(0.15, 0.15, 0.15, 1.0);
vec4 InnerLinesColor = vec4(0.2, 0.2, 0.2, 1.0);
vec4 SectionBorderColor = vec4(0.09, 0.09, 0.09, 0.15); 

void main() {  
    if ((int(gl_FragCoord.x) == int(grid_center.x))||(int(gl_FragCoord.y) == int(grid_center.y)))
        frag_color = CenterAxisColor;
    else if((int(gl_FragCoord.x - grid_center.x) % (grid_dx * 8) == 0)||(int(gl_FragCoord.y - grid_center.y) % (grid_dy * 8) == 0))
        frag_color = SectionBorderColor;
    else if ((int(gl_FragCoord.x - grid_center.x) % grid_dx == 0)||(int(gl_FragCoord.y - grid_center.y) % grid_dy == 0))
        frag_color = InnerLinesColor;
    else 
        frag_color = BackgroundColor;
}

ОБНОВЛЕНИЕ

В предыдущей версии шейдера было много ошибок и нет возможности использовать масштабирование и настройку. Поэтому я решил выложить окончательную версию с комментариями здесь.

#version 150

// Shader creates orthorgaphic grid like in Unreal Engine 4 Blueprint Editor.
// You can change parameters to create custom look and don't have problems with copyright.
// I dont provide lines thickness, because I would have to use a more cumbersome method for rendering.
// Even with one pixel size it works very accurate, because of straight lines and integer coordinates.
// You can do with that code what you want. I hope this helps someone. 

 // set top-left origin for window coordinates and moves the (x, y) value returned by gl_FragCoord of (0.5, 0.5) by default, to (0.0, 0.0)
layout (origin_upper_left, pixel_center_integer) in vec4 gl_FragCoord;

 // out pixel color. Set current pixel color for every shader call.
out vec4 frag_color;

// position of grid center. Used to pan grid. Just pass mouse position, when right mouse button pressed, for example.
uniform vec2 grid_center; 

// smallest cell size. Used to set grid zoom. By default in UE4 16px, with zoom changes to 14, 12, 10 etc.
uniform ivec2 cell_size = ivec2(16, 16); 

// you can also pass parameters in shader presented below just add "uniform"

// count of cells in section.
ivec2 cell_count = ivec2(8, 8); 

// all colors. By default like in UE4 Blueprint Editor
vec4 BackgroundColor = vec4(0.15, 0.15, 0.15, 1.0);
vec4 CenterAxisColor = vec4(0.0, 0.0, 0.0, 1.0);
vec4 InnerLinesColor = vec4(0.2, 0.2, 0.2, 1.0);
vec4 SectionBorderColor = vec4(0.09, 0.09, 0.09, 0.15); 

void main() {  
    frag_color = BackgroundColor; // set back color first and check other situations

    // check if that grid center?
    if ((gl_FragCoord.x == grid_center.x)||(gl_FragCoord.y == grid_center.y)) 
    {
         frag_color = CenterAxisColor;
    } 
    else 
    {
        //upper-right sections
        if ((gl_FragCoord.x >= grid_center.x) && (gl_FragCoord.y <= grid_center.y)) // that pixel in correct part, relative to the center?
            if(((int(gl_FragCoord.x - grid_center.x) % (cell_size.x * cell_count.x)) == 0)|| ((int(grid_center.y - gl_FragCoord.y) % (cell_size.y * cell_count.y)) == 0)) // that pixel lay on section border?
                frag_color = SectionBorderColor;
            else if(((int(gl_FragCoord.x - grid_center.x) % cell_size.x) == 0)|| ((int(grid_center.y - gl_FragCoord.y) % cell_size.y) == 0)) // that pixel lay on section divider-line?
                    frag_color = InnerLinesColor;

        //bottom-right sections
        if ((gl_FragCoord.x >= grid_center.x) && (gl_FragCoord.y >= grid_center.y)) // etc...
            if(((int(gl_FragCoord.x - grid_center.x) % (cell_size.x * cell_count.x)) == 0)|| ((int(gl_FragCoord.y - grid_center.y) % (cell_size.y * cell_count.y)) == 0)) 
                frag_color = SectionBorderColor;
            else if(((int(gl_FragCoord.x - grid_center.x) % cell_size.x) == 0)|| ((int(gl_FragCoord.y - grid_center.y) % cell_size.y) == 0)) 
                    frag_color = InnerLinesColor;

        //bottom-left sections
        if ((gl_FragCoord.x <= grid_center.x) && (gl_FragCoord.y >= grid_center.y))
            if(((int(grid_center.x - gl_FragCoord.x) % (cell_size.x * cell_count.x)) == 0)|| ((int(gl_FragCoord.y - grid_center.y) % (cell_size.y * cell_count.y)) == 0)) 
                frag_color = SectionBorderColor;
            else if(((int(grid_center.x - gl_FragCoord.x) % cell_size.x) == 0)|| ((int(gl_FragCoord.y - grid_center.y) % cell_size.y) == 0)) 
                    frag_color = InnerLinesColor;

        //upper-left sections
        if ((gl_FragCoord.x <= grid_center.x) && (gl_FragCoord.y <= grid_center.y))
            if(((int(grid_center.x - gl_FragCoord.x) % (cell_size.x * cell_count.x)) == 0)|| ((int(grid_center.y - gl_FragCoord.y) % (cell_size.y * cell_count.y)) == 0)) 
                frag_color = SectionBorderColor;
            else if(((int(grid_center.x - gl_FragCoord.x) % cell_size.x) == 0)|| ((int(grid_center.y - gl_FragCoord.y) % cell_size.y) == 0)) 
                    frag_color = InnerLinesColor;
    }
}

Скриншот работы шейдера

1 Ответ

1 голос
/ 30 января 2020

Если вы хотите использовать GL.Begin / Gl.End последовательностей, то вам необходимо использовать вершинный шейдер GLSL 1.20 и встроенные атрибуты вершин gl_Vertex, gl_Normal, gl_Color и gl_MultiTexCoord0.


В любом случае Язык затенения OpenGL 3.30 не поддерживает расположение Спецификатор макета для единообразных переменных (кроме включения расширение GL_ARB_explicit_uniform_location).

Необходимо удалить расположение макета (layout(location = 0)). Получите расположение универсальной переменной с помощью GL.GetUniformLocation после связывания программы.

#version 330

uniform int grid_dx;
uniform int grid_dy;
uniform vec2 grid_center;

out vec4 frag_color;

vec4 CenterAxisColor = vec4(0.0, 0.0, 0.0, 1.0);
vec4 BackgroundColor = vec4(0.15, 0.15, 0.15, 1.0);
vec4 InnerLinesColor = vec4(0.2, 0.2, 0.2, 1.0);
vec4 SectionBorderColor = vec4(0.09, 0.09, 0.09, 0.15); 

void main() {  
    if ((int(gl_FragCoord.x) == int(grid_center.x))||(int(gl_FragCoord.y) == int(grid_center.y)))
        frag_color = CenterAxisColor;
    else if((int(gl_FragCoord.x - grid_center.x) % (grid_dx * 8) == 0)||(int(gl_FragCoord.y - grid_center.y) % (grid_dy * 8) == 0))
        frag_color = SectionBorderColor;
    else if ((int(gl_FragCoord.x - grid_center.x) % grid_dx == 0)||(int(gl_FragCoord.y - grid_center.y) % grid_dy == 0))
        frag_color = InnerLinesColor;
    else 
        frag_color = BackgroundColor;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...