orangeduck / Corange

Pure C Game Engine
http://www.youtube.com/watch?v=482GxqTWXtA
Other
1.79k stars 199 forks source link

... how rotate camera? LoL ))) #31

Closed blogdron closed 5 years ago

blogdron commented 5 years ago

Hi, Daniel, I suddenly found that I did not understand how to adjust the angle of the camera. I wrote a dynamic environment for a cubic map and for rendering in a cubic texture, I move the camera to the object position, but I don’t understand how to rotate the camera on six sides.

Can you give one example, for example, turning the camera strictly up or down? And then I'll find out.

I have attached a piece of code to understand what I'm trying to do. ??

// prepare env cubemaps for surfaces
static void renderer_render_target_cubemap(renderer * dr)
{
    renderer_cubemap_dynamic_reset_counts(dr);
    vec3 cam_pos_save = dr->camera->position;

  for ( int j = 0; j < dr->render_objects_num; j++)
  {
    renderable * ren = NULL;
    if(dr->render_objects[j].type == RO_TYPE_STATIC)
    {
        dr->camera->position = dr->render_objects[j].static_object->position;
        ren = asset_hndl_ptr(&dr->render_objects[j].static_object->renderable);

    }else if(dr->render_objects[j].type == RO_TYPE_ANIMATED)
    {
        dr->camera->position = dr->render_objects[j].animated_object->position;
        ren = asset_hndl_ptr(&dr->render_objects[j].animated_object->renderable);

    }else if(dr->render_objects[j].type == RO_TYPE_INSTANCE)
    {
        //XXX: dynamic env only for one instance fix it!
        dr->camera->position = dr->render_objects[j].instance_object->instances[0].position;
        ren = asset_hndl_ptr(&dr->render_objects[j].instance_object->renderable);

    };
    GLint current_cube_texture = -1;
    for (int i = 0; i < ren->num_surfaces; ++i)
    {
       material_entry * me = material_get_entry(asset_hndl_ptr(&ren->material),i);
       if(material_entry_item(me,"envcube_dynamic").as_bool == false)
       {
            continue;
       }else{
           current_cube_texture = renderer_get_cubemap_dynamic_repare(dr);
       };
    for (int i = 0; i < 6; ++i)
    {

          swith(i)
          {      // help me this pleeeeeeeeeees ))))))))))))))))))))))
                 case 1:  dr->camera->target = /*????????*/ ;  break;
                 case 2:  dr->camera->target = /*????????*/ ; break;
                 case 3:  dr->camera->target = /*????????*/ ; break;
                 case 4:  dr->camera->target = /*????????*/ ; break;
                 case 5:  dr->camera->target = /*????????*/ ; break;
                 case 6:  dr->camera->target = /*????????*/ ; break;
          };

       dr->cubemap_dynamic_render_process = true; 
       render_shadows(dr);  
       render_clear(dr);    
       glPolygonMode( GL_FRONT_AND_BACK, dr->mode);
       render_gbuffer(dr);  
       glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
       render_ssao(dr);   
       render_skydome(dr);   
       render_skycube(dr); 
       render_compose(dr); 
       glPolygonMode( GL_FRONT_AND_BACK, dr->mode);
       render_sea(dr);    
       render_particles(dr);
       glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
       render_tonemap(dr);  
       render_post0(dr);    
       glBindFramebuffer(GL_FRAMEBUFFER, dr->cubemap_dynamic_fbo);
    glDrawBuffer(GL_COLOR_ATTACHMENT0 + i);
       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
       glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
                              GL_TEXTURE_CUBE_MAP_POSITIVE_X       + i,
                              current_cube_texture, 0);

       render_post1(dr);    
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
       dr->cubemap_dynamic_render_process = false;

    };

  };
 };
    dr->camera->position = cam_pos_save;
    renderer_set_camera(dr,dr->camera);
}

Next just render scene

blogdron commented 5 years ago

I partially solved this problem, I just thought that I was dealing with abstraction. There was an error with the fact that if the target values have exactly zero values, everything breaks and freezes, perhaps the problem in render_gbuffer is why you have to set camera values other than zero, which is bad because the coordinates of the editor are incorrectly set in a cubic map

       switch(i)
       {
              case 0: dr->camera->target = vec3_new(1,0,0); break;
              case 1: dr->camera->target = vec3_new(-1,0,0); break;
              case 2: dr->camera->target = vec3_new(0,1,0.1); break;   //bug if velue 0 frame freeze
              case 3: dr->camera->target = vec3_new(0,-1,0.1); break; //bug if velue  0 frame freeze
              case 4: dr->camera->target = vec3_new(0,0,1); break;
              case 5: dr->camera->target = vec3_new(0,0,-1); break;
       };
orangeduck commented 5 years ago

Hey - yeah the problem is one of abstraction because when you compute the view matrix for a camera defined just by the position and the target then it is undefined if the camera is pointing straight up or straight down. Instead you should probably try to set the view matrix directly (and maybe the projection matrix) if you are rendering something like a cube map. Does that make sense?

blogdron commented 5 years ago

