예제 #1
0
void Renderer::frustum_cull(glm::vec3 camera_position, SceneObject *object,
        float frustum[6][4], std::vector<SceneObject*>& scene_objects,
        bool need_cull, int planeMask) {

    // frustumCull() return 3 possible values:
    // 0 when the HBV of the object is completely outside the frustum: cull itself and all its children out
    // 1 when the HBV of the object is intersecting the frustum but the object itself is not: cull it out and continue culling test with its children
    // 2 when the HBV of the object is intersecting the frustum and the mesh BV of the object are intersecting (inside) the frustum: render itself and continue culling test with its children
    // 3 when the HBV of the object is completely inside the frustum: render itself and all its children without further culling test
    int cullVal;
    if (need_cull) {

        cullVal = object->frustumCull(camera_position, frustum, planeMask);
        if (cullVal == 0) {
            return;
        }

        if (cullVal >= 2) {
            scene_objects.push_back(object);
        }

        if (cullVal == 3) {
            need_cull = false;
        }
    } else {
        scene_objects.push_back(object);
    }

    const std::vector<SceneObject*> children = object->children();
    for (auto it = children.begin(); it != children.end(); ++it) {
        frustum_cull(camera_position, *it, frustum, scene_objects, need_cull, planeMask);
    }
}
예제 #2
0
void Renderer::frustum_cull(glm::vec3 camera_position, SceneObject *object,
        float frustum[6][4], std::vector<SceneObject*>& scene_objects,
        bool need_cull, int planeMask) {

    // frustumCull() return 3 possible values:
    // 0 when the HBV of the object is completely outside the frustum: cull itself and all its children out
    // 1 when the HBV of the object is intersecting the frustum but the object itself is not: cull it out and continue culling test with its children
    // 2 when the HBV of the object is intersecting the frustum and the mesh BV of the object are intersecting (inside) the frustum: render itself and continue culling test with its children
    // 3 when the HBV of the object is completely inside the frustum: render itself and all its children without further culling test
    int cullVal;

    if (!object->enabled()) {
        return;
    }

    //allows for on demand calculation of the camera distance; usually matters
    //when transparent objects are in play
    RenderData* renderData = object->render_data();
    if (nullptr != renderData) {
        renderData->setCameraDistanceLambda([object, camera_position]() {
            // Transform the bounding volume
            BoundingVolume bounding_volume_ = object->getBoundingVolume();
            glm::vec4 transformed_sphere_center(bounding_volume_.center(), 1.0f);

            // Calculate distance from camera
            glm::vec4 position(camera_position, 1.0f);
            glm::vec4 difference = transformed_sphere_center - position;
            float distance = glm::dot(difference, difference);

            // this distance will be used when sorting transparent objects
            return distance;
        });
    }

    if (need_cull) {
        cullVal = object->frustumCull(camera_position, frustum, planeMask);
        if (cullVal == 0) {
            object->setCullStatus(true);
            return;
        }

        if (cullVal >= 2) {
            object->setCullStatus(false);
            scene_objects.push_back(object);
        }

        if (cullVal == 3) {
            object->setCullStatus(false);
            need_cull = false;
        }
    } else {
        object->setCullStatus(false);
        scene_objects.push_back(object);
    }

    const std::vector<SceneObject*> children = object->children();
    for (auto it = children.begin(); it != children.end(); ++it) {
        frustum_cull(camera_position, *it, frustum, scene_objects, need_cull, planeMask);
    }
}
예제 #3
0
/*
 * Perform view frustum culling from a specific camera viewpoint
 */
void Renderer::cullFromCamera(Scene *scene, Camera* camera,
        ShaderManager* shader_manager)
{
    std::vector<SceneObject*> scene_objects;
    glm::mat4 view_matrix = camera->getViewMatrix();
    glm::mat4 projection_matrix = camera->getProjectionMatrix();
    glm::mat4 vp_matrix = glm::mat4(projection_matrix * view_matrix);
    glm::vec3 campos(view_matrix[3]);

    scene_objects.reserve(1024);
    scene_objects.clear();
    render_data_vector.clear();

    // Travese all scene objects in the scene as a tree and do frustum culling at the same time if enabled
    // 1. Build the view frustum
    float frustum[6][4];
    build_frustum(frustum, (const float*) glm::value_ptr(vp_matrix));

    // 2. Iteratively execute frustum culling for each root object (as well as its children objects recursively)
    SceneObject *object = scene->getRoot();
    if (DEBUG_RENDERER) {
        LOGD("FRUSTUM: start frustum culling for root %s\n", object->name().c_str());
    }
    //    frustum_cull(camera->owner_object()->transform()->position(), object, frustum, scene_objects, scene->get_frustum_culling(), 0);
    frustum_cull(campos, object, frustum, scene_objects, scene->get_frustum_culling(), 0);
    if (DEBUG_RENDERER) {
        LOGD("FRUSTUM: end frustum culling for root %s\n", object->name().c_str());
    }
    // 3. do occlusion culling, if enabled
    occlusion_cull(scene, scene_objects, shader_manager, vp_matrix);
}
예제 #4
0
/*
 * Perform view frustum culling from a specific camera viewpoint
 */
