Skip to content

Instantly share code, notes, and snippets.

@isaackwan
Last active November 10, 2017 01:53
Show Gist options
  • Save isaackwan/763e83a59d677dfd9fb98e5a3e8d85a5 to your computer and use it in GitHub Desktop.
Save isaackwan/763e83a59d677dfd9fb98e5a3e8d85a5 to your computer and use it in GitHub Desktop.
Posted on StackOverFlow - OpenGL Flickering when vector is multiplied
#version 430 core
in vec2 UV;
uniform layout(location = 3) sampler2D myTextureSampler;
out vec3 color;
in vec3 Position_worldspace;
in vec3 Normal_cameraspace;
in vec3 EyeDirection_cameraspace;
in vec3 LightDirection_cameraspace;
uniform layout(location = 6) vec3 LightPosition_worldspace;
void main()
{
// Light emission properties
// You probably want to put them as uniforms
vec3 LightColor = vec3(1,1,1);
float LightPower = 50.0f;
// Material properties
vec3 MaterialDiffuseColor = texture( myTextureSampler, UV ).rgb;
vec3 MaterialAmbientColor = vec3(0.1,0.1,0.1) * MaterialDiffuseColor;
vec3 MaterialSpecularColor = vec3(0.3,0.3,0.3);
// Distance to the light
float distance = length( LightPosition_worldspace - Position_worldspace );
// Normal of the computed fragment, in camera space
vec3 n = normalize( Normal_cameraspace );
// Direction of the light (from the fragment to the light)
vec3 l = normalize( LightDirection_cameraspace );
// Cosine of the angle between the normal and the light direction,
// clamped above 0
// - light is at the vertical of the triangle -> 1
// - light is perpendicular to the triangle -> 0
// - light is behind the triangle -> 0
float cosTheta = clamp( dot( n,l ), 0,1 );
// Eye vector (towards the camera)
vec3 E = normalize(EyeDirection_cameraspace);
// Direction in which the triangle reflects the light
vec3 R = reflect(-l,n);
// Cosine of the angle between the Eye vector and the Reflect vector,
// clamped to 0
// - Looking into the reflection -> 1
// - Looking elsewhere -> < 1
float cosAlpha = clamp( dot( E,R ), 0,1 );
color =
// Ambient : simulates indirect lighting
MaterialAmbientColor +
// Diffuse : "color" of the object
MaterialDiffuseColor * LightColor * LightPower * cosTheta / (distance*distance) +
// Specular : reflective highlight, like a mirror
MaterialSpecularColor * LightColor * LightPower * pow(cosAlpha,5) / (distance*distance);
color = MaterialDiffuseColor * vec3(0.5, 0.5, 0.5);
}
#include "Dependencies\glew\glew.h"
#include "Dependencies\freeglut\freeglut.h"
#include "Dependencies\glm\glm.hpp"
#include "Dependencies\glm\gtc\matrix_transform.hpp"
#include <iostream>
#include <fstream>
#include <vector>
#define positionAttrib 0
#define uvAttrib 1
#define vpTransformationAttrib 2
#define textureAttrib 3
#define modelTransformationAttrib 4
#define normalCoordinatesAttrib 5
using namespace std;
GLint programID;
GLuint vao[10];
GLuint vbo[10];
size_t obj1_size;
size_t obj2_size;
size_t obj3_size;
GLuint textureIds[3];
GLuint kbState[3];
bool checkStatus(
GLuint objectID,
PFNGLGETSHADERIVPROC objectPropertyGetterFunc,
PFNGLGETSHADERINFOLOGPROC getInfoLogFunc,
GLenum statusType)
{
GLint status;
objectPropertyGetterFunc(objectID, statusType, &status);
if (status != GL_TRUE)
{
GLint infoLogLength;
objectPropertyGetterFunc(objectID, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar* buffer = new GLchar[infoLogLength];
GLsizei bufferSize;
getInfoLogFunc(objectID, infoLogLength, &bufferSize, buffer);
cout << buffer << endl;
delete[] buffer;
return false;
}
return true;
}
bool checkShaderStatus(GLuint shaderID)
{
return checkStatus(shaderID, glGetShaderiv, glGetShaderInfoLog, GL_COMPILE_STATUS);
}
bool checkProgramStatus(GLuint programID)
{
return checkStatus(programID, glGetProgramiv, glGetProgramInfoLog, GL_LINK_STATUS);
}
string readShaderCode(const char* fileName)
{
ifstream meInput(fileName);
if (!meInput.good())
{
cout << "File failed to load..." << fileName;
exit(1);
}
return string(
istreambuf_iterator<char>(meInput),
istreambuf_iterator<char>()
);
}
void installShaders()
{
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
const GLchar* adapter[1];
string temp = readShaderCode("VertexShaderCode.glsl");
adapter[0] = temp.c_str();
glShaderSource(vertexShaderID, 1, adapter, 0);
temp = readShaderCode("FragmentShaderCode.glsl");
adapter[0] = temp.c_str();
glShaderSource(fragmentShaderID, 1, adapter, 0);
glCompileShader(vertexShaderID);
glCompileShader(fragmentShaderID);
if (!checkShaderStatus(vertexShaderID) || !checkShaderStatus(fragmentShaderID))
return;
programID = glCreateProgram();
glAttachShader(programID, vertexShaderID);
glAttachShader(programID, fragmentShaderID);
glLinkProgram(programID);
if (!checkProgramStatus(programID))
return;
glDeleteShader(vertexShaderID);
glDeleteShader(fragmentShaderID);
glUseProgram(programID);
}
void keyboard(unsigned char key, int x, int y)
{
if (key == 'z') {
cout << ++kbState[0] << endl;
}
else if (key == 'x') {
cout << --kbState[0] << endl;
}
else if (key == 'c') {
kbState[1] += 1;
cout << ++kbState[1] << endl;
}
else if (key == 'v') {
kbState[1] -= 1;
cout << --kbState[1] << endl;
}
else if (key == 'b') {
kbState[2] += 1;
cout << ++kbState[2] << endl;
}
else if (key == 'n') {
kbState[2] -= 1;
cout << --kbState[2] << endl;
}
}
void move(int key, int x, int y)
{
//TODO: Use arrow keys to do interactive events and animation
}
void PassiveMouse(int x, int y)
{
//TODO: Use Mouse to do interactive events and animation
}
bool loadOBJ(
const char * path,
std::vector<glm::vec3> & out_vertices,
std::vector<glm::vec2> & out_uvs,
std::vector<glm::vec3> & out_normals
) {
printf("Loading OBJ file %s...\n", path);
std::vector<unsigned int> vertexIndices, uvIndices, normalIndices;
std::vector<glm::vec3> temp_vertices;
std::vector<glm::vec2> temp_uvs;
std::vector<glm::vec3> temp_normals;
FILE * file = fopen(path, "r");
if (file == NULL) {
printf("Impossible to open the file ! Are you in the right path ? See Tutorial 1 for details\n");
getchar();
return false;
}
while (1) {
char lineHeader[128];
// read the first word of the line
int res = fscanf(file, "%s", lineHeader);
if (res == EOF)
break; // EOF = End Of File. Quit the loop.
// else : parse lineHeader
if (strcmp(lineHeader, "v") == 0) {
glm::vec3 vertex;
fscanf(file, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z);
temp_vertices.push_back(vertex);
}
else if (strcmp(lineHeader, "vt") == 0) {
glm::vec2 uv;
fscanf(file, "%f %f\n", &uv.x, &uv.y);
uv.y = -uv.y; // Invert V coordinate since we will only use DDS texture, which are inverted. Remove if you want to use TGA or BMP loaders.
temp_uvs.push_back(uv);
}
else if (strcmp(lineHeader, "vn") == 0) {
glm::vec3 normal;
fscanf(file, "%f %f %f\n", &normal.x, &normal.y, &normal.z);
temp_normals.push_back(normal);
}
else if (strcmp(lineHeader, "f") == 0) {
std::string vertex1, vertex2, vertex3;
unsigned int vertexIndex[3], uvIndex[3], normalIndex[3];
int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &vertexIndex[0], &uvIndex[0], &normalIndex[0], &vertexIndex[1], &uvIndex[1], &normalIndex[1], &vertexIndex[2], &uvIndex[2], &normalIndex[2]);
if (matches != 9) {
printf("File can't be read by our simple parser :-( Try exporting with other options\n");
fclose(file);
return false;
}
vertexIndices.push_back(vertexIndex[0]);
vertexIndices.push_back(vertexIndex[1]);
vertexIndices.push_back(vertexIndex[2]);
uvIndices.push_back(uvIndex[0]);
uvIndices.push_back(uvIndex[1]);
uvIndices.push_back(uvIndex[2]);
normalIndices.push_back(normalIndex[0]);
normalIndices.push_back(normalIndex[1]);
normalIndices.push_back(normalIndex[2]);
}
else {
// Probably a comment, eat up the rest of the line
char stupidBuffer[1000];
fgets(stupidBuffer, 1000, file);
}
}
// For each vertex of each triangle
for (unsigned int i = 0; i<vertexIndices.size(); i++) {
// Get the indices of its attributes
unsigned int vertexIndex = vertexIndices[i];
unsigned int uvIndex = uvIndices[i];
unsigned int normalIndex = normalIndices[i];
// Get the attributes thanks to the index
glm::vec3 vertex = temp_vertices[vertexIndex - 1];
glm::vec2 uv = temp_uvs[uvIndex - 1];
glm::vec3 normal = temp_normals[normalIndex - 1];
// Put the attributes in buffers
out_vertices.push_back(vertex);
out_uvs.push_back(uv);
out_normals.push_back(normal);
}
fclose(file);
return true;
}
GLuint loadBMP_custom(const char * imagepath) {
printf("Reading image %s\n", imagepath);
unsigned char header[54];
unsigned int dataPos;
unsigned int imageSize;
unsigned int width, height;
unsigned char * data;
FILE * file = fopen(imagepath, "rb");
if (!file) { printf("%s could not be opened. Are you in the right directory ? Don't forget to read the FAQ !\n", imagepath); getchar(); return 0; }
if (fread(header, 1, 54, file) != 54) {
printf("Not a correct BMP file\n");
return 0;
}
if (header[0] != 'B' || header[1] != 'M') {
printf("Not a correct BMP file\n");
return 0;
}
if (*(int*)&(header[0x1E]) != 0) { printf("Not a correct BMP file\n"); return 0; }
if (*(int*)&(header[0x1C]) != 24) { printf("Not a correct BMP file\n"); return 0; }
dataPos = *(int*)&(header[0x0A]);
imageSize = *(int*)&(header[0x22]);
width = *(int*)&(header[0x12]);
height = *(int*)&(header[0x16]);
if (imageSize == 0) imageSize = width*height * 3;
if (dataPos == 0) dataPos = 54;
data = new unsigned char[imageSize];
fread(data, 1, imageSize, file);
fclose(file);
//TODO: Create one OpenGL texture and set the texture parameter
GLuint textureId;
glGenTextures(1, &textureId);
// "Bind" the newly created texture : all future texture functions will modify this texture
glBindTexture(GL_TEXTURE_2D, textureId);
// Give the image to OpenGL
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
// OpenGL has now copied the data. Free our own version
delete[] data;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
cout << "Finished loading image " << imagepath << ", textureId: " << textureId << endl;
return textureId;
}
void sendDataToOpenGL()
{
//TODO:
//Load objects and bind to VAO & VBO
//Load texture
vector<glm::vec3> vertices;
vector<glm::vec2> uvs;
vector<glm::vec3> normals;
vector<glm::vec3> vertices2;
vector<glm::vec2> uvs2;
vector<glm::vec3> normals2;
vector<glm::vec3> vertices3;
vector<glm::vec2> uvs3;
vector<glm::vec3> normals3;
glGenVertexArrays(5, vao);
glGenBuffers(9, vbo);
bool res1 = loadOBJ("airplane4.obj", vertices, uvs, normals);
glBindVertexArray(vao[0]);
glEnableVertexAttribArray(positionAttrib);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
glVertexAttribPointer(
positionAttrib, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glEnableVertexAttribArray(uvAttrib);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(glm::vec2), &uvs[0], GL_STATIC_DRAW);
glVertexAttribPointer(
uvAttrib, // attribute
2, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glEnableVertexAttribArray(normalCoordinatesAttrib);
glBindBuffer(GL_ARRAY_BUFFER, vbo[6]);
glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), &normals[0], GL_STATIC_DRAW);
glVertexAttribPointer(
normalCoordinatesAttrib, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
obj1_size = vertices.size();
textureIds[0] = loadBMP_custom("airplane_texture.bmp");
glBindVertexArray(vao[4]);
bool res2 = loadOBJ("jeep5.obj", vertices2, uvs2, normals2);
glEnableVertexAttribArray(positionAttrib);
glBindBuffer(GL_ARRAY_BUFFER, vbo[4]);
glBufferData(GL_ARRAY_BUFFER, vertices2.size() * sizeof(glm::vec3), &vertices2[0], GL_STATIC_DRAW);
glVertexAttribPointer(
positionAttrib, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glEnableVertexAttribArray(uvAttrib);
glBindBuffer(GL_ARRAY_BUFFER, vbo[5]);
glBufferData(GL_ARRAY_BUFFER, uvs2.size() * sizeof(glm::vec2), &uvs2[0], GL_STATIC_DRAW);
glVertexAttribPointer(
uvAttrib, // attribute
2, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glEnableVertexAttribArray(normalCoordinatesAttrib);
glBindBuffer(GL_ARRAY_BUFFER, vbo[7]);
glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), &normals[0], GL_STATIC_DRAW);
glVertexAttribPointer(
normalCoordinatesAttrib, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
obj2_size = vertices2.size();
textureIds[1] = loadBMP_custom("jeep_texture.bmp");
glBindVertexArray(vao[2]);
bool res3 = loadOBJ("plane4.obj", vertices3, uvs3, normals3);
glEnableVertexAttribArray(positionAttrib);
glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
glBufferData(GL_ARRAY_BUFFER, vertices3.size() * sizeof(glm::vec3), &vertices3[0], GL_STATIC_DRAW);
glVertexAttribPointer(
positionAttrib, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glEnableVertexAttribArray(uvAttrib);
glBindBuffer(GL_ARRAY_BUFFER, vbo[3]);
glBufferData(GL_ARRAY_BUFFER, uvs3.size() * sizeof(glm::vec2), &uvs3[0], GL_STATIC_DRAW);
glVertexAttribPointer(
1, // attribute
2, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glEnableVertexAttribArray(normalCoordinatesAttrib);
glBindBuffer(GL_ARRAY_BUFFER, vbo[8]);
glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), &normals[0], GL_STATIC_DRAW);
glVertexAttribPointer(
normalCoordinatesAttrib, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
obj3_size = vertices3.size();
textureIds[2] = loadBMP_custom("plane_texture.bmp");
}
void paintGL(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.6, 0.6, 0.6, 0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnableVertexAttribArray(positionAttrib);
//TODO:
//Set lighting information, such as position and color of lighting source
//Set transformation matrix
//Bind different textures
glm::mat4 view = glm::lookAt(
glm::vec3(kbState[0]/70.0f -3.4f, kbState[1] / 70.0f, kbState[2] / 70.0f -43 / 20.0f + 6.0f),
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 0.0f, 1.0f)
);
glm::mat4 proj = glm::perspective(glm::radians(45.0f), 800.0f / 600.0f, 0.1f, 100.0f);
glm::mat4 vpTransformation = proj * view;
glm::mat4 modelTransformation;
glUniformMatrix4fv(vpTransformationAttrib, 1, GL_FALSE, &vpTransformation[0][0]);
glm::vec3 lightPos = glm::vec3(4, 4, 4);
glUniform3f(6, lightPos.x, lightPos.y, lightPos.z);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, textureIds[2]);
glUniform1i(textureAttrib, 2);
glBindVertexArray(vao[2]);
glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
modelTransformation = glm::mat4();
glUniformMatrix4fv(modelTransformationAttrib, 1, GL_FALSE, &modelTransformation[0][0]);
glDrawArrays(GL_TRIANGLES, 0, obj3_size);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureIds[0]);
glUniform1i(textureAttrib, 0);
glBindVertexArray(vao[0]);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
modelTransformation = glm::mat4();
modelTransformation = glm::scale(modelTransformation, glm::vec3(0.4f, 0.4f, 0.4f));
modelTransformation = glm::translate(modelTransformation, glm::vec3(-1.1f, -1.0f, 0.0f));
glUniformMatrix4fv(modelTransformationAttrib, 1, GL_FALSE, &modelTransformation[0][0]);
glDrawArrays(GL_TRIANGLES, 0, obj1_size);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textureIds[1]);
glUniform1i(textureAttrib, 1);
glBindVertexArray(vao[4]);
glBindBuffer(GL_ARRAY_BUFFER, vbo[4]);
modelTransformation = glm::mat4();
modelTransformation = glm::scale(modelTransformation, glm::vec3(0.4f, 0.4f, 0.4f));
modelTransformation = glm::translate(modelTransformation, glm::vec3(1.0f, 0.0f, 0.0f));
glUniformMatrix4fv(modelTransformationAttrib, 1, GL_FALSE, &modelTransformation[0][0]);
glDrawArrays(GL_TRIANGLES, 0, obj2_size);
glutSwapBuffers();
glutPostRedisplay();
}
void initializedGL(void)
{
glewInit();
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_CULL_FACE);
glEnable(GL_TEXTURE_2D);
installShaders();
sendDataToOpenGL();
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
//TODO:
//Create a window with title specified
glutInitWindowSize(800, 600);
glutCreateWindow("Assignment 1");
glewInit();
cout << "OpenGL Version: " << glGetString(GL_VERSION) << std::endl;
initializedGL();
glutDisplayFunc(paintGL);
glutKeyboardFunc(keyboard);
glutSpecialFunc(move);
glutPassiveMotionFunc(PassiveMouse);
glutMainLoop();
return 0;
}
#version 430 core
in layout(location = 0) vec3 position;
in layout(location = 1) vec2 vertexUV;
in layout(location = 5) vec3 normalCoordinates;
uniform layout(location = 2) mat4 vpTransformation;
uniform layout(location = 4) mat4 modelTransformation;
out vec2 UV;
out vec3 Position_worldspace;
out vec3 Normal_cameraspace;
out vec3 EyeDirection_cameraspace;
out vec3 LightDirection_cameraspace;
uniform layout(location = 6) vec3 LightPosition_worldspace;
void main()
{
gl_Position = modelTransformation * vpTransformation * vec4(position, 1.0);
UV = vertexUV;
Position_worldspace = (modelTransformation * vec4(position,1)).xyz;
vec3 vertexPosition_cameraspace = ( modelTransformation * vpTransformation * vec4(position,1)).xyz;
EyeDirection_cameraspace = vec3(0,0,0) - vertexPosition_cameraspace;
vec3 LightPosition_cameraspace = ( vpTransformation * vec4(LightPosition_worldspace,1)).xyz;
LightDirection_cameraspace = LightPosition_cameraspace + EyeDirection_cameraspace;
Normal_cameraspace = ( modelTransformation * vpTransformation * vec4(normalCoordinates,0)).xyz; // Only correct if ModelMatrix does not scale the model ! Use its inverse transpose if not.
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment