错误:0:2:'属性' :无法初始化此类限定符(无论使用从1.1到1.5的GLSL版本)

时间:2016-01-07 10:23:05

标签: opengl glsl shader

我跟着关于GLSL的developpez tuto,http://alexandre-laurent.developpez.com/tutoriels/OpenGL/OpenGL-GLSL;我下载了作者提出的最终项目,除了这行代码之外,一切正常:

ERROR: 0:2: 'attribute' :  cannot initialize this type of qualifier

这是vert文件内容:

#version 120
attribute vec3 couleur = vec3(0.0,1.0,0.0);

void main (void)
{
    gl_Position = ftransform(); 
    gl_FrontColor = vec4(couleur,1.0);
}

和frag文件

#version 120
void main(void)
{
    gl_FragColor = gl_Color;
}

即使我将版本更改为140,150,110,我仍然会收到此错误代码,认为作者显示的spashscreen显示所有工作;

如果有帮助,我会使用英特尔(R)高清显卡775Mb

这是我的main.cpp文件(我没有更改任何内容,它使用freeglut作为渲染器):

#include <GL/glew.h>

#include <GL/freeglut.h>
/*
#include <GL/gl.h>
#include <GL/glu.h>
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

// Déclaration des points de notre cube
GLfloat cubeVertices[] =
{
    // Face de devant
    1,1,1,
    -1,1,1,
    -1,-1,1,
    1,-1,1,

    1, 1, -1,
    -1, 1, -1,

    -1, -1, -1,
    1, -1, -1,
};

GLfloat cubeColours[] =
{
    1, 0, 0,
    0, 1, 0,
    0, 1, 0,
    1, 0, 0,

    0, 0, 1,
    1, 1, 0,

    1, 1, 0,
    0, 0, 1,
};

GLubyte cubeIndices[] =
{
    0, 1, 2, 3,
    0, 4, 7, 3,
    4, 5, 6, 7,
    1, 2, 6, 5,
    2, 3, 7, 6,
    0, 1, 5, 4
};

GLuint vertexID = 0;
GLuint fragmentID = 0;
GLuint programID = 0;

GLint attributeId = 0;

unsigned int getFileSize(FILE* const pFile)
{
    long length = 0;

    fseek(pFile,0,SEEK_END);

    length = ftell(pFile);

    // Ne pas oublier de mettre le fichier à son début, sinon on ne peut pas le lire
    fseek(pFile,0,SEEK_SET);

    return length;
}

/**
    Le fonction retourne un pointeur, qui a été alloué dans la fonction même.
    ! Ceci est extrèmement dangereux car cela peut entrainer des fuites de mémoire
    du à l'oubli de libéré le pointeur.
*/
char* readFile(const char* fileName)
{
    FILE* pFile = NULL;
    char* fileContent = NULL;
    unsigned int fileSize = 0;

    pFile = fopen(fileName,"r");
    if ( pFile == NULL )
    {
        fprintf(stderr,"Erreur d'ouverture du fichier: '%s'\n",fileName);
        return NULL;
    }

    fileSize = getFileSize(pFile);

    fileContent = (char*)malloc(fileSize+1);
    if ( fileContent == NULL )
    {
        fprintf(stderr,"Erreur d'allocation de la mémoire pour y placer le contenu du fichier\n");
        return NULL;
    }

    fread(fileContent,fileSize,1,pFile);
    // Termine le tableau qui contient le shader
    fileContent[fileSize] = '\0';

    fclose(pFile);

    return fileContent;
}

void deleteShader()
{
    // On arrête d'utiliser le programme shader
    glUseProgram(0);

    // Deliage des shaders au programme
    glDetachShader(programID, fragmentID);
    glDetachShader(programID, vertexID);

    // Destruction du programme
    glDeleteProgram(programID);

    // Destruction des IDs des shaders
    glDeleteShader(fragmentID);
    glDeleteShader(vertexID);
}

