我正在尝试使用一个名为box()的常用函数在OpenGL 4.5中绘制多个框。它似乎工作得相当好,我可以让它制作多个盒子。
然而,我在绘制将成为圆柱底部的东西时遇到了麻烦。我试图通过制作多个三角形来生成面部。三角形在中心共享一个顶点,其他顶点基于角度。
我知道你可以使用三角形扇形或条形来做到这一点,但我需要能够为以后的每个顶点指定法线。
我的问题是,当我渲染这个场景时,我只看到一个孤独的三角形浮动。这提出了两个主要问题:
1)我哪里错了?我通过printf输出验证了x和z坐标是否正确,只是为了看看生成了什么。
2)在绘制完全不同的形状时,交换顶点和颜色缓冲区的正确方法是什么。例如,我需要能够最终调用box(),进行一些变换,调用cylinder()等。
//compiled with g++ -std=c++11 test.cpp -Wall -Werror -lglut -lGLU -lGL -lm -lGLEW
// Link statically with GLEW
#define GLEW_STATIC
// Headers
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace glm;
//Glut
#include <GL/glut.h>
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <math.h>
#include <chrono>
using namespace std::chrono;
#include "cube.h"
#define Cos(x) (cos((x)*3.1415927/180))
#define Sin(x) (sin((x)*3.1415927/180))
GLuint MatrixID;
glm::mat4 MVP;
GLuint vertexbuffer;
GLuint colorbuffer;
GLuint shaderProgram;
high_resolution_clock::time_point t_start;
static const GLchar* vertexSource = {
"#version 330 core\n"
"\n"
"// Input vertex data, different for all executions of this shader.\n"
"layout(location = 0) in vec3 vertexPosition_modelspace;"
"layout(location = 1) in vec3 vertexColor;"
"\n"
"// Output data ; will be interpolated for each fragment.\n"
"out vec3 fragmentColor;"
"// Values that stay constant for the whole mesh.\n"
"uniform mat4 MVP;"
"\n"
"void main(){ "
"\n"
" // Output position of the vertex, in clip space : MVP * position\n"
" gl_Position = MVP * vec4(vertexPosition_modelspace,1);"
"\n"
" // The color of each vertex will be interpolated\n"
" // to produce the color of each fragment\n"
" fragmentColor = vertexColor;"
"}"
};
static const GLchar* fragmentSource = {
"#version 330 core\n"
"\n"
"// Interpolated values from the vertex shaders\n"
"in vec3 fragmentColor;"
"\n"
"// Ouput data\n"
"out vec3 color;"
"\n"
"void main(){"
"\n"
" // Output color = color specified in the vertex shader, \n"
" // interpolated between all 3 surrounding vertices\n"
" color = fragmentColor;"
"\n"
"}"
};
void checkError(int line)
{
GLint err;
do
{
err = glGetError();
switch (err)
{
case GL_NO_ERROR:
//printf("%d: No error\n", line);
break;
case GL_INVALID_ENUM:
printf("%d: Invalid enum!\n", line);
break;
case GL_INVALID_VALUE:
printf("%d: Invalid value\n", line);
break;
case GL_INVALID_OPERATION:
printf("%d: Invalid operation\n", line);
break;
case GL_INVALID_FRAMEBUFFER_OPERATION:
printf("%d: Invalid framebuffer operation\n", line);
break;
case GL_OUT_OF_MEMORY:
printf("%d: Out of memory\n", line);
break;
default:
printf("%d: glGetError default case. Should not happen!\n", line);
}
} while (err != GL_NO_ERROR);
}
int loadShaders()
{
GLuint vertexShader;
GLuint fragmentShader;
// Create shaders
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, NULL);
glCompileShader(vertexShader);
checkError(__LINE__);
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
glCompileShader(fragmentShader);
checkError(__LINE__);
// Create program and link to shaders
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glBindFragDataLocation(shaderProgram, 0, "color");
glLinkProgram(shaderProgram);
checkError(__LINE__);
glUseProgram(shaderProgram);
//TODO: add error checking and return code.
checkError(__LINE__);
return 0;
}
glm::mat4 Projection;
glm::mat4 View;
glm::mat4 Model;
void box()
{
MVP = Projection * View * Model;
// Send our transformation to the currently bound shader
// in the "MVP" uniform
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glDrawArrays(GL_TRIANGLES, 0, 12*3); // 12*3 indices starting at 0 -> 12 triangles
Model = glm::mat4(1.0);
}
typedef struct __vertex
{
GLfloat x;
GLfloat y;
GLfloat z;
} vertex_t;
typedef struct __color
{
GLfloat r;
GLfloat g;
GLfloat b;
} color_t;
void cylinder()
{
int theta = 0;
int dt = 15;
int i = 0;
vertex_t *pVert;
color_t *pColor;
// Bottom face
// 360 / dt = number of triangles
// Multiplied by 3 verticies per triangle
// Multiplied by 3 floating points to describe each vertex
GLfloat *vertex_buffer_data = new GLfloat[360 / dt * 9];
GLfloat *color_buffer_data = new GLfloat[360 / dt * 9];
for (theta=0; theta < 360; theta += dt, i += sizeof(vertex_t) / sizeof(GLfloat))
{
pVert = (vertex_t *)(vertex_buffer_data + i);
pColor = (color_t *)(color_buffer_data + i);
printf("theta: %d\n", theta);
pVert[0].x = 0;
pVert[0].y = 0;
pVert[0].z = 0;
pVert[1].x = Cos(theta);
pVert[1].y = 0;
pVert[1].z = Sin(theta);
printf("Vertex 1: %f %f %f\n", pVert[1].x, pVert[1].y, pVert[1].z);
pVert[2].x = Cos(theta + dt);
pVert[2].y = 0;
pVert[2].z = Sin(theta + dt);
printf("Vertex 2: %f %f %f\n", pVert[2].x, pVert[2].y, pVert[2].z);
pColor[0].r = 1.0f;
pColor[0].g = 1.0f;
pColor[0].b = 1.0f;
pColor[1].r = Cos(theta)*Cos(theta);
pColor[1].g = Sin(theta)*Sin(theta);
pColor[1].b = Cos(theta)*Cos(theta);
pColor[1].r = Cos(theta + dt)*Cos(theta + dt);
pColor[1].g = Sin(theta + dt)*Sin(theta + dt);
pColor[1].b = Cos(theta + dt)*Cos(theta + dt);
}
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 360 / dt * 9, vertex_buffer_data, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 360 / dt * 9, color_buffer_data, GL_STATIC_DRAW);
MVP = Projection * View * Model;
// Send our transformation to the currently bound shader,
// in the "MVP" uniform
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glDrawArrays(GL_TRIANGLES, 0, 360 / dt * 9); // 12*3 indices starting at 0 -> 12 triangles
Model = glm::mat4(1.0);
delete[] vertex_buffer_data;
delete[] color_buffer_data;
}
void display()
{
// Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
// Camera matrix
View = glm::lookAt(
glm::vec3(0,3,0), // Camera is at (4,3,-3), in World Space
glm::vec3(0,0,0), // and looks at the origin
glm::vec3(0,0,1) // Head is up (set to 0,-1,0 to look upside-down)
);
//auto t_now = high_resolution_clock::now();
//float time = duration_cast<duration<float>>(t_now - t_start).count();
glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Model = glm::mat4(1.0);
cylinder();
/*
Model = glm::scale(Model, glm::vec3(0.5, 0.5, 0.5)) * glm::rotate(Model, glm::radians(180.0f), glm::vec3(0.0f, 0.0f, 1.0f));
box();
Model = glm::translate(Model, glm::vec3(0.5, 2.5, 0.0)) * glm::scale(Model, glm::vec3(0.25, 0.25, 0.25)) * glm::rotate(Model, glm::radians(45.0f), glm::vec3(0.0f, 1.0f, 1.0f));
box();
*/
glFlush();
glutSwapBuffers();
}
void reshape(int width,int height)
{
// Set viewport as entire window
glViewport(0,0, width,height);
glutPostRedisplay();
}
void idle()
{
//glutPostRedisplay();
}
int init(int argc, char** argv)
{
t_start = high_resolution_clock::now();
glutInitWindowSize(640, 400);
glutInitWindowPosition (140, 140);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInit(&argc, argv);
glutCreateWindow( "OpenGL Application" );
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutIdleFunc(idle);
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
return -1;
}
loadShaders();
glEnable(GL_DEPTH_TEST);
MatrixID = glGetUniformLocation(shaderProgram, "MVP");
// Load models
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_cube_vertex_buffer_data), g_cube_vertex_buffer_data, GL_STATIC_DRAW);
glGenBuffers(1, &colorbuffer);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_cube_color_buffer_data), g_cube_color_buffer_data, GL_STATIC_DRAW);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 2nd attribute buffer : colors
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glVertexAttribPointer(
1, // attribute. No particular reason for 1, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
return 0;
}
int main(int argc, char** argv)
{
if (init(argc, argv) != 0) { return -1; }
glutMainLoop();
return 0;
}
cube.h只是顶点和颜色的缓冲区:
#ifndef __CUBE_H__
#define __CUBE_H__
static const GLfloat g_cube_vertex_buffer_data[] = {
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f,-1.0f,
1.0f,-1.0f, 1.0f,
-1.0f,-1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
1.0f,-1.0f, 1.0f,
-1.0f,-1.0f, 1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f,-1.0f, 1.0f,
1.0f,-1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f,-1.0f,
-1.0f, 1.0f,-1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f
};
// One color for each vertex. They were generated randomly.
static const GLfloat g_cube_color_buffer_data[] = {
0.583f, 0.771f, 0.014f,
0.609f, 0.115f, 0.436f,
0.327f, 0.483f, 0.844f,
0.822f, 0.569f, 0.201f,
0.435f, 0.602f, 0.223f,
0.310f, 0.747f, 0.185f,
0.597f, 0.770f, 0.761f,
0.559f, 0.436f, 0.730f,
0.359f, 0.583f, 0.152f,
0.483f, 0.596f, 0.789f,
0.559f, 0.861f, 0.639f,
0.195f, 0.548f, 0.859f,
0.014f, 0.184f, 0.576f,
0.771f, 0.328f, 0.970f,
0.406f, 0.615f, 0.116f,
0.676f, 0.977f, 0.133f,
0.971f, 0.572f, 0.833f,
0.140f, 0.616f, 0.489f,
0.997f, 0.513f, 0.064f,
0.945f, 0.719f, 0.592f,
0.543f, 0.021f, 0.978f,
0.279f, 0.317f, 0.505f,
0.167f, 0.620f, 0.077f,
0.347f, 0.857f, 0.137f,
0.055f, 0.953f, 0.042f,
0.714f, 0.505f, 0.345f,
0.783f, 0.290f, 0.734f,
0.722f, 0.645f, 0.174f,
0.302f, 0.455f, 0.848f,
0.225f, 0.587f, 0.040f,
0.517f, 0.713f, 0.338f,
0.053f, 0.959f, 0.120f,
0.393f, 0.621f, 0.362f,
0.673f, 0.211f, 0.457f,
0.820f, 0.883f, 0.371f,
0.982f, 0.099f, 0.879f
};
#endif // __CUBE_H__