diff --git a/BaseGLProject/BaseGLProject.vcxproj b/BaseGLProject/BaseGLProject.vcxproj index 086a1b7..6e687b5 100644 --- a/BaseGLProject/BaseGLProject.vcxproj +++ b/BaseGLProject/BaseGLProject.vcxproj @@ -197,8 +197,12 @@ + + + + diff --git a/BaseGLProject/BaseGLProject.vcxproj.filters b/BaseGLProject/BaseGLProject.vcxproj.filters index e3cd1e0..1ea1d8b 100644 --- a/BaseGLProject/BaseGLProject.vcxproj.filters +++ b/BaseGLProject/BaseGLProject.vcxproj.filters @@ -223,6 +223,18 @@ MankyuCode + + Shaders + + + Shaders + + + Shaders + + + Shaders + diff --git a/BaseGLProject/Multipass.cpp b/BaseGLProject/Multipass.cpp index c41e2ff..924fa0d 100644 --- a/BaseGLProject/Multipass.cpp +++ b/BaseGLProject/Multipass.cpp @@ -1,8 +1,8 @@ #include "Multipass.h" -Multipass::Multipass() : shader("textureViewer.vert", "textureViewer.frag") +Multipass::Multipass() { - + shader = new Shader("textureViewer.vert", "textureViewer.frag"); _draw_buffers_size = 0; glGenFramebuffers(1, &_fboId); glBindFramebuffer(GL_FRAMEBUFFER, _fboId); @@ -36,12 +36,15 @@ Multipass::~Multipass() } void Multipass::addTexture(const std::string & tex_name, GLuint filter, GLuint type, GLuint type_2, - bool depth, SceneContext &scnctx) + bool depth, SceneContext &scnctx, GLuint height, GLuint width) { + height = (height == 0) ? scnctx.height : height; + width = (width == 0) ? scnctx.width : width; + glBindFramebuffer(GL_FRAMEBUFFER, _fboId); glGenTextures(1, &_pass_textures[tex_name]);; glBindTexture(GL_TEXTURE_2D, _pass_textures[tex_name]); - glTexImage2D(GL_TEXTURE_2D, 0, type, scnctx.width, scnctx.height, 0, type_2, GL_FLOAT, 0); + glTexImage2D(GL_TEXTURE_2D, 0, type, width, height, 0, type_2, GL_FLOAT, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -67,17 +70,22 @@ void Multipass::drawResultToScreen(SceneContext & scnctx) glBindFramebuffer(GL_FRAMEBUFFER, 0); glViewport(0, 0, scnctx.width, scnctx.height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - shader.enable(); + shader->enable(); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, _pass_textures[_current_tex]); - shader.addUniform("tex", 0); + shader->addUniform("tex", 0); glBindVertexArray(_quad_vao); glBindBuffer(GL_ARRAY_BUFFER, _quad_vbo); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindTexture(GL_TEXTURE_2D, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); - shader.disable(); + shader->disable(); +} + +GLuint Multipass::getCurrentTexture() +{ + return _pass_textures[_current_tex]; } void Multipass::_createQuad() diff --git a/BaseGLProject/Multipass.h b/BaseGLProject/Multipass.h index b12cf31..12b2b3f 100644 --- a/BaseGLProject/Multipass.h +++ b/BaseGLProject/Multipass.h @@ -16,12 +16,13 @@ public: void bindToFrameBuffer(GLenum type, GLenum texture, std::string texName); void addTexture(const std::string &tex_name, GLuint filter, GLuint type, GLuint type_2, - bool depth, SceneContext &scnctx); + bool depth, SceneContext &scnctx, GLuint height = 0, GLuint width = 0); void enableFrameBufferTexture(const std::string tex_name); void drawResultToScreen(SceneContext &scnctx); + GLuint getCurrentTexture(); - Shader shader; + Shader *shader; private: void _createQuad(); diff --git a/BaseGLProject/MyGLWindow.cpp b/BaseGLProject/MyGLWindow.cpp index 9a32c2b..d84504b 100644 --- a/BaseGLProject/MyGLWindow.cpp +++ b/BaseGLProject/MyGLWindow.cpp @@ -88,6 +88,9 @@ void MyGlWindow::shaderSetup() shaders["Simple"]->uniformFlags = ShaderFlags::MVP_FLAG; shaders["BaseLight"] = new Shader("base_light.vert", "base_light.frag"); + shaders["ShadowLight"] = new Shader("shadow_light.vert", "shadow_light.frag"); + shaders["LightPOV"] = new Shader("light_pov.vert", "light_pov.frag"); + shaders["LightPOV"]->uniformFlags = 0; shaders["Fog"] = new Shader("fog.vert", "fog.frag"); shaders["TexBaseLight"] = new Shader("tex_base_light.vert", "tex_base_light.frag"); @@ -131,21 +134,23 @@ void MyGlWindow::lightSetup() void MyGlWindow::multipassSetup() { + //_multipassManager.shader = shaders["ShadowLight"]; _multipassManager.addTexture("render_tex", GL_NEAREST, GL_RGB, GL_RGB, false, _scnctx); _multipassManager.bindToFrameBuffer(GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, "render_tex"); _multipassManager.addTexture("depth_tex", GL_LINEAR, GL_DEPTH_COMPONENT24, - GL_DEPTH_COMPONENT, true, _scnctx); + GL_DEPTH_COMPONENT, true, _scnctx, 1024, 1024); _multipassManager.bindToFrameBuffer(GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, "depth_tex"); _multipassManager.setDrawBuffers(); - _multipassManager.shader.addSubroutine(GL_FRAGMENT_SHADER, "depthing"); - _multipassManager.shader.addSubroutine(GL_FRAGMENT_SHADER, "blurring"); - _multipassManager.shader.addSubroutine(GL_FRAGMENT_SHADER, "sharpening"); - _multipassManager.shader.addSubroutine(GL_FRAGMENT_SHADER, "sepia"); - _multipassManager.shader.addSubroutine(GL_FRAGMENT_SHADER, "grayscale"); - _multipassManager.shader.addSubroutine(GL_FRAGMENT_SHADER, "sobel_filter"); + _multipassManager.shader->addSubroutine(GL_FRAGMENT_SHADER, "depthing"); + _multipassManager.shader->addSubroutine(GL_FRAGMENT_SHADER, "blurring"); + _multipassManager.shader->addSubroutine(GL_FRAGMENT_SHADER, "sharpening"); + _multipassManager.shader->addSubroutine(GL_FRAGMENT_SHADER, "sepia"); + _multipassManager.shader->addSubroutine(GL_FRAGMENT_SHADER, "grayscale"); + _multipassManager.shader->addSubroutine(GL_FRAGMENT_SHADER, "sobel_filter"); + _multipassManager.shader->addSubroutine(GL_FRAGMENT_SHADER, "no_postprocess"); } void MyGlWindow::setup() @@ -180,23 +185,23 @@ void MyGlWindow::setup() //meshes["Buddha"]->addScaling(glm::vec4(4, 4, 4, 0)); //meshes["Buddha"]->addRotation(glm::vec4(0, 1, 0, 180)); - //Dataset moddata; + Dataset moddata; //moddata.simpleCube(); //meshes.emplace("Cube", new Mesh(moddata, shaders["TexBaseLight"])); //meshes["Cube"]->assignTexture(_scnctx.textures["BrickTex"]); //meshes["Cube"]->assignTexture(_scnctx.textures["MossTex"]); //meshes["Cube"]->addTranslation(glm::vec4(4, 3, -4, 0)); - meshes.emplace("Mountain", new Mesh("mountain/mount.blend1.obj", shaders["TexBaseLight"])); + //meshes.emplace("Mountain", new Mesh("mountain/mount.blend1.obj", shaders["TexBaseLight"])); //meshes.emplace("Sponza", new Mesh("sponza/sponza.obj", shaders["TexBaseLight"])); //meshes["Sponza"]->addTranslation(glm::vec4(0, -200, 0, 1)); - //moddata.checkeredFloor(20, 20, glm::vec3(0.1, 0.1, 0.1), glm::vec3(0.7, 0.7, 0.7)); - //meshes.emplace("Floor", new Mesh(moddata, shaders["BaseLight"])); - //meshes["Floor"]->addTranslation(glm::vec4(0, -0.05, 0, 1)); - //meshes["Floor"]->cullMode = BACK; + moddata.checkeredFloor(20, 20, glm::vec3(0.1, 0.1, 0.1), glm::vec3(0.7, 0.7, 0.7)); + meshes.emplace("Floor", new Mesh(moddata, shaders["LightPOV"])); + meshes["Floor"]->addTranslation(glm::vec4(0, -0.05, 0, 1)); + meshes["Floor"]->cullMode = BACK; //moddata.simpleCube(); //meshes.emplace("Cube", new Mesh(moddata, shaders["BrickBaseLight"])); @@ -210,9 +215,9 @@ void MyGlWindow::setup() //meshes.emplace("TeapotSilhouette", new Mesh("teapot.obj", shaders["Silhouette"])); //meshes["TeapotSilhouette"]->addTranslation(glm::vec4(5, 0 ,3, 1)); //meshes["TeapotSilhouette"]->cullMode = FRONT; - //meshes.emplace("Teapot", new Mesh("teapot.obj", shaders["Toon"])); - //meshes["Teapot"]->addTranslation(glm::vec4(5, 0, 3, 1)); - //meshes["Teapot"]->cullMode = BACK; + meshes.emplace("Teapot", new Mesh("teapot.obj", shaders["LightPOV"])); + meshes["Teapot"]->addTranslation(glm::vec4(5, 0, 3, 1)); + meshes["Teapot"]->cullMode = BACK; //meshes.emplace("Teapot", new Mesh("teapot.obj", shaders["Skybox"])); @@ -227,12 +232,19 @@ void MyGlWindow::draw() glm::vec3 look(viewer.getViewCenter().x, viewer.getViewCenter().y, viewer.getViewCenter().z); glm::vec3 up(viewer.getUpVector().x, viewer.getUpVector().y, viewer.getUpVector().z); glm::mat4 view = lookAt(eye, look, up); //Calculate view matrix from parameters of m_viewer - glm::mat4 projection = perspective(45.0f, (float)_scnctx.width / (float)_scnctx.height, 0.1f, 2000.0f); + glm::mat4 projection = perspective(45.0f, (float)_scnctx.width / (float)_scnctx.height, 0.1f, 40.0f); _scnctx.viewMatrix = view; _scnctx.projectionMatrix = projection; + + // Light POV matrixes + glm::mat4 lightMVP = glm::ortho(-25.0f, 25.0f, -25.0f, 25.0f, 0.1f, 40.0f) * + lookAt(glm::vec3(_scnctx.lights["Spotlight1"].location), glm::vec3(0) , glm::vec3(0, 1, 0)) * + glm::mat4(1.0); + + shaders["LightPOV"]->addUniform("lightmvp", lightMVP); - _multipassManager.enableFrameBufferTexture("render_tex"); + _multipassManager.enableFrameBufferTexture("depth_tex"); glClearColor(_scnctx.bg.r, _scnctx.bg.g, _scnctx.bg.b, _scnctx.bg.a); glViewport(0, 0, _scnctx.width, _scnctx.height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -242,7 +254,18 @@ void MyGlWindow::draw() for (auto it = meshes.begin(); it != meshes.end(); it++) (*it).second->draw(_scnctx); - _multipassManager.shader.enableSubroutine("sobel_filter"); + GLuint depth_tex = _multipassManager.getCurrentTexture(); + /*_multipassManager.enableFrameBufferTexture("render_tex"); + + for (auto it = meshes.begin(); it != meshes.end(); it++) + { + (*it).second->shader = shaders["ShadowLight"]; + (*it).second->shader->addUniform("lightmvp", lightMVP); + (*it).second->shader->addUniform("depth_tex", (int)depth_tex); + (*it).second->draw(_scnctx); + }*/ + + _multipassManager.shader->enableSubroutine("depthing"); _multipassManager.drawResultToScreen(_scnctx); //skybox.draw(shaders["Skybox"], _scnctx); } diff --git a/BaseGLProject/imgui.ini b/BaseGLProject/imgui.ini index cd0131f..44dd3c0 100644 --- a/BaseGLProject/imgui.ini +++ b/BaseGLProject/imgui.ini @@ -46,5 +46,5 @@ Collapsed=0 [Window][First Window] Pos=20,20 Size=357,188 -Collapsed=1 +Collapsed=0 diff --git a/BaseGLProject/light_pov.frag b/BaseGLProject/light_pov.frag new file mode 100644 index 0000000..6652ef5 --- /dev/null +++ b/BaseGLProject/light_pov.frag @@ -0,0 +1,5 @@ +#version 440 + +void main(void) +{ +} \ No newline at end of file diff --git a/BaseGLProject/light_pov.vert b/BaseGLProject/light_pov.vert new file mode 100644 index 0000000..54fdf95 --- /dev/null +++ b/BaseGLProject/light_pov.vert @@ -0,0 +1,13 @@ +#version 440 + +layout(location=0) in vec3 coord3d; +layout(location=1) in vec3 v_normal; +layout(location=2) in vec3 v_color; +layout(location=3) in vec2 v_texmap; + +uniform mat4 lightmvp; + +void main(void) +{ + gl_Position = lightmvp * vec4(coord3d, 1.0f); +} \ No newline at end of file diff --git a/BaseGLProject/shadow_light.frag b/BaseGLProject/shadow_light.frag new file mode 100644 index 0000000..f371ca9 --- /dev/null +++ b/BaseGLProject/shadow_light.frag @@ -0,0 +1,69 @@ +#version 440 + +out vec4 FragColor; + +in vec2 TexCoords; +in vec3 fragPos; +in vec3 fragNormal; +in vec4 fragPosLightSpace; + +uniform vec3 Kd; +uniform vec3 Ka; +uniform vec3 Ks; +uniform float Shininess; + +struct LightInfo { + vec4 Position; + vec3 Intensity; +}; + +uniform LightInfo Light[64]; +uniform int LightCount; + +uniform uint hasTextureDiffuse; +uniform sampler2D tex; +uniform sampler2D depth_tex; + +float ShadowCalculation(vec4 PInLightSpace) +{ + // perform perspective divide + vec3 projCoords = PInLightSpace.xyz / PInLightSpace.w; + // transform to [0,1] range + projCoords = projCoords * 0.5 + 0.5; //why? because it has a values [-1, 1], convert to [0, 1] + // get closest depth value from light's perspective (using [0,1] range fragPosLight as coords) + float closestDepth = texture(depth_tex, projCoords.xy).r; + // get depth of current fragment from light's perspective + float currentDepth = projCoords.z; + // check whether current frag pos is in shadow + float bias = 0.005; + float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0; + // Supress the limit of the far / close plane + if (projCoords.z > 1.0) + shadow = 0.0; + return shadow; +} + +void main() +{ + //calculate diffuse, specular, ambient + + vec3 c = vec3(1.0); + if (hasTextureDiffuse == 1) { + c = texture(tex, TexCoords).rgb; + } + + float shadow = ShadowCalculation(fragPosLightSpace); + + vec3 L = normalize(Light[LightCount - 1].Position.xyz - fragPos); + vec3 N = fragNormal; + vec3 V = normalize(-fragPos); + //vec3 R = normalize(reflect(-L, N)); + vec3 H = normalize(V + L); + + vec3 ambient = Ka * Light[LightCount - 1].Intensity; + vec3 diffuse = Kd * Light[LightCount - 1].Intensity * max(dot(L, N), 0.0); + vec3 specular = Ks * Light[LightCount - 1].Intensity * pow(max(dot(H, N), 0.0), Shininess); + + vec3 final = (ambient + (1-shadow)*(diffuse + specular))*c; + FragColor = vec4(final,1.0); +} diff --git a/BaseGLProject/shadow_light.vert b/BaseGLProject/shadow_light.vert new file mode 100644 index 0000000..fa2c840 --- /dev/null +++ b/BaseGLProject/shadow_light.vert @@ -0,0 +1,25 @@ +#version 440 + +layout (location = 0) in vec3 position; +layout (location = 1) in vec3 normal; +layout (location = 2) in vec2 v_color; +layout (location = 3) in vec2 texCoords; + +out vec2 TexCoords; +out vec3 fragPos; +out vec3 fragNormal; +out vec4 fragPosLightSpace; + +uniform mat4 mvp; +uniform mat4 ModelViewMatrix; +uniform mat3 NormalMatrix; +uniform mat4 lightmvp; + +void main() +{ + fragNormal = normalize(NormalMatrix * normal); + fragPos = vec3(ModelViewMatrix * vec4(position,1.0)); + TexCoords = texCoords; + fragPosLightSpace = lightmvp * vec4(position,1.0); + gl_Position = mvp * vec4(position, 1.0f); +} diff --git a/BaseGLProject/textureViewer.frag b/BaseGLProject/textureViewer.frag index 3f178b9..731ba1d 100644 --- a/BaseGLProject/textureViewer.frag +++ b/BaseGLProject/textureViewer.frag @@ -6,7 +6,6 @@ out vec4 final_color; uniform sampler2D tex; - subroutine vec4 shading_t(vec4 color); subroutine uniform shading_t Shading; @@ -36,10 +35,10 @@ vec4 grayscale(vec4 color) subroutine(shading_t) vec4 depthing(vec4 color) { - float zNear = 0.1f; // zNear of your perspective projection - float zFar = 2000.0f; // zFar of your perspective projection + float zNear = 2.1f; // zNear of your perspective projection + float zFar = 40.0f; // zFar of your perspective projection float depth = color.x; - float r = (2.0 * zNear) / (zFar + zNear - depth * (zFar - zNear)); + float r = (zNear * 2.0) / (zFar + zNear - depth * (zFar - zNear)); return vec4(r, r, r, 1); } @@ -103,41 +102,14 @@ vec4 sobel_filter(vec4 color) return grayscale(sobeled); } -void main() +subroutine(shading_t) +vec4 no_postprocess(vec4 color) { - //rrra because depth textures are not usual textures, they have only one channel + return color; +} + +void main() +{ final_color = texture(tex, uv).rgba; - final_color = Shading(final_color); - -// if (depth) { -// float d; -// d = LinearizeDepth(uv); -// final_color = vec4(d,d,d,1.0); -// } -// else if (blur) -// { -// final_color = vec4(blurring_func(uv), 1); -// } -// else if (sharpen) -// { -// final_color = vec4(sharpening_func(uv)); -// } -// else if (sepia) -// { -// final_color = vec4(final_color.r * .393 + final_color.g * .769 + final_color.b * .189, -// final_color.r * .349 + final_color.g * .686 + final_color.b * .168, -// final_color.r * .272 + final_color.g * .534 + final_color.b * .131, 1.0); -// } -// else if (grayscale) -// { -// float average = final_color.r * 0.2126 + final_color.g * 0.7152 + final_color.b * 0.0722; -// final_color = vec4(average, average, average, 1.0); -// } -// else if (sobel) -// { -// vec3 sobeled = sobel_filter(final_color.rgb); -// float average = sobeled.r * 0.2126 + sobeled.g * 0.7152 + sobeled.b * 0.0722; -// final_color = vec4(average, average, average, 1.0); -// } } \ No newline at end of file