Foros - Stratos

Programadores => Programación gráfica => Mensaje iniciado por: killgates en 05 de Diciembre de 2015, 06:43:33 PM

Título: Error al compilar objeto de shader
Publicado por: killgates en 05 de Diciembre de 2015, 06:43:33 PM
Hola,

Tengo un problema al compilar un objeto de shader. Pues me devuelve FALSE cuando compruebo el estado de la compilación. El código es el siguiente:
         
         //fuenteShader es un arreglo de 1000 índices de tipo char que contiene el fichero de shader todo seguido.
    const GLchar* tmp = static_cast<const GLchar*>(fuenteShader);  //Esta parte la he sacado de un libro de opengl con c++
    glShaderSource(objetoShader1, 1, (const GLchar**)&tmp, NULL);  //Si me la podeis explicar Gracias

    glCompileShader(objetoShader1);
    GLint result;
    glGetShaderiv(objetoShader1, GL_COMPILE_STATUS, &result);
    if (result == GL_TRUE)
        std::cout << "\nEl shader se compiló con éxito";
    else std::cout << "\nEl shader no se ha compilado con exito!";


Siempre me dice que el shader no se ha compilado con éxito.
Gracias.
Título: Re:Error al compilar objeto de shader
Publicado por: Gallo en 08 de Diciembre de 2015, 11:32:56 AM
Como el error puede ser debido a muchos motivos, desde que no estés pasando el tipo de shader correcto a cualquier error de sintaxis, te recomiendo agregar esto a la comprobación de errores:



      //fuenteShader es un arreglo de 1000 índices de tipo char que contiene el fichero de shader todo seguido.
    const GLchar* tmp = static_cast<const GLchar*>(fuenteShader);  //Esta parte la he sacado de un libro de opengl con c++
    glShaderSource(objetoShader1, 1, (const GLchar**)&tmp, NULL);  //Si me la podeis explicar Gracias

    glCompileShader(objetoShader1);
    GLint result;
    glGetShaderiv(objetoShader1, GL_COMPILE_STATUS, &result);

    if (result == GL_TRUE)
    {
        std::cout << "El shader se compiló con éxito" << std::endl;
    }
    else
    {
    GLchar log[1024];
        GLsizei logLen;
        glGetShaderInfoLog(objetoShader1, sizeof(GLchar)*1024, &logLen, log);
        std::cout << "El shader no se ha compilado con exito!" << std::endl;
        std::cout << "ShaderInfoLog: " << log << std::endl;
    }
Título: Re:Error al compilar objeto de shader
Publicado por: killgates en 09 de Diciembre de 2015, 04:38:33 PM
Hola,
He añadido lo que me has puesto en el else y ha quedado así:

    else {
        //!**********************
        GLchar log[1024];
        GLsizei logLen;
        glGetShaderInfoLog(objetoShader1, sizeof(GLchar)*1024, &logLen, log);
        std::cout << "El shader no se ha compilado con exito!" << std::endl;
        std::cout << "ShaderInfoLog: " << log << std::endl;
        //!****************************************************
    }


Me sigue devolviendo lo mismo. Seguido de "ShaderInfoLog" y en blanco.

Gracias
Título: Re:Error al compilar objeto de shader
Publicado por: [Fonet] en 09 de Diciembre de 2015, 05:50:06 PM
Buenas, no tengo ni idea de shaders y probablemente lo que voy a decir sea una tontería como una casa pero ¿no tendrías que pasar la variable log como referencia?

glGetShaderInfoLog(................................., &log)

Saludos!
Título: Re:Error al compilar objeto de shader
Publicado por: Gallo en 10 de Diciembre de 2015, 09:30:42 AM
Cita de: [Fonet] en 09 de Diciembre de 2015, 05:50:06 PM
Buenas, no tengo ni idea de shaders y probablemente lo que voy a decir sea una tontería como una casa pero ¿no tendrías que pasar la variable log como referencia?

glGetShaderInfoLog(................................., &log)

Saludos!

log ya es un puntero a char, es lo que espera la función y a mi este log me escupe los errores en el shader perfectamente, que raro que salga en blanco, el error debe estar en otro sitio. Al glGetShaderInfoLog le estas pasando el tipo correcto y tal no? que veo que no lo has puesto.
Título: Re:Error al compilar objeto de shader
Publicado por: killgates en 10 de Diciembre de 2015, 05:16:22 PM
Hola,

