//----------------------------------------------------------------------------- // 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). *
* Tristrip order elems look like this: * 0 1 2 2 1 3 2 3 4 4 3 5 4 5 7 7 5 6 <-- elems * b a a b b a b a a b b a b a a b b <-- ab pattern * \ 1 / \ 2 / \ 3 / \ 4 / \ 5 / <-- baa/bba groups */ void Stripmine(int numelems, unsigned int *elems); /** * Modifiy the vertices coord in function of vertex deformations. * @param s the basis surfaces * @param level the tesselation level for surface * @see Shader * @todo Terminate the autosprite + autosprite2 deformations. * @todo Terminate the normal deformation. */ void SetVertexCoords(Surface *s, int level = 0); /** * @todo Save last tcgen and last tcmod to know if we dont have * to recopy the coordinates. */ void SetTextureCoordinates(int tmu, Layer *l); void SetVertexColors(int tmu, Layer *l); /** * Generates the perspective matrix. * @param fov the camera fov * @param aspect the aspect ratio * @todo Put that in glutils... * @test Carmack uses vertical fov to deal with 16:9 monitors! */ void Perspective(float fov, float aspect); /** * Creates a fog texture. * Current fog version doesn't use any extension. The fog is simulated * with the fog texture. The fog texture is rendered in an additional pass * and texture coordinates are chosen in function of distance between vertex * and camera. See SetTextureCoordinates() function for details on texture * coordinates generation. * @param t The destination texture. */ void CreateFogTexture(texinfo *t); }; #endif /* __RENDER_H__ */