gpt4 book ai didi

c - glShaderSource 导致段错误

转载 作者:行者123 更新时间:2023-11-30 20:15:16 25 4
gpt4 key购买 nike

我正在尝试学习图形编程,并且编写了一个简单的 OpenGL 程序,该程序绘制一个三角形并将其着色为红色,但是当我为片段着色器调用函数 glShaderSource 时,它会导致段错误。

我不知道为什么它会导致段错误,因为 spec page没有说任何关于导致段错误的函数,并且任何关于着色器加载到内存中的错误也不可能是这样,因为顶点着色器以相同的方式加载,并且当我调用glGetShaderInfoLog时> 并打印日志,它表示顶点着色器编译良好。

无论如何,这是我加载着色器并链接着色程序的代码...

int LoadShader(char* Filename, GLchar* ShaderSource) //dont call this function by itself as it doesnt free its own memory
{
FILE* z;
z = fopen(Filename, "rb");

if(z == NULL) {printf("Error: file \"%s\" does not exist...\n", Filename); return -1;}

unsigned long len = 0;

//get file length
fseek(z, 0, SEEK_END);
len = ftell(z);
rewind(z);

if(len == 0) {printf("Error reading file \"%s\"\n", Filename); return -1;}


ShaderSource = (char*)malloc((sizeof(char)) * len + 1); //allocate enough bytes for the file
if(ShaderSource == NULL) {puts("Memory Error"); return -1;}

size_t result = fread(ShaderSource, 1, len, z);
if( result != len)
{
puts("Reading Error");
free(ShaderSource);
ShaderSource = NULL;
return -1;
}

ShaderSource[len] = 0; //make it null terminated

puts(ShaderSource); //debbugging

fclose(z);

return 1;
}

//----------------------------------------------------------------------
GLuint MakeProgram(char* VSpath, char* FSpath){

GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

GLchar* VSsource;
GLchar* FSsource;

if(!LoadShader(VSpath, VSsource))
return -1;


if(!LoadShader(FSpath, FSsource))
return -1;


GLint Result = GL_FALSE;
int InfoLogLength;

//compile shaders
const char* VS = VSsource; // glShaderSource needs a const char
glShaderSource(VertexShaderID, 1, &VS, NULL); //we use NULL for length becuase the source is null-terminated
glCompileShader(VertexShaderID);
//check
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
char* VSerr;
VSerr = (char*)malloc(sizeof(char) * InfoLogLength);

glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VSerr[0]);
printf("%s\n", VSerr);

free(VSerr);
VSerr = NULL;


//fragment shader
const char* FS = FSsource;
glShaderSource(FragmentShaderID, 1, &FS, NULL);
glCompileShader(FragmentShaderID);
//check
glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
char* FSerr;
FSerr = (char*)malloc(sizeof(char) * InfoLogLength);

glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FSerr[0]);
printf("%s\n", FSerr);

free(FSerr);
FSerr = NULL;


//link program
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
//check program
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
char* err;
err = (char*)malloc(sizeof(char) * InfoLogLength);

glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &err[0]);
printf("%s\n", err);

free(err);

//free the shaders
free(VSsource);
VSsource = NULL;

free(FSsource);
FSsource = NULL;

glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);

return ProgramID;
}

最佳答案

仔细查看 VSsource 的实际声明(未初始化),FSsource (未初始化)和 LoadShader (...) 的实现。因为这是 C,并且您不会通过引用传递对 ShaderSource 所做的任何更改。 LoadShader (...) 内的指针您最初编写的函数不会在函数外部传播。

简而言之,您实现了 LoadShader (...)错误地。您实际上需要更改存储在传递给它的指针中的地址(因为您是在函数内部分配此内存),但您不能这样做,因为您当前传递给它的是 GLchar* .

至于为什么GL在第一次调用glShaderSource (...)时接受未初始化的指针我不能说。也许你只是非常幸运?无论如何,您可以通过更改 LoadShader 来纠正您的问题采取GLchar**反而。我将在下面说明必要的更改:

/* Originally, you made a copy of an uninitialized pointer and then proceeded to
re-assign this copy a value when you called malloc (...) - you actually need
to pass a pointer to your pointer so you can update the address outside of
this function!
*/
int LoadShader(char* Filename, GLchar** pShaderSource) //dont call this function by itself as it doesnt free its own memory
{
[...]
*pShaderSource = (GLchar *)malloc((sizeof(GLchar)) * len + 1); //allocate enough bytes for the file

GLchar* ShaderSource = *pShaderSource;
[...]
}

GLuint MakeProgram(char* VSpath, char* FSpath){
[...]
GLchar* VSsource; /* Uninitialized */
GLchar* FSsource; /* Uninitialized */

if(!LoadShader(VSpath, &VSsource)) /* Pass the address of your pointer */
return -1;

if(!LoadShader(FSpath, &FSsource)) /* Pass the address of your pointer */
return -1;

/*
* Now, since you did not pass copies of your pointers, you actually have
* *VALID* initialized memory addresses !
*/
[...]
}

或者,您可以简单地修改函数以返回您分配的字符串的地址。您可以返回 NULL,而不是像现在这样在失败时返回 -1。如果您选择走这条路线,您的功能界面将像这样简单:GLchar* LoadShader (char* Filename) .

关于c - glShaderSource 导致段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20767036/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com