OpenGL - vertex normals in OBJ
Asked Answered
U

1

7

I want to know how can I use the vertex normals for lightning effect? Currently what I have is I can send both vertex and texture coords to the shader and use them but with normals, I don't know how to use them in the shader program. Below is what I have so far.

    // vertex shader
    layout(location = 0) in vec4 vert;
    layout(location = 1) in vec4 color;
    layout(location = 2) in vec2 texcoord;
    uniform mat4 m_model;
    uniform mat4 m_view;
    uniform mat4 m_proj;
    void main() {
        gl_Position = m_proj * m_view * m_model * vert;
    }

    // fragment shader
    in vec2 fragtexcoord;
    out vec4 color;
    uniform sampler2D textureunit;
    void main(void) {
        color = texture(textureunit, fragtexcoord);
    }

EDIT Here are my shaders for now.

vertex shader

    layout(location = 0) in vec4 vert;
    layout(location = 1) in vec4 color;
    layout(location = 2) in vec2 texcoord;
    layout(location = 3) in vec4 normal;
    out vec4 LightIntensity;
    uniform vec4 LightPosition;
    uniform vec4 Kd; 
    uniform vec4 Ld;
    uniform mat4 m_model;
    uniform mat4 m_view;
    uniform mat4 m_proj;
    void main() {
        gl_Position = m_proj * m_view * m_model * vert;

        mat4 normalmatrix = transpose(inverse(m_view));

        vec4 tnorm = normalize(normalmatrix * normal);
        vec4 eyeCoords = m_model * vec4(vert);
        vec4 s = normalize(vec4(LightPosition - eyeCoords));

        LightIntensity = Ld * Kd * max(dot(s, tnorm), 0.0);
    }

Fragment shader.

    in vec4 LightIntensity;
    out vec4 color;
    void main(void) {
        color = vec4(LightIntensity);
    }

Currently getting a black cube with no shading. Probably I did something wrong here in the shader which I don't have any idea which one :(

UPDATE :

vertex

    layout(location = 0) in vec4 vert;
    layout(location = 1) in vec4 color;
    layout(location = 2) in vec2 texcoord;
    layout(location = 3) in vec4 normal;
    out vec2 fragtexcoord;
    out vec4 fragnormal;
    uniform mat4 m_model;
    uniform mat4 m_view;
    uniform mat4 m_proj;
    void main() {
        gl_Position = m_proj * m_view * m_model * vert;
        fragtexcoord = texcoord;
        fragnormal = normal;
    }

fragment

    in vec2 fragtexcoord;
    in vec4 fragnormal;
    out vec4 fragment_color;
    uniform sampler2D textureunit;
    void main(void) {
        vec4 lt_ambient = vec4(0.2, 0.2, 0.2, 1.0);
        vec4 lt_direct = vec4(0.8, 0.8, 0.8, 1.0);
        vec4 lt_direct_dir = vec4(1.5, 1.0, 1.0, 1.0);
        vec4 color = texture(textureunit, fragtexcoord);
        fragment_color = (lt_ambient + (lt_direct * dot(lt_direct_dir, -fragnormal))) * color;
    }

I don't know what to put for lt_direct_dir that's why it has values like that :)

UPDATE : Below is the working shaders for me

    // vertex shader
    layout(location = 0) in vec4 vert;
    layout(location = 1) in vec4 color;
    layout(location = 2) in vec2 texcoord;
    layout(location = 3) in vec4 normal;

    out vec4 fragposition;
    out vec4 fragcolor;
    out vec4 fragnormal;
    out vec2 fragtexcoord;

    uniform mat4 m_model;
    uniform mat4 m_view;
    uniform mat4 m_proj;
    uniform vec4 lightpos;
    void main() {
        gl_Position = m_proj * m_view * m_model * vert;
        mat4 m_normal = transpose(inverse(m_model));
        fragposition = m_model * vert;
        fragnormal = m_normal * normal;
        fragtexcoord = texcoord;
    }

    // fragment shader
    in vec4 fragposition;
    in vec4 fragnormal;
    in vec2 fragtexcoord;

    out vec4 fragment_color;

    uniform sampler2D textureunit;

    void main() {
        vec4 lt_pnt_pos = vec4(2.5, 2.5, 2.5, 1.0);
        vec4 lt_pnt_col = vec4(0.8, 0.8, 0.8, 1.0);
        vec4 lt_amb_col = vec4(0.2, 0.2, 0.2, 1.0);

        vec4 lt_dir = normalize(lt_pnt_pos - fragposition);
        float li = dot(fragnormal, lt_dir);
        if(li < 0.0) {
            li = 0.0;
        }
        vec4 color = texture(textureunit, fragtexcoord);
        fragment_color = color * (lt_amb_col + (lt_pnt_col * li));
    }
