OpenGL - 难以构建形状
OpenGL - difficulty with constructing shapes
我正在开始为我的 3D 引擎开发一个简单的形状批处理系统,这将使我能够绘制线条和矩形等...并减少绘制调用次数。我想我已经弄清楚了大部分的基本想法,但是当我尝试绘制多个对象时遇到了问题(目前只是可以指定粗细的线条)。
这是一个屏幕截图,向您展示我的意思:
我使用 glDrawElements
的索引渲染和两个 VBO 来表示顶点数据 - 一个用于位置,一个用于颜色。
我通过指定起点和终点为我的 shape-batcher 构造一条线,如下所示:
shapeRenderer.begin();
shapeRenderer.setViewMatrix(viewMatrix);
shapeRenderer.setProjectionMatrix(projectionMatrix);
shapeRenderer.setCurrentColour(0, 1f, 0);
shapeRenderer.drawLine(2, 2, 5, 2);
shapeRenderer.setCurrentColour(0, 1f, 1f);
shapeRenderer.drawLine(2, 5, 5, 5);
shapeRenderer.end();
屏幕截图中以绿色表示的第一行显示完美。如果我只画一条线,那完全没问题。如果我只画第二条线,它也会完美显示。
当我调用 drawLine
时,将执行以下代码,我用它来计算方向和法线:
private Vector2f temp2fA = new Vector2f();
private Vector2f temp2fB = new Vector2f();
private Vector2f temp2fDir = new Vector2f();
private Vector2f temp2fNrm = new Vector2f();
private Vector2f temp2fTMP = new Vector2f();
private boolean flip = false;
public void drawLine(float xStart, float yStart, float xEnd, float yEnd){
resetLineStates();
temp2fA.set(xStart, yStart);
temp2fB.set(xEnd, yEnd);
v2fDirection(temp2fA, temp2fB, temp2fDir);
v2fNormal(temp2fDir, temp2fNrm);
float halfThickness = currentLineThickness / 2;
//System.out.println("new line called");
v2fScaleAndAdd(temp2fB, temp2fNrm, -halfThickness, temp2fTMP);
pushVertex(temp2fTMP);
v2fScaleAndAdd(temp2fB, temp2fNrm, halfThickness, temp2fTMP);
pushVertex(temp2fTMP);
v2fScaleAndAdd(temp2fA, temp2fNrm, halfThickness, temp2fTMP);
pushVertex(temp2fTMP);
v2fScaleAndAdd(temp2fA, temp2fNrm, -halfThickness, temp2fTMP);
pushVertex(temp2fTMP);
//System.out.println(indexCount + " before rendering.");
int index = indexCount;
pushIndices(index, index + 1, index + 3);
pushIndices(index + 1, index + 2, index + 3);
//System.out.println(indexCount + " after rendering.");
}
private void resetLineStates(){
temp2fA.set(0);
temp2fB.set(0);
temp2fDir.set(0);
temp2fNrm.set(0);
temp2fTMP.set(0);
}
pushIndices
是以下函数:
private void pushIndices(int i1, int i2, int i3){
shapeIndices.add(i1);
shapeIndices.add(i2);
shapeIndices.add(i3);
indexCount += 3;
}
而 pushVertex
是这样工作的:
private void pushVertex(float x, float y, float z){
shapeVertexData[vertexDataOffset] = x;
shapeColourData[vertexDataOffset] = currentShapeColour.x;
shapeVertexData[vertexDataOffset + 1] = y;
shapeColourData[vertexDataOffset + 1] = currentShapeColour.y;
shapeVertexData[vertexDataOffset + 2] = z;
shapeColourData[vertexDataOffset + 2] = currentShapeColour.z;
//System.out.println("\tpushed vertex: " + data.x + ", " + data.y + ", 0");
vertexDataOffset += 3;
}
我正在使用以下字段来存储顶点数据等 - 当我刷新批处理时,这些都被子缓冲到 VBO。如果顶点数据数组的大小不必增长,我会将它们子缓冲到它们各自的 VBO,同样使用元素缓冲区,否则如果它们必须增长,那么我会重新缓冲 VBO 以适应。
private float[] shapeVertexData;
private float[] shapeColourData;
private int vertexDataOffset;
private ArrayList<Integer> shapeIndices;
private int indexCount;
当我在 IDEA 中使用我的调试器时,顶点数据在我构建的数组中看起来完全正确,但是当我在 RenderDoc 中探索它时,它是错误的。我不明白为了得到这些结果我做错了什么,显然即使对于第二个矩形,前两个顶点看起来也完全没问题,但其他的完全错误。
我相信我的着色器不是问题,因为它们非常简单,但它们在这里:
shape_render.vs
(顶点着色器):
#version 330
layout (location = 0) in vec3 aPosition;
layout (location = 1) in vec3 aColour;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
flat out vec3 shapeFill;
void main(){
shapeFill = aColour;
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(aPosition.x, aPosition.y, 0.0, 1.0);
}
shape_render.fs
(片段着色器):
#version 330
layout (location = 0) out vec4 fragColour;
in vec3 shapeFill;
void main(){
fragColour = vec4(shapeFill, 1);
}
我想我已经尽我所知解释了它,任何见解都将不胜感激。我已经检查并确定我正在启用必要的顶点数组等......并渲染正确数量的索引(12):
非常感谢你帮我看看这个。
想了半天终于想通了。这与我如何指定索引有关。我使用了正确数量的索引,但错误地指定了它们。
为了构建三角形的参数,第一个三角形的索引计数为 0,并且有四个顶点,索引将为 1,2,3 和 2,3,1(例如)。然而,对于每个新三角形,我从旧计数加 6 开始索引计数,这对于寻址数组是有意义的,但是因为每个矩形只指定了四个顶点,所以我将索引指向不存在的数据。
因此,我不会在每次推送索引时都使用 indexCount += 3 ,而是获取当前的顶点数并从中构建索引。
我正在开始为我的 3D 引擎开发一个简单的形状批处理系统,这将使我能够绘制线条和矩形等...并减少绘制调用次数。我想我已经弄清楚了大部分的基本想法,但是当我尝试绘制多个对象时遇到了问题(目前只是可以指定粗细的线条)。
这是一个屏幕截图,向您展示我的意思:
我使用 glDrawElements
的索引渲染和两个 VBO 来表示顶点数据 - 一个用于位置,一个用于颜色。
我通过指定起点和终点为我的 shape-batcher 构造一条线,如下所示:
shapeRenderer.begin();
shapeRenderer.setViewMatrix(viewMatrix);
shapeRenderer.setProjectionMatrix(projectionMatrix);
shapeRenderer.setCurrentColour(0, 1f, 0);
shapeRenderer.drawLine(2, 2, 5, 2);
shapeRenderer.setCurrentColour(0, 1f, 1f);
shapeRenderer.drawLine(2, 5, 5, 5);
shapeRenderer.end();
屏幕截图中以绿色表示的第一行显示完美。如果我只画一条线,那完全没问题。如果我只画第二条线,它也会完美显示。
当我调用 drawLine
时,将执行以下代码,我用它来计算方向和法线:
private Vector2f temp2fA = new Vector2f();
private Vector2f temp2fB = new Vector2f();
private Vector2f temp2fDir = new Vector2f();
private Vector2f temp2fNrm = new Vector2f();
private Vector2f temp2fTMP = new Vector2f();
private boolean flip = false;
public void drawLine(float xStart, float yStart, float xEnd, float yEnd){
resetLineStates();
temp2fA.set(xStart, yStart);
temp2fB.set(xEnd, yEnd);
v2fDirection(temp2fA, temp2fB, temp2fDir);
v2fNormal(temp2fDir, temp2fNrm);
float halfThickness = currentLineThickness / 2;
//System.out.println("new line called");
v2fScaleAndAdd(temp2fB, temp2fNrm, -halfThickness, temp2fTMP);
pushVertex(temp2fTMP);
v2fScaleAndAdd(temp2fB, temp2fNrm, halfThickness, temp2fTMP);
pushVertex(temp2fTMP);
v2fScaleAndAdd(temp2fA, temp2fNrm, halfThickness, temp2fTMP);
pushVertex(temp2fTMP);
v2fScaleAndAdd(temp2fA, temp2fNrm, -halfThickness, temp2fTMP);
pushVertex(temp2fTMP);
//System.out.println(indexCount + " before rendering.");
int index = indexCount;
pushIndices(index, index + 1, index + 3);
pushIndices(index + 1, index + 2, index + 3);
//System.out.println(indexCount + " after rendering.");
}
private void resetLineStates(){
temp2fA.set(0);
temp2fB.set(0);
temp2fDir.set(0);
temp2fNrm.set(0);
temp2fTMP.set(0);
}
pushIndices
是以下函数:
private void pushIndices(int i1, int i2, int i3){
shapeIndices.add(i1);
shapeIndices.add(i2);
shapeIndices.add(i3);
indexCount += 3;
}
而 pushVertex
是这样工作的:
private void pushVertex(float x, float y, float z){
shapeVertexData[vertexDataOffset] = x;
shapeColourData[vertexDataOffset] = currentShapeColour.x;
shapeVertexData[vertexDataOffset + 1] = y;
shapeColourData[vertexDataOffset + 1] = currentShapeColour.y;
shapeVertexData[vertexDataOffset + 2] = z;
shapeColourData[vertexDataOffset + 2] = currentShapeColour.z;
//System.out.println("\tpushed vertex: " + data.x + ", " + data.y + ", 0");
vertexDataOffset += 3;
}
我正在使用以下字段来存储顶点数据等 - 当我刷新批处理时,这些都被子缓冲到 VBO。如果顶点数据数组的大小不必增长,我会将它们子缓冲到它们各自的 VBO,同样使用元素缓冲区,否则如果它们必须增长,那么我会重新缓冲 VBO 以适应。
private float[] shapeVertexData;
private float[] shapeColourData;
private int vertexDataOffset;
private ArrayList<Integer> shapeIndices;
private int indexCount;
当我在 IDEA 中使用我的调试器时,顶点数据在我构建的数组中看起来完全正确,但是当我在 RenderDoc 中探索它时,它是错误的。我不明白为了得到这些结果我做错了什么,显然即使对于第二个矩形,前两个顶点看起来也完全没问题,但其他的完全错误。
我相信我的着色器不是问题,因为它们非常简单,但它们在这里:
shape_render.vs
(顶点着色器):
#version 330
layout (location = 0) in vec3 aPosition;
layout (location = 1) in vec3 aColour;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
flat out vec3 shapeFill;
void main(){
shapeFill = aColour;
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(aPosition.x, aPosition.y, 0.0, 1.0);
}
shape_render.fs
(片段着色器):
#version 330
layout (location = 0) out vec4 fragColour;
in vec3 shapeFill;
void main(){
fragColour = vec4(shapeFill, 1);
}
我想我已经尽我所知解释了它,任何见解都将不胜感激。我已经检查并确定我正在启用必要的顶点数组等......并渲染正确数量的索引(12):
非常感谢你帮我看看这个。
想了半天终于想通了。这与我如何指定索引有关。我使用了正确数量的索引,但错误地指定了它们。 为了构建三角形的参数,第一个三角形的索引计数为 0,并且有四个顶点,索引将为 1,2,3 和 2,3,1(例如)。然而,对于每个新三角形,我从旧计数加 6 开始索引计数,这对于寻址数组是有意义的,但是因为每个矩形只指定了四个顶点,所以我将索引指向不存在的数据。 因此,我不会在每次推送索引时都使用 indexCount += 3 ,而是获取当前的顶点数并从中构建索引。