La función glgetshaderinfolog(); también me aparece en el libro. Aunque no entiendo su funcionamiento muy bien (soy un poco novato todavía).
Mejor pongo el código completo que tengo puesto en la etapa de compilación... :


    char fuenteShader[500];
    char fuenteFragmentShader[500];
    GLuint objetoShader1;
    GLuint objetoShader2;
    GLuint programaShader;

void glsl::compila(){
        objetoShader1 = glCreateShader(GL_VERTEX_SHADER);        //!Esto crea los objetos de shader (2) y el objeto de programa
        objetoShader2 = glCreateShader(GL_FRAGMENT_SHADER);
        programaShader = glCreateProgram();

    //!--------------- Primer objeto ---------------
        //!Aquí guardo en los objetos el codigo
    const GLchar* tmp = static_cast<const GLchar*>(fuenteShader);
    glShaderSource(objetoShader1, 1, &tmp, NULL);

        //!Y aquí compilo..
    glCompileShader(objetoShader1);
    GLint result;
    glGetShaderiv(objetoShader1, GL_COMPILE_STATUS, &result);
    if (result == 1)
        std::cout << "\nEl vertex shader se compiló con éxito";
    else {

        //!**********************
        GLchar log[1024];
        GLsizei logLen;
        glGetShaderInfoLog(objetoShader1, sizeof(GLchar)*1024, &logLen, log);
        std::cout << "El vertex shader no se ha compilado con exito!" << std::endl;
        std::cout << "ShaderInfoLog: " << log << std::endl;
        //!****************************************************
    }
    //!---------------- segundo objeto --------------
    const GLchar* tmp2 = static_cast<const GLchar*>(fuenteFragmentShader);
    glShaderSource(objetoShader2, 1, (const GLchar**)&tmp2, NULL);
        //!Y aquí compilo..
    glCompileShader(objetoShader2);
    glGetShaderiv(objetoShader2, GL_COMPILE_STATUS, &result);
    if (result == 1)
        std::cout << "\nEl fragment shader se compiló con éxito";
    else {

        //!********************** sacado de un foro de internet
        GLchar log[1024];
        GLsizei logLen;
        glGetShaderInfoLog(objetoShader1, sizeof(GLchar)*1024, &logLen, log);
        std::cout << "El fragment shader no se ha compilado con exito!" << std::endl;
        std::cout << "ShaderInfoLog: " << log << std::endl;
        //!****************************************************
    }
    //! Esto añade los shaders ya compilados al objeto de programa
    glAttachShader(programaShader, objetoShader1);
    glAttachShader(programaShader, objetoShader2);
    //! Y esto vincula el programa
    glLinkProgram(programaShader);
    //! Y esto comprueba la vinculación
    glGetProgramiv(programaShader, GL_LINK_STATUS, &result);
    if (result == GL_TRUE){
        std::cout << "\nEl programa de shaders se ha vinculado con exito!";
    }
    else std::cout << "\nEl programa de shader no se ha vinculado con exito!";
    glGetProgramiv(programaShader, GL_ATTACHED_SHADERS, &result);
    std::cout << "\nSe han aduntado " << result << " numeros de shader al programa";
    }


los arreglos "fuenteshader" y "fuentefragmentShader" contienen el código de los shaders. En una sóla cadena.
Los leo a través de getc(fichero).

Gracias

Título: Re:Error al compilar objeto de shader
Publicado por: Ray en 10 de Diciembre de 2015, 07:38:37 PM
glShaderSource lo que hace es reemplazar el código en un objeto ya creado, pero antes tienes que crearlo con glCreateShader




Título: Re:Error al compilar objeto de shader
Publicado por: killgates en 10 de Diciembre de 2015, 09:18:34 PM
Hola,

Ya creo el objeto de shader con glcreateshader() al principio de la función glsl::compila()

Me parece que eso lo hago bien
Título: Re:Error al compilar objeto de shader
Publicado por: Gallo en 11 de Diciembre de 2015, 10:18:36 AM
Si de hecho en mi comentario anterior me equivoqué me refería a glCreateShader y el copy paste me la jugó, estas llamando a glCreateShader con el tipo correcto no? También estamos seguros de que el código fuente está correctamente guardado en esa variable y tal no? Es muy raro. Lo último es que tu tarjeta gráfica soporte la versión de OpenGL donde son compatibles por primera vez estas funciones.
Título: Re:Error al compilar objeto de shader
Publicado por: Ray en 11 de Diciembre de 2015, 11:22:52 AM
¿pero qué hay en "fuenteShader"?, ¿estás cargando algo?



