diff --git a/26-geometry-shaders/config.json b/26-geometry-shaders/config.json index 5fa8ece..4bf8839 100644 --- a/26-geometry-shaders/config.json +++ b/26-geometry-shaders/config.json @@ -1,20 +1,24 @@ { "scene": { "shader": { - "vertex_path": "shaders/21-framebuffers.vert.glsl", - "frag_path": "shaders/21-framebuffers.frag.glsl" + "vertex_path": "shaders/26-framebuffers.vert.glsl", + "frag_path": "shaders/26-framebuffers.frag.glsl", + "geometry_path": "shaders/26-geometry.glsl" }, "reflect_shader": { "vertex_path": "shaders/24-vert.glsl", - "frag_path": "shaders/24-frag.glsl" + "frag_path": "shaders/24-frag.glsl", + "geometry_path": "" }, "screen_shader": { "vertex_path": "shaders/21-screen.vert.glsl", - "frag_path": "shaders/21-screen.frag.glsl" + "frag_path": "shaders/21-screen.frag.glsl", + "geometry_path": "" }, "skybox_shader": { "vertex_path": "shaders/24-skybox.vert.glsl", - "frag_path": "shaders/24-skybox.frag.glsl" + "frag_path": "shaders/24-skybox.frag.glsl", + "geometry_path": "" }, "skybox_faces": [ "../assets/skybox/sky/right.jpg", diff --git a/26-geometry-shaders/shaders/26-frag.glsl b/26-geometry-shaders/shaders/26-frag.glsl new file mode 100644 index 0000000..44b8a3d --- /dev/null +++ b/26-geometry-shaders/shaders/26-frag.glsl @@ -0,0 +1,17 @@ +#version 330 core +out vec4 FragColor; + +in vec3 Normal; +in vec3 FragPos; +in vec2 TexCoords; + +uniform vec3 cameraPos; +uniform samplerCube skybox; + +void main() +{ + float ratio = 1.0/1.52; + vec3 I = normalize(FragPos - cameraPos); + vec3 R = refract(I, normalize(Normal), ratio); + FragColor = vec4(texture(skybox, R).rgb, 1.0); +} diff --git a/26-geometry-shaders/shaders/26-framebuffers.frag.glsl b/26-geometry-shaders/shaders/26-framebuffers.frag.glsl new file mode 100644 index 0000000..4b161b8 --- /dev/null +++ b/26-geometry-shaders/shaders/26-framebuffers.frag.glsl @@ -0,0 +1,11 @@ +#version 330 core +out vec4 FragColor; + +in vec2 TexCoords; + +uniform sampler2D texture1; + +void main() +{ + FragColor = texture(texture1, TexCoords); +} diff --git a/26-geometry-shaders/shaders/26-framebuffers.vert.glsl b/26-geometry-shaders/shaders/26-framebuffers.vert.glsl new file mode 100644 index 0000000..6e66946 --- /dev/null +++ b/26-geometry-shaders/shaders/26-framebuffers.vert.glsl @@ -0,0 +1,23 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; + +out vec3 FragPos; +out vec3 Normal; + +out VS_OUT { + vec2 texCoords; +} vs_out; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +void main() +{ + gl_Position = projection * view * model * vec4(aPos, 1.0); + FragPos = vec3(model * vec4(aPos, 1.0)); + Normal = mat3(transpose(inverse(model))) * aNormal; + vs_out.texCoords = aTexCoords; +} diff --git a/26-geometry-shaders/shaders/26-geometry.glsl b/26-geometry-shaders/shaders/26-geometry.glsl new file mode 100644 index 0000000..b15fe36 --- /dev/null +++ b/26-geometry-shaders/shaders/26-geometry.glsl @@ -0,0 +1,40 @@ +#version 330 core +layout (triangles) in; +layout (triangle_strip, max_vertices = 3) out; + +in VS_OUT { + vec2 texCoords; +} gs_in[]; + +out vec2 TexCoords; + +uniform float time; + +vec4 explode(vec4 position, vec3 normal) +{ + float magnitude = 2.0; + vec3 direction = normal * ((sin(time) + 1.0) / 2.0) * magnitude; + return position + vec4(direction, 0.0); +} + +vec3 GetNormal() +{ + vec3 a = vec3(gl_in[0].gl_Position) - vec3(gl_in[1].gl_Position); + vec3 b = vec3(gl_in[2].gl_Position) - vec3(gl_in[1].gl_Position); + return normalize(cross(a, b)); +} + +void main() { + vec3 normal = GetNormal(); + + gl_Position = explode(gl_in[0].gl_Position, normal); + TexCoords = gs_in[0].texCoords; + EmitVertex(); + gl_Position = explode(gl_in[1].gl_Position, normal); + TexCoords = gs_in[1].texCoords; + EmitVertex(); + gl_Position = explode(gl_in[2].gl_Position, normal); + TexCoords = gs_in[2].texCoords; + EmitVertex(); + EndPrimitive(); +} diff --git a/26-geometry-shaders/shaders/26-vert.glsl b/26-geometry-shaders/shaders/26-vert.glsl new file mode 100644 index 0000000..2df21b0 --- /dev/null +++ b/26-geometry-shaders/shaders/26-vert.glsl @@ -0,0 +1,21 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; + +out vec3 FragPos; +out vec3 Normal; +out vec2 TexCoords; +out vec3 Position; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +void main() +{ + Normal = mat3(transpose(inverse(model))) * aNormal; + FragPos = vec3(model * vec4(aPos, 1.0)); + gl_Position = projection * view * vec4(FragPos, 1.0); + TexCoords = aTexCoords; +} diff --git a/26-geometry-shaders/src/components.hpp b/26-geometry-shaders/src/components.hpp index 61ba43b..8b1d4cc 100644 --- a/26-geometry-shaders/src/components.hpp +++ b/26-geometry-shaders/src/components.hpp @@ -5,8 +5,8 @@ #include #include "json.hpp" -const unsigned int SCR_WIDTH = 800; -const unsigned int SCR_HEIGHT = 600; +const unsigned int SCR_WIDTH = 1792; +const unsigned int SCR_HEIGHT = 1008; #define MAX_LIGHTS 4 @@ -96,9 +96,10 @@ namespace components { struct Shader { std::string vertex_path; std::string frag_path; + std::string geometry_path; }; - ENROLL_COMPONENT(Shader, vertex_path, frag_path); + ENROLL_COMPONENT(Shader, vertex_path, frag_path, geometry_path); struct Scene { components::Shader shader; diff --git a/26-geometry-shaders/src/scene.cpp b/26-geometry-shaders/src/scene.cpp index 369fbbe..2adfcfb 100644 --- a/26-geometry-shaders/src/scene.cpp +++ b/26-geometry-shaders/src/scene.cpp @@ -50,6 +50,7 @@ void Scene::render(GLFWwindow* window) { with_shader.setMat4("view", view); with_shader.setMat4("projection", projection); with_shader.setVec3("cameraPos", camera.position); + with_shader.setFloat("time", glfwGetTime()); for(auto& thing : things) { draw_thing(with_shader, thing); diff --git a/26-geometry-shaders/src/scene.hpp b/26-geometry-shaders/src/scene.hpp index ffc3ac2..5ea9073 100644 --- a/26-geometry-shaders/src/scene.hpp +++ b/26-geometry-shaders/src/scene.hpp @@ -46,11 +46,11 @@ struct Scene { bool reflect_on = false; Scene(components::Scene& config): - shader{config.shader.vertex_path, config.shader.frag_path}, - reflect_shader{config.reflect_shader.vertex_path, config.reflect_shader.frag_path}, - skybox_shader{config.skybox_shader.vertex_path, config.skybox_shader.frag_path}, + shader{config.shader}, + reflect_shader{config.reflect_shader}, + skybox_shader{config.skybox_shader}, skybox_faces{config.skybox_faces}, - screen{.shader={config.screen_shader.vertex_path, config.screen_shader.frag_path}}, + screen{.shader={config.screen_shader}}, materials{config.materials}, camera{ .position=config.camera.position, diff --git a/26-geometry-shaders/src/shader.cpp b/26-geometry-shaders/src/shader.cpp index e965c61..0203296 100644 --- a/26-geometry-shaders/src/shader.cpp +++ b/26-geometry-shaders/src/shader.cpp @@ -61,19 +61,33 @@ unsigned int Shader::load_shader(const std::string& filename, GLenum shader_type return shader_id; } -Shader::Shader(const std::string& vertexPath, const std::string& fragmentPath) { - unsigned int vertex = load_shader(vertexPath, GL_VERTEX_SHADER); - unsigned int fragment = load_shader(fragmentPath, GL_FRAGMENT_SHADER); + +Shader::Shader(components::Shader config) { + dbc::log($F("Loading shaders vert={}, frag={}, geom={}", config.vertex_path, config.frag_path, config.geometry_path)); + + unsigned int vertex = load_shader(config.vertex_path, GL_VERTEX_SHADER); + unsigned int fragment = load_shader(config.frag_path, GL_FRAGMENT_SHADER); + unsigned int geometry = UINT_MAX; ID = glCreateProgram(); + dbc::log($F("Created shader program ID: {}", ID)); glAttachShader(ID, vertex); glAttachShader(ID, fragment); - glLinkProgram(ID); + if(config.geometry_path != "") { + geometry = load_shader(config.geometry_path, GL_GEOMETRY_SHADER); + glAttachShader(ID, geometry); + } + + glLinkProgram(ID); check_error("link", ID, GL_LINK_STATUS); glDeleteShader(vertex); glDeleteShader(fragment); + + if(config.geometry_path != "") { + glDeleteShader(geometry); + } } void Shader::use() const { diff --git a/26-geometry-shaders/src/shader.hpp b/26-geometry-shaders/src/shader.hpp index 594dd0d..a7c26bc 100644 --- a/26-geometry-shaders/src/shader.hpp +++ b/26-geometry-shaders/src/shader.hpp @@ -16,7 +16,8 @@ class Shader public: unsigned int ID = UINT_MAX; - Shader(const std::string& vertexPath, const std::string& fragmentPath); + Shader(components::Shader config); + unsigned int load_shader(const std::string& filename, GLenum shader_type); void use() const; void setBool(const std::string &name, bool value) const; diff --git a/26-geometry-shaders/tests/model_tests.cpp b/26-geometry-shaders/tests/model_tests.cpp index 54b159d..cecaca8 100644 --- a/26-geometry-shaders/tests/model_tests.cpp +++ b/26-geometry-shaders/tests/model_tests.cpp @@ -11,7 +11,7 @@ using namespace fuc2; */ namespace model_tests { void test_load_textures() { - Shader shader{"shaders/14-vert.glsl", "shaders/14-frag.glsl"}; + Shader shader({"shaders/14-vert.glsl", "shaders/14-frag.glsl", ""}); Model popcorn{"assets", "popcorn_model_a.glb"}; popcorn.draw(shader); diff --git a/26-geometry-shaders/tests/shader_tests.cpp b/26-geometry-shaders/tests/shader_tests.cpp index 270b921..a56bfd3 100644 --- a/26-geometry-shaders/tests/shader_tests.cpp +++ b/26-geometry-shaders/tests/shader_tests.cpp @@ -7,7 +7,7 @@ using namespace fuc2; namespace shader_tests { void test_load_shaders() { - Shader shader("shaders/3.3.shader.vs", "shaders/3.3.shader.fs"); + Shader shader({"shaders/3.3.shader.vs", "shaders/3.3.shader.fs", ""}); shader.use(); @@ -16,7 +16,7 @@ namespace shader_tests { void test_compile_fail() { auto runner = [&]() { - Shader shader("tests/bad_shader.vs", "shaders/3.3.shader.fs"); + Shader shader({"tests/bad_shader.vs", "shaders/3.3.shader.fs", ""}); }; BLOWS_UP(runner, "compile fail should blow up");