GLSL 中的版本兼容性

Version Compatibility in GLSL

我正在用 GLSL 做一个项目(我没有这方面的经验)。我目前没有自己编写任何代码,只是想 运行 别人的代码。不幸的是,他们使用 120 版编写代码,而我正在尝试 运行 使用 330 版。注意:我 运行 在 Mac 上使用 10.15 版。这是代码:

# version 330 core
in vec3 mynormal; 
in vec4 myvertex; 

uniform mat4 modelview;

out vec4 fragColor;

uniform vec3 color;

const int numLights = 10; 
uniform bool enablelighting; // are we lighting at all (global).
uniform vec4 lightposn[numLights]; // positions of lights 
uniform vec4 lightcolor[numLights]; // colors of lights
uniform int numused;               // number of lights used  

uniform vec4 ambient; 
uniform vec4 diffuse; 
uniform vec4 specular; 
uniform vec4 emission; 
uniform float shininess; 

vec4 ComputeLight (const in vec3 direction, const in vec4 lightcolor, const in vec3 normal, const in vec3 halfvec, const in vec4 mydiffuse, const in vec4 myspecular, const in float myshininess) {

    float nDotL = max(dot(normal, direction), 0.0);
    vec4 diffuse = mydiffuse * lightcolor * nDotL;

    float nDotH = max(dot(normal, halfvec), 0.0);
    vec4 specular = myspecular * lightcolor * pow(nDotH, myshininess);

    return diffuse + specular;
}

void main (void)
{
    if (enablelighting) {
        const vec3 eyepos = vec3(0,0,0) ;
        vec4 _mypos = gl_ModelViewMatrix * myvertex ;
        vec3 mypos = _mypos.xyz / _mypos.w;
        vec3 eyedir = normalize(eyepos - mypos);

        vec3 _normal = (gl_ModelViewMatrixInverseTranspose*vec4(mynormal,0.0)).xyz ;
        vec3 normal = normalize(_normal);

        gl_FragColor = ambient;
        for (int i = 0; i < numused; ++i) {
            vec3 light_direction;
            if (lightposn[i].w == 0) {
                light_direction = lightposn[i].xyz;
            } else {
                vec3 light_position = lightposn[i].xyz / lightposn[i].w ;
                light_direction = normalize(light_position - mypos); // no attenuation
            }
            vec3 half = normalize (light_direction + eyedir);
            vec4 col = ComputeLight(light_direction, lightcolor[i], normal, half, diffuse, specular, shininess);
            gl_FragColor += col;
        }
    }
    else gl_FragColor = color ;
}

这是我遇到的错误:

Compile Error, Log Below
ERROR: 0:60: Use of undeclared identifier 'gl_ModelViewMatrix'
ERROR: 0:61: Use of undeclared identifier '_mypos'
ERROR: 0:61: Use of undeclared identifier '_mypos'
ERROR: 0:63: Use of undeclared identifier 'mypos'
ERROR: 0:64: Use of undeclared identifier 'gl_NormalMatrix'
ERROR: 0:79: Use of undeclared identifier 'mypos'
ERROR: 0:90: Use of undeclared identifier 'mypos'
ERROR: 0:101: Use of undeclared identifier 'mypos'
ERROR: 0:112: Use of undeclared identifier 'mypos'
ERROR: 0:123: Use of undeclared identifier 'mypos'
ERROR: 0:134: Use of undeclared identifier 'mypos'
ERROR: 0:145: Use of undeclared identifier 'mypos'
ERROR: 0:156: Use of undeclared identifier 'mypos'
ERROR: 0:167: Use of undeclared identifier 'mypos'
ERROR: 0:178: Use of undeclared identifier 'mypos'
ERROR: 0:193: Use of undeclared identifier 'eyedirn'
ERROR: 0:196: Use of undeclared identifier 'normal'
ERROR: 0:196: Use of undeclared identifier 'halfy'
ERROR: 0:197: Use of undeclared identifier 'colApp'
ERROR: 0:206: Use of undeclared identifier 'gl_FragColor'
ERROR: 0:208: Use of undeclared identifier 'gl_FragColor'

google了一下,发现是版本间的兼容性问题。但是,我对 GLSL 的了解还不够,不知道如何解决这个问题。我希望将此文件修改为 运行 而不是尝试自己编写它以兼容版本 330。 谁能给我建议如何将此代码修改为 运行?

最高 OpenGL 2.1。几何是由 glBegin/glEnd 序列或固定函数属性绘制的。顶点坐标已由当前模型视图和投影矩阵转换,无需着色器程序。
为了与着色器程序一起使用,内置制服 gl_ModelViewMatrixgl_NormalMatrixgl_ModelViewMatrixInverseTranspose 等,提供对 Legacy OpenGL matrices. This uniforms are provided up to OpenGL Shading Language 1.20 的访问权限,然后被删除。
在兼容性配置文件 OpenGL Context 中,此类应用程序仍然可以 运行 使用最新的 OpenGL 版本,但顶点着色器无法升级到更高版本。

在 "modern" OpenGL 中,您必须自己管理矩阵变换。矩阵由 Uniform variables(例如类型 mat4)提供给着色器程序。

您的着色器似乎混合了这两种技术。我想是的,因为

的规范
uniform mat4 modelview;

此外,片段着色器输出 gl_FragColor 已弃用。对于片段着色器输出,必须声明一个输出变量。您的着色器也有这样的输出变量:

out vec4 fragColor;

要编译着色器,您必须

  • modelview
  • 代替gl_ModelViewMatrix
  • gl_ModelViewMatrixInverseTranspose 来自 inverse(transpose(modelview))
  • gl_FragColor 通过 fragColor

gl_NormalMatrix 是一个 3x3 矩阵 (mat3) 并且是 gl_ModelViewMatrixInverseTranspose.
的左上角 3x3 gl_NormalMatrix 可以替换为 mat3(inverse(transpose(modelview)))

您不会 "run GLSL" 在真空中,缺少 运行 着色器之外的任何上下文。着色器不能在其设计环境的上下文之外工作。

您使用的着色器是针对固定函数矩阵等编写的。这些矩阵在 GLSL 3.30 中不存在。但是针对 OpenGL 3.3 编写的程序也不 提供 这些矩阵。它正在使用自己的用户定义数据进行渲染。

如果您要将着色器移植到不同的环境,那么您要么可以控制该环境,要么已被告知该环境如何工作。无论哪种方式,您都知道该环境期望在何处拥有其着色器数据。如果您不知道,那么这将行不通。

所以你现在需要的只是了解 1.20 的东西在做什么。然后,您可以用当前着色器环境的数据替换对它们的引用(或者如果尚未提供,则用所述数据对其进行扩充)。因此:

  • gl_ModelViewMatrix:这是模型到相机的变换矩阵。
  • gl_ModelViewMatrixInverseTranspose:这就是上面的inverse/transpose。
  • gl_FragColor:这是这个片段要写入的输出颜色。您应该改为声明一个 layout(location = 0) out vec4 someName; 变量并写入该变量。
  • gl_NormalMatrix:这是一个 3x3 矩阵,旨在用于变换法线。 OpenGL 的计算方式是计算模型-视图矩阵的 inverse/transpose。

因此,只需在这些位置替换您的数据,您应该没问题。