Ответ 1
Вы должны использовать треугольник/квадрат тесселяции, в котором каждый патч имеет 3 или 4 вершины. Как я вижу, вы используете квадрациклы (я тоже их использую). В этом случае вы можете установить его так:
glPatchParameteri(GL_PATCH_VERTICES,4);
glBindVertexArray(VertexArray);
(СОВЕТ: используйте чертежные элементы для вашей местности, гораздо лучшую производительность для сетки с 2D-смещением).
В контрольном шейдере используйте
layout (vertices = 4) out;
так как ваш патч имеет 4 контрольных точки. Заказ по-прежнему важен (CCW/CW).
Лично я не люблю использовать встроенные переменные, поэтому для вершинного шейдера вы можете отправить свои данные вершин в tesscontrol следующим образом:
layout (location = 0) out vec3 outPos;
....
outPos.xz = grid.xy;
outPos.y = noise(outPos.xz);
Управление теснением:
layout (location = 0) in vec3 inPos[]; //outPos (location = 0) from vertex shader
//'collects' the 4 control points to an array in the order they're sended
layout (location = 0) out vec3 outPos[]; //send the c.points to the ev. shader
...
gl_TessLevelOuter[0] = outt[0];
gl_TessLevelOuter[1] = outt[1];
gl_TessLevelOuter[2] = outt[2];
gl_TessLevelOuter[3] = outt[3];
gl_TessLevelInner[0] = inn[0];
gl_TessLevelInner[1] = inn[1];
outPos[ID] = inPos[ID];//gl_invocationID = ID
Обратите внимание, что как внутренние, так и внешние данные вершин являются массивом.
Тессев прост:
layout (location = 0) in vec3 inPos[]; //the 4 control points
layout (location = 0) out vec3 outPos; //this is no longer array, next is the fragment shader
...
//edit: do not forgot to add the next line
layout (quads) in;
vec3 interpolate3D(vec3 v0, vec3 v1, vec3 v2, vec3 v3) //linear interpolation for x,y,z coords on the quad
{
return mix(mix(v0,v1,gl_TessCoord.x),mix(v3,v2,gl_TessCoord.x),gl_TessCoord.y);
};
...main{...
outPos = interpolate3D(inPos[0],inPos[1],inPos[2],inPos[3]); //the four control points of the quad. Every other point is linearly interpolated between them according to the TessCoord.
gl_Position = mvp * vec4(outPos,1.0f);
Хорошее представление четырехмерного домена: http://ogldev.atspace.co.uk/www/tutorial30/tutorial30.html.
Я думаю, проблема связана с вашим одновершинным патчем. Я не могу представить, как один вершинный путь можно разделить на треугольники, я не знаю, как он работает на другом оборудовании. Тесселяция состоит в том, чтобы делить примитивы на другие простые примитивы, на треугольники в случае OGL, так как это может быть легко обработано графическим процессором (3 точки всегда лежат в плоскости). Итак, минимальное количество вершин патчей должно быть 3, для треугольника. Мне нравятся квадроциклы, потому что он проще индексировать, а стоимость памяти меньше. Он также будет разделен на треугольники во время тесселяции. http://www.informit.com/articles/article.aspx?p=2120983 Кроме того, существует другой тип - тесселяция изоляции. (проверьте ссылки, второй очень хорош.)
В общем, попробуйте с помощью квадов или треугольников и установите контрольные вершины на 4 (или 3). Мой (довольно сложный) рельефный шейдер здесь, с усеченным отрезком, тесселяционным шейдером, отбирающим для местности, основанной на геоклипаме. Кроме того, без тесселяции он работает с вершинным морфом в вершинном шейдере. Возможно, какая-то часть этого кода будет полезна. http://speedy.sh/TAvPR/gshader.txt
Сцена с тесселяцией около 4 пикселов/треугольников работает при 75 FPS (с фреймами) с обычным вычислением времени выполнения и бикубическим сглаживанием и другими вещами. Я использую AMD HD 5750. Он все еще может быть намного быстрее с лучшим кодом и предварительно испеченными нормалями: D. (работает при макс. 120 w/o нормальном расчете).
О, и вы можете отправлять координаты x и z только в том случае, если вы смещаете вершину в шейдере. Это также будет быстрее.
Множество вершин.