void WorldRenderer::RenderWorld(const corgi::CameraInterface& camera, fplbase::Renderer& renderer, World* world) { mat4 camera_transform = camera.GetTransformMatrix(); renderer.set_color(mathfu::kOnes4f); renderer.DepthTest(true); renderer.set_model_view_projection(camera_transform); assert(textured_shadowed_shader_); textured_shadowed_shader_->SetUniform("view_projection", camera_transform); textured_shadowed_shader_->SetUniform("light_view_projection", light_camera_.GetTransformMatrix()); textured_shadowed_shader_->SetUniform( "shadow_intensity", world->config->rendering_config()->shadow_intensity()); float shadow_intensity = world->config->rendering_config()->shadow_intensity(); float ambient_intensity = 1.0f - shadow_intensity; vec4 ambient = vec4(ambient_intensity, ambient_intensity, ambient_intensity, 1.0f); float diffuse_intensity = shadow_intensity; vec4 diffuse = vec4(diffuse_intensity, diffuse_intensity, diffuse_intensity, 1.0f); textured_lit_cutout_shader_->SetUniform("ambient_material", ambient); textured_lit_cutout_shader_->SetUniform("diffuse_material", diffuse); textured_lit_shader_->SetUniform("ambient_material", ambient); textured_lit_shader_->SetUniform("diffuse_material", diffuse); textured_lit_bank_shader_->SetUniform("ambient_material", ambient); textured_lit_bank_shader_->SetUniform("diffuse_material", diffuse); textured_skinned_lit_shader_->SetUniform("ambient_material", ambient); textured_skinned_lit_shader_->SetUniform("diffuse_material", diffuse); float texture_repeats = world->config->river_config()->texture_repeats(); float river_offset = world->river_component.river_offset(); river_shader_->SetUniform("river_offset", river_offset); river_shader_->SetUniform("texture_repeats", texture_repeats); SetFogUniforms(textured_shadowed_shader_, world); SetFogUniforms(textured_lit_shader_, world); SetFogUniforms(textured_lit_bank_shader_, world); SetFogUniforms(textured_skinned_lit_shader_, world); shadow_map_.BindAsTexture(kShadowMapTextureID); if (!world->skip_rendermesh_rendering) { for (int pass = 0; pass < corgi::RenderPass_Count; pass++) { world->render_mesh_component.RenderPass(pass, camera, renderer); } } if (world->draw_debug_physics) { world->physics_component.DebugDrawWorld(&renderer, camera_transform); } }
void WorldRenderer::CreateShadowMap(const corgi::CameraInterface& camera, fplbase::Renderer& renderer, World* world) { float shadow_map_resolution = static_cast<float>( world->config->rendering_config()->shadow_map_resolution()); float shadow_map_zoom = world->config->rendering_config()->shadow_map_zoom(); float shadow_map_offset = world->config->rendering_config()->shadow_map_offset(); vec3 light_position = LoadVec3(world->config->rendering_config()->light_position()); SetLightPosition(light_position); light_camera_.set_viewport_angle(kShadowMapViewportAngle / shadow_map_zoom); light_camera_.set_viewport_resolution( vec2(shadow_map_resolution, shadow_map_resolution)); vec3 light_camera_focus = camera.position() + camera.facing() * shadow_map_offset; light_camera_focus.z() = 0; vec3 light_facing = light_camera_focus - light_camera_.position(); light_camera_.set_facing(light_facing.Normalized()); // Shadow map needs to be cleared to near-white, since that's // the maximum (furthest) depth. shadow_map_.SetAsRenderTarget(); renderer.ClearFrameBuffer(kShadowMapClearColor); renderer.SetCulling(fplbase::Renderer::kCullBack); depth_shader_->Set(renderer); // Generate the shadow map: // TODO - modify this so that shadowcast is its own render pass for (int pass = 0; pass < corgi::RenderPass_Count; pass++) { world->render_mesh_component.RenderPass(pass, light_camera_, renderer, depth_shader_); } }
void TouchscreenButton::DebugRender(const vec3& position, const vec3& texture_size, fplbase::Renderer& renderer) const { #if defined(DEBUG_RENDER_BOUNDS) if (debug_shader_ && draw_bounds_) { const vec2 window_size = vec2(renderer.window_size()); static const float kButtonZDepth = 0.0f; static const fplbase::Attribute kFormat[] = {fplbase::kPosition3f, fplbase::kEND }; static const unsigned short kIndices[] = {0, 1, 1, 3, 2, 3, 2, 0}; const vec3 bottom_left = position - (texture_size / 2.0f); const vec3 top_right = position + (texture_size / 2.0f); // vertex format is [x, y, z] float vertices[] = { bottom_left.x(), bottom_left.y(), bottom_left.z(), top_right.x(), bottom_left.y(), bottom_left.z(), bottom_left.x(), top_right.y(), top_right.z(), top_right.x(), top_right.y(), top_right.z(), }; renderer.set_color(vec4(1.0f, 0.0f, 1.0f, 1.0f)); debug_shader_->Set(renderer); fplbase::Mesh::RenderArray(fplbase::Mesh::kLines, 8, kFormat, sizeof(float) * 3, reinterpret_cast<const char*>(vertices), kIndices); renderer.set_color(vec4(1.0f, 1.0f, 0.0f, 1.0f)); debug_shader_->Set(renderer); static unsigned short indicesButtonDef[] = {1, 0, 1, 2, 2, 3, 3, 0}; float verticesButtonDef[] = { button_def()->top_left()->x() * window_size.x(), button_def()->top_left()->y() * window_size.y(), kButtonZDepth, button_def()->top_left()->x() * window_size.x(), button_def()->bottom_right()->y() * window_size.y(), kButtonZDepth, button_def()->bottom_right()->x() * window_size.x(), button_def()->bottom_right()->y() * window_size.y(), kButtonZDepth, button_def()->bottom_right()->x() * window_size.x(), button_def()->top_left()->y() * window_size.y(), kButtonZDepth, }; fplbase::Mesh::RenderArray(fplbase::Mesh::kLines, 8, kFormat, sizeof(float) * 3, reinterpret_cast<const char*>(verticesButtonDef), indicesButtonDef); } #else (void)position; (void)texture_size; (void)renderer; #endif // DEBUG_RENDER_BOUNDS }
void WorldRenderer::CreateShadowMap(const corgi::CameraInterface &camera, fplbase::Renderer &renderer, World *world) { PushDebugMarker("CreateShadowMap"); PushDebugMarker("Setup"); float shadow_map_resolution = static_cast<float>( world->config->rendering_config()->shadow_map_resolution()); float shadow_map_zoom = world->config->rendering_config()->shadow_map_zoom(); float shadow_map_offset = world->config->rendering_config()->shadow_map_offset(); LightComponent *light_component = world->entity_manager.GetComponent<LightComponent>(); const EntityRef &main_light_entity = light_component->begin()->entity; const TransformData *light_transform = world->entity_manager.GetComponentData<TransformData>(main_light_entity); vec3 light_position = light_transform->position; SetLightPosition(light_position); float viewport_angle = world->config->rendering_config()->shadow_map_viewport_angle() * kDegreesToRadians; light_camera_.set_viewport_angle(viewport_angle / shadow_map_zoom); light_camera_.set_viewport_resolution( vec2(shadow_map_resolution, shadow_map_resolution)); vec3 light_camera_focus = camera.position() + camera.facing() * shadow_map_offset; light_camera_focus.z = 0; vec3 light_facing = light_camera_focus - light_camera_.position(); light_camera_.set_facing(light_facing.Normalized()); // Shadow map needs to be cleared to near-white, since that's // the maximum (furthest) depth. shadow_map_.SetAsRenderTarget(); renderer.ClearFrameBuffer(kShadowMapClearColor); renderer.SetCulling(fplbase::kCullingModeBack); depth_shader_->Set(renderer); depth_skinned_shader_->Set(renderer); // Generate the shadow map: // TODO - modify this so that shadowcast is its own render pass PopDebugMarker(); // Setup for (int pass = 0; pass < corgi::RenderPass_Count; pass++) { PushDebugMarker("RenderPass"); world->render_mesh_component.RenderPass(pass, light_camera_, renderer, ShaderIndex_Depth); PopDebugMarker(); } fplbase::RenderTarget::ScreenRenderTarget(renderer).SetAsRenderTarget(); PopDebugMarker(); // CreateShadowMap }
void TouchscreenButton::Render(fplbase::Renderer& renderer) { static const float kButtonZDepth = 0.0f; if (!is_visible_) { return; } renderer.set_color(vec4(color_)); auto mat = (button_.is_down() && down_material_ != nullptr) ? down_material_ : up_current_ < up_materials_.size() ? up_materials_[up_current_] : nullptr; if (!mat) return; // This is an invisible button. const vec2 window_size = vec2(renderer.window_size()); const float texture_scale = window_size.y() * one_over_cannonical_window_height_; vec2 base_size = LoadVec2( is_highlighted_ ? button_def_->draw_scale_highlighted() : (button_.is_down() ? button_def_->draw_scale_pressed() : button_def_->draw_scale_normal())); auto pulse = sinf(static_cast<float>(elapsed_time_) / 100.0f); if (is_highlighted_) { base_size += mathfu::kOnes2f * pulse * 0.05f; } vec3 texture_size = texture_scale * vec3(mat->textures()[0]->size().x() * base_size.x(), -mat->textures()[0]->size().y() * base_size.y(), 0); vec3 position = vec3(button_def()->texture_position()->x() * window_size.x(), button_def()->texture_position()->y() * window_size.y(), kButtonZDepth); renderer.set_color(mathfu::kOnes4f); if (is_active_ || inactive_shader_ == nullptr) { shader_->Set(renderer); } else { inactive_shader_->Set(renderer); } mat->Set(renderer); fplbase::Mesh::RenderAAQuadAlongX(position - (texture_size / 2.0f), position + (texture_size / 2.0f), vec2(0, 1), vec2(1, 0)); #if defined(DEBUG_RENDER_BOUNDS) DebugRender(position, texture_size, renderer); #endif // DEBUG_RENDER_BOUNDS }
static void RenderSettingsGear(fplbase::Renderer& renderer, World* world) { vec2i res = renderer.window_size(); renderer.set_model_view_projection(mathfu::mat4::Ortho( 0.0f, static_cast<float>(res.x), static_cast<float>(res.y), 0.0f, -1.0f, 1.0f)); renderer.set_color(mathfu::kOnes4f); auto shader = world->asset_manager->LoadShader("shaders/textured"); world->cardboard_settings_gear->Set(renderer); shader->Set(renderer); fplbase::Mesh::RenderAAQuadAlongX( vec3((res.x - kGearSize) / 2.0f, res.y - kGearSize, 0.0f), vec3((res.x + kGearSize) / 2.0f, res.y, 0.0f)); }
void RenderMeshComponent::RenderAllEntities(fplbase::Renderer& renderer, const CameraInterface& camera) { // Make sure we only draw the front-facing polygons: renderer.SetCulling(fplbase::Renderer::kCullBack); // Render the actual game: for (int pass = 0; pass < RenderPass_Count; pass++) { RenderPass(pass, camera, renderer); } }
void StaticImage::Render(fplbase::Renderer& renderer) { if (!Valid()) return; if (!is_visible_) return; renderer.set_color(vec4(color_)); auto material = materials_[current_material_index_]; const vec2 window_size = vec2(renderer.window_size()); const float texture_scale = window_size.y() * one_over_cannonical_window_height_; const vec2 texture_size = texture_scale * vec2(material->textures()[0]->size()) * vec2(scale_); const vec2 position_percent = vec2(texture_position_); const vec2 position = window_size * position_percent; const vec3 position3d(position.x(), position.y(), image_def_->z_depth()); const vec3 texture_size3d(texture_size.x(), -texture_size.y(), 0.0f); shader_->Set(renderer); material->Set(renderer); fplbase::Mesh::RenderAAQuadAlongX(position3d - texture_size3d * 0.5f, position3d + texture_size3d * 0.5f, vec2(0, 1), vec2(1, 0)); }
// Draw the shadow map in the world, so we can see it. void WorldRenderer::DebugShowShadowMap(const corgi::CameraInterface& camera, fplbase::Renderer& renderer) { fplbase::RenderTarget::ScreenRenderTarget(renderer).SetAsRenderTarget(); static const mat4 kDebugTextureWorldTransform = mat4::FromScaleVector(mathfu::vec3(10.0f, 10.0f, 10.0f)); const mat4 mvp = camera.GetTransformMatrix() * kDebugTextureWorldTransform; const mat4 world_matrix_inverse = kDebugTextureWorldTransform.Inverse(); renderer.set_camera_pos(world_matrix_inverse * camera.position()); renderer.set_light_pos(world_matrix_inverse * light_camera_.position()); renderer.set_model_view_projection(mvp); renderer.set_color(vec4(1.0f, 1.0f, 1.0f, 1.0f)); shadow_map_.BindAsTexture(0); textured_shader_->Set(renderer); // Render a large quad in the world, with the shadowmap texture on it: fplbase::Mesh::RenderAAQuadAlongX(vec3(0.0f, 0.0f, 0.0f), vec3(10.0f, 0.0f, 10.0f), vec2(1.0f, 0.0f), vec2(0.0f, 1.0f)); }
void RenderWorld(fplbase::Renderer& renderer, World* world, Camera& camera, Camera* cardboard_camera, fplbase::InputSystem* input_system) { vec2 window_size = vec2(renderer.window_size()); world->river_component.UpdateRiverMeshes(); if (world->rendering_mode() == kRenderingStereoscopic) { window_size.x = window_size.x / 2; cardboard_camera->set_viewport_resolution(window_size); } camera.set_viewport_resolution(window_size); if (world->rendering_mode() == kRenderingStereoscopic) { // This takes care of setting/clearing the framebuffer for us. RenderStereoscopic(renderer, world, camera, cardboard_camera, input_system); } else { // Always clear the framebuffer, even though we overwrite it with the // skybox, since it's a speedup on tile-based architectures, see .e.g.: // http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-TileBasedArchitectures.pdf renderer.ClearFrameBuffer(mathfu::kZeros4f); if (world->RenderingOptionEnabled(kShadowEffect)) { world->world_renderer->RenderShadowMap(camera, renderer, world); } world->world_renderer->RenderWorld(camera, renderer, world); } }
void WorldRenderer::RenderWorld(const corgi::CameraInterface &camera, fplbase::Renderer &renderer, World *world) { PushDebugMarker("Render World"); PushDebugMarker("Scene Setup"); if (world->RenderingOptionsDirty()) { RefreshGlobalShaderDefines(world); } mat4 camera_transform = camera.GetTransformMatrix(); renderer.set_color(mathfu::kOnes4f); renderer.SetDepthFunction(fplbase::kDepthFunctionLess); renderer.set_model_view_projection(camera_transform); float texture_repeats = world->CurrentLevel()->river_config()->texture_repeats(); float river_offset = world->river_component.river_offset(); if (world->RenderingOptionEnabled(kShadowEffect)) { world->asset_manager->ForEachShaderWithDefine( kDefinesText[kShadowEffect], [&](fplbase::Shader *shader) { shader->SetUniform("view_projection", camera_transform); shader->SetUniform("light_view_projection", light_camera_.GetTransformMatrix()); }); } world->asset_manager->ForEachShaderWithDefine( "WATER", [&](fplbase::Shader *shader) { shader->SetUniform("river_offset", river_offset); shader->SetUniform("texture_repeats", texture_repeats); }); world->asset_manager->ForEachShaderWithDefine( kDefinesText[kPhongShading], [&](fplbase::Shader *shader) { SetLightingUniforms(shader, world); }); world->asset_manager->ForEachShaderWithDefine( "FOG_EFFECT", [&](fplbase::Shader *shader) { SetFogUniforms(shader, world); }); shadow_map_.BindAsTexture(kShadowMapTextureID); PopDebugMarker(); // Scene Setup if (!world->skip_rendermesh_rendering) { for (int pass = 0; pass < corgi::RenderPass_Count; pass++) { PushDebugMarker("RenderPass"); world->render_mesh_component.RenderPass(pass, camera, renderer); PopDebugMarker(); } } if (world->draw_debug_physics) { PushDebugMarker("Debug Draw World"); world->physics_component.DebugDrawWorld(&renderer, camera_transform); PopDebugMarker(); } PushDebugMarker("Text"); world->render_3d_text_component.RenderAllEntities(camera); PopDebugMarker(); PopDebugMarker(); // Render World }
static float AspectRatio(const fplbase::Renderer& renderer) { return static_cast<float>(renderer.window_size().x) / renderer.window_size().y; }
// Render a single render-pass, by ID. void RenderMeshComponent::RenderPass(int pass_id, const CameraInterface& camera, fplbase::Renderer& renderer, const fplbase::Shader* shader_override) { mat4 camera_vp = camera.GetTransformMatrix(); for (size_t i = 0; i < pass_render_list_[pass_id].size(); i++) { EntityRef& entity = pass_render_list_[pass_id][i].entity; RenderMeshData* rendermesh_data = Data<RenderMeshData>(entity); TransformData* transform_data = Data<TransformData>(entity); AnimationData* anim_data = Data<AnimationData>(entity); // TODO: anim_data will set uniforms for an array of matricies. Each // matrix represents one bone position. const bool has_anim = anim_data != nullptr && anim_data->motivator.Valid(); const int num_mesh_bones = rendermesh_data->mesh->num_bones(); const int num_anim_bones = has_anim ? anim_data->motivator.DefiningAnim()->NumBones() : 0; const bool has_one_bone_anim = has_anim && (num_mesh_bones <= 1 || num_anim_bones == 1); const mat4 world_transform = has_one_bone_anim ? transform_data->world_transform * mat4::FromAffineTransform( anim_data->motivator.GlobalTransforms()[0]) : transform_data->world_transform; const mat4 mvp = camera_vp * world_transform; const mat4 world_matrix_inverse = world_transform.Inverse(); renderer.set_light_pos(world_matrix_inverse * light_position_); renderer.set_color(rendermesh_data->tint); renderer.set_model(world_transform); // If the mesh has a skeleton, we need to update the bone positions. // The positions are normally supplied by the animation, but if they are // not, use the default pose in the RenderMesh. if (num_mesh_bones > 1) { const bool use_default_pose = num_anim_bones != num_mesh_bones || rendermesh_data->default_pose; const mathfu::AffineTransform* bone_transforms = use_default_pose ? rendermesh_data->mesh->bone_global_transforms() : anim_data->motivator.GlobalTransforms(); rendermesh_data->mesh->GatherShaderTransforms( bone_transforms, rendermesh_data->shader_transforms); renderer.SetBoneTransforms(rendermesh_data->shader_transforms, rendermesh_data->num_shader_transforms); } if (!camera.IsStereo()) { renderer.set_camera_pos(world_matrix_inverse * camera.position()); renderer.set_model_view_projection(mvp); if (!shader_override && rendermesh_data->shader) { rendermesh_data->shader->Set(renderer); } else { shader_override->Set(renderer); } rendermesh_data->mesh->Render(renderer); } else { const fplbase::Shader* shader = nullptr; if (!shader_override && rendermesh_data->shader) { shader = rendermesh_data->shader; } else { shader = shader_override; } mathfu::vec4i viewport[2] = {camera.viewport(0), camera.viewport(1)}; mat4 camera_vp_stereo = camera.GetTransformMatrix(1); mat4 mvp_matrices[2] = {mvp, camera_vp_stereo * world_transform}; vec3 camera_positions[2] = {world_matrix_inverse * camera.position(0), world_matrix_inverse * camera.position(1)}; rendermesh_data->mesh->RenderStereo(renderer, shader, viewport, mvp_matrices, camera_positions); } } }