我一直在尝试对我创建的多维数据集进行纹理处理,但看不到纹理。我只能看到一个空白的多维数据集渲染。我尝试过不使用纹理并将其设置为单一颜色,但这也没有用。我查看了一下代码,看是否有什么问题,但是我没有看到任何问题,但是我认为这是因为我是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)
这意味着一路编码错误
答案 0 :(得分:2)
没有颜色可能意味着照明/正常问题,或者只是没有编译/链接的着色器而导致固定功能的使用,该功能使用不同的输入位置,因此没有颜色/纹理等。
首先检查 GLSL 日志,因为这是绝对必要的。即使是诸如缺少;
或字符错误之类的小错误,也可能会阻止您进行编译,并且如果不检查就无法知道什么有效。在这里看看:
complete GL+GLSL+VAO/VBO C++ example
看看如何使用glGetShaderInfoLog
和glGetProgramInfoLog
。保存或打印其结果以检查错误。
完成此操作后,看来着色器的编码有问题:
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 中搜索您的错误代码或强制执行 ASCII ,或在编译器/ IDE文档中查找有关此类信息。
新手常见的问题是,他们构建整个应用程序并且仅开始编译。那是错的。因为在那之后他们花了永恒的调试...
他们应该逐步构建应用。因此,从小处着手,然后在工作时移至下一步。这样,如果错误在刚刚添加的新代码中显示了其99%的时间,那么就无需进行困难的搜索...
但是,新的GL api阻止了这种方法,因为在东西开始显示之前,您需要有效的GL上下文,VBO / VAO,网格加载器/生成器,视图,着色器,兼容的gfx驱动程序。这一次有很多可能的问题。这就是为什么我建议从旧的api开始,然后与新的api一起删除的原因。或者改为使用一些有效的开始模板。