从.glsl文件中读取OpenGL着色器语言

3
我正在尝试从文件中读取shader字符串,但是我在glShaderSource()函数行遇到了一个问题。正如你所知,glShaderSource()需要const char**,而我必须声明char *来从文件中读取。因此,我使用转换来进行类型转换。
如果我使用const_cast<const char **>,形状就出现了;但是它的颜色不对(应该是橙色而不是白色)。 如果我使用reinterpret_cast<const char**>,我在运行时会收到访问冲突,位置0x73726576的错误提示。
那么,我应该如何解决这个问题呢?谢谢!
平台:Windows 7,Visual Studio 2010
代码行:

文件:shader.glsl

#version 330

in vec3 vp;

void main() {
  gl_Position = vec4( vp, 1.0);
}

主函数():

/* FILE READING */
FILE* shaderFile = fopen( "shader.glsl ", "r");
int fileSize = 0;
char* vertex_shader = NULL;

//Getting File Size
fseek( shaderFile, 0, SEEK_END );
fileSize = ftell( shaderFile );
rewind( shaderFile );

//Reading From File
vertex_shader = (char*)malloc( sizeof( char) * (fileSize+1) );
fread( vertex_shader, sizeof( char ), fileSize, shaderFile );
vertex_shader[ fileSize] = '\0';
fclose( shaderFile );



//Shader definition - If I used this format, it works.
/*const char* vertex_shader = "#version 330\n"
                            "in vec3 vp;"
                            "void main(){"
                            "gl_Position = vec4( vp, 1.0);"
                            "}";*/


    //If I use const char* vertex_shader above, it appears orange.
const char* fragment_shader = "#version 330\n"
                              "out vec4 frag_colour;"
                              "void main () {"
                              "  frag_colour = vec4(0.7, 0.4, 0.2, 1.0);"
                              "}";

//Shader compiling
unsigned int vertexShader = glCreateShader( GL_VERTEX_SHADER );
    //The shape appears but not orange
glShaderSource( vertexShader, 1, const_cast<const char **>(&vertex_shader) , NULL );
//glShaderSource( vertexShader, 1, reinterpret_cast<const char**>(vertex_shader) , NULL ); //Gives error

glCompileShader( vertexShader );

unsigned int fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( fragmentShader, 1, &fragment_shader, NULL);
glCompileShader( fragmentShader );

//Shader program
unsigned int shaderProgram = glCreateProgram();
glAttachShader( shaderProgram, fragmentShader );
glAttachShader( shaderProgram, vertexShader );
glLinkProgram( shaderProgram );

//Drawing
while( !glfwWindowShouldClose( window ) )
{
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    glUseProgram( shaderProgram );
    glBindVertexArray( vao );
    glDrawArrays( GL_TRIANGLES, 0, 3);
    glfwPollEvents();
    glfwSwapBuffers( window);
}

1
你尝试过这个吗:glShaderSource( vertexShader, 1, (const GLchar**)&vertex_shader, NULL); - karlphillip
error C2664: 'void (GLuint,GLsizei,const GLchar **,const GLint *)' : cannot convert parameter 3 from 'char **' to 'const GLchar **' - ciyo
错误是由于const性引起的。 - karlphillip
glShaderSource(vertexShader, 1, (const GLchar**)&vertex_shader, NULL); 仍然是白色的。 - ciyo
目前在下面的 const char* fragment_shader 行处,fclose(shaderFile); 未从另一个文件中读取。 - ciyo
显示剩余5条评论
2个回答

6

将数组的地址传递给函数:

glShaderSource( vertexShader, 1, (const GLchar**)&vertex_shader, NULL);

编辑:

感谢您更新问题中的代码。如果您的程序编译成功,不会崩溃,但着色器仍然无法工作,那么现在是时候调查GLSL编译器是否返回了任何错误了!在每次调用glCompileShader()后写入以下内容以显示编译过程中发生的任何问题:

// This checks for errors upon compiling the Vertex Shader
GLint _compiled = 0;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &_compiled);
if (!_compiled)
{
   GLint length;
   GLchar* log;
   glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &length);
   log = new GLchar[length];
   glGetShaderInfoLog(vertexShader, length, &length, log);
   std::cerr << "!!! Compile log = " << log << std::endl;
   delete log;
   return;
}

const char* fragment_shader = "#version 330\n" "out vec4 frag_colour;" "void main () {" " frag_colour = vec4(0.7, 0.4, 0.2, 1.0);" "}";我已经在 main() 中添加了这些行,并按照您的写法传递了地址,但是它并没有改变任何东西。 - ciyo
如果我不从文件中读取着色器,并在main()中声明vertex_shader为const char,它可以工作,并且形状呈橙色。因此,fragment_shader没有问题。 首先,我只使用const char编写它,它可以工作。 - ciyo
听着,我们没有看到你使用 fragment_shader 的代码,因为你与我们分享的只是顶点着色器的加载和编译。所以从代码上来看,变量 fragment_shader 并没有真正被用于任何事情,因此不应该影响最终结果。我很高兴听到我已经帮助你解决了顶点问题。祝你好运! - karlphillip
glCompileShader( vertexShader ); 这一行之后,我复制粘贴了 GLint _compiled = 0... 这几行代码。它进入了 if 语句并创建了一个包含 0x00a83ce0 "0(7) error C0000: syntax error, unexpected $undefined at token "<undefined>"" 的日志。 - ciyo
@ciyo:当您传递长度为零的着色器时,就会发生这种情况。出于某种原因,您传递的地址的第一个字节似乎是 '\0',并且通过将长度传递为 NULL 告诉OpenGL它是以空字符结尾的字符串。也许文件名末尾的额外空格有些责任?"shader.glsl "** - Andon M. Coleman
1
你知道,fread() 函数返回成功读取的元素数量。将这些信息打印到屏幕上并确保应用程序实际上从磁盘中读取了一些内容是个好主意。 - karlphillip

0

shaderSource 函数需要一个 char ** 参数,因此请使用 & 运算符代替尝试强制转换来处理你的 char * 参数。


当我这样做时,它会出现一个错误C2664:'void(GLuint,GLsizei,const GLchar **,const GLint *)':无法将参数3从'char **'转换为'const GLchar **'。 - ciyo
将您的着色器字符串声明为 GLchar * - Jesus Ramos
1
@ciyo 伙计,别灰心,错误信息已经告诉你出了什么问题以及需要做什么了。它在说你的 GLchar** 需要是 const ... const GLchar** - vallentin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接