OpenGL:ios 上的 MultiTexture 行为异常

OpenGL: MultiTexture misbehaving on ios

我在向片段着色器发送多个纹理时遇到问题。附件是准系统测试脚本。我正在使用 GLProgram 脚本来加载着色器 (http://iphonedevelopment.blogspot.com.au/2010/11/opengl-es-20-for-ios-chapter-4.html)。

您会在片段着色器中看到我只是使用 mix 将两个纹理组合在一起,但似乎我为 texture1 和 texture2 获得了相同的纹理。

// Extends GLKViewController

#import "ViewControllerImage.h"
#import <OpenGLES/ES2/glext.h>
#import "GLProgram.h"

typedef struct {
    float Position[2];
    float UV[2];
} VertexStruct;

const VertexStruct TestData[] = {
    {{-1.0, 1.0},{0.0, 0.0}},
    {{-1.0, -1.0},{0.0, 1.0}},
    {{1.0, -1.0},{1.0, 1.0}}
};

const GLuint TestIndices[] = {
    0,1,2
};

@implementation ViewControllerImage{
    GLProgram *glProgram;
    EAGLContext *context;
    GLuint uvBuffer;
    GLuint indexBuffer;
    GLuint positionBuffer;
    GLint positionID;
    GLuint uvID;
    GLint textureID1;
    GLint textureID2;
    int indiciesCount;
    int vertexCount;
    GLKTextureInfo *textureInfo1;
    GLKTextureInfo *textureInfo2;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    [self setupContext];
    [self setupShaderProgram];
    [self setupGL];
}

- (void) setupContext{
    context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    [EAGLContext setCurrentContext:context];
    GLKView *glkView = (GLKView *)self.view;
    glkView.context = context;
}

-(void) setupShaderProgram{
    glProgram = [[GLProgram alloc] initWithVertexShaderFilename:@"TestVertex" fragmentShaderFilename:@"TestFragment"];
    //reguster Shader attributes
    [glProgram addAttribute:@"position"];
    [glProgram addAttribute:@"uvPosition"];
    [glProgram addAttribute:@"texture1"];
    [glProgram addAttribute:@"texture2"];

    // Link Program and output log if fails
    if (![glProgram link]){
        NSLog(@"Failed to link");
        glProgram = nil;
        return;
    }
    [glProgram use];

    //retireve attribute indicies
    positionID    = [glProgram attributeIndex:@"position"];
    uvID          = [glProgram attributeIndex:@"uvPosition"];
    textureID1    = [glProgram attributeIndex:@"texture1"];
    textureID2    = [glProgram attributeIndex:@"texture2"];
}

-(void) setupGL{
    vertexCount =   sizeof(TestData)/sizeof(TestData[0]);
    indiciesCount = sizeof(TestIndices)/sizeof(TestIndices[0]);

    glGenBuffers(1, &positionBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(VertexStruct)*vertexCount, &TestData[0].Position, GL_STATIC_DRAW);

    glGenBuffers(1, &uvBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, uvBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(VertexStruct)*vertexCount, &TestData[0].UV, GL_STATIC_DRAW);

    glGenBuffers(1, &indexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(TestIndices), &TestIndices[0], GL_STATIC_DRAW);

    //Bind indicies
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);

    //Bind position and UV buffers
    glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
    glVertexAttribPointer(positionID, 2, GL_FLOAT, GL_FALSE, sizeof(VertexStruct), 0);
    glEnableVertexAttribArray(positionID);

    glBindBuffer(GL_ARRAY_BUFFER, uvBuffer);
    glVertexAttribPointer(uvID, 2, GL_FLOAT, GL_FALSE, sizeof(VertexStruct), 0);
    glEnableVertexAttribArray(uvID);

    //Load textures
NSError *error;
    textureInfo1 = [GLKTextureLoader textureWithCGImage:[[UIImage imageNamed:@"image1.png"] CGImage] options:nil error:&error];
    if(error.description) NSLog(@"Texture 1 error: %@", error.description);
    textureInfo2 = [GLKTextureLoader textureWithCGImage:[[UIImage imageNamed:@"image2.png"] CGImage] options:nil error:&error];
    if(error.description) NSLog(@"Texture 2 error: %@", error.description);

    //Bind Textures
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(textureInfo1.target, textureInfo1.name);
    glUniform1i( textureID1, 0);

    glActiveTexture(GL_TEXTURE1);
    glBindTexture(textureInfo2.target, textureInfo2.name);
    glUniform1i( textureID2, 1);
}

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect{
    glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
    glClear( GL_COLOR_BUFFER_BIT );
    glDrawElements(GL_TRIANGLES, indiciesCount, GL_UNSIGNED_INT, 0);
}

