Why does this OpenGL ES 2.0 shader not work with my VBO on iOS?

If someone can shed light on what is wrong here, perhaps a violation of the gl rules or some other incompatible sequence of commands, I would be extremely grateful for your help. I try to keep this code running all day without success, despite numerous Google research and examples in the OpenGL ES 2.0 Programming Guide.

I am trying to use the vertex buffer object and custom shaders in OpenGL ES 2.0 on an iPhone. I am trying to alternate vertex data from a series of user structures of the following type:

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

Positions, radius and color bytes should be considered for the location of the vertex, their selection and color, respectively. Identifiers for them are initialized:

 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. 

A step for them is specified in each glVertexAttribPointer call.

It is assumed that each vertex is drawn in its x, y position with the specified color and indicates its radius. Associated with each of the above attributes is the vertex shader attribute, these are "a_position", "a_color" and "a_radius". Here are the vertex and fragment shaders:

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,0.0,0.0,1.0); } 

I wonder if a projection matrix is ​​needed in the vertex shader? All the points that I create are 2D in the size of the iPhone screen, and as you can see, each of them has "z, w" added as "0.0,1.0" in the vertex shader above.

The remaining kernel code for setting up VBO and rendering with glDrawElements is shown below. When running this code, it is obvious that glClear was successful, and the NSLog print confirms this, however, no VType vertices are displayed in the view using the DrawFrame code below. The coordinates of the vertices are within the screen size, for example. x, y: (92, 454).

Note that any undeclared variables in the following code are properties of the class and the corresponding type, for example, “vao” is GLuint, “vbos” is GLuint [2], “program” is the handle of the GLuint program. I also refused the OpenGL installation code, which was tested with various internal code components and shown to work.

Download shader code

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

Initialization Code

  GLfloat screenHeight = [[UIScreen mainScreen] bounds].size.height; GLfloat screenWidth = [[UIScreen mainScreen] bounds].size.width; glViewport(0, 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, 2, GL_FLOAT, GL_FALSE, sizeof(VType), BUFFER_OFFSET(0)); glEnableVertexAttribArray(ID_ATT_Radius);// Radius glVertexAttribPointer(ID_ATT_Radius, 1, GL_FLOAT, GL_FALSE, sizeof(VType), BUFFER_OFFSET(sizeof(float)*2)); glEnableVertexAttribArray(ID_ATT_Color);// Color glVertexAttribPointer(ID_ATT_Color, 4, GL_FLOAT, GL_FALSE, sizeof(VType), 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, GL_INFO_LOG_LENGTH, &infoLen); if (infoLen > 1) { char* infoLog = (char*)malloc(sizeof(char)*infoLen); glGetProgramInfoLog(program, infoLen, NULL, infoLog); NSLog(@"Error linking program:\n%s\n",infoLog); free(infoLog); } glDeleteProgram(program); } 

DrawFrame Code

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

Let me know if any other information is needed, thanks for your time.

+7
source share
1 answer

You don't need a projection matrix for your 2d vertices, but you definitely need to convert all 3 coordinates to the range [-1,1] (which you already did for z by setting it to 0). These coordinates are then converted by GL with the current viewport transformation (which usually should fit your screen size). Therefore, if the coordinates are in screen size, then convert them to [-1,1] in the shader or just use the [-1,1] coordinates in the application (which would also be more inactive).

EDIT: And I don't know how OpenGL ES handles this, but in the desktop GL (at least until 2.1) you need to call glEnable(GL_VERTEX_PROGRAM_POINT_SIZE) so that the vertex shader can chnage the point size.

+3
source

All Articles