Título: Re:Error al compilar objeto de shader
Publicado por: killgates en 11 de Diciembre de 2015, 04:30:47 PM
Hola,

En fuenteshader está el código sin compilar de los shaders. Que se cargan en la memora de la gpu.

Y esto no lo acabo de entender (lo he sacado de un libro):

    const GLchar* tmp = static_cast<const GLchar*>(fuenteShader);
    glShaderSource(objetoShader1, 1, &tmp, NULL);

Lo que interpreto es que creo una variable puntero de tipo GLchar llamada "tmp". (const no lo utilizo nunca)
Y le asigno la dirección del arreglo fuenteshader (que es donde está el código). Lo de "static_cast<const GLchar*>( )" tampoco lo entiendo muy bien. Si me lo podeis explicarj, gracias. Lo he sacado de un libro.

Y también por qué no puedo hacer:

glShaderSource(objetoShader1, 1, &fuenteshader, NULL);


No puede estar ahí el error?
Gracias a todos
Título: Re:Error al compilar objeto de shader
Publicado por: Ray en 11 de Diciembre de 2015, 10:30:01 PM
es que no se ve que cargues ningún código en ese array, o no se sabe lo que contiene porque puede ser algún error de compilación.

te pongo un ejemplo de shader simple que está sacado del opengl superbible, se crea en una función sin nada más, esta función devuelve el programa que luego se usará

GLuint compile_shaders(void)
{
GLuint vertex_shader;
GLuint fragment_shader;
GLuint program;

/*
aquí el código se carga directamente pero también se puede cargar de un archivo de texto de manera normal
lo que hace este vertex shader es dibujar un triángulo enviando la posición de cada vértice que le llegue para ser dibujado,
como en este caso no se le va a pasar ningún  vértice lo que hará es pasar el vertice del vector que se define en el propio shader,
basta con que el shader sepa qué número de vertice es, que le viene indicado en gl_VertexID */

static const GLchar * vertex_shader_source[] =
{
"void main(void) \n"
"{ \n"
" const vec4 vertices[3] = vec4[3](vec4(0.25, -0.25, 0.5, 1.0), \n"
" vec4(-0.25, -0.25, 0.5, 1.0), \n"
" vec4(0.25, 0.25, 0.5, 1.0)); \n"
" gl_Position = vertices[gl_VertexID]; \n"
"} \n"
};

// el fragment shader simplemente coge todos los vértices que le lleguen y los pinta del color que está definido en un vector

static const GLchar * fragment_shader_source[] =
{
"out vec4 color; \n"
" \n"
"void main(void) \n"
"{ \n"
" color = vec4(0.0, 0.8, 1.0, 1.0); \n"
"} \n"
};

// esto es lo típico, se crea el shader, se le carga el código, y se compila.

// Create and compile vertex shader
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, vertex_shader_source, NULL);
glCompileShader(vertex_shader);

// Create and compile fragment shader
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, fragment_shader_source, NULL);
glCompileShader(fragment_shader);

// luego ya se crea el programa, se asigna los shader y se enlaza, listo para ser ejecutado
// Create program, attach shaders to it, and link it
program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);

// los shader se puede borrar porque ya se cargaron en el programa
// Delete the shaders as the program has them now
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);

return program;
}



para usarlo es muy simple, primero se carga el programa

   rendering_program = compile_shaders();

y para ejecutar el shader, basta con activar el programa de shader que vamos a usar
   
   glUseProgram(rendering_program);

y dibujar los triángulos, (que en este caso solo va a dibujar uno porque se le pasan 3 vértices)
   glDrawArrays(GL_TRIANGLES, 0, 3);


una vez que tienes esto podrías modificar el shader para que dibuje por ejemplo una tira de triángulos con 20 vértices mediante un bucle, y mandando la función de dibujo correspondiente.

   glDrawArrays(GL_TRIANGLE_STRIP, 0, 20);

Título: Re:Error al compilar objeto de shader
Publicado por: killgates en 12 de Diciembre de 2015, 05:21:13 PM
Hola,

Perdón. Ahora pongo la función que lee un fichero del disco (el shader) y lo guarda en un arreglo unidimensional normal, para luego pasarlo al objeto de shader.

