简体   繁体   English

OpenGL ES 2.0纹理无法显示

[英]OpenGL ES 2.0 Texture Won't Display

So I am currently learning OpenGL ES 2.0 with iOS and working on a maze game. 因此,我目前正在使用iOS学习OpenGL ES 2.0,并正在从事迷宫游戏。 The maze is randomly generated (so not a loaded model) and my struggle is texturing the walls and floor of the maze. 迷宫是随机生成的(因此不是加载模型),我的工作是对迷宫的墙壁和地板进行纹理处理。 My approach is to just treat the maze as a series of cubes, and I have code that draws the individual faces of a cube separately (so I can create a path by simply leaving some faces out). 我的方法是将迷宫视为一系列多维数据集,并且我有代码分别绘制多维数据集的各个面(因此我可以通过简单地省略一些面来创建路径)。

Using capture GPU frame, I have confirmed that the texture is indeed loading in correctly, the data in the frame buffers is correct and that I'm not getting any errors. 使用捕获的GPU框架,我已经确认纹理确实正确加载,框架缓冲区中的数据正确,并且没有出现任何错误。 I can see my other lighting effects (so the face isn't completely black), but no texture appears. 我可以看到其他照明效果(因此脸部不是完全黑色),但没有纹理出现。

Here is how I've defined my cube faces 这是我定义立方体面的方法

 GLfloat rightCubeVertexData[] =
{
    0.5f, -0.5f, -0.5f,
    0.5f, -0.5f, 0.5f,
    0.5f, 0.5f, -0.5f,
    0.5f, 0.5f, -0.5f,
    0.5f, -0.5f, 0.5f,
    0.5f, 0.5f, 0.5f,
};

GLfloat rightCubeNormalData[] =
{
    -1.0f, 0.0f, 0.0f,
    -1.0f, 0.0f, 0.0f,
    -1.0f, 0.0f, 0.0f,
    -1.0f, 0.0f, 0.0f,
    -1.0f, 0.0f, 0.0f,
    -1.0f, 0.0f, 0.0f,
};

GLfloat rightCubeTexCoords[] =
{
    0.0, 0.0,
    1.0, 0.0,
    0.0, 1.0,
    0.0, 1.0,
    1.0, 0.0,
    1.0, 1.0,
};

The other faces are defined essentially the same way (except they are in one array each, splitting up the position, normals, and tex coords was just something I tried; I'm just trying to get one face to texture and then I'll expand to the rest). 其他面的定义基本上是相同的方式(除了它们每个都在一个数组中,将位置,法线和tex坐标分开是我尝试的;我只是想使一个面具有纹理,然后我将扩展到其余部分)。

Here is how I load the data into the buffer 这是我将数据加载到缓冲区的方法

glGenVertexArraysOES(1, &_rightVertexArray);
glBindVertexArrayOES(_rightVertexArray);

glGenBuffers(3, _rightVertexBuffer);

glBindBuffer(GL_ARRAY_BUFFER, _rightVertexBuffer[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(rightCubeVertexData), rightCubeVertexData, GL_STATIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 12, BUFFER_OFFSET(0));

glBindBuffer(GL_ARRAY_BUFFER, _rightVertexBuffer[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(rightCubeNormalData), rightCubeNormalData, GL_STATIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 12, BUFFER_OFFSET(0));

glBindBuffer(GL_ARRAY_BUFFER, _rightVertexBuffer[2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(rightCubeTexCoords), rightCubeTexCoords, GL_STATIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 12, BUFFER_OFFSET(0));

Again, using three buffers was an experiment, the rest are defined in one buffer with an offset. 同样,使用三个缓冲区是一个实验,其余的都在一个带有偏移量的缓冲区中定义。

Here is how I load textures 这是我加载纹理的方式

crateTexture = [self setupTexture:@"crate.jpg"];
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, crateTexture);
glUniform1i(uniforms[UNIFORM_TEXTURE], 0);

// Load in and set up texture image (adapted from Ray Wenderlich)
- (GLuint)setupTexture:(NSString *)fileName
{
    CGImageRef spriteImage = [UIImage imageNamed:fileName].CGImage;
    if (!spriteImage) {
        NSLog(@"Failed to load image %@", fileName);
        exit(1);
    }

    size_t width = CGImageGetWidth(spriteImage);
    size_t height = CGImageGetHeight(spriteImage);

    GLubyte *spriteData = (GLubyte *) calloc(width*height*4, sizeof(GLubyte));

    CGContextRef spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width*4, CGImageGetColorSpace(spriteImage), kCGImageAlphaPremultipliedLast);

    CGContextDrawImage(spriteContext, CGRectMake(0, 0, width, height), spriteImage);

    CGContextRelease(spriteContext);

    GLuint texName;
    glGenTextures(1, &texName);
    glBindTexture(GL_TEXTURE_2D, texName);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);

    free(spriteData);
    return texName;
}

Then, at the appropriate time, I simply call glDrawArrays to draw the face. 然后,在适当的时间,我只需调用glDrawArrays来绘制面。 I am completely stumped on this, and it is probably a very silly error, but any help anybody could provide would be much appreciated. 我对此完全感到困惑,这可能是一个非常愚蠢的错误,但是任何人都可以提供的任何帮助将不胜感激。

PS Here is my fragment shader PS这是我的片段着色器

varying vec3 eyeNormal;
varying vec4 eyePos;
varying vec2 texCoordOut;

uniform sampler2D texture;