void Renderer::cullFromCamera(Scene *scene, Camera* camera,
        ShaderManager* shader_manager,
        std::vector<SceneObject*>& scene_objects) {
    render_data_vector.clear();
    scene_objects.clear();

    glm::mat4 view_matrix = camera->getViewMatrix();
    glm::mat4 projection_matrix = camera->getProjectionMatrix();
    glm::mat4 vp_matrix = glm::mat4(projection_matrix * view_matrix);

    // 1. Travese all scene objects in the scene as a tree and do frustum culling at the same time if enabled
    if (scene->get_frustum_culling()) {
        if (DEBUG_RENDERER) {
           LOGD("FRUSTUM: start frustum culling\n");
       }

        // 1. Build the view frustum
        float frustum[6][4];
        build_frustum(frustum, (const float*) glm::value_ptr(vp_matrix));

        // 2. Iteratively execute frustum culling for each root object (as well as its children objects recursively)
        std::vector<SceneObject*> root_objects = scene->scene_objects();
        for (auto it = root_objects.begin(); it != root_objects.end(); ++it) {
            SceneObject *object = *it;
            if (DEBUG_RENDERER) {
                LOGD("FRUSTUM: start frustum culling for root %s\n",
                        object->name().c_str());
            }
            frustum_cull(camera->owner_object()->transform()->position(), object, frustum, scene_objects, true, 0);
            if (DEBUG_RENDERER) {
                LOGD("FRUSTUM: end frustum culling for root %s\n",
                        object->name().c_str());
            }
        }
        if (DEBUG_RENDERER) {
            LOGD("FRUSTUM: end frustum culling\n");
        }
    }
    else
        scene_objects = scene->getWholeSceneObjects();
    // 2. do occlusion culling, if enabled
    occlusion_cull(scene, scene_objects, shader_manager, vp_matrix);
}
예제 #5
0
int main()
{
 int exit_flag = 0, i;
 MAT16F tmat;
 VEC3F pos = vec3f(0.0, 0.0, 0.5), ang = vec3f(0.0, 0.0, 0.0);
 MD2_MODEL mdl;
 VERTEX *model_verts;
 TRI *model_tris;

 if(load_md2("data/babe.md2", &mdl))
  {
   allegro_message("Error: I need the MD2 model, stupid!");
   exit(1);
  }

 convert_md2_to_base(&model_verts, &model_tris, &mdl, 0.02);

 init();
 
 LOCK_VARIABLE(fps);
 LOCK_VARIABLE(frame_count);
 LOCK_FUNCTION(update_fps);
 install_int(update_fps, 1000);

 float frame = 0.0;
 int flag = 0, flag2 = 0;
 int anim_flag = 0, point_flag = 0;

 while(!exit_flag)
  {
   set_texture_mapping_mode(0);

   if(key[KEY_ESC]) { exit_flag = 1; }
   if(key[KEY_LEFT]) { pos.x -= 0.01; }
   if(key[KEY_RIGHT]) { pos.x += 0.01; }
   if(key[KEY_UP]) { pos.z += 0.02; }
   if(key[KEY_DOWN]) { pos.z -= 0.02; }
   if(key[KEY_SPACE]) { frame += 0.1; }
   if(key[KEY_P]) { anim_flag = anim_flag ? 0 : 1; key[KEY_P] = 0; }
   if(key[KEY_O]) { point_flag = point_flag ? 0 : 1; key[KEY_O] = 0; }

   VEC2F mp, cp;
   cp = vec2f(mouse_x, mouse_y);

   if(mouse_b == 1)
    {
     if(flag == 0)
       mp = cp;
     flag = 1;

     ang.y -= ((cp.x - mp.x) * 0.0002);
    }

   else
    flag = 0;

   if(mouse_b == 2)
    {
     if(flag2 == 0)
       mp = cp;
     flag2 = 1;

     pos.z -= ((cp.y - mp.y) * 0.0002);
    }

   else
    flag2 = 0;

   ang.x = M_PI * 1.5;

   convert_md2_frame_to_base(model_verts, &mdl, frame, 0.02);
   
   if(anim_flag)
   frame += 0.1 * (60.0 / (fps + 1.0));

   reset_mat16f(tmat);
   rotate_mat16f(tmat, ang.x, ang.y, ang.z);
   translate_mat16f(tmat, pos.x, pos.y, pos.z);

   for(i = 0; i < mdl.header.num_vertices; i++)
    {
     transform_vec3f(&model_verts[i].world, model_verts[i].local, tmat);
     project_vertex(&model_verts[i]);
    }

   clear_bitmap(buffer);
   clear_to_color(zbuffer, ZBUFFER_PRECISION);

   for(i = 0; i < mdl.header.num_tris; i++)
    {
     update_tri_normal(&model_tris[i], model_verts);
     frustum_cull(&model_tris[i], model_verts, -0.95, 20.0);
     cull_backface(&model_tris[i], model_verts);
    }

   for(i = 0; i < mdl.header.num_tris; i++)
    if(model_tris[i].vis)
     my_triangle(buffer, model_verts, model_tris[i]);

   if(point_flag)
   for(i = 0; i < mdl.header.num_tris; i++)
    if(model_tris[i].vis)
     {
      int x1 = model_verts[model_tris[i].a].sx, y1 = model_verts[model_tris[i].a].sy,
          x2 = model_verts[model_tris[i].b].sx, y2 = model_verts[model_tris[i].b].sy,
          x3 = model_verts[model_tris[i].c].sx, y3 = model_verts[model_tris[i].c].sy;

      float z, z1 = model_verts[model_tris[i].a].screen.z,
               z2 = model_verts[model_tris[i].b].screen.z,
               z3 = model_verts[model_tris[i].c].screen.z;

      if(on_bitmap(x1, y1, SCREEN_W, SCREEN_H))
       {
        z = (float)RI_PIXEL_Z(x1, y1) / (float)(ZBUFFER_PRECISION);
        if(z1 < z + 0.001) circlefill(buffer, x1, y1, 1, makecol(255, 0, 0));
       }

      if(on_bitmap(x2, y2, SCREEN_W, SCREEN_H))
       {
        z = (float)RI_PIXEL_Z(x2, y2) / (float)(ZBUFFER_PRECISION);
        if(z2 < z + 0.001) circlefill(buffer, x2, y2, 1, makecol(255, 0, 0));
       }

      if(on_bitmap(x3, y3, SCREEN_W, SCREEN_H))
       {
        z = (float)RI_PIXEL_Z(x3, y3) / (float)(ZBUFFER_PRECISION);
        if(z3 < z + 0.001) circlefill(buffer, x3, y3, 1, makecol(255, 0, 0));
       }
     }

   textprintf_ex(buffer, font, 10, 10, makecol(255, 255, 255), 0, "FPS: %d", fps);
   blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
   frame_count++;
  }

 free_md2(&mdl);
 free(model_tris);
 free(model_verts);
 destroy_bitmap(texture);
 destroy_bitmap(zbuffer);
 destroy_bitmap(buffer);
 deinit_renderer();

 return 0;
}
예제 #6
0
void main()
{
	tcPosition[ID] 	= vPosition[ID];
	tcIndex[ID] 	= vIndex[ID];
	tcTessCoord[ID] = vTessCoord[ID];

	vec4 data = texelFetch(attribute_texture, int(vIndex[ID]) * 5);

	if ( frustum_cull() ) {
		if ( abs(vTessCoord[0].x - vTessCoord[1].x) * abs(vTessCoord[1].y - vTessCoord[2].y) == 1.0 ) {
			vec4 curve_factor = clamp(texelFetch(attribute_texture, int(vIndex[ID]) * 5 + 4), 1, 4);
			vec4 edgelen = control_polygon_length(parameter_texture, int(data.x), int(data.y), int(data.z));

			//	    2
			//	2------3
			//3	|      |      1
			//      |      |
			//      0------1
			//	    0

			float edge01 = edge_tesslevel(edgelen[0]);
			float edge32 = edge_tesslevel(edgelen[2]);
			float edge13 = edge_tesslevel(edgelen[1]);
			float edge20 = edge_tesslevel(edgelen[3]);

			//Following three must be same for Ist Pass
			gl_TessLevelInner[0] = inner_tesslevel();
			gl_TessLevelOuter[1] = edge01;
			gl_TessLevelOuter[3] = edge32;

			//Following three must be same for Ist Pass
			gl_TessLevelInner[1] = inner_tesslevel();
			gl_TessLevelOuter[0] = edge20;
			gl_TessLevelOuter[2] = edge13;
		} else {
			vec4 point_on_plane0 = to_screen_space(vPosition[0]);
			vec4 point_on_plane1 = to_screen_space(vPosition[1]);
			vec4 point_on_plane2 = to_screen_space(vPosition[2]);
			vec4 point_on_plane3 = to_screen_space(vPosition[3]);

			//Approach I-----> For Outer Tessellation Levels : Take ratio according to the original control polygon length.
			//		   For Inner Tessellation Levels : Evaluate the mid point of the patch and get the diagonal length.

			vec4 edgelen = control_polygon_length(parameter_texture, int(data.x), int(data.y), int(data.z));

			vec2 p1 = mix(vTessCoord[0].xy, vTessCoord[1].xy, 0.5);
			vec2 p2 = mix(vTessCoord[3].xy, vTessCoord[2].xy, 0.5);

			vec2 mid_uv = mix(p1, p2, 0.5);
			vec4 du, dv, _puv;

			HornerBernstein(parameter_texture, int(data.x), int(data.y), int(data.z), mid_uv, du, dv, _puv);

			_puv = to_screen_space(_puv.xyz);

			float length1 = length(point_on_plane0.xy - _puv.xy) + length(_puv.xy - point_on_plane3.xy);
			float length2 = length(point_on_plane2.xy - _puv.xy) + length(_puv.xy - point_on_plane1.xy);

			float diagonal_length = min(length1, length2);

			float edge01 = edge_tesslevel(mix(edgelen[0], edgelen[2], abs(vTessCoord[0].y - vTessCoord[2].y)));
			float edge32 = edge_tesslevel(mix(edgelen[0], edgelen[2], abs(vTessCoord[0].y - vTessCoord[2].y)));
			float edge13 = edge_tesslevel(mix(edgelen[1], edgelen[3], abs(vTessCoord[0].x - vTessCoord[1].x)));
			float edge20 = edge_tesslevel(mix(edgelen[1], edgelen[3], abs(vTessCoord[0].x - vTessCoord[1].x)));

			/*****/

			//Approach II-----> For Outer Tessellation Levels : Approximate the curvature length of the edge according to the angle between its normals.
			//		    For Inner Tessellation Levels : Approximate the curvature of the surface according to the all edge normals.

			//Normals projected in XY-Plane
/*			vec2 normal0 = normalize(transpose(inverse(mat3(view_matrix * model_matrix))) * vNormal[0].xyz).xy;
			vec2 normal1 = normalize(transpose(inverse(mat3(view_matrix * model_matrix))) * vNormal[1].xyz).xy;
			vec2 normal2 = normalize(transpose(inverse(mat3(view_matrix * model_matrix))) * vNormal[2].xyz).xy;
			vec2 normal3 = normalize(transpose(inverse(mat3(view_matrix * model_matrix))) * vNormal[3].xyz).xy;

			float edge01 = edge_tesslevel(length(point_on_plane0 - point_on_plane1) * acos(dot(normal0, normal1)) / (2.0 * sin(acos(dot(normal0, normal1) / 2.0))));
			float edge32 = edge_tesslevel(length(point_on_plane3 - point_on_plane2) * acos(dot(normal3, normal2)) / (2.0 * sin(acos(dot(normal3, normal2) / 2.0))));
			float edge13 = edge_tesslevel(length(point_on_plane1 - point_on_plane3) * acos(dot(normal1, normal3)) / (2.0 * sin(acos(dot(normal1, normal3) / 2.0))));
			float edge20 = edge_tesslevel(length(point_on_plane2 - point_on_plane0) * acos(dot(normal2, normal0)) / (2.0 * sin(acos(dot(normal2, normal0) / 2.0))));*/

			//Following three must be same for Ist Pass
			gl_TessLevelInner[0] = edge_tesslevel(diagonal_length);
			gl_TessLevelOuter[1] = edge01;
			gl_TessLevelOuter[3] = edge32;

			//Following three must be same for Ist Pass
			gl_TessLevelInner[1] = edge_tesslevel(diagonal_length);
			gl_TessLevelOuter[0] = edge20;
			gl_TessLevelOuter[2] = edge13;
		}
	} else {
		gl_TessLevelInner[0] = 1;
		gl_TessLevelOuter[1] = 1;
		gl_TessLevelOuter[3] = 1;

		gl_TessLevelInner[1] = 1;
		gl_TessLevelOuter[0] = 1;
		gl_TessLevelOuter[2] = 1;
	}
}