I intend to implement gouroud shading with two light.(point light and directional light)
I want to translate the point light and rotate the directional light with keyboard callback function of openGL.
But by my current code, light is not moving.
This is my main.cpp.
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <GL/glew.h>
#include <GL/glut.h>
#include <GL/glm/glm.hpp>
#include <GL/glm/gtx/transform.hpp> // rotate(), scale(), translate()
#include <GL/glm/gtc/quaternion.hpp>
#include <GL/glm/gtc/type_ptr.hpp>
using namespace std;
GLuint VertexArrayID;
GLuint programID;
GLint modelLoc;
GLint viewLoc;
GLint projLoc;
float sx = 0;
float sy = 0;
float sz = 0;
float translationStep = 0.1f;
float rotationAngle = 0.0f;
float rotationStep = 5.0f;
bool projMode = true; // true: perspective, false: ortho
GLint pointLightPosLoc;
GLint pointLightColorLoc;
GLuint directLightDirLoc;
GLuint directLightColorLoc;
glm::vec3 pointLightPos;
glm::vec3 pointLightColor;
glm::vec3 directLightDir;
glm::vec3 directLightColor;
GLfloat cubeVertices[] = {
0.1f, 0.1f, 0.1f, // v0
-0.1f, 0.1f, 0.1f, // v1
-0.1f, -0.1f, 0.1f, // v2
0.1f, -0.1f, 0.1f, // v3
0.1f, -0.1f, -0.1f, // v4
0.1f, 0.1f, -0.1f, // v5
-0.1f, 0.1f, -0.1f, // v6
-0.1f, -0.1f, -0.1f // v7
};
GLfloat cubeColors[] = {
1.0f, 0.0f, 0.0f, 1.0f, // Red
0.0f, 1.0f, 0.0f, 1.0f, // Green
0.0f, 0.0f, 1.0f, 1.0f, // Blue
1.0f, 1.0f, 0.0f, 1.0f, // Yellow
1.0f, 0.0f, 1.0f, 1.0f, // Magenta
0.0f, 1.0f, 1.0f, 1.0f, // Cyan
};
GLint cubeIndices[] = {
//front
0,1,2,
0,2,3,
//right
0,3,4,
0,4,5,
//up
0,1,6,
0,6,5,
//left
1,2,7,
1,7,6,
//down
3,7,4,
3,2,7,
//back
5,7,6,
5,4,7,
};
GLfloat cubeNormals[] = {
0.0f, 0.0f, 1.0f, // front
1.0f, 0.0f, 0.0f, // right
0.0f, 1.0f, 0.0f, // up
-1.0f, 0.0f, 0.0f, // left
0.0f, -1.0f, 0.0f, // down
0.0f, 0.0f, -1.0f, // back
};
GLuint LoadShaders(const char* vertex_file_path, const char* fragment_file_path)
{
//create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
GLint Result = GL_FALSE;
int InfoLogLength;
//Read the vertex shader code from the file
string VertexShaderCode;
ifstream VertexShaderStream(vertex_file_path, ios::in);
if (VertexShaderStream.is_open())
{
string Line = "";
while (getline(VertexShaderStream, Line))
VertexShaderCode += "n" + Line;
VertexShaderStream.close();
}
//Compile Vertex Shader
char const* VertexSourcePointer = VertexShaderCode.c_str();
glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL);
glCompileShader(VertexShaderID);
printf("Compiling shader : %sn", vertex_file_path);
//Check Vertex Shader
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
vector<char> VertexShaderErrorMessage(InfoLogLength);
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
fprintf(stdout, "%sn", &VertexShaderErrorMessage[0]);
}
//Read the fragment shader code from the file
string FragmentShaderCode;
ifstream FragmentShaderStream(fragment_file_path, ios::in);
if (FragmentShaderStream.is_open())
{
string Line = "";
while (getline(FragmentShaderStream, Line))
FragmentShaderCode += "n" + Line;
FragmentShaderStream.close();
}
//Compile Fragment Shader
char const* FragmentSourcePointer = FragmentShaderCode.c_str();
glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer, NULL);
glCompileShader(FragmentShaderID);
printf("Compiling shader : %sn", fragment_file_path);
//Check Fragment Shader
glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
vector<char> FragmentShaderErrorMessage(InfoLogLength);
glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
fprintf(stdout, "%sn", &FragmentShaderErrorMessage[0]);
}
//Link the program
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
fprintf(stdout, "Linking programn");
// Check the program
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
vector<char> ProgramErrorMessage(max(InfoLogLength, int(1)));
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
fprintf(stdout, "%sn", &ProgramErrorMessage[0]);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
return ProgramID;
}
void renderScene(void)
{
//Clear all pixels
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Let's draw something here
glBindVertexArray(VertexArrayID);
//define the size of point and draw a point.
int numCubes = 10;
for (int i = 0; i < numCubes; i++) {
glm::mat4 model = glm::mat4(1.0f);
glm::vec3 translateVec(0.0f + sx, i * 0.3f + sy, 0.0f + sz);
model = glm::translate(model, translateVec);
glm::vec3 rotationAxis = glm::vec3(0.0f, 1.0f, 0.0f);
model = glm::rotate(model, glm::radians(rotationAngle), rotationAxis);
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glDrawElements(GL_TRIANGLES, sizeof(cubeIndices) / sizeof(GLint), GL_UNSIGNED_INT, 0);
}
//Double buffer
glutSwapBuffers();
}
void translationKeyboard(unsigned char key, int x, int y) {
switch (key) {
case 'q':
sx += translationStep;
break;
case 'w':
sx -= translationStep;
break;
case 'a':
sy += translationStep;
break;
case 's':
sy -= translationStep;
break;
case 'z':
sz += translationStep;
break;
case 'x':
sz -= translationStep;
break;
case 'o':
printf("%dn", pointLightPos.x); //temporary
pointLightPos.x += translationStep;
break;
case 'p':
pointLightPos.x -= translationStep;
break;
case 'k':
pointLightPos.y += translationStep;
break;
case 'l':
pointLightPos.y -= translationStep;
break;
case 'n':
pointLightPos.z += translationStep;
break;
case 'm':
pointLightPos.z -= translationStep;
break;
}
glutPostRedisplay();
}
void rotationKeyboard(int key, int x, int y) {
switch (key) {
case GLUT_KEY_LEFT:
rotationAngle -= rotationStep;
break;
case GLUT_KEY_RIGHT:
rotationAngle += rotationStep;
break;
case GLUT_KEY_UP:
directLightDir.y += rotationStep;
break;
case GLUT_KEY_DOWN:
directLightDir.y -= rotationStep;
break;
}
glutPostRedisplay();
}
void setProjectionMatrix() {
glm::mat4 proj;
int width = glutGet(GLUT_WINDOW_WIDTH);
int height = glutGet(GLUT_WINDOW_HEIGHT);
if (projMode) {
// perspective projection
proj = glm::perspective(glm::radians(45.0f), (float)width / (float)height, 0.1f, 100.0f);
}
else {
// orthogonal projection
proj = glm::ortho(-3.0f, 3.0f, -3.0f, 3.0f, -15.0f, 15.0f);
}
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(proj));
}
void ProjecionModeMouse(int button, int state, int x, int y) {
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
projMode = !projMode;
setProjectionMatrix();
glutPostRedisplay();
}
}
void init()
{
//initilize the glew and check the errors.
GLenum res = glewInit();
if (res != GLEW_OK)
{
fprintf(stderr, "Error: '%s' n", glewGetErrorString(res));
}
//select the background color
glClearColor(1.0, 1.0, 1.0, 1.0);
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glDepthRange(0.0f, 1.0f);
}
int main(int argc, char** argv)
{
//init GLUT and create Window
//initialize the GLUT
glutInit(&argc, argv);
//GLUT_DOUBLE enables double buffering (drawing to a background buffer while the other buffer is displayed)
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
//These two functions are used to define the position and size of the window.
glutInitWindowPosition(200, 200);
glutInitWindowSize(480, 480);
//This is used to define the name of the window.
glutCreateWindow("Simple OpenGL Window");
//call initization function
init();
//0.
programID = LoadShaders("GVertexShader.txt", "GFragmentShader.txt");
glUseProgram(programID);
/**************************************************/
// 모델, 뷰, 프로젝션 행렬을 셰이더에 전달
modelLoc = glGetUniformLocation(programID, "model");
viewLoc = glGetUniformLocation(programID, "view");
projLoc = glGetUniformLocation(programID, "proj");
// 뷰 행렬 설정
glm::vec3 cameraPosition(5.0f, 3.0f, 5.0f); // 카메라 위치
glm::vec3 targetPosition(2.0f, 2.0f, 2.0f); // 타겟(큐브) 위치
glm::vec3 upVector(0.0f, 1.0f, 0.0f); // 업 벡터
glm::mat4 view = glm::lookAt(cameraPosition, targetPosition, upVector);
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
// 프로젝션 행렬 설정
setProjectionMatrix();
glm::vec3 pointLightPos(2.0f, 2.0f, 2.0f);
glm::vec3 pointLightColor(1.0f, 1.0f, 1.0f);
glm::vec3 directLightDir(-2.0f, -2.0f, -2.0f);
glm::vec3 directLightColor(1.0f, 1.0f, 1.0f);
// 점 광원의 위치, 색상을 셰이더에 전달
pointLightPosLoc = glGetUniformLocation(programID, "pointLightPos");
glUniform3fv(directLightDirLoc, 1, glm::value_ptr(directLightDir));
pointLightColorLoc = glGetUniformLocation(programID, "pointLightColor");
glUniform3fv(pointLightColorLoc, 1, glm::value_ptr(pointLightColor));
// 방향 광원의 위치, 색상을 셰이더에 전달
GLuint directLightDirLoc = glGetUniformLocation(programID, "directLightDir");
glUniform3fv(directLightDirLoc, 1, glm::value_ptr(directLightDir));
GLuint directLightColorLoc = glGetUniformLocation(programID, "directLightColor");
glUniform3fv(directLightColorLoc, 1, glm::value_ptr(directLightColor));
/**************************************************/
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
GLuint VBOs[3];
glGenBuffers(3, VBOs);
GLuint EBO[1];
glGenBuffers(1, EBO);
glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), cubeVertices, GL_STATIC_DRAW);
GLuint posAttribLoc = glGetAttribLocation(programID, "inPos");
glVertexAttribPointer(posAttribLoc, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(0));
glEnableVertexAttribArray(posAttribLoc);
glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeColors), cubeColors, GL_STATIC_DRAW);
GLuint colorAttribLoc = glGetAttribLocation(programID, "inColor");
glVertexAttribPointer(colorAttribLoc, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(0));
glEnableVertexAttribArray(colorAttribLoc);
glBindBuffer(GL_ARRAY_BUFFER, VBOs[2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeNormals), cubeNormals, GL_STATIC_DRAW);
GLuint normalAttribLoc = glGetAttribLocation(programID, "inNormal");
glVertexAttribPointer(normalAttribLoc, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(0));
glEnableVertexAttribArray(normalAttribLoc);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO[0]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cubeIndices), cubeIndices, GL_STATIC_DRAW);
glutDisplayFunc(renderScene);
glutKeyboardFunc(translationKeyboard); // translate cube and point light
glutSpecialFunc(rotationKeyboard); // rotate cube and directional light
glutMouseFunc(ProjecionModeMouse); // switch projection mode
//enter GLUT event processing cycle
glutMainLoop();
glDeleteVertexArrays(1, &VertexArrayID);
return 1;
}
And this is my GVertexShader.txt.
#version 400 core
in vec3 inPos;
in vec4 inColor;
in vec3 inNormal;
out vec4 vColor;
uniform mat4 model;
uniform mat4 view;
uniform mat4 proj;
uniform vec3 pointLightPos;
uniform vec3 pointLightColor;
uniform vec3 directLightDir;
uniform vec3 directLightColor;
void main()
{
vec4 vPos = vec4(inPos, 1.0);
vPos = proj * view * model * vPos;
vec3 tNormal = normalize(mat3(transpose(inverse(model))) * inNormal);
vec3 pointLightDir = normalize(pointLightPos - vPos.xyz);
float pointDiffuseStrength = max(dot(pointLightDir, tNormal), 0.0);
vec3 pointDiffuse = pointDiffuseStrength * pointLightColor;
float directDiffuseStrength = max(dot(-directLightDir, tNormal), 0.0);
vec3 directDiffuse = directDiffuseStrength * directLightColor;
vec3 reflectedLight = reflect(-pointLightDir, tNormal);
float specularStrength = pow(max(dot(reflectedLight, normalize(vec3(0, 0, 1))), 0.0), 1.0);
vec3 specular = specularStrength * vec3(1, 1, 1);
vColor = vec4(inColor.rgb * (pointDiffuse + directDiffuse) + specular, inColor.a);
gl_Position = vPos;
}
and GFragmentShader.txt.
#version 400 core
in vec4 vColor;
out vec4 fColor;
void main()
{
fColor = vColor;
}
Maybe i think there are some problem with declaration and point uniform (e.g.’pointLightPos’, ‘directLightDir’)
I try to print pointLightPos.x when keyboard ‘o’ is pressed. then result is random number.
Like below.
0
-1610612736
-1610612736
1073741824
-1610612736
0
1073741824
-2147483648
-1073741824
0
536870912
-1073741824
1610612736
0
-1610612736
1073741824
Please help me to solve this problem.
and Please understand that my English is not very good. 🙂
thank you.