// Pour plus de simplicité, j'ajoute une fonction qui vérifie la compilation des shaders
char checkShaderCompilation(GLuint shaderID)
{
    GLint compilationStatus = 0;

    // Verification de la compialtion pour le vertex shader
    glGetShaderiv(vertexID, GL_COMPILE_STATUS, &compilationStatus);
    if ( compilationStatus != GL_TRUE )
    {
        // Nous savons que la compilation a échoué, donc nous devons savoir pourquoi
        // Nous devons récupéré la taille du log
        GLint logLength = 0;
        GLchar* log = NULL;

        glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &logLength);

        // Maintenant que nous avons la taille, nous pouvons alloué la mémoire suffisante pour ce log
        log = (GLchar*)malloc(logLength);
        if ( log == NULL )
        {
            fprintf(stderr,"Erreur d'allocation de mémoire pour le log de la compilation du shader\n");
            return 0;
        }

        glGetShaderInfoLog(shaderID, logLength, &logLength, log);

        // On peut afficher le message
        fprintf(stderr,"Erreur de compilation:\n%s",log);

        // Et on n'oublie pas de libéré la mémoire
        free(log);

        return 0;
    }

    return 1; // Pas d'erreur
}

void loadShader()
{
    GLchar* vertexSource = NULL;
    GLchar* fragmentSource = NULL;
    GLint programState = 0;
    GLint vertexSize = 0;
    GLint fragmentSize = 0;
    GLenum errorState = GL_NO_ERROR;

    // Création des IDs
    vertexID = glCreateShader(GL_VERTEX_SHADER);
    fragmentID = glCreateShader(GL_FRAGMENT_SHADER);

    // Lecture des fichiers
    // Certaines personnes aiment avoir le fichier du vertex shader avec l'extion .vert
    // et le fichier du fragement shader avec l'extension .frag
    vertexSource = (GLchar*)readFile("data/simple.vert");
    fragmentSource = (GLchar*)readFile("data/simple.frag");

    if ( !vertexSource || !fragmentSource )
    {
        // Ici, il faudrait faire en sorte que le programme s'arrête
        deleteShader();    // Nettoyage
        return;
    }

    // Chargement des sources dans OpenGL
    vertexSize = strlen(vertexSource);
    fragmentSize = strlen(fragmentSource);
    glShaderSource(vertexID, 1, (const GLchar**)(&vertexSource), &vertexSize);
    glShaderSource(fragmentID, 1, (const GLchar**)(&fragmentSource), &fragmentSize);

    // Compilation du vertex shader
    glCompileShader(vertexID);
    glCompileShader(fragmentID);

    // Vérification des erreurs
    if ( !checkShaderCompilation(vertexID) || !checkShaderCompilation(fragmentID))
    {
        deleteShader();
        return;
    }


    // Creation de l'ID pour le programme
    programID = glCreateProgram();

    // On attache les shader ensemble
    glAttachShader(programID, vertexID);
    glAttachShader(programID, fragmentID);

    // On peut enfin passer aux liage.
    glLinkProgram(programID);

    // Et encore une fois on vérifie si tout se passe bien
    glGetProgramiv(programID , GL_LINK_STATUS  , &programState);
    if ( programState != GL_TRUE)
    {
        // On récupère la taille du log
        GLint logSize = 0;
        GLchar* log = NULL;

        glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &logSize);

        // On peut allouer la mémoire, une fois que l'on a la taille du log
        log = (GLchar*)malloc(logSize);
        if ( log == NULL )
        {
            fprintf(stderr,"Erreur d'allocation de mémoire pour le log de la compilation du programme\n");
            deleteShader();
            return;
        }

        // Et on récupère le log
        glGetProgramInfoLog(programID, logSize, &logSize, log);

        // On affiche
        fprintf(stderr,"Erreur lors du liage du shader:\n%s",log);

        free(log);
        deleteShader();
        return;
    }

    attributeId = glGetAttribLocation(programID, "couleur");
    errorState = glGetError();
    if ( attributeId == -1 || errorState != GL_NO_ERROR )
    {
        fprintf(stderr,"Erreur (%d) lors de la récupération de l'id de la variable attribute 'couleur'\n",errorState);
    }

    // Voilà, nous sommes prêt
    glUseProgram(programID);

    glEnableVertexAttribArray(attributeId);
    errorState = glGetError();

    glVertexAttribPointer(attributeId,
                          3,
                          GL_FLOAT,
                          GL_TRUE,
                          0,
                          cubeColours);

    if ( errorState != GL_NO_ERROR )
    {
        fprintf(stderr,"Erreur (%d) lors du passage du tableau de valeur à la variable attribute 'couleur'\n",errorState);
    }
}

