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

标签 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)


这意味着一路编码错误

最佳答案

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

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


complete GL+GLSL+VAO/VBO C++ example

并查看如何使用glGetShaderInfoLogglGetProgramInfoLog。保存或打印其结果以检查错误。


完成此操作后,看来您在着色器的编码方面遇到了问题:

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


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


着色器文件中的错误

如果您使用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]以查看十六进制视图或使用其他十六进制查看工具。
将文件加载到程序中时出错

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

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

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

解决此问题(保存的文件为标准ASCII文本)后,GLSL编译应继续进行而不会出现错误...
在cpp代码中强制ASCII和着色器代码

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

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


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


菜鸟还常见的问题是,他们只构建整个应用程序,然后才开始编译。那是错的。因为在那之后他们花了永恒的调试...

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

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

关于c++ - GLSL着色器即使没有明显的错误也不会编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53436683/

相关文章:

c++ - 使用 GLEW 和 WGL 的 OpenGL 抗锯齿

opengl - 为什么在调用 glfwWindowHint() 后,glewInit() 会导致 GL_INVALID_ENUM

c++ - 是否可以垂直同步单个缓冲上下文?

c++ - 我删除sdl2和opengl是正确的c++吗

c++ - 如何在没有 Z-fighting 的情况下在 OpenGL 中绘制一条线

时间:2019-03-08 标签:c++char*parsing

c++ - 初始化列表需要其效果的初始化函数调用?

c++ - CV 合格的数据成员和类型转换

c++ - 如何使用 boost::unit_test?

c++ - 将指向同一类的私有(private)成员指针设置为 NULL?