Skip to content

Instantly share code, notes, and snippets.

@junodeveloper
Created May 16, 2019 08:25
Show Gist options
  • Save junodeveloper/2bf6f863326212b2d0183534d3eed45c to your computer and use it in GitHub Desktop.
Save junodeveloper/2bf6f863326212b2d0183534d3eed45c to your computer and use it in GitHub Desktop.
InClass 08
#version 330 core
out vec4 FragColor;
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
struct DirLight {
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
struct SpotLight {
vec3 position;
float constant;
float linear;
float quadratic;
float innerCutOff;
float outerCutOff;
vec3 ambient;
vec3 diffuse;
vec3 specular;
vec3 direction;
};
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoords;
uniform vec3 viewPos;
uniform DirLight dirLight;
uniform SpotLight spotLight;
uniform Material material;
// function prototypes
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
void main()
{
// properties
vec3 norm = normalize(Normal);
vec3 viewDir = normalize(viewPos - FragPos);
// directional lighting
vec3 result = CalcDirLight(dirLight, norm, viewDir);
// spotlight
result += CalcSpotLight(spotLight, norm, FragPos, viewDir);
FragColor = vec4(result, 1.0);
}
// calculates the color when using a directional light.
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
vec3 lightDir = normalize(-light.direction);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// combine results
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
return (ambient + diffuse + specular);
}
// calculates the color when using a point light.
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
// combine results
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
vec3 I = (ambient + diffuse + specular);
// cutoff
float theta = dot(lightDir, normalize(-light.direction));
if(theta < light.outerCutOff)
return ambient;
else if(theta > light.innerCutOff)
return I;
return I * (theta - light.outerCutOff) / (light.innerCutOff - light.outerCutOff);
}
// 32_InfinitePointLights
// Mouse: Arcball manipulation
// Keyboard: 'r' - reset arcball
// 'a' - toggle camera/object rotation
#define GLM_ENABLE_EXPERIMENTAL
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iostream>
#include <cmath>
#include <shader.h>
#include <cube.h>
#include <arcball.h>
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
using namespace std;
// Function Prototypes
GLFWwindow *glAllInit();
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void key_callback(GLFWwindow *window, int key, int scancode, int action , int mods);
void mouse_button_callback(GLFWwindow *window, int button, int action, int mods);
void cursor_position_callback(GLFWwindow *window, double x, double y);
unsigned int loadTexture(char *);
void render();
// Global variables
GLFWwindow *mainWindow = NULL;
Shader *lightingShader = NULL;
Shader *lampShader = NULL;
unsigned int SCR_WIDTH = 600;
unsigned int SCR_HEIGHT = 600;
Cube *cube;
Cube *lamp;
glm::mat4 projection, view, model;
// for arcball
float arcballSpeed = 0.2f;
static Arcball camArcBall(SCR_WIDTH, SCR_HEIGHT, arcballSpeed, true, true );
static Arcball modelArcBall(SCR_WIDTH, SCR_HEIGHT, arcballSpeed, true, true);
bool arcballCamRot = true;
// for camera
glm::vec3 cameraPos(0.0f, 0.0f, 9.0f);
// for lighting
glm::vec3 lightSize(0.1f, 0.1f, 0.1f);
glm::vec3 lightPos(1.2f, 1.0f, 2.0f);
// for spotlight
glm::vec3 spotPosition(1.0f, 1.0f, 1.0f);
glm::vec3 spotDirection(-1.0f, -1.0f, -1.0f);
// for texture
static unsigned int diffuseMap, specularMap; // texture ids for diffuse and specular maps
int main()
{
mainWindow = glAllInit();
// shader loading and compile (by calling the constructor)
lightingShader = new Shader("6.multiple_lights.vs", "6.multiple_lights.fs");
lampShader = new Shader("6.lamp.vs", "6.lamp.fs");
// projection and view matrix
lightingShader->use();
projection = glm::perspective(glm::radians(45.0f),
(float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
lightingShader->setMat4("projection", projection);
lampShader->use();
lampShader->setMat4("projection", projection);
// load texture
diffuseMap = loadTexture("container2.bmp");
specularMap = loadTexture("container2_specular.bmp");
// transfer texture id to fragment shader
lightingShader->use();
lightingShader->setInt("material.diffuse", 0);
lightingShader->setInt("material.specular", 1);
lightingShader->setFloat("material.shininess", 32);
lightingShader->setVec3("viewPos", cameraPos);
// transfer lighting parameters to fragment shader
// directional light
lightingShader->setVec3("dirLight.direction", -0.2f, -1.0f, -0.3f);
lightingShader->setVec3("dirLight.ambient", 0.1f, 0.1f, 0.1f);
lightingShader->setVec3("dirLight.diffuse", 0.4f, 0.4f, 0.4f);
lightingShader->setVec3("dirLight.specular", 0.5f, 0.5f, 0.5f);
// spotlight
lightingShader->setVec3("spotLight.position", spotPosition);
lightingShader->setVec3("spotLight.ambient", 0.1f, 0.1f, 0.1f);
lightingShader->setVec3("spotLight.diffuse", 1.0f, 1.0f, 1.0f);
lightingShader->setVec3("spotLight.specular", 1.0f, 1.0f, 1.0f);
lightingShader->setFloat("spotLight.constant", 1.0f);
lightingShader->setFloat("spotLight.linear", 0.09);
lightingShader->setFloat("spotLight.quadratic", 0.032);
lightingShader->setVec3("spotLight.direction", spotDirection);
lightingShader->setFloat("spotLight.innerCutOff", glm::cos(glm::radians(12.5f)));
lightingShader->setFloat("spotLight.outerCutOff", glm::cos(glm::radians(17.5f)));
// create a cubes
cube = new Cube();
while (!glfwWindowShouldClose(mainWindow)) {
render();
glfwPollEvents();
}
glfwTerminate();
return 0;
}
GLFWwindow *glAllInit()
{
GLFWwindow *window;
// glfw: initialize and configure
if (!glfwInit()) {
printf("GLFW initialisation failed!");
glfwTerminate();
exit(-1);
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
// glfw window creation
window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "Infinite and Point Lights", NULL, NULL);
if (window == NULL) {
cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
exit(-1);
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSetKeyCallback(window, key_callback);
glfwSetMouseButtonCallback(window, mouse_button_callback);
glfwSetCursorPosCallback(window, cursor_position_callback);
// OpenGL states
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glEnable(GL_DEPTH_TEST);
// Allow modern extension features
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK) {
cout << "GLEW initialisation failed!" << endl;
glfwDestroyWindow(window);
glfwTerminate();
exit(-1);
}
return window;
}
unsigned int loadTexture(char *texFileName) {
unsigned int texture;
// Create texture ids.
glGenTextures(1, &texture);
// All upcomming GL_TEXTURE_2D operations now on "texture" object
glBindTexture(GL_TEXTURE_2D, texture);
// Set texture parameters for wrapping.
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Set texture parameters for filtering.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int width, height, nrChannels;
stbi_set_flip_vertically_on_load(true); // vertical flip the texture
unsigned char *image = stbi_load(texFileName, &width, &height, &nrChannels, 0);
if (!image) {
printf("texture %s loading error ... \n", texFileName);
}
else printf("texture %s loaded\n", texFileName);
GLenum format;
if (nrChannels == 1) format = GL_RED;
else if (nrChannels == 3) format = GL_RGB;
else if (nrChannels == 4) format = GL_RGBA;
glBindTexture( GL_TEXTURE_2D, texture );
glTexImage2D( GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, image );
glGenerateMipmap(GL_TEXTURE_2D);
return texture;
}
void render() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
view = glm::lookAt(cameraPos, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
view = view * camArcBall.createRotationMatrix();
// cube objects
lightingShader->use();
lightingShader->setMat4("view", view);
// texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, diffuseMap);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, specularMap);
// cube1
model = glm::mat4(1.0f);
model = model * modelArcBall.createRotationMatrix();
lightingShader->setMat4("model", model);
cube->draw(lightingShader);
// cube2
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(1.0f, -1.0f, -1.0f));
lightingShader->setMat4("model", model);
cube->draw(lightingShader);
// cube3
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(-1.5f, 2.0f, 1.0f));
lightingShader->setMat4("model", model);
cube->draw(lightingShader);
// lamp (spotlight)
lampShader->use();
lampShader->setMat4("view", view);
model = glm::mat4(1.0f);
model = glm::translate(model, spotPosition);
model = glm::scale(model, lightSize);
lampShader->setMat4("model", model);
cube->draw(lampShader);
glfwSwapBuffers(mainWindow);
}
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
// make sure the viewport matches the new window dimensions; note that width and
// height will be significantly larger than specified on retina displays.
glViewport(0, 0, width, height);
SCR_WIDTH = width;
SCR_HEIGHT = height;
}
void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
glfwSetWindowShouldClose(window, true);
}
else if (key == GLFW_KEY_R && action == GLFW_PRESS) {
camArcBall.init(SCR_WIDTH, SCR_HEIGHT, arcballSpeed, true, true);
modelArcBall.init(SCR_WIDTH, SCR_HEIGHT, arcballSpeed, true, true);
}
else if (key == GLFW_KEY_A && action == GLFW_PRESS) {
arcballCamRot = !arcballCamRot;
if (arcballCamRot) {
cout << "ARCBALL: Camera rotation mode" << endl;
}
else {
cout << "ARCBALL: Model rotation mode" << endl;
}
}
}
void mouse_button_callback(GLFWwindow *window, int button, int action, int mods) {
if (arcballCamRot)
camArcBall.mouseButtonCallback( window, button, action, mods );
else
modelArcBall.mouseButtonCallback( window, button, action, mods );
}
void cursor_position_callback(GLFWwindow *window, double x, double y) {
if (arcballCamRot)
camArcBall.cursorCallback( window, x, y );
else
modelArcBall.cursorCallback( window, x, y );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment