你能用OpenGL 4.4的顶点阵列做到这一点吗
Can you do this with vertex arrays OpenGL 4.4?
我正在加载一个Collada(.dae文件),该模型有两个对象。第一个是一块有很多顶点的布料,材质为浅蓝色。第二个是一个盒子,当布掉下来的时候,应该把它折叠起来。
这应该是一个250帧的动画,但我不确定它是否真的是。当我把它加载到Assimp的aiScene*
中时,它说HasAnimation() == 0
。。。它还说布料的网眼没有颜色,有HasVertexColors() == 0
,这让我担心我必须再看一眼出口。我不知道,也许你能告诉我?我将在外部链接它,因为它太大了,不适合这篇文章。(很抱歉)
落布(Collada animation.dae):http://pastebin.com/54LkKq8k
我的问题是我没有看到浅蓝色的布,盒子是黑色的,就像(0, 0, 0)
。。。
初始化VBO:
void AssimpMesh::initMesh(aiMesh *mesh, MeshData *data) {
//Buffer for temporary storage of new ids
GLuint id;
//Make vertex array
glGenVertexArrays(1, &id);
data->meshArray = id;
//Tell OpenGL to use this array
glBindVertexArray(id);
//Assign vertices
if (mesh->HasPositions()) {
//Make buffer
glGenBuffers(1, &id);
data->buffers.push_back(id);
data->bufferNames.push_back("Positions");
//Set buffer data
glBindBuffer(GL_ARRAY_BUFFER, id);
glBufferData(GL_ARRAY_BUFFER, sizeof(aiVector3D) * mesh->mNumVertices, &mesh->mVertices[0], GL_STATIC_DRAW);
//Set shader attribute data
glEnableVertexAttribArray(VBO_VERTEX);
glVertexAttribPointer(VBO_VERTEX, 3, GL_FLOAT, GL_FALSE, NULL, NULL);
}
//Assign colors
if (mesh->HasVertexColors(0)) {
//Make buffer
glGenBuffers(1, &id);
data->buffers.push_back(id);
data->bufferNames.push_back("Colors");
//Set buffer data
glBindBuffer(GL_ARRAY_BUFFER, id);
glBufferData(GL_ARRAY_BUFFER, sizeof(aiColor4D) * mesh->mNumVertices, &mesh->mColors[0], GL_STATIC_DRAW);
//Set shader attribute data
glEnableVertexAttribArray(VBO_COLOR);
glVertexAttribPointer(VBO_COLOR, 4, GL_FLOAT, GL_FALSE, NULL, NULL);
}
//Assign texture coords
if (mesh->HasTextureCoords(0)) {
//Make buffer
glGenBuffers(1, &id);
data->buffers.push_back(id);
data->bufferNames.push_back("TextureCoords");
//Set buffer data
glBindBuffer(GL_ARRAY_BUFFER, id);
glBufferData(GL_ARRAY_BUFFER, sizeof(aiVector3D) * mesh->mNumVertices, &mesh->mTextureCoords[0], GL_STATIC_DRAW);
//Set shader attribute data
glEnableVertexAttribArray(VBO_TEXCORD);
glVertexAttribPointer(VBO_TEXCORD, 3, GL_FLOAT, GL_FALSE, NULL, NULL);
}
//Assign colors
if (mesh->HasNormals()) {
//Make buffer
glGenBuffers(1, &id);
data->buffers.push_back(id);
data->bufferNames.push_back("Normals");
//Set buffer data
glBindBuffer(GL_ARRAY_BUFFER, id);
glBufferData(GL_ARRAY_BUFFER, sizeof(aiVector3D) * mesh->mNumVertices, &mesh->mNormals[0], GL_STATIC_DRAW);
//Set shader attribute data
glEnableVertexAttribArray(VBO_NORMAL);
glVertexAttribPointer(VBO_NORMAL, 3, GL_FLOAT, GL_FALSE, NULL, NULL);
}
if (mesh->HasFaces()) {
vector <unsigned int> indices;
aiFace face;
for (int i = 0; i < mesh->mNumFaces; i++) {
face = mesh->mFaces[i];
for (int j = 0; j < face.mNumIndices; j++) {
indices.push_back(face.mIndices[j]);
}
}
//Make buffer
glGenBuffers(1, &id);
data->buffers.push_back(id);
data->bufferNames.push_back("Faces");
//Set buffer data
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * indices.size(), &indices.front(), GL_STATIC_DRAW);
}
//Unbind vertex array
glBindVertexArray(NULL);
}
绘图模型:
void AssimpMesh::draw() {
//Draw all vertex arrays
aiMesh *mesh;
aiFace face;
MeshData *data;
for (int i = 0; i < meshes.size(); i++) {
mesh = scene->mMeshes[i];
face = mesh->mFaces[0];
data = meshes[i];
//Tell OpenGL to use this array
glBindVertexArray(data->meshArray);
//Tell OpenGL which shader to use
glUseProgram(data->program);
//Draw the elements of the array
glDrawElements(GL_TRIANGLES, face.mNumIndices * mesh->mNumFaces, GL_UNSIGNED_INT, 0);
}
//Unbind vertex array
glBindVertexArray(NULL);
//Unbind shader
glUseProgram(NULL);
}
顶点着色器:
#version 120
attribute vec3 vertex;
attribute vec4 color;
attribute vec3 texCoord;
attribute vec3 normal;
uniform mat4 transform;
varying vec3 shared_color;
varying vec2 shared_texCoord;
varying vec3 shared_normal;
void main() {
gl_Position = transform * vec4(vertex, 1.0);
//Send data to fragment shader
shared_color = color.xyz;
shared_texCoord = texCoord.xy;
shared_normal = (transform * vec4(normal, 0.0)).xyz;
}
片段着色器:
#version 120
uniform sampler2D diffuse;
uniform int flagTexture;
varying vec3 shared_color;
varying vec2 shared_texCoord;
varying vec3 shared_normal;
void main() {
vec4 color = vec4(shared_color, 1);
vec4 texture = texture2D(diffuse, shared_texCoord);
vec4 finalColor = color;
if (flagTexture >= 1) {
finalColor = vec4(mix(color.rgb, texture.bgr, texture.a), 1);
//finalColor = color * texture;
}
float shade = 0;
if (shade >= 1) {
vec3 lightPosition = vec3(0, 0, -1);
float shadowDarkness = 0.8;
vec3 actualLightPos = vec3(-lightPosition.x, lightPosition.y, lightPosition.z);
float lightStrength = clamp(dot(actualLightPos, shared_normal), 1 - shadowDarkness, 1.0);
vec4 litColor = finalColor * lightStrength;
finalColor = litColor;
}
gl_FragColor = finalColor;
}
在查看了您正在使用的库的文档后,我看到了一些问题:
- 对于颜色,您得到的类型是aiColor4D。顾名思义,这是一个包含4个浮点的类。但是您将3作为大小传递给
glVertexAttribPointer()
的相应调用 - 对于纹理坐标,类型为aiVector3D,其中包含3个浮动。但是您将2作为大小传递给
glVertexAttribPointer()
的相应调用 - aiFace是一个类,它包含一个索引计数和一个指向该面的索引的指针。你不能只把这些家伙的数组作为索引传递给
glBufferData()
。实际上,您传递的是一系列索引计数和指针,而不是一系列索引 glDrawElements()
的第二个参数是索引的数量,而不是三角形的数量
一旦这些问题得到解决,请告诉我们情况如何。另一个常见的错误来源是顶点属性如何与顶点着色器绑定,这是我们在这里看不到的代码。
1)它能工作吗
你测试过了吗?它看起来应该正确渲染,尽管您的释放看起来不正确。glDelete*
为其第二个参数取一个指针;您正在传递对front元素的引用。
更改为:
for (int i = 0; i < buffers.size(); i++) {
glDeleteBuffers(buffers[i].size(), &buffers[i].front());
}
glDeleteVertexArrays(meshes.size(), &meshes.front());
2) 它有什么好处吗
这是一个非常标准的渲染循环,其速度几乎完全取决于着色器的复杂程度。尽管如此,我还是会在循环之外声明一个指针,然后重新分配它,而不是为每个网格声明一个新的指针:
aiMesh *mesh;
for (int i = 0; i < meshes.size(); i++) {
mesh = scene->mMeshes[i];
//Tell OpenGL to use this array
glBindVertexArray(meshes[i]);
//Draw the elements of the array
glDrawElements(GL_TRIANGLES, mesh->mNumFaces, GL_UNSIGNED_INT, 0);
}
3) 额外信息
它有一个可怕的小数学库,我永远不会推荐它,但你应该知道如何处理顶点和以后的事情(例如,当你稍后映射缓冲区时)
因此,如果你想映射你的GL_ARRAY_BUFFER
来修改存储的顶点,你必须使用这样的东西:
glBindVertexArray(the_vao);
aiVector3D *data = reinterpret_cast<aiVector3D*>(glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE));
// do all the changes!
glUnmapBuffer(GL_ARRAY_BUFFER);
我查看了文档,发现HasVertexColors()
实际上不是我想要的材料的漫反射值。因此,我通过使用网格中索引的材质来解决这个问题,并将漫反射颜色提取到大小为mNumVertices
的数组中。
unsigned int matId = mesh->mMaterialIndex;
aiMaterial *material = scene->mMaterials[matId];
vector <aiColor3D> colors;
aiColor3D diffuse(0, 0, 0);
material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse);
for (int i = 0; i < mesh->mNumVertices; i++) {
colors.push_back(diffuse);
}
- 这是什么类型的C++语法,我应该采取什么步骤来理解这一点
- 我无法理解这一点,有人可以帮我解释一下吗?
- 结构本身就包含在内.如何理解这一点?
- 只需要知道我在c ++中打印模式的方式是否有效,或者有另一种方法可以有效地做到这一点
- 我可以直接为指针分配地址吗?如果是,如何做到这一点
- 请证明这一点的合理性 C++.
- 为什么要按值传递string_view?为什么Visual Studio不能优化这一点?
- [expr.unary.op]/9 似乎暗示"运算符!()' 不能应用于下面的类型 A.但编译器不同意这一点
- 为什么我有一个无限循环,我如何以不同的方式做到这一点
- 我想使用 CMake 生成和编译 Visual Studio projet,我需要从构建中排除单元测试文件。有没有办法做到这一点?
- 所有版本的 GCC 都与默认成员初始值设定项作斗争,该初始值设定项捕获了这一点,并结合了继承的构造函数
- 如果有条件使用String.length()的条件,为什么不一致地评估这一点
- 对随机序列进行降采样会降低随机性吗?有没有原理/定理来证明这一点?
- 在C++有没有更好的方法可以做到这一点?检查哪些数字满足条件 [A*B*C = A! + B! + C!]
- 4.5年应该是4年零178年,我如何在C 中做到这一点
- 为什么添加constexpr使VS2013拒绝这一点
- 如何在GTEST中否定匹配者断言或期望这一点
- 循环工作时如何做到这一点?
- 如何做到这一点:Objet.getsObject().setssObject()
- 你能用OpenGL 4.4的顶点阵列做到这一点吗