Merge branch 'multiple-lights'

This commit is contained in:
Luca Conte 2024-06-24 15:30:36 +02:00
commit c7744cce2e
12 changed files with 211 additions and 45 deletions

View File

@ -24,7 +24,11 @@ $ make run
Bedienung über Keyboard :D
- WASD
- R & F für Hoch & Runter
- 1,2,3,4,5 für Verschiedene Kamerapositionen
- 1,2,3,4,5,6 für Verschiedene Kamerapositionen
- 1: Vor den Tafeln
- 2-4: Verschiedene Sitzplätze
- 5: Vogelperspektive
- 6: Close-Up vom Normal Map Demo Cube
## TODO LIST

45
obj/cube/cube.obj Normal file
View File

@ -0,0 +1,45 @@
# Blender v3.0.1 OBJ File: ''
# www.blender.org
o Cube_Cube.001
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 0.000000
vt 0.000000 1.000000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
usemtl None
s off
f 1/1/1 2/2/1 4/3/1 3/4/1
f 3/5/2 4/6/2 8/7/2 7/8/2
f 7/9/3 8/10/3 6/11/3 5/12/3
f 5/13/4 6/14/4 2/15/4 1/16/4
f 3/5/5 7/17/5 5/18/5 1/16/5
f 8/19/6 4/6/6 2/15/6 6/20/6

View File

@ -9,6 +9,7 @@ texture ../texture/chair/chair_texture.png
model 2
file ../obj/chalkboard/Chalkboard.obj
texture ../texture/chalkboard/Chalkboard.jpg
texture2 ../texture/chalkboard/text.png
model 3
file ../obj/chalkboard/ChalkboardPoles.obj
@ -42,6 +43,12 @@ model 10
file ../obj/floor/Floor2.obj
texture ../texture/floor/Carpet.png
model 11
file ../obj/cube/cube.obj
texture ../texture/crate/texture.jpg
normal ../texture/crate/normal.jpg
shininess 100
# Reihe 1 #
# Platz 1 #
@ -1686,3 +1693,10 @@ rotateY 3.14159
rotateZ 0.0
translate 6.0 -0.8 -6.0
parent 0
# Normal Map Crate
obj 1000
use 11
name normalMapCrate
scale 0.5 0.5 0.5
translate 3.0 0.0 3.0

View File

@ -15,7 +15,7 @@ test.out: test.o $(OBJ)
gcc -o $@ test.o $(OBJ) $(ALL_LIBS)
%Shader.c: %Shader.glsl
xxd -i $? > $@
xxd -i $? | tac | sed "3s/$$/, 0x00/" | tac > $@
main.o: $(SHADERS) matrixMath.h transformation.h wavefrontobj.h sceneGraph.h objectHandler.h shader.h

View File