Urial answered 6/8, 2015 at 8:22 Comment(6)
You need to re-write the question, telling us what you want to do with the normals. I suspect some kind of lighting but your question doesn't mention it. You already know how to get normals into your shader (the same way you get position, color and texcoord).Brockwell
@Robinson: I have edited the question. Sorry for not asking it the right way. I just want to know how can I use the normals in shader to create a lightning effect, you said that I know how to get normals into my shader the same way as the texcoord but I don't know how can I do it with the normals. I'm just a beginner in opengl.Urial
Well that's a different question. There are different lighting models: Blinn, Phong, etc. I would start with Gourad as it's easiest. Basically those are the search terms you need to use on google. The one tip I would give you is to make sure you transform the normals by the inverse transpose of the view matrix, otherwise they won't be oriented correctly.Brockwell
@Robinson: Thank you for the information. I will read regarding the lightning models. As of now, I will research and hopefully can get an idea on how to use the normals in the most basic way. HahaUrial
@Urial look at: normals and Normal mapping for some basicsWitch
@Witch is the normal map image really necessary? What about if I don't have one? Currently what I have is the .obj, .mtl and the texture image, I know how to bind the normals to the VBO's but I don't still have a correct shader for this. Struggling to write one.Urial
W
11

normal/bump maps

Provide fine details without increasing complexity of geometry that means more details at very low performance cost. Normal/bump maps are optional of coarse.

normal shading (fragment shader)

Normal is vector perpendicular to fragment/face/primitive there are 2 use for it:

  1. dull surface illumination

lets have:

  • color - per fragment/face/primitive color (modulated with texture)
  • normal - per fragment/face/primitive 3D normal vector (pointing out of mesh)
  • lt_ambient,lt_direct - the lights color and strength
  • lt_direct_dir - directional light direction

