我尝试制作一些可以解决面部法线问题的东西,我不知道它是否有效,我的模型上有光滑的阴影。
它似乎可以很好地作为一个四边形,但是当我尝试一个立方体时,它只在顶部呈现1个四边形,随机变为阴影,其他一切都是黑色的。如果我关闭照明,它只会渲染一个位于顶部的四边形。
模特课:
public class Model {
private int vbo, ibo, vao, tbo, nbo;
private int count = 0;
private float[] normal;
private Matrix4f modelMatrix;
private Vector3f position, rotation;
private Texture texture;
private boolean hasTexture = false;
private String matrixName;
public Model(float[] vertices, String matrixName, int[] ... indices) {
if (!initialized) {
log.err("JORL not initialized", "Run 'init()' at the start of your program");
System.exit(1);
}
this.matrixName = matrixName;
vao = glGenVertexArrays();
vbo = glGenBuffers();
ibo = glGenBuffers();
nbo = glGenBuffers();
for (int[] face : indices)
count += face.length;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
for (int[] face : indices)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, put(face), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, put(vertices), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
normal = new float[count];
int current = 0;
for (int[] face : indices) {
Vector3f p1 = new Vector3f(vertices[face[0] * 3], vertices[face[0] * 3 + 1], vertices[face[0] * 3 + 2]);
Vector3f p2 = new Vector3f(vertices[face[1] * 3], vertices[face[1] * 3 + 1], vertices[face[1] * 3 + 2]);
Vector3f p3 = new Vector3f(vertices[face[2] * 3], vertices[face[2] * 3 + 1], vertices[face[2] * 3 + 2]);
log.info(p1.toString());
log.info(p2.toString());
log.info(p3.toString());
Vector3f U = p2;
Vector3f V = p3;
U.sub(p1);
V.sub(p1);
normal[current * 3] = (U.y * V.z) - (U.z * V.y);
normal[current * 3 + 1] = (U.z * V.x) - (U.x * V.z);
normal[current * 3 + 2] = (U.x * V.y) - (U.y * V.x);
System.out.println(normal[current * 3]);
System.out.println(normal[current * 3 + 1]);
System.out.println(normal[current * 3 + 2]);
current++;
}
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, nbo);
glBufferData(GL_ARRAY_BUFFER, put(normal), GL_STATIC_DRAW);
glVertexAttribPointer(2, 3, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
modelMatrix = new Matrix4f();
position = new Vector3f(0, 0, 0);
rotation = new Vector3f(0, 0, 0);
}
public void setTexture(ShaderProgram shader, Texture texture, float[] coords) {
this.texture = texture;
hasTexture = true;
shader.bind();
shader.editUniform(1, "has_texture");
shader.editUniform(texture.getSampler(), "tex");
shader.bind();
tbo = glGenBuffers();
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, tbo);
glBufferData(GL_ARRAY_BUFFER, put(coords), GL_STATIC_DRAW);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
private FloatBuffer put(float[] data) {
FloatBuffer pData = BufferUtils.createFloatBuffer(data.length);
pData.put(data).flip();
return pData;
}
private IntBuffer put(int[] data) {
IntBuffer pData = BufferUtils.createIntBuffer(data.length);
pData.put(data).flip();
return pData;
}
public void increaseX(float increase) { position.x += increase; }
public void increaseY(float increase) { position.y += increase; }
public void increaseZ(float increase) { position.z += increase; }
public void increaseRotX(float increase) { rotation.x += increase; }
public void increaseRotY(float increase) { rotation.y += increase; }
public void increaseRotZ(float increase) { rotation.z += increase; }
public void render(ShaderProgram shader) {
modelMatrix.identity();
modelMatrix.translate(position);
modelMatrix.rotateX((float) Math.toRadians(rotation.x));
modelMatrix.rotateY((float) Math.toRadians(rotation.y));
modelMatrix.rotateZ((float) Math.toRadians(rotation.z));
shader.editUniform(modelMatrix, matrixName);
glBindVertexArray(vao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(2);
if (hasTexture) {
glEnableVertexAttribArray(1);
texture.bind();
}
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, 0);
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(0);
if (hasTexture) {
glDisableVertexAttribArray(1);
texture.unbind();
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
public void delete() {
glDeleteBuffers(vbo);
glDeleteBuffers(ibo);
glDeleteBuffers(nbo);
if (hasTexture) {
glDeleteBuffers(tbo);
texture.delete();
}
glDeleteVertexArrays(vao);
}
}
我有一个光类,它只向着色器输出颜色和位置矢量。 如果我不使用照明,相机工作正常,其他一切正常。 (除了超过1张脸)。
几何着色器:
#version 400
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
in vec4 colour[];
in vec2 pass_tex_coords[];
in vec3 pass_normal[];
out vec3 t_normal;
out vec3 t_light;
out vec2 pass_tex_coords_;
out vec4 pass_colour;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
uniform vec3 light_position;
void main(void) {
for (int i = 0; i < gl_in.length(); i++) {
vec4 world_pos = projection * view * model * gl_in[i].gl_Position;
gl_Position = world_pos;
pass_tex_coords_ = pass_tex_coords[i];
pass_colour = colour[i];
t_normal = (view * model * vec4(pass_normal[i], 0)).xyz;
t_light = (view * vec4(light_position, 1)).xyz;
EmitVertex();
}
EndPrimitive();
}
片段着色器:
#version 400
in vec4 pass_colour;
in vec2 pass_tex_coords_;
in vec3 t_normal;
in vec3 t_light;
out vec4 out_colour;
uniform int has_texture;
uniform sampler2D tex;
uniform vec4 light_colour;
void main(void) {
vec3 n_normal = normalize(t_normal);
vec3 n_light = normalize(t_light);
float cosTheta = dot(n_normal, n_light);
if (has_texture != 1) {
out_colour = texture(tex, pass_tex_coords_) * pass_colour * cosTheta;
} else {
out_colour = pass_colour;
}
}
如果任何人有任何链接到每个面部照明将是伟大的,我找不到任何。 我认为这与我的带有indices参数的凌乱的Model类有关。
EDIT 所有面孔现在渲染,现在我如何修复奇怪的平滑渐变照明作为每面平面照明?
答案 0 :(得分:0)
上传索引缓冲区似乎是错误的:
for (int[] face : indices)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, put(face), GL_STATIC_DRAW);
此代码在每次迭代中覆盖绑定元素数组缓冲区,但似乎您希望将索引一个接一个地添加到缓冲区。你真正想要的是这样的事情:
//Calculate total length of indices
int lenght = 0;
for (int[] face : indices)
length += face.length;
//Pack data together
IntBuffer pData = BufferUtils.createIntBuffer(length);
int start_idx = 0;
for (int[] face : indices)
{
pData.put(face, start_idx, face.length);
start_idx += face.length;
}
pData.flip();
//Upload to OpenGL
glBufferData(GL_ELEMENT_ARRAY_BUFFER, pData, GL_STATIC_DRAW);
请注意,索引(int[] face
)中的每个条目都必须包含三个元素,因为OpenGL核心配置文件只能绘制三角形。因此,您可以用int length = indices.length * 3;