【问题标题】:Crash when using matrices as vertex shader attributes使用矩阵作为顶点着色器属性时崩溃
【发布时间】:2014-11-23 16:53:19
【问题描述】:

我正在尝试创建一个 OpenGL 顶点着色器,它对每个顶点都有一个额外的转换矩阵。我的着色器代码如下所示:

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

每当我在 android 模拟器中执行此操作时,模拟器都会崩溃。

我试图找出问题并发现它在我访问vertexTransformation 属性时发生。即使不涉及进一步的矩阵运算,以下代码也会导致崩溃。

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

我正在使用glBufferData 来传递数据:

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

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

然后将属性与

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

我做错了什么?有什么方法可以为顶点提供矩阵属性并在顶点着色器中使用它们?

【问题讨论】:

  • shader中如何传递属性?
  • ByteBuffer vertexData = ...;顶点数据.position(0); GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertexData.remaining(), vertexData, GLES20.GL_STATIC_DRAW);
  • 我的意思是 glVertexAttribPointer 调用 (add them to the post)
  • 你设置了多少个顶点属性数组?一个mat4 顶点属性相当于4 个vec4s,并且应该有4 个单独的属性指针(N,N+1,N+2,N+3),其中N 是“vertexTransformation”的属性位置。您很可能没有其他 3 个数组(N+1 到 N+3)设置为有效状态。

标签: android opengl-es vertex-shader


【解决方案1】:

这段代码是错误的:

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

OpenGL 中的顶点属性始终是 4 分量的,因此mat4 顶点属性实际上是 4 个连续的 4 分量数组。

这是处理mat4 顶点属性的正确方法:

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

注意它需要 4 个顶点属性指针吗?顶点属性“vertexTransformation”实际上占据了handlehandle+3的位置。

【讨论】:

  • 非常感谢,我会试试的。但是如果你说顶点属性总是 4 个分量,为什么 coordinates 向量起作用,因为我在那里只传递了 3 个值?
  • 好吧,你只给它足够的值来满足 4 个组件中的 3 个。这不会改变顶点属性在幕后工作的方式。在这种情况下,w 组件会自动分配一个值 1.0。这就是为什么在顶点着色器中将顶点位置属性写为vec4 通常很方便;如果您了解 OpenGL 在这种情况下的作用,您就不必再写 vec4( coordinates, 1 ) 了。 1.0 自动分配给w 仅适用于w,对于任何其他缺失的组件,GL 会自动分配0.0
猜你喜欢
  • 2013-02-12
  • 1970-01-01
  • 2019-07-31
  • 1970-01-01
  • 1970-01-01
  • 2012-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多