then the output is easy:

  • fragment_color=(lt_ambient+(lt_direct*dot(lt_direct_dir,-normal))*color;

this is called normal shading

dot returns the cos(angle between light and normal) if you want to have booth sides geometries then use fabs(dot(...)). The light color and strength vectors summed together should not exceed 1.0 per channel otherwise clamping could cause color artifacts. Use for example:

  • lt_ambient=(0.2,0.2,0.2)
  • lt_direct =(0.8,0.8,0.8)

as lt_direct_dir you can use (fragment_xyz-Sun.xyz) and normalize to unit vector or use camera view direction. You need to have unit vector for dot product otherwise it will not work properly

  1. reflection

if you have any environment map (cube_map) then you can add reflections. You got the fragment (x,y,z) coordinates and normal so you can compute direction of reflected viewing direction and add the texel to which is it pointing to the result fragment_color.

There are more stuff like specular highlights and different light equations but I think you should start with normal shading first. When you got the basics then is no problem to understand the more advanced stuff just always remember what is behind ...

[edit1] well as you are rookie then you obviously need complete example to start with:

So here complete GL+VAO/VBO+GLSL+shaders example in C++. As I use Borland environment it is in VCL form app so just ignore the VCL stuff and extract only what you need. This is how it looks like:

normal shading

That cross is my point light position to visually check the correctness and that arrow (hand drawed) shows average light direction.

normal_shading.glsl_vert

// Vertex
#version 400 core
layout(location = 0) in vec3 pos;
layout(location = 2) in vec3 nor;
layout(location = 3) in vec3 col;
uniform mat4 m_model;   // model matrix
uniform mat4 m_normal;  // model matrix with origin=(0,0,0)
uniform mat4 m_view;    // inverse of camera matrix
uniform mat4 m_proj;    // projection matrix
out vec3 pixel_pos;     // fragment position [GCS]
out vec3 pixel_col;     // fragment surface color
out vec3 pixel_nor;     // fragment surface normal [GCS]
void main()
    {
    pixel_col=col;
    pixel_pos=(m_model*vec4(pos,1)).xyz;
    pixel_nor=(m_normal*vec4(nor,1)).xyz;
    gl_Position=m_proj*m_view*m_model*vec4(pos,1);
    }

normal_shading.glsl_frag

// Fragment
#version 400 core
uniform vec3 lt_pnt_pos;// point light source position [GCS]
uniform vec3 lt_pnt_col;// point light source color&strength
uniform vec3 lt_amb_col;// ambient light source color&strength
in vec3 pixel_pos;      // fragment position [GCS]
in vec3 pixel_col;      // fragment surface color
in vec3 pixel_nor;      // fragment surface normal [GCS]
out vec4 col;
void main()
    {
    float li;
    vec3 c,lt_dir;
    lt_dir=normalize(lt_pnt_pos-pixel_pos); // vector from fragment to point light source in [GCS]
    li=dot(pixel_nor,lt_dir);
    if (li<0.0) li=0.0;
    c=pixel_col*(lt_amb_col+(lt_pnt_col*li));
    col=vec4(c,1.0);
    }

gl_simple.h

//---------------------------------------------------------------------------
//--- GL simple ver: 1.000 --------------------------------------------------
//---------------------------------------------------------------------------
#define GLEW_STATIC
#include "glew.c"
#include <gl\gl.h>
#include <gl\glu.h>
//---------------------------------------------------------------------------
//--- OpenGL GL example -----------------------------------------------------
//---------------------------------------------------------------------------
int     xs,ys;      // screen size
HDC     hdc=NULL;   // device context
HGLRC   hrc=NULL;   // rendering context
int  gl_inicialized=0;
int  gl_init(HWND Handle);
void gl_exit();
void gl_draw();
void gl_resize(int _xs,int _ys);
//---------------------------------------------------------------------------
//--- OpenGL GLSL example ---------------------------------------------------
//---------------------------------------------------------------------------
GLint prog_id=0,    // whole program
      vert_id=0,    // vertex shader
      frag_id=0;    // fragment shader
char  glsl_log[4096];// compile/link GLSL log
int   glsl_logs=0;
void  glsl_init(char *vert,char *frag);     // create/compile/link GLSL program
void  glsl_exit();
//---------------------------------------------------------------------------
//--- OpenGL VAO example ----------------------------------------------------
//---------------------------------------------------------------------------
#pragma pack(1)
//#define vao_indices
GLuint vbo[4]={-1,-1,-1,-1};
GLuint vao[4]={-1,-1,-1,-1};
const GLfloat vao_pos[]=
    {
//  x    y    z     //ix
    -1.0,+1.0,-1.0, //0
    +1.0,+1.0,-1.0, //1
    +1.0,-1.0,-1.0, //2
    -1.0,-1.0,-1.0, //3

    -1.0,-1.0,+1.0, //4
    +1.0,-1.0,+1.0, //5
    +1.0,+1.0,+1.0, //6
    -1.0,+1.0,+1.0, //7

    #ifndef vao_indices
    -1.0,-1.0,-1.0, //3
    +1.0,-1.0,-1.0, //2
    +1.0,-1.0,+1.0, //5
    -1.0,-1.0,+1.0, //4

    +1.0,-1.0,-1.0, //2
    +1.0,+1.0,-1.0, //1
    +1.0,+1.0,+1.0, //6
    +1.0,-1.0,+1.0, //5

    +1.0,+1.0,-1.0, //1
    -1.0,+1.0,-1.0, //0
    -1.0,+1.0,+1.0, //7
    +1.0,+1.0,+1.0, //6

    -1.0,+1.0,-1.0, //0
    -1.0,-1.0,-1.0, //3
    -1.0,-1.0,+1.0, //4
    -1.0,+1.0,+1.0, //7
    #endif
    };

const GLfloat vao_col[]=
    {
//  r   g   b    //ix
    0.0,0.0,0.0, //0
    1.0,0.0,0.0, //1
    1.0,1.0,0.0, //2
    0.0,1.0,0.0, //3
    0.0,0.0,1.0, //4
    1.0,0.0,1.0, //5
    1.0,1.0,1.0, //6
    0.0,1.0,1.0, //7

    #ifndef vao_indices
    0.0,0.0,0.0, //0
    1.0,0.0,0.0, //1
    1.0,0.0,1.0, //5
    0.0,0.0,1.0, //4

    1.0,0.0,0.0, //1
    1.0,1.0,0.0, //2
    1.0,1.0,1.0, //6
    1.0,0.0,1.0, //5

    1.0,1.0,0.0, //2
    0.0,1.0,0.0, //3
    0.0,1.0,1.0, //7
    1.0,1.0,1.0, //6

    0.0,1.0,0.0, //3
    0.0,0.0,0.0, //0
    0.0,0.0,1.0, //4
    0.0,1.0,1.0, //7
    #endif
    };

#ifndef vao_indices
const GLfloat vao_nor[]=
    {
//   nx   ny   nz   //ix
     0.0, 0.0,-1.0, //0
     0.0, 0.0,-1.0, //1
     0.0, 0.0,-1.0, //2
     0.0, 0.0,-1.0, //3

     0.0, 0.0,+1.0, //4
     0.0, 0.0,+1.0, //5
     0.0, 0.0,+1.0, //6
     0.0, 0.0,+1.0, //7

     0.0,-1.0, 0.0, //0
     0.0,-1.0, 0.0, //1
     0.0,-1.0, 0.0, //5
     0.0,-1.0, 0.0, //4

    +1.0, 0.0, 0.0, //1
    +1.0, 0.0, 0.0, //2
    +1.0, 0.0, 0.0, //6
    +1.0, 0.0, 0.0, //5

     0.0,+1.0, 0.0, //2
     0.0,+1.0, 0.0, //3
     0.0,+1.0, 0.0, //7
     0.0,+1.0, 0.0, //6

    -1.0, 0.0, 0.0, //3
    -1.0, 0.0, 0.0, //0
    -1.0, 0.0, 0.0, //4
    -1.0, 0.0, 0.0, //7
    };
#endif

#ifdef vao_indices
const GLuint vao_ix[]=
    {
    0,1,2,3,
    4,5,6,7,
    3,2,5,4,
    2,1,6,5,
    1,0,7,6,
    0,3,4,7,
    };
#endif

#pragma pack()
void vao_init();
void vao_exit();
void vao_draw();
//---------------------------------------------------------------------------
//--- bodies: ---------------------------------------------------------------
//---------------------------------------------------------------------------
int gl_init(HWND Handle)
    {
    if (gl_inicialized) return 1;
    hdc = GetDC(Handle);            // get device context
    PIXELFORMATDESCRIPTOR pfd;
    ZeroMemory( &pfd, sizeof( pfd ) );      // set the pixel format for the DC
    pfd.nSize = sizeof( pfd );
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 24;
    pfd.cDepthBits = 24;
    pfd.iLayerType = PFD_MAIN_PLANE;
    SetPixelFormat(hdc,ChoosePixelFormat(hdc, &pfd),&pfd);
    hrc = wglCreateContext(hdc);            // create current rendering context
    if(hrc == NULL)
            {
            ShowMessage("Could not initialize OpenGL Rendering context !!!");
            gl_inicialized=0;
            return 0;
            }
    if(wglMakeCurrent(hdc, hrc) == false)
            {
            ShowMessage("Could not make current OpenGL Rendering context !!!");
            wglDeleteContext(hrc);          // destroy rendering context
            gl_inicialized=0;
            return 0;
            }
    gl_resize(1,1);
    glEnable(GL_DEPTH_TEST);                // Zbuf
    glDisable(GL_CULL_FACE);                // vynechavaj odvratene steny
    glDisable(GL_TEXTURE_2D);               // pouzivaj textury, farbu pouzivaj z textury
    glDisable(GL_BLEND);                    // priehladnost
    glShadeModel(GL_SMOOTH);                // gourard shading
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);   // background color
    gl_inicialized=1;
    glewInit();
    return 1;
    }