Antes pongo la función que abre ficheros.. :      (lo estoy haciendo todo separado en funciones dentro de una clase "glsl")


    void glsl::OpenFiles(){
        if ((fichero=fopen(nombreFicheroShader, "r"))==NULL){
            std::cout << "no se ha podido abrir el fichero: " << nombreFicheroShader <<  ".. Pulse una tecla para salir\n";
            getchar();
            exit(1);
        }
        //else std::cout << "\nFichero Abierto con exito!";
        if ((fichero2=fopen(nombreFicheroFragmentShader, "r"))==NULL){
            std::cout << "no se ha podido abrir el fichero: " << nombreFicheroFragmentShader <<  ".. Pulse una tecla para salir\n";
            getchar();
            exit(1);
        }
    }


Y ahora, la función que lee los ficheros y los guarda en dos arreglos: "fuenteshader" y "fuenteshaderfragment"


    void glsl::leeFichero(){
        char caracter;
        int x = 0, y = 0;
        if ((fichero == NULL)||(fichero2 == NULL)){
            std::cout << "\nAlgun fichero no esta abierto!";
            return;
        }
        fseek(fichero, 0, SEEK_SET);  //!Hasta aquí abro el fichero y me coloco al principio
        //!Y leo todo el fichero y lo guardo en el arreglo fuenteShader de una dimensión
        do {
            caracter = getc(fichero);
            if (caracter == EOF){
                std::cout << "No hay nada en el fichero de shaders!, es decir, está en blanco!";
                return;
            }
        } while ((caracter == ' ')||(caracter == 13));
        for (int contador = 0; caracter != EOF; contador++){
            caracter = getc(fichero);
            fuenteShader[contador] = caracter;
        }
        //!******** Y hag lo mismo con el fichero de fragment shader ..:

                fseek(fichero2, 0, SEEK_SET);  //!Hasta aquí abro el fichero y me coloco al principio
        //!Y leo todo el fichero y lo guardo en el arreglo nombreFicheroFragmentShader[] de una dimensión
        do {
            caracter = getc(fichero2);
            if (caracter == EOF){
                std::cout << "No hay nada en el fichero de fragment shaders!, es decir, está en blanco!";
                return;
            }
        } while ((caracter == ' ')||(caracter == 13));
        for (int contador = 0; caracter != EOF; contador++){
            caracter = getc(fichero2);
            fuenteFragmentShader[contador] = caracter;
        }
        //!**** aquí acabo de leer los dos ficheros.. **
    }


Veo que tú generás el código de los shaders desde el programa. Yo los tomo de ficheros.
Si hago un "puts(fuenteshader);" me aparece el código del fichero shader leído.
Que es éste:


#version 130

uniform mat4 projection_matrix;
uniform mat4 modelview_matrix;

in vec3 a_Vertex;
in vec3 a_Color;
out vec4 color;

void main(void)
{
vec4 pos = modelview_matrix * vec4(a_Vertex, 1.0);
gl_Position = projection_matrix * pos;
color = vec4(a_Color, 1.0);
}



Y luego vendría el otro..:


#version 130

in vec4 color;
out vec4 outColor;

void main(void) {
outColor = color;
}



Esto está sacado de un libro que he comprado.
Gracias
Título: Re:Error al compilar objeto de shader
Publicado por: Ray en 14 de Diciembre de 2015, 12:10:46 PM
puede ser porque esas cadenas de texto tienen que tener al final el null '0\' para que sepa donde termina.
Título: Re:Error al compilar objeto de shader
Publicado por: killgates en 15 de Diciembre de 2015, 06:26:22 PM
Hola,

Tengo una función dentro de la clase que pone a NULL todo el arreglo fuenteshader[] y fuenteshaderfragment[], que es lo que contiene el código del vertex y fragment shader. La llamo antes de rellenar los arreglos.

La verdad, no se que estoy haciendo mal. He repasado las funciones que leen los ficheros que contienen los shader y había el error que se comía el "#" del principio, y ya lo he arreglado. Pero sigue sin funcionar..

Gracias
Título: Re:Error al compilar objeto de shader
Publicado por: Ray en 15 de Diciembre de 2015, 07:41:16 PM
intenta acotar el problema, prueba a cargar los shader que te he puesto antes de ejemplo, para ver si compilan bien.

