【问题标题】:GLSL: shader linking fail (but no log)GLSL:着色器链接失败(但没有日志)
【发布时间】:2014-02-05 17:58:17
【问题描述】:

我正在尝试为窗口的亮度和对比度创建一个小着色器(我见过here)。

我可以加载文件,并成功编译着色器。但我无法链接它。我的问题是日志没有输出,所以我看不出它有什么问题。如何检查链接问题?在哪里可以找到有关链接失败的信息,并检查链接失败的原因(我是着色器新手)。

我使用的是 Ubuntu 12.04。

这是初始化代码

if (GLEW_ARB_fragment_shader) {
    // I enter here so I suppose that shader is enabled for
    // my graphics card
    std::cout << "arb shader enabled" << std::endl;
}

// Loading shader
string fragmentShaderSource;
GLint len;
std::ifstream in("/path/to/file.glsl");
fragmentShaderSource = std::string((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
len = fragmentShaderSource->size();

// I've checked the string and file seems to be loaded properly.

// Creating shader
GLint flength;
GLuint fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
GLcharARB** text = new (GLcharARB*);
text[0] = (char*)fragmentShaderSource.c_str();
glShaderSourceARB(fragmentShader, 1, (const GLcharARB**) text, &flength);

// Compile shader
glCompileShaderARB(fragmentShader);
GLint compiled;

glGetObjectParameteriv(ShaderObject, GL_COMPILE_STATUS, &compiled);
if (compiled)
{
    // I enter here so I suppose that compilation is ok.
    std::cout << "shader compiled" << std::endl;
} 

// Attaching to program
GLuint program;
program = glCreateProgram();
glAttachShader(program, fragmentShader);

// Linking
glLinkProgram(program);

// Link check
GLint linked;
glGetProgramivARB(program, GL_LINK_STATUS, &linked);
if (linked) {
    std::cout << "linked" << std::endl;
} else {
    // I enter here so linking is failed
    std::cout << "not linked" << std::endl;
    GLint blen = 0;
    GLsizei slen = 0;
    glGetShaderiv(program, GL_INFO_LOG_LENGTH, &blen);
    // blen is equal to zero so I cannot print the log message
    // because it's absent
    if (blen > 1) {
        GLchar* linking_log = (GLchar*) malloc(blen);
        glGetProgramInfoLog(program, blen, &slen, linking_log);
        glGetInfoLogARB(program, blen, &slen, linking_log);
        std::cout << "compiler_log:\n" << linking_log << std::endl;
        free(linking_log);
    }
}

这是我加载的 glsl 代码

uniform float Brightness : register(C0);
uniform float Contrast : register(C1);

sampler2D Texture1Sampler : register(S0);

float4 main(float2 uv : TEXCOORD) : COLOR
{
    float4 pixelColor = tex2D(Texture1Sampler, uv);
    pixelColor.rgb /= pixelColor.a;

    // Apply contrast.
    pixelColor.rgb = ((pixelColor.rgb - 0.5f) * max(Contrast, 0)) + 0.5f;

    // Apply brightness.
    pixelColor.rgb += Brightness;

    // Return final pixel color.
    pixelColor.rgb *= pixelColor.a;
    return pixelColor;
}

编辑:

我修复了日志,当链接失败时,我得到以下输出:

Fragment info
-------------
0(1) : warning C7557: OpenGL does not allow Cg-style semantics
0(2) : warning C7557: OpenGL does not allow Cg-style semantics
0(4) : warning C7557: OpenGL does not allow Cg-style semantics
0(4) : warning C7554: OpenGL requires sampler variables to be explicitly declared as uniform
0(6) : warning C7506: OpenGL does not define the global type float4
0(6) : warning C7506: OpenGL does not define the global type float2
0(6) : warning C7557: OpenGL does not allow Cg-style semantics
0(6) : warning C7557: OpenGL does not allow Cg-style semantics
0(6) : warning C7527: OpenGL requires main to take no parameters
0(6) : warning C7530: OpenGL requires main to return void
0(9) : warning C7506: OpenGL does not define the global function tex2D
0(13) : warning C7502: OpenGL does not allow type suffix 'f' on constant literals in versions below 120
0(13) : warning C7011: implicit cast from "int" to "float"
0(13) : warning C7502: OpenGL does not allow type suffix 'f' on constant literals in versions below 120

EDIT2:

我已经修复了片段着色器

uniform float Brightness;
uniform float Contrast;
uniform vec2 vTextureCoord;
uniform sampler2D Texture1Sampler;

void main() {
    vec4 textureColor = texture2D(Texture1Sampler, vTextureCoord);
    vec3 fragRGB = textureColor.rgb / textureColor.a;
    fragRGB.rgb = ((fragRGB.rgb - 0.5) * max(Contrast, 0.0)) + 0.5;
    fragRGB.rgb += Brightness;
    fragRGB.rgb *= textureColor.a;
    gl_FragColor = vec4(fragRGB, textureColor.a);
}

我添加了一个基本的顶点着色器

attribute vec4 gl_Vertex;

void main(){
  gl_Position = gl_Vertex;
}

我已将它们添加到程序中。现在所有编译警告都消失了,但链接又失败了。

program = glCreateProgram(); 
glAttachShader(program, fragmentShader); // fragment shader compiled. No warnings
glAttachShader(program, vertexShader); // vertex shader compiled. No warnings
glLinkProgram(program);
GLint linked;
glGetProgramivARB(program, GL_LINK_STATUS, &linked); // linked != GL_TRUE. Linking failed.

我做错了什么?

【问题讨论】:

    标签: opengl linker glsl fragment-shader


    【解决方案1】:

    您只是附加了一个片段着色器,而不是一个顶点着色器。在完全可编程的 openGL 中,两者都是必需的。你的代码应该是:

    glAttachShader(program, fragmentShader);
    glAttachShader(program, vertexShader);
    

    在着色器附加到程序后发生链接,并且由于顶点和片段着色器都需要链接失败。

    此外,您基本上是在用 GLSL 编写 Cg。

    float4 main(float2 uv : TEXCOORD) : COLOR // These Cg semantics are not accepted in GLSL
    

    关键是 GLSL 不使用 Cg 之类的语义,您需要使用 GLSL 特殊输出变量。检查以下伪 GLSL 代码。

     in vec3 vertex;
        //vertex shader.
        void main() // write a main and output should be done using special variables
        {
          // output using special variables.
        gl_Position = vertex;
        }
    
    
        //fragment shader.
        uniform vec4 color;
        void main() // write a main and output should be done using special variables 
        {
          // output using special variables.
        gl_FragColor = color;
        }
    

    我实际上建议你选择像 this one 这样的 GLSL 语言教程。

    【讨论】:

    • 非常感谢。所以我需要创建一个空的顶点着色器才能仅将 B/C 应用于屏幕?
    • @Jepessen 你需要最小的顶点着色器,gl_Position = vertex;
    • 嗨。此顶点着色器无法编译。我应该怎么办? void main() { gl_Position = vertex; }
    • @Jepessen 是的。它实际上需要一个 main 我放弃了它,因为我认为注释不是编写代码的好地方。您还需要将顶点定义为属性。
    • @Vallentin 为什么不提供更好的答案?我的代码只是一个占位符。
    猜你喜欢
    • 1970-01-01
    • 2022-10-14
    • 2018-03-22
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多