blob: 65fb441c63035ec3a29cd990965ee9327346b870 [file] [log] [blame]
/*
* Copyright © 2012 Linaro Limited
*
* This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
*
* glmark2 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 3 of the License, or (at your option) any later
* version.
*
* glmark2 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
* glmark2. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Alexandros Frantzis
*/
#include "scene.h"
#include "renderer.h"
#include "shader-source.h"
void
create_blur_shaders(ShaderSource& vtx_source, ShaderSource& frg_source,
unsigned int radius, float sigma, BlurRenderer::BlurDirection direction,
float tilt_shift);
BlurRenderer::BlurRenderer(const LibMatrix::vec2 &size, int radius, float sigma,
BlurDirection dir, const LibMatrix::vec2 &step, float tilt_shift) :
TextureRenderer(size, *blur_program(true, radius, sigma, dir, step, tilt_shift))
{
blur_program_ = blur_program(false, radius, sigma, dir, step, tilt_shift);
}
Program *
BlurRenderer::blur_program(bool create_new, int radius, float sigma,
BlurDirection dir, const LibMatrix::vec2 &step,
float tilt_shift)
{
static Program *blur_program(0);
if (create_new)
blur_program = 0;
if (!blur_program) {
blur_program = new Program();
ShaderSource blur_vtx_shader;
ShaderSource blur_frg_shader;
create_blur_shaders(blur_vtx_shader, blur_frg_shader, radius,
sigma, dir, tilt_shift);
if (dir == BlurDirectionHorizontal || dir == BlurDirectionBoth)
blur_frg_shader.add_const("TextureStepX", step.x());
if (dir == BlurDirectionVertical || dir == BlurDirectionBoth)
blur_frg_shader.add_const("TextureStepY", step.y());
Scene::load_shaders_from_strings(*blur_program,
blur_vtx_shader.str(),
blur_frg_shader.str());
blur_program->start();
(*blur_program)["Texture0"] = 0;
(*blur_program)["uvOffset"] = LibMatrix::vec2(0.0f, 0.0f);
(*blur_program)["uvScale"] = LibMatrix::vec2(1.0f, 1.0f);
blur_program->stop();
}
return blur_program;
}
void
create_blur_shaders(ShaderSource& vtx_source, ShaderSource& frg_source,
unsigned int radius, float sigma, BlurRenderer::BlurDirection direction,
float tilt_shift)
{
vtx_source.append_file(GLMARK_DATA_PATH"/shaders/terrain-texture.vert");
frg_source.append_file(GLMARK_DATA_PATH"/shaders/terrain-blur.frag");
/* Don't let the gaussian curve become too narrow */
if (sigma < 1.0)
sigma = 1.0;
unsigned int side = 2 * radius + 1;
float values[radius];
float sum = 0.0;
for (unsigned int i = 0; i < radius + 1; i++) {
float s2 = 2.0 * sigma * sigma;
float k = 1.0 / std::sqrt(M_PI * s2) * std::exp( - (static_cast<float>(i) * i) / s2);
values[i] = k;
sum += k;
}
sum += sum - values[0];
for (unsigned int i = 0; i < radius + 1; i++) {
std::stringstream ss_tmp;
ss_tmp << "Kernel" << i;
frg_source.add_const(ss_tmp.str(), values[i] / sum);
}
frg_source.add_const("TiltShift", tilt_shift);
std::stringstream ss;
if (direction == BlurRenderer::BlurDirectionHorizontal ||
direction == BlurRenderer::BlurDirectionBoth)
{
if (tilt_shift == 1.0)
ss << "const float stepX = TextureStepX;" << std::endl;
else
ss << "float stepX = TextureStepX * abs(TiltShift - TextureCoord.y) / abs(1.0 - TiltShift);" << std::endl;
}
if (direction == BlurRenderer::BlurDirectionVertical ||
direction == BlurRenderer::BlurDirectionBoth)
{
if (tilt_shift == 1.0)
ss << "const float stepY = TextureStepY;" << std::endl;
else
ss << "float stepY = TextureStepY * abs(TiltShift - TextureCoord.y) / abs(1.0 - TiltShift);" << std::endl;
}
ss << "result = " << std::endl;
if (direction == BlurRenderer::BlurDirectionHorizontal) {
for (unsigned int i = 0; i < side; i++) {
int offset = static_cast<int>(i - radius);
ss << "texture2D(Texture0, TextureCoord + vec2(" <<
offset << ".0 * stepX, 0.0)) * Kernel" <<
std::abs(offset) << " +" << std::endl;
}
ss << "0.0 ;" << std::endl;
}
else if (direction == BlurRenderer::BlurDirectionVertical) {
for (unsigned int i = 0; i < side; i++) {
int offset = static_cast<int>(i - radius);
ss << "texture2D(Texture0, TextureCoord + vec2(0.0, " <<
offset << ".0 * stepY)) * Kernel" <<
std::abs(offset) << " +" << std::endl;
}
ss << "0.0 ;" << std::endl;
}
else if (direction == BlurRenderer::BlurDirectionBoth) {
for (unsigned int i = 0; i < side; i++) {
int ioffset = static_cast<int>(i - radius);
for (unsigned int j = 0; j < side; j++) {
int joffset = static_cast<int>(j - radius);
ss << "texture2D(Texture0, TextureCoord + vec2(" <<
ioffset << ".0 * stepX, " <<
joffset << ".0 * stepY))" <<
" * Kernel" << std::abs(ioffset) <<
" * Kernel" << std::abs(joffset) << " +" << std::endl;
}
}
ss << " 0.0;" << std::endl;
}
frg_source.replace("$CONVOLUTION$", ss.str());
}