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 Bedienung über Keyboard :D
- WASD - WASD
- R & F für Hoch & Runter - 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 ## 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 model 2
file ../obj/chalkboard/Chalkboard.obj file ../obj/chalkboard/Chalkboard.obj
texture ../texture/chalkboard/Chalkboard.jpg texture ../texture/chalkboard/Chalkboard.jpg
texture2 ../texture/chalkboard/text.png
model 3 model 3
file ../obj/chalkboard/ChalkboardPoles.obj file ../obj/chalkboard/ChalkboardPoles.obj
@ -42,6 +43,12 @@ model 10
file ../obj/floor/Floor2.obj file ../obj/floor/Floor2.obj
texture ../texture/floor/Carpet.png 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 # # Reihe 1 #
# Platz 1 # # Platz 1 #
@ -1686,3 +1693,10 @@ rotateY 3.14159
rotateZ 0.0 rotateZ 0.0
translate 6.0 -0.8 -6.0 translate 6.0 -0.8 -6.0
parent 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) gcc -o $@ test.o $(OBJ) $(ALL_LIBS)
%Shader.c: %Shader.glsl %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 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 float shininess;
uniform vec4 ambientLight; uniform vec4 ambientLight;
uniform vec3 lightPosition; uniform vec3 lightPositions[2];
uniform float lightBrightness[2];
uniform vec4 lightColor; uniform vec4 lightColor;
uniform sampler2D textureSampler; uniform sampler2D textureSampler;
uniform bool useSecondaryTexture;
uniform bool useNormalMap;
uniform sampler2D secondaryTexture;
uniform sampler2D normalMap; uniform sampler2D normalMap;
@ -23,16 +30,35 @@ float emissionStrength = 0.0;
void main() { void main() {
vec4 color = vec4(texture(textureSampler, textureCoordinate).rgb, 1.0); 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)); 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); for (int i = 0; i < lightPositions.length(); i++) {
float specular = pow(max(dot(halfway, norm), 0.0), shininess); 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 = gl_FragColor =
// EMISSION // EMISSION
@ -42,8 +68,8 @@ void main() {
ambientLight * color + ambientLight * color +
// DIFFUSION // DIFFUSION
color * diff + color * sumDiffusion +
// SPECULAR // SPECULAR
specular * lightColor * color; sumSpecular * lightColor * color;
} }

View File

