Неправильные данные вершин OpenGL ES 2.0

Я пытаюсь визуализировать некоторые точечные спрайты на iOS, но некоторые данные вершин всегда кажутся равными нулю. После нескольких часов отладки я сузил его до этого очень простого примера, пытаясь просто визуализировать одну единственную частицу.

Вершинный шейдер:

uniform mat4 projection;
uniform mat4 modelView;

attribute vec3 position;
attribute vec3 positionEnd;

void main()
{
  vec3 result = position + positionEnd;
  gl_Position = u_projection * u_model_view * vec4(result.x, result.y, result.z, 1.0);
  gl_PointSize = 15.0;
}

Фрагментный шейдер:

uniform sampler2D texture;

void main()
{
  gl_FragColor = texture2D(u_texture, gl_PointCoord);
}

Загрузка данных вершин:

vertices = std::vector<float>(6);
//attribute position
vertices[0] = 0;
vertices[1] = 0;
vertices[2] = 0;
//attribute positionEnd
vertices[3] = 0;
vertices[4] = 0;
vertices[5] = 0;

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

glGenBuffers(1, &mVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.size(), vertices.data(), GL_STATIC_DRAW);

auto positionLocation = glGetAttribLocation(3, "position");
auto positionEndLocation = glGetAttribLocation(3, "positionEnd");

glEnableVertexAttribArray(positionLocation);
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (GLvoid *)0);
glEnableVertexAttribArray(positionEndLocation);
glVertexAttribPointer(positionEndLocation, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (GLvoid *)3);

glBindVertexArrayOES(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);

Рисунок:

glBindVertexArrayOES(mVao);
glDrawArrays(GL_POINTS, 0, 1);

Теперь я установил для всех вершин ноль, что рендерит спрайт в середине экрана, что, однако, вполне нормально, если я изменю данные вершины на

//attribute position
vertices[0] = 20;
vertices[1] = 0;
vertices[2] = 0;
//attribute positionEnd
vertices[3] = -20;
vertices[4] = 0;
vertices[5] = 0;

Его нужно снова нарисовать посередине экрана (используя вышеупомянутый вершинный шейдер), верно? Но это не так, но вместо этого отрисовано 20 единиц вправо. Я предполагаю, что positionEnd (и, следовательно, -20) никогда не устанавливается должным образом в вершинном шейдере, но что я делаю не так?


person cboe    schedule 03.12.2013    source источник


Ответы (1)


Проблема заключается в смещении вашего буфера (последний параметр):

glVertexAttribPointer(positionEndLocation, 3, GL_FLOAT, GL_FALSE, 
                      6 * sizeof(float), (GLvoid*)3);

Вы устанавливаете его на 3, поскольку вы, вероятно, имеете в виду "начать 3 числа с плавающей запятой (один атрибут) позже", но на самом деле это означает "начать на 3 байта позже". Итак, что вам действительно нужно установить для шага, так это размер 3 чисел с плавающей запятой в байтах и, следовательно, 3 * sizeof(float)

glVertexAttribPointer(positionEndLocation, 3, GL_FLOAT, GL_FALSE, 
                      6 * sizeof(float), (GLvoid*)(3*sizeof(float)));

Или, в качестве альтернативы, используйте арифметику указателя:

glVertexAttribPointer(positionEndLocation, 3, GL_FLOAT, GL_FALSE, 
                      6 * sizeof(float), (float*)0 + 3);

И, кстати, твои glGetAttribLocation звонки тоже довольно странные. В качестве первого параметра они ожидают объект программы GLSL (идентификатор, полученный из glCreateProgram). Я никогда не видел, чтобы кто-то использовал там реальное число (хотя объекты GL действительно являются просто числами для внешнего мира, поэтому для целей отладки было бы нормально подключить его, даже если это действительно странно).

person Christian Rau    schedule 03.12.2013
comment
да, столько часов потрачено на такую ​​простую вещь, спасибо! Фактический номер, как вы сказали, предназначен только для отладки, поскольку я знал, что программе будет присвоен номер 3. - person cboe; 03.12.2013