所以我一直在研究用OpenGL 3.3(FreeGLUT + GLEW)完成的一个旧的大学项目,但是遇到了一些问题。
从一开始,我就运行该程序,并且在编译BumpMap Fragment Shader时遇到错误:
#version 330 core
#define lightCount 10
in vec4 vertPos;
in vec4 eyeModel;
in vec3 normalInterp;
in vec4 ambient;
in vec4 color;
in vec4 spec;
in vec2 texuv;
in vec4 lightPosition[lightCount];
struct LightSource {
vec4 Position;
vec4 Direction;
vec4 Color;
float CutOff;
float AmbientIntensity;
float DiffuseIntensity;
float SpecularIntensity;
float ConstantAttenuation;
float LinearAttenuation;
float ExponentialAttenuation;
int lightType;
};
layout(std140) uniform LightSources {
LightSource lightSource[10];
};
uniform sampler2D diffuse_tex;
uniform sampler2D normal_tex;
out vec4 out_Color;
void main() {
out_Color = vec4(0);
for(int i=0; i<lightCount; i++) {
if(lightSource[i].lightType == 0)
continue;
vec3 NormalMap = texture2D(normal_tex, texuv).rgb;
vec3 normal = normalize(NormalMap * 2.0 - 1.0); //normalize(normalInterp);
vec4 LightDirection = vertPos - lightSource[i].Position;
float Distance = length(LightDirection);
LightDirection = normalize(LightDirection);
vec4 ambientColor = ambient * lightSource[i].Color * lightSource[i].AmbientIntensity;
vec4 diffuseColor = vec4(0, 0, 0, 0);
vec4 dColor = texture2D(diffuse_tex, texuv);
vec4 specularColor = vec4(0, 0, 0, 0);
float DiffuseFactor = dot(normal, vec3(-LightDirection));
if (DiffuseFactor > 0) {
diffuseColor = dColor * lightSource[i].Color * lightSource[i].DiffuseIntensity * DiffuseFactor;
vec3 VertexToEye = normalize(vec3(eyeModel - vertPos));
vec3 LightReflect = normalize(reflect(vec3(LightDirection), normal));
float SpecularFactor = dot(VertexToEye, LightReflect);
SpecularFactor = pow(SpecularFactor, 255);
if(SpecularFactor > 0.0){
//SpecularFactor = pow( max(SpecularFactor,0.0), 255);
specularColor = spec * lightSource[i].Color * lightSource[i].SpecularIntensity * SpecularFactor;
}
}
out_Color += ambientColor + diffuseColor + specularColor;
}
}
错误:0:55:“功能”:已在向前兼容的上下文texture2D中删除
错误:0:55:'texture2D':找不到匹配的重载函数(使用隐式转换)
因此,我查找了问题,即使我认为在我知道已经正常运行的项目中遇到此问题很奇怪,我还是将texture2D
呼叫切换为texture
呼叫现在着色器可以编译,但是出现另一个错误,即为场景中的第一个对象创建缓冲区对象:
//Consts defined here for readability
#define VERTICES 0
#define COLORS 1
#define NORMALS 2
#define TEXUVS 3
#define AMBIENTS 4
#define TANGENTS 5
#define SPECULARS 6
#define SPECULARS_CONSTANTS 7
#define NOISE_SCALE 8
void BufferObject::createBufferObject() {
glGenVertexArrays(1, &_vertexArrayObjectID);
glBindVertexArray(_vertexArrayObjectID);
glGenBuffers(1, &_vertexBufferObjectID);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferObjectID);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*_vertexCount, _vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(VERTICES);
glVertexAttribPointer(VERTICES, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
glEnableVertexAttribArray(COLORS);
glVertexAttribPointer(COLORS, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)sizeof(_vertices[0].XYZW));
glEnableVertexAttribArray(NORMALS);
glVertexAttribPointer(NORMALS, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(_vertices[0].XYZW)+sizeof(_vertices[0].RGBA)));
glEnableVertexAttribArray(TEXUVS);
glVertexAttribPointer(TEXUVS, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(_vertices[0].XYZW)+sizeof(_vertices[0].RGBA)+sizeof(_vertices[0].NORMAL)));
glEnableVertexAttribArray(AMBIENTS);
glVertexAttribPointer(AMBIENTS, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(_vertices[0].XYZW)+sizeof(_vertices[0].RGBA)+sizeof(_vertices[0].NORMAL)+sizeof(_vertices[0].TEXUV)));
glEnableVertexAttribArray(TANGENTS);
glVertexAttribPointer(TANGENTS, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(_vertices[0].XYZW)+sizeof(_vertices[0].RGBA)+sizeof(_vertices[0].NORMAL)+sizeof(_vertices[0].TEXUV)+sizeof(_vertices[0].AMBIENT)));
glEnableVertexAttribArray(SPECULARS);
glVertexAttribPointer(SPECULARS, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(_vertices[0].XYZW)+sizeof(_vertices[0].RGBA)+sizeof(_vertices[0].NORMAL)+sizeof(_vertices[0].TEXUV)+sizeof(_vertices[0].AMBIENT)+sizeof(_vertices[0].TANGENT)));
glEnableVertexAttribArray(SPECULARS_CONSTANTS);
glVertexAttribPointer(SPECULARS_CONSTANTS, 1, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(_vertices[0].XYZW)+sizeof(_vertices[0].RGBA)+sizeof(_vertices[0].NORMAL)+sizeof(_vertices[0].TEXUV)+sizeof(_vertices[0].AMBIENT)+sizeof(_vertices[0].TANGENT)+sizeof(_vertices[0].SPECULAR)));
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
glDisableVertexAttribArray(VERTICES);
glDisableVertexAttribArray(COLORS);
glDisableVertexAttribArray(NORMALS);
glDisableVertexAttribArray(TEXUVS);
glDisableVertexAttribArray(AMBIENTS);
glDisableVertexAttribArray(TANGENTS);
glDisableVertexAttribArray(SPECULARS);
glDisableVertexAttribArray(SPECULARS_CONSTANTS);
Utility::checkOpenGLError("ERROR: Buffer Object creation failed.");
}
OpenGL错误[无效操作] = 1282
这就是我得到的所有信息。我已经移动了checkOpenGLError
并发现行glDisableVertexAttribArray(VERTICES)
给出了错误。
经过更多的挖掘,我发现您不应该设置glBindVertexArray(0)
(至少在glDisableVertexAttribArray
之前),据我所知,我们将这些标志设置为0,这样就不会意外影响任何我们不想要的东西
此时,错误转移到我们绘制场景对象之一的位置。在这一点上,我碰壁了一点,不要去下一步了。我想我的问题是,在运行项目时是否存在需要设置的配置,或者仅在较新的图形卡上运行该配置是否可以解释不同的行为。最后一点,这是在Widnows中运行于Visual Studio 10(或15,还原所有更改且未重新定位解决方案时切换为10)的Windows上的,程序配置如下:
//GLUT Init
glutInit(&argc, argv);
glutInitContextVersion(3, 3);
glutInitContextFlags(GLUT_FORWARD_COMPATIBLE);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,GLUT_ACTION_GLUTMAINLOOP_RETURNS);
glutInitWindowSize(windowWidth, windowHeight);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
windowHandle = glutCreateWindow(CAPTION);
//GLEW Init
glewExperimental = GL_TRUE;
GLenum result = glewInit();
//GLUT Init
std::cerr << "CONTEXT: OpenGL v" << glGetString(GL_VERSION) << std::endl;
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glDepthMask(GL_TRUE);
glDepthRange(0.0,1.0);
glClearDepth(1.0);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);
上面的上下文是:
上下文:OpenGL v3.3.0-内部版本22.20.16.4749
让我知道是否需要任何其他信息,我不想添加任何不必要的混乱情况,并且该项目太大,无法将其全部粘贴在这里...
答案 0 :(得分:2)
在着色器中,您使用的是glsl版本330内核,这意味着texture2D()
已过时,应改为使用texture()
。
至于您的INVALID OPERATION错误,问题在于您用glBindVertexArray(0);
解除了vao的绑定,然后调用了glDisableVertexAttribArray(VERTICES);
来对当前绑定的vao进行操作。您应将glBindVertexArray(0);
移至这些通话下。
答案 1 :(得分:1)
首先让我参考一下规范OpenGL 4.6 API Core Profile Specification; 10.3.1 Vertex Array Objects; page 347:
顶点数组对象的名称空间是无符号整数, GL保留了零。
...
通过用命令绑定GenVertexArray
返回的名称来创建顶点数组对象void BindVertexArray( uint array );
array
是顶点数组对象名称。所得的顶点数组对象是一个新的状态向量,包括所有状态,并且初始值与表23.3和23.4中列出的相同。
BindVertexArray
也可以用于绑定现有的顶点数组对象。如果绑定成功,则不会更改绑定的顶点数组对象的状态,并且任何先前的绑定都会中断。表23.3,顶点数组对象状态
VERTEX_ATTRIB_ARRAY_ENABLED
,VERTEX_ATTRIB_ARRAY_SIZE
,VERTEX_ATTRIB_ARRAY_STRIDE
,VERTEX_ATTRIB_ARRAY_TYPE
,VERTEX_ATTRIB_ARRAY_NORMALIZED
,VERTEX_ATTRIB_ARRAY_INTEGER
,VERTEX_ATTRIB_ARRAY_LONG
,VERTEX_ATTRIB_ARRAY_DIVISOR
,{{ 1}}表23.4,顶点数组对象状态
VERTEX_ATTRIB_ARRAY_POINTER
,ELEMENT_ARRAY_BUFFER_BINDING
,VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
,VERTEX_ATTRIB_BINDING
,VERTEX_ATTRIB_RELATIVE_OFFSET
,VERTEX_BINDING_OFFSET
,VERTEX_BINDING_STRIDE
,{ {1}}。
这意味着Vertex Array Object收集绘制对象所需的所有信息。在顶点数组对象中存储有关顶点属性的位置和格式的信息。 此外,顶点数组对象“知道”属性是启用还是禁用。
如果您这样做
VERTEX_BINDING_DIVISOR
当您使用核心配置文件OpenGL context时,这会导致VERTEX_BINDING_BUFFER
错误,因为顶点数组对象0不是有效的顶点数组对象。
如果使用兼容性配置文件上下文,则不会导致错误,因为顶点数组对象0是默认的顶点数组对象,并且是有效的。
如果愿意
glBindVertexArray(0);
glDisableVertexAttribArray( .... );
然后绘图调用将失败。您已努力定义通用顶点属性数据的所有数组并正确启用它们,但是在此之后立即再次禁用它们。因此,在顶点数组对象中存储了所有属性的“禁用”状态。
定义顶点数组对象的正确过程是:
INVALID_OPERATION
glBindVertexArray(_vertexArrayObjectID);
glEnableVertexAttribArray( ..... );
glVertexAttribPointer( ..... );
glDisableVertexAttribArray( ..... );
glBindVertexArray(0);
glGenBuffers(1, &_vertexBufferObjectID);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferObjectID);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*_vertexCount, _vertices, GL_STATIC_DRAW);
glGenVertexArrays(1, &_vertexArrayObjectID);
glBindVertexArray(_vertexArrayObjectID);
),则必须立即指定它,因为元素缓冲区对象(的引用)的名称存储在顶点数组对象中,并且具有绑定元素缓冲区对象时,当前绑定。glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferObjectID);
glEnableVertexAttribArray(VERTICES);
glVertexAttribPointer(VERTICES, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
....
glBindBuffer(GL_ARRAY_BUFFER, 0);
GL_ELEMENT_ARRAY_BUFFER
。但是没有理由这样做。在指定新网格之前,绑定一个新的顶点数组对象就足够了,或者在绘制网格之前绑定一个适当的顶点数组对象就足够了。此外,只要您不想更改顶点数组对象规范,就不需要glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, ..... );
。状态“启用”存储在顶点数组对象中并保持在那里。如果绑定新的顶点数组对象,则该对象及其所有状态都将变为当前状态。
现在绘制很简单:
glBindVertexArray(0)
再次在绘制调用之后(尤其是在核心模式下)不需要glDisableVertexAttribArray
。