GLSL着色器即使没有明显的错误也不会编译

时间:2018-11-22 18:48:26

标签: c++ opengl

我一直在尝试对我创建的多维数据集进行纹理处理,但看不到纹理。我只能看到一个空白的多维数据集渲染。我尝试过不使用纹理并将其设置为单一颜色,但这也没有用。我查看了一下代码,看是否有什么问题,但是我没有看到任何问题,但是我认为这是因为我是OpenGL新手,所以也许其他人可以看到代码出了什么问题。

这是我在vertex_array构造函数中的纹理代码:

vertex_array::vertex_array(float* vertex_buffer, int num_of_floats, const std::string& texture_file)
{
    glGenVertexArrays(1, &va_ID);
    glBindVertexArray(va_ID);

    glGenBuffers(1, &vb_ID);
    glBindBuffer(GL_ARRAY_BUFFER, vb_ID);
    glBufferData(GL_ARRAY_BUFFER, num_of_floats * sizeof(float), vertex_buffer, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(0 * sizeof(float)));
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    int width, height, nrChanells;
    stbi_set_flip_vertically_on_load(true);
    unsigned char* data = stbi_load(texture_file.c_str(), &width, &height, &nrChanells, 0);
    if (data)
    {
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(GL_TEXTURE_2D);
    }
    else {std::cout << "failed to load texture" << std::endl;}
    stbi_image_free(data);

    glGenBuffers(1, &ib_ID);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib_ID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(index_buffer), index_buffer, GL_STATIC_DRAW);
    glBindVertexArray(0);
}

这是我的着色器:

#version 330 core

layout(location = 0) in vec4 position;
layout(location = 1) in vec2 texCoord;

out vec2 v_TexCoord;

uniform mat4 view;
uniform mat4 projection;

void main()
{
v_TexCoord = texCoord;
gl_Position = projection * view * position;
};

#version 330 core

layout(location = 0) out vec4 color;

in vec2 v_TexCoord;

uniform sampler2D u_Texture;

void main()
{
vec4 texColor = texture(u_Texture, v_TexCoord);
color = texColor;
//color = vec4(0.0, 0.7, 0.4, 1.0);
};

这是着色器类:

#include "shader.h"
#include <fstream>
#include <string>
#include <sstream>

shader::shader(const std::string& shader_file)
{
    std::ifstream file(shader_file);
    std::string line;
    std::stringstream shaders[2];
    std::string shader_type;

    while (getline(file, line))
    {
        if (line.find("#shader") != std::string::npos)
        {
            if (line.find("vertex") != std::string::npos)
                shader_type = "vertex";
            else if (line.find("fragment") != std::string::npos)
                shader_type = "fragment";
        }

        else
        {
            if (shader_type == "vertex")
            {
                shaders[0] << line << "\n";
                //std::cout << line << "\n";
            }
            else if (shader_type == "fragment")
            {
                shaders[1] << line << "\n";
                //std::cout << line << "\n";
            }
        }
    }

    s_ID = glCreateProgram();
    unsigned int vs_ID = glCreateShader(GL_VERTEX_SHADER);
    unsigned int fs_ID = glCreateShader(GL_FRAGMENT_SHADER);
    const char* vertex_shader = shaders[0].str().c_str();
    const char* fragment_shader = shaders[1].str().c_str(); 
    glShaderSource(vs_ID, 1, &vertex_shader, nullptr);
    glShaderSource(fs_ID, 1, &fragment_shader, nullptr);
    glCompileShader(vs_ID);
    glCompileShader(fs_ID);
    glAttachShader(s_ID, vs_ID);
    glAttachShader(s_ID, fs_ID);
    glLinkProgram(s_ID);
    glValidateProgram(s_ID);
    glDeleteShader(vs_ID);
    glDeleteShader(fs_ID);
}

void shader::bind()
{
    glUseProgram(s_ID);
}

void shader::unbind()
{
    glUseProgram(0);
}

这是我的主要应用代码:

vertex_array va_1(cube1, 40, "resources/blocks.png");
shader shader_1("src/shader1.shader");
va_1.bind();
shader_1.bind();

[由Spektre编辑]

在进入 GLSL 着色器日志后达到峰值,问题是:

ERROR: 0:1: '' : syntax error: illegal extended ASCII character (0xdd)

这意味着一路编码错误