uniform vec3 flashlightPosition;
uniform vec3 diffuseLightPosition;
uniform vec4 diffuseComponent;
uniform float shininess;
uniform vec4 specularComponent;
uniform vec4 ambientComponent;

void main()
{
    vec4 ambient = ambientComponent;

    vec3 N = normalize(eyeNormal);
    float nDotVP = max(0.0, dot(N, normalize(diffuseLightPosition)));
    vec4 diffuse = diffuseComponent * nDotVP;

    vec3 E = normalize(-eyePos.xyz);
    vec3 L = normalize(flashlightPosition - eyePos.xyz);
    vec3 H = normalize(L+E);
    float Ks = pow(max(dot(N, H), 0.0), shininess);
    vec4 specular = Ks*specularComponent;
    if( dot(L, N) < 0.0 ) {
        specular = vec4(0.0, 0.0, 0.0, 1.0);
    }

    gl_FragColor = (ambient + diffuse + specular) * texture2D(texture, texCoordOut);
    //gl_FragColor = ambient + diffuse + specular;
    gl_FragColor.a = 1.0;
}

And yes, all the uniform names are correct and correspond to something in the main code. 是的,所有统一名称都是正确的,并且与主代码中的某些名称相对应。

EDIT: Here is the vertex shader 编辑:这是顶点着色器

precision mediump float;

attribute vec4 position;
attribute vec3 normal;
attribute vec2 texCoordIn;

varying vec3 eyeNormal;
varying vec4 eyePos;
varying vec2 texCoordOut;

uniform mat4 modelViewProjectionMatrix;
uniform mat4 modelViewMatrix;
uniform mat3 normalMatrix;

void main()
{
    eyeNormal = (normalMatrix * normal);
    eyePos = modelViewMatrix * position;
    texCoordOut = texCoordIn;
    gl_Position = modelViewProjectionMatrix * position;
}

Turns out I had forgotten to bind the attribute location when compiling the shader. 原来,我在编译着色器时忘记绑定属性位置。 Needed to add the line 需要添加行

glBindAttribLocation(_program, GLKVertexAttribTexCoord0, "texCoordIn");

to the load shaders method. 加载着色器方法。

To sum up the procedure done from the comments... 总结从注释中完成的过程...

There is much that can go wrong when dealing with textures and it is good to know how to pinpoint where the issue is. 处理纹理时可能会出错,因此最好知道如何找出问题所在。

What to be careful wit the texture itself: 需要注意的是纹理本身:

  • Check if you did set the parameters such as 检查是否设置了诸如

     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
  • Check setting the uniform as glUniform1i(uniformName, 0) where the last parameter corresponds to the active texture and not the texture ID. 检查将统一设置为glUniform1i(uniformName, 0) ,其中最后一个参数对应于活动纹理而不是纹理ID。
  • Other include checking if the uniform name is correct, texture is bound.. And if possible check the debugger if the texture is properly loaded. 其他包括检查统一名称是否正确,纹理是否绑定。以及(如果可能)检查调试器是否正确加载了纹理。

Next to that there are chances your texture coordinates are messed up and this seems to be a very common issue. 紧接着,您的纹理坐标可能会混乱,这似乎是一个非常普遍的问题。 To debug that it is best that you replace the color gotten from the texture in your fragment shader with the texture coordinate itself. 要进行调试,最好将片段着色器中从纹理获取的颜色替换为纹理坐标本身。 Eg replace texture2D(texture, texCoordOut) with vec4(texCoordOut.x, texCoordOut.y, .0, 1.0) . 例如用vec4(texCoordOut.x, texCoordOut.y, .0, 1.0) texture2D(texture, texCoordOut)替换texture2D(texture, texCoordOut) vec4(texCoordOut.x, texCoordOut.y, .0, 1.0) Since the texture coordinates should be in range [0,1] you should see nice gradients between red and green color in your scene. 由于纹理坐标应在[0,1]范围内,因此您应该在场景中看到红色和绿色之间的良好渐变。 If you do not see them then your texture coordinates are messed up: If all is black your coordinates are all zero, if most is yellow then your coordinates are most likely too large. 如果看不到它们,则纹理坐标会混乱:如果全部为黑色,则坐标均为零,如果大多数为黄色,则坐标很可能太大。

In your case the texture coordinates were all black which means you were always getting the first pixel from the texture thus a constant color in your scene. 在您的情况下,纹理坐标全为黑色,这意味着您始终从纹理中获取第一个像素,因此场景中的颜色恒定。 What to check at this point is: 此时要检查的是:

  • Are the coordinates you push to the GPU correct 您推送到GPU的坐标是否正确
  • Is the pointer set correctly as glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 12, BUFFER_OFFSET(0)) (check all the parameters) 指针是否正确设置为glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 12, BUFFER_OFFSET(0)) (检查所有参数)
  • Is the attribute enabled glEnableVertexAttribArray(GLKVertexAttribTexCoord0) 是否启用了属性glEnableVertexAttribArray(GLKVertexAttribTexCoord0)
  • Is the attribute bound to the shader being compiled. 属性绑定到正在编译的着色器吗?

In your case you have forgotten to bind the texture coordinate attribute which is quite natural to miss. 在您的情况下,您忘记绑定纹理坐标属性,这是很自然会错过的。

From the information you have given us it is impossible to find this mistake but you should note the procedure I have given you to pinpoint the issue as to where it actually lies. 根据您提供给我们的信息,不可能找到此错误,但是您应该注意我提供的过程,以查明问题的根源。 It might be handy in future as well. 将来也可能很方便。

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

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