为了获得更好的精度,我绑定了双精度数据,而不是GLfloat,并尝试在着色器中使用数据,如下所示:(我刚刚测试过绘制单个三角形。)

cpp。 >
// xyzw three vertices
double points[] = { 0.0, 0.0, 0.0, 1.0 , 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0 };

glGenVertexArrays(1, VAO);
glBindVertexArray(VAO);

glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, 96, points, GL_STATIC_DRAW);


int data = 0;
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_DOUBLE, GL_FALSE, 0, (void*)data);


着色器。

#version 460 core
layout(location = 0) in dvec4 vPos;


void main() {
    gl_Position = vec4(vPos);
}


我怎么了?

(如果我将上面的着色器中的dvec4更改为vec4,则绘制了三角形,但也许它不再是两倍了。我想在着色器中使用double。)

评论

您需要记住,与使用CPU相比,在GPU上加倍,实际上会显着提高性能,除非您使用的是Quadro或Teslas之类的计算卡。在Nvidia方面,直到最近,您在fp吞吐量和双精度吞吐量之间的比率为1:32。计算7.0,我相信比率会下降到1:2,但我不会指望它会很快好起来,因为Quadros是基于对double到float精度的权衡而出售的,而teslas在这两者上的性能均相同,但与消费者游戏GPU相比并没有其他任何优势。

#1 楼

问题是,glVertexAttribPointer(0, 4, GL_DOUBLE...并没有按照您的想象做。

使用实际的双精度顶点属性并执行双精度计算是一项非常现代的硬件功能(GL4 / DX12),与在良好的旧GL_DOUBLE调用中指定类型glVertexAttribPointer。这始终有效,除了指定输入类型(即内存中顶点数据的类型)外,什么也没有做。它所做的只是使GL将您的双打转换为单打并将其馈送到普通的单精度属性(如果没有则失败),与其他输入类型(如GL_SHORTGL_UNSIGNED_BYTE)相同。

何时为真正的双精度属性指定数据时,必须改用glVertexAttribLPointer(注意L)。真正的整数属性(ivecX / uvecX)也是如此,它们使用glVertexAttribIPointer


当然,如果没有一些一般性的建议,答案是不完整的,您应该确保自己确实需要双精度顶点属性,甚至需要双精度计算。即使在速度仍然很慢的现代硬件上,而不是那些GPU的真正用途,更不用说顶点数据的内存消耗增加了一倍。如果不是必需的话,更高的精度并不一定总会更好。如果使用得当,您可能会惊讶于一个糟糕的小巧float能够完成的任务。