In general, I decided everything in the forehead)))))))) I was too lazy to build separate matrices and check everything. I just set huge values ​​for the target and it works for me, everything is correctly drawn, of course it should be done normally, but it will work for me and so maybe it will be useful later

       switch(i)
       {        // it work correct! lol )))))))))))
                case 0: dr->camera->target = vec3_new(1000,0,0); break;
                case 1: dr->camera->target = vec3_new(-1000,0,0); break;
                case 2: dr->camera->target = vec3_new(0,1000,0.1000); break;
                case 3: dr->camera->target = vec3_new(0,-1000,0.1000); break;
                case 4: dr->camera->target = vec3_new(0,0,1000); break;
                case 5: dr->camera->target = vec3_new(0,0,-1000); break;
       };

The final reflections and refractions look like this, it is slow, but quite acceptable if there is, say, a real mirror in the scene or the main character wears glasses. More than three surfaces greatly reduce frames, but most importantly it works))) Click in image to video reflect-refract-dynamic

blogdron commented 5 years ago

I suffered for a very long time trying to understand how to do everything correctly, my code is bad, I will not upload it, but if someone decides for himself to render the scene into a cubic map for the dynamic environment, I will indicate the most important details, maybe it will be useful for someone. I have a lot of specifics, but by the names everything will be clear

Setting up the camera in render_gbuffer ()

  if (render_is_envcube_render_process ())
  {
    dr-> camera_view = render_get_envcube_camera_view ();
    dr-> camera_proj = camera_proj_matrix_custom (dr-> camera-> fov,
                                                dr-> camera-> near_clip,
                                                dr-> camera-> far_clip,
                                                dr-> viewport_size_x,
                                                dr-> viewport_size_y);
  } else {
    dr-> camera_view = camera_view_matrix (dr-> camera);
  };
  if (dr-> viewport_custom || render_is_envcube_render_process ())
  {
    if (dr-> viewport_custom) {
    dr-> camera_proj = camera_proj_matrix_custom (dr-> camera-> fov,
                                                dr-> camera-> near_clip,
                                                dr-> camera-> far_clip,
                                                dr-> viewport_size_x,
                                                dr-> viewport_size_y);
    };
    if (render_is_envcube_render_process ())
    {

        float ratio_size = option_graphics_int (asset_hndl_ptr (& dr-> options), "envcube", 1024,512,256);
        dr-> camera_proj = camera_proj_matrix_custom (dr-> camera-> fov,
                                                     dr-> camera-> near_clip,
                                                     dr-> camera-> far_clip,
                                                     ratio_size,
                                                     ratio_size); // or just 1
    };
  } else {
    dr-> camera_proj = camera_proj_matrix (dr-> camera);
  }

Setting post_1 ()

 if (render_is_envcube_render_process ()) {
   glViewport (dr-> viewport_position_x, dr-> viewport_position_y,
              option_graphics_int (asset_hndl_ptr (& dr-> options), "envcube", 1024,512,256),
              option_graphics_int (asset_hndl_ptr (& dr-> options), "envcube", 1024,512,256));
   glLoadIdentity ();
}
....
  shader_program_set_mat4 (shader, "proj", mat4_orthographic (1, -1, 1, -1, 1, -1)); // revert up to down

Moving the camera to the surface position


      renderable * rende = asset_hndl_ptr (& dr-> render_objects [0] .static_object-> renderable);
      vec3 posit = dr-> render_objects [0] .static_object-> position;
      dr-> camera-> position = vec3_add (rende-> surfaces [i] -> sphere.center, posit);

Turns the camera to render a cubic map

 switch (i)
               {
                    case 0: {
                    mat4 view = camera_view_matrix_custom (dr-> camera-> position,
                                                          vec3_new (10,000,0,0),
                                                          vec3_new (0,1,0));
                    render_set_envcube_camera_view (view);
                           } break;
                    case 1: {
                    mat4 view = camera_view_matrix_custom (dr-> camera-> position,
                                                          vec3_new (-10000,0,0),
                                                          vec3_new (0,1,0));
                    render_set_envcube_camera_view (view);
                           } break;
                    case 2: {
                    mat4 view = camera_view_matrix_custom (dr-> camera-> position,
                                                          vec3_new (0,10000,0),
                                                          vec3_new (0,0, -1));
                    render_set_envcube_camera_view (view);
                           } break;
                    case 3: {
                    mat4 view = camera_view_matrix_custom (dr-> camera-> position,
                                                          vec3_new (0, -10000.0),
                                                          vec3_new (0,0,1));
                    render_set_envcube_camera_view (view);
                           } break;
                    case 4: {
                    mat4 view = camera_view_matrix_custom (dr-> camera-> position,
                                                          vec3_new (0,0,10000),
                                                          vec3_new (0,1,0));
                    render_set_envcube_camera_view (view);
                           } break;
                    case 5: {
                    mat4 view = camera_view_matrix_custom (dr-> camera-> position,
                                                          vec3_new (0,0, -10000),
                                                          vec3_new (0,1,0));
                    render_set_envcube_camera_view (view);
                           } break;
               };

This is all the most important thing, the rest depends on how you implement the render to the cubic map. I used the result of the editor as a function post1 () which draws the ldr_front_buffer texture in the frame buffer instead of effects

I made a cubic map for calibration, it is convenient https://drive.google.com/file/d/1VOymM0yQ4CteJ66_84bNqWuRP9IVduAt/view?usp=sharing

Imgur

and @orangeduck thanks for the advice!

orangeduck commented 5 years ago

Look great, nice one!