Невозможно связать скомпилированные шейдеры (GLSL)

У меня есть небольшой класс, который позволяет мне загружать шейдеры и использовать их в своей программе. Я умею компилировать шейдеры, но когда приходит время их линковать, они просто не хотят. Используя glGetProgramInfoLog, я получил следующий журнал ошибок. Я не понимаю, почему он говорит мне, что программа не определена, поскольку компиляция работала нормально...

Vertex info
-----------
(0) : error C3001: no program defined
Fragment info
-------------
(0) : error C3001: no program defined

Код ниже выполняет привязку GLSL:

program_ = glCreateProgramObjectARB();

if (vertex_) {
   glAttachObjectARB(program_, vertex_);
}

if (fragment_) {
   glAttachObjectARB(program_, fragment_);
}

glLinkProgramARB(program_); 

vertex_ и fragment_ — это вершинный и фрагментный шейдер, а program_ — это ProgramObjectARB.

Я хотел бы знать, какие необходимые изменения мне нужно сделать, чтобы сделать этот запуск.

Вершинный шейдер:

varying vec4 OCPosition;   // surface positon in world's coordinates
varying vec4 ECposition;   // surface position in eye coordinates
varying vec4 ECballCenter; // ball center in eye coordinates
uniform vec4 BallCenter;   // ball center in modelling coordinates

void main()
{
  OCPosition   = gl_Vertex;
  ECposition   = gl_ModelViewMatrix * OCPosition;
  ECballCenter = gl_ModelViewMatrix * BallCenter;

  gl_Position  = gl_ProjectionMatrix * ECposition;
}

Фрагментный шейдер:

varying vec4 OCPosition;   // surface position in world coordinates
varying vec4 ECposition;   // surface position in eye coordinates
varying vec4 ECballCenter; // ball center in eye coordinates

uniform vec4  LightDir;     // light direction, should be normalized
uniform vec4  HVector;      // reflection vector for infinite light source
uniform vec4  SpecularColor;
uniform vec4  BaseColor, StripeColor;

uniform float StripeWidth;  // = 0.3
uniform float FWidth;       // = 0.005

void main()
{
vec3  normal;              // Analytically computed normal
vec4  p;                   // Point in shader space
vec4  surfColor;           // Computed color of the surface
float intensity;           // Computed light intensity
vec4  distance;            // Computed distance values
float inorout;             // Counter for computing star pattern

p.xyz = normalize(OCPosition.xyz);    // Calculate p
p.w   = 1.0;

distance.y = StripeWidth - abs(p.z);
distance.xy = smoothstep(-FWidth, FWidth, distance.xy);

surfColor = mix(BaseColor, StripeColor, distance.y);

// normal = point on surface for sphere at (0,0,0)
normal = normalize(ECposition.xyz - ECballCenter.xyz);

// Per fragment diffuse lighting
intensity  = 0.2; // ambient
intensity += 0.8 * clamp(dot(LightDir.xyz, normal), 0.0, 1.0);
surfColor *= intensity;

// Per fragment specular lighting
intensity  = clamp(dot(HVector.xyz, normal), 0.0, 1.0);
intensity  = pow(intensity, SpecularColor.a);
surfColor += SpecularColor * intensity;

gl_FragColor = surfColor;
}

EDIT - SOLUTION Кажется, метод, который я использовал для чтения исходного файла, был неверным. Шейдер компилировался, но при линковке работал некорректно. Теперь я использую этот метод для чтения моего файла, и ссылка правильная:

char *textFileRead(char *fn) {


FILE *fp;
char *content = NULL;

int count=0;

if (fn != NULL) {
    fp = fopen(fn,"rt");

    if (fp != NULL) {

        fseek(fp, 0, SEEK_END);
        count = ftell(fp);
        rewind(fp);

        if (count > 0) {
            content = (char *)malloc(sizeof(char) * (count+1));
            count = fread(content,sizeof(char),count,fp);
            content[count] = '\0';
        }
        fclose(fp);
    }
}
return content;
}

person tomzx    schedule 21.12.2009    source источник


Ответы (3)


