如何调试 GLSL 片段着色器(代码更改后程序链接错误)
How to debug GLSL Fragment shader (Program Linking error after code change)
(原标题)请帮我调试我的 glsl 光照着色器,以便它可以编译!这是我第一次调试glsl
您好,我是 opengl 的新手。我正在修改我在网上找到的另一个着色器。我在网上找到的版本效果很好,但是在我的代码中某处我在编辑时犯了一个错误。问题是我已经梳理过了,看不到它,我希望能有一些新鲜的眼光。
需要说明的是,并不是绘制的内容不正确,而是无法编译
#version 330 core
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
float ambient;
};
struct DirLight {
vec3 direction;
vec3 color;
float strength;
};
struct PointLight {
vec3 position;
vec3 color;
float strength;
float active;
};
struct SpotLight {
vec3 position;
vec3 direction;
float cutOff;
float outerCutOff;
float constant;
float linear;
float quadratic;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
#define NR_POINT_LIGHTS 150
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoords;
out vec4 color;
uniform vec3 viewPos;
uniform DirLight dirLight;
uniform PointLight pointLights[NR_POINT_LIGHTS];
uniform SpotLight spotLight;
uniform Material material;
// Function prototypes
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir, vec3 fcolor);
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
void main()
{
// Properties
vec3 norm = normalize(Normal);
vec3 viewDir = normalize(viewPos - FragPos);
vec3 fragColor = texture(material.diffuse, TexCoords).rgb;
// == ======================================
// Our lighting is set up in 3 phases: directional, point lights and an optional flashlight
// For each phase, a calculate function is defined that calculates the corresponding color
// per lamp. In the main() function we take all the calculated colors and sum them up for
// this fragment's final color.
// == ======================================
// Phase 1: Directional lighting
vec3 result = vec3(0.0f);
//result = CalcDirLight(dirLight, norm, viewDir);
// Phase 2: Point lights
for(int i = 0; i < NR_POINT_LIGHTS; i++)
{
result += CalcPointLight(pointLights[i], norm, FragPos, viewDir, fragColor);
}
// Phase 3: Spot light
//result += CalcSpotLight(spotLight, norm, FragPos, viewDir);
result += material.ambient * fragColor;
color = vec4(result, 1.0);
}
// Calculates the color when using a directional light.
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
vec3 lightDir = normalize(-light.direction);
// Diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// Specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// Combine results
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
return (diffuse + specular);
}
// Calculates the color when using a point light.
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir, vec3 fcolor)
{
if (light.active == 1)
{
// Lighting
vec3 lighting = vec3(0.0f);
// Diffuse
vec3 lightDir = normalize(light.position - fragPos);
float diff = max(dot(lightDir, normal), 0.0);
vec3 result = light.color * diff * fcolor;
// Attenuation (use quadratic as we have gamma correction)
float distance = (length(fragPos - light.position)/light.strength);
result *= 1.0 / (distance * distance);
lighting += result;
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = spec * vec3(texture(material.specular, TexCoords)) * light.color;
specular *= material.shininess;
specular *= 1.0 / (distance * distance);
vec3 toReturn = lighting + specular;
return toReturn;
}
else
{
return vec3(0.0f, 0.0f, 0.0f);
}
}
// Calculates the color when using a spot light.
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - fragPos);
// Diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// Specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// Attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0f / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
// Spotlight intensity
float theta = dot(lightDir, normalize(-light.direction));
float epsilon = light.cutOff - light.outerCutOff;
float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);
// Combine results
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
ambient *= attenuation * intensity;
diffuse *= attenuation * intensity;
specular *= attenuation * intensity;
return (diffuse + specular);
}
谢天谢地,我的程序确实打印出了编译错误。这是吐出来的。不幸的是,它指向的线不是真实的......就像它们存在但它们没有任何问题,其中一个错误指向一条没有代码的线......我没有改变它的原始片段着色器部分所以这不是问题
错误图片可在以下位置找到:https://app.box.com/s/3nrzjyu3p2smnow5zo8j0q1lbqgdf149
我试过 glslDevil,但我不知道如何导入我的着色器。
非常感谢!
编辑:
我发现的有趣的东西...
我注意到的一件有趣的事情是,如果你这样定义定向光函数
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
vec3 lightDir = normalize(-light.direction);
// Diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// Specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// Combine results
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
return (diffuse + specular);
}
它只会抛出一个错误,即 diffuse、specular 和 ambient 不是该结构的成员(这是故意的)
你的错误日志不好
- 这是您正在使用的工具的一些链接日志
- 不是 OpenGL 编译日志!!!
我把你的片段着色器放入OpenGL,这是真实的编译日志(使用nVidia):
[Fragment]
Compiler error
0(94) : error C1009: "ambient" is not member of struct "DirLight"
0(95) : error C1009: "diffuse" is not member of struct "DirLight"
0(96) : error C1009: "specular" is not member of struct "DirLight"
[Program]
Linker error
Fragment info
-------------
0(94) : error C1009: "ambient" is not member of struct "DirLight"
0(95) : error C1009: "diffuse" is not member of struct "DirLight"
0(96) : error C1009: "specular" is not member of struct "DirLight"
- 你应该为你在 OpenGL
中使用的每个 shader/program 对象使用 glGetShaderInfoLog
- 我使用类似 this
有道理:
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
vec3 lightDir = normalize(-light.direction);
// Diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// Specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// Combine results
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
return (diffuse + specular);
}
在 // Combine results
之后您正在访问 struct
中未定义的字段:
struct DirLight {
vec3 direction;
vec3 color;
float strength;
};
[edit1] 在 C++ 中我将我的 class 用于 GLSL:
//------------------------------------------------------------------------------
//--- GLSL program class -------------------------------------------------------
//------------------------------------------------------------------------------
class GLSLprogram // GLSL program class
{
public:
AnsiString log;
int prog_id, // whole program
tesc_id, // tessellation control
tese_id, // tessellation evaluation
geom_id, // geometry
vert_id, // vertex
frag_id; // fragment
GLSLprogram();
GLSLprogram(GLSLprogram& a);
~GLSLprogram();
GLSLprogram* operator = (const GLSLprogram *a);
//GLSLprogram* operator = (const GLSLprogram &a);
void bind();
void unbind();
void set_source_text(AnsiString tesc,AnsiString tese,AnsiString geom,AnsiString vert,AnsiString frag); // set source texts
void set_source_file(AnsiString tesc,AnsiString tese,AnsiString geom,AnsiString vert,AnsiString frag); // load and set source files
void set1f (AnsiString name,GLfloat x);
void set2f (AnsiString name,GLfloat x, GLfloat y);
void set3f (AnsiString name,GLfloat x, GLfloat y, GLfloat z);
void set4f (AnsiString name,GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void set1i (AnsiString name,GLint x);
void set2i (AnsiString name,GLint x, GLint y);
void set3i (AnsiString name,GLint x, GLint y, GLint z);
void set4i (AnsiString name,GLint x, GLint y, GLint z, GLint w);
void set1fv (AnsiString name,GLfloat *p);
void set2fv (AnsiString name,GLfloat *p);
void set3fv (AnsiString name,GLfloat *p);
void set4fv (AnsiString name,GLfloat *p);
void set1iv (AnsiString name,GLint *p);
void set2iv (AnsiString name,GLint *p);
void set3iv (AnsiString name,GLint *p);
void set4iv (AnsiString name,GLint *p);
void set2x2fv(AnsiString name,GLfloat *p);
void set3x3fv(AnsiString name,GLfloat *p);
void set4x4fv(AnsiString name,GLfloat *p);
void get1f (AnsiString name,GLfloat &x);
void get2f (AnsiString name,GLfloat &x, GLfloat &y);
void get3f (AnsiString name,GLfloat &x, GLfloat &y, GLfloat &z);
void get4f (AnsiString name,GLfloat &x, GLfloat &y, GLfloat &z, GLfloat &w);
void get1i (AnsiString name,GLint &x);
void get2i (AnsiString name,GLint &x, GLint &y);
void get3i (AnsiString name,GLint &x, GLint &y, GLint &z);
void get4i (AnsiString name,GLint &x, GLint &y, GLint &z, GLint &w);
void get1fv (AnsiString name,GLfloat *p);
void get2fv (AnsiString name,GLfloat *p);
void get3fv (AnsiString name,GLfloat *p);
void get4fv (AnsiString name,GLfloat *p);
void get1iv (AnsiString name,GLint *p);
void get2iv (AnsiString name,GLint *p);
void get3iv (AnsiString name,GLint *p);
void get4iv (AnsiString name,GLint *p);
void get2x2fv(AnsiString name,GLfloat *p);
void get3x3fv(AnsiString name,GLfloat *p);
void get4x4fv(AnsiString name,GLfloat *p);
};
//------------------------------------------------------------------------------
GLSLprogram::GLSLprogram()
{
prog_id=0;
tesc_id=0;
tese_id=0;
geom_id=0;
vert_id=0;
frag_id=0;
}
//------------------------------------------------------------------------------
GLSLprogram::~GLSLprogram()
{
if (glDetachShader==NULL) return;
if (glDeleteShader==NULL) return;
unbind();
if (tesc_id>0) { glDetachShader(prog_id,tesc_id); glDeleteShader(tesc_id); }
if (tese_id>0) { glDetachShader(prog_id,tese_id); glDeleteShader(tese_id); }
if (geom_id>0) { glDetachShader(prog_id,geom_id); glDeleteShader(geom_id); }
if (vert_id>0) { glDetachShader(prog_id,vert_id); glDeleteShader(vert_id); }
if (frag_id>0) { glDetachShader(prog_id,frag_id); glDeleteShader(frag_id); }
if (prog_id>0) { glDeleteShader(prog_id); }
log="";
}
//------------------------------------------------------------------------------
void GLSLprogram::bind()
{
if (glUseProgram==NULL) return;
glUseProgram(prog_id);
}
//------------------------------------------------------------------------------
void GLSLprogram::unbind()
{
if (glUseProgram==NULL) return;
glUseProgram(0);
}
//------------------------------------------------------------------------------
void GLSLprogram::set_source_text(AnsiString tesc,AnsiString tese,AnsiString geom,AnsiString vert,AnsiString frag)
{
if (glCreateProgram==NULL) return;
if (glShaderSource==NULL) return;
if (glCompileShader==NULL) return;
if (glAttachShader==NULL) return;
if (glGetShaderiv==NULL) return;
if (glGetShaderInfoLog==NULL) return;
if (glLinkProgram==NULL) return;
if (glGetProgramiv==NULL) return;
if (glGetProgramInfoLog==NULL) return;
if (glReleaseShaderCompiler==NULL) return;
const int _size=1024;
char dat[_size];
GLint status,siz=0,i;
const char * TC = tesc.c_str();
const char * TE = tese.c_str();
const char * GS = geom.c_str();
const char * VS = vert.c_str();
const char * FS = frag.c_str();
log="";
if (prog_id<=0) prog_id=glCreateProgram();
if (tesc_id<=0) tesc_id=glCreateShader(GL_TESS_CONTROL_SHADER);
else glDetachShader(prog_id,tesc_id);
if (tesc!="")
{
glShaderSource(tesc_id, 1, &TC,NULL);
glCompileShader(tesc_id);
glAttachShader(prog_id,tesc_id);
glGetShaderiv(tesc_id,GL_COMPILE_STATUS,&status);
log+="[Tessellation control]\n";
if (status) log+="OK\n"; else log+="Compiler error\n";
glGetShaderInfoLog(tesc_id,_size,&siz,dat);
for (i=0;i<siz;i++) log+=dat[i];
}
if (tese_id<=0) tese_id=glCreateShader(GL_TESS_EVALUATION_SHADER);
else glDetachShader(prog_id,tese_id);
if (tese!="")
{
glShaderSource(tese_id, 1, &TE,NULL);
glCompileShader(tese_id);
glAttachShader(prog_id,tese_id);
glGetShaderiv(tese_id,GL_COMPILE_STATUS,&status);
log+="[Tessellation evaluation]\n";
if (status) log+="OK\n"; else log+="Compiler error\n";
glGetShaderInfoLog(tese_id,_size,&siz,dat);
for (i=0;i<siz;i++) log+=dat[i];
}
if (geom_id<=0) geom_id=glCreateShader(GL_GEOMETRY_SHADER);
else glDetachShader(prog_id,geom_id);
if (geom!="")
{
glShaderSource(geom_id, 1, &GS,NULL);
glCompileShader(geom_id);
glAttachShader(prog_id,geom_id);
glGetShaderiv(geom_id,GL_COMPILE_STATUS,&status);
log+="[Geometry]\n";
if (status) log+="OK\n"; else log+="Compiler error\n";
glGetShaderInfoLog(geom_id,_size,&siz,dat);
for (i=0;i<siz;i++) log+=dat[i];
}
if (vert_id<=0) vert_id=glCreateShader(GL_VERTEX_SHADER);
else glDetachShader(prog_id,vert_id);
if (vert!="")
{
glShaderSource(vert_id, 1, &VS,NULL);
glCompileShader(vert_id);
glAttachShader(prog_id,vert_id);
glGetShaderiv(vert_id,GL_COMPILE_STATUS,&status);
log+="[Vertex]\n";
if (status) log+="OK\n"; else log+="Compiler error\n";
glGetShaderInfoLog(vert_id,_size,&siz,dat);
for (i=0;i<siz;i++) log+=dat[i];
}
if (frag_id<=0) frag_id=glCreateShader(GL_FRAGMENT_SHADER);
else glDetachShader(prog_id,frag_id);
if (frag!="")
{
glShaderSource(frag_id, 1, &FS,NULL);
glCompileShader(frag_id);
glAttachShader(prog_id,frag_id);
glGetShaderiv(frag_id,GL_COMPILE_STATUS,&status);
log+="\n[Fragment]\n";
if (status) log+="OK\n"; else log+="Compiler error\n";
glGetShaderInfoLog(frag_id,_size,&siz,dat);
for (i=0;i<siz;i++) log+=dat[i];
}
glLinkProgram(prog_id);
glGetProgramiv(prog_id,GL_LINK_STATUS,&status);
log+="\n[Program]\n";
if (status) log+="OK\n"; else log+="Linker error\n";
glGetProgramInfoLog(prog_id,_size,&siz,dat);
for (i=0;i<siz;i++) log+=dat[i];
glReleaseShaderCompiler();
}
//------------------------------------------------------------------------------
void GLSLprogram::set_source_file(AnsiString tesc,AnsiString tese,AnsiString geom,AnsiString vert,AnsiString frag)
{
set_source_text(load(tesc),load(tese),load(geom),load(vert),load(frag));
}
//------------------------------------------------------------------------------
void GLSLprogram::set1f (AnsiString name,GLfloat x) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform1f (id,x); }
void GLSLprogram::set2f (AnsiString name,GLfloat x, GLfloat y) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform2f (id,x,y); }
void GLSLprogram::set3f (AnsiString name,GLfloat x, GLfloat y, GLfloat z) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform3f (id,x,y,z); }
void GLSLprogram::set4f (AnsiString name,GLfloat x, GLfloat y, GLfloat z, GLfloat w){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform4f (id,x,y,z,w); }
void GLSLprogram::set1i (AnsiString name,GLint x) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform1i (id,x); }
void GLSLprogram::set2i (AnsiString name,GLint x, GLint y) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform2i (id,x,y); }
void GLSLprogram::set3i (AnsiString name,GLint x, GLint y, GLint z) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform3i (id,x,y,z); }
void GLSLprogram::set4i (AnsiString name,GLint x, GLint y, GLint z, GLint w) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform4i (id,x,y,z,w); }
void GLSLprogram::set1fv (AnsiString name,GLfloat *p) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform1fv (id,1,p); }
void GLSLprogram::set2fv (AnsiString name,GLfloat *p) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform2fv (id,2,p); }
void GLSLprogram::set3fv (AnsiString name,GLfloat *p) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform3fv (id,3,p); }
void GLSLprogram::set4fv (AnsiString name,GLfloat *p) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform4fv (id,4,p); }
void GLSLprogram::set1iv (AnsiString name,GLint *p) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform1iv (id,1,p); }
void GLSLprogram::set2iv (AnsiString name,GLint *p) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform2iv (id,2,p); }
void GLSLprogram::set3iv (AnsiString name,GLint *p) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform3iv (id,3,p); }
void GLSLprogram::set4iv (AnsiString name,GLint *p) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform4iv (id,4,p); }
void GLSLprogram::set2x2fv(AnsiString name,GLfloat *p) { GLboolean q=true; GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniformMatrix2fv(id, 4,q,p); }
void GLSLprogram::set3x3fv(AnsiString name,GLfloat *p) { GLboolean q=true; GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniformMatrix3fv(id, 9,q,p); }
void GLSLprogram::set4x4fv(AnsiString name,GLfloat *p) { GLboolean q=true; GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniformMatrix4fv(id,16,q,p); }
//------------------------------------------------------------------------------
void GLSLprogram::get1f (AnsiString name,GLfloat &x){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformfv(prog_id,id,&x); }
void GLSLprogram::get1i (AnsiString name,GLint &x) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformiv(prog_id,id,&x); }
void GLSLprogram::get1fv (AnsiString name,GLfloat *p){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformfv(prog_id,id,p); }
void GLSLprogram::get2fv (AnsiString name,GLfloat *p){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformfv(prog_id,id,p); }
void GLSLprogram::get3fv (AnsiString name,GLfloat *p){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformfv(prog_id,id,p); }
void GLSLprogram::get4fv (AnsiString name,GLfloat *p){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformfv(prog_id,id,p); }
void GLSLprogram::get1iv (AnsiString name,GLint *p) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformiv(prog_id,id,p); }
void GLSLprogram::get2iv (AnsiString name,GLint *p) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformiv(prog_id,id,p); }
void GLSLprogram::get3iv (AnsiString name,GLint *p) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformiv(prog_id,id,p); }
void GLSLprogram::get4iv (AnsiString name,GLint *p) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformiv(prog_id,id,p); }
void GLSLprogram::get2x2fv(AnsiString name,GLfloat *p){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformfv(prog_id,id,p); }
void GLSLprogram::get3x3fv(AnsiString name,GLfloat *p){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformfv(prog_id,id,p); }
void GLSLprogram::get4x4fv(AnsiString name,GLfloat *p){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformfv(prog_id,id,p); }
//------------------------------------------------------------------------------
AnsiString
只是 VCL 字符串 class(自重定位字符串 class)可以使用其他任何东西,例如 char[]
或 char*
而不是,但您需要处理粗运算符...
AnsiString().c_str()
returns char*
存储字符串的兼容指针
用法:
// [variables]
GLSLprogram shader;
// [init]
shader.set_source_text("","","","your vertex shader source text","your fragment shader source text");
shader.log; // contains the compile/link log ...
shader.prog_id; // contains the OpenGL id for your shader object
// [render]
shader.bind();
// here render
shader.unbind();
[edit2] 而且我忘了添加:
AnsiString load(AnsiString file)
{
int i,hnd,siz;
char *dat=NULL;
hnd=FileOpen(file,fmOpenRead);
if (hnd<0) return "";
siz=FileSeek(hnd,0,2);
FileSeek(hnd,0,0);
if (siz==0) { FileClose(hnd); return ""; }
dat=new char[siz+1];
if (dat==NULL) { FileClose(hnd); return ""; }
FileRead(hnd,dat,siz);
FileClose(hnd);
AnsiString s=""; for (i=0;i<siz;i++) s+=dat[i];
delete dat;
return s;
}
(原标题)请帮我调试我的 glsl 光照着色器,以便它可以编译!这是我第一次调试glsl
您好,我是 opengl 的新手。我正在修改我在网上找到的另一个着色器。我在网上找到的版本效果很好,但是在我的代码中某处我在编辑时犯了一个错误。问题是我已经梳理过了,看不到它,我希望能有一些新鲜的眼光。
需要说明的是,并不是绘制的内容不正确,而是无法编译
#version 330 core
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
float ambient;
};
struct DirLight {
vec3 direction;
vec3 color;
float strength;
};
struct PointLight {
vec3 position;
vec3 color;
float strength;
float active;
};
struct SpotLight {
vec3 position;
vec3 direction;
float cutOff;
float outerCutOff;
float constant;
float linear;
float quadratic;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
#define NR_POINT_LIGHTS 150
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoords;
out vec4 color;
uniform vec3 viewPos;
uniform DirLight dirLight;
uniform PointLight pointLights[NR_POINT_LIGHTS];
uniform SpotLight spotLight;
uniform Material material;
// Function prototypes
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir, vec3 fcolor);
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
void main()
{
// Properties
vec3 norm = normalize(Normal);
vec3 viewDir = normalize(viewPos - FragPos);
vec3 fragColor = texture(material.diffuse, TexCoords).rgb;
// == ======================================
// Our lighting is set up in 3 phases: directional, point lights and an optional flashlight
// For each phase, a calculate function is defined that calculates the corresponding color
// per lamp. In the main() function we take all the calculated colors and sum them up for
// this fragment's final color.
// == ======================================
// Phase 1: Directional lighting
vec3 result = vec3(0.0f);
//result = CalcDirLight(dirLight, norm, viewDir);
// Phase 2: Point lights
for(int i = 0; i < NR_POINT_LIGHTS; i++)
{
result += CalcPointLight(pointLights[i], norm, FragPos, viewDir, fragColor);
}
// Phase 3: Spot light
//result += CalcSpotLight(spotLight, norm, FragPos, viewDir);
result += material.ambient * fragColor;
color = vec4(result, 1.0);
}
// Calculates the color when using a directional light.
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
vec3 lightDir = normalize(-light.direction);
// Diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// Specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// Combine results
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
return (diffuse + specular);
}
// Calculates the color when using a point light.
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir, vec3 fcolor)
{
if (light.active == 1)
{
// Lighting
vec3 lighting = vec3(0.0f);
// Diffuse
vec3 lightDir = normalize(light.position - fragPos);
float diff = max(dot(lightDir, normal), 0.0);
vec3 result = light.color * diff * fcolor;
// Attenuation (use quadratic as we have gamma correction)
float distance = (length(fragPos - light.position)/light.strength);
result *= 1.0 / (distance * distance);
lighting += result;
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = spec * vec3(texture(material.specular, TexCoords)) * light.color;
specular *= material.shininess;
specular *= 1.0 / (distance * distance);
vec3 toReturn = lighting + specular;
return toReturn;
}
else
{
return vec3(0.0f, 0.0f, 0.0f);
}
}
// Calculates the color when using a spot light.
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - fragPos);
// Diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// Specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// Attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0f / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
// Spotlight intensity
float theta = dot(lightDir, normalize(-light.direction));
float epsilon = light.cutOff - light.outerCutOff;
float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);
// Combine results
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
ambient *= attenuation * intensity;
diffuse *= attenuation * intensity;
specular *= attenuation * intensity;
return (diffuse + specular);
}
谢天谢地,我的程序确实打印出了编译错误。这是吐出来的。不幸的是,它指向的线不是真实的......就像它们存在但它们没有任何问题,其中一个错误指向一条没有代码的线......我没有改变它的原始片段着色器部分所以这不是问题
错误图片可在以下位置找到:https://app.box.com/s/3nrzjyu3p2smnow5zo8j0q1lbqgdf149
我试过 glslDevil,但我不知道如何导入我的着色器。
非常感谢!
编辑: 我发现的有趣的东西... 我注意到的一件有趣的事情是,如果你这样定义定向光函数
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
vec3 lightDir = normalize(-light.direction);
// Diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// Specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// Combine results
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
return (diffuse + specular);
}
它只会抛出一个错误,即 diffuse、specular 和 ambient 不是该结构的成员(这是故意的)
你的错误日志不好
- 这是您正在使用的工具的一些链接日志
- 不是 OpenGL 编译日志!!!
我把你的片段着色器放入OpenGL,这是真实的编译日志(使用nVidia):
[Fragment]
Compiler error
0(94) : error C1009: "ambient" is not member of struct "DirLight"
0(95) : error C1009: "diffuse" is not member of struct "DirLight"
0(96) : error C1009: "specular" is not member of struct "DirLight"
[Program]
Linker error
Fragment info
-------------
0(94) : error C1009: "ambient" is not member of struct "DirLight"
0(95) : error C1009: "diffuse" is not member of struct "DirLight"
0(96) : error C1009: "specular" is not member of struct "DirLight"
- 你应该为你在 OpenGL 中使用的每个 shader/program 对象使用
- 我使用类似 this
glGetShaderInfoLog
有道理:
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
vec3 lightDir = normalize(-light.direction);
// Diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// Specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// Combine results
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
return (diffuse + specular);
}
在 // Combine results
之后您正在访问 struct
中未定义的字段:
struct DirLight {
vec3 direction;
vec3 color;
float strength;
};
[edit1] 在 C++ 中我将我的 class 用于 GLSL:
//------------------------------------------------------------------------------
//--- GLSL program class -------------------------------------------------------
//------------------------------------------------------------------------------
class GLSLprogram // GLSL program class
{
public:
AnsiString log;
int prog_id, // whole program
tesc_id, // tessellation control
tese_id, // tessellation evaluation
geom_id, // geometry
vert_id, // vertex
frag_id; // fragment
GLSLprogram();
GLSLprogram(GLSLprogram& a);
~GLSLprogram();
GLSLprogram* operator = (const GLSLprogram *a);
//GLSLprogram* operator = (const GLSLprogram &a);
void bind();
void unbind();
void set_source_text(AnsiString tesc,AnsiString tese,AnsiString geom,AnsiString vert,AnsiString frag); // set source texts
void set_source_file(AnsiString tesc,AnsiString tese,AnsiString geom,AnsiString vert,AnsiString frag); // load and set source files
void set1f (AnsiString name,GLfloat x);
void set2f (AnsiString name,GLfloat x, GLfloat y);
void set3f (AnsiString name,GLfloat x, GLfloat y, GLfloat z);
void set4f (AnsiString name,GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void set1i (AnsiString name,GLint x);
void set2i (AnsiString name,GLint x, GLint y);
void set3i (AnsiString name,GLint x, GLint y, GLint z);
void set4i (AnsiString name,GLint x, GLint y, GLint z, GLint w);
void set1fv (AnsiString name,GLfloat *p);
void set2fv (AnsiString name,GLfloat *p);
void set3fv (AnsiString name,GLfloat *p);
void set4fv (AnsiString name,GLfloat *p);
void set1iv (AnsiString name,GLint *p);
void set2iv (AnsiString name,GLint *p);
void set3iv (AnsiString name,GLint *p);
void set4iv (AnsiString name,GLint *p);
void set2x2fv(AnsiString name,GLfloat *p);
void set3x3fv(AnsiString name,GLfloat *p);
void set4x4fv(AnsiString name,GLfloat *p);
void get1f (AnsiString name,GLfloat &x);
void get2f (AnsiString name,GLfloat &x, GLfloat &y);
void get3f (AnsiString name,GLfloat &x, GLfloat &y, GLfloat &z);
void get4f (AnsiString name,GLfloat &x, GLfloat &y, GLfloat &z, GLfloat &w);
void get1i (AnsiString name,GLint &x);
void get2i (AnsiString name,GLint &x, GLint &y);
void get3i (AnsiString name,GLint &x, GLint &y, GLint &z);
void get4i (AnsiString name,GLint &x, GLint &y, GLint &z, GLint &w);
void get1fv (AnsiString name,GLfloat *p);
void get2fv (AnsiString name,GLfloat *p);
void get3fv (AnsiString name,GLfloat *p);
void get4fv (AnsiString name,GLfloat *p);
void get1iv (AnsiString name,GLint *p);
void get2iv (AnsiString name,GLint *p);
void get3iv (AnsiString name,GLint *p);
void get4iv (AnsiString name,GLint *p);
void get2x2fv(AnsiString name,GLfloat *p);
void get3x3fv(AnsiString name,GLfloat *p);
void get4x4fv(AnsiString name,GLfloat *p);
};
//------------------------------------------------------------------------------
GLSLprogram::GLSLprogram()
{
prog_id=0;
tesc_id=0;
tese_id=0;
geom_id=0;
vert_id=0;
frag_id=0;
}
//------------------------------------------------------------------------------
GLSLprogram::~GLSLprogram()
{
if (glDetachShader==NULL) return;
if (glDeleteShader==NULL) return;
unbind();
if (tesc_id>0) { glDetachShader(prog_id,tesc_id); glDeleteShader(tesc_id); }
if (tese_id>0) { glDetachShader(prog_id,tese_id); glDeleteShader(tese_id); }
if (geom_id>0) { glDetachShader(prog_id,geom_id); glDeleteShader(geom_id); }
if (vert_id>0) { glDetachShader(prog_id,vert_id); glDeleteShader(vert_id); }
if (frag_id>0) { glDetachShader(prog_id,frag_id); glDeleteShader(frag_id); }
if (prog_id>0) { glDeleteShader(prog_id); }
log="";
}
//------------------------------------------------------------------------------
void GLSLprogram::bind()
{
if (glUseProgram==NULL) return;
glUseProgram(prog_id);
}
//------------------------------------------------------------------------------
void GLSLprogram::unbind()
{
if (glUseProgram==NULL) return;
glUseProgram(0);
}
//------------------------------------------------------------------------------
void GLSLprogram::set_source_text(AnsiString tesc,AnsiString tese,AnsiString geom,AnsiString vert,AnsiString frag)
{
if (glCreateProgram==NULL) return;
if (glShaderSource==NULL) return;
if (glCompileShader==NULL) return;
if (glAttachShader==NULL) return;
if (glGetShaderiv==NULL) return;
if (glGetShaderInfoLog==NULL) return;
if (glLinkProgram==NULL) return;
if (glGetProgramiv==NULL) return;
if (glGetProgramInfoLog==NULL) return;
if (glReleaseShaderCompiler==NULL) return;
const int _size=1024;
char dat[_size];
GLint status,siz=0,i;
const char * TC = tesc.c_str();
const char * TE = tese.c_str();
const char * GS = geom.c_str();
const char * VS = vert.c_str();
const char * FS = frag.c_str();
log="";
if (prog_id<=0) prog_id=glCreateProgram();
if (tesc_id<=0) tesc_id=glCreateShader(GL_TESS_CONTROL_SHADER);
else glDetachShader(prog_id,tesc_id);
if (tesc!="")
{
glShaderSource(tesc_id, 1, &TC,NULL);
glCompileShader(tesc_id);
glAttachShader(prog_id,tesc_id);
glGetShaderiv(tesc_id,GL_COMPILE_STATUS,&status);
log+="[Tessellation control]\n";
if (status) log+="OK\n"; else log+="Compiler error\n";
glGetShaderInfoLog(tesc_id,_size,&siz,dat);
for (i=0;i<siz;i++) log+=dat[i];
}
if (tese_id<=0) tese_id=glCreateShader(GL_TESS_EVALUATION_SHADER);
else glDetachShader(prog_id,tese_id);
if (tese!="")
{
glShaderSource(tese_id, 1, &TE,NULL);
glCompileShader(tese_id);
glAttachShader(prog_id,tese_id);
glGetShaderiv(tese_id,GL_COMPILE_STATUS,&status);
log+="[Tessellation evaluation]\n";
if (status) log+="OK\n"; else log+="Compiler error\n";
glGetShaderInfoLog(tese_id,_size,&siz,dat);
for (i=0;i<siz;i++) log+=dat[i];
}
if (geom_id<=0) geom_id=glCreateShader(GL_GEOMETRY_SHADER);
else glDetachShader(prog_id,geom_id);
if (geom!="")
{
glShaderSource(geom_id, 1, &GS,NULL);
glCompileShader(geom_id);
glAttachShader(prog_id,geom_id);
glGetShaderiv(geom_id,GL_COMPILE_STATUS,&status);
log+="[Geometry]\n";
if (status) log+="OK\n"; else log+="Compiler error\n";
glGetShaderInfoLog(geom_id,_size,&siz,dat);
for (i=0;i<siz;i++) log+=dat[i];
}
if (vert_id<=0) vert_id=glCreateShader(GL_VERTEX_SHADER);
else glDetachShader(prog_id,vert_id);
if (vert!="")
{
glShaderSource(vert_id, 1, &VS,NULL);
glCompileShader(vert_id);
glAttachShader(prog_id,vert_id);
glGetShaderiv(vert_id,GL_COMPILE_STATUS,&status);
log+="[Vertex]\n";
if (status) log+="OK\n"; else log+="Compiler error\n";
glGetShaderInfoLog(vert_id,_size,&siz,dat);
for (i=0;i<siz;i++) log+=dat[i];
}
if (frag_id<=0) frag_id=glCreateShader(GL_FRAGMENT_SHADER);
else glDetachShader(prog_id,frag_id);
if (frag!="")
{
glShaderSource(frag_id, 1, &FS,NULL);
glCompileShader(frag_id);
glAttachShader(prog_id,frag_id);
glGetShaderiv(frag_id,GL_COMPILE_STATUS,&status);
log+="\n[Fragment]\n";
if (status) log+="OK\n"; else log+="Compiler error\n";
glGetShaderInfoLog(frag_id,_size,&siz,dat);
for (i=0;i<siz;i++) log+=dat[i];
}
glLinkProgram(prog_id);
glGetProgramiv(prog_id,GL_LINK_STATUS,&status);
log+="\n[Program]\n";
if (status) log+="OK\n"; else log+="Linker error\n";
glGetProgramInfoLog(prog_id,_size,&siz,dat);
for (i=0;i<siz;i++) log+=dat[i];
glReleaseShaderCompiler();
}
//------------------------------------------------------------------------------
void GLSLprogram::set_source_file(AnsiString tesc,AnsiString tese,AnsiString geom,AnsiString vert,AnsiString frag)
{
set_source_text(load(tesc),load(tese),load(geom),load(vert),load(frag));
}
//------------------------------------------------------------------------------
void GLSLprogram::set1f (AnsiString name,GLfloat x) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform1f (id,x); }
void GLSLprogram::set2f (AnsiString name,GLfloat x, GLfloat y) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform2f (id,x,y); }
void GLSLprogram::set3f (AnsiString name,GLfloat x, GLfloat y, GLfloat z) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform3f (id,x,y,z); }
void GLSLprogram::set4f (AnsiString name,GLfloat x, GLfloat y, GLfloat z, GLfloat w){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform4f (id,x,y,z,w); }
void GLSLprogram::set1i (AnsiString name,GLint x) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform1i (id,x); }
void GLSLprogram::set2i (AnsiString name,GLint x, GLint y) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform2i (id,x,y); }
void GLSLprogram::set3i (AnsiString name,GLint x, GLint y, GLint z) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform3i (id,x,y,z); }
void GLSLprogram::set4i (AnsiString name,GLint x, GLint y, GLint z, GLint w) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform4i (id,x,y,z,w); }
void GLSLprogram::set1fv (AnsiString name,GLfloat *p) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform1fv (id,1,p); }
void GLSLprogram::set2fv (AnsiString name,GLfloat *p) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform2fv (id,2,p); }
void GLSLprogram::set3fv (AnsiString name,GLfloat *p) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform3fv (id,3,p); }
void GLSLprogram::set4fv (AnsiString name,GLfloat *p) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform4fv (id,4,p); }
void GLSLprogram::set1iv (AnsiString name,GLint *p) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform1iv (id,1,p); }
void GLSLprogram::set2iv (AnsiString name,GLint *p) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform2iv (id,2,p); }
void GLSLprogram::set3iv (AnsiString name,GLint *p) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform3iv (id,3,p); }
void GLSLprogram::set4iv (AnsiString name,GLint *p) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform4iv (id,4,p); }
void GLSLprogram::set2x2fv(AnsiString name,GLfloat *p) { GLboolean q=true; GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniformMatrix2fv(id, 4,q,p); }
void GLSLprogram::set3x3fv(AnsiString name,GLfloat *p) { GLboolean q=true; GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniformMatrix3fv(id, 9,q,p); }
void GLSLprogram::set4x4fv(AnsiString name,GLfloat *p) { GLboolean q=true; GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniformMatrix4fv(id,16,q,p); }
//------------------------------------------------------------------------------
void GLSLprogram::get1f (AnsiString name,GLfloat &x){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformfv(prog_id,id,&x); }
void GLSLprogram::get1i (AnsiString name,GLint &x) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformiv(prog_id,id,&x); }
void GLSLprogram::get1fv (AnsiString name,GLfloat *p){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformfv(prog_id,id,p); }
void GLSLprogram::get2fv (AnsiString name,GLfloat *p){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformfv(prog_id,id,p); }
void GLSLprogram::get3fv (AnsiString name,GLfloat *p){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformfv(prog_id,id,p); }
void GLSLprogram::get4fv (AnsiString name,GLfloat *p){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformfv(prog_id,id,p); }
void GLSLprogram::get1iv (AnsiString name,GLint *p) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformiv(prog_id,id,p); }
void GLSLprogram::get2iv (AnsiString name,GLint *p) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformiv(prog_id,id,p); }
void GLSLprogram::get3iv (AnsiString name,GLint *p) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformiv(prog_id,id,p); }
void GLSLprogram::get4iv (AnsiString name,GLint *p) { GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformiv(prog_id,id,p); }
void GLSLprogram::get2x2fv(AnsiString name,GLfloat *p){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformfv(prog_id,id,p); }
void GLSLprogram::get3x3fv(AnsiString name,GLfloat *p){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformfv(prog_id,id,p); }
void GLSLprogram::get4x4fv(AnsiString name,GLfloat *p){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformfv(prog_id,id,p); }
//------------------------------------------------------------------------------
AnsiString
只是 VCL 字符串 class(自重定位字符串 class)可以使用其他任何东西,例如char[]
或char*
而不是,但您需要处理粗运算符...AnsiString().c_str()
returnschar*
存储字符串的兼容指针
用法:
// [variables]
GLSLprogram shader;
// [init]
shader.set_source_text("","","","your vertex shader source text","your fragment shader source text");
shader.log; // contains the compile/link log ...
shader.prog_id; // contains the OpenGL id for your shader object
// [render]
shader.bind();
// here render
shader.unbind();
[edit2] 而且我忘了添加:
AnsiString load(AnsiString file)
{
int i,hnd,siz;
char *dat=NULL;
hnd=FileOpen(file,fmOpenRead);
if (hnd<0) return "";
siz=FileSeek(hnd,0,2);
FileSeek(hnd,0,0);
if (siz==0) { FileClose(hnd); return ""; }
dat=new char[siz+1];
if (dat==NULL) { FileClose(hnd); return ""; }
FileRead(hnd,dat,siz);
FileClose(hnd);
AnsiString s=""; for (i=0;i<siz;i++) s+=dat[i];
delete dat;
return s;
}