【发布时间】:2017-03-29 07:56:29
【问题描述】:
我的 OpenGL 版本是 4.0。我想通过纬度和经度画一个球体。我用这个方法:
x=ρsinϕcosθ
y=ρsinϕsinθ
z=ρcosϕ
这是我的代码的一部分:
glm::vec3 buffer[1000];
glm::vec3 outer;
buffercount = 1000;
float section = 10.0f;
GLfloat alpha, beta;
int index = 0;
for (alpha = 0.0 ; alpha <= PI; alpha += PI/section)
{
for (beta = 0.0 ; beta <= 2* PI; beta += PI/section)
{
outer.x = radius*cos(beta)*sin(alpha);
outer.y = radius*sin(beta)*sin(alpha);
outer.z = radius*cos(alpha);
buffer[index] = outer;
index = index +1;
}
}
GLuint sphereVBO, sphereVAO;
glGenVertexArrays(1, &sphereVAO);
glGenBuffers(1,&sphereVBO);
glBindVertexArray(sphereVAO);
glBindBuffer(GL_ARRAY_BUFFER,sphereVBO);
glBufferData(GL_ARRAY_BUFFER,sizeof(glm::vec3) *buffercount ,&buffer[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
...
while (!glfwWindowShouldClose(window))
{
...
...
for (GLuint i = 0; i < buffercount; i++)
{
...
...
glm::mat4 model;
model = glm::translate(model, buffer[i]);
GLfloat angle = 10.0f * i;
model = glm::rotate(model, angle, glm::vec3(1.0f, 0.3f, 0.5f));
glUniformMatrix4fv(modelMat, 1, GL_FALSE, glm::value_ptr(model));
}
glDrawArrays(GL_TRIANGLE_FAN, 0, 900);
glfwSwapBuffers(window);
}
如果section = 5,表现是这样的:
如果section = 20。表现是这样的:
我认为我的代码中可能存在逻辑问题。我在这个问题上挣扎...
-----更新-----
我编辑了我的代码,它没有任何错误,但我得到了一个空白屏幕。我猜我的顶点着色器出了点问题。我可能会将错误的变量传递给顶点脱落器。请帮我。
gluperspective 在我的 OpenGL 4.1 中已弃用
我切换到:
float aspect=float(4.0f)/float(3.0f);
glm::mat4 projection_matrix = glm::perspective(60.0f/aspect,aspect,0.1f,100.0f);
它表明这个错误:常量表达式的计算结果为 -1,不能缩小到类型 'GLuint'(aka 'unsigned int')
GLuint sphere_vbo[4]={-1,-1,-1,-1};
GLuint sphere_vao[4]={-1,-1,-1,-1};
我不知道如何修改它...我切换到:
GLuint sphere_vbo[4]={1,1,1,1};
GLuint sphere_vao[4]={1,1,1,1};
我把Spektre的代码放在spherer.h文件里
这是我的 main.cpp 文件的一部分:
...
...
Shader shader("basic.vert", "basic.frag");
sphere_init();
while (!glfwWindowShouldClose(window))
{
glfwPollEvents();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
shader.Use();
GLuint MatrixID = glGetUniformLocation(shader.Program, "MVP");
GLfloat radius = 10.0f;
GLfloat camX = sin(glfwGetTime()) * radius;
GLfloat camZ = cos(glfwGetTime()) * radius;
// view matrix
glm::mat4 view;
view = glm::lookAt(glm::vec3(camX, 0.0, camZ), glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0, 1.0, 0.0));
glm::mat4 view_matrix = view;
// projection matrix
float aspect=float(4.0f)/float(3.0f);
glm::mat4 projection_matrix = glm::perspective(60.0f/aspect,aspect,0.1f,100.0f);
// model matrix
glm::mat4 model_matrix = glm::mat4(1.0f);// identity
//ModelViewProjection
glm::mat4 model_view_projection = projection_matrix * view_matrix * model_matrix;
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &model_view_projection[0][0]);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0,0.0,-10.0);
glEnable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);
sphere_draw();
glFlush();
glfwSwapBuffers(window);
}
sphere_exit();
glfwTerminate();
return 0;
}
这是我的顶点着色器文件:
#version 410 core
uniform mat4 MVP;
layout(location = 0) in vec3 vertexPosition_modelspace;
out vec4 vertexColor;
void main()
{
gl_Position = MVP * vec4(vertexPosition_modelspace,1);
vertexColor = vec4(0, 1, 0, 1.0);
}
我在我的 shader.h 文件中添加了错误检查功能 get_log。
...
...
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, NULL);
glCompileShader(vertex);
checkCompileErrors(vertex, "VERTEX");
get_log(vertex);
...
...
void get_log(GLuint shader){
GLint isCompiled = 0;
GLchar infoLog[1024];
glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
if(isCompiled == GL_FALSE)
{
printf("----error--- \n");
GLint maxLength = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
glGetShaderInfoLog(shader, 1024, NULL, infoLog);
std::cout << "| ERROR::::" << &infoLog << "\n| -- ------------------ --------------------------------- -- |" << std::endl;
glDeleteShader(shader); // Don't leak the shader.
}else{
printf("---no error --- \n");
}
}
我测试了片段着色器和顶点着色器,都显示---没有错误---
【问题讨论】:
-
这看起来是对的,你的观点是正确的。只是你没有画出球体的表面,而是一个圆锥形螺旋线或一组在北极点的圆锥体填充了球体.问题是,
buffer是如何变成网格的? -
我非常怀疑您是否可以绘制球形三角形扇形。由于每个三角形都包含北极顶点,因此这仅适用于第一个“环”,而不适用于所有其他“环”。
-
请查看stackoverflow.com/q/5988686/3088138 以了解生成球体的 C++ 方式或将您的语言更改为 [C]。另请参阅stackoverflow.com/a/8044252/3088138,了解
GL_TRIANGLE_FAN如何解释缓冲区数据,从而为您提供所见即所得的信息。 -
在每一层上使用 TRIANGLE_FAN ...它需要设置索引缓冲区来索引哪些点与三角形相连。执行此操作还有另一种选择:sphere triangulation by subdivision 或 Applying map of the earth texture a Sphere。此外,如果您渲染线框,您会更好地了解发生了什么,因为您不使用灯光和法线 ....
-
嗨@LutzL,谢谢你的建议。看起来
glDrawElemen ts(GL_QUADS..GL_QUADS 不支持我的 openGL 版本(我的版本是 4.1)。