OpenGL-шейдер получает неверные данные, даже если они кажутся правильными
Я только начал изучать, как использовать OpenGL 3.2, и сейчас я пытаюсь собрать утилиту для загрузки данных геометрии. Когда я смотрю на код для загрузки в вершинах, все выглядит правильно, и вывод отладки, который я вставляю, даже, кажется, дает мне правильные значения. Код должен создавать один треугольник, в котором каждая точка получает полные значения r, g или b, но вместо этого получает почти чистый красный / оранжевый.
Вот код с данными геометрии:
final float[] vertexPositions3 = new float[] {
0.0f, 0.5f, 0.0f, 1.0f,
0.5f, -0.366f, 0.0f, 1.0f,
-0.5f, -0.366f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
};
geometry = new Geometry();
geometry.addBufferOffset(vertexPositions3, GL_STATIC_DRAW, 0, Geometry.VERTEX_4F, Geometry.VERTEX_4F);
И код, который загружает его:
protected int getDataTypeSize(int dataType) {
if(dataType == VERTEX_1F) {
return 1;
}
else if(dataType == VERTEX_2F) {
return 2;
}
else if(dataType == VERTEX_3F) {
return 3;
}
else {
return 4;
}
}
public void addBufferOffset(float[] data, int usage, int vertexColumn, int... dataTypes) {
if(numAttributes + dataTypes.length >= MAX_VBO) {
throw new IllegalStateException("Can only have up to 16 attributes, requested: " + (numAttributes + dataTypes.length));
}
int rowSize = 0;
for(int type : dataTypes) {
rowSize += getDataTypeSize(type);
}
if(numRows == 0) {
numRows = data.length / rowSize;
}
else if(numRows != (data.length / rowSize)) {
throw new IllegalStateException("Number of rows in buffers don't match: " + numRows + " vs " + (data.length / rowSize));
}
if(numVertices == 0) {
numVertices = getDataTypeSize(dataTypes[0]) * (data.length / rowSize) / getDataTypeSize(dataTypes[0]);
}
else {
int addingVerts = getDataTypeSize(dataTypes[0]) * (data.length / rowSize);
if(addingVerts != numVertices) {
throw new IllegalStateException("Vertex count for buffers don't match: " + numVertices + " vs " + addingVerts);
}
}
glBindVertexArray(vao);
FloatBuffer buf = BufferUtils.createFloatBuffer(data.length);
buf.put(data);
buf.flip();
int vbo = glGenBuffers();
vbos[numBuffers++] = vbo;
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, buf, usage);
int startPos = 0;
for(int i = 0; i < dataTypes.length; i++) {
glEnableVertexAttribArray(numAttributes + i);
glVertexAttribPointer(numAttributes + i, getDataTypeSize(dataTypes[i]), GL_FLOAT, false, 0, startPos);
System.out.println((numAttributes + i) + ", " + getDataTypeSize(dataTypes[i]) + ", " + startPos);
startPos += numRows * getDataTypeSize(dataTypes[i]);
}
System.out.println("Num verts: " + numVertices);
if(usesIndices) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicesRef);
}
numAttributes += dataTypes.length;
glBindVertexArray(0);
}
И вершинный шейдер:
#version 330
layout(location = 0) in vec4 position;
layout(location = 1) in vec4 color;
smooth out vec4 theColor;
uniform float loopDuration;
uniform float time;
uniform vec4 camera;
void main() {
float timeScale = 3.14159f * 2.0f / loopDuration;
vec4 totalOffset = vec4(
cos(time * 1.5f * timeScale) * 0.5f,
sin(time * 1.5f * timeScale) * 0.5f,
0.0f,
0.0f);
gl_Position = position + totalOffset;
theColor = color;
}
И, наконец, фрагмент шейдера:
#version 330
smooth in vec4 theColor;
out vec4 outputColor;
uniform float fragLoopDuration;
uniform float time;
const vec4 firstColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);
const vec4 secondColor = vec4(0.0f, 1.0f, 0.0f, 1.0f);
void main() {
float lerpTime = time * 1.5f / fragLoopDuration;
outputColor = theColor;
}
Когда я запускаю программу, метод addBufferOffset производит следующий вывод:
0, 4, 0
1, 4, 12
Num verts: 3
Это означает, что он нашел два набора из трех вершин с четырьмя значениями с плавающей точкой каждый. Один из них начинается со смещения массива 0, а другой начинается со смещения массива 12. Это соответствует отправляемому в него массиву: 3 вершины со значениями x, y, z, w и 3 вершины с r, g, b, значения. Судя по выходным данным, это должно работать, но это не так. Я был бы очень признателен за помощь в выяснении этого.
1 ответ
Я не знаком с lwjgl, но последний аргумент OpenGL glVertexAttribPointer
Функция в C API - это смещение байтов данных - кажется, что вместо этого вы передаете индекс массива. Это может объяснить, почему вы видите красный / оранжевый треугольник, потому что данные, начинающиеся с 12-го байта (после 3-х чисел), выглядят так:
1.0f, 0.5f, -0.366f, 0.0f,
1.0f, -0.5f, -0.366f, 0.0f,
1.0f, 1.0f, 0.0f, 0.0f
Ограничение этих значений от 0 до 1 даст
1.0f, 0.5f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f, 0.0f,
1.0f, 1.0f, 0.0f, 0.0f
Предполагая, что настройки смешивания таковы, что вы игнорируете нулевой альфа-компонент, они дадут оранжевые, красные и желтые вершины.