diff --git a/data/effects/mip-mapper.effect b/data/effects/mip-mapper.effect new file mode 100644 index 0000000..13efe8c --- /dev/null +++ b/data/effects/mip-mapper.effect @@ -0,0 +1,49 @@ +uniform matrix4 ViewProj; + +uniform texture2d image; +uniform float2 imageTexel; +uniform int layer; + +sampler_state textureSampler { + Filter = Point; + AddressU = Clamp; + AddressV = Clamp; +}; + +struct VertDataIn { + float4 pos : POSITION; + float2 uv : TEXCOORD0; +}; + +struct VertDataOut { + float4 pos : POSITION; + float2 uv : TEXCOORD0; +}; + +VertDataOut VSDefault(VertDataIn v_in) +{ + VertDataOut vert_out; + vert_out.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj); + vert_out.uv = v_in.uv; + return vert_out; +} + +float4 PSAverage(VertDataOut v_in) : TARGET +{ + float4 rgba = 0; + for (float x = -1; x <= 1; x++) { + for (float y = -1; y <= 1; y++) { + rgba += image.Sample(textureSampler, v_in.uv + vec2(x,y) * imageTexel + imageTexel); + } + } + return rgba / 9.0; +} + +technique Draw +{ + pass + { + vertex_shader = VSDefault(v_in); + pixel_shader = PSAverage(v_in); + } +} diff --git a/source/gs-mipmapper.cpp b/source/gs-mipmapper.cpp new file mode 100644 index 0000000..2f4b05a --- /dev/null +++ b/source/gs-mipmapper.cpp @@ -0,0 +1,159 @@ +/* + * Modern effects for a modern Streamer + * Copyright (C) 2017 Michael Fabian Dirks + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "gs-mipmapper.h" +extern "C" { +#pragma warning (push) +#pragma warning (disable: 4201) +#include "libobs/obs.h" +#include "libobs/graphics/graphics.h" +#pragma warning (pop) +} + +#define MAX_LAYERS 16 + +GS::MipMapper::MipMapper() : m_rt(GS_RGBA, GS_ZS_NONE), m_vb(65535) { + // Sub layers start here now. + double_t size = 0.5, offset = 0.0; + for (size_t layer = 0; layer < MAX_LAYERS; layer++) { + // Large Block + if (layer == 0) { + { + GS::Vertex& v = m_vb.at(layer * 12); + vec3_set(&v.position, offset, offset, 0); + vec4_set(&v.uv[0], 0, 0, 0, 0); + } + { + GS::Vertex& v = m_vb.at(layer * 12 + 1); + vec3_set(&v.position, offset + size, offset, 0); + vec4_set(&v.uv[0], 1, 0, 0, 0); + } + { + GS::Vertex& v = m_vb.at(layer * 12 + 2); + vec3_set(&v.position, offset + size, offset + size, 0); + vec4_set(&v.uv[0], 1, 1, 0, 0); + } + { + GS::Vertex& v = m_vb.at(layer * 12 + 3); + vec3_set(&v.position, offset, offset + size, 0); + vec4_set(&v.uv[0], 0, 1, 0, 0); + } + } else { + { + GS::Vertex& v = m_vb.at(layer * 12); + vec3_set(&v.position, offset, offset, 0); + vec4_set(&v.uv[0], offset - size * 2, offset - size * 2, 0, 0); + } + { + GS::Vertex& v = m_vb.at(layer * 12 + 1); + vec3_set(&v.position, offset + size, offset, 0); + vec4_set(&v.uv[0], offset, offset - size * 2, 0, 0); + } + { + GS::Vertex& v = m_vb.at(layer * 12 + 2); + vec3_set(&v.position, offset + size, offset + size, 0); + vec4_set(&v.uv[0], offset, offset, 0, 0); + } + { + GS::Vertex& v = m_vb.at(layer * 12 + 3); + vec3_set(&v.position, offset, offset + size, 0); + vec4_set(&v.uv[0], offset - size * 2, offset, 0, 0); + } + } + + if (layer != 0) { + // Horizontal Slice + { + GS::Vertex& v = m_vb.at(layer * 12 + 4); + vec3_set(&v.position, 0, offset, 0); + vec4_set(&v.uv[0], 0, offset - size, 0, 0); + } + { + GS::Vertex& v = m_vb.at(layer * 12 + 5); + vec3_set(&v.position, size, offset, 0); + vec4_set(&v.uv[0], .5, offset - size, 0, 0); + } + { + GS::Vertex& v = m_vb.at(layer * 12 + 6); + vec3_set(&v.position, size, offset + size, 0); + vec4_set(&v.uv[0], .5, offset, 0, 0); + } + { + GS::Vertex& v = m_vb.at(layer * 12 + 7); + vec3_set(&v.position, 0, offset + size, 0); + vec4_set(&v.uv[0], 0, offset, 0, 0); + } + + // Vertical Slice + { + GS::Vertex& v = m_vb.at(layer * 12 + 8); + vec3_set(&v.position, offset, 0, 0); + vec4_set(&v.uv[0], offset - size, 0, 0, 0); + } + { + GS::Vertex& v = m_vb.at(layer * 12 + 9); + vec3_set(&v.position, offset + size, 0, 0); + vec4_set(&v.uv[0], offset, 0, 0, 0); + } + { + GS::Vertex& v = m_vb.at(layer * 12 + 10); + vec3_set(&v.position, offset + size, size, 0); + vec4_set(&v.uv[0], offset, 0.5, 0, 0); + } + { + GS::Vertex& v = m_vb.at(layer * 12 + 11); + vec3_set(&v.position, offset, size, 0); + vec4_set(&v.uv[0], offset - size, 0.5, 0, 0); + } + } + + offset += size; + size /= 2.0; + } +} + +GS::MipMapper::~MipMapper() {} + +gs_texture_t* GS::MipMapper::Render(gs_texture_t* intex) { + // Get Texture Size + uint32_t width = gs_texture_get_width(intex), + height = gs_texture_get_height(intex); + + // Calculate total mipmap layers. + uint32_t layers = 1, size = height; + if (width > height) size = width; + layers = static_cast(ceil(log(double_t(size)) / log(2.0))); + size = pow(2, layers); + + // Render + m_buf = GS::Texture(size, size, GS_RGBA, 1, nullptr, GS_DYNAMIC); + for (uint32_t layer = 0; layer < layers; layer++) { + try { + GS::RenderTargetOp op = m_rt.Render(size * 2, size * 2); + gs_load_vertexbuffer(m_vb.get()); + gs_load_indexbuffer(nullptr); + gs_draw(gs_draw_mode::GS_TRIS, layer * 12, 12); + } catch (...) { + return intex; + } + gs_copy_texture(m_buf.GetObject(), m_rt.GetTextureObject()); + } + + return m_buf.GetObject(); +} diff --git a/source/gs-mipmapper.h b/source/gs-mipmapper.h new file mode 100644 index 0000000..ed1870a --- /dev/null +++ b/source/gs-mipmapper.h @@ -0,0 +1,45 @@ +/* + * Modern effects for a modern Streamer + * Copyright (C) 2017 Michael Fabian Dirks + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma once +#include "gs-vertexbuffer.h" +#include "gs-rendertarget.h" +#include "gs-texture.h" + +extern "C" { + #pragma warning (push) + #pragma warning (disable: 4201) + #include "libobs/graphics/graphics.h" + #pragma warning (pop) +} + +namespace GS { + class MipMapper { + public: + MipMapper(); + ~MipMapper(); + + gs_texture_t* Render(gs_texture_t*); + + private: + GS::VertexBuffer m_vb; + GS::RenderTarget m_rt; + GS::Texture m_buf; + }; +}