1 个答案:

答案 0 :(得分:2)

没有颜色可能意味着照明/正常问题,或者只是没有编译/链接的着色器而导致固定功能的使用,该功能使用不同的输入位置,因此没有颜色/纹理等。

首先检查 GLSL 日志,因为这是绝对必要的。即使是诸如缺少;或字符错误之类的小错误,也可能会阻止您进行编译,并且如果不检查就无法知道什么有效。在这里看看:

完成此操作后,看来着色器的编码有问题:

ERROR: 0:1: '' : syntax error: illegal extended ASCII character (0xdd)

还有更多原因可能导致这种情况:

    着色器文件中的
  1. 错误

    如果您使用UNICODE工具或使用国家键盘来编辑着色器,或者从WEB复制粘贴,则结果文件可能包含“特殊”字符,甚至整个文件都可以编码为UNICODE( UTF8,UTF16 )。这是错误的,因为gfx驱动程序 GLSL 编译器无法处理这种情况。

    因此,请以十六进制视图检查文件(或编写一个小的脚本来检查127以上是否存在非ASCII代码)。

    UTF 编码易于检测,这是 UTF8 SVG文件开头的十六进制视图:

    EF BB BF 3C 3F 78 6D 6C 20 76 65 72 73 69 6F 6E | <?xml version
    

    这是另一个SVG,但这次 UTF16

    FF FE 3C 00 3F 00 78 00 6D 00 6C 00 20 00 76 00 | ˙ţ< ? x m l   v 
    

    您可以看到,开头的2个BYTE是检测 UTF 编码的 UTF 幻数。在 UTF8 中,字符可以为1个或多个字节。在 UTF16 中,每个字符都有2个字节。这很容易检测到。但是,如果您的文件仅包含非 ASCII 字符(code>127),则可能很难发现并编写脚本来检测该文件更加可靠。

    但是错误消息表明您的问题在第一行,因此您无需搜索整个文件即可发现它...如果您使用 Total Commander ,在着色器上点击[F3]文件,然后点击[3]以查看十六进制视图或使用任何其他十六进制视图工具。

  2. 将文件加载到程序中时出错

    我不知道您使用的是哪个编译器/ IDE /平台,但是如果您的编译器是UNICODE友好的,则有可能您将着色器文件加载到强制执行UNICODE的某些字符串变量中。在这种情况下,您不会在#1 中发现任何错误,但是编译器仍然会抛出非法字符。

    要在将着色器加载到字符串中后进行确认,请将其保存回某个文件并检查其编码是否正确(对它执行#1 )。

    如果情况只是停止使用执行此操作的字符串变量,而是使用8位数据类型的数组。注意,如果要使用char,必须确保它是char而不是UNICODE Wide char!不要问我如何将文档搜索到您的编译器/ IDE。

    此问题解决后(保存的文件是标准的 ASCII 文本), GLSL 编译应继续进行而不会出错...

  3. 在cpp代码中强制使用ASCII和着色器代码

    某些程序不使用着色器文件。相反,它们将源代码存储为应用程序源代码中的const字符串。这种方式容易遇到与#2 相同的问题。为了解决这个问题,一些编译器引入了一个宏,该宏告诉编译器该字符串是ASCII而不是UNICODE,应该照此处理。我不知道宏的命名方式,但是我在SE / SO上的不同GLSL相关问题中使用了它们。 IIRC就像这样:

    const char *txt=TEXT('bla bla vla');
    

    但是我不确定是TEXT还是Text还是稍微不同的东西。因此,请在 QA 中搜索您的错误代码或强制执行 ASCII ,或在编译器/ IDE文档中查找有关此类信息。

新手常见的问题是,他们构建整个应用程序并且仅开始编译。那是错的。因为在那之后他们花了永恒的调试...

他们应该逐步构建应用。因此,从小处着手,然后在工作时移至下一步。这样,如果错误在刚刚添加的新代码中显示了其99%的时间,那么就无需进行困难的搜索...

但是,新的GL api阻止了这种方法,因为在东西开始显示之前,您需要有效的GL上下文,VBO / VAO,网格加载器/生成器,视图,着色器,兼容的gfx驱动程序。这一次有很多可能的问题。这就是为什么我建议从旧的api开始,然后与新的api一起删除的原因。或者改为使用一些有效的开始模板。