si compilan bien entonces entonces es problema del código que estás cargando, analiza con el depurador el string justo antes de pasarle el source, a ver qué es lo que le está llegando.
Título: Re:Error al compilar objeto de shader
Publicado por: killgates en 18 de Diciembre de 2015, 04:22:40 PM
Hola amigos!

Buf.. Perdonad por ser tan novato todavía. La solución era crear crear la ventana e iniciar opengl.  8o

Lo estaba intentando directamente. Y tenía la parte del código que crea la ventana y el contexto de Opengl desactivado.  :..

Lo que no entiendo es por qué los shaders necesitan todo esto sólo para compilar..  Oo

Título: Re:Error al compilar objeto de shader
Publicado por: anais en 28 de Febrero de 2023, 05:48:55 PM
Cita de: killgates en 12 de Diciembre de 2015, 05:21:13 PMHola,

Perdón. Ahora pongo la función que lee un fichero del disco (el shader) y lo guarda en un arreglo unidimensional normal, para luego pasarlo al objeto

Antes pongo la función que abre ficheros.. :      (lo estoy haciendo todo separado en funciones dentro de una clase "glsl")

    void glsl::OpenFiles(){
        if ((fichero=fopen(nombreFicheroShader, "r"))==NULL){
            std::cout << "no se ha podido abrir el fichero: " << nombreFicheroShader <<  ".. Pulse una tecla para salir\n";
            getchar();
            exit(1);
        }
        //else std::cout << "\nFichero Abierto con exito!";
        if ((fichero2=fopen(nombreFicheroFragmentShader, "r"))==NULL){
            std::cout << "no se ha podido abrir el fichero: " << nombreFicheroFragmentShader <<  ".. Pulse una tecla para salir\n";
            getchar();
            exit(1);
        }
    }

Y ahora, la función que lee los ficheros y los guarda en dos arreglos: "fuenteshader" y "fuenteshaderfragment" con la ruleta aleatoria (https://www.ruletasaleatorias.com/) .

    void glsl::leeFichero(){
        char caracter;
        int x = 0, y = 0;
        if ((fichero == NULL)||(fichero2 == NULL)){
            std::cout << "\nAlgun fichero no esta abierto!";
            return;
        }
        fseek(fichero, 0, SEEK_SET);  //!Hasta aquí abro el fichero y me coloco al principio
        //!Y leo todo el fichero y lo guardo en el arreglo a de una dimensión
        do {
            caracter = getc(fichero);
            if (caracter == EOF){
                std::cout << "No hay nada en el fichero de shaders!, es decir, está en blanco!";
                return;
            }
        } while ((caracter == ' ')||(caracter == 13));
        for (int contador = 0; caracter != EOF; contador++){
            caracter = getc(fichero);
            fuenteShader[contador] = caracter;
        }
        //!******** Y hag lo mismo con el fichero de fragment shader ..:

                fseek(fichero2, 0, SEEK_SET);  //!Hasta aquí abro el fichero y me coloco al principio
        //!Y leo todo el fichero y lo guardo en el arreglo nombreFicheroFragmentShader[] de una dimensión
        do {
            caracter = getc(fichero2);
            if (caracter == EOF){
                std::cout << "No hay nada en el fichero de fragment shaders!, es decir, está en blanco!";
                return;
            }
        } while ((caracter == ' ')||(caracter == 13));
        for (int contador = 0; caracter != EOF; contador++){
            caracter = getc(fichero2);
            fuenteFragmentShader[contador] = caracter;
        }
        //!**** aquí acabo de leer los dos ficheros.. **
    }

Veo que tú generás el código de los shaders desde el programa. Yo los tomo de ficheros.
Si hago un "puts(fuenteshader);" me aparece el código del fichero shader leído.
Que es éste:

#version 130

uniform mat4 projection_matrix;
uniform mat4 modelview_matrix;

in vec3 a_Vertex;
in vec3 a_Color;
out vec4 color;

void main(void)
{
    vec4 pos = modelview_matrix * vec4(a_Vertex, 1.0);
    gl_Position = projection_matrix * pos;   
    color = vec4(a_Color, 1.0);
}



Y luego vendría el otro..:

#version 130

in vec4 color;
out vec4 outColor;

void main(void) {
    outColor = color;   
}


Esto está sacado de un libro que he comprado.
Gracias


Buenas compi

Me paso lo mismo hace mucho, en todo momento tienes  que inicializar la ventana al crearlar con opengl.