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 <cstdlib>
namespace oglplus {
class PointVertShader
{
public:
PointVertShader(void)
ObjectDesc("Vertex shader"),
"#version 330\n"
"uniform mat4 ProjectionMatrix, CameraMatrix, ModelMatrix;"
"uniform vec3 Color1, Color2;"
"uniform float Status;"
"in vec4 Position1, Position2;"
"in float Radiance1, Radiance2;"
"out vec3 vertColor;"
"void main(void)"
"{"
" gl_Position = "
" ProjectionMatrix * "
" CameraMatrix * "
" ModelMatrix * "
" mix(Position1, Position2, Status);"
" gl_PointSize = (2.0 + 3.0 * mix("
" Radiance1, "
" Radiance2, "
" Status"
" ));"
" vertColor = mix("
" (0.2 + Radiance1) * Color1,"
" (0.2 + Radiance2) * Color2,"
" Status"
" );"
"}"
)
{ }
};
class PointFragShader
{
public:
PointFragShader(void)
ObjectDesc("Fragment shader"),
"#version 330\n"
"in vec3 vertColor;"
"out vec3 fragColor;"
"void main(void)"
"{"
" fragColor = vertColor;"
"}"
)
{ }
};
class PointProgram :
public Program
{
private:
{
Program prog(ObjectDesc(
"Point program"));
prog.AttachShader(PointVertShader());
prog.AttachShader(PointFragShader());
prog.Link().Use();
return prog;
}
const Program& prog(
void)
const {
return *
this; }
public:
ProgramUniform<Mat4f> projection_matrix, camera_matrix, model_matrix;
ProgramUniform<Vec3f> color_1, color_2;
ProgramUniform<GLfloat> status;
PointProgram(void)
, projection_matrix(prog(), "ProjectionMatrix")
, camera_matrix(prog(), "CameraMatrix")
, model_matrix(prog(), "ModelMatrix")
, color_1(prog(), "Color1")
, color_2(prog(), "Color2")
, status(prog(), "Status")
{ }
};
class Shape
{
protected:
Context gl;
Array<Buffer> vbos;
const GLuint point_count;
void make_shape_1(
const Program& prog,
int vbo,
const GLchar* name)
{
vbos[vbo].Bind(Buffer::Target::Array);
std::vector<GLfloat> data(point_count * 3);
auto i = data.begin(), e = data.end();
while(i != e)
{
auto rho =
RightAngles((std::rand() % 1001)*0.002-1.0);
*i++ = Cos(phi) * Cos(rho);
*i++ = Sin(rho);
*i++ = Sin(phi) * Cos(rho);
}
Buffer::Data(Buffer::Target::Array, data);
VertexArrayAttrib attr(prog, name);
attr.Enable();
}
void make_shape_2(
const Program& prog,
int vbo,
const GLchar* name)
{
vbos[vbo].Bind(Buffer::Target::Array);
std::vector<GLfloat> data(point_count * 3);
auto i = data.begin(), e = data.end();
while(i != e)
{
*i++ = Cos(phi) * (0.5 + 0.5 * (1.0 + Cos(rho)));
*i++ = Sin(rho) * 0.5;
*i++ = Sin(phi) * (0.5 + 0.5 * (1.0 + Cos(rho)));
}
Buffer::Data(Buffer::Target::Array, data);
VertexArrayAttrib attr(prog, name);
attr.Enable();
}
void make_radiance(
const Program& prog,
int vbo,
const GLchar* name)
{
vbos[vbo].Bind(Buffer::Target::Array);
std::vector<GLfloat> data(point_count);
for(auto i=data.begin(), e=data.end(); i!=e; ++i)
*i = (std::rand() % 101) * 0.01;
Buffer::Data(Buffer::Target::Array, data);
VertexArrayAttrib attr(prog, name);
attr.Setup<GLfloat>();
attr.Enable();
}
public:
: vbos(4)
, point_count(4096)
{
vao.Bind();
make_shape_1(prog, 0, "Position1");
make_shape_2(prog, 1, "Position2");
make_radiance(prog, 2, "Radiance1");
make_radiance(prog, 3, "Radiance2");
}
{
vao.Bind();
}
};
class MorphingExample : public Example
{
private:
Context gl;
PointProgram point_prog;
Shape shape;
double status;
public:
MorphingExample(void)
: shape(point_prog)
, status(0.0)
{
point_prog.color_1 =
Vec3f(1.0f, 0.5f, 0.4f);
point_prog.color_2 =
Vec3f(1.0f, 0.8f, 0.7f);
gl.ClearColor(0.2f, 0.2f, 0.2f, 0.0f);
gl.ClearDepth(1.0f);
}
void Reshape(GLuint width, GLuint height)
{
gl.Viewport(width, height);
point_prog.projection_matrix.Set(
Degrees(48),
double(width)/height,
1, 20
)
);
}
void Render(ExampleClock& clock)
{
if(long(clock.Now().Seconds()) % 4 == 0)
{
status += clock.Interval().Seconds();
}
else if(status != double(long(status)))
{
if(status - double(long(status)) < 0.5)
status = double(long(status));
else status =1.0 + double(long(status));
}
gl.Clear().ColorBuffer().DepthBuffer();
point_prog.status = 0.5 - 0.5*
CosineWave(status * 0.5);
5.5,
Degrees(45 +
SineWave(clock.Now().Seconds()/15.0) * 40)
);
point_prog.camera_matrix.Set(camera);
point_prog.model_matrix.Set(
);
shape.Draw();
}
{
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 MorphingExample);
}
}