【问题标题】:Setting highlight to an image in OpenGL shader language在 OpenGL 着色器语言中为图像设置高光
【发布时间】:2026-01-06 09:45:01
【问题描述】:

我正在尝试为当前被鼠标覆盖的图像设置高光遮罩。我的问题是,不是将蒙版设置到图像的所有角落,而是将其设置到左上角。 这是我的着色器:

string vertexShaderSource = @"
            #version 140

            uniform mat4 modelview_matrix;            
            uniform mat4 projection_matrix;

            // incoming
            in vec3 vertex_position;
            in vec2 i_texCoord;
            in vec4 i_highlightColor;

            //outgoing
            out vec2 o_texCoord;
            out vec4 o_highlightColor;

            void main(void)
            {
              gl_Position = projection_matrix * modelview_matrix * vec4( vertex_position, 1 );
              o_texCoord = i_texCoord;
              o_highlightColor = i_highlightColor;
            }";

            string fragmentShaderSource = @"
            #version 140

            precision highp float;

            in vec2 o_texCoord;
            in vec4 o_highlightColor;
            out vec4 out_frag_color;
            uniform sampler2D s_texture;

            void main(void)
            {
              out_frag_color = texture( s_texture, o_texCoord ) + o_highlightColor;
              if(out_frag_color.a == 0.0)
                discard;
            }";

这就是我将高亮颜色传输到显卡的方式:

        float[] highlightColor = new float[myList.Count * 4];
        int count = 0;
        float[] noHighlight = new float[4] { 0.0f, 0.0f, 0.0f, 0.0f };
        float[] yesHighlight = new float[4] { 1.0f, 0.0f, 0.0f, 0.3f };
        foreach (GameObject go in myList)
        {
            ...
            for (int i = 0; i < 4; i++)
            {
                if (go.currentlyHovered)
                    highlightColor[count * 4 + i] = yesHighlight[i];
                else
                    highlightColor[count * 4 + i] = noHighlight[i];
            }
            ...
            count++;
        }
...
GL.BindBuffer(BufferTarget.ArrayBuffer, highlightColorLocation);
            GL.BufferData<float>(BufferTarget.ArrayBuffer,
                new IntPtr(highlightColor.Length * sizeof(float)),
                highlightColor, BufferUsageHint.StaticDraw);
            GL.EnableVertexAttribArray(2);
            GL.BindAttribLocation(shaderProgramHandle, 2, "i_highlightColor");
            GL.VertexAttribPointer(2, 4, VertexAttribPointerType.Float, false, OpenTK.Vector4.SizeInBytes, 0);
...

似乎我只将高亮颜色发送到一个顶点,但为什么呢?我认为 glsl 中的“in”修饰符导致数据被发送到每个顶点......有趣的是,当我用“+ vec4(1.0,0.0,0.0,0.3)”替换我的fargment着色器中的“+ o_highlightColor”时然后灯光覆盖整个图像!

【问题讨论】:

    标签: opengl graphics glsl


    【解决方案1】:

    似乎我忽略了这样一个事实,即为了将高光应用到整个四边形,我需要将高光数据发送到所有 4 个顶点,而不仅仅是像上面的一个。在每个渲染帧中,每个对象总共将有 16 个浮点数,以便在对象的整个区域上应用一致的高光。

    float[] highlightColor = new float[myList.Count * 16];
            int count = 0;
            float[] noHighlight = new float[4] { 0.0f, 0.0f, 0.0f, 0.0f };
            float[] yesHighlight = new float[4] { 1.0f, 0.0f, 0.0f, 0.3f };
            foreach (GameObject go in myList)
            {
                ...
                for (int i = 0; i < 16; i++)
                {
                    if (go.currentlyHovered)
                        highlightColor[count * 16 + i] = yesHighlight[i % 4];
                    else
                        highlightColor[count * 16 + i] = noHighlight[i % 4];
                }
                ...
                count++;
            }
    

    【讨论】: