简体   繁体   English

在OpenGL 3.3上使用Texture2D

[英]Using texture2D on OpenGL 3.3

So I've been fiddling with an old University project done in OpenGL 3.3 (FreeGLUT + GLEW) and I've run into some problems. 因此,我一直在用OpenGL 3.3(FreeGLUT + GLEW)完成一个旧的大学项目,但遇到了一些问题。

Right at the start, I run the program and I'm getting an error compiling the BumpMap Fragment Shader: 就在开始时,我运行程序,并且在编译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;
        }
}

ERROR: 0:55: 'function' : is removed in Forward Compatible context texture2D 错误:0:55:“功能”:在正向兼容上下文Texture2D中已删除
ERROR: 0:55: 'texture2D' : no matching overloaded function found (using implicit conversion) 错误:0:55:'texture2D':找不到匹配的重载函数(使用隐式转换)

So I looked the problem up and even though I thought it was weird I was getting this problem on a project I knew had been in working condition, I switched the texture2D call for a texture call and now the shader compiles, but I get a different error, where creating the buffer object for the first object in the scene: 于是我起来看了看这个问题,尽管我认为这件事很奇怪,我在一个项目上得到这个问题,我就知道一直处于工作状态,我切换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 ERROR [Invalid Operation] = 1282 OpenGL错误[无效操作] = 1282

And that's all the info I'm getting. 这就是我得到的所有信息。 I've moved the checkOpenGLError around and figured out the line glDisableVertexAttribArray(VERTICES) is giving the error. 我已经移动了checkOpenGLError ,并发现glDisableVertexAttribArray(VERTICES)行给出了错误。 After a bit more of digging I found out that you're not supposed to set glBindVertexArray(0) (at least before you glDisableVertexAttribArray , from what I remember we set those flags to 0 so we wouldn't accidentally affect anything we didn't want) 经过更多的挖掘之后,我发现您不应该将glBindVertexArray(0)设置glBindVertexArray(0)至少在glDisableVertexAttribArray之前glBindVertexArray(0) ,根据我记得,我们将这些标志设置为0,这样我们就不会意外地影响到我们没有想)

At this point the error moves to where we're drawing one of the scene objects. 此时,错误移至我们绘制场景对象之一的位置。 At this point I've hit a bit of a wall and don't where to go to next. 在这一点上,我碰壁了一点,不要去下一步了。 I guess my question is whether there is a configuration when running the project that needs to be set, or whether just running this on a more recent graphics card could account for the different behaviour. 我想我的问题是,在运行项目时是否存在需要设置的配置,或者仅在较新的图形卡上运行该配置是否可以解释不同的行为。 As a final note, this is running on windows off of Visual Studio 10 (or 15, switched to 10 when reverted all changes and didn't retarget the solution) in widnows, the program configurations are as follows: 最后一点,这是在Widnows中的Visual Studio 10(或15,还原所有更改且未重新定位解决方案时切换为10)的窗口上运行的,程序配置如下:

//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);

with the context above being: 上面的上下文是:

CONTEXT: OpenGL v3.3.0 - Build 22.20.16.4749 上下文:OpenGL v3.3.0-内部版本22.20.16.4749

Let me know if any aditional information is required, I didn't want to add any more unnecessary clutter and the project is too big to just paste it all here... 让我知道是否需要任何其他信息,我不想添加任何不必要的混乱情况,并且该项目太大,无法将其全部粘贴到这里...

In your shader you are using glsl version 330 core, which means texture2D() is deprecated and you should use texture() instead. 在您的着色器中,您使用的是glsl版本330内核,这意味着不建议使用texture2D() ,而应使用texture()

As for your INVALID OPERATION error, the problem is that you unbound the vao with glBindVertexArray(0); 至于您的无效操作错误,问题在于您使用glBindVertexArray(0);解除了glBindVertexArray(0);绑定glBindVertexArray(0); and then called glDisableVertexAttribArray(VERTICES); 然后称为glDisableVertexAttribArray(VERTICES); which operates on the currently bound vao. 在当前绑定的vao上运行。 You should move glBindVertexArray(0); 您应该移动glBindVertexArray(0); under these calls. 在这些电话下。

First let me refer to the specification, OpenGL 4.6 API Core Profile Specification; 首先让我参考规范OpenGL 4.6 API核心配置文件规范; 10.3.1 Vertex Array Objects; 10.3.1顶点数组对象 page 347 : 第347页

The name space for vertex array objects is the unsigned integers, with zero reserved by the GL . 顶点数组对象的名称空间是无符号整数, 其中GL保留零
... ...
A vertex array object is created by binding a name returned by GenVertexArray with the command 通过使用命令绑定GenVertexArray返回的名称来创建顶点数组对象

 void BindVertexArray( uint array ); 

array is the vertex array object name. array是顶点数组对象名称。 The resulting vertex array object is a new state vector, comprising all the state and with the same initial values listed in tables 23.3 and 23.4. 所得的顶点数组对象是一个新的状态向量,包括所有状态,并具有表23.3和23.4中列出的相同初始值。
BindVertexArray may also be used to bind an existing vertex array object. BindVertexArray也可以用于绑定现有的顶点数组对象。 If the bind is successful no change is made to the state of the bound vertex array object, and any previous binding is broken. 如果绑定成功,则不会更改绑定的顶点数组对象的状态,并且任何先前的绑定都会中断。

Tables 23.3, Vertex Array Object State 表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 , VERTEX_ATTRIB_ARRAY_POINTER VERTEX_ATTRIB_ARRAY_ENABLEDVERTEX_ATTRIB_ARRAY_SIZEVERTEX_ATTRIB_ARRAY_STRIDEVERTEX_ATTRIB_ARRAY_TYPEVERTEX_ATTRIB_ARRAY_NORMALIZEDVERTEX_ATTRIB_ARRAY_INTEGERVERTEX_ATTRIB_ARRAY_LONGVERTEX_ATTRIB_ARRAY_DIVISORVERTEX_ATTRIB_ARRAY_POINTER

Table 23.4, Vertex Array Object State 表23.4,顶点数组对象状态
ELEMENT_ARRAY_BUFFER_BINDING , VERTEX_ATTRIB_ARRAY_BUFFER_BINDING , VERTEX_ATTRIB_BINDING , VERTEX_ATTRIB_RELATIVE_OFFSET , VERTEX_BINDING_OFFSET , VERTEX_BINDING_STRIDE , VERTEX_BINDING_DIVISOR , VERTEX_BINDING_BUFFER . ELEMENT_ARRAY_BUFFER_BINDINGVERTEX_ATTRIB_ARRAY_BUFFER_BINDINGVERTEX_ATTRIB_BINDINGVERTEX_ATTRIB_RELATIVE_OFFSETVERTEX_BINDING_OFFSETVERTEX_BINDING_STRIDEVERTEX_BINDING_DIVISORVERTEX_BINDING_BUFFER

This means that a Vertex Array Object collects all the information which is necessary to draw an object. 这意味着“ 顶点阵列对象”将收集绘制对象所需的所有信息。 In the vertex array object is stored the information about the location of the vertex attributes and the format. 在顶点数组对象中存储有关顶点属性的位置和格式的信息。 Further the vertex array object "knows" whether an attribute is enabled or disabled. 此外,顶点数组对象“知道”属性是启用还是禁用。

If you do 如果你这样做

glBindVertexArray(0);

glDisableVertexAttribArray( .... );

this causes an INVALID_OPERATION error, when you use a core profile OpenGL context , because then the vertex array object 0 is not a valid vertex array object. 当您使用核心配置文件OpenGL上下文时 ,这会导致INVALID_OPERATION错误,因为顶点数组对象0不是有效的顶点数组对象。 If you would use a compatibility profile context this would not cause an error, because then the vertex array object 0 is the default vertex array object and is valid. 如果使用兼容性配置文件上下文,则不会导致错误,因为顶点数组对象0是默认的顶点数组对象,并且是有效的。

If you do 如果你这样做

glBindVertexArray(_vertexArrayObjectID);

glEnableVertexAttribArray( ..... );
glVertexAttribPointer( ..... );

glDisableVertexAttribArray( ..... );

glBindVertexArray(0);

then the draw call will fail. 那么抽奖电话将失败。 You have made the effort to define all the arrays of generic vertex attributes data and to enable them all correctly, but right after doing that you disable them again. 您已努力定义通用顶点属性数据的所有数组并正确启用它们,但是在此之后立即再次禁用它们。 So in the vertex array object is stored the "disabled" state for all the attributes. 因此,在顶点数组对象中存储了所有属性的“禁用”状态。

The correct procedure to define a vertex array object is: 定义顶点数组对象的正确过程是:

  • Generate the vertex buffers, and creates and initializes the buffer object's data store (this step can be done after creating and binding the vertex array object, too): 生成顶点缓冲区,并创建和初始化缓冲区对象的数据存储(此步骤也可以在创建并绑定顶点数组对象之后完成):
glGenBuffers(1, &_vertexBufferObjectID);

glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferObjectID);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*_vertexCount, _vertices, GL_STATIC_DRAW);
  • Generate and bind the vertex array object: 生成并绑定顶点数组对象:
glGenVertexArrays(1, &_vertexArrayObjectID);
glBindVertexArray(_vertexArrayObjectID);
  • Define and enable the arrays of generic vertex attributes data (this has to be done after binding the vertex array object): 定义并启用通用顶点属性数据的数组(这必须在绑定顶点数组对象之后完成):
glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferObjectID);
glEnableVertexAttribArray(VERTICES);
glVertexAttribPointer(VERTICES, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);

....

glBindBuffer(GL_ARRAY_BUFFER, 0);
  • If you would use an element buffer ( GL_ELEMENT_ARRAY_BUFFER ), then you would have to specify it now, because the name of (reference to) the element buffer object is stored in the vertex array object, and this has to be currently bound, when the element buffer object gets bound. 如果要使用元素缓冲区( GL_ELEMENT_ARRAY_BUFFER ),则必须立即指定它,因为元素缓冲区对象(的引用)的名称存储在顶点数组对象中,并且当元素缓冲区对象被绑定。
glGenBuffers(1, &ibo);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, ..... );
  • Finally you can do glBindVertexArray(0) . 最后,您可以执行glBindVertexArray(0) But there is no reason to do that. 但是没有理由这样做。 It is sufficient to bind a new vertex array object, before you specify a new mesh, or to bind the proper vertex array object before you draw a mesh. 在指定新网格之前,绑定一个新的顶点阵列对象就足够了,或者在绘制网格之前绑定一个适当的顶点数组对象就足够了。

Further there is no need for glDisableVertexAttribArray , as long you don't want to change the vertex array object specification. 此外,只要您不想更改顶点数组对象的规范,就不需要glDisableVertexAttribArray The state "enabled" is stored in the vertex array object an kept there. 状态“启用”存储在顶点数组对象中并保持在那里。 If you bind a new vertex array object, the then the object and so all its states become current. 如果绑定一个新的顶点数组对象,则该对象及其所有状态都将变为当前状态。

Now drawing is simple: 现在绘制很简单:

 glBindVertexArray(_vertexArrayObjectID);
 glDrawArrays( .... );

Again there is no need of glBindVertexArray(0) , after the draw call (especially in core mode). 同样,在绘制调用之后(尤其是在核心模式下),不需要glBindVertexArray(0) )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM