为什么这个OpenGL ES 2.0着色器不能在iOS上使用我的VBO?

前端之家收集整理的这篇文章主要介绍了为什么这个OpenGL ES 2.0着色器不能在iOS上使用我的VBO?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
如果有人能够了解这里出了什么问题,也许是对gl命令或其他一些不兼容的命令序列的错误排序,我将非常感谢你的帮助.尽管谷歌在“OpenGL ES 2.0编程指南”中进行了大量研究和研究,但我一直试图让这段代码整天都没有成功.

我正在尝试在iPhone上的OpenGL ES 2.0中使用顶点缓冲区对象和自定义着色器.我试图交错来自以下类型的一系列自定义结构的顶点数据:

typedef struct {
    float x,y; // Position.
    float radius;
    float colR,colG,colB,colA; // Color rgba components.
} VType;

位置,半径和颜色字节分别考虑顶点位置,点大小和颜色.这些的ID已初始化:

ID_ATT_Pos = 0;
ID_ATT_Radius = 1;
ID_ATT_Color = 2;
// Note: I have also tried values of 1,2,3 but no difference.

这些的步幅在每个glVertexAttribPointer调用中指定.

意图是每个顶点在其x,y位置绘制,具有指定的颜色和半径的点数.与每个上述属性相关联的是顶点着色器属性,它们是“a_position”,“a_color”和“a_radius”.以下是顶点和片段着色器:

VertexShader.txt

attribute vec2 a_position;      
attribute vec4 a_color;     
attribute float a_radius;       
varying vec4 v_color;
void main()
{
    gl_Position = vec4(a_position,0.0,1.0);
    gl_PointSize = a_radius;
    v_color = a_color;
}

FragmentShader.txt

#ifdef GL_FRAGMENT_PRECISION_HIGH
    precision highp float;
#else
    precision mediump float;
#endif
void main()
{
    gl_FragColor = vec4(1.0,1.0);
}

我想知道顶点着色器中是否需要投影矩阵?我创建的所有点都是iPhone屏幕尺寸的2D,正如您所看到的,它们每个都在上面的顶点着色器中附加’z,w’作为’0.0,1.0′.

下面列出了使用glDrawElements设置VBO和渲染的剩余核心代码.当运行此代码时,很明显glClear已经成功,并且NSLog打印确实确认了这一点,但是视口中没有通过下面列出的DrawFrame代码绘制VType顶点.顶点坐标完全在屏幕尺寸内,例如x,y:(92,454).

请注意,以下代码中的任何未声明的变量都是类属性,并且具有适当的类型,例如’vao’是GLuint,’vbos’是GLuint [2],’program’是GLuint程序句柄.我还遗漏了样板OpenGL设置代码,该代码已经过不同代码内部测试并显示可以工作.

加载着色器代码

-(GLuint)loadShaderType:(GLenum)type From:(NSString*)shaderFile {
    GLuint shader;
    GLint compiled;

    // Create and compile vertex shader.
    NSString *filepath = [[NSBundle mainBundle] pathForResource:shaderFile ofType:@"txt"];

    const GLchar *shaderSrc = (GLchar *)[[NSString stringWithContentsOfFile:filepath encoding:NSUTF8StringEncoding error:nil] UTF8String];
    if (!shaderSrc) {
        NSLog(@"Failed to load vertex shader");
        return 0;
    }

    // Create shader object.
    shader = glCreateShader(type);
    if (shader == 0) return 0;
    // Load shader source.
    glShaderSource(shader,1,&shaderSrc,NULL);
    // Compile shader.
    glCompileShader(shader);
    // Check compile status.
    glGetShaderiv(shader,GL_COMPILE_STATUS,&compiled);

    if (!compiled) {
        GLint infoLen = 0;
        glGetShaderiv(shader,GL_INFO_LOG_LENGTH,&infoLen);

        if (infoLen > 1) {
            char * infoLog = (char*)malloc(sizeof(char)*infoLen);
            glGetShaderInfoLog(shader,infoLen,NULL,infoLog);
            NSLog(@"Error compiling shader:\n%s\n",infoLog);
            free(infoLog);
        }
        glDeleteShader(shader);
        return 0;
    }
    return shader;
}

初始化代码

GLfloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
GLfloat screenWidth = [[UIScreen mainScreen] bounds].size.width;

glViewport(0,screenWidth,screenHeight);


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

// Generate buffer,bind to use now,set initial data.
glGenBuffers(2,vbos);

glBindBuffer(GL_ARRAY_BUFFER,vbos[0]);
glBufferData(GL_ARRAY_BUFFER,vxBufSize,squidVxs,GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,vbos[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,ixBufSize,squidIxs,GL_STATIC_DRAW);

glEnableVertexAttribArray(ID_ATT_Pos); // Pos   
glVertexAttribPointer(ID_ATT_Pos,GL_FLOAT,GL_FALSE,sizeof(VType),BUFFER_OFFSET(0));
glEnableVertexAttribArray(ID_ATT_Radius);// Radius
glVertexAttribPointer(ID_ATT_Radius,BUFFER_OFFSET(sizeof(float)*2));
glEnableVertexAttribArray(ID_ATT_Color);// Color
glVertexAttribPointer(ID_ATT_Color,4,BUFFER_OFFSET(sizeof(float)*3));

GLuint shaders[2];
shaders[0] = [self loadShaderType:GL_VERTEX_SHADER From:@"VertexShader"];
shaders[1] = [self loadShaderType:GL_FRAGMENT_SHADER From:@"FragmentShader"];

program = glCreateProgram();
glAttachShader(program,shaders[0]);
glAttachShader(program,shaders[1]);

glBindAttribLocation(program,ID_ATT_Pos,"a_position");
glBindAttribLocation(program,ID_ATT_Radius,"a_radius");
glBindAttribLocation(program,ID_ATT_Color,"a_color");

glLinkProgram(program);

GLint linked;
glGetProgramiv(program,GL_LINK_STATUS,&linked);

if (!linked) {
    GLint infoLen = 0;
    glGetProgramiv(program,&infoLen);
    if (infoLen > 1) {
        char* infoLog = (char*)malloc(sizeof(char)*infoLen);
        glGetProgramInfoLog(program,infoLog);
        NSLog(@"Error linking program:\n%s\n",infoLog);
        free(infoLog);
    }
    glDeleteProgram(program);
}

DrawFrame代码

// Note: Framebuffer swapping is taken care of before/after these
//       lines,and has been shown to work.
glClearColor(0.33f,0.0f,0.33f,1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
glDrawElements(GL_POINTS,numPoints,GL_UNSIGNED_SHORT,BUFFER_OFFSET(0));

如果需要任何其他信息,请告诉我,谢谢你的时间.

解决方法

您不一定需要2d顶点的投影矩阵,但您肯定需要将所有3个坐标转换为[-1,1]范围(通过将其设置为0已经为z做了).然后,GL使用当前视口转换(通常应与屏幕尺寸匹配)转换这些坐标.因此,如果坐标在屏幕尺寸中,则在着色器中将它们转换为[-1,1],或者仅在应用程序中使用[-1,1]坐标(这也将更加与分辨率无关).

编辑:我不知道OpenGL ES如何处理这个问题,但是在桌面GL(至少高达2.1)中你需要为顶点着色器调用glEnable(GL_VERTEX_PROGRAM_POINT_SIZE)以便能够控制点大小.

猜你在找的iOS相关文章