1

我目前正在学习 OpenGL 2.0 并正在创建一个基本的 iPhone 应用程序。我在搅拌机中创建了一个模型并将其导出到一个 .obj 文件并编写了一个解析器来提取坐标。形状显示正常但没有颜色(黑色)。这意味着法线有问题。但是我检查了法线,发现它们有什么问题。我的代码中是否缺少某些内容?

对于这方面的任何帮助,我将不胜感激!

截屏

在此处输入图像描述

这是我的 OpenGL 代码

glEnable(GL_DEPTH_TEST);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);


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

glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, loader.currentCountOfVerticies * sizeof(GLfloat) * 3, arrayOfVerticies, GL_STATIC_DRAW);

glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 12, BUFFER_OFFSET(0));

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

glGenBuffers(1, &_normalBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _normalBuffer);
glBufferData(GLKVertexAttribNormal, loader.currentCountOfNormals  * sizeof(GLfloat) * 3,loader.arrayOfNormals , GL_STATIC_DRAW);

glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 12, BUFFER_OFFSET(0));

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

glGenBuffers(1, &_textureBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _textureBuffer);
glBufferData(GL_ARRAY_BUFFER, loader.currentCountOfTextureCoordinates * sizeof(GLfloat) * 2, loader.arrayOftextureCoOrdinates, GL_STATIC_DRAW);

glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 8, BUFFER_OFFSET(0));


glBindVertexArrayOES(0);

和我的DrawRect方法

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    glClearColor(0.65f, 0.65f, 0.65f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glBindVertexArrayOES(_vertexArray); 

    glUseProgram(_program);

    glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
    glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m);

    #ifdef DEBUG_VERTEX_DATA_LOOP
    NSLog(@"size of c array * type %ld", loader.currentCountOfVerticies *sizeof(GLfloat));
    #endif

    //Takes in the ammout of indicies not triangels!
    glDrawArrays(GL_TRIANGLES, 0, loader.currentCountOfVerticies);
}

来自加载着色器方法的代码

glBindAttribLocation(_program, GLKVertexAttribPosition, "position");  
glBindAttribLocation(_program, GLKVertexAttribNormal, "normal");
glBindAttribLocation(_program, GLKVertexAttribTexCoord0, "TextCo");

顶点着色器

//  Created by Jake Cunningham on 13/10/2012.
//  Copyright (c) 2012 Jake Cunningham. All rights reserved.
//

attribute vec4 position;
attribute vec3 normal;

varying lowp vec4 colorVarying;

uniform mat4 modelViewProjectionMatrix;
uniform mat3 normalMatrix;

attribute vec2 TextCo;
varying vec2 textCoOut;

void main()
{
    vec3 eyeNormal = normalize(normalMatrix * normal);
    vec3 lightPosition = vec3(0.0, 0.0, 1.0);
    vec4 diffuseColor = vec4(0.4, 0.4, 1.0, 1.0);

    float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition)));

    colorVarying = diffuseColor * nDotVP;

    gl_Position = modelViewProjectionMatrix * position;
    textCoOut = TextCo;
}

片段着色器

//
//  Created by Jake Cunningham on 13/10/2012.
//  Copyright (c) 2012 Jake Cunningham. All rights reserved.
//

varying lowp vec4 colorVarying;

varying lowp vec2 textCoOut;
uniform sampler2D texture;

void main()
{
    gl_FragColor = colorVarying * texture2D(texture, textCoOut);
}
4

3 回答 3

2

我建议首先测试与纹理分开的照明。片段着色器中的乘法意味着如果你的纹素是黑色的——如果你没有加载纹理或有其他纹理问题,很可能是这样——你将看不到照明代码的输出。

于 2013-01-01T20:18:37.300 回答
0

我已经解决了这个问题,但我必须承认我仍然不确定问题是什么。我将我的代码从上面更改为

glEnable(GL_DEPTH_TEST);

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

glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, total * sizeof(GLfloat), mergedArray, GL_STATIC_DRAW);

glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));
glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));

glBindVertexArrayOES(0);

将顶点和法线数组合并到一个缓冲区中解决了这个问题。我现在有照明。为什么我无法使用 2 个缓冲区,我不知道如果有人能发现我看不到的东西,我将不胜感激任何反馈。

非常感谢所有 GC

于 2013-01-02T12:30:53.203 回答
0

问题是您使用了多个顶点数组对象。顶点数组对象 (VAO) 是一个轻量级对象(意味着它不包含任何实际的顶点属性数据),它封装了使用单个绘制调用渲染一组顶点数组所需的所有状态,特别是:

  • glVertexAttribPointer为每个属性索引所做的设置
  • 启用的属性数组
  • 绑定元素数组缓冲区

因此,它比单个顶点属性数组高一级,包括单个(概念)场景对象的所有顶点属性数组设置,或者更准确地说,单个绘制调用。

但是在您的代码中,您为每个单独的属性创建一个新的顶点数组对象。然后渲染时,您只绑定_vertexArray,而后者只设置和启用GLKVertexAttribPosition属性,因此没有法线、texCoords 或其他任何东西。

因此,您应该将原始代码替换为:

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

glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, loader.currentCountOfVerticies * sizeof(GLfloat) * 3, arrayOfVerticies, GL_STATIC_DRAW);

glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 12, BUFFER_OFFSET(0));

//forget this
//glGenVertexArraysOES(1, &_normalArray);
//glBindVertexArrayOES(_normalArray);

glGenBuffers(1, &_normalBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _normalBuffer);
glBufferData(GLKVertexAttribNormal, loader.currentCountOfNormals  * sizeof(GLfloat) * 3,loader.arrayOfNormals , GL_STATIC_DRAW);

glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 12, BUFFER_OFFSET(0));

//and this, too
//glGenVertexArraysOES(1, &_textureArray);
//glBindVertexArrayOES(_textureArray);

glGenBuffers(1, &_textureBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _textureBuffer);
glBufferData(GL_ARRAY_BUFFER, loader.currentCountOfTextureCoordinates * sizeof(GLfloat) * 2, loader.arrayOftextureCoOrdinates, GL_STATIC_DRAW);

glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 8, BUFFER_OFFSET(0));

glBindVertexArrayOES(0);
于 2013-01-02T13:15:34.233 回答