从顶点到片段着色器的平滑 64 位输入 - “错误 C7570:64 位输入应该是平坦的”

Posted

技术标签:

【中文标题】从顶点到片段着色器的平滑 64 位输入 - “错误 C7570:64 位输入应该是平坦的”【英文标题】:smooth 64bit input from vertex to frag shader - "error C7570: 64 bit input should be flat" 【发布时间】:2020-08-22 10:47:22 【问题描述】:

我在 OpenGL 中制作了一个小程序来绘制 Mandelbrot set,但是我在片段着色器中使用 64 位值时遇到了一些问题。当我像这样在我的着色器中使用 vec2 类型并在 c++ 中为我的顶点数组使用双精度数组时,一切都按预期工作:

#shader vertex
#version 410 core

layout(location = 0) in vec4 a_position;
layout(location = 1) in vec3 a_colour;
layout(location = 2) in vec2 mandelbrot;
smooth out vec3 frag_colour;
smooth out vec2 frag_mandelbrot;
uniform float view_zoom;
uniform vec2 view_translate;
void main()

    gl_Position = a_position;
    frag_colour = a_colour;
    frag_mandelbrot = (mandelbrot / view_zoom) + view_translate;
;


#shader fragment
#version 410 core

layout(location = 0) out vec3 colour;
in vec3 frag_colour;
in vec2 frag_mandelbrot;

void main()

    double x = 0;
    double y = 0;
    vec3 start = vec3(0.0f, 0.0f, 0.0f);
    vec3 end = vec3(1.0f, 1.0f, 1.0f);
    int iteration = 0;
    int max_iteration = 250;
    while (x*x + y * y <= 2 * 2 && iteration < max_iteration) 
        double xtemp = x * x - y * y + frag_mandelbrot[0];
        y = 2 * x*y + frag_mandelbrot[1];
        x = xtemp;
        iteration++;
    
    float t = float(iteration) / float(max_iteration);
    colour = mix(start,end,t);
;

但是,当我尝试像这样使用 dvec2 类型时:

#shader vertex
#version 410 core

layout(location = 0) in vec4 a_position;
layout(location = 1) in vec3 a_colour;
layout(location = 2) in dvec2 mandelbrot;
smooth out vec3 frag_colour;
smooth out dvec2 frag_mandelbrot;
uniform double view_zoom;
uniform dvec2 view_translate;
void main()

    gl_Position = a_position;
    frag_colour = a_colour;
    frag_mandelbrot = (mandelbrot / view_zoom) + view_translate;
;


#shader fragment
#version 410 core

layout(location = 0) out vec3 colour;
in vec3 frag_colour;
in dvec2 frag_mandelbrot;

void main()

    double x = 0;
    double y = 0;
    vec3 start = vec3(0.0f, 0.0f, 0.0f);
    vec3 end = vec3(1.0f, 1.0f, 1.0f);
    int iteration = 0;
    int max_iteration = 250;
    while (x*x + y * y <= 2 * 2 && iteration < max_iteration) 
        double xtemp = x * x - y * y + frag_mandelbrot[0];
        y = 2 * x*y + frag_mandelbrot[1];
        x = xtemp;
        iteration++;
    
    float t = float(iteration) / float(max_iteration);
    colour = mix(start,end,t);
;

我的片段着色器出现以下编译错误:

0(5):错误 C7570:64 位输入“frag_mandelbrot”应该是平坦的

我的问题是,为什么它应该是平的? GLSL 文档声明如下:

“注意:支持 GLSL 中的精度限定符是为了与 OpenGL ES 兼容。它们使用与 ES 限定符相同的语法,但它们没有功能效果。除非您希望着色器与 ES 兼容,否则不要使用它们。”

所以我认为这些(highp、mediump 等)不适用于普通桌面 opengl。碎片着色器是否不可能将从顶点属性插值的 64 位值作为输入?还是我只是在某个地方犯了一些愚蠢的错误?

【问题讨论】:

【参考方案1】:

片段着色器输入的类型

in dvec2 frag_mandelbrot;

是双精度浮点类型。

查看最新的 GLSL 规范,OpenGL Shading Language 4.60 Specification (html) - 4.3.3. Constant Expressions

[...] 作为或包含整数或双精度浮点类型的片段着色器输入必须使用插值限定符 flat 进行限定。 [...]

【讨论】:

谢谢 - 我想我运气不好,只能使用这种方法将我的 mandelbrot 设置放大到可怜的 32 位精度:P @JimMarshall 是的,你必须使用 32 位浮点数。

以上是关于从顶点到片段着色器的平滑 64 位输入 - “错误 C7570:64 位输入应该是平坦的”的主要内容,如果未能解决你的问题,请参考以下文章

片段着色器是不是处理来自顶点着色器的所有像素?

为啥 gl_Color 不是片段着色器的内置变量?

顶点着色器的绘制操作

跨多个着色器的 OpenGL 统一

传递给片段着色器的纹理坐标全部为 0

如何在片段着色器中找到 4 个顶点之间的插值位置?