opengl - 为什么这个 glsl 着色器在尝试使用该程序时会导致 "Invalid Operation"?

标签 opengl glsl shader core

我正在检查日志,一切都编译正常。着色器看起来像这样:

顶点:

#version 330 core
layout(location = 0) in struct InData {
    vec3 position;
    vec4 color;
} inData;
out struct OutData {
    vec3 position;
    vec4 color;
} outData;
void main()
{  
    outData.position = inData.position;
    outData.color = inData.color;
}

片段:

#version 330 core
in struct InData {
    vec2 position;
    vec4 color;
} inData;
out vec4 color;
void main(){
    color = inData.color;
}

我正在像这样准备着色器:

    public Shader(string src, ShaderType type)
    {

        shaderId = GL.CreateShader(type);
        GL.ShaderSource(shaderId, GetShader(src));
        GL.CompileShader(shaderId);
        EventSystem.Log.Message(GL.GetShaderInfoLog(shaderId));
        EventSystem.Log.Message("GLERROR: " + GL.GetError());
        packs = new List<ShaderPack>();
    }
    public void Attach(ShaderPack pack)
    {
        packs.Add(pack);
        GL.AttachShader(pack.ProgramID, shaderId);
        EventSystem.Log.Message(GL.GetProgramInfoLog(pack.ProgramID));
        EventSystem.Log.Message("GLERROR: " + GL.GetError());
    }

然后我编译着色器:

    public void Compile()
    {
        if(program >= 0)
            GL.DeleteProgram(program);
        program = GL.CreateProgram();
        foreach (var s in shaders.Values)
            s.Attach(this);
        EventSystem.Log.Message(GL.GetProgramInfoLog(program));
        EventSystem.Log.Message("GLERROR: " + GL.GetError());
    }

然后我尝试使用它:

        mesh = new Mesh();
        mesh.AddTriangle(
            new Vector3(0, 0, 0), new Vector4(1, 0, 0, 1),
            new Vector3(0, sizeY, 0), new Vector4(0, 1, 0, 1),
            new Vector3(sizeX, sizeY, 0), new Vector4(0, 0, 1, 1));
        mesh.RefreshBuffer();
        
        shaderPack.Apply();
        shaderPack.SetVertexAttribute<Mesh.MeshData1>("vertex", 0, mesh.meshData);
        EventSystem.Log.Message("GLERROR: " + GL.GetError());

在Apply中调用GL.UseProgram并且GetError返回“无效操作”

更新:

好的,我更改了代码:

    public void Compile()
    {
        if(program >= 0)
            GL.DeleteProgram(program);
        program = GL.CreateProgram();
        foreach (var s in shaders.Values)
            s.Attach(this);
       // GL.LinkProgram(program);
        //GL.ValidateProgram(program);

        GL.ValidateProgram(program);
        EventSystem.Log.Message("Validate: " + GL.GetProgramInfoLog(program) + " - " + GL.GetError());
    }
    public void Apply()
    {
        
        GL.UseProgram(program);
        EventSystem.Log.Message("GLERROR (Apply): " + GL.GetError());
    }

输出是

[23:25:55][Log]: Validate: - NoError

[23:25:55][Log]: GLERROR (Apply): InvalidOperation

编辑:好的,我更改了顶点着色器:

#version 330 core
layout(location = 0) in struct InData {
    vec3 position;
    vec4 color;
} inData;
void main()
{  
    gl_Position = vec4(inData.position, 1);
}

...

#version 330 core
//in struct InData {
//    vec2 position;
//    vec4 color;
//} inData;
out vec4 color;

void main(){
    color = vec4(1,0,0,1);
}

它编译没有错误,但我有一个空白屏幕......


预回滚:


编辑:好的,我怀疑问题出在这里:

    public void VertexAttribute<T>(int loc, ShaderPack p, T[] dataArray) where T : struct
    {
        int buf;
        GL.GenBuffers(1, out buf);
        GL.BindBuffer(BufferTarget.ArrayBuffer, buf);
        GL.BufferData<T>(BufferTarget.ArrayBuffer, (IntPtr)(dataArray.Length * Marshal.SizeOf(typeof(T))), dataArray, BufferUsageHint.StaticDraw);
        GL.EnableVertexAttribArray(0);
        GL.VertexAttribPointer<T>(loc, 2, VertexAttribPointerType.Float, false, 0, ref dataArray[0]);
        GL.BindBuffer(BufferTarget.ArrayBuffer, 0);

    }

我用以下类型的数组传递它:

    public struct MeshData1
    {
        public Vector3 vertex;
        public Vector4 color;
        public MeshData1(Vector3 vertex, Vector4 color)
        {
            this.vertex = vertex;
            this.color = color;
        }
    }

输入如下所示:

#version 330 core
layout(location = 0) in struct InData {
    vec3 position;
    vec4 color;
} inData;
void main()
{  
    gl_Position = vec4(inData.position, 1.0);
}

我做错了什么?

最佳答案

立即想到两个问题:

  1. 您从未在程序对象中链接附加的着色器阶段(最重要)
  2. glGetProgramInfoLog (...) 输出的字符串仅在链接或验证 GLSL 程序后生成/更新。

要解决此问题,您应该调用 glLinkProgram (...)连接着色器后,还要了解,在执行此操作之前,程序信息日志将是未定义的。


glValidateProgram (...)是更新程序信息日志内容的另一种方法。除了生成信息日志之外,该函数还将返回您的程序是否处于适合执行的状态。此操作的结果存储在名为 GL_VALIDATE_STATUS 的每个程序状态中。

关于opengl - 为什么这个 glsl 着色器在尝试使用该程序时会导致 "Invalid Operation"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19669990/

相关文章:

opengl - OpenGL/GLSL 着色器中的统一位置之间是否存在间隙是否重要?

ios - 在 Metal 中反射着色器统一名称

c++ - 自定义 glBlendFunc 比原生慢很多

c++ - 编译错误: cannot find -lGLU and -lGL in kubuntu linux

opengl - Unity Shader 高亮重叠

opengl - 如何使用OpenGL着色器在平面上绘制没有透视的纹理?

java - LWJGL 无法在着色器中采样帧缓冲区纹理

python - PyOpenGL OBJ Loader 未正确加载

c++ - 将模型渲染到帧缓冲区

c++ - 不正确的插值,opengl索引的vbo,顶点结构和glsl