OpenGL Projects
This is an ocean generated by creating a plane of the same texture. Once created, the vertices get passed into the vertex shader and go into a function consisting of compounding sine waves. This generates the ocean effect. Next, the fog is created in the fragment shader by taking the distance from the camera and using a linear function to calculate how much grey value each pixel should take on.
Vertex Shader:
#version 410 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec4 aColor;
layout (location = 2) in vec2 aTexCoord;
layout (location = 3) in vec3 aNormal;
out vec2 TexCoord;
out vec3 FragPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
#define SCALE 10.0
uniform float time;
float calculateSurface(float x, float z) {
float y = 0.0;
y += (sin(x * 1.0 / SCALE + time * 1.0) + sin(x * 2.3 / SCALE + time * 1.5) + sin(x * 3.3 / SCALE + time * 0.4)) / 3.0;
y += (sin(z * 0.2 / SCALE + time * 1.8) + sin(z * 1.8 / SCALE + time * 1.8) + sin(z * 2.8 / SCALE + time * 0.8)) / 3.0;
return y;
}
void main()
{
TexCoord = aTexCoord;
vec3 pos = aPos;
float strength = 1.0;
pos.y += strength * calculateSurface(pos.x, pos.z);
pos.y -= strength * calculateSurface(0.0, 0.0);
FragPos = vec3(view * model * vec4(pos, 1.0));
gl_Position = projection * view * model * vec4(pos, 1.0);
}
Fragment Shader:
#version 410 core
struct FogInfo{
float maxDist;
float minDist;
vec3 color;
};
in vec2 TexCoord;
in vec3 FragPos;
out vec4 FragColor;
uniform sampler2D text;
void main()
{
FogInfo f;
f.maxDist = 50.0;
f.minDist = 2.0;
f.color = vec3(0.4, 0.4, 0.4);
float dist = abs(FragPos.z);
float fogFactor = (f.maxDist - dist) / (f.maxDist - f.minDist);
fogFactor = clamp(fogFactor, 0.0, 1.0);
vec4 outputColor;
if(texture(text, TexCoord) != vec4(0.0)){
outputColor = mix(vec4(f.color, 1.0), texture(text, TexCoord), fogFactor);
}
else{
outputColor = vec4(0.8, 0.8, 0.8, 1.0);
}
FragColor = outputColor;
}
This is a parabola generated in a circular pattern. The cubes are spawning over a random vertex, hitting it, then disappearing when it hits the center. Finally the cube resets at another random vertex.
void CircularParabola::createLineFunc(std::shared_ptr<Shader> shaderProgram)
{
std::vector<GLuint> indices;
std::vector<glm::vec4> graphColor;
glm::mat4 model = glm::mat4(1.0f);
for (float i = 0; i < 360.0f; i += 360 / numLines) {
model = glm::rotate(model, glm::radians(360.0f / numLines), glm::vec3(0.0f, 1.0f, 0.0f));
for (float j = 0.0; j < numPoints / 10.0; j += 0.1) {
glm::vec4 vec = model * glm::vec4(j, lineFuncFormula(j), 0, 0); //update bottom function too
verts.push_back(glm::vec3(vec[0], vec[1], vec[2]));
graphColor.push_back(glm::vec4(0.0f, 0.0f, i * 2 / 100, 0.5f));
}
}
//all faces except the last one
for (int i = 0; i < verts.size() - (verts.size() / numLines); i += verts.size() / numLines) {
indices.push_back(numPoints + 1 + i);
indices.push_back(1 + i);
indices.push_back(i);
for (int j = 0; j < numPoints - 2; j++) {
indices.push_back(numPoints + 1 + j + i);
indices.push_back(2 + j + i);
indices.push_back(1 + j + i);
indices.push_back(numPoints + 2 + j + i);
indices.push_back(2 + j + i);
indices.push_back(numPoints + 1 + j + i);
}
}
//last face
int lastFaceStart = verts.size() - (verts.size() / numLines);
indices.push_back(1);
indices.push_back(1 + lastFaceStart);
indices.push_back(0);
for (int i = 0; i < numPoints - 2; i++) {
indices.push_back(1 + i);
indices.push_back(lastFaceStart + 2 + i);
indices.push_back(lastFaceStart + 1 + i);
indices.push_back(2 + i);
indices.push_back(lastFaceStart + 2 + i);
indices.push_back(1 + i);
}
std::shared_ptr<GeometricObject> line = std::make_shared<GeometricObject>(verts);
line->setColor(glm::vec4(0.0f, 0.0f, 0.8f, 0.8f));
line->indices = indices;
std::shared_ptr<SceneObject> list = std::make_shared<SceneObject>();
*list = { line, Scene::createVAO(line->vertexData, line->indices), model, shaderProgram, GL_TRIANGLES }
graphLines.push_back(list);
}
float CircularParabola::lineFuncFormula(float val)
{
return 0.01f * val * val;
}
glm::mat4 CircularParabola::resetCubePosition(std::shared_ptr<GeometricObject> cube)
{
glm::mat4 model(1.0f);
int randomVertIndex = 0;
int adjVertIndex;
while (randomVertIndex % numPoints == 0) {
randomVertIndex = rand() % verts.size();
}
adjVertIndex = randomVertIndex + numPoints;
if (adjVertIndex > verts.size()) {
adjVertIndex = randomVertIndex - (randomVertIndex / numPoints) * numPoints;
}
glm::vec3 center = verts[randomVertIndex] - glm::vec3(0.5f) * (verts[randomVertIndex] - verts[adjVertIndex]);
model = glm::mat4(1.0f);
model = glm::translate(model, center + glm::vec3(0.0f, 5.0f, 0.0f));
model = glm::scale(model, glm::vec3(1.0f));
cube->tragectory->addTarget(center, center + glm::vec3(0.0f, 5.0f, 0.0f));
cube->tragectory->addTarget(glm::vec3(0.0f, 1.0f, 0.0f), center);
return model;
}
void CircularParabola::createFallingCubes(std::shared_ptr<Shader> shaderProgram)
{
Material material{ glm::vec3(1.0f, 0.5f, 0.31f), glm::vec3(1.0f, 0.5f, .031f), glm::vec3(0.5f, 0.5f, 0.5f), 32.0f }
std::shared_ptr<SceneObject> list;
glm::mat4 model(1.0f);
std::shared_ptr<GeometricObject> cube = std::make_shared<Cube>(glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), material);
GLuint VAO = Scene::createVAO(cube->vertexData);
for (int i = 0; i < 10; i++) {
list.reset(new SceneObject());
cube.reset(new Cube(glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), material));
model = resetCubePosition(cube);
*list = { cube, VAO, model, shaderProgram, GL_TRIANGLES }
fallingCubes.push_back(list);
}
}
void CircularParabola::updateFallingCubes()
{
for (int i = 0; i < fallingCubes.size(); i++) {
fallingCubes[i]->model = fallingCubes[i]->object->tragectory->update() * fallingCubes[i]->model;
fallingCubes[i]->model = glm::rotate(fallingCubes[i]->model, glm::radians(1.0f), glm::vec3(0.4f, 0.3f, 0.6f));
if (fallingCubes[i]->object->tragectory->targetQueue.size() == 0) {
fallingCubes[i]->model = resetCubePosition(fallingCubes[i]->object);
}
}
}
This is a cube with a wooden crate with a metal frame texture using a green emission texture. There is a specular map used to causes specular reflection with the metal, but not the wooden part of the texture.
#version 410 core
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
struct Light {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
out vec4 FragColor;
in vec4 vertexColor;
in vec2 TexCoord;
in vec3 Normal;
in vec3 FragPos;
uniform sampler2D emissionMap;
uniform vec3 viewPos;
uniform Material material;
uniform Light light;
void main()
{
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoord));
vec3 unitNorm = normalize(Normal);
vec3 lightDir = normalize(light.position - FragPos);
float diffuseFactor = max(dot(unitNorm, lightDir), 0.0);
vec3 diffuse = light.diffuse * diffuseFactor * vec3(texture(material.diffuse, TexCoord));
float specularStrength = 0.5;
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, unitNorm);
float specFactor = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = light.specular * specFactor * vec3(texture(material.specular, TexCoord));
vec3 emission;
if(vec3(texture(material.specular, TexCoord)) == vec3(0.0)){
emission = texture(emissionMap, TexCoord).rgb;
}
else{
emission = vec3(0.0);
}
FragColor = vec4(ambient + diffuse + specular + emission, 1.0) * vertexColor;
}
Whenever the spectral value of any pixel is greater than 0, remove the emission texture
#version 410 core
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
struct Light {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
out vec4 FragColor;
in vec4 vertexColor;
in vec2 TexCoord;
in vec3 Normal;
in vec3 FragPos;
uniform sampler2D emissionMap;
uniform vec3 viewPos;
uniform Material material;
uniform Light light;
void main()
{
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoord));
vec3 unitNorm = normalize(Normal);
vec3 lightDir = normalize(light.position - FragPos);
float diffuseFactor = max(dot(unitNorm, lightDir), 0.0);
vec3 diffuse = light.diffuse * diffuseFactor * vec3(texture(material.diffuse, TexCoord));
float specularStrength = 0.5;
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, unitNorm);
float specFactor = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = light.specular * specFactor * vec3(texture(material.specular, TexCoord));
vec3 emission;
if(specular == vec3(0.0)){
emission = texture(emissionMap, TexCoord).rgb;
}
else{
emission = vec3(0.0);
}
FragColor = vec4(ambient + diffuse + specular + emission, 1.0) * vertexColor;
}