Ramopolo Baig
Ramopolo Baig

Reputation: 43

Crash when using matrices as vertex shader attributes

I'm trying to create an OpenGL vertex shader that has an additional transformation matrix for each vertex. My shader code looks like this:

uniform mat4 mvpMatrix;

attribute vec3 coordinates;
attribute mat4 vertexTransformation;
attribute vec4 vertexColor;

varying vec4 v_color;

void main() 
{
    vec4 pos = vec4( coordinates, 1 );

    pos = vertexTransformation * pos;
    pos = mvpMatrix * pos;
    gl_Position = pos;

    v_color = color;
}

Whenever I execute this in the android emulator, the emulator crashes.

I tried to isolate the problem and found that it happens, whenever I access the vertexTransformation attribute. The following code also results in a crash, even if there are no further matrix operations involved.

uniform mat4 mvpMatrix;

attribute vec3 coordinates;
attribute mat4 vertexTransformation;
attribute vec4 vertexColor;

varying vec4 v_color;

void main() 
{
    vec4 pos = vec4( coordinates, 1 );

    pos = mvpMatrix * pos;
    gl_Position = pos;

    vec4 col = vec4( 0,0,0,1 );
    if ( vertexTransformation[0][0] == 0.5 )
        v_color = color;
    else
        v_color = vec4( 1, 1, 1, 1 );    
}    

I'm using glBufferData to pass the data:

ByteBuffer vertexData = ...;
vertexData.position( 0 );

GLES20.glBufferData( GLES20.GL_ARRAY_BUFFER, vertexData.remaining(), vertexData, GLES20.GL_STATIC_DRAW );

and then bind the attributes with

int handle = GLES20.glGetAttribLocation( programId, "vertexTransformation" );
GLES20.glEnableVertexAttribArray( handle );
GLES20.glVertexAttribPointer( handle, 16, GLES20.GL_FLOAT, false, 92, 28 );

What am I doing wrong? Is there any way to provide matrix attributes to a vertex and use them in the vertex shader?

Upvotes: 4

Views: 231

Answers (1)

Andon M. Coleman
Andon M. Coleman

Reputation: 43369

This blurb of code is wrong:

int handle = GLES20.glGetAttribLocation( programId, "vertexTransformation" );
GLES20.glEnableVertexAttribArray( handle );
GLES20.glVertexAttribPointer( handle, 16, GLES20.GL_FLOAT, false, 92, 28 );

Vertex attributes in OpenGL are always 4-component, thus a mat4 vertex attribute is actually 4 sequential 4-component arrays.

This is the proper way of handling a mat4 vertex attribute:

int handle = GLES20.glGetAttribLocation( programId, "vertexTransformation" );

GLES20.glEnableVertexAttribArray( handle );
GLES20.glVertexAttribPointer( handle, 4, GLES20.GL_FLOAT, false, 92, 28 );

GLES20.glEnableVertexAttribArray( handle + 1 );
GLES20.glVertexAttribPointer( handle + 1, 4, GLES20.GL_FLOAT, false, 92, 28+16 );

GLES20.glEnableVertexAttribArray( handle + 2 );
GLES20.glVertexAttribPointer( handle + 2, 4, GLES20.GL_FLOAT, false, 92, 28+32 );

GLES20.glEnableVertexAttribArray( handle + 3 );
GLES20.glVertexAttribPointer( handle + 3, 4, GLES20.GL_FLOAT, false, 92, 28+48 );

Notice how it requires 4 vertex attribute pointers? The vertex attribute "vertexTransformation" actually occupies locations handle through handle+3.

Upvotes: 5

Related Questions