void initScene()
{
    glClearColor(0.0,0.5,0.0,1.0);

    // Depth
    glClearDepth(1.0);
    glDepthFunc(GL_LESS);
    glEnable(GL_DEPTH_TEST);

    // Perspective mode
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    gluPerspective(45.0f,(GLfloat)640/(GLfloat)480,0.1f,100.0f);

    glMatrixMode(GL_MODELVIEW);

    loadShader();

    // Init the cube
        // Tell to OpenGL that we are using :
        //  - Vertices
        //  - Colours
    glEnableClientState(GL_VERTEX_ARRAY);
    //glEnableClientState(GL_COLOR_ARRAY);

    // Assign our data to OpenGL
    glVertexPointer(3, GL_FLOAT, 0, cubeVertices);
    //glColorPointer(3, GL_FLOAT, 0, cubeColours);
}

void renderScene()
{
    // Rotation stuff
    static unsigned int rotationAngle;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();

    gluLookAt(-2,5,-4,
              0,0,0,
              0,1,0);

    glRotated(rotationAngle, 1, 1, 0);

    // draw the cube
    glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, cubeIndices);

    if ( glGetError() != GL_NO_ERROR )
    {
        fprintf(stderr,"Error occur during drawing");
        return;
    }

    glutSwapBuffers();

    rotationAngle++;
}

void quitScene()
{
    glDisableVertexAttribArray(attributeId);
    //glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);

    deleteShader();
}

void keyboardFeedback(unsigned char key, int x, int y)
{
    if ( key == 27 ) // Escape
    {
        quitScene();
        glutLeaveMainLoop();
    }
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);

    glutInitWindowPosition(-1, -1);
    glutInitWindowSize(640,480);

    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE |GLUT_DEPTH);

    glutCreateWindow("OpenGL Shaders");

    // Demarrage de GLEW
    if ( glewInit() != GLEW_OK )
    {
        fprintf(stderr,"Echec du demarrage de GLEW\n");
        return -1;
    }

    // On vérifie que l'on peut géré les shaders
    // Check if the machine is capable of rendering our scene
    if ( !glewIsSupported("GL_ARB_shading_language_100") )
    {
        fprintf(stderr,"GL_ARB_shading_language_100 introuvables\n");
        return -2;
    }
    if ( !glewIsSupported("GL_ARB_shader_objects") )
    {
        fprintf(stderr,"GL_ARB_shader_objects introuvables\n");
        return -3;
    }
    if ( !glewIsSupported("GL_ARB_vertex_shader") )
    {
        fprintf(stderr,"GL_ARB_vertex_shader introuvables\n");
        return -4;
    }
    if ( !glewIsSupported("GL_ARB_fragment_shader") )
    {
        fprintf(stderr,"GL_ARB_fragment_shader introuvables\n");
        return -5;
    }

    initScene();
    // glutDisplayFunc(renderScene);
    glutKeyboardFunc(keyboardFeedback);
    glutIdleFunc(renderScene);

    glutMainLoop();

    quitScene();

    return 0;
}

请帮助:p

2 个答案:

答案 0 :(得分:2)

问题出在这一行:

attribute vec3 couleur = vec3(0.0,1.0,0.0);

如消息所示,GLSL中不允许初始化属性。他们必须从计划外填补。将行更改为

attribute vec3 couleur;

然后着色器将编译。但是您仍然需要将一些数据附加到属性中。

答案 1 :(得分:0)

执行以下操作:

    if(solidColor) {gl.vertexAttrib4f(program.colorVertLocation, red, green, blue, alpha);}
    if(!solidColor) {gl.enableVertexAttribArray(program.colorVertLocation);}

如果有时需要所有顶点使用一种颜色,则可以使用“ vertexAttrib4f”设置默认属性值,然后在任何时候不启用顶点属性数组时,它将使用该默认值。