我对OpenGL编程是一个完全的初学者,我正在努力学习
learnopengl.com
但是我想把球画成一个实际的圆,而不是像乔伊建议的那样使用有纹理的四边形。然而,谷歌因为“DrawCircle opengl 3.3”或类似短语而向我抛出的每一个结果似乎都至少有几年的历史了,而且使用的API版本甚至比那个版本还要旧:-(
我找到的最接近的东西是
this SO question
当然,行动只是
使用自定义
VertexFormat
对象抽象了一些细节,没有分享他/她这样的实现!只是我的运气!:页
还有
this YouTube tutorial
它使用了一个看似较旧的API版本,但是逐字复制代码(除了最后几行代码看起来很旧)仍然让我一无所获。
我的版本
SpriteRenderer::initRenderData()
void SpriteRenderer::initRenderData() {
GLuint vbo;
auto attribSize = 0;
GLfloat* vertices = nullptr;
// Determine whether this sprite is a circle or
// quad and setup the vertices array accordingly
if (!this->isCircle) {
attribSize = 4;
vertices = new GLfloat[24] {...} // works for rendering quads
} else {
// This code is adapted from the YouTube tutorial that I linked
// above and is where things go pear-shaped for me...or at least
// **not** circle-shaped :P
attribSize = 3;
GLfloat x = 0.0f;
GLfloat y = 0.0f;
GLfloat z = 0.0f;
GLfloat r = 100.0f;
GLint numSides = 6;
GLint numVertices = numSides + 2;
GLfloat* xCoords = new GLfloat[numVertices];
GLfloat* yCoords = new GLfloat[numVertices];
GLfloat* zCoords = new GLfloat[numVertices];
xCoords[0] = x;
yCoords[0] = y;
zCoords[0] = z;
for (auto i = 1; i < numVertices; i++) {
xCoords[i] = x + (r * cos(i * (M_PI * 2.0f) / numSides));
yCoords[i] = y + (r * sin(i * (M_PI * 2.0f) / numSides));
zCoords[i] = z;
}
vertices = new GLfloat[numVertices * 3];
for (auto i = 0; i < numVertices; i++) {
vertices[i * 3] = xCoords[i];
vertices[i * 3 + 1] = yCoords[i];
vertices[i * 3 + 2] = zCoords[i];
}
}
// This is where I go back to the learnopengl.com code. Once
// again, the following works for quads but not circles!
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, 24 * sizeof(
GLfloat), vertices, GL_STATIC_DRAW);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, attribSize, GL_FLOAT, GL_FALSE,
attribSize * sizeof(GLfloat), (GLvoid*)0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
下面是
SpriteRenderer::DrawSprite()
方法(与原始方法的唯一区别是第24-28行):
void SpriteRenderer::Draw(vec2 position, vec2 size, GLfloat rotation, vec3 colour) {
// Prepare transformations
shader.Use();
auto model = mat4(1.0f);
model = translate(model, vec3(position, 0.0f));
model = translate(model, vec3(0.5f * size.x, 0.5f * size.y, 0.0f)); // Move origin of rotation to center
model = rotate(model, rotation, vec3(0.0f, 0.0f, 1.0f)); // Rotate quad
model = translate(model, vec3(-0.5f * size.x, -0.5f * size.y, 0.0f)); // Move origin back
model = scale(model, vec3(size, 1.0f)); // Lastly, scale
shader.SetMatrix4("model", model);
// Render textured quad
shader.SetVector3f("spriteColour", colour);
glActiveTexture(GL_TEXTURE0);
texture.Bind();
glBindVertexArray(vao);
if (!isCircular) {
glDrawArrays(GL_TRIANGLES, 0, 6);
} else {
glDrawArrays(GL_TRIANGLE_FAN, 0, 24); // also tried "12" and "8" for the last param, to no avail
}
glBindVertexArray(0);
}
最后,着色器(与用于四边形的着色器不同):
// Vertex shader
#version 330 core
layout (location = 0) in vec3 position;
uniform mat4 model;
uniform mat4 projection;
void main() {
gl_Position = projection * model *
vec4(position.xyz, 1.0f);
}
// Fragment shader
#version 330 core
out vec4 colour;
uniform vec3 spriteColour;
void main() {
colour = vec4(spriteColour, 1.0);
}
全部的
P、 我刚意识到learnopengl.com网站这个网站有一个专门调试OpenGL应用程序的部分,所以我设置了这个部分,但是没有用:-(我认为我的驱动程序(inteluhdgraphics620最新的驱动程序)不支持错误处理,因为
GL_CONTEXT_FLAG_DEBUG_BIT
未按照说明进行设置:
在GLFW中请求一个调试上下文非常容易,因为我们所要做的就是向GLFW传递一个提示,表示我们想要一个调试输出上下文。在调用glfwCreateWindow之前,我们必须这样做:
glfwWindowHint(GLFW\u OPENGL\u DEBUG\u CONTEXT,GL\u TRUE);
一旦我们初始化GLFW,如果我们使用的是opengl4.3或更高版本,我们就应该有一个调试上下文,否则我们就必须冒险,希望系统仍然能够请求一个调试上下文。否则,我们必须使用OpenGL扩展请求调试输出。
要检查是否成功初始化调试上下文,可以查询OpenGL:
GLint flags;glGetIntegerv(GL\u CONTEXT\u flags,&flags);
if(标志和GL\u上下文\u标志\u调试\u位){
if
声明永远不会被输入!