我一直在使用LWJGL 3和LearnOpenGL.com上的教程来创建游戏引擎。但是,在学习了本教程之后,我发现使用glVertexAttribPointer
无效。它在上载顶点位置和索引时有效,但是当我尝试上载颜色和纹理坐标时,什么也没有发生,而我只是得到了一个白框。我已经附加了渲染引擎,主类和着色器的源代码:
public class Mesh {
public float[] vertices;
public float[] colors;
public float[] textureCoords;
public int[] indices;
public Mesh(float[] vertices, float[] colors, float[] textureCoords, int[] indices) {
this.vertices = vertices;
this.colors = colors;
this.textureCoords = textureCoords;
this.indices = indices;
}
}
public class MasterRenderer {
private int vbo;
private int vao;
private int ebo;
private Mesh mesh;
private ShaderProgram program;
public void Init(Mesh mesh) {
this.mesh = mesh;
program = new ShaderProgram();
vao = GL30.glGenVertexArrays();
vbo = GL20.glGenBuffers();
ebo = GL20.glGenBuffers();
}
public void Render(Color clearColor) {
// Clear Screen
GL11.glClearColor(clearColor.getRed(), clearColor.getGreen(), clearColor.getBlue(), clearColor.getAlpha());
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
// Bind vao
GL30.glBindVertexArray(vao);
// Bind Buffers
GL20.glBindBuffer(GL20.GL_ARRAY_BUFFER, vbo);
GL20.glBufferData(GL20.GL_ARRAY_BUFFER, mesh.vertices, GL20.GL_STATIC_DRAW);
GL20.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, ebo);
GL20.glBufferData(GL20.GL_ELEMENT_ARRAY_BUFFER, mesh.indices, GL20.GL_STATIC_DRAW);
// Enable vertex attribPointers
GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);
GL20.glEnableVertexAttribArray(0);
// Handle Textures
Texture texture = Utils.LoadTexture("resources//textures//test.png");
// Uniforms
// Use Program
program.UseProgram();
// Draw the shape
GL20.glActiveTexture(GL20.GL_TEXTURE0);
GL20.glBindTexture(GL20.GL_TEXTURE_2D, texture.getId());
GL30.glBindVertexArray(vao);
GL20.glDrawElements(GL20.GL_TRIANGLES, 6, GL20.GL_UNSIGNED_INT, 0);
}
}
public class ShaderProgram {
public int programID;
public int vertexShaderID;
public int fragmentShaderID;
public ShaderProgram() {
programID = GL20.glCreateProgram();
try {
CompileVertexShader(Utils.LoadResource("resources/shaders/default/defaultShader.vs"));
CompileFragmentShader(Utils.LoadResource("resources/shaders/default/defaultShader.fs"));
GL20.glAttachShader(programID, vertexShaderID);
GL20.glAttachShader(programID, fragmentShaderID);
if(GL20.glGetShaderi(vertexShaderID, GL20.GL_COMPILE_STATUS) == 0) {
Logger.LogErrorClose("Error compiling vertex shader code: " + GL20.glGetShaderInfoLog(vertexShaderID, 1024));
}
if(GL20.glGetShaderi(fragmentShaderID, GL20.GL_COMPILE_STATUS) == 0) {
Logger.LogErrorClose("Error compiling fragment shader code: " + GL20.glGetShaderInfoLog(fragmentShaderID, 1024));
}
GL20.glLinkProgram(programID);
} catch (Exception e) {
e.printStackTrace();
}
}
public void UseProgram() {
GL20.glUseProgram(programID);
GL20.glDeleteShader(vertexShaderID);
GL20.glDeleteShader(fragmentShaderID);
}
public void CompileVertexShader(String shaderCode) {
vertexShaderID = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
GL20.glShaderSource(vertexShaderID, shaderCode);
GL20.glCompileShader(vertexShaderID);
}
public void CompileFragmentShader(String shaderCode) {
fragmentShaderID = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER);
GL20.glShaderSource(fragmentShaderID, shaderCode);
GL20.glCompileShader(fragmentShaderID);
}
}
public class Texture {
private int id;
public Texture(int id){
this.id = id;
}
public int getId(){
return id;
}
}
public class FoodFight {
public static void main(String[] args) {
Logger.LogMessage("Running on LWJGL Version: " + Version.getVersion());
Window w = new Window();
long window = w.CreateWindow(640, 360, "Food Fight");
MasterRenderer renderer = new MasterRenderer();
float[] vertices = {
0.5f, 0.5f, 0f,
0.5f, -0.5f, 0f,
-0.5f, -0.5f, 0f,
-0.5f, 0.5f, 0f
};
float[] colors = {
1f, 0f, 0f,
0f, 1f, 0f,
0f, 0f, 1f,
1f, 1f, 0f
};
float[] textureCoords = {
1f, 1f,
1f, 0f,
0f, 0f,
0f, 1f
};
int[] indices = {
0, 1, 3,
1, 2, 3
};
Mesh m = new Mesh(vertices, colors, textureCoords, indices);
renderer.Init(m);
while(!w.ShouldClose(window)) {
Input.ProcessInput(window);
renderer.Render(Color.black);
w.HandleWindow(window);
}
w.DestroyWindow(window);
}
}
片段:
#version 330 core
in vec3 color;
in vec2 texCoords;
out vec4 fragColor;
uniform sampler2D inputTexture;
void main() {
fragColor = texture(inputTexture, texCoords) * vec4(color, 1.0);
}
顶点:
#version 330 core
in vec3 aPos;
in vec3 aColor;
in vec2 aTexCoord;
out vec3 color;
out vec2 texCoord;
void main() {
gl_Position = vec4(aPos, 1.0);
color = aColor;
texCoord = aTexCoord;
}
答案 0 :(得分:1)
由于顶点坐标,颜色和纹理坐标有单独的数组,因此为属性指定了分离缓冲区:
vbo_ver = GL20.glGenBuffers();
vbo_col = GL20.glGenBuffers();
vbo_tex = GL20.glGenBuffers();
创建并初始化缓冲区对象的数据存储
GL20.glBindBuffer(GL20.GL_ARRAY_BUFFER, vbo_ver);
GL20.glBufferData(GL20.GL_ARRAY_BUFFER, mesh.vertices, GL20.GL_STATIC_DRAW);
GL20.glBindBuffer(GL20.GL_ARRAY_BUFFER, vbo_col);
GL20.glBufferData(GL20.GL_ARRAY_BUFFER, mesh.colors, GL20.GL_STATIC_DRAW);
GL20.glBindBuffer(GL20.GL_ARRAY_BUFFER, vbo_tex);
GL20.glBufferData(GL20.GL_ARRAY_BUFFER, mesh.textureCoords, GL20.GL_STATIC_DRAW);
在layout qualifiers的顶点着色器中指定属性索引:
#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aColor;
layout(location = 2) in vec2 aTexCoord;
glVertexAttribPointer
在当前绑定的Vertex Array Object的状态向量中,将当前绑定到ARRAY_BUFFER
目标的缓冲区与指定的属性(索引)相关联。 (请参见Vertex Specification)。
因此,必须在glVertexAttribPointer
之前绑定适当的缓冲区和VAO。
(ELEMENT_ARRAY_BUFFER
是在VAO中声明的,因此必须在指定索引缓冲区之前绑定VAO):
GL30.glBindVertexArray(vao);
GL20.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, ebo);
GL20.glBufferData(GL20.GL_ELEMENT_ARRAY_BUFFER, mesh.indices, GL20.GL_STATIC_DRAW);
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(1);
GL20.glEnableVertexAttribArray(2);
GL20.glBindBuffer(GL20.GL_ARRAY_BUFFER, vbo_ver);
GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);
GL20.glBindBuffer(GL20.GL_ARRAY_BUFFER, vbo_col);
GL20.glVertexAttribPointer(1, 3, GL11.GL_FLOAT, false, 0, 0);
GL20.glBindBuffer(GL20.GL_ARRAY_BUFFER, vbo_tex);
GL20.glVertexAttribPointer(2, 2, GL11.GL_FLOAT, false, 0, 0);
或者,您可以将顶点和属性放入1个数组:
float[] attributes = {
// x y z r g b u v
0.5f, 0.5f, 0f, 1f, 0f, 0f, 1f, 1f,
0.5f, -0.5f, 0f, 0f, 1f, 0f, 1f, 0f,
-0.5f, -0.5f, 0f, 0f, 0f, 1f, 0f, 0f,
-0.5f, 0.5f, 0f, 1f, 1f, 0f 0f, 1f
};
vbo = GL20.glGenBuffers();
GL20.glBindBuffer(GL20.GL_ARRAY_BUFFER, vbo);
GL20.glBufferData(GL20.GL_ARRAY_BUFFER, mesh.attributes, GL20.GL_STATIC_DRAW);
步幅和偏移量必须在bates中指定:
GL20.glBindBuffer(GL20.GL_ARRAY_BUFFER, vbo);
int stride = 8 * 4; // the tuple size is 8 (x y z r g b u v), sizeof float is 4
GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, stride, 0);
GL20.glVertexAttribPointer(1, 3, GL11.GL_FLOAT, false, stride, 3*4);
GL20.glVertexAttribPointer(2, 2, GL11.GL_FLOAT, false, stride, 6*4);