void Canvas::wheelEvent(QWheelEvent *event) { // Find GL position before the zoom operation // (to zoom about mouse cursor) auto p = event->pos(); QVector3D v(1 - p.x() / (0.5*width()), p.y() / (0.5*height()) - 1, 0); QVector3D a = transform_matrix().inverted() * view_matrix().inverted() * v; if (event->delta() < 0) { for (int i=0; i > event->delta(); --i) zoom *= 1.001; } else if (event->delta() > 0) { for (int i=0; i < event->delta(); ++i) zoom /= 1.001; } // Then find the cursor's GL position post-zoom and adjust center. QVector3D b = transform_matrix().inverted() * view_matrix().inverted() * v; center += b - a; update(); }
// TODO(Zhardas): Make a template for vertex buffer structure. void Renderer::DrawScene(std::shared_ptr<Scene> scene) { LPDIRECT3DDEVICE9 device = device_; device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(255, color_.r, color_.g, color_.b), 1.0f, 0); device->BeginScene(); // Move camera auto cam_pos = scene->camera_->position_; D3DXMATRIX view_matrix; D3DXMatrixIdentity(&view_matrix); view_matrix(3, 0) = -cam_pos.x; view_matrix(3, 1) = -cam_pos.y; view_matrix(3, 2) = cam_pos.z; // TODO(Zhardas): 3D: Check the assigned value. device->SetTransform(D3DTS_VIEW, &view_matrix); for (const auto &layer : *scene->GetLayers()) { // NOTE: Scene has a limit of 256 layers. UINT index = 0; // Generate Vertex Buffer switch (layer->type()) { case Layer::STATIC: { if (layer->reload_) { layer->reload_ = false; if (layer->vertex_buffer_ != NULL) { layer->vertex_buffer_->Release(); } layer->vertex_buffer_ = GenerateVertexBuffer(STATIC, &layer->drawable_list_); } break; } case Layer::DYNAMIC: { layer->vertex_buffer_ = GenerateVertexBuffer(DYNAMIC, &layer->drawable_list_); break; } } // Setup and draw if (layer->vertex_buffer_ != NULL) { device_->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1); device_->SetStreamSource(0, layer->vertex_buffer_, 0, sizeof(v_3ct)); for (const auto &obj : layer->drawable_list_) { DrawComplex(obj.get(), index, layer->visible_); } } // Release dynamic buffers if (layer->type() == Layer::DYNAMIC && layer->vertex_buffer_ != nullptr) { layer->vertex_buffer_->Release(); layer->vertex_buffer_ = NULL; } } device->EndScene(); device->Present(NULL, NULL, NULL, NULL); }
kmVec3 Camera::project_point(ViewportID vid, const kmVec3& point) { if(!scene_) { throw LogicError("Passes a nullptr as a camera's Scene"); } kglt::Viewport& viewport = scene_->window().viewport(vid); kmVec3 tmp; kmVec3Fill(&tmp, point.x, point.y, point.z); kmVec3 result; kmVec3MultiplyMat4(&tmp, &tmp, &view_matrix()); kmVec3MultiplyMat4(&tmp, &tmp, &projection_matrix()); tmp.x /= tmp.z; tmp.y /= tmp.z; float vp_width = viewport.width(); float vp_height = viewport.height(); result.x = (tmp.x + 1) * vp_width / 2.0; result.y = (tmp.y + 1) * vp_height / 2.0; return result; }
vec3 camera_t::screen_to_world_coord(vec2 const& screen_coord) const { vec4 vp; vp.xy = viewport.bottom_left; vp.zw = viewport.size_d2 * 2.0f; return unProject(vec3(screen_coord, 0.0f), view_matrix(), projection_ortho(), vp).xyz; }
void Canvas::draw_mesh() { mesh_shader.bind(); // Load the transform and view matrices into the shader glUniformMatrix4fv( mesh_shader.uniformLocation("transform_matrix"), 1, GL_FALSE, transform_matrix().data()); glUniformMatrix4fv( mesh_shader.uniformLocation("view_matrix"), 1, GL_FALSE, view_matrix().data()); // Compensate for z-flattening when zooming glUniform1f(mesh_shader.uniformLocation("zoom"), 1/zoom); // Find and enable the attribute location for vertex position const GLuint vp = mesh_shader.attributeLocation("vertex_position"); glEnableVertexAttribArray(vp); // Then draw the mesh with that vertex position mesh->draw(vp); // Clean up state machine glDisableVertexAttribArray(vp); mesh_shader.release(); }
void Camera2::ensure_matrix_valid() const { if (m_matrix_valid) return; m_matrix = projection_matrix() * view_matrix(); m_matrix_valid = true; }
void Camera::update_frustum() { //Recalculate the view matrix kmMat4Inverse(&view_matrix_, &transform_); kmMat4 mvp; kmMat4Multiply(&mvp, &projection_matrix(), &view_matrix()); frustum_.build(&mvp); //Update the frustum for this camera }
static void pointer(const viewglut *P, int x, int y, int zoom, double v[3]) { const double W = (double) glutGet(GLUT_WINDOW_WIDTH); const double H = (double) glutGet(GLUT_WINDOW_HEIGHT); const double z = zoom ? 0.5 : view_matrix(P->V, NULL, NULL); v[0] = P->n * z * (2.0 * x / W - 1.0); v[1] = -P->n * z * (2.0 * y / H - 1.0) * H / W; v[2] = -P->n; }
int menu(int * matrix[MATRIX_SIZE][MATRIX_SIZE], STRING * name_list[MATRIX_SIZE]) { system("cls"); printf("MAIN MENU\n\nPlease make a selection.\n"); printf("0: Quit\n"); printf("1: Modify relations\n"); printf("2: View mapping\n"); printf("3: View Adjacency Matrix\n"); printf("4: New mapping\n"); char c; int q=0; c = getch(); c-=48; switch(c) { case 0: { q=1; break; } case 1: { break; } case 2: { view_mapping(name_list); getch(); break; } case 3: { view_matrix(matrix); break; } case 4: { create_mapping(name_list); break; } default: { printf("n/a"); break; } } return q; }
void Instance::Render(GLfloat aspect) { glUseProgram(program); //We change view by click the mosue float t = float(GetTickCount() & 0x3FFFF) / float(0x3FFFF); static float q = 0.0f; static const glm::vec3 X(1.0f, 0.0f, 0.0f); static const glm::vec3 Y(0.0f, 1.0f, 0.0f); static const glm::vec3 Z(0.0f, 0.0f, 1.0f); // Set model matrices for each instance glm::mat4 matrices[INSTANCE_COUNT]; for (int n = 0; n < INSTANCE_COUNT; n++) { float a = 50.0f * float(n) / 4.0f; float b = 50.0f * float(n) / 5.0f; float c = 50.0f * float(n) / 6.0f; matrices[n] = glm::rotate(glm::mat4(1.0), a + t * 360.0f, glm::vec3(1.0f, 0.0f, 0.0f)) * glm::rotate(glm::mat4(1.0), b + t * 360.0f, glm::vec3(0.0f, 1.0f, 0.0f)) * glm::rotate(glm::mat4(1.0), c + t * 360.0f, glm::vec3(0.0f, 0.0f, 1.0f)) * glm::translate(glm::mat4(1.0), glm::vec3(10.0f + a, 40.0f + b, 50.0f + c)); } glBindBuffer(GL_TEXTURE_BUFFER, model_tbo); glBufferData(GL_TEXTURE_BUFFER, sizeof(matrices), matrices, GL_DYNAMIC_DRAW); glBindBuffer(GL_TEXTURE_BUFFER, 0); glm::mat4 projection_matrix(glm::frustum(-1.0f, 1.0f, -aspect, aspect, 1.0f, 5000.0f)); glUniformMatrix4fv(proj_loc, 1, GL_FALSE, glm::value_ptr(projection_matrix)); glm::mat4 view_matrix(glm::translate(glm::mat4(1.0), glm::vec3(0.0f, 0.0f, -1500.0f)) * glm::rotate(glm::mat4(1.0), t * 360.0f * 2.0f, glm::vec3(0.0f, 1.0f, 0.0f))); glUniformMatrix4fv(view_loc, 1, GL_FALSE, glm::value_ptr(view_matrix)); //Draw the instance m_Armadillo.Render(0, INSTANCE_COUNT); glUseProgram(0); }
void viewglut_apply(const viewglut *P) { double v[3], M[16]; assert(P); /* Get the view matrix and compute the view frustum parameters. */ view_matrix(P->V, M, NULL); pointer(P, 0, 0, 0, v); /* Set the projection and view matrices. */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(+v[0], -v[0], -v[1], +v[1], P->n, P->f); glMatrixMode(GL_MODELVIEW); glLoadMatrixd(M); }
void Canvas::mouseMoveEvent(QMouseEvent* event) { auto p = event->pos(); auto d = p - mouse_pos; if (event->buttons() & Qt::LeftButton) { yaw = fmod(yaw - d.x(), 360); tilt = fmax(0, fmin(180, tilt - d.y())); update(); } else if (event->buttons() & Qt::RightButton) { center = transform_matrix().inverted() * view_matrix().inverted() * QVector3D(-d.x() / (0.5*width()), d.y() / (0.5*height()), 0); update(); } mouse_pos = p; }
kmVec3 Camera::project_point(const RenderTarget &target, const Viewport &viewport, const kmVec3& point) { if(!window_) { throw std::logic_error("Passed a nullptr as a camera's window"); } kmVec3 tmp; kmVec3Fill(&tmp, point.x, point.y, point.z); kmVec3 result; kmVec3MultiplyMat4(&tmp, &tmp, &view_matrix()); kmVec3MultiplyMat4(&tmp, &tmp, &projection_matrix()); tmp.x /= tmp.z; tmp.y /= tmp.z; float vp_width = viewport.width_in_pixels(target); float vp_height = viewport.height_in_pixels(target); result.x = (tmp.x + 1) * vp_width / 2.0; result.y = (tmp.y + 1) * vp_height / 2.0; return result; }
void Process(VertexData& vertex) { Vec3<int> mec = Vec3<int>(gstate.getMaterialEmissiveR(), gstate.getMaterialEmissiveG(), gstate.getMaterialEmissiveB()); Vec3<int> mac = (gstate.materialupdate&1) ? vertex.color0.rgb() : Vec3<int>(gstate.getMaterialAmbientR(), gstate.getMaterialAmbientG(), gstate.getMaterialAmbientB()); Vec3<int> final_color = mec + mac * Vec3<int>(gstate.getAmbientR(), gstate.getAmbientG(), gstate.getAmbientB()) / 255; Vec3<int> specular_color(0, 0, 0); for (unsigned int light = 0; light < 4; ++light) { // Always calculate texture coords from lighting results if environment mapping is active // TODO: specular lighting should affect this, too! // TODO: Not sure if this really should be done even if lighting is disabled altogether if (gstate.getUVGenMode() == GE_TEXMAP_ENVIRONMENT_MAP) { Vec3<float> L = Vec3<float>(getFloat24(gstate.lpos[3*light]&0xFFFFFF), getFloat24(gstate.lpos[3*light+1]&0xFFFFFF),getFloat24(gstate.lpos[3*light+2]&0xFFFFFF)); float diffuse_factor = Dot(L,vertex.worldnormal) / L.Length() / vertex.worldnormal.Length(); if (gstate.getUVLS0() == light) vertex.texturecoords.s() = (diffuse_factor + 1.f) / 2.f; if (gstate.getUVLS1() == light) vertex.texturecoords.t() = (diffuse_factor + 1.f) / 2.f; } } if (!gstate.isLightingEnabled()) return; for (unsigned int light = 0; light < 4; ++light) { if (!gstate.isLightChanEnabled(light)) continue; // L = vector from vertex to light source // TODO: Should transfer the light positions to world/view space for these calculations Vec3<float> L = Vec3<float>(getFloat24(gstate.lpos[3*light]&0xFFFFFF), getFloat24(gstate.lpos[3*light+1]&0xFFFFFF),getFloat24(gstate.lpos[3*light+2]&0xFFFFFF)); L -= vertex.worldpos; float d = L.Length(); float lka = getFloat24(gstate.latt[3*light]&0xFFFFFF); float lkb = getFloat24(gstate.latt[3*light+1]&0xFFFFFF); float lkc = getFloat24(gstate.latt[3*light+2]&0xFFFFFF); float att = 1.f; if (!gstate.isDirectionalLight(light)) { att = 1.f / (lka + lkb * d + lkc * d * d); if (att > 1.f) att = 1.f; if (att < 0.f) att = 0.f; } float spot = 1.f; if (gstate.isSpotLight(light)) { Vec3<float> dir = Vec3<float>(getFloat24(gstate.ldir[3*light]&0xFFFFFF), getFloat24(gstate.ldir[3*light+1]&0xFFFFFF),getFloat24(gstate.ldir[3*light+2]&0xFFFFFF)); float _spot = Dot(-L,dir) / d / dir.Length(); float cutoff = getFloat24(gstate.lcutoff[light]&0xFFFFFF); if (_spot > cutoff) { spot = _spot; float conv = getFloat24(gstate.lconv[light]&0xFFFFFF); spot = pow(_spot, conv); } else { spot = 0.f; } } // ambient lighting Vec3<int> lac = Vec3<int>(gstate.getLightAmbientColorR(light), gstate.getLightAmbientColorG(light), gstate.getLightAmbientColorB(light)); final_color.r() += (int)(att * spot * lac.r() * mac.r() / 255); final_color.g() += (int)(att * spot * lac.g() * mac.g() / 255); final_color.b() += (int)(att * spot * lac.b() * mac.b() / 255); // diffuse lighting Vec3<int> ldc = Vec3<int>(gstate.getDiffuseColorR(light), gstate.getDiffuseColorG(light), gstate.getDiffuseColorB(light)); Vec3<int> mdc = (gstate.materialupdate&2) ? vertex.color0.rgb() : Vec3<int>(gstate.getMaterialDiffuseR(), gstate.getMaterialDiffuseG(), gstate.getMaterialDiffuseB()); float diffuse_factor = Dot(L,vertex.worldnormal) / d / vertex.worldnormal.Length(); if (gstate.isUsingPoweredDiffuseLight(light)) { float k = getFloat24(gstate.materialspecularcoef&0xFFFFFF); diffuse_factor = pow(diffuse_factor, k); } if (diffuse_factor > 0.f) { final_color.r() += (int)(att * spot * ldc.r() * mdc.r() * diffuse_factor / 255); final_color.g() += (int)(att * spot * ldc.g() * mdc.g() * diffuse_factor / 255); final_color.b() += (int)(att * spot * ldc.b() * mdc.b() * diffuse_factor / 255); } if (gstate.isUsingSpecularLight(light)) { Vec3<float> E(0.f, 0.f, 1.f); Mat3x3<float> view_matrix(gstate.viewMatrix); Vec3<float> worldE = view_matrix.Inverse() * (E - Vec3<float>(gstate.viewMatrix[9], gstate.viewMatrix[10], gstate.viewMatrix[11])); Vec3<float> H = worldE / worldE.Length() + L / L.Length(); Vec3<int> lsc = Vec3<int>(gstate.getSpecularColorR(light), gstate.getSpecularColorG(light), gstate.getSpecularColorB(light)); Vec3<int> msc = (gstate.materialupdate&4) ? vertex.color0.rgb() : Vec3<int>(gstate.getMaterialSpecularR(), gstate.getMaterialSpecularG(), gstate.getMaterialSpecularB()); float specular_factor = Dot(H,vertex.worldnormal) / H.Length() / vertex.worldnormal.Length(); float k = getFloat24(gstate.materialspecularcoef&0xFFFFFF); specular_factor = pow(specular_factor, k); if (specular_factor > 0.f) { specular_color.r() += (int)(att * spot * lsc.r() * msc.r() * specular_factor / 255); specular_color.g() += (int)(att * spot * lsc.g() * msc.g() * specular_factor / 255); specular_color.b() += (int)(att * spot * lsc.b() * msc.b() * specular_factor / 255); } } } vertex.color0.r() = final_color.r(); vertex.color0.g() = final_color.g(); vertex.color0.b() = final_color.b(); if (gstate.isUsingSecondaryColor()) { vertex.color1 = specular_color; } else { vertex.color0.r() += specular_color.r(); vertex.color0.g() += specular_color.g(); vertex.color0.b() += specular_color.b(); vertex.color1 = Vec3<int>(0, 0, 0); } int maa = (gstate.materialupdate&1) ? vertex.color0.a() : gstate.getMaterialAmbientA(); vertex.color0.a() = gstate.getAmbientA() * maa / 255; if (vertex.color0.r() > 255) vertex.color0.r() = 255; if (vertex.color0.g() > 255) vertex.color0.g() = 255; if (vertex.color0.b() > 255) vertex.color0.b() = 255; if (vertex.color0.a() > 255) vertex.color0.a() = 255; if (vertex.color1.r() > 255) vertex.color1.r() = 255; if (vertex.color1.g() > 255) vertex.color1.g() = 255; if (vertex.color1.b() > 255) vertex.color1.b() = 255; if (vertex.color0.r() < 0) vertex.color0.r() = 0; if (vertex.color0.g() < 0) vertex.color0.g() = 0; if (vertex.color0.b() < 0) vertex.color0.b() = 0; if (vertex.color0.a() < 0) vertex.color0.a() = 0; if (vertex.color1.r() < 0) vertex.color1.r() = 0; if (vertex.color1.g() < 0) vertex.color1.g() = 0; if (vertex.color1.b() < 0) vertex.color1.b() = 0; }
glm::mat4 pv_matrix(){ return projection_matrix()*view_matrix(); }
ViewCoords TransformUnit::WorldToView(const WorldCoords& coords) { Mat3x3<float> view_matrix(gstate.viewMatrix); return ViewCoords(view_matrix * coords) + Vec3<float>(gstate.viewMatrix[9], gstate.viewMatrix[10], gstate.viewMatrix[11]); }
void GLRenderer::RenderScene() { // set depth to read/write glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); // clear framebuffer const float clearDepth = (cameraData.isOrtho) ? 0.0f : 1.0f; glClearBufferfv(GL_DEPTH, 0, &clearDepth); const float clearColor[] = { 0.0f, 1.0f, 1.0f, 1.0f }; glClearBufferfv(GL_COLOR, 0, clearColor); cull_frustum_obb_list(frustum, boundingBoxes, NUM_MODELS * NUM_SUBMESHES, boundsVisible); // sort meshes //renderQueue.Sort(CompareMeshes()); // loop through and draw meshes mat4x4 view = view_matrix(cameraData.viewX, cameraData.viewY, cameraData.viewZ, cameraData.position); mat4x4 viewProjection = cameraData.projection * view; RenderPhase phase = PHASE_TRANSPARENT; int material = 0; ViewportLayer viewportLayer = LAYER_GUI; int cnt = 0; FOR_EACH(mesh, renderQueue) { //*** VIEWPORT LAYER CHANGE *** if(mesh->viewportLayer != viewportLayer) { viewportLayer = (ViewportLayer) mesh->viewportLayer; switch(viewportLayer) { case LAYER_SCREEN: case LAYER_GUI: { glDisable(GL_DEPTH_TEST); break; } case LAYER_WORLD: { break; } } } //*** PHASE CHANGE *** if(mesh->phase != phase) { phase = (RenderPhase) mesh->phase; switch(phase) { case PHASE_SOLID: { defaultShader.Bind(); break; } case PHASE_MASKED: { alphaTestShader.Bind(); break; } case PHASE_BACKGROUND: { glDepthMask(GL_FALSE); defaultShader.Bind(); break; } case PHASE_TRANSPARENT: { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break; } case PHASE_COMMUTATIVE: { break; } } } //*** MATERIAL CHANGE *** if(mesh->material != material) { GLUniformBuffer::BufferData(materialUniformBuffer, &mesh->materialBlock, sizeof mesh->materialBlock); glBindTexture(GL_TEXTURE_2D, mesh->textureID); } //*** DRAW CALL *** mesh->objectBlock.modelViewProjection = viewProjection * mesh->model; GLUniformBuffer::BufferData(objectUniformBuffer, &mesh->objectBlock, sizeof mesh->objectBlock); if(boundsVisible[cnt++]) mesh->Draw(); } ObjectBlock objectBlock; objectBlock.modelViewProjection = viewProjection * MAT_I; GLUniformBuffer::BufferData(objectUniformBuffer, &objectBlock, sizeof objectBlock); glBindTexture(GL_TEXTURE_2D, scaleTexture); Terrain::Render(); for(int i = 0; i < NUM_MODELS * NUM_SUBMESHES; i++) { GLPrimitives::AddLineBox(boundingBoxes[i].center, 2 * boundingBoxes[i].extents); } GLPrimitives::Draw(); /* const vec4 verts[] = { vec4(-20, -10, 0, 1), vec4(-10, -10, 0, 1), vec4(-20, 10, 0, 1), vec4(-20, 10, 0, 1), vec4(-10, -10, 0, 1), vec4(-10, 10, 0, 1), }; const vec2 coords[] = { vec2(0.0f, 0.0f), vec2(1.0f, 0.0f), vec2(0.0f, 1.0f), vec2(0.0f, 1.0f), vec2(1.0f, 0.0f), vec2(1.0f, 1.0f), }; GLPrimitives::AddTris(verts, coords, 6); GLPrimitives::Draw(); GLPrimitives::AddLineBox(VEC3_ONE, vec3(10, 10, 10), QUAT_I); GLPrimitives::AddLineBox(vec3(10, 0, 0), vec3(10, 10, 10), QUAT_I); GLPrimitives::AddLineBox(vec3(20, 0, 0), vec3(10, 10, 10), QUAT_I); GLPrimitives::AddLineSphere(vec3(30, 10, 0), 10.0f); GLPrimitives::Draw(); */ //*** SKY PASS *** /* defaultShader.Bind(); defaultShader.SetTexture(0, blankTexture); const float farthest = (isOrtho) ? -0.999999f : 0.999999f; const vec4 skyVerts[] = { vec4(-1, -1, farthest, 1), vec4(1, -1, farthest, 1), vec4(-1, 1, farthest, 1), vec4(-1, 1, farthest, 1), vec4(1, -1, farthest, 1), vec4(1, 1, farthest, 1), }; const vec2 skyCoords[] = { vec2(0.0f, 0.0f), vec2(1.0f, 0.0f), vec2(0.0f, 1.0f), vec2(0.0f, 1.0f), vec2(1.0f, 0.0f), vec2(1.0f, 1.0f), }; GLPrimitives::AddTris(skyVerts, skyCoords, ARRAY_LENGTH(skyVerts)); GLPrimitives::Draw(); */ }
glm::mat4 Camera::sent_uniform(GLuint programID,float aspect,std::string name){ glm::mat4 VP=view_matrix(aspect); glUniform3f(glGetUniformLocation(programID,"camera_pos"),pos.x,pos.y,pos.z); glUniformMatrix4fv(glGetUniformLocation(programID,name.c_str()),1,GL_FALSE,&(VP[0][0])); return VP; }
std::shared_ptr<Texture> RenderPass:: get_buffer(std::string const& name, CameraMode mode, bool draw_fps) { // check for existance of desired buffer if ((mode == CENTER && center_eye_buffers_.find(name) == center_eye_buffers_.end()) || (mode == LEFT && left_eye_buffers_.find(name) == left_eye_buffers_.end()) || (mode == RIGHT && right_eye_buffers_.find(name) == right_eye_buffers_.end())) { WARNING("Failed to get buffer \"%s\" from pass \"%s\": " "A buffer with this name does not exist!", name.c_str(), get_name().c_str()); return NULL; } // return appropriate buffer if it has been rendered already if (mode == CENTER && rendererd_center_eye_) return center_eye_buffers_[name]; if (mode == LEFT && rendererd_left_eye_) return left_eye_buffers_[name]; if (mode == RIGHT && rendererd_right_eye_) return right_eye_buffers_[name]; // serialize the scenegraph Optimizer optimizer; optimizer.check(pipeline_->get_current_graph(), render_mask_); // if there are dynamic texture inputs for this render pass, get the // according buffers recursively for (auto& node: optimizer.get_data().nodes_) { auto material(inputs_.find(node.material_)); if (material != inputs_.end()) { for (auto& uniform: material->second) { overwrite_uniform_texture(material->first, uniform.first, pipeline_->get_render_pass(uniform.second.first)-> get_buffer(uniform.second.second, mode)); } } } // we'll need these two very often now... OptimizedScene const& scene(optimizer.get_data()); RenderContext const& ctx(pipeline_->get_context()); // get the fbo which should be rendered to FrameBufferObject* fbo(NULL); switch (mode) { case CENTER: fbo = ¢er_eye_fbo_; break; case LEFT: fbo = &left_eye_fbo_; break; case RIGHT: fbo = &right_eye_fbo_; break; } fbo->bind(ctx); fbo->clear_color_buffers(ctx); fbo->clear_depth_stencil_buffer(ctx); ctx.render_context->set_viewport(scm::gl::viewport(math::vec2(0,0), math::vec2(fbo->width(), fbo->height()))); auto camera_it(scene.cameras_.find(camera_)); auto screen_it(scene.screens_.find(screen_)); if (camera_it != scene.cameras_.end() && screen_it != scene.screens_.end()) { auto camera(camera_it->second); auto screen(screen_it->second); math::mat4 camera_transform(camera.transform_); if (mode == LEFT) { scm::math::translate(camera_transform, -camera.stereo_width_*0.5f, 0.f, 0.f); } else if (mode == RIGHT) { scm::math::translate(camera_transform, camera.stereo_width_*0.5f, 0.f, 0.f); } auto projection(math::compute_frustum(camera_transform.column(3), screen.transform_, 0.1, 100000.f)); math::mat4 view_transform(screen.transform_); view_transform[12] = 0.f; view_transform[13] = 0.f; view_transform[14] = 0.f; view_transform[15] = 1.f; math::vec3 camera_position(camera_transform.column(3)[0], camera_transform.column(3)[1], camera_transform.column(3)[2]); view_transform = scm::math::make_translation(camera_position) * view_transform; math::mat4 view_matrix(scm::math::inverse(view_transform)); // update light data uniform block if (scene.lights_.size() > 0) { if (!light_information_) { light_information_ = new scm::gl::uniform_block<LightInformation>(ctx.render_device); } light_information_->begin_manipulation(ctx.render_context); LightInformation light; light.light_count = math::vec4i(scene.lights_.size(), scene.lights_.size(), scene.lights_.size(), scene.lights_.size()); for (unsigned i(0); i < scene.lights_.size(); ++i) { math::mat4 transform(scene.lights_[i].transform_); // calc light radius and position light.position[i] = math::vec4(transform[12], transform[13], transform[14], transform[15]); float radius = scm::math::length(light.position[i] - transform * math::vec4(0.f, 0.f, 1.f, 1.f)); light.color_radius[i] = math::vec4(scene.lights_[i].color_.r(), scene.lights_[i].color_.g(), scene.lights_[i].color_.b(), radius); } **light_information_ = light; light_information_->end_manipulation(); ctx.render_context->bind_uniform_buffer( light_information_->block_buffer(), 0); } for (auto& core: scene.nodes_) { auto geometry = GeometryBase::instance()->get(core.geometry_); auto material = MaterialBase::instance()->get(core.material_); if (material && geometry) { material->use(ctx); if (float_uniforms_.find(core.material_) != float_uniforms_.end()) { for (auto val : float_uniforms_[core.material_]) material->get_shader()->set_float(ctx, val.first, val.second); } if (texture_uniforms_.find(core.material_) != texture_uniforms_.end()) { for (auto val : texture_uniforms_[core.material_]) material->get_shader()->set_sampler2D(ctx, val.first, *val.second); } material->get_shader()->set_mat4(ctx, "projection_matrix", projection); material->get_shader()->set_mat4(ctx, "view_matrix", view_matrix); material->get_shader()->set_mat4(ctx, "model_matrix", core.transform_); material->get_shader()->set_mat4(ctx, "normal_matrix", scm::math::transpose( scm::math::inverse(core.transform_))); geometry->draw(ctx); material->unuse(ctx); } else if (material) { WARNING("Cannot render geometry \"%s\": Undefined geometry " "name!", core.geometry_.c_str()); } else if (geometry) { WARNING("Cannot render geometry \"%s\": Undefined material " "name: \"%s\"!", core.geometry_.c_str(), core.material_.c_str()); } else { WARNING("Cannot render geometry \"%s\": Undefined geometry " "and material name: \"%s\"!", core.geometry_.c_str(), core.material_.c_str()); } } if (scene.lights_.size() > 0) { ctx.render_context->reset_uniform_buffers(); } } fbo->unbind(ctx); // draw fps on the screen if (draw_fps) { if (!text_renderer_) text_renderer_ = new TextRenderer(pipeline_->get_context()); if (mode == CENTER) { text_renderer_->render_fps(pipeline_->get_context(), center_eye_fbo_, pipeline_->get_application_fps(), pipeline_->get_rendering_fps()); } else if (mode == LEFT) { text_renderer_->render_fps(pipeline_->get_context(), left_eye_fbo_, pipeline_->get_application_fps(), pipeline_->get_rendering_fps()); } else { text_renderer_->render_fps(pipeline_->get_context(), right_eye_fbo_, pipeline_->get_application_fps(), pipeline_->get_rendering_fps()); } } // return the buffer and set the already-rendered-flag if (mode == CENTER) { rendererd_center_eye_ = true; return center_eye_buffers_[name]; } else if (mode == LEFT) { rendererd_left_eye_ = true; return left_eye_buffers_[name]; } else { rendererd_right_eye_ = true; return right_eye_buffers_[name]; } }