Этот конкретный код ошибки от компилятора GLSL в драйвере Nvidia означает, что ему не удалось найти функцию с именем main в вашем шейдере (в данном случае либо вершину, либо фрагмент)

Наиболее распространенная причина этого заключается в том, что вы на самом деле не передаете программу драйверу, когда думаете, что это так: либо строка, которую вы передаете, не была инициализирована, либо вы передаете длину 0, и вы на самом деле ничего не компилируете.

Изменить

Я думаю, что что-то не так с вызовами glCreateShader или glSetShaderSource. В большинстве случаев ошибки появляются только тогда, когда вы пытаетесь связать шейдеры (а не компилировать), так как драйвер впервые узнает, что у него есть полные шейдеры, а не только частичные, неполные шейдеры, для завершения которых требуется связать другой шейдер. .

person Chris Dodd    schedule 21.12.2009
comment
Компиляция выглядит нормально, если я очистил один из файлов, он больше не работает, выдавая мне еще одну ошибку о EOF. Я считаю, что компиляция выполнена правильно, но по какой-то причине не может произойти связывание... Я передаю инициализированную строку с нулевым завершением. - person tomzx; 21.12.2009

Ваши шейдеры у меня отлично работают, я сделал небольшую тестовую программу для их компиляции и проблем не возникло:

GLuint program = glCreateProgramObjectARB();
assert(program);

GLuint vertex_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
assert(vertex_shader);
glShaderSourceARB(vertex_shader, 1, /*your vertex shader*/, 0);
glCompileShaderARB(vertex_shader);

GLint compile_status;
glGetObjectParameterivARB(vertex_shader, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);
assert(1 == compile_status);

GLuint fragment_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
assert(fragment_shader);
glShaderSourceARB(fragment_shader, 1, /*your fragment shader*/, 0);
glCompileShaderARB(fragment_shader);

glGetObjectParameterivARB(vertex_shader, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);
assert(1 == compile_status);

glAttachObjectARB(program, vertex_shader);
assert(GL_NO_ERROR == glGetError());

glAttachObjectARB(program, fragment_shader);
assert(GL_NO_ERROR == glGetError());

glLinkProgramARB(program);  
assert(GL_NO_ERROR == glGetError());

GLint link_status;
glGetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &link_status);
assert(1 == link_status);

Вы делаете то же самое?

person Andreas Brinck    schedule 21.12.2009
comment
Я попробовал вашу программу, и все же она не работает при связывании, link_status == 0 и утверждение не выполняется. - person tomzx; 21.12.2009
comment
@tomzx Можете ли вы показать, как вы называете glShaderSourceARB? Какая у вас видеокарта и какой драйвер? - person Andreas Brinck; 21.12.2009
comment
glShaderSourceARB(fragment_shader, 1, (const GLcharARB**)&cstr, 0); cstr — это указатель на динамически выделяемый char (char* cstr = new char[]). У меня nVidia GeForce 8800GT, драйвера стоят по умолчанию, версия 191.07. - person tomzx; 21.12.2009
comment
@tomzx Я предполагаю, что с данными в cstr что-то не так. Что можно проверить: 1. Оканчивается ли он нулем? 2. Есть ли перевод строки в конце исходника (это не должно иметь значения, но иногда все же имеет значение ;)? - person Andreas Brinck; 21.12.2009

Попробуйте использовать glGetError после ваших вызовов glAttachObjectARB, чтобы увидеть, не сработали ли они.

person tkerwin    schedule 21.12.2009
comment
glGetError после того, как оба вызова вернут 0. - person tomzx; 21.12.2009
comment
Вы также можете попробовать: bool fragCompiled, vertCompiled; glGetShaderiv(fragment_, GL_COMPILE_STATUS, &fragCompiled); glGetShaderiv(vertex_, GL_COMPILE_STATUS, &vertCompiled); - person tkerwin; 21.12.2009
comment
Я изменил ваш bool на GLint, и они оба возвращают 1, поэтому они скомпилированы. - person tomzx; 21.12.2009
comment
Похоже, вы могли столкнуться с ошибкой драйвера. - person tkerwin; 21.12.2009