/*
 * Copyright (C) Volition, Inc. 1999.  All rights reserved.
 *
 * All source code herein is the property of Volition, Inc. You may not sell 
 * or otherwise commercially exploit the source or things you created based on the 
 * source.
 *
*/


#ifndef GR_OPENGLDRAW_H
#define GR_OPENGLDRAW_H

#include "graphics/2d.h"
#include "gropenglstate.h"
#include "gropenglshader.h"
#include "graphics/shadows.h"
#include <glad/glad.h>

extern GLuint Scene_framebuffer;
extern GLuint Scene_framebuffer_ms;
extern GLuint Scene_ldr_texture;
extern GLuint Scene_color_texture;
extern GLuint Scene_position_texture;
extern GLuint Scene_normal_texture;
extern GLuint Scene_specular_texture;
extern GLuint Scene_emissive_texture;
extern GLuint Scene_color_texture_ms;
extern GLuint Scene_position_texture_ms;
extern GLuint Scene_normal_texture_ms;
extern GLuint Scene_specular_texture_ms;
extern GLuint Scene_emissive_texture_ms;
extern GLuint Scene_luminance_texture;
extern GLuint Scene_composite_texture;
extern GLuint Scene_depth_texture;
extern GLuint Scene_depth_texture_ms;
extern GLuint Cockpit_depth_texture;
extern GLuint Scene_stencil_buffer;

extern GLuint Back_framebuffer;
extern GLuint Back_texture;

void gr_opengl_update_distortion();

void gr_opengl_sphere(material *material_def, float rad);

void gr_opengl_shadow_map_start(matrix4 *shadow_view_matrix, const matrix *light_orient, vec3d* eye_pos);
void gr_opengl_shadow_map_end();

void gr_opengl_render_shield_impact(shield_material* material_info,
	primitive_type prim_type,
	vertex_layout* layout,
	gr_buffer_handle buffer_handle,
	int n_verts);

void opengl_setup_scene_textures();
void opengl_scene_texture_shutdown();
void gr_opengl_scene_texture_begin();
void gr_opengl_scene_texture_end();
void gr_opengl_copy_effect_texture();

void opengl_render_primitives(primitive_type prim_type,
	vertex_layout* layout,
	int n_verts,
	gr_buffer_handle buffer_handle,
	size_t vert_offset,
	size_t byte_offset);
void opengl_render_primitives_immediate(primitive_type prim_type,
	vertex_layout* layout,
	int n_verts,
	void* data,
	int size);

void gr_opengl_render_primitives(material* material_info,
	primitive_type prim_type,
	vertex_layout* layout,
	int offset,
	int n_verts,
	gr_buffer_handle buffer_handle,
	size_t buffer_offset);
void gr_opengl_render_primitives_particle(particle_material* material_info,
	primitive_type prim_type,
	vertex_layout* layout,
	int offset,
	int n_verts,
	gr_buffer_handle buffer_handle);
void gr_opengl_render_primitives_batched(batched_bitmap_material* material_info,
	primitive_type prim_type,
	vertex_layout* layout,
	int offset,
	int n_verts,
	gr_buffer_handle buffer_handle);
void gr_opengl_render_primitives_distortion(distortion_material* material_info,
	primitive_type prim_type,
	vertex_layout* layout,
	int offset,
	int n_verts,
	gr_buffer_handle buffer_handle);
void gr_opengl_render_movie(movie_material* material_info,
	primitive_type prim_type,
	vertex_layout* layout,
	int n_verts,
	gr_buffer_handle buffer,
	size_t buffer_offset);
void gr_opengl_render_nanovg(nanovg_material* material_info,
	primitive_type prim_type,
	vertex_layout* layout,
	int offset,
	int n_verts,
	gr_buffer_handle buffer_handle);
void gr_opengl_render_decals(decal_material* material_info,
	primitive_type prim_type,
	vertex_layout* layout,
	int num_elements,
	const indexed_vertex_source& binding,
	const gr_buffer_handle& instance_buffer,
	int num_instances);
void gr_opengl_render_rocket_primitives(interface_material* material_info,
	primitive_type prim_type,
	vertex_layout* layout,
	int n_indices,
	gr_buffer_handle vertex_buffer,
	gr_buffer_handle index_buffer);

void opengl_draw_textured_quad(GLfloat x1,
	GLfloat y1,
	GLfloat u1,
	GLfloat v1,
	GLfloat x2,
	GLfloat y2,
	GLfloat u2,
	GLfloat v2);

/**
 * @brief Draw "something" so that the entire screen is covered and the corners use the UV values that are provided.
 *
 * @details This actually draws a a single oversized triangle that covers the screen in such a way so that the provided
 * UV values are generated by the GPU in the corners of the screen. This is better than drawing two triangles since then
 * the diagonal would be shaded differently for the two triangles causing visual differences.
 *
 * @param u1 The U value of the lower left corner.
 * @param v1 The V value of the lower left corner.
 * @param u2 The U value of the upper right corner.
 * @param v2 The V value of the upper right corner.
 */
void opengl_draw_full_screen_textured(GLfloat u1, GLfloat v1, GLfloat u2, GLfloat v2);

inline GLenum opengl_primitive_type(primitive_type prim_type);

void gr_opengl_start_decal_pass();
void gr_opengl_stop_decal_pass();

void gr_opengl_calculate_irrmap();

extern int Scene_texture_initialized;

extern GLuint Scene_color_texture;
extern GLuint Scene_ldr_texture;
extern GLuint Scene_luminance_texture;

extern int Scene_texture_width;
extern int Scene_texture_height;

extern float Scene_texture_u_scale;
extern float Scene_texture_v_scale;

#endif	// !GR_OPENGLDRAW_H
