//----------------------------------------------------------------------------- // Render + OpenGL Driver support //----------------------------------------------------------------------------- #ifndef __RENDER_H__ #define __RENDER_H__ #include "cake.h" #include "camera.h" /** * Interface with OpenGL states. * Records the current state. This class can be seen as an OpenGL states * interface. */ class State { public: // there is only a current state, thus all the members are static static void SetInitialState(int multitexture); /** * Set to default state * @todo Terminate this ! */ static void SetDefaultState(void); /** * Binds the texture of the given layer * @param l layer to bind texture to * @param unit texturing unit on the 3d card (be careful with this * because currently the only card that supports 4 texturing * units is the geforce * @test It is incredible how much time does the engine spend here! */ static void BindTexture(Layer *l, int unit); /** * Set the appropriate state to render the layer. * @test check all redundant state changes ??? */ static void setState(Layer *l); /** * Active shader states. */ static void SetupShader(void); /** * Evaluates a deform function. * @param p a parameters table * @return the function result */ static float Eval(float *p); // input related static Shader * curr_shader; static Shader * curr_effect; static int curr_depthFunc; static int curr_depthWrite; static int curr_blendsrc; static int curr_blenddst; static int curr_culling; static int curr_alphaFunc; static int curr_polygonmode; static int curr_texture[MAX_TEXTURE_UNITS]; static int skipping; static int curr_lightmap; static int last_tcgen[MAX_TEXTURE_UNITS]; static int pass; // output related // Following functions change manually an opengl state static void setDepthFunc(int val); static void setDepthWrite(int val); static void setBlend(int src, int dst); static void setCulling(int val); static void setAlphaFunc(int func, float funcref = 0); static void setPolygonMode(int val); }; /** * Vertex buffer used for arrays generation. */ typedef struct { int st_content; /**< vertex texture coordinates */ float* st; /**< 2 texture coordinates */ int c_content; /**< vertex color */ byte* c; /**< 4 colors */ } Buffer; /** * Structure used to communicate triangles to graphic card. */ typedef struct { int numelems; unsigned int * elems; /**< elements buffer */ int numverts; float* xyz; /**< 4 coordinates for a vertice */ float* tex_st; /**< 2 texture coordinates */ float* lm_st; /**< 2 lightmap coordinates */ float* normal; /**< 4 coordinates for the normal */ byte* c; /**< 4 colors */ #if MODIF_FOG cplane_t** fog; /**< fog plane */ #else float* fog; /**< 5 fog parameters (normal, dist and type) */ #endif } Input; typedef void (APIENTRY *swapcommand_t) (void); /** * Render class. * The render is a class that interacts with OpenGL driver. All faces are * sent to the OpenGL API through the render. * For now, the render supposes that we use GLUT in the main program for * window management. * This has to consequence that some 3D graphic cards shouldn't work * correctly with the engine, especially the cards which need dynamic drivers * (3Dfx voodoo based cards for example). For these cards, we should rewrite * the driver and use GLS.H instead of GLUT.H and GL.H. *
* Notes on the Quake 3 axis system : * ______________________________________ * | | * | | * | Z /|\ _ Y | This represents the orientation * | | /| _____ | of axis in the engine for a * | | / / /| | camera angle of (90 0 0). * | | / /____ / | O O | * | | / | | | /|\ \|/ | (by default, the camera has a * | | / | | / | | | pitch = 90, otherwise, the * | | / |_____|/ / \ / \ | camera looks to the ground) * | |/ \ | * | --+----------------------- X | * | /| O / | * | | * |______________________________________| * * The Quake3 axis system is similar to OpenGL system (right hand system). * On the above figure, the pitch of camera is 90. This explains why Z axis * is going up. * In fact, the engine considers Oxy plane as ground and Oz vector as up * vector. * In the engine, XYZ axis can be viewed using the grid display. The x, y * and z axis are respectively displayed in red, green and blue colors. * They have a length of 1000 and are centered at position (0,0,0). ** The global principle of render work is to push triangles that have same * shader on a stack, and then to send all the stack to the graphic card * using
glDrawElements
. A state system is used to store
* texture and shader parameters of the triangles.
* @see State
* @todo Resolve the display problem: the first top line of the screen
* doesn't displays correctly. If r_clear == 1, the first line of
* the screen manifestly appears incorrect.
* @bug Check that camera is defined for each part that require the camera pointer.
*/
class Render
{
private:
int state;
Input input;
Buffer buffer[MAX_TEXTURE_UNITS];
/**
* Increases the buffer size.
* @param newsize the new buffer size.
*/
void IncreaseBuffer(unsigned int newsize);
/**
* Increases the elems size.
* @param newsize the new elems size.
*/
void IncreaseElems(unsigned int newsize);
protected:
bool ext_swapControl;
swapcommand_t swapbuffersfunc;
public:
Camera* current_camera; /**< current camera used for rendering */
int ready; /**< inform if render is ready */
int windowIndex; /**< window index */
texinfo fogtexture; /**< fog texture */
int gridpass; /**< grid related */
unsigned long num_flush; /**< number of flush calls */
unsigned long num_tris; /**< number of triangles rendered */
unsigned long num_verts; /**< number of vertices */
unsigned long num_apicalls; /**< number of gl api calls */
Render(void);
~Render(void);
/**
* Indicates we are beginning a new frame.
*/
int BeginFrame(void);
/**
* Indicates the frame is finished and the render can flush all unflushed triangles.
*/
int EndFrame(void);
/**
* Reset window size and automatically recalculate the console background size.
* @param w the new width size
* @param h the new height size
* @param c the new color bit
* @param f the new frequency
*/
void SetWindowSettings(GLsizei w = -1, GLsizei h = -1, GLint c = -1, GLint f = -1);
/**
* Initialize the render.
* @param func a pointer to function used for buffers swap
* @return 1 if initialization succeeded, 0 if not
*/
int Init(swapcommand_t func);
/**
* Shuts down the render.
*/
void Shut(void);
/**
* Gets the window width.
* @return the window width
*/
int GetWidth(void);
/**
* Gets the window height.
* @return the window height
*/
int GetHeight(void);
/**
* Gets the window left position.
* @return the window left position
*/
int GetLeft(void);
/**
* Gets the window top position.
* @return the window top position
*/
int GetTop(void);
/**
* Gets a report of the current OpenGL states.
*/
void DumpGLState(void);
/**
* Check for GL error and update gl function counter
* The function depends on enableGLChecks constant. If enabled,
* the function reports the error in console for release mode and
* generates a break in debug mode.
* @param ncalls The number of api calls
*/
void CheckGLError(int ncalls = 1);
/**
* Determines if an extension is supported.
* The function must be called after a valid context has been created.
*/
bool CheckExtension(char *extName);
// TODO: Comment those functions.
int RegisterTexInfo(texinfo *tex, int flags);
void UnregisterTexInfo(texinfo *tex);
void SetRenderState(Shader *s, int lightmap = ~0, Shader *e = NULL);
void InitializeViewPort(void);
void PushTriangles(Surface *surf, int *visible = NULL);
void Flush(void);
/**
* Force the flushing.
*/
void ForceFlush(void);
// Flushing functions
void FlushMtxCVA(void);
void FlushMtx(void);
void FlushGenericCVA(void);
void FlushGeneric(void);
void FlushSingleCVA(void);
void FlushSingle(void);
void FlushVertexLit(void);
void FlushGridCVA(void);
void FlushGrid(void);
void SwapBuffers(void);
/**
* This function looks for and sends tristrips.
* Vertexes are in tristrip order where possible. If we can't lock
* the vertex arrays (glLockArraysEXT), then it's better to send
* tristrips instead of triangles (less transformations).
*