//---------------------------------------------------------------------------
void gl_exit()
    {
    if (!gl_inicialized) return;
    wglMakeCurrent(NULL, NULL);     // release current rendering context
    wglDeleteContext(hrc);          // destroy rendering context
    gl_inicialized=0;
    }
//---------------------------------------------------------------------------
void gl_resize(int _xs,int _ys)
    {
    xs=_xs;
    ys=_ys;
    if (xs<=0) xs = 1;                  // Prevent a divide by zero
    if (ys<=0) ys = 1;
    if (!gl_inicialized) return;
    glViewport(0,0,xs,ys);              // Set Viewport to window dimensions
    glMatrixMode(GL_PROJECTION);        // operacie s projekcnou maticou
    glLoadIdentity();                   // jednotkova matica projekcie
    gluPerspective(30,float(xs)/float(ys),0.1,100.0); // matica=perspektiva,120 stupnov premieta z viewsize do 0.1
    glMatrixMode(GL_TEXTURE);           // operacie s texturovou maticou
    glLoadIdentity();                   // jednotkova matica textury
    glMatrixMode(GL_MODELVIEW);         // operacie s modelovou maticou
    glLoadIdentity();                   // jednotkova matica modelu (objektu)
    }
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void glsl_init(char *vert,char *frag)
    {
    const int _size=1024;
    GLint status,siz=0,i;
    const char * VS = vert;
    const char * FS = frag;
    glsl_logs=0;
    if (prog_id<=0) prog_id=glCreateProgram();

    if (vert_id<=0) vert_id=glCreateShader(GL_VERTEX_SHADER); else glDetachShader(prog_id,vert_id);
    if (vert)
        {
        glShaderSource(vert_id, 1, &VS,NULL);
        glCompileShader(vert_id);
        glAttachShader(prog_id,vert_id);
        glGetShaderiv(vert_id,GL_COMPILE_STATUS,&status);
        const char t[]="[Vertex]\r\n"; for (i=0;t[i];i++) { glsl_log[glsl_logs]=t[i]; glsl_logs++; }
        glGetShaderInfoLog(vert_id,_size,&siz,glsl_log+glsl_logs);
        glsl_logs+=siz;
        }
    if (frag_id<=0) frag_id=glCreateShader(GL_FRAGMENT_SHADER); else glDetachShader(prog_id,frag_id);
    if (frag)
        {
        glShaderSource(frag_id, 1, &FS,NULL);
        glCompileShader(frag_id);
        glAttachShader(prog_id,frag_id);
        glGetShaderiv(frag_id,GL_COMPILE_STATUS,&status);
        const char t[]="[Fragment]\r\n"; for (i=0;t[i];i++) { glsl_log[glsl_logs]=t[i]; glsl_logs++; }
        glGetShaderInfoLog(frag_id,_size,&siz,glsl_log+glsl_logs);
        glsl_logs+=siz;
        }
    glLinkProgram(prog_id);
    glGetProgramiv(prog_id,GL_LINK_STATUS,&status);
    const char t[]="[Program]\r\n"; for (i=0;t[i];i++) { glsl_log[glsl_logs]=t[i]; glsl_logs++; }
    glGetProgramInfoLog(prog_id,_size,&siz,glsl_log+glsl_logs);
    glsl_logs+=siz;

    glReleaseShaderCompiler();
    glsl_log[glsl_logs]=0;
    }
