簡體   English   中英

OpenGL ES 2.0紋理無法顯示

[英]OpenGL ES 2.0 Texture Won't Display

因此,我目前正在使用iOS學習OpenGL ES 2.0,並正在從事迷宮游戲。 迷宮是隨機生成的(因此不是加載模型),我的工作是對迷宮的牆壁和地板進行紋理處理。 我的方法是將迷宮視為一系列多維數據集,並且我有代碼分別繪制多維數據集的各個面(因此我可以通過簡單地省略一些面來創建路徑)。

使用捕獲的GPU框架,我已經確認紋理確實正確加載,框架緩沖區中的數據正確,並且沒有出現任何錯誤。 我可以看到其他照明效果(因此臉部不是完全黑色),但沒有紋理出現。

這是我定義立方體面的方法

 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,
};

其他面的定義基本上是相同的方式(除了它們每個都在一個數組中,將位置,法線和tex坐標分開是我嘗試的;我只是想使一個面具有紋理,然后我將擴展到其余部分)。

這是我將數據加載到緩沖區的方法

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

同樣,使用三個緩沖區是一個實驗,其余的都在一個帶有偏移量的緩沖區中定義。

這是我加載紋理的方式

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;
}

然后,在適當的時間,我只需調用glDrawArrays來繪制面。 我對此完全感到困惑,這可能是一個非常愚蠢的錯誤,但是任何人都可以提供的任何幫助將不勝感激。

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;
}

是的,所有統一名稱都是正確的,並且與主代碼中的某些名稱相對應。

編輯:這是頂點着色器

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;
}

原來,我在編譯着色器時忘記綁定屬性位置。 需要添加行

glBindAttribLocation(_program, GLKVertexAttribTexCoord0, "texCoordIn");

加載着色器方法。

總結從注釋中完成的過程...

處理紋理時可能會出錯,因此最好知道如何找出問題所在。

需要注意的是紋理本身:

  • 檢查是否設置了諸如

     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); 
  • 檢查將統一設置為glUniform1i(uniformName, 0) ,其中最后一個參數對應於活動紋理而不是紋理ID。
  • 其他包括檢查統一名稱是否正確,紋理是否綁定。以及(如果可能)檢查調試器是否正確加載了紋理。

緊接着,您的紋理坐標可能會混亂,這似乎是一個非常普遍的問題。 要進行調試,最好將片段着色器中從紋理獲取的顏色替換為紋理坐標本身。 例如用vec4(texCoordOut.x, texCoordOut.y, .0, 1.0) texture2D(texture, texCoordOut)替換texture2D(texture, texCoordOut) vec4(texCoordOut.x, texCoordOut.y, .0, 1.0) 由於紋理坐標應在[0,1]范圍內,因此您應該在場景中看到紅色和綠色之間的良好漸變。 如果看不到它們,則紋理坐標會混亂:如果全部為黑色,則坐標均為零,如果大多數為黃色,則坐標很可能太大。

在您的情況下,紋理坐標全為黑色,這意味着您始終從紋理中獲取第一個像素,因此場景中的顏色恆定。 此時要檢查的是:

  • 您推送到GPU的坐標是否正確
  • 指針是否正確設置為glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 12, BUFFER_OFFSET(0)) (檢查所有參數)
  • 是否啟用了屬性glEnableVertexAttribArray(GLKVertexAttribTexCoord0)
  • 屬性綁定到正在編譯的着色器嗎?

在您的情況下,您忘記綁定紋理坐標屬性,這是很自然會錯過的。

根據您提供給我們的信息,不可能找到此錯誤,但是您應該注意我提供的過程,以查明問題的根源。 將來也可能很方便。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM