OpenGL 着色器加载失败
Posted
技术标签:
【中文标题】OpenGL 着色器加载失败【英文标题】:OpenGL shader loading fails 【发布时间】:2012-01-07 09:34:24 【问题描述】:我的着色器加载代码有问题。让我感到困惑的奇怪之处在于,它可能会在 5 次中起作用,但之后只能起作用。例如,它会加载碎片着色器,但随后纹理将无法正常工作(它会在几何体上绘制一种奇怪的纹理外观)。我认为问题在于加载代码,所以这就是我的问题所在。谁能发现我在下面的代码中没有发现的错误?
char* vs, * fs;
vertexShaderHandle = glCreateShader(GL_VERTEX_SHADER);
fragmentShaderHandle = glCreateShader(GL_FRAGMENT_SHADER);
long sizeOfVShaderFile = getSizeOfFile(VERTEX_SHADER_FILE_NAME);
long sizeOfFShaderFile = getSizeOfFile(FRAGMENT_SHADER_FILE_NAME);
if(sizeOfVShaderFile == -1)
cerr << VERTEX_SHADER_FILE_NAME<<" is null! Exiting..." << endl;
return;
if(sizeOfFShaderFile == -1)
cerr << FRAGMENT_SHADER_FILE_NAME<<" is null! Exiting..." << endl;
return;
vs = readFile(VERTEX_SHADER_FILE_NAME);
fs = readFile(FRAGMENT_SHADER_FILE_NAME);
const char* vv = vs, *ff = fs;
glShaderSource(vertexShaderHandle , 1, &vv, NULL);
cout << "DEBUGGING SHADERS" << endl;
cout << "VERTEX SHADER: ";
printShaderInfoLog(vertexShaderHandle);
cout << endl;
glShaderSource(fragmentShaderHandle, 1, &ff, NULL);
cout << "FRAGMENT SHADER: ";
printShaderInfoLog(fragmentShaderHandle);
cout << endl;
glCompileShader(vertexShaderHandle);
cout << "VERTEX SHADER: ";
printShaderInfoLog(vertexShaderHandle);
cout << endl;
glCompileShader(fragmentShaderHandle);
cout << "FRAGMENT SHADER: ";
printShaderInfoLog(fragmentShaderHandle);
cout << endl;
programHandle = glCreateProgram();
cout << "DEBUGGING PROGRAM" << endl;
glAttachShader(programHandle, vertexShaderHandle);
printProgramInfoLog(programHandle);
glAttachShader(programHandle, fragmentShaderHandle);
printProgramInfoLog(programHandle);
glLinkProgram(programHandle);
printProgramInfoLog(programHandle);
glUseProgram(programHandle);
printProgramInfoLog(programHandle);
delete[] vs; delete[] fs;
这里是 readFile 函数:
char* readFile(const char* path)
unsigned int fileSize = getSizeOfFile(path);
char* file_data = new char[fileSize];
ifstream input_stream;
input_stream.open(path, ios::binary);
input_stream.read(file_data, fileSize);
input_stream.close();
//this is deleted at the end of the shader code
return file_data;
以下所有消息都来自完全相同的可执行文件(没有重建)。
这是第一个可能的错误消息:
BallGLWidget::initializeGL called
DEBUGGING SHADERS
VERTEX SHADER:
FRAGMENT SHADER:
VERTEX SHADER: ERROR: 0:17: '<' : syntax error syntax error
FRAGMENT SHADER:
DEBUGGING PROGRAM
ERROR: One or more attached shaders not successfully compiled
ERROR: One or more attached shaders not successfully compiled
glGetError enum value: GL_NO_ERROR
另一个可能的错误信息:
BallGLWidget::initializeGL called
DEBUGGING SHADERS
VERTEX SHADER:
FRAGMENT SHADER:
VERTEX SHADER: ERROR: 0:17: 'tt' : syntax error syntax error
FRAGMENT SHADER: ERROR: 0:33: '?' : syntax error syntax error
DEBUGGING PROGRAM
ERROR: One or more attached shaders not successfully compiled
ERROR: One or more attached shaders not successfully compiled
这是工作时的输出(可能是 5 次或 6 次中的 1 次)
BallGLWidget::initializeGL called
DEBUGGING SHADERS
VERTEX SHADER:
FRAGMENT SHADER:
VERTEX SHADER:
FRAGMENT SHADER:
DEBUGGING PROGRAM
Image format is GL_RGB
Checking textures...
glGetError enum value: GL_NO_ERROR
我严重怀疑它的着色器本身,因为它们有时会工作......并且报告的错误是垃圾。
如果有更多信息对我有帮助,我很乐意提供。
编辑:这是着色器
顶点着色器:
attribute vec2 a_v_position;
attribute vec2 a_tex_position;
varying vec2 tex_coord_output;
void main()
tex_coord_output = a_tex_position;
gl_Position = vec4(a_v_position, 0.0, 1.0);
片段着色器:
varying vec2 tex_coord_output;
uniform sampler2D ballsampler;
void main()
gl_FragColor = texture2D(ballsampler, tex_coord_output);
【问题讨论】:
我们可以看看实际的着色器吗? 当然,我在编辑中发布了它们 您能否检查 ifstream.read() 调用的返回值,以确保您正在读取的数据是实际数据并且它没有因某种原因而失败?您的初始化乍一看似乎是正确的,错误似乎表明它可能正在从流中读取垃圾数据(将仔细检查您的代码,以防我在这个假设中出错) 【参考方案1】:您的问题与Getting garbage chars when reading GLSL files 重复,这是我的answer:
您使用的是 C++,所以我建议您利用它。我建议您不要读入一个自分配的 char 数组,而是读入一个 std::string:
#include <string>
#include <fstream>
std::string loadFileToString(char const * const fname)
std::ifstream ifile(fname);
std::string filetext;
while( ifile.good() )
std::string line;
std::getline(ifile, line);
filetext.append(line + "\n");
return filetext;
它会自动处理所有内存分配和适当的定界——关键字是 RAII:资源分配是初始化。稍后您可以上传着色器源,例如
void glcppShaderSource(GLuint shader, std::string const &shader_string)
GLchar const *shader_source = shader_string.c_str();
GLint const shader_length = shader_string.size();
glShaderSource(shader, 1, &shader_source, &shader_length);
void load_shader(GLuint shaderobject, char * const shadersourcefilename)
glcppShaderSource(shaderobject, loadFileToString(shadersourcefilename));
【讨论】:
嘿,非常感谢您提供的代码 sn-ps!为我节省了大量工作!【参考方案2】:您正在阅读文件,但据我所知,您并没有以零结尾的文本。尝试分配 filesize+1 并将最后一个字符设置为零。
【讨论】:
谢谢!就是这样!太好了,我从没想过。 要么零终止,要么向 glShaderSource 提供数据长度。以上是关于OpenGL 着色器加载失败的主要内容,如果未能解决你的问题,请参考以下文章
使用 python opengl (PyOpenGL) 创建几何着色器失败
我的OpenGL学习进阶之旅如何抽取着色器代码到assets目录下的GLSL文件,以及如何通过Java或者C++代码来加载着GLSL文件?