I have written a C++ program where I draw a teapot and apply lighting. It is itself simple, but I also use shaders. Simple I'm new with GLSL I just tried a simple fragment shader, but the screen output is inexplicable.
In this file I initialize glew in the init method, where I also compile the vertex and fragment shader. They're in the "vertex_shader" and "fragment_shader" files.
The thing you may not recognize is what's Light and Material. They're just some structs containing all info about the lights. I've tested these struct so I'm sure the work as expected. When I declare material=BlackPlastic I just set it to a default value defined with the define directive. I may also post this code if you think that the problem is there.
#include <GL/glew.h>
#include <GL/glut.h>
#include <iostream>
#include <fstream>
#include <vector>
#include "utility.hpp"
#define MAX_DIM 1000
GLfloat width=600, height=800;
GLuint vertex_shader, fragment_shader;
GLuint program;
const char* vertex_shader_filename= "vertex_shader";
const char* fragment_shader_filename= "fragment_shader";
Light light;
Material material;
void init()
{
// Inizializzazione di GLEW
glewInit();
if(GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader)
{
cout << "Supporto GLSL" << endl;
}
// Lettura e compilazione del vertex shader
GLchar* buffer= new GLchar[MAX_DIM];
ifstream stream;
streamsize count;
stream.open(vertex_shader_filename);
stream.read(buffer,MAX_DIM);
count= stream.gcount();
stream.close();
vertex_shader= glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, (const GLchar**)&buffer, &count);
glCompileShader(vertex_shader);
// Lettura, inizializzazione ed esecuzione del fragment shader
stream.open(fragment_shader_filename);
stream.read(buffer,MAX_DIM);
count= stream.gcount();
stream.close();
fragment_shader= glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, (const GLchar**)&buffer, &count);
glCompileShader(fragment_shader);
delete[] buffer;
// Creazione del programma
program= glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
glUseProgram(program);
// Inizializzazione materiale e luce
material= BlackPlastic;
light= {vector<GLfloat>{-2,2,2,1} ,vector<GLfloat>{1,1,1,1},vector<GLfloat>{1,1,1,1},vector<GLfloat>{1,1,1,1} };
}
void display()
{
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45,width/height,1,1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,0,-100,0,0,0,0,1,0);
// Illuminazione
glShadeModel(GL_SMOOTH);
material.apply(); // This just causes glMaterialfv to be called for the ambient, diffuse, specular and shininess values.
light.apply(); // This just causes glLightfv to be called for the ambient, diffuse and specular values
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
// Rendering
glClearColor(0.8,0.8,0.8,1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glutSolidTeapot(10);
glutSwapBuffers();
}
void reshape(int w, int h)
{
width=w;
height=h;
glutPostRedisplay();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowPosition(100,100);
glutInitWindowSize(500,500);
glutCreateWindow("test");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
init();
glutMainLoop();
return 0;
}
I don't think that the vertex shader is causing any problem, it just assigns the color and calculate the position, correctly. Also the fragment shader is apparently correct, this is the only instruction executed:
gl_FragColor = gl_Color;
If I do this I just see a white teapot. If instead I change this value to a whatever color:
gl_FragColor = vec4{0,0,1,1};
I get the teapot with the right color: black plastic. And I don't know why, I don't apply lighting here, I should calculate it.
I precisate that I executed the same identical program but without applying the shaders, and I got the teapot to have the right color.