29
30
#include "program.h"
30
31
#include "shader-source.h"
37
using LibMatrix::vec3;
34
40
SceneTexture::SceneTexture(Canvas &pCanvas) :
35
Scene(pCanvas, "texture")
41
Scene(pCanvas, "texture"), radius_(0.0),
42
orientModel_(false), orientationAngle_(0.0)
37
mOptions["texture-filter"] = Scene::Option("texture-filter", "nearest",
38
"[nearest, linear, mipmap]");
44
const ModelMap& modelMap = Model::find_models();
46
for (ModelMap::const_iterator modelIt = modelMap.begin();
47
modelIt != modelMap.end();
50
static bool doSeparator(false);
55
const std::string& curName = modelIt->first;
56
optionValues += curName;
59
options_["model"] = Scene::Option("model", "cube", "Which model to use",
61
options_["texture-filter"] = Scene::Option("texture-filter", "nearest",
62
"The texture filter to use",
63
"nearest,linear,linear-shader,mipmap");
65
const TextureMap& textureMap = Texture::find_textures();
66
for (TextureMap::const_iterator textureIt = textureMap.begin();
67
textureIt != textureMap.end();
70
static bool doSeparator(false);
75
const std::string& curName = textureIt->first;
76
optionValues += curName;
79
options_["texture"] = Scene::Option("texture", "crate-base", "Which texture to use",
81
options_["texgen"] = Scene::Option("texgen", "false",
82
"Whether to generate texcoords in the shader",
41
86
SceneTexture::~SceneTexture()
45
int SceneTexture::load()
49
if(!model.load_3ds(GLMARK_DATA_PATH"/models/cube.3ds"))
52
model.calculate_normals();
53
model.convert_to_mesh(mCubeMesh);
54
mCubeMesh.build_vbo();
56
mRotationSpeed = LibMatrix::vec3(36.0f, 36.0f, 36.0f);
63
void SceneTexture::unload()
68
void SceneTexture::setup()
93
rotationSpeed_ = LibMatrix::vec3(36.0f, 36.0f, 36.0f);
101
SceneTexture::unload()
107
SceneTexture::setup()
73
112
static const std::string vtx_shader_filename(GLMARK_DATA_PATH"/shaders/light-basic.vert");
113
static const std::string vtx_shader_texgen_filename(GLMARK_DATA_PATH"/shaders/light-basic-texgen.vert");
74
114
static const std::string frg_shader_filename(GLMARK_DATA_PATH"/shaders/light-basic-tex.frag");
115
static const std::string frg_shader_bilinear_filename(GLMARK_DATA_PATH"/shaders/light-basic-tex-bilinear.frag");
75
116
static const LibMatrix::vec4 lightPosition(20.0f, 20.0f, 10.0f, 1.0f);
76
117
static const LibMatrix::vec4 materialDiffuse(1.0f, 1.0f, 1.0f, 1.0f);
77
ShaderSource vtx_source(vtx_shader_filename);
78
ShaderSource frg_source(frg_shader_filename);
80
// Add constants to shaders
81
vtx_source.add_const("LightSourcePosition", lightPosition);
82
vtx_source.add_const("MaterialDiffuse", materialDiffuse);
84
if (!Scene::load_shaders_from_strings(mProgram, vtx_source.str(),
90
std::vector<GLint> attrib_locations;
91
attrib_locations.push_back(mProgram["position"].location());
92
attrib_locations.push_back(mProgram["normal"].location());
93
attrib_locations.push_back(mProgram["texcoord"].location());
94
mCubeMesh.set_attrib_locations(attrib_locations);
96
119
// Create texture according to selected filtering
97
120
GLint min_filter = GL_NONE;
98
121
GLint mag_filter = GL_NONE;
99
const std::string &filter = mOptions["texture-filter"].value;
122
const std::string &filter = options_["texture-filter"].value;
101
124
if (filter == "nearest") {
102
125
min_filter = GL_NEAREST;
106
129
min_filter = GL_LINEAR;
107
130
mag_filter = GL_LINEAR;
132
else if (filter == "linear-shader") {
133
min_filter = GL_NEAREST;
134
mag_filter = GL_NEAREST;
109
136
else if (filter == "mipmap") {
110
137
min_filter = GL_LINEAR_MIPMAP_LINEAR;
111
138
mag_filter = GL_LINEAR;
114
Texture::load(GLMARK_DATA_PATH"/textures/crate-base.png", &mTexture,
115
min_filter, mag_filter, 0);
120
mRotation = LibMatrix::vec3();
122
mStartTime = Scene::get_timestamp_us() / 1000000.0;
123
mLastUpdateTime = mStartTime;
141
const string& whichTexture(options_["texture"].value);
142
if (!Texture::load(whichTexture, &texture_, min_filter, mag_filter, 0))
146
bool doTexGen(options_["texgen"].value == "true");
147
ShaderSource vtx_source;
149
vtx_source.append_file(vtx_shader_texgen_filename);
150
vtx_source.add_const("PI", static_cast<float>(M_PI));
153
vtx_source.append_file(vtx_shader_filename);
155
ShaderSource frg_source;
156
if (filter == "linear-shader") {
157
frg_source.append_file(frg_shader_bilinear_filename);
158
LibMatrix::vec2 texture_size(512, 512);
159
frg_source.add_const("TextureSize", texture_size);
162
frg_source.append_file(frg_shader_filename);
165
// Add constants to shaders
166
vtx_source.add_const("LightSourcePosition", lightPosition);
167
vtx_source.add_const("MaterialDiffuse", materialDiffuse);
169
if (!Scene::load_shaders_from_strings(program_, vtx_source.str(),
176
const string& whichModel(options_["model"].value);
177
bool modelLoaded = model.load(whichModel);
181
// Now that we're successfully loaded, there are a few quirks about
182
// some of the known models that we need to account for. The draw
183
// logic for the scene wants to rotate the model around the Y axis.
184
// Most of our models are described this way. Some need adjustment
185
// (an additional rotation that gets the model into the correct
190
// Angel rotates around the Y axis
191
// Armadillo rotates around the Y axis
192
// Buddha rotates around the X axis
193
// Bunny rotates around the Y axis
194
// Dragon rotates around the X axis
195
// Horse rotates around the Y axis
196
if (whichModel == "buddha" || whichModel == "dragon")
199
orientationAngle_ = -90.0;
200
orientationVec_ = vec3(1.0, 0.0, 0.0);
202
else if (whichModel == "armadillo")
205
orientationAngle_ = 180.0;
206
orientationVec_ = vec3(0.0, 1.0, 0.0);
209
if (model.needTexcoords())
210
model.calculate_texcoords();
211
model.calculate_normals();
212
// Tell the converter which attributes we care about
213
std::vector<std::pair<Model::AttribType, int> > attribs;
214
attribs.push_back(std::pair<Model::AttribType, int>(Model::AttribTypePosition, 3));
215
attribs.push_back(std::pair<Model::AttribType, int>(Model::AttribTypeNormal, 3));
217
attribs.push_back(std::pair<Model::AttribType, int>(Model::AttribTypeTexcoord, 2));
219
model.convert_to_mesh(mesh_, attribs);
222
// Calculate a projection matrix that is a good fit for the model
223
vec3 maxVec = model.maxVec();
224
vec3 minVec = model.minVec();
225
vec3 diffVec = maxVec - minVec;
226
centerVec_ = maxVec + minVec;
228
float diameter = diffVec.length();
229
radius_ = diameter / 2;
230
float fovy = 2.0 * atanf(radius_ / (2.0 + radius_));
233
float aspect(static_cast<float>(canvas_.width())/static_cast<float>(canvas_.height()));
234
perspective_.setIdentity();
235
perspective_ *= LibMatrix::Mat4::perspective(fovy, aspect, 2.0, 2.0 + diameter);
239
std::vector<GLint> attrib_locations;
240
attrib_locations.push_back(program_["position"].location());
241
attrib_locations.push_back(program_["normal"].location());
243
program_["CenterPoint"] = centerVec_;
246
attrib_locations.push_back(program_["texcoord"].location());
248
mesh_.set_attrib_locations(attrib_locations);
251
rotation_ = LibMatrix::vec3();
253
startTime_ = Util::get_timestamp_us() / 1000000.0;
254
lastUpdateTime_ = startTime_;
126
void SceneTexture::teardown()
260
SceneTexture::teardown()
131
glDeleteTextures(1, &mTexture);
265
glDeleteTextures(1, &texture_);
133
267
Scene::teardown();
136
void SceneTexture::update()
271
SceneTexture::update()
138
double current_time = Scene::get_timestamp_us() / 1000000.0;
139
double dt = current_time - mLastUpdateTime;
140
double elapsed_time = current_time - mStartTime;
142
mLastUpdateTime = current_time;
144
if (elapsed_time >= mDuration) {
145
mAverageFPS = mCurrentFrame / elapsed_time;
149
mRotation += mRotationSpeed * dt;
275
double elapsed_time = lastUpdateTime_ - startTime_;
277
rotation_ = rotationSpeed_ * elapsed_time;
154
void SceneTexture::draw()
156
283
// Load the ModelViewProjectionMatrix uniform in the shader
157
284
LibMatrix::Stack4 model_view;
158
LibMatrix::mat4 model_view_proj(mCanvas.projection());
160
model_view.translate(0.0f, 0.0f, -5.0f);
161
model_view.rotate(mRotation.x(), 1.0f, 0.0f, 0.0f);
162
model_view.rotate(mRotation.y(), 0.0f, 1.0f, 0.0f);
163
model_view.rotate(mRotation.z(), 0.0f, 0.0f, 1.0f);
285
model_view.translate(-centerVec_.x(), -centerVec_.y(), -(centerVec_.z() + 2.5 + radius_));
286
model_view.rotate(rotation_.x(), 1.0f, 0.0f, 0.0f);
287
model_view.rotate(rotation_.y(), 0.0f, 1.0f, 0.0f);
288
model_view.rotate(rotation_.z(), 0.0f, 0.0f, 1.0f);
291
model_view.rotate(orientationAngle_, orientationVec_.x(), orientationVec_.y(), orientationVec_.z());
293
LibMatrix::mat4 model_view_proj(perspective_);
164
294
model_view_proj *= model_view.getCurrent();
166
mProgram["ModelViewProjectionMatrix"] = model_view_proj;
296
program_["ModelViewProjectionMatrix"] = model_view_proj;
168
298
// Load the NormalMatrix uniform in the shader. The NormalMatrix is the
169
299
// inverse transpose of the model view matrix.
170
300
LibMatrix::mat4 normal_matrix(model_view.getCurrent());
171
301
normal_matrix.inverse().transpose();
172
mProgram["NormalMatrix"] = normal_matrix;
302
program_["NormalMatrix"] = normal_matrix;
174
304
glActiveTexture(GL_TEXTURE0);
175
glBindTexture(GL_TEXTURE_2D, mTexture);
305
glBindTexture(GL_TEXTURE_2D, texture_);
177
mCubeMesh.render_vbo();
180
310
Scene::ValidationResult
181
311
SceneTexture::validate()
183
static const double radius_3d(std::sqrt(3.0));
313
static const double radius_3d(std::sqrt(3 * 2.0 * 2.0));
185
if (mRotation.x() != 0 || mRotation.y() != 0 || mRotation.z() != 0)
315
if (rotation_.x() != 0 || rotation_.y() != 0 || rotation_.z() != 0)
186
316
return Scene::ValidationUnknown;
188
318
Canvas::Pixel ref;
190
Canvas::Pixel pixel = mCanvas.read_pixel(mCanvas.width() / 2 + 3,
191
mCanvas.height() / 2 + 3);
320
Canvas::Pixel pixel = canvas_.read_pixel(canvas_.width() / 2 + 3,
321
canvas_.height() / 2 + 3);
193
const std::string &filter = mOptions["texture-filter"].value;
323
const std::string &filter = options_["texture-filter"].value;
195
325
if (filter == "nearest")
196
ref = Canvas::Pixel(0x3b, 0x3a, 0x39, 0xff);
326
ref = Canvas::Pixel(0x2b, 0x2a, 0x28, 0xff);
197
327
else if (filter == "linear")
198
ref = Canvas::Pixel(0x36, 0x36, 0x34, 0xff);
328
ref = Canvas::Pixel(0x2b, 0x2a, 0x28, 0xff);
329
else if (filter == "linear-shader")
330
ref = Canvas::Pixel(0x2d, 0x2c, 0x2a, 0xff);
199
331
else if (filter == "mipmap")
200
ref = Canvas::Pixel(0x35, 0x35, 0x34, 0xff);
332
ref = Canvas::Pixel(0x2c, 0x2d, 0x2a, 0xff);
202
334
return Scene::ValidationUnknown;
204
double dist = pixel_value_distance(pixel, ref);
336
double dist = pixel.distance_rgb(ref);
206
338
if (dist < radius_3d + 0.01) {
207
339
return Scene::ValidationSuccess;