ios - 似乎无法将纹理加载到 OpenGL ES 中。我究竟做错了什么?

标签 ios opengl-es

我正在尝试在 iOS 下的 OpenGL ES 中加载纹理。这是我正在采取的方法:

  • 解析一个 obj,从中我得到位置、正常和 texcoord
    属性。
  • 仅启用(对于此测试)着色器的位置和 texcoords。
  • 将任意 512x512 png 转换为 raw 并将其加载到 GL 中,
    通过采样器 0。
  • 在顶点着色器中,仅以规范返回 gl_Position
    将 texcoords 传递给片段时的体积/剪辑空间
    着色器。
  • 在片段着色器中,将查找分配给 gl_FragColor
    纹理2d。

  • 纹理文件:t1.png:
    enter image description here

    渲染结果:

    enter image description here

    显然没有纹理映射到立方体上。 尽管我从 texture2D() 中获得了一些值(value),但正如您所见,着色器中没有传递或处理光照或颜色......
    我的猜测是我以某种方式搞砸了我认为我将 png 转换为原始缓冲区以传递到纹理内存的方式。

    这是 obj 文件。一个测试立方体:
    # Blender v2.63 (sub 0) OBJ File: ''
    # www.blender.org
    mtllib cube2.mtl
    o Cube
    v 1.000000 -1.000000 -1.000000
    v 1.000000 -1.000000 1.000000
    v -1.000000 -1.000000 1.000000
    v -1.000000 -1.000000 -1.000000
    v 1.000000 1.000000 -0.999999
    v 0.999999 1.000000 1.000001
    v -1.000000 1.000000 1.000000
    v -1.000000 1.000000 -1.000000
    vt 0.000000 0.000000
    vt 1.000000 0.000000
    vt 1.000000 1.000000
    vt 0.000000 1.000000
    vn 0.000000 -1.000000 0.000000
    vn 0.000000 1.000000 0.000000
    vn 1.000000 0.000000 0.000000
    vn -0.000000 -0.000000 1.000000
    vn -1.000000 -0.000000 -0.000000
    vn 0.000000 0.000000 -1.000000
    usemtl Material
    s off
    f 1/1/1 2/2/1 3/3/1
    f 1/1/1 3/3/1 4/4/1
    f 5/1/2 8/2/2 7/3/2
    f 5/1/2 7/3/2 6/4/2
    f 1/1/3 5/2/3 6/3/3
    f 1/1/3 6/3/3 2/4/3
    f 2/1/4 6/2/4 7/3/4
    f 2/1/4 7/3/4 3/4/4
    f 3/1/5 7/2/5 8/3/5
    f 3/1/5 8/3/5 4/4/5
    f 5/1/6 1/2/6 4/3/6
    f 5/1/6 4/3/6 8/4/6
    

    然后是解析 obj 并创建数据结构的代码 - 法线被正确解析。然后,相关的代码片段是:

    确保在链接期间绑定(bind)位置和 texcoords:
            // Attach vertex shader to program.
            glAttachShader(_program, vertShader);
    
            // Attach fragment shader to program.
            glAttachShader(_program, fragShader);
    
            // Bind attribute locations.
            glBindAttribLocation(_program, 0, "position");
            glBindAttribLocation(_program, 1, "tCoordinates");
    

    顶点着色器(只是将 texcoords 传递给片段着色器):
    uniform mat4 modelViewProjectionMatrix;
    uniform mat3 normalMatrix;
    
    attribute vec4 position;
    attribute vec2 tCoordinates;
    
    varying highp vec2 tCoordinatesVarying;
    
    void main()
    {
        tCoordinatesVarying = tCoordinates;
        gl_Position = modelViewProjectionMatrix * position;
    }
    

    片段着色器,它“应该”从加载的纹理中获取 vec4 并仅将其作为片段颜色传递:
    uniform sampler2D s_texture;
    
    varying highp vec2 tCoordinatesVarying;
    
    void main()
    {
        gl_FragColor = texture2D(s_texture, tCoordinatesVarying);
    }
    

    以及设置代码,预绘图,在设置顶点属性以及纹理和纹理单元/采样器绑定(bind)的应用程序中:(暂时忽略我不释放CG对象)
     NSString* path = [[NSBundle mainBundle] pathForResource:@"t1.png" ofType:nil];
        NSData* texData = [NSData dataWithContentsOfFile:path];
        UIImage* image = [UIImage imageWithData:texData];
        GLuint width = CGImageGetWidth(image.CGImage);
        GLuint height = CGImageGetHeight(image.CGImage);
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
        void* imageData = malloc(height*width*4);
        CGContextRef context = CGBitmapContextCreate(imageData, width, height, 8, 4*width, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Host);
        CGContextClearRect(context, CGRectMake(0, 0, width, height));
        CGContextDrawImage(context, CGRectMake(0, 0, width, height), image.CGImage);
        CGContextRelease(context);
    
        [EAGLContext setCurrentContext:self.context];
        [self loadShaders];
    
        glEnable(GL_DEPTH_TEST);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
    
        glActiveTexture(GL_TEXTURE0);
    
        glGenTextures(1, &_textureId);
        glBindTexture(GL_TEXTURE_2D, _textureId);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
    
        int loc = glGetUniformLocation(_program, "s_texture");
        glUniform1i(loc, 0);
    
        glGenVertexArraysOES(1, &_vertexArray);
        glBindVertexArrayOES(_vertexArray);
    
        glGenBuffers(1, &_vertexBuffer);
        glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
        glBufferData(GL_ARRAY_BUFFER, vboData->vertexAttributesSize, vboData->vertexAttributes, GL_STATIC_DRAW);
        glEnableVertexAttribArray(GLKVertexAttribPosition);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vboData->vertexAttributesStride,vboData->vPositionOffset);
        glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, vboData->vertexAttributesStride,vboData->vTCoordinatesOffset);
    

    最佳答案

    根据 zacaj 的建议,我意识到我只是没有将任何 texcoords 放入着色器中。错误是:

    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, vboData->vertexAttributesStride,vboData->vTCoordinatesOffset);
    

    所以,我启用了通过 GLKVertexAttribTexCoord0 引用的属性号但在属性 1 中绑定(bind)属性。显然,GLK 常量没有转换为 1。

    而是做
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, vboData->vertexAttributesStride,vboData->vTCoordinatesOffset);
    

    我开始在着色器中获取 texcoords。

    关于ios - 似乎无法将纹理加载到 OpenGL ES 中。我究竟做错了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12850296/

    相关文章:

    iphone - 如何在Cocos2d-x(C++ openGL)中制作可拉伸(stretch)图像

    iphone - 从 iPhone 上的 VBO 读回数据

    linux - 在 x86 Linux 上是否有任何 GLES 示例,用 C++ 编写?

    ios - 使用分组样式时如何计算 UITableView 中单元格的大小?

    iphone - 更改 Storyboard 中的开始 View

    ios - 如何为一个类只运行一次代码

    Android Opengl ES 平铺引擎,平滑滚动

    ios - 对成员 animate 的模糊引用

    ios - 覆盖绘图应用程序的 drawRect

    android - Android 中的 GLES20.glTexImage2d() 和 GLUtils.texImage2d() 有什么区别?