The vertices are simply disposed on 2 parallel line, so that every vertices on a line have the y component equal to the other(they practically are along the sides of a rectangle orthogonal to the screen).

I'm working in a 2D world.

I'm trying to position some vertices in specific points i pass to the shader, and make the other vertices interpolate their position from them.

I generate in my code this matrix

u_specialCoordinatesLocation = { x1, x2, x3, x4, y1, y2, y3, y4, x5, x6, x7, x8, y5, y6, y7, y8 };

and pass it to the shader as an uniform (transposing it).

This is the code of the shader. Below i explain it.

/* upperVertexShader*/ /* externally defined: * QUALITY_CODE * SCREEN_WIDTH * SCREEN_HEIGHT */ uniform mat4 u_modelViewProjectionMatrix; uniform vec2 u_playerPosition; uniform float u_elapsedSeconds; /* * mat4 = { * {x1, x2, x3, x4}, * {y1, y2, y3, y4}, * {x5, ...}, * {}} */ uniform mat4 u_specialCoordinatesPosition; attribute vec4 a_position; attribute vec2 a_textureCoordinates; varying vec2 v_textureCoordinates; varying vec2 v_playerPosition; varying vec2 v_pointPosition; const float ERROR_LIMIT = 0.01; const float MIN_VALUE = -2e6; const float MAX_VALUE = 2e6; float linearInterp(float n0, float n1, float a) { return ((1.0 - a) * n0) + (a * n1); } float scurve5(float a) { float a3 = a*a*a; float a4 = a3 * a; float a5 = a4 * a; return (6.0 * a5) - (15.0 * a4) + (10.0 * a3); } float min4fv(vec4 vector) { return min(min(vector.x, vector.y),min(vector.z, vector.w)); } float max4fv(vec4 vector) { return max(max(vector.x, vector.y),max(vector.z, vector.w)); } /* only return the correct value to offset the vertex if the vertex is one of the ones in the uniform, 0.f otherwise*/ float offsetValue(float Xposition) { float offSet = 0.0; vec4 tmp_vector4; vec4 positionX = vec4(Xposition); // first row // 1.0 if positionX is almost equal to the one specified in the uniform tmp_vector4 = 1.0 - step(ERROR_LIMIT, abs(u_specialCoordinatesPosition[0] - positionX)); tmp_vector4 = tmp_vector4 * u_specialCoordinatesPosition[1]; offSet += tmp_vector4.x + tmp_vector4.y + tmp_vector4.z + tmp_vector4.w; // second row tmp_vector4 = 1.0 - step(ERROR_LIMIT, abs(u_specialCoordinatesPosition[2] - positionX)); tmp_vector4 = tmp_vector4 * u_specialCoordinatesPosition[3]; offSet += tmp_vector4.x + tmp_vector4.y + tmp_vector4.z + tmp_vector4.w; return offSet; } vec2 interpolationVertices(float vertexX) { /* .x = left distance * .y = right distance */ vec2 distances; /* 0 if at the left of the vertex, else 1*/ vec4 left_filter; /* 1 if at the left of the vertex, else 0*/ vec4 right_filter; vec4 positionX = vec4(vertexX); /* First row*/ left_filter = step(positionX + ERROR_LIMIT, u_specialCoordinatesPosition[0]); // grants that the vertices at the right of the point will not count, by adding only to them a very negative number distances.x = max4fv(u_specialCoordinatesPosition[0] - positionX + left_filter * MIN_VALUE); right_filter = 1.0 - step(positionX - ERROR_LIMIT, u_specialCoordinatesPosition[0]); // grants that the vertices at the left of the point will not count, by adding only to them a very positive number distances.y = min4fv(u_specialCoordinatesPosition[0] - positionX + left_filter * MAX_VALUE); /* Second row*/ left_filter = step(positionX + ERROR_LIMIT, u_specialCoordinatesPosition[2]); // grants that the vertices at the right of the point will not count, by adding only to them a very negative number distances.x = max(distances.x, max4fv(u_specialCoordinatesPosition[2] - positionX + left_filter * MIN_VALUE)); right_filter = 1.0 - step(positionX - ERROR_LIMIT, u_specialCoordinatesPosition[2]); // grants that the vertices at the left of the point will not count, by adding only to them a very positive number distances.y = min(distances.y , min4fv(u_specialCoordinatesPosition[2] - positionX + left_filter * MAX_VALUE)); return distances; } float interpolatedValue(float vertexX) { vec2 interpVertices = interpolationVertices(vertexX); vec2 interpValue = vec2(offsetValue(vertexX + interpVertices.x), offsetValue(vertexX + interpVertices.y)); float int_value = scurve5(abs((vertexX - interpVertices.x) / (interpVertices.y - interpVertices.x))); return linearInterp(interpValue.x, interpValue.y, int_value); } void main(void) { v_textureCoordinates = a_textureCoordinates; v_playerPosition = u_playerPosition; v_pointPosition = a_position.xy; v_pointPosition.y += interpolatedValue(a_position.x) * (a_position.y) / (a_position.y + 0.0001); vec4 temp_position = u_modelViewProjectionMatrix * vec4(v_pointPosition, a_position.z, a_position.w); gl_Position = temp_position; }

The vertices y position in the VBO have only 2 different values: 0, or another fixed value (SCREEN_HEIGHT/3).

The vertices that have position.y = 0 shouldn't be moved, so

v_pointPosition.y = interpolatedValue(a_position.x) * (a_position.y) / (a_position.y + 0.0001);

is equal 0 if a_position.y is 0, else is almost equal

v_pointPosition.y = interpolatedValue(a_position.x);

The function

float offsetValue(float Xposition)

should find the value of the Ya in the u_specialCoordinateLocation when passed Xa, 0 otherwise.

The 1.0 - step function is used in order to only account for the correct value each time (since only if the passed vertices distance from the Xa is less than ERROR_LIMIT it will be set to 1.0 and then multiplied by the Ya value)

The function

vec2 interpolationVertices(float vertexX)

should find the Xa and Xb value of the 2 vertices inside the u_specialCoordinateLocation matrix that are nearest to the passed x coordinate.

This is achived by calculating the max of the distance from the left (that should be negative) without taking into account the values bigger than 0

In fact

left_filter = step(positionX + ERROR_LIMIT, u_specialCoordinatesPosition[0]);will set each component to 0 for each vertex on the left of the passed X position, and to 1.0 otherwise, while

u_specialCoordinatesPosition[0] - positionX + left_filter * MIN_VALUEwill subtract a big value if the filter component is set to 1, thus making impossible to vertices at the right of the position X to contribute once this value is passed to max4fv()

The same is done for the right distance, and then the 2 X coordinates of the 2 vertices are returned.

Finally

float interpolatedValue(float vertexX)find the 2 vertices "bounding" the passed vertex, retrieve their values, interpolate between them, and return the new position.

I think everything should work, but when i test it on my phone the mesh doesn't show up.

What i'm doing wrong?

Is there a better way of doing it, i must admit that my code isn't really stright forward, and i wish there is a more elegant way?

What do you suggest? (rebuilding the VBO on the cpu and streaming is not a viable option since i would need to do it every frame for 2 meshes of this kind)

Thanks for the help and the patience

**Edited by Makers_F, 20 September 2012 - 06:31 AM.**