blob: 2a3d0e2ac632ce1579b69d3e8eb0706e35213087 [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 <vector>
#include "mesh.h"
#include "vec.h"
#include "program.h"
#include "gl-headers.h"
/**
* Renderer interface.
*/
class IRenderer
{
public:
/**
* Sets up the renderer's target.
*/
virtual void setup(const LibMatrix::vec2 &size, bool onscreen, bool has_depth) = 0;
/**
* Sets up the renderer's target texture (if any).
*/
virtual void setup_texture(GLint min_filter, GLint mag_filter,
GLint wrap_s, GLint wrap_t) = 0;
/**
* Sets the renderer's input texture.
*/
virtual void input_texture(GLuint t) = 0;
/**
* Gets the renderer's target texture (if any).
*/
virtual GLuint texture() = 0;
/**
* Gets the size of the renderer's target.
*/
virtual LibMatrix::vec2 size() = 0;
/**
* Makes the renderer current i.e. the rendering target.
*/
virtual void make_current() = 0;
/**
* Updates the mipmap of the texture backing the renderer (if any).
*/
virtual void update_mipmap() = 0;
/**
* Renders to the renderer's target.
*/
virtual void render() = 0;
protected:
virtual ~IRenderer() {}
};
/**
* A chain of renderers, which implements IRenderer
*/
class RendererChain : public IRenderer
{
public:
RendererChain() {}
virtual ~RendererChain() {}
/* IRenderer methods */
void setup(const LibMatrix::vec2 &size, bool onscreen, bool has_depth);
void setup_texture(GLint min_filter, GLint mag_filter,
GLint wrap_s, GLint wrap_t);
void input_texture(GLuint t);
GLuint texture();
LibMatrix::vec2 size();
void make_current();
void update_mipmap();
void render();
/**
* Appends a renderer to the chain.
*
* @param renderer the renderer to append
*/
void append(IRenderer &renderer);
private:
std::vector<IRenderer *> renderers_;
};
/**
* A base implementation of the IRenderer interface.
*/
class BaseRenderer : public IRenderer
{
public:
BaseRenderer(const LibMatrix::vec2 &size);
virtual ~BaseRenderer();
/* IRenderer methods */
virtual void setup(const LibMatrix::vec2 &size, bool onscreen, bool has_depth);
virtual void setup_texture(GLint min_filter, GLint mag_filter,
GLint wrap_s, GLint wrap_t);
virtual void input_texture(GLuint t) { input_texture_ = t; }
virtual GLuint texture() { return texture_; }
virtual LibMatrix::vec2 size() { return size_; }
virtual void make_current();
virtual void update_mipmap();
virtual void render() = 0;
protected:
void recreate(bool onscreen, bool has_depth);
void create_texture();
void update_texture_parameters();
void create_fbo(bool has_depth);
LibMatrix::vec2 size_;
GLuint texture_;
GLuint input_texture_;
GLuint fbo_;
GLuint depth_renderbuffer_;
GLint min_filter_;
GLint mag_filter_;
GLint wrap_s_;
GLint wrap_t_;
};
/**
* A renderer that renders its input texture to its target,
* according to the supplied GL Program.
*/
class TextureRenderer : public BaseRenderer
{
public:
TextureRenderer(const LibMatrix::vec2 &size, Program &program);
virtual ~TextureRenderer() { }
/* IRenderer/BaseRenderer methods */
virtual void render();
/**
* Gets the program associated with the renderer.
*/
Program &program() { return program_; }
private:
void create_mesh();
Mesh mesh_;
Program &program_;
};
/**
* A renderer that copies the input texture to its target.
*/
class CopyRenderer : public TextureRenderer
{
public:
CopyRenderer(const LibMatrix::vec2 &size);
virtual ~CopyRenderer() { delete copy_program_; }
private:
static Program *copy_program(bool create_new);
Program *copy_program_;
};
/**
* A renderer that renders simplex noise to its target.
*/
class SimplexNoiseRenderer : public TextureRenderer
{
public:
SimplexNoiseRenderer(const LibMatrix::vec2 &size);
virtual ~SimplexNoiseRenderer() { delete noise_program_; }
LibMatrix::vec2 uv_scale() { return uv_scale_; }
private:
static Program *noise_program(bool create_new);
static LibMatrix::vec2 uv_scale_;
Program *noise_program_;
};
/**
* A renderer that renders a normal map to its target from a
* height map in its input texture.
*/
class NormalFromHeightRenderer : public TextureRenderer
{
public:
NormalFromHeightRenderer(const LibMatrix::vec2 &size);
virtual ~NormalFromHeightRenderer() { delete normal_from_height_program_; }
private:
static Program *normal_from_height_program(const LibMatrix::vec2 &size,
bool create_new);
Program *normal_from_height_program_;
};
/**
* A renderer that renders the luminance of its input texture to its target.
*/
class LuminanceRenderer : public TextureRenderer
{
public:
LuminanceRenderer(const LibMatrix::vec2 &size);
virtual ~LuminanceRenderer() { delete luminance_program_; }
private:
static Program *luminance_program(bool create_new);
Program *luminance_program_;
};
/**
* A renderer that renders a blurred version of the input texture to its target.
*/
class BlurRenderer : public TextureRenderer
{
public:
enum BlurDirection {
BlurDirectionHorizontal,
BlurDirectionVertical,
BlurDirectionBoth
};
BlurRenderer(const LibMatrix::vec2 &size, int radius, float sigma,
BlurDirection dir, const LibMatrix::vec2 &step, float tilt_shift);
virtual ~BlurRenderer() { delete blur_program_; }
private:
static Program *blur_program(bool create_new, int radius, float sigma,
BlurDirection dir, const LibMatrix::vec2 &step,
float tilt_shift);
Program *blur_program_;
};
/**
* A renderer that renders with opacity (overlays) it's input texture over
* the target of another renderer.
*/
class OverlayRenderer : public IRenderer
{
public:
OverlayRenderer(IRenderer &target, GLfloat opacity);
virtual ~OverlayRenderer() { }
/* IRenderable Methods */
void setup(const LibMatrix::vec2 &size, bool onscreen, bool has_depth);
void setup_texture(GLint min_filter, GLint mag_filter,
GLint wrap_s, GLint wrap_t);
void input_texture(GLuint t) { input_texture_ = t; }
virtual GLuint texture() { return target_renderer_.texture(); }
virtual LibMatrix::vec2 size() { return target_renderer_.size(); }
virtual void render();
void make_current();
void update_mipmap();
private:
void create_mesh();
void create_program();
Mesh mesh_;
Program program_;
IRenderer &target_renderer_;
GLfloat opacity_;
GLuint input_texture_;
};
/**
* A renderer that renders a dynamic terrain as per the WebGL
* dynamic terrain demo.
*/
class TerrainRenderer : public BaseRenderer
{
public:
TerrainRenderer(const LibMatrix::vec2 &size, const LibMatrix::vec2 &repeat_overlay);
virtual ~TerrainRenderer();
/* IRenderable Methods */
virtual void render();
/**
* Gets the program associated with the renderer.
*/
Program &program() { return program_; }
/**
* Sets the height map texture to use.
*/
void height_map_texture(GLuint tex) { height_map_tex_ = tex; }
/**
* Sets the normal map texture to use.
*/
void normal_map_texture(GLuint tex) { normal_map_tex_ = tex; }
/**
* Sets the specular map texture to use.
*/
void specular_map_texture(GLuint tex) { specular_map_tex_ = tex; }
/**
* Returns the main diffuse texture.
*/
GLuint diffuse1_texture() { return diffuse1_tex_; }
LibMatrix::vec2 repeat_overlay() { return repeat_overlay_; }
private:
void create_mesh();
void init_textures();
void init_program();
void bind_textures();
void deinit_textures();
LibMatrix::vec3 color_to_vec3(uint32_t c)
{
return LibMatrix::vec3(((c >> 0) & 0xff) / 255.0,
((c >> 8) & 0xff) / 255.0,
((c >> 16) & 0xff) / 255.0);
}
Mesh mesh_;
Program program_;
GLuint height_map_tex_;
GLuint normal_map_tex_;
GLuint specular_map_tex_;
GLuint diffuse1_tex_;
GLuint diffuse2_tex_;
GLuint detail_tex_;
LibMatrix::vec2 repeat_overlay_;
};