C++ 在现代OpenGL中绘制直线
我只是想在屏幕上画一条线。我正在使用OpenGL4.6。我找到的所有教程都使用了C++ 在现代OpenGL中绘制直线,c++,opengl,graphics,C++,Opengl,Graphics,我只是想在屏幕上画一条线。我正在使用OpenGL4.6。我找到的所有教程都使用了glvertexinter,据我所知,这是不推荐使用的 我知道如何用缓冲区画三角形,所以我试着用一条线。它没有工作,只是显示了一个黑屏。(我使用的是GLFW和GLEW,我使用的是已经在三角形上测试过的顶点+片段着色器) //生成行 浮动线[]={ 0.0, 0.0, 1.0, 1.0 }; 无符号整数缓冲区;//ID是VRAM的指针 glGenBuffers(1,&buffer);//为三角形分配内存 glBindB
glvertexinter
,据我所知,这是不推荐使用的
我知道如何用缓冲区画三角形,所以我试着用一条线。它没有工作,只是显示了一个黑屏。(我使用的是GLFW和GLEW,我使用的是已经在三角形上测试过的顶点+片段着色器)
//生成行
浮动线[]={
0.0, 0.0,
1.0, 1.0
};
无符号整数缓冲区;//ID是VRAM的指针
glGenBuffers(1,&buffer);//为三角形分配内存
glBindBuffer(GL_数组_BUFFER,BUFFER);//将缓冲区设置为活动阵列
glBufferData(GL_数组_BUFFER,2*sizeof(float),line,GL_STATIC_DRAW);//用数据填充缓冲区
glvertexattributepointer(0,2,GL_FLOAT,GL_FALSE,2*sizeof(FLOAT),0);//指定缓冲区如何转换为顶点
GlenableVertexAttributeArray(0);//启用顶点数组
//循环,直到用户关闭窗口
而(!glfwWindowShouldClose(窗口))
{
//清除以前的
glClear(GLU颜色缓冲位);
//划清界限
gldrawArray(GL_线,0,2);
//交换前后缓冲区
glfwSwapBuffers(窗口);
//轮询并处理事件
glfwPollEvents();
}
我的方向是正确的,还是完全不同的方法是当前的最佳实践?
如果是,如何修复代码?问题在于调用。第二个参数是缓冲区的大小(以字节为单位)。由于顶点数组由2个坐标和2个组件组成,因此缓冲区的大小是4*sizeof(float)
,而不是2*sizeof(float)
:
glBufferData(GL_数组_BUFFER,2*sizeof(float),line,GL_STATIC_DRAW)代码>
glBufferData(GL_数组_BUFFER,4*sizeof(float),line,GL_STATIC_DRAW);
但请注意,这仍然不是“现代”的OpenGL。如果您想使用核心配置文件,那么您必须使用程序和
但是,如果您使用的是核心,并且设置了前向兼容性位,则行()的宽度不能大于1.0。
看
宽行-大于1.0的线宽值将生成无效\u值
错误。
你必须找到一种不同的方法
我建议使用a,它沿线条带(甚至是线条循环)生成。
任务是生成粗线条带,尽可能减少CPU和GPU开销。这意味着避免在CPU上计算多边形以及几何体着色器(或细分着色器)
直线的每一段由一个四边形组成,分别由两个三角形图元和六个顶点表示
025
+-------+ +
| / / |
| / / |
| / / |
+ +-------+
1 3 4
在线段之间必须找到斜接,并且必须将四边形切割为斜接
+----------------+
| / |
|第1部分/|
| / |
+--------+ |
|第2部分
| |
| |
+-------+
使用线条带的角点创建阵列。数组必须包含第一个点和最后一个点两次。当然,通过比较索引0和数组长度来识别数组的第一个和最后一个元素是很容易的,但是我们不想在着色器中进行任何额外的检查。
如果必须绘制线循环,则必须将最后一个点添加到阵列头部,将第一个点添加到阵列尾部
点的数组存储到一个数组中。我们使用的好处是,SSBO的最后一个变量可以是一个大小可变的数组。在较旧版本的OpenGL(或OpenGL ES)中,可以使用a或甚至a
着色器不需要任何顶点坐标或属性。我们只需要知道线段的索引。坐标存储在缓冲区中。为了找到索引,我们使用当前正在处理的顶点的索引()。
要使用N
段绘制线条条,6*(N-1)
顶点必须进行tpo处理
我们必须创建一个“空”(没有任何顶点属性规范):
glgenvertexarray(1,&vao);
glBindVertexArray(vao);
并绘制2*(N-1)
三角形(6*(N-1)
顶点):
gldrawArray(GL_三角形,0,6*(N-1));
对于SSBO中的坐标数组,使用了数据类型vec4
(请相信我,您不想使用):
layout(std430,binding=0)缓冲区TVertex
{
vec4顶点[];
};
计算线段的索引,其中顶点坐标也属于该线段,以及2个三角形中点的索引:
int line\u i=gl\u VertexID/6;
int tri_i=gl_VertexID%6;
由于我们正在绘制N-1
线段,但数组中的元素数量为N+2
,因此可以针对顶点着色器中处理的每个顶点访问元素形式为顶点[line\t]
到顶点[line\t+3]
。
顶点[line\u t+1]
和顶点[line\u t+2]
分别是线段的起点和终点坐标<代码>顶点[line\u t]
和顶点[line\u t+3]
是计算斜接所必需的
线条的厚度应以像素为单位设置(均匀浮点u_厚度
)。坐标必须从模型空间转换到窗口空间。为此,必须知道视口的分辨率(uniform vec2 u_分辨率
)。别忘了这道菜。线条的绘制甚至可以在透视投影下进行
vec4va[4];
对于(int i=0;i,以下是如何在“现代”OpenGL(3.3+)中创建两个顶点之间的直线:
顶点着色器:
#version 330 core
layout (location = 0) in vec3 aPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
}
片段着色器:
#version 330 core
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0); // white
}
GLfloat lineSeg[] =
{
0.0f, 0.0f, 0.0f, // first vertex
2.0f, 0.0f, 2.0f // second vertex
};
GLuint lineVAO, lineVBO;
glGenVertexArrays(1, &lineVAO);
glGenBuffers(1, &lineVBO);
glBindVertexArray(lineVAO);
glBindBuffer(GL_ARRAY_BUFFER, lineVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(lineSeg), &lineSeg, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void*)0);
shader.use();
shader.setMat4("projection", projection);
shader.setMat4("view", view);
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(0.0f, 0.5f, 0.0f));
shader.setMat4("model", model);
//glEnable(GL_LINE_SMOOTH);
//glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glBindVertexArray(lineVAO);
glLineWidth(3.3f);
glDrawArrays(GL_LINES, 0, 2);
glLineWidth(1.0f);