//------------------------------------------------------------------------------
void glsl_exit()
    {
    glUseProgram(0);
    if (vert_id>0) { glDetachShader(prog_id,vert_id); glDeleteShader(vert_id); }
    if (frag_id>0) { glDetachShader(prog_id,frag_id); glDeleteShader(frag_id); }
    if (prog_id>0) {                                  glDeleteShader(prog_id); }
    glsl_log[0]=0;
    }
//---------------------------------------------------------------------------
//------------------------------------------------------------------------------
void vao_init()
    {
    GLuint i;
    glGenVertexArrays(4,vao);
    glGenBuffers(4,vbo);
    glBindVertexArray(vao[0]);
    i=0; // vertex
    glBindBuffer(GL_ARRAY_BUFFER,vbo[i]);
    glBufferData(GL_ARRAY_BUFFER,sizeof(vao_pos),vao_pos,GL_STATIC_DRAW);
    glEnableVertexAttribArray(i);
    glVertexAttribPointer(i,3,GL_FLOAT,GL_FALSE,0,0);
    i=1; // indices
    #ifdef vao_indices
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,vbo[i]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(vao_ix),vao_ix,GL_STATIC_DRAW);
    glEnableVertexAttribArray(i);
    glVertexAttribIPointer(i,4,GL_UNSIGNED_INT,0,0);
    #endif
    i=2; // normal
    #ifndef vao_indices
    glBindBuffer(GL_ARRAY_BUFFER,vbo[i]);
    glBufferData(GL_ARRAY_BUFFER,sizeof(vao_nor),vao_nor,GL_STATIC_DRAW);
    glEnableVertexAttribArray(i);
    glVertexAttribPointer(i,3,GL_FLOAT,GL_FALSE,0,0);
    #endif
    i=3; // color
    glBindBuffer(GL_ARRAY_BUFFER,vbo[i]);
    glBufferData(GL_ARRAY_BUFFER,sizeof(vao_col),vao_col,GL_STATIC_DRAW);
    glEnableVertexAttribArray(i);
    glVertexAttribPointer(i,3,GL_FLOAT,GL_FALSE,0,0);

    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER,0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(2);
    glDisableVertexAttribArray(3);
    }
