【发布时间】:2015-06-24 11:35:43
【问题描述】:
我对 OpenGL 法线有疑问。 我正在渲染龙模型,但我有一些奇怪的正常模式。
这是我的渲染截图: render_screen
这是我的缓冲区创建方法:
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
if (has_position) {
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * 3 * sizeof(float), vertices.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(kVertexArray);
glVertexAttribPointer(kVertexArray, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
}
if (has_normal) {
glGenBuffers(1, &normal_buffer);
glBindBuffer(GL_ARRAY_BUFFER, normal_buffer);
glBufferData(GL_ARRAY_BUFFER, normals.size() * 3 * sizeof(float), normals.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(kNormalArray);
glVertexAttribPointer(kNormalArray, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
}
if (has_tex_coord) {
glGenBuffers(1, &tex_coord_buffer);
glBindBuffer(GL_ARRAY_BUFFER, tex_coord_buffer);
glBufferData(GL_ARRAY_BUFFER, tex_coords.size() * 3 * sizeof(float), tex_coords.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(kTexCoordArray);
glVertexAttribPointer(kTexCoordArray, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
}
if (has_index) {
glGenBuffers(1, &index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * 3 * sizeof(unsigned short), indices.data(), GL_STATIC_DRAW);
glBindVertexArray(0);
}
并使用:
glDrawElements(GL_TRIANGLES, indices.size() * 3, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));
Wavefront obj 加载器方法:
bool Loadfs() {
CVector3<float> vertex;
CVector3<unsigned short> vindex, tindex, nindex;
while(file_stream->offset_ < file_stream->size_) {
if (file_stream->buffer_[file_stream->offset_] == '#') {
char comment[512] = {0};
file_stream->ReadLine(comment); // check return code -> "its local variable return address"
file_stream->SkipLine();
}
else if (file_stream->buffer_[file_stream->offset_] == 'v') {
file_stream->offset_++;
if (file_stream->buffer_[file_stream->offset_] == ' ') {
has_position = true;
file_stream->offset_++;
file_stream->SkipWhiteSpace();
vertex.x = file_stream->ReadFloat();
file_stream->SkipWhiteSpace();
vertex.y = file_stream->ReadFloat();
file_stream->SkipWhiteSpace();
vertex.z = file_stream->ReadFloat();
file_stream->SkipLine();
vertices.push_back(vertex);
}
else if (file_stream->buffer_[file_stream->offset_] == 'n') {
has_normal = true;
file_stream->offset_++;
file_stream->SkipWhiteSpace();
vertex.x = file_stream->ReadFloat();
file_stream->SkipWhiteSpace();
vertex.y = file_stream->ReadFloat();
file_stream->SkipWhiteSpace();
vertex.z = file_stream->ReadFloat();
file_stream->SkipLine();
normals.push_back(vertex);
}
else if (file_stream->buffer_[file_stream->offset_] == 't') {
has_tex_coord = true;
file_stream->offset_++;
file_stream->SkipWhiteSpace();
vertex.x = file_stream->ReadFloat();
file_stream->SkipWhiteSpace();
vertex.y = file_stream->ReadFloat();
file_stream->SkipWhiteSpace();
vertex.z = file_stream->ReadFloat();
file_stream->SkipLine();
tex_coords.push_back(vertex);
}
}
else if (file_stream->buffer_[file_stream->offset_] == 'f') {
has_index = true;
file_stream->offset_++;
file_stream->SkipWhiteSpace();
//
if (has_position) {
vindex.x = file_stream->ReadShort();
}
if (has_tex_coord) {
file_stream->offset_++;
tindex.x = file_stream->ReadShort();
}
if (has_normal) {
file_stream->offset_++;
nindex.x = file_stream->ReadShort();
}
file_stream->SkipWhile(' ');
//
if (has_position) {
vindex.y = file_stream->ReadShort();
}
if (has_tex_coord) {
file_stream->offset_++;
tindex.y = file_stream->ReadShort();
}
if (has_normal) {
file_stream->offset_++;
nindex.y = file_stream->ReadShort();
}
file_stream->SkipWhile(' ');
//
if (has_position) {
vindex.z = file_stream->ReadShort();
}
if (has_tex_coord) {
file_stream->offset_++;
tindex.z = file_stream->ReadShort();
}
if (has_normal) {
file_stream->offset_++;
nindex.z = file_stream->ReadShort();
}
vi.push_back(--vindex);
ti.push_back(--tindex);
ni.push_back(--nindex);
//indices.push_back(--vindex);
}
else file_stream->SkipLine();
}
indices.insert(indices.end(), vi.begin(), vi.end());
return true;
}
这里 vs:glsl 主要方法:
position_ = MV * vec4(vVertex, 1.0);
normal_ = normalize(N * vNormal);
texture_ = vTexture;
//shadow_ = S * M * vec4(vVertex, 1.0);
gl_Position = MVP * vec4(vVertex, 1.0);
和fs.glsl主要方法:
vec3 rgb = vec3(1.0, 1.0, 1.0);
rgb = PhongShade(g_light, g_material, position_, normal_);
_frag_color = vec4(rgb, 1.0);
//_frag_color = texel * vec4(ambient + diffuse + specular, 1.0);
有人有什么想法吗?
【问题讨论】:
-
这已经以类似的形式出现过很多次了。例如:stackoverflow.com/questions/29718501/… 或 stackoverflow.com/questions/23349080/…。
-
但我认为其中一个使用固定函数,其他使用绘制数组方法。我使用元素方法,所以我应该留下波前文件吗?我也在研究光线追踪。您对我的代码中使用的模型文件类型有什么建议吗?谢谢。
-
如果你想使用 glDrawElements,你可以使用@RetoKoradi 的answer here 中的算法。索引逻辑对于固定功能和可编程管道的工作方式相同,因此不会成为问题。
标签: opengl glsl lighting normals wavefront