Copyright 2008-2014 Matus Chochlik. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <oglplus/dsa/ext/buffer.hpp>
#include <oglplus/dsa/ext/framebuffer.hpp>
#include <oglplus/dsa/ext/renderbuffer.hpp>
#include <oglplus/dsa/ext/texture.hpp>
#include <map>
namespace oglplus {
class DrawProg
{
private:
{
vs.Source(
"#version 330\n"
"uniform mat4 ProjectionMatrix, CameraMatrix;"
"layout (std140) uniform OffsetBlock {vec3 Offset[16*16*16];};"
"in vec3 Position;"
"void main(void)"
"{"
" gl_Position = "
" ProjectionMatrix *"
" CameraMatrix *"
" vec4(Position+Offset[gl_InstanceID], 1.0);"
"}"
).Compile();
fs.Source(
"#version 330\n"
"out float fragValue;"
"void main(void)"
"{"
" fragValue = 1.0/16.0;"
"}"
).Compile();
prog.AttachShader(vs).AttachShader(fs).Link().Use();
return std::move(prog);
}
Program&
self(void) {
return *
this; }
public:
ProgramUniform<Mat4f> projection_matrix, camera_matrix;
DrawProg(void)
, projection_matrix(self(), "ProjectionMatrix")
, camera_matrix(self(), "CameraMatrix")
{ }
};
class ScreenProg
{
private:
{
vs.Source(
"#version 330\n"
"uniform vec2 ScreenSize;"
"in vec4 Position;"
"in vec2 TexCoord;"
"out vec2 vertTexCoord;"
"void main(void)"
"{"
" gl_Position = Position;"
" vertTexCoord = TexCoord*ScreenSize;"
"}"
).Compile();
fs.Source(
"#version 330\n"
"uniform sampler1D Palette;"
"uniform sampler2DRect Tex;"
"in vec2 vertTexCoord;"
"out vec4 fragColor;"
"void main(void)"
"{"
" float Overdraw = texture(Tex, vertTexCoord).r;"
" fragColor = texture(Palette, Overdraw);"
"}"
).Compile();
prog.AttachShader(vs).AttachShader(fs).Link().Use();
return std::move(prog);
}
Program&
self(void) {
return *
this; }
public:
ProgramUniform<Vec2f> screen_size;
ScreenProg(void)
, screen_size(self(), "ScreenSize")
{ }
};
struct OffsetData
: public std::vector<GLfloat>
{
OffsetData(GLuint n)
: std::vector<GLfloat>(n*n*n*4)
{
GLfloat d = 1.414f;
auto p = begin();
for(GLuint k=0; k!=n; ++k)
{
GLfloat z = (k-(n+1)*0.5f)*d;
for(GLuint j=0; j!=n; ++j)
{
GLfloat y = (j-(n+1)*0.5f)*d;
for(GLuint i=0; i!=n; ++i)
{
GLfloat x = (i-(n+1)*0.5f)*d;
(*p++) = x;
(*p++) = y;
(*p++) = z;
(*p++) = 0;
}
}
}
}
};
class CubeExample : public Example
{
private:
const GLuint n;
Context gl;
ScreenProg screen_prog;
DrawProg draw_prog;
shapes::ShapeWrapper screen, cube;
DSABufferEXT cube_pos;
DSATextureEXT palette, tex;
DSAFramebufferEXT fbo;
DSARenderbufferEXT rbo;
public:
CubeExample(void)
: n(16)
, screen_prog()
, draw_prog()
, cube(
List(
"Position").Get(), shapes::Cube(), draw_prog)
{
draw_prog.Use();
<< OffsetData(n);
ProgramUniformSampler(screen_prog, "Palette").Set(0);
Texture::Active(0);
palette << Texture::Target::_1D
<< images::LinearGradient(
16,
std::map<GLfloat, Vec3f>({
{ 0.0/16.0,
Vec3f(0.0, 0.0, 0.0)},
{ 1.0/16.0,
Vec3f(0.5, 0.0, 1.0)},
{ 3.0/16.0,
Vec3f(0.0, 0.0, 1.0)},
{ 6.0/16.0,
Vec3f(0.0, 0.6, 0.6)},
{ 8.0/16.0,
Vec3f(0.0, 1.0, 0.0)},
{ 11.0/16.0,
Vec3f(0.6, 0.6, 0.0)},
{ 13.0/16.0,
Vec3f(1.0, 0.1, 0.0)},
{ 16.0/16.0,
Vec3f(0.7, 0.0, 0.0)}
})
);
ProgramUniformSampler(screen_prog, "Tex").Set(1);
Texture::Active(1);
tex << Texture::Target::Rectangle
<< images::ImageSpec(
64, 64,
);
fbo << Framebuffer::Target::Draw
<< FramebufferComplete();
gl.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl.ClearDepth(1.0f);
}
void Reshape(GLuint width, GLuint height)
{
gl.Viewport(width, height);
draw_prog.projection_matrix.Set(
Degrees(70),
double(width)/height,
1, 100
)
);
screen_prog.screen_size.Set(width, height);
tex.Image2D(
0,
width, height,
0,
nullptr
);
}
void RenderOffscreen(double time)
{
fbo.Bind(Framebuffer::Target::Draw);
gl.Clear().ColorBuffer().DepthBuffer();
draw_prog.Use();
draw_prog.camera_matrix.Set(
27.0,
Degrees(time * 23),
)
);
cube.Use();
cube.Draw(n*n*n);
dfb.Bind(Framebuffer::Target::Draw);
}
void RenderOnscreen(double)
{
screen_prog.Use();
screen.Use();
screen.Draw();
}
{
RenderOffscreen(time);
RenderOnscreen(time);
}
double ScreenshotTime(void) const
{
return 8.1;
}
{
return time < 30.0;
}
};
void setupExample(ExampleParams& ){ }
std::unique_ptr<ExampleThread> makeExampleThread(
Example& ,
unsigned ,
const ExampleParams&
){ return std::unique_ptr<ExampleThread>(); }
std::unique_ptr<Example> makeExample(const ExampleParams& )
{
return std::unique_ptr<Example>(new CubeExample);
}
}