Fragment shader unexplained bahaviour

I wrote a C ++ program where I draw a kettle and apply lighting. This is simple in itself, but I also use shaders. I'm just new to GLSL. I just tried a simple fragment shader but the output to the screen is inexplicable.

In this file, I initialize glew in the init method, where I also compile the vertex and fragment shader. They are located in the files "vertex_shader" and "fragment_shader".

What you cannot recognize is what is light and material. These are just some of the structures that contain all the information about fires. I've tested this framework, so I'm pretty sure it works as expected. When I declare material = BlackPlastic, I just set it to the default as defined in the define directive. I can also post this code if you think 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 the vertex shader is causing any problem, it just assigns the color and calculates the position correctly. Also, the fragment shader appears to be correct, this is the only command:

gl_FragColor = gl_Color;

      

If I do this, I just see a white kettle. If instead I change this value to any color:

gl_FragColor = vec4{0,0,1,1};

      

I get the teapot with the correct color: black plastic. And I don't know why, I am not applying lighting here, I have to calculate it.

I'm pretty sure I followed the same program, but without applying shaders, and I ended up with a teapot that has the correct color.

0


source to share


1 answer


First of all, you are mixing a fixed function pipeline with "new material". This is real bad practice because it can cause a lot of problems because you don't really know what's going on in the background.

If you want to have real lighting with diffuse shaders, you need to calculate the diffuse color yourself. I used ffp a long time ago for the last time, so I searched for some shaders that use it:

Vertex shader



varying vec3 normal;
varying vec3 v;
varying vec3 lightvec;
void main(void)
{
    normal      = normalize(gl_NormalMatrix * gl_Normal);
    v           = vec3(gl_ModelViewMatrix * gl_Vertex);
    lightvec    = normalize(gl_LightSource[0].position.xyz - v);
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

      

Fragment Shader

varying vec3 normal;
varying vec3 v;
varying vec3 lightvec;

void main(void)
{
   vec3 Eye          = normalize(-v);
   vec3 Reflected    = normalize( reflect( -lightvec, normal )); 
   vec4 IAmbient     = gl_LightSource[0].ambient * gl_FrontMaterial.ambient;
   vec4 IDiffuse     = gl_LightSource[0].diffuse * gl_FrontMaterial.diffuse * max(dot(normal, lightvec), 0.0);
   vec4 ISpecular    = gl_LightSource[0].specular * gl_FrontMaterial.specular * pow(max(dot(Reflected, Eye), 0.0), gl_FrontMaterial.shininess);
   gl_FragColor      = gl_FrontLightModelProduct.sceneColor + IAmbient + IDiffuse + ISpecular;
}

      

+2


source







All Articles