@ -45,14 +45,36 @@ int framesSinceUpdate = 0;
GLfloat step = 0.0f; GLfloat step = 0.0f;
const GLfloat pi = 3.14159f; 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 objectPosition = {0.0f, 0.0f, 0.0f};
vec3 cameraTravelPosition = {0.0f, 3.0f, 5.5f};
bool cameraTraveling = true;
GLfloat radius = 1.0f; GLfloat radius = 1.0f;
mat4 viewingTransformation; mat4 viewingTransformation;
// Define a global scene graph root node // Define a global scene graph root node
SceneNode* rootNode; 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. * Input handler for camera movement.
* */ * */
@ -61,37 +83,42 @@ void handleInputs(double deltaTime) {
assert(window != NULL); assert(window != NULL);
if (glfwGetKey(window, GLFW_KEY_1) == GLFW_PRESS) { 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) { 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) { 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) { 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) { 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) { if (glfwGetKey(window, GLFW_KEY_6) == GLFW_PRESS) {
cameraPosition.z += deltaTime * 10; travelCamera((vec3){3.574698f, 0.966039f, 3.852249f});
} }
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) { if (!cameraTraveling) {
cameraPosition.z -= deltaTime * 10; if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
} cameraPosition.z += deltaTime * 10;
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) { }
cameraPosition.x += deltaTime * 10; if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
} cameraPosition.z -= deltaTime * 10;
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) { }
cameraPosition.x -= deltaTime * 10; if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
} cameraPosition.x += deltaTime * 10;
if (glfwGetKey(window, GLFW_KEY_F) == GLFW_PRESS) { }
cameraPosition.y += deltaTime * 10; if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
} cameraPosition.x -= deltaTime * 10;
if (glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS) { }
cameraPosition.y -= 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); SceneNode* chalkboard = findNodeByName("myChalkboard1", rootNode);
@ -121,13 +148,13 @@ void handleInputs(double deltaTime) {
if (glfwGetKey(window, GLFW_KEY_J) == GLFW_PRESS) { if (glfwGetKey(window, GLFW_KEY_J) == GLFW_PRESS) {
objectPosition.x -= deltaTime * 10; objectPosition.x -= deltaTime * 10;
} }
if (glfwGetKey(window, GLFW_KEY_I) == GLFW_PRESS) { if (glfwGetKey(window, GLFW_KEY_I) == GLFW_PRESS) {
objectPosition.z += deltaTime * 10; objectPosition.z += deltaTime * 10;
} }
if (glfwGetKey(window, GLFW_KEY_K) == GLFW_PRESS) { if (glfwGetKey(window, GLFW_KEY_K) == GLFW_PRESS) {
objectPosition.z -= deltaTime * 10; objectPosition.z -= deltaTime * 10;
} }
if (glfwGetKey(window, GLFW_KEY_O) == GLFW_PRESS) { if (glfwGetKey(window, GLFW_KEY_O) == GLFW_PRESS) {
radius += deltaTime * 10; radius += deltaTime * 10;
} }
if (glfwGetKey(window, GLFW_KEY_U) == GLFW_PRESS) { 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); glUniformMatrix3fv(glGetUniformLocation(program, "normalModelView"), 1, GL_FALSE, (GLfloat*)&normalModelView);
// SET MATERIAL DATA // SET MATERIAL DATA
glUniform1f(glGetUniformLocation(program, "shininess"), 60.0f * 4.0f); glUniform1f(glGetUniformLocation(program, "shininess"), node->model->shininess * 4.0f);
// BIND TEXTURES // BIND TEXTURES
@ -176,10 +203,29 @@ void renderNode(SceneNode* node) {
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, node->model->texture); glBindTexture(GL_TEXTURE_2D, node->model->texture);
// textureLocation = glGetUniformLocation(program, "normalMap"); if (node->model->secondaryTexture != -1) {
// glUniform1i(textureLocation, 4);
// glActiveTexture(GL_TEXTURE4); glUniform1i(glGetUniformLocation(program, "useSecondaryTexture"), 1);
// glBindTexture(GL_TEXTURE_2D, textures[NORMAL]);
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); draw_object(node->model->objectData);
} }
@ -251,7 +297,7 @@ void init(void) {
void updateStats() { void updateStats() {
printf("\rFPS: %.1f", framesSinceUpdate / timeSinceUpdate); 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); fflush(stdout);
} }
@ -260,6 +306,8 @@ void updateStats() {
*/ */
void draw(void) { void draw(void) {
handleCameraTravel();
// FPS Counter // FPS Counter
framesSinceUpdate++; framesSinceUpdate++;
double deltaTime = glfwGetTime(); double deltaTime = glfwGetTime();
@ -302,7 +350,7 @@ void draw(void) {
// -------------- PROJECTION TRANSFORMATION ---------------- // -------------- PROJECTION TRANSFORMATION ----------------
mat4 projectionTransformation; mat4 projectionTransformation;
GLfloat near = 0.1f; GLfloat near = 0.1f;
GLfloat far = 20.0f; GLfloat far = 40.0f;
perspectiveProjection(&projectionTransformation, near, far); perspectiveProjection(&projectionTransformation, near, far);
// -------------- NORMALISATION TRANSFORMATION ------------- // -------------- NORMALISATION TRANSFORMATION -------------
@ -318,13 +366,17 @@ void draw(void) {
glUniformMatrix4fv(glGetUniformLocation(program, "projection"), 1, GL_FALSE, (GLfloat*)&projection); glUniformMatrix4fv(glGetUniformLocation(program, "projection"), 1, GL_FALSE, (GLfloat*)&projection);
// SET LIGHT DATA // 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); 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}; vec4 lightPosition = {cos(stepi) * 5.0f, 5.0f, sin(stepi) * 5.0f, 1.0f};
multiplyAny((GLfloat*)&lightPosition, (GLfloat*)&viewingTransformation, (GLfloat*)&lightPosition, 4, 4, 1); 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); renderSceneNode(rootNode);

View File

@ -19,6 +19,9 @@
#define KEYWORD_DEFINE_OBJ_FILE "file" #define KEYWORD_DEFINE_OBJ_FILE "file"
#define KEYWORD_DEFINE_TEXTURE_FILE "texture" #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_USE_MODEL "use"
#define KEYWORD_DEFINE_PARENT "parent" #define KEYWORD_DEFINE_PARENT "parent"
@ -99,7 +102,7 @@ void loadTexture(char* textureFile, GLuint* texture) {
glBindTexture(GL_TEXTURE_2D, *texture); glBindTexture(GL_TEXTURE_2D, *texture);
printf("%s - %d\n", textureFile, nrChannels); 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 ----- ^^^^^^ // load texture using previously determined format ----- ^^^^^^
glGenerateMipmap(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D);
@ -196,6 +199,11 @@ SceneNode* loadSceneGraphFromFile(char* path) {
if (strcmp(keyword, KEYWORD_DEFINE_MODEL) == 0) { if (strcmp(keyword, KEYWORD_DEFINE_MODEL) == 0) {
sscanf(buf, KEYWORD_DEFINE_MODEL " %d", &currentModel); 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; continue;
} }
if (strcmp(keyword, KEYWORD_DEFINE_OBJ_FILE) == 0) { if (strcmp(keyword, KEYWORD_DEFINE_OBJ_FILE) == 0) {
@ -208,6 +216,20 @@ SceneNode* loadSceneGraphFromFile(char* path) {
loadTexture(filepathBuffer, &models[currentModel].texture); loadTexture(filepathBuffer, &models[currentModel].texture);
continue; 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) { if (strcmp(keyword, KEYWORD_DEFINE_NODE) == 0) {

View File

@ -14,6 +14,9 @@ typedef struct SceneNode SceneNode;
typedef struct { typedef struct {
ObjectData* objectData; ObjectData* objectData;
GLuint texture; GLuint texture;
GLuint secondaryTexture;
GLuint normalMap;
GLfloat shininess;
} Model; } Model;
struct SceneNode { 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