@ -10,10 +10,17 @@ flat in mat3 TBN;
uniform float shininess;
uniform vec4 ambientLight;
uniform vec3 lightPosition;
uniform vec3 lightPositions[2];
uniform float lightBrightness[2];
uniform vec4 lightColor;
uniform sampler2D textureSampler;
uniform bool useSecondaryTexture;
uniform bool useNormalMap;
uniform sampler2D secondaryTexture;
uniform sampler2D normalMap;
@ -23,16 +30,35 @@ float emissionStrength = 0.0;
void main() {
vec4 color = vec4(texture(textureSampler, textureCoordinate).rgb, 1.0);
vec3 norm = normalize(normal);
if (useSecondaryTexture) {
vec4 secondColor = texture(secondaryTexture, textureCoordinate).rgba;
color = vec4(color.rgb * (1 - secondColor.a) + secondColor.rgb * secondColor.a, min(color.a + secondColor.a, 1.0));
}
vec3 lightDir = normalize(lightPosition - fragmentPosition);
vec3 norm;
vec3 eyeDir = (-normalize(fragmentPosition));
if (useNormalMap) {
norm = normalize((texture(normalMap, textureCoordinate).xyz * 2 - vec3(1,1,1)));
eyeDir = TBN * eyeDir;
} else {
norm = normalize(normal);
}
float diff = max(dot(norm, lightDir), 0.0);
float sumDiffusion = 0;
float sumSpecular = 0;
vec3 halfway = (lightDir + eyeDir) / length(lightDir + eyeDir);
float specular = pow(max(dot(halfway, norm), 0.0), shininess);
for (int i = 0; i < lightPositions.length(); i++) {
vec3 lightDir = normalize(lightPositions[i] - fragmentPosition);
if (useNormalMap) {
lightDir = TBN * lightDir;
}
sumDiffusion += max(dot(norm, lightDir), 0.0) * lightBrightness[i];
vec3 halfway = (lightDir + eyeDir) / length(lightDir + eyeDir);
sumSpecular += pow(max(dot(halfway, norm), 0.0), shininess);
}
gl_FragColor =
// EMISSION
@ -42,8 +68,8 @@ void main() {
ambientLight * color +
// DIFFUSION
color * diff +
color * sumDiffusion +
// SPECULAR
specular * lightColor * color;
sumSpecular * lightColor * color;
}

View File

@ -45,14 +45,36 @@ int framesSinceUpdate = 0;
GLfloat step = 0.0f;
const GLfloat pi = 3.14159f;
vec3 cameraPosition = {0.0f, 3.0f, 5.5f};
vec3 cameraPosition = {0.0f, 2.0f, 1.0f};
vec3 objectPosition = {0.0f, 0.0f, 0.0f};
vec3 cameraTravelPosition = {0.0f, 3.0f, 5.5f};
bool cameraTraveling = true;
GLfloat radius = 1.0f;
mat4 viewingTransformation;
// Define a global scene graph root node
SceneNode* rootNode;
void handleCameraTravel() {
if (cameraTraveling) {
vec3 delta;
vec3Subtract(&delta, &cameraTravelPosition, &cameraPosition);
if (vec3Length(&delta) < 0.0001) cameraTraveling = false;
vec3Multiply(&delta, &delta, 0.1);
vec3Add(&cameraPosition, &cameraPosition, &delta);
}
}
void travelCamera(vec3 newPosition) {
cameraTravelPosition = newPosition;
cameraTraveling = true;
}
/**
* Input handler for camera movement.
* */
@ -61,37 +83,42 @@ void handleInputs(double deltaTime) {
assert(window != NULL);
if (glfwGetKey(window, GLFW_KEY_1) == GLFW_PRESS) {
cameraPosition = (vec3){0.0f, 1.7f, 2.4f};
travelCamera((vec3){0.0f, 1.7f, 2.4f});
}
if (glfwGetKey(window, GLFW_KEY_2) == GLFW_PRESS) {
cameraPosition = (vec3){3.3f, 3.4f, -11.0f};
travelCamera((vec3){3.3f, 3.4f, -11.0f});
}
if (glfwGetKey(window, GLFW_KEY_3) == GLFW_PRESS) {
cameraPosition = (vec3){-3.0f, 2.9f, -7.5f};
travelCamera((vec3){-3.0f, 2.9f, -7.5f});
}
if (glfwGetKey(window, GLFW_KEY_4) == GLFW_PRESS) {
cameraPosition = (vec3){-0.6f, 2.1f, -4.5f};
travelCamera((vec3){-0.6f, 2.1f, -4.5f});
}
if (glfwGetKey(window, GLFW_KEY_5) == GLFW_PRESS) {
cameraPosition = (vec3){-10.6f, 22.1f, -4.5f};
travelCamera((vec3){-10.6f, 22.1f, -4.5f});
}
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
cameraPosition.z += deltaTime * 10;
if (glfwGetKey(window, GLFW_KEY_6) == GLFW_PRESS) {
travelCamera((vec3){3.574698f, 0.966039f, 3.852249f});
}
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
cameraPosition.z -= deltaTime * 10;
}
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
cameraPosition.x += deltaTime * 10;
}
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
cameraPosition.x -= deltaTime * 10;
}
if (glfwGetKey(window, GLFW_KEY_F) == GLFW_PRESS) {
cameraPosition.y += deltaTime * 10;
}
if (glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS) {
cameraPosition.y -= deltaTime * 10;
if (!cameraTraveling) {
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
cameraPosition.z += deltaTime * 10;
}
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
cameraPosition.z -= deltaTime * 10;
}
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
cameraPosition.x += deltaTime * 10;
}
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
cameraPosition.x -= deltaTime * 10;
}
if (glfwGetKey(window, GLFW_KEY_F) == GLFW_PRESS) {
cameraPosition.y += deltaTime * 10;
}
if (glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS) {
cameraPosition.y -= deltaTime * 10;
}
}
SceneNode* chalkboard = findNodeByName("myChalkboard1", rootNode);
@ -121,13 +148,13 @@ void handleInputs(double deltaTime) {
if (glfwGetKey(window, GLFW_KEY_J) == GLFW_PRESS) {
objectPosition.x -= deltaTime * 10;
}
if (glfwGetKey(window, GLFW_KEY_I) == GLFW_PRESS) {
if (glfwGetKey(window, GLFW_KEY_I) == GLFW_PRESS) {
objectPosition.z += deltaTime * 10;
}
if (glfwGetKey(window, GLFW_KEY_K) == GLFW_PRESS) {
objectPosition.z -= deltaTime * 10;
}
if (glfwGetKey(window, GLFW_KEY_O) == GLFW_PRESS) {
if (glfwGetKey(window, GLFW_KEY_O) == GLFW_PRESS) {
radius += deltaTime * 10;
}
if (glfwGetKey(window, GLFW_KEY_U) == GLFW_PRESS) {
@ -166,7 +193,7 @@ void renderNode(SceneNode* node) {
glUniformMatrix3fv(glGetUniformLocation(program, "normalModelView"), 1, GL_FALSE, (GLfloat*)&normalModelView);
// SET MATERIAL DATA
glUniform1f(glGetUniformLocation(program, "shininess"), 60.0f * 4.0f);
glUniform1f(glGetUniformLocation(program, "shininess"), node->model->shininess * 4.0f);
// BIND TEXTURES
@ -176,10 +203,29 @@ void renderNode(SceneNode* node) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, node->model->texture);
// textureLocation = glGetUniformLocation(program, "normalMap");
// glUniform1i(textureLocation, 4);
// glActiveTexture(GL_TEXTURE4);
// glBindTexture(GL_TEXTURE_2D, textures[NORMAL]);
if (node->model->secondaryTexture != -1) {
glUniform1i(glGetUniformLocation(program, "useSecondaryTexture"), 1);
glUniform1i(glGetUniformLocation(program, "secondaryTexture"), 1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, node->model->secondaryTexture);
} else {
glUniform1i(glGetUniformLocation(program, "useSecondaryTexture"), 0);
}
if (node->model->normalMap != -1) {
glUniform1i(glGetUniformLocation(program, "useNormalMap"), 1);
glUniform1i(glGetUniformLocation(program, "normalMap"), 2);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, node->model->normalMap);
} else {
glUniform1i(glGetUniformLocation(program, "useNormalMap"), 0);
}
draw_object(node->model->objectData);
}
@ -251,7 +297,7 @@ void init(void) {
void updateStats() {
printf("\rFPS: %.1f", framesSinceUpdate / timeSinceUpdate);
printf(" - Camera Position: [%f, %f, %f]", cameraPosition.x, cameraPosition.y, cameraPosition.z);
printf(" - Camera Position: [%f, %f, %f] - Traveling: %s ", cameraPosition.x, cameraPosition.y, cameraPosition.z, cameraTraveling ? "true" : "false");
fflush(stdout);
}
@ -260,6 +306,8 @@ void updateStats() {
*/
void draw(void) {
handleCameraTravel();
// FPS Counter
framesSinceUpdate++;
double deltaTime = glfwGetTime();
@ -302,7 +350,7 @@ void draw(void) {
// -------------- PROJECTION TRANSFORMATION ----------------
mat4 projectionTransformation;
GLfloat near = 0.1f;
GLfloat far = 20.0f;
GLfloat far = 40.0f;
perspectiveProjection(&projectionTransformation, near, far);
// -------------- NORMALISATION TRANSFORMATION -------------
@ -318,13 +366,17 @@ void draw(void) {
glUniformMatrix4fv(glGetUniformLocation(program, "projection"), 1, GL_FALSE, (GLfloat*)&projection);
// SET LIGHT DATA
glUniform4f(glGetUniformLocation(program, "lightColor"), 1.0f, 1.0f, 1.0f, 1.0f);
glUniform4f(glGetUniformLocation(program, "lightColor"), 0.2f, 0.2f, 0.2f, 0.5f);
glUniform4f(glGetUniformLocation(program, "ambientLight"), 0.05f, 0.05f, 0.05f, 1.0f);
vec4 lightPosition = {cos(stepi) * 5.0f, 5.0f, sin(stepi) * 5.0f, 1.0f};
multiplyAny((GLfloat*)&lightPosition, (GLfloat*)&viewingTransformation, (GLfloat*)&lightPosition, 4, 4, 1);
glUniform3f(glGetUniformLocation(program, "lightPosition"), lightPosition.x, lightPosition.y, lightPosition.z);
glUniform3f(glGetUniformLocation(program, "lightPositions[0]"), lightPosition.x, lightPosition.y, lightPosition.z);
glUniform3f(glGetUniformLocation(program, "lightPositions[1]"), -lightPosition.x, lightPosition.y, -lightPosition.z);
glUniform1f(glGetUniformLocation(program, "lightBrightness[0]"), 0.5f);
glUniform1f(glGetUniformLocation(program, "lightBrightness[1]"), 0.5f);
renderSceneNode(rootNode);

View File

@ -19,6 +19,9 @@
#define KEYWORD_DEFINE_OBJ_FILE "file"
#define KEYWORD_DEFINE_TEXTURE_FILE "texture"
#define KEYWORD_DEFINE_SECONDARY_TEXTURE_FILE "texture2"
#define KEYWORD_DEFINE_NORMAL_MAP_FILE "normal"
#define KEYWORD_DEFINE_SHININESS "shininess"
#define KEYWORD_USE_MODEL "use"
#define KEYWORD_DEFINE_PARENT "parent"
@ -99,7 +102,7 @@ void loadTexture(char* textureFile, GLuint* texture) {
glBindTexture(GL_TEXTURE_2D, *texture);
printf("%s - %d\n", textureFile, nrChannels);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, format, GL_UNSIGNED_BYTE, image);
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, image);
// load texture using previously determined format ----- ^^^^^^
glGenerateMipmap(GL_TEXTURE_2D);
@ -196,6 +199,11 @@ SceneNode* loadSceneGraphFromFile(char* path) {
if (strcmp(keyword, KEYWORD_DEFINE_MODEL) == 0) {
sscanf(buf, KEYWORD_DEFINE_MODEL " %d", &currentModel);
models[currentModel].objectData = NULL;
models[currentModel].texture = -1;
models[currentModel].secondaryTexture = -1;
models[currentModel].normalMap = -1;
models[currentModel].shininess = 10.0f;
continue;
}
if (strcmp(keyword, KEYWORD_DEFINE_OBJ_FILE) == 0) {
@ -208,6 +216,20 @@ SceneNode* loadSceneGraphFromFile(char* path) {
loadTexture(filepathBuffer, &models[currentModel].texture);
continue;
}
if (strcmp(keyword, KEYWORD_DEFINE_SECONDARY_TEXTURE_FILE) == 0) {
sscanf(buf, KEYWORD_DEFINE_SECONDARY_TEXTURE_FILE " %s", filepathBuffer);
loadTexture(filepathBuffer, &models[currentModel].secondaryTexture);
continue;
}
if (strcmp(keyword, KEYWORD_DEFINE_NORMAL_MAP_FILE) == 0) {
sscanf(buf, KEYWORD_DEFINE_NORMAL_MAP_FILE " %s", filepathBuffer);
loadTexture(filepathBuffer, &models[currentModel].normalMap);
continue;
}
if (strcmp(keyword, KEYWORD_DEFINE_SHININESS) == 0) {
sscanf(buf, KEYWORD_DEFINE_SHININESS " %f", &models[currentModel].shininess);
continue;
}
if (strcmp(keyword, KEYWORD_DEFINE_NODE) == 0) {

View File

@ -14,6 +14,9 @@ typedef struct SceneNode SceneNode;
typedef struct {
ObjectData* objectData;
GLuint texture;
GLuint secondaryTexture;
GLuint normalMap;
GLfloat shininess;
} Model;
struct SceneNode {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 25 KiB

BIN
texture/chalkboard/text.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

BIN
texture/crate/normal.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

BIN
texture/crate/texture.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB