OpenGL ES 2.0照明在iOS应用程序中无效

时间:2012-12-31 15:41:26

标签: ios opengl-es-2.0

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

如果有任何帮助,我会非常感激!

屏幕截图

enter image description here

这是我的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);
}

3 个答案:

答案 0 :(得分:2)

我建议首先测试与纹理分开的照明。片段着色器中的乘法意味着如果您的纹理元素是黑色的 - 如果您未能加载纹理或有其他纹理问题,则可能会出现这种情况 - 您将看不到照明代码的输出。

答案 1 :(得分: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个缓冲区我不知道如果有人能发现我无法发现的东西我会感激任何反馈。

非常感谢所有G.C

答案 2 :(得分:0)

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

  • 使用glVertexAttribPointer为每个属性索引进行的设置
  • 已启用的属性数组
  • 绑定元素数组缓冲区

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

但是在代码中,您为每个单独的属性创建一个新的顶点数组对象。然后渲染时只绑定_vertexArray,而GLKVertexAttribPosition只会设置并启用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); 属性,因此不会生成法线,或texCoords或其他任何内容。

所以你应该用原来的代码替换:

{{1}}