Dear all,
I’ve been ripping my hair off for too long and beg your help.
I am following Computer Graphics with Modern OpenGL and C++ training course by Ben Cook on Udemy.
On lecture 23, he is showcasing diffuse lighting.
Instead of building kinda pyramids like he did, I built cubes. And the diffuse lighting as explained in the lecture won’t work with my cubes (apart from the intensity factor).
I’m getting nuts, please help.
First, here is a screenshot of my (unlit) cubes :
Now here is my code:
Mesh.cpp
#include "Mesh.h"
Mesh::Mesh()
:
mVAO(0),
mVBO(0),
mIBO(0),
mIndexCount(0),
mModel(NULL),
mProjection(NULL),
mDirection(true),
mOffset(0.0f),
mMaxOffset(1.0f),
mIncrement(0.0005f),
mCurrAngle(0.0f)
{}
Mesh::Mesh(bool direction, float offset, float maxOffset, float increment)
:
mVAO(0),
mVBO(0),
mIBO(0),
mIndexCount(0),
mModel(NULL),
mProjection(NULL),
mCurrAngle(0.0f)
{
mDirection = direction;
mOffset = offset;
mMaxOffset = maxOffset;
mIncrement = increment;
}
Mesh::~Mesh()
{
ClearMesh();
}
void Mesh::CreateMesh(std::vector<GLfloat>& vertices, std::vector<GLuint>& indices, GLuint numOfVertices, GLuint numOfIndices)
{
mIndexCount = numOfIndices;
glGenVertexArrays(1, &mVAO);
glBindVertexArray(mVAO);
// Index buffer
glGenBuffers(1, &mIBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), indices.data(), GL_STATIC_DRAW);
// Vertex buffer
glGenBuffers(1, &mVBO);
glBindBuffer(GL_ARRAY_BUFFER, mVBO);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), vertices.data(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertices[0]) * 8, (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertices[0]) * 8, (void*)(sizeof(vertices[0]) * 3));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(vertices[0]) * 8, (void*)(sizeof(vertices[0]) * 5));
glEnableVertexAttribArray(2);
// Unbind
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void Mesh::RenderMesh()
{
glBindVertexArray(mVAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIBO);
glDrawArrays(GL_TRIANGLES, 0, mIndexCount);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void Mesh::ClearMesh()
{
if (mIBO != 0)
{
glDeleteBuffers(1, &mIBO);
mIBO = 0;
}
if (mVBO != 0)
{
glDeleteBuffers(1, &mVBO);
mVBO = 0;
}
if (mVAO != 0)
{
glDeleteVertexArrays(1, &mVAO);
mVAO = 0;
}
mIndexCount = 0;
}
Shader.cpp
#include "Shader.h"
Shader::Shader()
:
mShaderID(0),
mUniformModel(0),
mUniformProjection(0),
mUniformView(0),
mUniformAmbientIntensity(0),
mUniformAmbientColour(0),
mUniformDiffuseIntensity(0),
mUniformDirection(0)
{}
Shader::~Shader()
{
ClearShader();
}
void Shader::CreateFromString(const char* vertexCode, const char* fragmentCode)
{
CompileShader(vertexCode, fragmentCode);
}
void Shader::CreateFromFiles(const char* vertexShaderLocation, const char* fragmentShaderLocation)
{
std::string vertexString = ReadFile(vertexShaderLocation);
std::string fragmentString = ReadFile(fragmentShaderLocation);
const char* vertexCode = vertexString.c_str();
const char* fragmentCode = fragmentString.c_str();
CompileShader(vertexCode, fragmentCode);
}
std::string Shader::ReadFile(const char* fileLocation)
{
std::string content;
std::ifstream fileStream(fileLocation, std::ios::in);
if (!fileStream.is_open())
{
printf("[ERR] Failed to read %s. File doesn't exist.", fileLocation);
return "";
}
std::string line = "";
while (!fileStream.eof())
{
std::getline(fileStream, line);
content.append(line + "\n");
}
fileStream.close();
return content;
}
void Shader::UseShader()
{
glUseProgram(mShaderID);
}
void Shader::ClearShader()
{
if (mShaderID != 0)
{
glDeleteProgram(mShaderID);
mShaderID = 0;
}
mUniformModel = 0;
mUniformProjection = 0;
}
bool Shader::AddShader(GLuint theProgram, const char* shaderCode, GLenum shaderType)
{
GLuint theShader = glCreateShader(shaderType);
const GLchar* theCode[1] = { 0 };
theCode[0] = shaderCode;
GLint codeLength[1] = { 0 };
codeLength[0] = strlen(shaderCode);
glShaderSource(theShader, 1, theCode, codeLength);
glCompileShader(theShader);
GLint result = 0;
GLchar eLog[1024] = { 0 };
glGetShaderiv(theShader, GL_COMPILE_STATUS, &result);
if (!result)
{
glGetProgramInfoLog(theShader, sizeof(eLog), nullptr, eLog);
printf("[ERR] Error compiling the %d shader: '%s' \n", shaderType, eLog);
return false;
}
glAttachShader(theProgram, theShader);
return true;
}
bool Shader::CompileShader(const char* vertexCode, const char* fragmentCode)
{
mShaderID = glCreateProgram();
if (!mShaderID)
{
printf("[ERR] Error creating shader program.");
return false;
}
AddShader(mShaderID, vertexCode, GL_VERTEX_SHADER);
AddShader(mShaderID, fragmentCode, GL_FRAGMENT_SHADER);
GLint result = 0;
GLchar eLog[1024] = { 0 };
glLinkProgram(mShaderID);
glGetProgramiv(mShaderID, GL_LINK_STATUS, &result);
if (!result)
{
glGetProgramInfoLog(mShaderID, sizeof(eLog), nullptr, eLog);
printf("[ERR] Error linking program: '%s' \n", eLog);
return false;
}
glValidateProgram(mShaderID);
glGetProgramiv(mShaderID, GL_VALIDATE_STATUS, &result);
if (!result)
{
glGetProgramInfoLog(mShaderID, sizeof(eLog), nullptr, eLog);
printf("[ERR] Error validating program: '%s' \n", eLog);
return false;
}
mUniformProjection = glGetUniformLocation(mShaderID, "projection");
mUniformModel = glGetUniformLocation(mShaderID, "model");
mUniformView = glGetUniformLocation(mShaderID, "view");
mUniformAmbientColour = glGetUniformLocation(mShaderID, "directionalLight.colour");
mUniformAmbientIntensity = glGetUniformLocation(mShaderID, "directionalLight.ambientIntensity");
mUniformDirection = glGetUniformLocation(mShaderID, "directionalLight.direction");
mUniformDiffuseIntensity = glGetUniformLocation(mShaderID, "directionalLight.diffuseIntensity");
return true;
}
Light.cpp
#include "Light.h"
Light::Light()
{
mAmbientColour = glm::vec3(1.0f, 1.0f, 1.0f);
mAmbientIntensity = 1.0f;
mDirection = glm::vec3(0.0f, -1.0f, 0.0f);
mDiffuseIntensity = 0.0f;
}
Light::Light(GLfloat r, GLfloat g, GLfloat b, GLfloat ambIntensity, GLfloat xDir, GLfloat yDir, GLfloat zDir, GLfloat difIntensity)
{
mAmbientColour = glm::vec3(r, g, b);
mAmbientIntensity = ambIntensity;
mDirection = glm::vec3(xDir, yDir, zDir);
mDiffuseIntensity = difIntensity;
}
Light::~Light()
{}
void Light::UseLight(
GLfloat ambientIntensityLocation,
GLfloat ambientColourLocation,
GLfloat diffuseIntensityLocation,
GLfloat directionLocation
)
{
glUniform3f(ambientColourLocation, mAmbientColour.x, mAmbientColour.y, mAmbientColour.z);
glUniform1f(ambientIntensityLocation, mAmbientIntensity);
glUniform3f(directionLocation, mDirection.x, mDirection.y, mDirection.z);
glUniform1f(diffuseIntensityLocation, mDiffuseIntensity);
}
App.cpp (the core module)
#include "App.h"
App::App()
:
mClientWidth(800),
mClientHeight(600),
mWindowName("Skelkingr"),
mMainWindow(nullptr),
mBufferWidth(0),
mBufferHeight(0),
mLastMousePosition({ 0.0f, 0.0f }),
mMouseChange({ 0.0f, 0.0f }),
mMouseFirstMoved(true),
mTextureList({})
{
for (size_t i = 0; i < 1024; i++)
mKeys[i] = false;
mCamera = Camera(
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 1.0f, 0.0f),
-90.0f,
0.0f,
5.0f,
200.0f
);
mMainLight = Light(1.0f, 1.0f, 1.0f, 0.2f, 2.0f, -1.0f, -2.0f, 1.0f);
}
App::~App()
{
for (Texture* texture : mTextureList)
{
texture->ClearTexture();
delete texture;
}
for (Mesh* obj : mMeshList)
{
obj->ClearMesh();
delete obj;
}
glfwDestroyWindow(mMainWindow);
glfwTerminate();
}
void App::Clear(float r, float g, float b, float a)
{
glClearColor(r, g, b, a);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
int App::Run()
{
while (!glfwWindowShouldClose(mMainWindow))
{
glfwPollEvents();
GLfloat deltaTime = mTimer.DeltaTime();
mCamera.KeyControl(mKeys, deltaTime);
mCamera.MouseControl(GetMouseChangeX(), GetMouseChangeY(), deltaTime);
Update(0.35f);
Clear(0.0f, 0.0f, 0.0f, 1.0f);
Render();
}
return 0;
}
bool App::Init()
{
if (!InitMainWindow())
{
printf("[ERR] Failed to initialize the main window.");
return false;
}
CreateObject(true, 0.05f, 1.5f, 0.0005f);
CreateObject(false, 0.0f, 1.5f, 0.0005f);
CreateObject(true, -0.5f, 1.5f, 0.0005f);
CreateShader();
InitTextures();
for (Mesh* obj : mMeshList)
obj->SetProjection(glm::perspective(45.0f, (GLfloat)mBufferWidth / (GLfloat)mBufferHeight, 0.1f, 100.0f));
return true;
}
void App::Update(float deltaTime)
{
for (Mesh* obj : mMeshList)
{
if (obj->GetDirection())
{
obj->SetOffset(obj->GetOffset() + obj->GetIncrement() * deltaTime);
}
else
{
obj->SetOffset(obj->GetOffset() - obj->GetIncrement() * deltaTime);
}
if (abs(obj->GetOffset()) >= obj->GetMaxOffset())
obj->SetDirection(!obj->GetDirection());
obj->SetCurrentAngle(obj->GetCurrentAngle() + 0.01f);
if (obj->GetCurrentAngle() >= 360.0f)
obj->SetCurrentAngle(obj->GetCurrentAngle() - 360.0f);
}
}
void App::Render()
{
int i = 0;
for (Mesh* obj : mMeshList)
{
mShaderList[0].UseShader();
GLfloat a = (GLfloat)mShaderList[0].GetAmbientIntensityLocation();
GLfloat b = (GLfloat)mShaderList[0].GetAmbientColourLocation();
GLfloat c = (GLfloat)mShaderList[0].GetDirectionLocation();
GLfloat d = (GLfloat)mShaderList[0].GetDiffuseIntensityLocation();
mMainLight.UseLight(a, b, c, d);
obj->SetModel(glm::mat4(1.0f));
obj->SetModel(glm::translate(obj->GetModel(), glm::vec3(obj->GetOffset(), 1 - i, -3.0f)));
obj->SetModel(glm::rotate(obj->GetModel(), obj->GetCurrentAngle() * TO_RADIANS, glm::vec3(0.0f, 1.0f, 0.0f)));
obj->SetModel(glm::scale(obj->GetModel(), glm::vec3(0.3f, 0.3f, 0.3f)));
glUniformMatrix4fv(mShaderList[0].GetModelLocation(), 1, GL_FALSE, glm::value_ptr(obj->GetModel()));
glUniformMatrix4fv(mShaderList[0].GetProjectionLocation(), 1, GL_FALSE, glm::value_ptr(obj->GetProjection()));
glUniformMatrix4fv(mShaderList[0].GetViewLocation(), 1, GL_FALSE, glm::value_ptr(mCamera.CalculateViewMatrix()));
mTextureList[i]->UseTexture();
obj->RenderMesh();
glUseProgram(0);
i++;
}
glfwSwapBuffers(mMainWindow);
}
void App::CreateObject(bool direction, float offset, float maxOffset, float increment)
{
std::vector<GLuint> indices =
{
//Front:
0, 1, 2,
1, 3, 2,
//Left:
4, 0, 7,
0, 3, 7,
//Back:
5, 4, 6,
4, 7, 6,
//Right:
1, 5, 2,
5, 6, 2,
//Bottom:
0, 1, 4,
1, 5, 4,
//Top:
3, 2, 7,
2, 6, 7
};
// X, Y, Z U, V NX, NY, NZ
std::vector<GLfloat> vertices =
{
//Front:
-1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // First triangle
1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // Second triangle
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f,
-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
//Left:
-1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // First triangle
-1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
-1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
-1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // Second triangle
-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f,
-1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
//Back:
1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // First triangle
-1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
-1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // Second triangle
-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f,
1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
//Right:
1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // First triangle
1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // Second triangle
1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f,
1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
//Bottom:
-1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // First triangle
1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
-1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // Second triangle
1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f,
-1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
//Top:
-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // First triangle
1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
-1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // Second triangle
1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f,
-1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f
};
ComputeAverageNormals(indices, indices.size(), vertices, vertices.size(), 24, 5);
Mesh* obj = new Mesh(direction, offset, maxOffset, increment);
obj->CreateMesh(vertices, indices, vertices.size(), indices.size());
mMeshList.push_back(obj);
}
void App::CreateShader()
{
Shader* shader = new Shader();
shader->CreateFromFiles("Shaders\\shader.vert", "Shaders\\shader.frag");
mShaderList.push_back(*shader);
}
void App::InitTextures()
{
mTextureList.push_back(new Texture((char*)"Textures\\brick.png"));
mTextureList.push_back(new Texture((char*)"Textures\\dirt.png"));
mTextureList.push_back(new Texture((char*)"Textures\\wood.png"));
for (Texture* tex : mTextureList)
tex->LoadTexture();
}
GLfloat App::GetMouseChangeX()
{
GLfloat theChange = mMouseChange.x;
mMouseChange.x = 0.0f;
return theChange;
}
GLfloat App::GetMouseChangeY()
{
GLfloat theChange = mMouseChange.y;
mMouseChange.y = 0.0f;
return theChange;
}
bool App::InitMainWindow()
{
if (!glfwInit())
{
printf("[ERR] GLFW initialisation failed.");
glfwTerminate();
return false;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Core profile = no backwards compatibility
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Allow forward compatibility
mMainWindow = glfwCreateWindow(mClientWidth, mClientHeight, mWindowName, nullptr, nullptr);
if (!mMainWindow)
{
printf("[ERR] GLFW window creation failed.");
glfwTerminate();
return false;
}
glfwGetFramebufferSize(mMainWindow, &mBufferWidth, &mBufferHeight);
// Bind context to window
glfwMakeContextCurrent(mMainWindow);
// Handle key + mouse input
CreateCallbacks();
glfwSetInputMode(mMainWindow, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glewExperimental = GL_TRUE; // Allow modern extension features
if (glewInit() != GLEW_OK)
{
printf("[ERR] Glew initialisation failed.");
glfwDestroyWindow(mMainWindow);
glfwTerminate();
return false;
}
// Enable depth
glEnable(GL_DEPTH_TEST);
// Setup viewport size
glViewport(0, 0, mBufferWidth, mBufferHeight);
glfwSetWindowUserPointer(mMainWindow, this);
return true;
}
void App::CreateCallbacks()
{
glfwSetKeyCallback(mMainWindow, HandleKeys);
glfwSetCursorPosCallback(mMainWindow, HandleMouse);
}
void App::HandleKeys(GLFWwindow* window, int key, int code, int action, int mode)
{
App* theApp = static_cast<App*>(glfwGetWindowUserPointer(window));
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
{
glfwSetWindowShouldClose(window, GL_TRUE);
}
if (key >= 0 && key <= 1024)
{
if (action == GLFW_PRESS)
{
theApp->mKeys[key] = true;
}
else if (action == GLFW_RELEASE)
{
theApp->mKeys[key] = false;
}
}
}
void App::HandleMouse(GLFWwindow* window, double xPos, double yPos)
{
App* theApp = static_cast<App*>(glfwGetWindowUserPointer(window));
if (theApp->mMouseFirstMoved)
{
theApp->mLastMousePosition.x = (GLfloat)xPos;
theApp->mLastMousePosition.y = (GLfloat)yPos;
theApp->mMouseFirstMoved = false;
}
theApp->mMouseChange.x = (GLfloat)xPos - theApp->mLastMousePosition.x;
theApp->mMouseChange.y = theApp->mLastMousePosition.y - (GLfloat)yPos;
theApp->mLastMousePosition.x = (GLfloat)xPos;
theApp->mLastMousePosition.y = (GLfloat)yPos;
}
As per the ComputeAverageNormals function, it is in a separate Util.h file, here it is :
namespace
{
void ComputeAverageNormals(
std::vector<GLuint>& indices,
GLuint indicesCount,
std::vector<GLfloat>& vertices,
GLuint verticesCount,
GLuint vLength,
GLuint normalOffset
)
{
for (size_t i = 0; i < indicesCount; i += 3)
{
unsigned int in0 = indices[i] * vLength;
unsigned int in1 = indices[i + 1] * vLength;
unsigned int in2 = indices[i + 2] * vLength;
glm::vec3 v1(vertices[in1] - vertices[in0], vertices[in1 + 1] - vertices[in0 + 1], vertices[in1 + 2] - vertices[in0 + 2]);
glm::vec3 v2(vertices[in2] - vertices[in0], vertices[in2 + 1] - vertices[in0 + 1], vertices[in2 + 2] - vertices[in0 + 2]);
glm::vec3 normal = glm::cross(v1, v2);
normal = glm::normalize(normal);
in0 += normalOffset; in1 += normalOffset; in2 += normalOffset;
vertices[in0] += normal.x; vertices[in0 + 1] += normal.y; vertices[in0 + 2] += normal.z;
vertices[in1] += normal.x; vertices[in1 + 1] += normal.y; vertices[in1 + 2] += normal.z;
vertices[in2] += normal.x; vertices[in2 + 1] += normal.y; vertices[in2 + 2] += normal.z;
}
for (size_t i = 0; i < verticesCount / vLength; i++)
{
unsigned int nOffset = i * vLength + normalOffset;
glm::vec3 vec(vertices[nOffset], vertices[nOffset + 1], vertices[nOffset + 2]);
vec = glm::normalize(vec);
vertices[nOffset] = vec.x; vertices[nOffset + 1] = vec.y; vertices[nOffset + 2] = vec.z;
}
}
}
Please help fellows
Oh, I almost forgot, my shader files :
Vertex shader :
#version 330
layout (location = 0) in vec3 pos;
layout (location = 1) in vec2 tex;
layout (location = 2) in vec3 norm;
out vec4 vCol;
out vec2 TexCoord;
out vec3 Normal;
uniform mat4 model;
uniform mat4 projection;
uniform mat4 view;
void main()
{
gl_Position = projection * view * model * vec4(pos, 1.0);
vCol = vec4(clamp(pos, 0.0f, 1.0f), 1.0f);
TexCoord = tex;
Normal = norm;
}
Fragment shader
#version 330
in vec4 vCol;
in vec2 TexCoord;
in vec3 Normal;
out vec4 colour;
struct DirectionalLight
{
vec3 colour;
float ambientIntensity;
vec3 direction;
float diffuseIntensity;
};
uniform sampler2D theTexture;
uniform DirectionalLight directionalLight;
void main()
{
vec4 ambientColour = vec4(directionalLight.colour, 1.0f) * directionalLight.ambientIntensity;
float diffuseFactor = max(dot(normalize(Normal), normalize(-directionalLight.direction)), 0.0f);
vec4 diffuseColour = vec4(directionalLight.colour, 1.0f) * directionalLight.diffuseIntensity * diffuseFactor;
colour = texture(theTexture, TexCoord) * (ambientColour + diffuseColour);
}
Bless you all.
Skelkingr