@end

顶点着色器:

precision mediump float;
attribute vec4 position;
attribute vec2 uvPosition;
varying vec2 uv;

void main(void){
    uv = uvPosition;
    gl_Position = position;
}

片段着色器

precision mediump float;
uniform sampler2D texture1;
uniform sampler2D texture2;
varying vec2 uv;

void main(void){
    gl_FragColor = mix(texture2D(texture1, uv),texture2D(texture2, uv),0.5);
}

如果有人能帮助我解决我遇到的这个问题,我将不胜感激。我相信这一定很简单。我还检查了 GL_MAX_TEXTURE_IMAGE_UNITS 其中 returns 8.

好的,我想我已经解决了。我需要从 1 而不是 0 开始纹理单元索引。否则 TEXTURE1 与 TEXTURE0 是相同的纹理!!

不正确:

glActiveTexture(GL_TEXTURE0);
glBindTexture(textureInfo1.target, textureInfo1.name);
glUniform1i(textureID1, 0);

glActiveTexture(GL_TEXTURE1);
glBindTexture(textureInfo2.target, textureInfo2.name);
glUniform1i( textureID2, 1);

正确:

glActiveTexture(GL_TEXTURE1);
glBindTexture(textureInfo1.target, textureInfo1.name);
glUniform1i(textureID1, 1);

glActiveTexture(GL_TEXTURE2);
glBindTexture(textureInfo2.target, textureInfo2.name);
glUniform1i( textureID2, 2);

奇怪。

快点!我想到了。我错误地访问了属性和统一位置。属性使用 glBindAttribLocation 制服使用 glGetUniformLocation 我正在使用 GLProgram class,它使用方便的方法 addAttribute / attributeIndex uniformIndex

这是违规代码:

-(void) setupShaderProgram{
    glProgram = [[GLProgram alloc] initWithVertexShaderFilename:@"TestVertex" fragmentShaderFilename:@"TestFragment"];
    //reguster Shader attributes
    [glProgram addAttribute:@"position"];
    [glProgram addAttribute:@"uvPosition"];
    [glProgram addAttribute:@"texture1"]; //wrong - this is not an attribute
    [glProgram addAttribute:@"texture2"]; //wrong - this is not an attribute

    // Link Program and output log if fails
    if (![glProgram link]){
        NSLog(@"Failed to link");
        glProgram = nil;
        return;
    }
    [glProgram use];

    //retireve attribute indicies
    positionID    = [glProgram attributeIndex:@"position"];
    uvID          = [glProgram attributeIndex:@"uvPosition"];
    textureID1    = [glProgram attributeIndex:@"texture1"]; //Wrong - this is a uniform
    textureID2    = [glProgram attributeIndex:@"texture2"];//Wrong - this is a uniform
}

它应该是这样的:

-(void) setupShaderProgram{
    glProgram = [[GLProgram alloc] initWithVertexShaderFilename:@"EmptyVertex" fragmentShaderFilename:@"EmptyFragment"];
    //register Shader attributes
    [glProgram addAttribute:@"position"];
    [glProgram addAttribute:@"uvPosition"];

    // Link Program and output log if fails
    if (![glProgram link]){
        NSLog(@"Failed to link");
        glProgram = nil;
        return;
    }
    [glProgram use];

    //retrieve attribute indicies
    positionID    = [glProgram attributeIndex:@"position"];
    uvID          = [glProgram attributeIndex:@"uvPosition"];
    //retrieve uniform indicies
    textureID1    = [glProgram uniformIndex:@"texture1"];
    textureID2    = [glProgram uniformIndex:@"texture2"];

}

我真是个菜鸟