//---------------------------------------------------------------------------
void vao_exit()
    {
    glDeleteVertexArrays(4,vao);
    glDeleteBuffers(4,vbo);
    }
//---------------------------------------------------------------------------
void vao_draw()
    {
    glBindVertexArray(vao[0]);
    #ifndef vao_indices
    glDrawArrays(GL_QUADS,0,sizeof(vao_pos)/sizeof(vao_pos[0]));                    // QUADS ... no indices
    #endif
    #ifdef vao_indices
    glDrawElements(GL_QUADS,sizeof(vao_ix)/sizeof(vao_ix[0]),GL_UNSIGNED_INT,0);    // indices (choose just one line not both !!!)
    #endif
    glBindVertexArray(0);
    }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------

VCL App main form source:

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include "gl_simple.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
GLfloat lt_pnt_pos[3]={+2.5,+2.5,+2.5};
GLfloat lt_pnt_col[3]={0.8,0.8,0.8};
GLfloat lt_amb_col[3]={0.2,0.2,0.2};
//---------------------------------------------------------------------------
void gl_draw()
    {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // load values into shader
    GLint i,id;
    GLfloat m[16];
    glUseProgram(prog_id);
    id=glGetUniformLocation(prog_id,"lt_pnt_pos"); glUniform3fv(id,1,lt_pnt_pos);
    id=glGetUniformLocation(prog_id,"lt_pnt_col"); glUniform3fv(id,1,lt_pnt_col);
    id=glGetUniformLocation(prog_id,"lt_amb_col"); glUniform3fv(id,1,lt_amb_col);
    glGetFloatv(GL_MODELVIEW_MATRIX,m);
    id=glGetUniformLocation(prog_id,"m_model"   ); glUniformMatrix4fv(id,1,GL_FALSE,m);
    m[12]=0.0; m[13]=0.0; m[14]=0.0;
    id=glGetUniformLocation(prog_id,"m_normal"  ); glUniformMatrix4fv(id,1,GL_FALSE,m);
    for (i=0;i<16;i++) m[i]=0.0; m[0]=1.0; m[5]=1.0; m[10]=1.0; m[15]=1.0;
    id=glGetUniformLocation(prog_id,"m_view"    ); glUniformMatrix4fv(id,1,GL_FALSE,m);
    glGetFloatv(GL_PROJECTION_MATRIX,m);
    id=glGetUniformLocation(prog_id,"m_proj"    ); glUniformMatrix4fv(id,1,GL_FALSE,m);
    // draw VAO cube
    vao_draw();
    // turn of shader
    glUseProgram(0);
    // rotate the cube to see animation
    glMatrixMode(GL_MODELVIEW);
    glRotatef(1.0,0.0,1.0,0.0);
    glRotatef(1.0,1.0,0.0,0.0);

    // render point light source in [GCS]
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
    GLfloat x,y,z,d=0.25;
    x=lt_pnt_pos[0];
    y=lt_pnt_pos[1];
    z=lt_pnt_pos[2];
    glBegin(GL_LINES);
    glColor3fv(lt_pnt_col);
    glVertex3f(x-d,y,z);
    glVertex3f(x+d,y,z);
    glVertex3f(x,y-d,z);
    glVertex3f(x,y+d,z);
    glVertex3f(x,y,z-d);
    glVertex3f(x,y,z+d);
    glEnd();
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();

    glFlush();
    SwapBuffers(hdc);
    }
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner)
    {
    gl_init(Handle);

    int hnd,siz; char vertex[4096],fragment[4096];
    hnd=FileOpen("normal_shading.glsl_vert",fmOpenRead); siz=FileSeek(hnd,0,2); FileSeek(hnd,0,0); FileRead(hnd,vertex  ,siz); vertex  [siz]=0; FileClose(hnd);
    hnd=FileOpen("normal_shading.glsl_frag",fmOpenRead); siz=FileSeek(hnd,0,2); FileSeek(hnd,0,0); FileRead(hnd,fragment,siz); fragment[siz]=0; FileClose(hnd);
    glsl_init(vertex,fragment);
    hnd=FileCreate("GLSL.txt"); FileWrite(hnd,glsl_log,glsl_logs); FileClose(hnd);

    vao_init();
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
    {
    gl_exit();
    glsl_exit();
    vao_exit();
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormResize(TObject *Sender)
    {
    gl_resize(ClientWidth,ClientHeight);
    glMatrixMode(GL_PROJECTION);
    glTranslatef(0,0,-15.0);
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
    {
    gl_draw();
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
    {
    gl_draw();
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseWheel(TObject *Sender, TShiftState Shift, int WheelDelta, TPoint &MousePos, bool &Handled)
    {
    GLfloat dz=2.0;
    if (WheelDelta<0) dz=-dz;
    glMatrixMode(GL_PROJECTION);
    glTranslatef(0,0,dz);
    gl_draw();
    }
//---------------------------------------------------------------------------

Do not forget to change the layouts to yours, add textures and stuff only if this is already working and always check GLSL.txt (compile/link log) file to see if all is as should be.

Also you need GLEW for this so see

Here is this same example with texture atlas:

Witch answered 10/8, 2015 at 7:11 Comment(11)
Thank you for a detailed explanation on this. Previously I was following this tutorial gamedev.net/page/resources/_/technical/opengl/… which I have edited above and post my current shaders, for now I will update it based on what you have. Hoping to get a better results :)Urial
@Urial 1. your normal matrix and eyeCoord look suspicious they should be in the same coordinate system does not matter which one. 2. what values are you passing to Ld,Kd? 3. do not accept answer if you do not have wanted results yet (it means your issue is solved).Witch
gl_Position = m_proj * m_view * m_model * vert; transform vertex to screen space so gl_Position = m_view * m_model * vert; transforms to camera space and gl_Position = m_model * vert; transforms to world space [GCS]. the normal is vector so you need to discard the offset so normal matrix should be the same as m_model but the origin of it should be set to (0.0,0.0,0.0) see transform matrices. Then tnorm = m_normal * normal or tnorm = (m_model*normal) - m_model.originWitch
I cannot understand how can I get lt_direct_dir? I don't know where to get the fragment.xyz / Sun.xyz.Urial
Sorry for not understanding all of this after the detailed answer you gave. I am very new to OpenGL and this whole 3D thing. As of now I can get ideas only based on your answers but can't translate anything into code at all.Urial
Currently getting output like this imgur.com/OerdzNu, the left side is clear but when trying to rotate to other sides, their are black.Urial
@Urial added full example of VAO colored cube with normals (untextured) and GLSL normal shading (with single point/position light source). 1. fragment.xyz is the position of the fragment in my example it is pixel_pos 2. Sun.xyz is the position of sun (or any light source) you want to simulate ... so you choose where it is for normal shading it is usually placed behind cameraWitch
@Urial when you get this to work then you can add more stuff like diminishing light strength with distance, more lights, refections, .... PS I use layouts matching nVidia default positions so if shader is not compilable the output is still rendered with fixed function on nVidia gfx cards/driversWitch
Thank you for the complete example. I will try first to fix my shaders and I will update you once I am done. Thanks for the patience :DUrial
It works like magic. Thanks for the long support. You are a great man! Probably gonna experiment from now on :)Urial
@Urial I updated my gl_simple.h repaired the winding of the cube (GL_CULL_FACE now works for all sides) and also repaired 2 minor bugs one in obtaining program info log and one with indices (was using wrong functions for both) spot that just now while writing an example using it ...Witch

© 2022 - 2024 — McMap. All rights reserved.