diff --git a/src/renderer/passes/material-pass.cpp b/src/renderer/passes/material-pass.cpp index ca5d77e..e0d22aa 100644 --- a/src/renderer/passes/material-pass.cpp +++ b/src/renderer/passes/material-pass.cpp @@ -327,6 +327,7 @@ void material_pass::render(render_context* context) const } } + /* if ((material_flags & MATERIAL_FLAG_OUTLINE) != (active_material_flags & MATERIAL_FLAG_OUTLINE)) { if (material_flags & MATERIAL_FLAG_OUTLINE) @@ -342,7 +343,7 @@ void material_pass::render(render_context* context) const glStencilMask(0x00); } } - + */ active_material_flags = material_flags; } diff --git a/src/renderer/passes/outline-pass.cpp b/src/renderer/passes/outline-pass.cpp index e678a4e..ca8de9c 100644 --- a/src/renderer/passes/outline-pass.cpp +++ b/src/renderer/passes/outline-pass.cpp @@ -38,13 +38,18 @@ outline_pass::outline_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, resource_manager* resource_manager): render_pass(rasterizer, framebuffer), - outline_shader(nullptr) + fill_shader(nullptr), + stroke_shader(nullptr) { - // Load outline shader - outline_shader = resource_manager->load("outline-unskinned.glsl"); - model_view_projection_input = outline_shader->get_input("model_view_projection"); - outline_width_input = outline_shader->get_input("outline_width"); - outline_color_input = outline_shader->get_input("outline_color"); + // Load fill shader + fill_shader = resource_manager->load("outline-fill-unskinned.glsl"); + fill_model_view_projection_input = fill_shader->get_input("model_view_projection"); + + // Load stroke shader + stroke_shader = resource_manager->load("outline-stroke-unskinned.glsl"); + stroke_model_view_projection_input = stroke_shader->get_input("model_view_projection"); + stroke_width_input = stroke_shader->get_input("width"); + stroke_color_input = stroke_shader->get_input("color"); } outline_pass::~outline_pass() @@ -54,49 +59,81 @@ void outline_pass::render(render_context* context) const { rasterizer->use_framebuffer(*framebuffer); - if (outline_color.w < 1.0f) - { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - else - { - glDisable(GL_BLEND); - } - - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - glCullFace(GL_BACK); - - glEnable(GL_STENCIL_TEST); - glStencilFunc(GL_NOTEQUAL, 1, 0xFF); - glStencilMask(0x00); - // Determine viewport based on framebuffer resolution auto viewport = framebuffer->get_dimensions(); rasterizer->set_viewport(0, 0, std::get<0>(viewport), std::get<1>(viewport)); + // Get camera matrices float4x4 view = context->camera->get_view_tween().interpolate(context->alpha); float4x4 view_projection = context->camera->get_view_projection_tween().interpolate(context->alpha); + float4x4 model_view_projection; - // Perform iterative blur subpass - rasterizer->use_program(*outline_shader); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glDisable(GL_DEPTH_TEST); - outline_width_input->upload(outline_width); - outline_color_input->upload(outline_color); + // Render fill + { + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + glEnable(GL_STENCIL_TEST); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + glStencilFunc(GL_ALWAYS, 1, 0xFF); + glStencilMask(0xFF); + glDisable(GL_BLEND); + + // Setup fill shader + rasterizer->use_program(*fill_shader); + + // Render fills + for (const render_operation& operation: context->operations) + { + const ::material* material = operation.material; + if (!material || !(material->get_flags() & MATERIAL_FLAG_OUTLINE)) + continue; + + model_view_projection = view_projection * operation.transform; + fill_model_view_projection_input->upload(model_view_projection); + + rasterizer->draw_arrays(*operation.vertex_array, operation.drawing_mode, operation.start_index, operation.index_count); + } + } - // Render outlines - for (const render_operation& operation: context->operations) + // Render stroke { - const ::material* material = operation.material; - if (!material || !(material->get_flags() & MATERIAL_FLAG_OUTLINE)) - continue; + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + if (outline_color.w < 1.0f) + { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + else + { + glDisable(GL_BLEND); + } + + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_NOTEQUAL, 1, 0xFF); + glStencilMask(0x00); - model_view_projection = view_projection * operation.transform; - model_view_projection_input->upload(model_view_projection); + // Setup stroke shader + rasterizer->use_program(*stroke_shader); + stroke_width_input->upload(outline_width); + stroke_color_input->upload(outline_color); - rasterizer->draw_arrays(*operation.vertex_array, operation.drawing_mode, operation.start_index, operation.index_count); + // Render strokes + for (const render_operation& operation: context->operations) + { + const ::material* material = operation.material; + if (!material || !(material->get_flags() & MATERIAL_FLAG_OUTLINE)) + continue; + + model_view_projection = view_projection * operation.transform; + stroke_model_view_projection_input->upload(model_view_projection); + + rasterizer->draw_arrays(*operation.vertex_array, operation.drawing_mode, operation.start_index, operation.index_count); + } } glDisable(GL_STENCIL_TEST); diff --git a/src/renderer/passes/outline-pass.hpp b/src/renderer/passes/outline-pass.hpp index 73db35f..9f81b04 100644 --- a/src/renderer/passes/outline-pass.hpp +++ b/src/renderer/passes/outline-pass.hpp @@ -41,10 +41,13 @@ public: void set_outline_color(const float4& color); private: - shader_program* outline_shader; - const shader_input* model_view_projection_input; - const shader_input* outline_width_input; - const shader_input* outline_color_input; + shader_program* fill_shader; + const shader_input* fill_model_view_projection_input; + + shader_program* stroke_shader; + const shader_input* stroke_model_view_projection_input; + const shader_input* stroke_width_input; + const shader_input* stroke_color_input; float outline_width; float4 outline_color;