Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 传递给着色器的颜色不';行不通_C++_Opengl_Glfw_Opengl 3 - Fatal编程技术网

C++ 传递给着色器的颜色不';行不通

C++ 传递给着色器的颜色不';行不通,c++,opengl,glfw,opengl-3,C++,Opengl,Glfw,Opengl 3,我是OpenGL的新手,现在有一个简单的程序 我遇到的问题是,当我传递一个数组来表示点的颜色时,颜色就变成了黑色。如果我只是在片段着色器中显式定义一种颜色,并且如果我在VAO中切换数据的索引,则可以将三角形移动到作为颜色的点 我尝试使用API跟踪,得到以下结果: 6872: message: major api error 1282: GL_INVALID_OPERATION error generated. <program> is not a program object, or

我是OpenGL的新手,现在有一个简单的程序

我遇到的问题是,当我传递一个数组来表示点的颜色时,颜色就变成了黑色。如果我只是在片段着色器中显式定义一种颜色,并且如果我在VAO中切换数据的索引,则可以将三角形移动到作为颜色的点

我尝试使用API跟踪,得到以下结果:

6872: message: major api error 1282: GL_INVALID_OPERATION error generated. <program> is not a program object, or <shader> is not a shader object.
6872 @0 glAttachShader(program = 1, shader = 1)
6872: warning: glGetError(glAttachShader) = GL_INVALID_OPERATION
6876: message: major api error 1282: GL_INVALID_OPERATION error generated. Handle does not refer to the expected type of object (GL_SHADER_OBJECT_ARB).
6876 @0 glDeleteShader(shader = 1)
6876: warning: glGetError(glDeleteShader) = GL_INVALID_OPERATION
6878: message: major api error 1282: GL_INVALID_OPERATION error generated. Handle does not refer to the expected type of object (GL_SHADER_OBJECT_ARB).
6878 @0 glDeleteShader(shader = 1)
6878: warning: glGetError(glDeleteShader) = GL_INVALID_OPERATION
Rendered 507 frames in 8.52598 secs, average of 59.4653 fps
您可能需要知道的是,
是一个
向量
程序::getCurrentProgram()
是一个静态函数,返回当前正在使用的程序,
drawShape
在本例中是
GL_三角形

顶点着色器:

#version 400 core

layout(location=0) in vec3 vert;
layout(location=1) in vec3 vertColor;

out vec3 color;

void main()
{
    color = vertColor;
    gl_Position = vec4(vert, 1);
}
片段着色器:

#version 400 core

in vec3 color;

out vec4 finalColor;

void main()
{
    finalColor = vec4(color, 1.0);
}
如果这是一个需要仔细研究的问题,我很抱歉。在过去的一天左右,我环顾四周,尝试了几种不同的方法,但都没有奏效。如果需要任何其他信息,以便某人不必对我的所有代码进行排序,请让我知道

我从apitrace中得到的信息似乎表明我可能对着色器ID做了一些错误,尽管如果我将颜色编码到片段着色器中,然后颜色正常工作,仍然会发生错误

我正在使用GLFW创建我的OpenGL上下文。我已经设置了一个错误回调,我没有从中得到任何信息,我的印象是它也应该通过OpenGL错误传递,尽管我在他们的FAQ上没有看到任何明确的说明

我还在编译着色器和链接程序时检查错误,但也没有发生任何事情

也,我想知道,如果一个对象超出了范围,使用C++会有风险丢失OpenGL状态吗? 编辑:这里有一些我没有展示的内容:

着色器初始化:

// Create OpenGL Shader
shaderID = glCreateShader(shaderType);

glShaderSource(shaderID, 1, &cShaderString, NULL);

// Compile
glCompileShader(shaderID);
着色器析构函数只调用
glDeleteShader(shaderID)

这是相当标准的。它位于着色器类的构造函数中,
shaderID
着色器的成员变量
shaderType
是一个
GLenum
,在本例中,它是
GL\u VERTEX\u着色器
GL\u FRAGMENT\u着色器

程序初始化: //创建程序 programID=glCreateProgram()

//遍历着色器
对于(std::vector::iterator shader=shaders.begin();shader!=shaders.end();shader++)
{
//附加着色器
glAttachShader(programID,shader->getShaderID());
}
//链接程序
glLinkProgram(programID);
程序析构函数:

// Iterate through attached shaders
for(std::vector<Shader>::iterator shader = shaders.begin(); shader != shaders.end(); shader++)
{
    // Detach Shader
    glDetachShader(programID, shader->getShaderID());
}

// Delete program
glDeleteProgram(programID);
//迭代连接的着色器
对于(std::vector::iterator shader=shaders.begin();shader!=shaders.end();shader++)
{
//分离着色器
glDetachShader(programID,shader->getShaderID());
}
//删除程序
glDeleteProgram(programID);
再一次,这看起来很标准,并且在
程序的构造函数中

编辑2:在弄乱了一些代码之后,我发现了一件相当奇怪的事情。如果我将创建和绑定缓冲区并绘制三角形的代码移动到我正在使用的类的构造函数中来表示三角形,那么我得到的位置是颜色而不是位置。这与我在数据上切换索引(位置为1,颜色为0)时发生的情况相同

编辑3:实际上,在仔细观察之后,它似乎绘制了一个与颜色完全不同的三角形。为Triangle类创建一个vao成员并将其绑定到draw上似乎可以解决这个问题

编辑4:似乎
glValidateProgram()
确实产生了一个成功的结果,这让我怀疑其着色器是否存在问题

也,我想知道,如果一个对象超出作用域并删除了,C++是否可以冒丢失OpenGL状态的风险。 是的,有。我相信这正是这里正在发生的事情。这并不意味着你不能在C++类中包装OpenGL对象,但是你必须非常小心。 <>你遇到的问题是,在C++对象的析构函数中删除包裹的OpenGL对象。因此,每当这些对象中的一个超出范围,或者由于任何其他原因被破坏时,它就会带上相应的OpenGL对象

如果复制对象,这会导致特别难看的问题。让我们看一个人造的例子:

Shader a(...);
{
    Shader b = a;
}
在此之后,您在
a
的构造函数中创建的OpenGL对象将被删除。当创建
b
作为
a
的副本时,默认副本构造函数将
a
中存储的着色器id复制到
b
。然后,当
b
超出范围时,其析构函数将删除着色器id。它仍存储在
a
中,但现在无效

当然,您不会完全像上面那样编写代码。但是,如果您按值将对象传递给函数/方法,您可能会遇到非常类似的情况,这部分发生在您的代码中

更危险的是,因为更难识别,如果将这些对象存储在容器中,如
std::vector
,会发生什么。当添加新元素会使向量超出其当前容量时,向量将重新分配其内存。在重新分配期间,它会创建
向量
(调用复制构造函数)中所有现有元素的副本,然后销毁原始元素。这与上面的示例非常相似,在上面的示例中,对象引用已删除的OpenGL对象

这正是你的情况。您将
着色器
对象推入
向量
,当您
// Iterate through attached shaders
for(std::vector<Shader>::iterator shader = shaders.begin(); shader != shaders.end(); shader++)
{
    // Detach Shader
    glDetachShader(programID, shader->getShaderID());
}

// Delete program
glDeleteProgram(programID);
Shader a(...);
{
    Shader b = a;
}