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.
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;
}
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
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!
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.
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
glShaderSource lo que hace es reemplazar el código en un objeto ya creado, pero antes tienes que crearlo con glCreateShader
Hola,
Ya creo el objeto de shader con glcreateshader() al principio de la función glsl::compila()
Me parece que eso lo hago bien
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.
¿pero qué hay en "fuenteShader"?, ¿estás cargando algo?
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
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);
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
puede ser porque esas cadenas de texto tienen que tener al final el null '0\' para que sepa donde termina.
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
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.
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
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.