//************************************************************** //* OpenGLide for Macintosh - Glide to OpenGL Wrapper //* http://macglide.sourceforge.net/ //* //* implementation of the GLRender class //* //* OpenGLide is OpenSource under LGPL license //* Originaly made by Fabio Barros //* Modified by Paul for Glidos (http://www.glidos.net) //* Mac version and additional features by Jens-Olaf Hemprich //************************************************************** #include "Glide.h" #include "GlideApplication.h" #include "GlideFrameBuffer.h" #include "GlideSettings.h" #include "GLextensions.h" #include "GLRender.h" #include "GLRenderUpdateState.h" #include "PGTexture.h" // The functions for the color combine ALPHAFACTORFUNCPROC AlphaFactorFunc; COLORFACTORFUNCPROC ColorFactor3Func; COLORFUNCTIONPROC ColorFunctionFunc; // Snapping constant static const float vertex_snap_compare = 4096.0f; static const float vertex_snap = float( 3L << 18 ); #define DEBUG_MIN_MAX( var, maxvar, minvar ) \ if ( var > maxvar ) maxvar = var; \ if ( var < minvar ) minvar = var; // Standard structs for the render RenderStruct OGLRender; // Variables for the AddXXX functions static TColorStruct Local, Other, CFactor; #ifdef OGL_DEBUG_GLIDE_COORDS void GlideMsg(const GrVertex* v, float maxoow) { GlideMsg("vertex(x=%g,y=%g,ooz=%g,oow=%g)", v->x, v->y, v->ooz, v->oow); GlideMsg(",tmu0(sow=%g,tow=%g,oow=%g)\n", v->tmuvtx[0].sow * maxoow, v->tmuvtx[0].tow * maxoow, v->tmuvtx[0].oow); } #endif #ifdef OGL_DEBUG_OPENGL_COORDS void GlideMsg(TVertexStruct* v) { GlideMsg(" glVertex(x=%g,y=%g,z=%g)", v->ax, v->ay, v->az); GlideMsg(" glVertex(x=%g,y=%g,z=%g)", v->bx, v->by, v->bz); GlideMsg(" glVertex(x=%g,y=%g,z=%g)", v->cx, v->cy, v->cz); } #endif #ifdef OGL_DEBUG_OPENGL_COORDS void GlideMsg(TVertexStruct* v, TTextureStruct* t) { GlideMsg(" glVertex(x=%g,y=%g,z=%g)", v->ax, v->ay, v->az); GlideMsg(", glTexture(s=%g,t=%g,q=%g,w=%g)\n", t->as, t->at, t->aq, t->aoow); GlideMsg(" glVertex(x=%g,y=%g,z=%g)", v->bx, v->by, v->bz); GlideMsg(", glTexture(s=%g,t=%g,q=%g,w=%g)\n", t->bs, t->bt, t->bq, t->boow); GlideMsg(" glVertex(x=%g,y=%g,z=%g)", v->cx, v->cy, v->cz); GlideMsg(", glTexture(s=%g,t=%g,q=%g,w=%g)\n", t->cs, t->ct, t->cq, t->coow); } #endif inline GLfloat precision_fix(GLfloat oow) { const GLfloat w = 1.0f / oow; return 8.9375f - (GLfloat( ( (*(FxU32 *)&w >> 11) & 0xFFFFF ) * D1OVER65536) ); } void RenderInitialize(void) { #ifdef OGL_ALL GlideMsg( "RenderInitialize()\n"); #endif glReportErrors("RenderInitialize"); // Allocate vertex array buffers OGLRender.NumberOfTriangles = 0; const int triangles = OGLRender.FrameBufferStartIndex + 2 * Framebuffer::MaxTiles * Framebuffer::MaxTiles; // Framebuffer utilises color, vertex and texture array only OGLRender.TColor = (TColorStruct*) AllocBuffer(triangles, sizeof(TColorStruct)); if (OpenGL.ColorAlphaUnit2 == 0) { // This must be initialiased even if the secondary color extension is absent // (Because there are no additional checks later on) OGLRender.TColor2 = (TColorStruct*) AllocBuffer(OGLRender.FrameBufferStartIndex, sizeof(TColorStruct)); } else { OGLRender.TColor2 = NULL; } OGLRender.TTexture = (TTextureStruct*) AllocBuffer(triangles, sizeof(TTextureStruct)); // Preinit static data and save a few cycles in RenderAddXXX() for(int i = 0; i < OGLRender.FrameBufferStartIndex; i++) { TTextureStruct* pTS = &OGLRender.TTexture[i]; pTS->aq = pTS->bq = pTS->cq = 0.0f; } OGLRender.TVertex = (TVertexStruct*) AllocBuffer(triangles, sizeof(TVertexStruct)); OGLRender.TFog = (TFogStruct*) AllocBuffer(triangles, sizeof(TFogStruct)); // Initialise compiled vertex arrays OGLRender.BufferLocked = false; OGLRender.BufferStart = 0; OGLRender.BufferLockedStart = OGLRender.RenderBufferSize; // fog is initially turned off OGLRender.UseEnvCombineFog = false; if (InternalConfig.EXT_compiled_vertex_array) { // Initialise to start at the first element of the buffer glVertexPointer(3, GL_FLOAT, 4 * sizeof(GLfloat), &OGLRender.TVertex[0]); glEnableClientState(GL_VERTEX_ARRAY); glColorPointer(4, GL_FLOAT, 0, &OGLRender.TColor[0]); glEnableClientState( GL_COLOR_ARRAY ); glReportError(); if (InternalConfig.EXT_secondary_color && OpenGL.ColorAlphaUnit2 == NULL) { glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT); glSecondaryColorPointerEXT(3, GL_FLOAT, 4 * sizeof(GLfloat), &OGLRender.TColor2[0]); glReportError(); } #ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD if (InternalConfig.FogMode == OpenGLideFogEmulation_FogCoord) { glFogCoordPointerEXT(1, GL_FLOAT, &OGLRender.TFog[0]); glEnableClientState(GL_FOG_COORDINATE_ARRAY_EXT); glReportError(); } #endif } VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); VERIFY_TEXTURE_ENABLED_STATE(); #ifdef OGL_DEBUG OGLRender.FrameTriangles = 0; OGLRender.MaxTriangles = 0; OGLRender.MaxSequencedTriangles = 0; OGLRender.OverallTriangles = 0; OGLRender.OverallRenderTriangleCalls = 0; OGLRender.OverallLines = 0; OGLRender.OverallPoints = 0; OGLRender.MinX = OGLRender.MinY = OGLRender.MinZ = OGLRender.MinW = 99999999.0f; OGLRender.MaxX = OGLRender.MaxY = OGLRender.MaxZ = OGLRender.MaxW = -99999999.0f; OGLRender.MinS = OGLRender.MinT = OGLRender.MinF = 99999999.0f; OGLRender.MaxS = OGLRender.MaxT = OGLRender.MaxF = -99999999.0f; OGLRender.MinR = OGLRender.MinG = OGLRender.MinB = OGLRender.MinA = 99999999.0f; OGLRender.MaxR = OGLRender.MaxG = OGLRender.MaxB = OGLRender.MaxA = -99999999.0f; #endif } // Shuts down the renderer and frees memory void RenderFree(void) { #ifdef OGL_ALL GlideMsg("RenderFree()\n"); #endif // free triangle buffers FreeBuffer(OGLRender.TColor); if (OGLRender.TColor2) FreeBuffer(OGLRender.TColor2); FreeBuffer(OGLRender.TTexture); FreeBuffer(OGLRender.TVertex); FreeBuffer(OGLRender.TFog); } void RenderDrawTriangles_ImmediateMode(bool use_two_tex) { glReportErrors("RenderDrawTriangles_ImmediateMode"); if(!OpenGL.Blend && OpenGL.ChromaKey) { // Render only the color, not the alpha glBegin( GL_TRIANGLES ); const int count = OGLRender.BufferStart + OGLRender.NumberOfTriangles; for (int i = OGLRender.BufferStart; i < count; i++ ) { glColor3fv( &OGLRender.TColor[ i ].ar ); if (InternalConfig.EXT_secondary_color) { glSecondaryColor3fvEXT( &OGLRender.TColor2[ i ].ar ); } if (OpenGL.Texture) { glTexCoord4fv( &OGLRender.TTexture[ i ].as ); if (OpenGL.ColorAlphaUnit2) { glMultiTexCoord4fvARB(OpenGL.ColorAlphaUnit2, &OGLRender.TTexture[ i ].as); } } if (OpenGL.Fog) { if (OGLRender.UseEnvCombineFog) { glMultiTexCoord1fARB(OpenGL.FogTextureUnit, OGLRender.TFog[ i ].af); } #ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD else if (InternalConfig.FogMode == OpenGLideFogEmulation_FogCoord) { glFogCoordfEXT( OGLRender.TFog[ i ].af ); } #endif } glVertex3fv( &OGLRender.TVertex[ i ].ax ); glColor3fv( &OGLRender.TColor[ i ].br ); if (InternalConfig.EXT_secondary_color) { glSecondaryColor3fvEXT( &OGLRender.TColor2[ i ].br ); } if (OpenGL.Texture) { glTexCoord4fv( &OGLRender.TTexture[ i ].bs ); if (OpenGL.ColorAlphaUnit2) { glMultiTexCoord4fvARB(OpenGL.ColorAlphaUnit2, &OGLRender.TTexture[ i ].bs); } } if (OpenGL.Fog) { if (OGLRender.UseEnvCombineFog) { glMultiTexCoord1fARB(OpenGL.FogTextureUnit, OGLRender.TFog[ i ].bf); } #ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD else if (InternalConfig.FogMode == OpenGLideFogEmulation_FogCoord) { glFogCoordfEXT( OGLRender.TFog[ i ].bf ); } #endif } glVertex3fv( &OGLRender.TVertex[ i ].bx ); glColor3fv( &OGLRender.TColor[ i ].cr ); if (InternalConfig.EXT_secondary_color) { glSecondaryColor3fvEXT( &OGLRender.TColor2[ i ].cr ); } if (OpenGL.Texture) { glTexCoord4fv(&OGLRender.TTexture[ i ].cs); if (OpenGL.ColorAlphaUnit2) { glMultiTexCoord4fvARB(OpenGL.ColorAlphaUnit2, &OGLRender.TTexture[ i ].cs); } } if (OpenGL.Fog) { if (OGLRender.UseEnvCombineFog) { glMultiTexCoord1fARB(OpenGL.FogTextureUnit, OGLRender.TFog[ i ].cf); } #ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD else if (InternalConfig.FogMode == OpenGLideFogEmulation_FogCoord) { glFogCoordfEXT( OGLRender.TFog[ i ].cf ); } #endif } glVertex3fv( &OGLRender.TVertex[ i ].cx ); } glEnd( ); glReportError(); } else { glBegin( GL_TRIANGLES ); const int count = OGLRender.BufferStart + OGLRender.NumberOfTriangles; for (int i = OGLRender.BufferStart; i < count; i++ ) { glColor4fv( &OGLRender.TColor[ i ].ar ); if (InternalConfig.EXT_secondary_color) { glSecondaryColor3fvEXT( &OGLRender.TColor2[ i ].ar ); } if (OpenGL.Texture) { glTexCoord4fv( &OGLRender.TTexture[ i ].as ); if (OpenGL.ColorAlphaUnit2 || use_two_tex ) { glMultiTexCoord4fvARB( OpenGL.ColorAlphaUnit1 + 1, &OGLRender.TTexture[ i ].as ); } } if (OpenGL.Fog) { if (OGLRender.UseEnvCombineFog) { glMultiTexCoord1fARB( OpenGL.FogTextureUnit, OGLRender.TFog[ i ].af ); } #ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD else if (InternalConfig.FogMode == OpenGLideFogEmulation_FogCoord) { glFogCoordfEXT( OGLRender.TFog[ i ].af ); } #endif } glVertex3fv( &OGLRender.TVertex[ i ].ax ); glColor4fv( &OGLRender.TColor[ i ].br ); if (InternalConfig.EXT_secondary_color) { glSecondaryColor3fvEXT( &OGLRender.TColor2[ i ].br ); } if (OpenGL.Texture) { glTexCoord4fv( &OGLRender.TTexture[ i ].bs ); if (OpenGL.ColorAlphaUnit2 || use_two_tex ) { glMultiTexCoord4fvARB( OpenGL.ColorAlphaUnit1 + 1, &OGLRender.TTexture[ i ].bs ); } } if (OpenGL.Fog) { if (OGLRender.UseEnvCombineFog) { glMultiTexCoord1fARB( OpenGL.FogTextureUnit, OGLRender.TFog[ i ].bf ); } #ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD else if (InternalConfig.FogMode == OpenGLideFogEmulation_FogCoord) { glFogCoordfEXT( OGLRender.TFog[ i ].bf ); } #endif } glVertex3fv( &OGLRender.TVertex[ i ].bx ); glColor4fv( &OGLRender.TColor[ i ].cr ); if (InternalConfig.EXT_secondary_color) { glSecondaryColor3fvEXT( &OGLRender.TColor2[ i ].cr ); } if (OpenGL.Texture) { glTexCoord4fv( &OGLRender.TTexture[ i ].cs ); if (OpenGL.ColorAlphaUnit2 || use_two_tex ) { glMultiTexCoord4fvARB( OpenGL.ColorAlphaUnit1 + 1, &OGLRender.TTexture[ i ].cs ); } } if (OpenGL.Fog) { if (OGLRender.UseEnvCombineFog) { glMultiTexCoord1fARB( OpenGL.FogTextureUnit, OGLRender.TFog[ i ].cf ); } #ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD else if (InternalConfig.FogMode == OpenGLideFogEmulation_FogCoord) { glFogCoordfEXT( OGLRender.TFog[ i ].cf ); } #endif } glVertex3fv( &OGLRender.TVertex[ i ].cx ); } glEnd( ); glReportError(); } } inline GLfloat dist(GLfloat ax, GLfloat ay, GLfloat bx, GLfloat by) { const GLfloat ad = ax - bx; const GLfloat bd = ay - by; return sqrt(ad * ad + bd * bd); } inline void GapFix(const TVertexStruct* u, TVertexStruct* v, GLfloat p) { // Enlarge the triangle by enlarging the incircle of the triangle by p. // The enlarged triangle will close background pixel-gaps between landscape tiles // as seen in TR1 & TR2. // For p = 1.0, horizontal and vertical one-pixel wide gaps can be closed // by drawing just lines, whereas for p > 1 the whole triangle must be repainted. // (preperably with disabling zbuffer writes and drawing behind the original // triangle with z=OpenGL.ZMin) // Background: http://de.wikipedia.org/wiki/Inkreis // Many thanks to Yves Edel for providing the mathematical background // // The incircle: // let r=sqrt({(s-a)(s-b)(s-c)}/s) // with // s = (a+b+c)/2 // Centre of the incircle: // M = (aA+bB+cC) / (a+b+c) // (with barycentric coordinates) // New vertices of the triangle // A' = A+(A-M)* p / r. const GLfloat a = dist(u->bx, u->by, u->cx, u->cy); const GLfloat b = dist(u->ax, u->ay, u->cx, u->cy); const GLfloat c = dist(u->ax, u->ay, u->bx, u->by); const GLfloat abc = a + b + c; const GLfloat s = abc / 2; const GLfloat r = sqrt( (s-a)*(s-b)*(s-c) / s ); // Enlarge the radius by a factor derived from the avarage vertex depth // As a result, triangles in the foreground must have a larger incircle than // the ones in the background in order to apply the gapfix. GLfloat zr; if (InternalConfig.GapFix & OpenGLideGapFixFlag_DepthFactor) { GLfloat z; if (InternalConfig.PrecisionFix == false && OpenGL.DepthBufferType == 0) { z = (precision_fix(u->az) + precision_fix(u->bz) + precision_fix(u->cz)) / 3.0f; } else { z= (u->az + u->bz + u->cz) / 3.0f; } // Now z is [0...1] and the precision fix has been applied in all cases, // and the average z in TR1 is about 0.34 // (and we can use the same depth factor regardless of the precision fix state) zr = InternalConfig.GapFixDepthFactor * z; } else { zr = 1.0f; } // Filter artecfacts when rendering geometry in front of "holes", which means // all fragments produced by glClear() and not painted over by other geometry const GLfloat r1 = InternalConfig.GapFixParam1; const GLfloat gs = InternalConfig.GapFixParam2; const GLfloat r2 = InternalConfig.GapFixParam3; // Apply the gapfix: // smaller z values allow smaller triangles to pass the gapfix test const OpenGLideGapFixFlags g = InternalConfig.GapFix; if ( ((g & OpenGLideGapFixFlag_IncircleOr) && (r > r1 * zr || abc < gs * r)) || ((g & OpenGLideGapFixFlag_IncircleAnd) && (r > r1 * zr && abc < gs * r)) // r1 > r2 or the formula will degenerate to r > r2 || ((g & OpenGLideGapFixFlag_IncircleSecondRadius) && ((r > r1 * zr || abc < gs * r) && r > r2 * zr)) || ((g & OpenGLideGapFixFlag_VertexLengthSecondRadius) && ((r > r1 * zr || max(a, max(b, c)) > gs) && r > r2 * zr)) ) { const GLfloat Mx = (a * u->ax + b * u->bx + c * u->cx) / abc; const GLfloat My = (a * u->ay + b * u->by + c * u->cy) / abc; // Transform coordinates to fill the gaps v->ax = u->ax + (u->ax - Mx) * p / r; v->ay = u->ay + (u->ay - My) * p / r; v->bx = u->bx + (u->bx - Mx) * p / r; v->by = u->by + (u->by - My) * p / r; v->cx = u->cx + (u->cx - Mx) * p / r; v->cy = u->cy + (u->cy - My) * p / r; } else if (u != v) { *v = *u; } } void RenderDrawTriangles_impl( void ) { glReportErrors("RenderDrawTriangles"); #ifdef OGL_OPTIMISE_DEBUG GlideMsg("RenderDrawTriangles(): %d\n", OGLRender.NumberOfTriangles); #else #ifdef OGL_ALL GlideMsg( "RenderDrawTriangles()\n"); #endif #endif // Finish rendering of the last buffer RenderUnlockArrays(); s_Framebuffer.OnRenderDrawTriangles(); // Update the state after processing the frame buffer because // the framebuffer class might request state changes as well // in order to restore the previous state RenderUpdateState(); bool use_two_tex = false; if (OpenGL.Texture) { use_two_tex = Textures->MakeReady(&OGLRender.TTexture[OGLRender.BufferStart], OGLRender.NumberOfTriangles); if (use_two_tex) { glActiveTextureARB(OpenGL.ColorAlphaUnit1 + 1); glEnable(GL_TEXTURE_2D); if (InternalConfig.EXT_compiled_vertex_array) { glClientActiveTextureARB(OpenGL.ColorAlphaUnit1 + 1); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(4, GL_FLOAT, 0, &OGLRender.TTexture[0]); } glActiveTextureARB(OpenGL.ColorAlphaUnit1); glReportError(); } } // Provide dummy coordinates when fog is turned off but // the texture unit is on because of color/alpha inversion if (OGLRender.UseEnvCombineFog && OpenGL.Fog == false) { int buffer_end = OGLRender.BufferStart + OGLRender.NumberOfTriangles; TFogStruct* pF = OGLRender.TFog; for (int index = OGLRender.BufferStart; index < buffer_end; index++) { pF[index].af = pF[index].bf = pF[index].cf = 0.0f; } } // Render the triangles const bool use_compiled_vertex_arrays = InternalConfig.EXT_compiled_vertex_array // && OGLRender.NumberOfTriangles > 1 // Might be more optimal ; if (use_compiled_vertex_arrays) { // Remember the position of the currently locked buffer OGLRender.BufferLockedStart = OGLRender.BufferStart; // Continue rendering in next buffer OGLRender.BufferStart += OGLRender.NumberOfTriangles; // choose the largest buffer if (OGLRender.BufferStart > OGLRender.RenderBufferSize / 2 || OGLRender.BufferStart >= OGLRender.RenderBufferSize -1) { OGLRender.BufferStart = 0; } glLockArraysEXT(OGLRender.BufferLockedStart * 3, OGLRender.NumberOfTriangles * 3); OGLRender.BufferLocked = true; glDrawArrays(GL_TRIANGLES, OGLRender.BufferLockedStart * 3, OGLRender.NumberOfTriangles * 3); } else { RenderDrawTriangles_ImmediateMode(use_two_tex); } // Fill gaps? if ((InternalConfig.GapFix & OpenGLideGapFixFlag_Enabled) && !OpenGL.Blend) { // Only in 3D scenery if (OpenGL.DepthBufferWritting) { if (use_compiled_vertex_arrays) { RenderUnlockArrays(); } // Enlarge triangles to fill the gaps between tiles in TR1 & TR2 const int buffer_end = OGLRender.BufferLockedStart + OGLRender.NumberOfTriangles; for (int index = OGLRender.BufferLockedStart; index < buffer_end; index++) { TVertexStruct* t = &OGLRender.TVertex[index]; const GLfloat p = 1.0; GapFix(t, t, p); } // Turn off z-buffer writes // disable depth buffer because although the stencil buffer is used, // gapfix striangles may be rendered first and end up in front of // regular triangles glDepthMask(false); glDepthFunc(GL_EQUAL); glDisable(GL_DEPTH_TEST); glStencilFunc(GL_NOTEQUAL, 0x02, 0x03); glStencilOp(GL_KEEP, GL_INCR, GL_INCR); glReportError(); if (use_compiled_vertex_arrays) { glLockArraysEXT(OGLRender.BufferLockedStart * 3, OGLRender.NumberOfTriangles * 3); OGLRender.BufferLocked = true; glDrawArrays(GL_TRIANGLES, OGLRender.BufferLockedStart * 3, OGLRender.NumberOfTriangles * 3); glReportError(); } else { RenderDrawTriangles_ImmediateMode(use_two_tex); } // restore previous state glDepthMask(OpenGL.DepthBufferWritting); glDepthFunc(OpenGL.DepthFunction); if (Glide.State.DepthBufferMode != GR_DEPTHBUFFER_DISABLE) { glEnable(GL_DEPTH_TEST); } glStencilFunc(GL_ALWAYS, 0x02, 0x03); glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); glReportError(); } } if (use_two_tex) { glActiveTextureARB(OpenGL.ColorAlphaUnit1 + 1); if (use_compiled_vertex_arrays) { glDisableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer( 4, GL_FLOAT, 0, NULL); glClientActiveTextureARB(OpenGL.ColorAlphaUnit1); } glDisable(GL_TEXTURE_2D); glActiveTextureARB(OpenGL.ColorAlphaUnit1); glReportError(); } #ifdef OGL_DEBUG if ( OGLRender.NumberOfTriangles > OGLRender.MaxSequencedTriangles ) { OGLRender.MaxSequencedTriangles = OGLRender.NumberOfTriangles; } OGLRender.OverallTriangles += OGLRender.NumberOfTriangles; OGLRender.OverallRenderTriangleCalls++; #endif OGLRender.NumberOfTriangles = 0; // Render the front buffer after each triangle sequence // (However, rendering each triangle seperately would be more correct) if (Glide.State.RenderBuffer == GR_BUFFER_FRONTBUFFER) { glFlush(); } s_Framebuffer.SetRenderBufferChanged(); // Clipping is turned off here per default to save the state-change call // for unclipped triangles. Usally this never triggers, so it's called // once per triangle sequence. // This allows for one call per triangle sequence + one call per clipped // triangle instead of one call for any (even unclipped) triangle SetClipVerticesState(false); VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); } void RenderAddLine( const GrVertex *a, const GrVertex *b, bool unsnap ) { #ifdef OGL_DEBUG OGLRender.OverallLines++; #endif #ifdef OGL_ALL GlideMsg( "RenderAddLine()\n"); #endif glReportErrors("RenderAddLine"); // Peek to avoid updating the render state twice if (OGLRender.NumberOfTriangles) { RenderDrawTriangles_impl(); } else { // Finish rendering of last render buffer RenderUnlockArrays(); s_Framebuffer.OnRenderDrawTriangles(); // Update the state after processing the frame buffer because // the framebuffer class might request state changes as well // in order to restore the previous state RenderUpdateState(); } TColorStruct* pC = &OGLRender.TColor[OGLRender.RenderBufferSize]; TColorStruct* pC2; const GlideState glidestate = Glide.State; if (OpenGL.ColorAlphaUnit2) { { // Color pC->ar = a->r * D1OVER255; pC->ag = a->g * D1OVER255; pC->ab = a->b * D1OVER255; pC->br = b->r * D1OVER255; pC->bg = b->g * D1OVER255; pC->bb = b->b * D1OVER255; } // Alpha if (glidestate.AlphaLocal == GR_COMBINE_LOCAL_DEPTH) { // @todo: find out whether z has to be divided by 255 or by 65535 pC->aa = a->z * D1OVER255; pC->ba = b->z * D1OVER255; } else { pC->aa = a->a * D1OVER255; pC->ba = b->a * D1OVER255; } } else { pC2 = &OGLRender.TColor2[OGLRender.RenderBufferSize]; memset( pC2, 0, sizeof( TColorStruct ) ); // Color Stuff, need to optimize it if ( Glide.ALocal ) { switch (glidestate.AlphaLocal) { case GR_COMBINE_LOCAL_ITERATED: Local.aa = a->a * D1OVER255; Local.ba = b->a * D1OVER255; break; case GR_COMBINE_LOCAL_CONSTANT: Local.aa = Local.ba = OpenGL.ConstantColor[3]; break; case GR_COMBINE_LOCAL_DEPTH: Local.aa = a->z; Local.ba = b->z; break; } } if ( Glide.AOther ) { switch (glidestate.AlphaOther) { case GR_COMBINE_OTHER_ITERATED: Other.aa = a->a * D1OVER255; Other.ba = b->a * D1OVER255; break; case GR_COMBINE_OTHER_CONSTANT: Other.aa = Other.ba = OpenGL.ConstantColor[3]; break; case GR_COMBINE_OTHER_TEXTURE: Other.aa = Other.ba = 1.0f; break; } } if ( Glide.CLocal ) { switch (glidestate.ColorCombineLocal) { case GR_COMBINE_LOCAL_ITERATED: Local.ar = a->r * D1OVER255; Local.ag = a->g * D1OVER255; Local.ab = a->b * D1OVER255; Local.br = b->r * D1OVER255; Local.bg = b->g * D1OVER255; Local.bb = b->b * D1OVER255; break; case GR_COMBINE_LOCAL_CONSTANT: { GLfloat* color; if (glidestate.Delta0Mode) { color = &OpenGL.Delta0Color[0]; } else { color = &OpenGL.ConstantColor[0]; } Local.ar = Local.br = color[0]; Local.ag = Local.bg = color[1]; Local.ab = Local.bb = color[2]; } break; } } if ( Glide.COther ) { switch (glidestate.ColorCombineOther) { case GR_COMBINE_OTHER_ITERATED: Other.ar = a->r * D1OVER255; Other.ag = a->g * D1OVER255; Other.ab = a->b * D1OVER255; Other.br = b->r * D1OVER255; Other.bg = b->g * D1OVER255; Other.bb = b->b * D1OVER255; break; case GR_COMBINE_OTHER_CONSTANT: { GLfloat* color; if (glidestate.Delta0Mode) { color = &OpenGL.Delta0Color[0]; } else { color = &OpenGL.ConstantColor[0]; } Other.ar = Other.br = color[0]; Other.ag = Other.bg = color[1]; Other.ab = Other.bb = color[2]; } break; case GR_COMBINE_OTHER_TEXTURE: Other.ar = Other.ag = Other.ab = 1.0f; Other.br = Other.bg = Other.bb = 1.0f; break; } } switch (glidestate.ColorCombineFunction) { case GR_COMBINE_FUNCTION_ZERO: pC->ar = pC->ag = pC->ab = 0.0f; pC->br = pC->bg = pC->bb = 0.0f; break; case GR_COMBINE_FUNCTION_LOCAL: pC->ar = Local.ar; pC->ag = Local.ag; pC->ab = Local.ab; pC->br = Local.br; pC->bg = Local.bg; pC->bb = Local.bb; break; case GR_COMBINE_FUNCTION_LOCAL_ALPHA: pC->ar = pC->ag = pC->ab = Local.aa; pC->br = pC->bg = pC->bb = Local.ba; break; case GR_COMBINE_FUNCTION_SCALE_OTHER: ColorFactor3Func( &CFactor, &Local, &Other ); pC->ar = CFactor.ar * Other.ar; pC->ag = CFactor.ag * Other.ag; pC->ab = CFactor.ab * Other.ab; pC->br = CFactor.br * Other.br; pC->bg = CFactor.bg * Other.bg; pC->bb = CFactor.bb * Other.bb; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL: ColorFactor3Func( &CFactor, &Local, &Other ); pC->ar = CFactor.ar * Other.ar; pC->ag = CFactor.ag * Other.ag; pC->ab = CFactor.ab * Other.ab; pC->br = CFactor.br * Other.br; pC->bg = CFactor.bg * Other.bg; pC->bb = CFactor.bb * Other.bb; pC2->ar = Local.ar; pC2->ag = Local.ag; pC2->ab = Local.ab; pC2->br = Local.br; pC2->bg = Local.bg; pC2->bb = Local.bb; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA: ColorFactor3Func( &CFactor, &Local, &Other ); pC->ar = CFactor.ar * Other.ar; pC->ag = CFactor.ag * Other.ag; pC->ab = CFactor.ab * Other.ab; pC->br = CFactor.br * Other.br; pC->bg = CFactor.bg * Other.bg; pC->bb = CFactor.bb * Other.bb; pC2->ar = pC2->ag = pC2->ab = Local.aa; pC2->br = pC2->bg = pC2->bb = Local.ba; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL: ColorFactor3Func( &CFactor, &Local, &Other ); pC->ar = CFactor.ar * (Other.ar - Local.ar); pC->ag = CFactor.ag * (Other.ag - Local.ag); pC->ab = CFactor.ab * (Other.ab - Local.ab); pC->br = CFactor.br * (Other.br - Local.br); pC->bg = CFactor.bg * (Other.bg - Local.bg); pC->bb = CFactor.bb * (Other.bb - Local.bb); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL: if (((glidestate.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_ALPHA) || (glidestate.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_RGB)) && (glidestate.ColorCombineOther == GR_COMBINE_OTHER_TEXTURE)) { pC->ar = Local.ar; pC->ag = Local.ag; pC->ab = Local.ab; pC->br = Local.br; pC->bg = Local.bg; pC->bb = Local.bb; } else { ColorFactor3Func( &CFactor, &Local, &Other ); pC->ar = CFactor.ar * (Other.ar - Local.ar); pC->ag = CFactor.ag * (Other.ag - Local.ag); pC->ab = CFactor.ab * (Other.ab - Local.ab); pC->br = CFactor.br * (Other.br - Local.br); pC->bg = CFactor.bg * (Other.bg - Local.bg); pC->bb = CFactor.bb * (Other.bb - Local.bb); pC2->ar = Local.ar; pC2->ag = Local.ag; pC2->ab = Local.ab; pC2->br = Local.br; pC2->bg = Local.bg; pC2->bb = Local.bb; } break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA: if (((glidestate.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_ALPHA) || (glidestate.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_RGB)) && (glidestate.ColorCombineOther == GR_COMBINE_OTHER_TEXTURE)) { pC->ar = pC->ag = pC->ab = Local.aa; pC->br = pC->bg = pC->bb = Local.ba; } else { ColorFactor3Func( &CFactor, &Local, &Other ); pC->ar = CFactor.ar * (Other.ar - Local.ar); pC->ag = CFactor.ag * (Other.ag - Local.ag); pC->ab = CFactor.ab * (Other.ab - Local.ab); pC->br = CFactor.br * (Other.br - Local.br); pC->bg = CFactor.bg * (Other.bg - Local.bg); pC->bb = CFactor.bb * (Other.bb - Local.bb); pC2->ar = pC2->ag = pC2->ab = Local.aa; pC2->br = pC2->bg = pC2->bb = Local.ba; } break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL: ColorFactor3Func( &CFactor, &Local, &Other ); pC->ar = ( 1.0f - CFactor.ar ) * Local.ar; pC->ag = ( 1.0f - CFactor.ag ) * Local.ag; pC->ab = ( 1.0f - CFactor.ab ) * Local.ab; pC->br = ( 1.0f - CFactor.br ) * Local.br; pC->bg = ( 1.0f - CFactor.bg ) * Local.bg; pC->bb = ( 1.0f - CFactor.bb ) * Local.bb; pC2->ar = Local.ar; pC2->ag = Local.ag; pC2->ab = Local.ab; pC2->br = Local.br; pC2->bg = Local.bg; pC2->bb = Local.bb; break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA: ColorFactor3Func( &CFactor, &Local, &Other ); pC->ar = CFactor.ar * -Local.ar; pC->ag = CFactor.ag * -Local.ag; pC->ab = CFactor.ab * -Local.ab; pC->br = CFactor.br * -Local.br; pC->bg = CFactor.bg * -Local.bg; pC->bb = CFactor.bb * -Local.bb; pC2->ar = pC2->ag = pC2->ab = Local.aa; pC2->br = pC2->bg = pC2->bb = Local.ba; break; } switch (glidestate.AlphaFunction) { case GR_COMBINE_FUNCTION_ZERO: pC->aa = pC->ba = 0.0f; break; case GR_COMBINE_FUNCTION_LOCAL: case GR_COMBINE_FUNCTION_LOCAL_ALPHA: pC->aa = Local.aa; pC->ba = Local.ba; break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL: case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA: pC->aa = ((1.0f - AlphaFactorFunc( Local.aa, Other.aa )) * Local.aa); pC->ba = ((1.0f - AlphaFactorFunc( Local.ba, Other.ba )) * Local.ba); break; case GR_COMBINE_FUNCTION_SCALE_OTHER: pC->aa = (AlphaFactorFunc( Local.aa, Other.aa ) * Other.aa); pC->ba = (AlphaFactorFunc( Local.ba, Other.ba ) * Other.ba); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL: case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA: pC->aa = (AlphaFactorFunc( Local.aa, Other.aa ) * Other.aa + Local.aa); pC->ba = (AlphaFactorFunc( Local.ba, Other.ba ) * Other.ba + Local.ba); // pC2->aa = Local.aa; // pC2->ba = Local.ba; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL: pC->aa = (AlphaFactorFunc( Local.aa, Other.aa ) * ( Other.aa - Local.aa )); pC->ba = (AlphaFactorFunc( Local.ba, Other.ba ) * ( Other.ba - Local.ba )); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL: case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA: pC->aa = (AlphaFactorFunc( Local.aa, Other.aa ) * ( Other.aa - Local.aa ) + Local.aa); pC->ba = (AlphaFactorFunc( Local.ba, Other.ba ) * ( Other.ba - Local.ba ) + Local.ba); // pC2->aa = Local.aa; // pC2->ba = Local.ba; break; } if (OpenGL.FogTextureUnit == 0) { if (glidestate.ColorCombineInvert) { pC->ar = 1.0f - pC->ar - pC2->ar; pC->ag = 1.0f - pC->ag - pC2->ag; pC->ab = 1.0f - pC->ab - pC2->ab; pC->br = 1.0f - pC->br - pC2->br; pC->bg = 1.0f - pC->bg - pC2->bg; pC->bb = 1.0f - pC->bb - pC2->bb; pC2->ar = pC2->ag = pC2->ab = 0.0f; pC2->br = pC2->bg = pC2->bb = 0.0f; } if (glidestate.AlphaInvert) { pC->aa = 1.0f - pC->aa - pC2->aa; pC->ba = 1.0f - pC->ba - pC2->ba; pC2->aa = pC2->ba = 0.0f; } } } TVertexStruct* pV = &OGLRender.TVertex[OGLRender.RenderBufferSize]; // Z-Buffering if ((glidestate.DepthBufferMode == GR_DEPTHBUFFER_DISABLE) || (glidestate.DepthBufferMode == GR_CMP_ALWAYS)) { pV->az = 0.0f; pV->bz = 0.0f; } else if ( OpenGL.DepthBufferType ) { pV->az = a->ooz * D1OVER65536; pV->bz = b->ooz * D1OVER65536; } else { /* * For silly values of oow, depth buffering doesn't * seem to work, so map them to a sensible z. When * games use these silly values, they probably don't * use z buffering anyway. */ if ( a->oow > 1.0 ) { pV->az = pV->bz = 0.9f; } else if ( InternalConfig.PrecisionFix ) { pV->az = precision_fix(a->oow); pV->bz = precision_fix(b->oow); } else { pV->az = a->oow; pV->bz = b->oow; } } if ( ( unsnap ) && ( a->x > vertex_snap_compare ) ) { pV->ax = a->x - vertex_snap; pV->ay = a->y - vertex_snap; pV->bx = b->x - vertex_snap; pV->by = b->y - vertex_snap; } else { pV->ax = a->x; pV->ay = a->y; pV->bx = b->x; pV->by = b->y; } TTextureStruct* pTS = &OGLRender.TTexture[OGLRender.RenderBufferSize]; if (OpenGL.Texture) { const float hAspect = Textures->GetHAspect(); const float wAspect = Textures->GetWAspect(); pTS->as = a->tmuvtx[0].sow * wAspect; pTS->at = a->tmuvtx[0].tow * hAspect; pTS->bs = b->tmuvtx[0].sow * wAspect; pTS->bt = b->tmuvtx[0].tow * hAspect; float atmuoow; float btmuoow; if ((glidestate.STWHint & GR_STWHINT_W_DIFF_TMU0) == 0) { atmuoow = a->oow; btmuoow = b->oow; } else { atmuoow = a->tmuvtx[ 0 ].oow; btmuoow = b->tmuvtx[ 0 ].oow; } pTS->aoow = atmuoow; pTS->boow = btmuoow; #ifdef OGL_DEBUG_GLIDE_COORDS GlideMsg(a, atmuoow); GlideMsg(b, btmuoow); #endif } #ifdef OGL_DEBUG_GLIDE_COORDS else { GlideMsg(a, 1.0f); GlideMsg(b, 1.0f); } #endif TFogStruct* pF = &OGLRender.TFog[OGLRender.RenderBufferSize]; if (glidestate.FogMode) { if (glidestate.FogMode & GR_FOG_WITH_TABLE) { pF->af = (float)OpenGL.FogTable[ (FxU16)(1.0f / a->oow) ] * D1OVER255; pF->bf = (float)OpenGL.FogTable[ (FxU16)(1.0f / b->oow) ] * D1OVER255; } else { pF->af = a->a * D1OVER255; pF->bf = b->a * D1OVER255; } /* if ( glidestate.FogMode & GR_FOG_ADD2 ) { pF->af = 1.0f - pF->af; pF->bf = 1.0f - pF->bf; } */ #ifdef OGL_DEBUG DEBUG_MIN_MAX( pF->af, OGLRender.MaxF, OGLRender.MinF ); DEBUG_MIN_MAX( pF->bf, OGLRender.MaxF, OGLRender.MinF ); #endif } else /* if (OGLRender.UseEnvCombineFog) */ // env combine fog is the default { // Must provide dummy coords if fog is turned off but // the texture unit is active because of inveting color/alpha pF->af = pF->bf = 0.0; } #ifdef OGL_DEBUG DEBUG_MIN_MAX( pC->ar, OGLRender.MaxR, OGLRender.MinR ); DEBUG_MIN_MAX( pC->br, OGLRender.MaxR, OGLRender.MinR ); DEBUG_MIN_MAX( pC->ag, OGLRender.MaxG, OGLRender.MinG ); DEBUG_MIN_MAX( pC->bg, OGLRender.MaxG, OGLRender.MinG ); DEBUG_MIN_MAX( pC->ab, OGLRender.MaxB, OGLRender.MinB ); DEBUG_MIN_MAX( pC->bb, OGLRender.MaxB, OGLRender.MinB ); DEBUG_MIN_MAX( pC->aa, OGLRender.MaxA, OGLRender.MinA ); DEBUG_MIN_MAX( pC->ba, OGLRender.MaxA, OGLRender.MinA ); DEBUG_MIN_MAX( pV->az, OGLRender.MaxZ, OGLRender.MinZ ); DEBUG_MIN_MAX( pV->bz, OGLRender.MaxZ, OGLRender.MinZ ); DEBUG_MIN_MAX( pV->ax, OGLRender.MaxX, OGLRender.MinX ); DEBUG_MIN_MAX( pV->bx, OGLRender.MaxX, OGLRender.MinX ); DEBUG_MIN_MAX( pV->ay, OGLRender.MaxY, OGLRender.MinY ); DEBUG_MIN_MAX( pV->by, OGLRender.MaxY, OGLRender.MinY ); if (OpenGL.Texture) { DEBUG_MIN_MAX( pTS->as, OGLRender.MaxS, OGLRender.MinS ); DEBUG_MIN_MAX( pTS->bs, OGLRender.MaxS, OGLRender.MinS ); DEBUG_MIN_MAX( pTS->at, OGLRender.MaxT, OGLRender.MinT ); DEBUG_MIN_MAX( pTS->bt, OGLRender.MaxT, OGLRender.MinT ); } #endif #ifdef OGL_DEBUG_OPENGL_COORDS GlideMsg(pV, pTS); #endif RenderUpdateState(); if (OpenGL.Texture) { Textures->MakeReady(); } glBegin( GL_LINES ); OpenGL.ChromaKey ? glColor3fv( &pC->ar ) : glColor4fv( &pC->ar ); if (InternalConfig.EXT_secondary_color) { glSecondaryColor3fvEXT( &pC2->ar ); } if (OpenGL.Texture) { glTexCoord4fv( &pTS->as ); if (OpenGL.ColorAlphaUnit2) { glMultiTexCoord4fvARB( OpenGL.ColorAlphaUnit2, &pTS->as ); } } if (glidestate.FogMode) { if (OGLRender.UseEnvCombineFog) { glMultiTexCoord1fARB( OpenGL.FogTextureUnit, pF->af ); } #ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD else if (InternalConfig.FogMode == OpenGLideFogEmulation_FogCoord) { glFogCoordfEXT( pF->af ); } #endif } glVertex3fv( &pV->ax ); OpenGL.ChromaKey ? glColor3fv( &pC->br ) : glColor4fv( &pC->br ); if (InternalConfig.EXT_secondary_color) { glSecondaryColor3fvEXT( &pC2->br ); } if (OpenGL.Texture) { glTexCoord4fv( &pTS->bs ); if (OpenGL.ColorAlphaUnit2) { glMultiTexCoord4fvARB( OpenGL.ColorAlphaUnit2, &pTS->bs ); } } if (glidestate.FogMode) { if (OGLRender.UseEnvCombineFog) { glMultiTexCoord1fARB( OpenGL.FogTextureUnit, pF->bf ); } #ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD if (InternalConfig.FogMode == OpenGLideFogEmulation_FogCoord) { glFogCoordfEXT( pF->bf ); } #endif } glVertex3fv( &pV->bx ); glEnd(); glReportError(); s_Framebuffer.SetRenderBufferChanged(); VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); } void RenderAddTriangle( const GrVertex *a, const GrVertex *b, const GrVertex *c, bool unsnap ) { glReportErrors("RenderAddTriangle"); #ifdef OGL_DEBUG OGLRender.OverallTriangles++; #endif const int TriangleIndex = OGLRender.BufferStart + OGLRender.NumberOfTriangles; #ifdef OGL_ALL GlideMsg( "RenderAddTriangle(%d)\n", TriangleIndex); #endif TColorStruct* pC = &OGLRender.TColor[TriangleIndex]; TColorStruct* pC2; const GlideState glidestate = Glide.State; if (OpenGL.ColorAlphaUnit2) { { // Color pC->ar = a->r * D1OVER255; pC->ag = a->g * D1OVER255; pC->ab = a->b * D1OVER255; pC->br = b->r * D1OVER255; pC->bg = b->g * D1OVER255; pC->bb = b->b * D1OVER255; pC->cr = c->r * D1OVER255; pC->cg = c->g * D1OVER255; pC->cb = c->b * D1OVER255; } // Alpha if (glidestate.AlphaLocal == GR_COMBINE_LOCAL_DEPTH) { // @todo: find out whether z has to be divided by 255 or by 65535 pC->aa = a->z * D1OVER255; pC->ba = b->z * D1OVER255; pC->ca = c->z * D1OVER255; } else { pC->aa = a->a * D1OVER255; pC->ba = b->a * D1OVER255; pC->ca = c->a * D1OVER255; } } else { pC2 = &OGLRender.TColor2[ TriangleIndex ]; memset( pC2, 0, sizeof( TColorStruct ) ); if ( Glide.ALocal ) { switch (glidestate.AlphaLocal) { case GR_COMBINE_LOCAL_ITERATED: Local.aa = a->a * D1OVER255; Local.ba = b->a * D1OVER255; Local.ca = c->a * D1OVER255; break; case GR_COMBINE_LOCAL_CONSTANT: Local.aa = Local.ba = Local.ca = OpenGL.ConstantColor[ 3 ]; break; case GR_COMBINE_LOCAL_DEPTH: Local.aa = a->z * D1OVER255; Local.ba = b->z * D1OVER255; Local.ca = c->z * D1OVER255; break; } } if ( Glide.AOther ) { switch (glidestate.AlphaOther) { case GR_COMBINE_OTHER_ITERATED: Other.aa = a->a * D1OVER255; Other.ba = b->a * D1OVER255; Other.ca = c->a * D1OVER255; break; case GR_COMBINE_OTHER_CONSTANT: Other.aa = Other.ba = Other.ca = OpenGL.ConstantColor[ 3 ]; break; case GR_COMBINE_OTHER_TEXTURE: if ( OpenGL.Texture ) { Other.aa = Other.ba = Other.ca = 1.0f; } else { Other.aa = Other.ba = Other.ca = 0.0f; } break; } } if ( Glide.CLocal ) { switch (glidestate.ColorCombineLocal) { case GR_COMBINE_LOCAL_ITERATED: Local.ar = a->r * D1OVER255; Local.ag = a->g * D1OVER255; Local.ab = a->b * D1OVER255; Local.br = b->r * D1OVER255; Local.bg = b->g * D1OVER255; Local.bb = b->b * D1OVER255; Local.cr = c->r * D1OVER255; Local.cg = c->g * D1OVER255; Local.cb = c->b * D1OVER255; break; case GR_COMBINE_LOCAL_CONSTANT: { GLfloat* color; if (glidestate.Delta0Mode) { color = &OpenGL.Delta0Color[0]; } else { color = &OpenGL.ConstantColor[0]; } Local.ar = Local.br = Local.cr = color[0]; Local.ag = Local.bg = Local.cg = color[1]; Local.ab = Local.bb = Local.cb = color[2]; } break; } } if ( Glide.COther ) { switch ( glidestate.ColorCombineOther ) { case GR_COMBINE_OTHER_ITERATED: Other.ar = a->r * D1OVER255; Other.ag = a->g * D1OVER255; Other.ab = a->b * D1OVER255; Other.br = b->r * D1OVER255; Other.bg = b->g * D1OVER255; Other.bb = b->b * D1OVER255; Other.cr = c->r * D1OVER255; Other.cg = c->g * D1OVER255; Other.cb = c->b * D1OVER255; break; case GR_COMBINE_OTHER_CONSTANT: { GLfloat* color; if (glidestate.Delta0Mode) { color = &OpenGL.Delta0Color[0]; } else { color = &OpenGL.ConstantColor[0]; } Other.ar = Other.br = Other.cr = color[0]; Other.ag = Other.bg = Other.cg = color[1]; Other.ab = Other.bb = Other.cb = color[2]; } break; case GR_COMBINE_OTHER_TEXTURE: if ( OpenGL.Texture ) { Other.ar = Other.ag = Other.ab = 1.0f; Other.br = Other.bg = Other.bb = 1.0f; Other.cr = Other.cg = Other.cb = 1.0f; } else { Other.ar = Other.ag = Other.ab = 0.0f; Other.br = Other.bg = Other.bb = 0.0f; Other.cr = Other.cg = Other.cb = 0.0f; } break; } } ColorFunctionFunc( pC, pC2, &Local, &Other ); switch (glidestate.AlphaFunction) { case GR_COMBINE_FUNCTION_ZERO: pC->aa = pC->ba = pC->ca = 0.0f; break; case GR_COMBINE_FUNCTION_LOCAL: case GR_COMBINE_FUNCTION_LOCAL_ALPHA: pC->aa = Local.aa; pC->ba = Local.ba; pC->ca = Local.ca; break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL: case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA: pC->aa = ( 1.0f - AlphaFactorFunc( Local.aa, Other.aa ) ) * Local.aa; pC->ba = ( 1.0f - AlphaFactorFunc( Local.ba, Other.ba ) ) * Local.ba; pC->ca = ( 1.0f - AlphaFactorFunc( Local.ca, Other.ca ) ) * Local.ca; break; case GR_COMBINE_FUNCTION_SCALE_OTHER: pC->aa = AlphaFactorFunc( Local.aa, Other.aa ) * Other.aa; pC->ba = AlphaFactorFunc( Local.ba, Other.ba ) * Other.ba; pC->ca = AlphaFactorFunc( Local.ca, Other.ca ) * Other.ca; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL: case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA: pC->aa = AlphaFactorFunc( Local.aa, Other.aa ) * Other.aa + Local.aa; pC->ba = AlphaFactorFunc( Local.ba, Other.ba ) * Other.ba + Local.ba; pC->ca = AlphaFactorFunc( Local.ca, Other.ca ) * Other.ca + Local.ca; // pC2->aa = Local.aa; // pC2->ba = Local.ba; // pC2->ca = Local.ca; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL: pC->aa = AlphaFactorFunc( Local.aa, Other.aa ) * ( Other.aa - Local.aa ); pC->ba = AlphaFactorFunc( Local.ba, Other.ba ) * ( Other.ba - Local.ba ); pC->ca = AlphaFactorFunc( Local.ca, Other.ca ) * ( Other.ca - Local.ca ); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL: case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA: pC->aa = AlphaFactorFunc( Local.aa, Other.aa ) * ( Other.aa - Local.aa ) + Local.aa; pC->ba = AlphaFactorFunc( Local.ba, Other.ba ) * ( Other.ba - Local.ba ) + Local.ba; pC->ca = AlphaFactorFunc( Local.ca, Other.ca ) * ( Other.ca - Local.ca ) + Local.ca; // pC2->aa = Local.aa; // pC2->ba = Local.ba; // pC2->ca = Local.ca; break; } if (OpenGL.FogTextureUnit == 0) { if (glidestate.ColorCombineInvert) { pC->ar = 1.0f - pC->ar - pC2->ar; pC->ag = 1.0f - pC->ag - pC2->ag; pC->ab = 1.0f - pC->ab - pC2->ab; pC->br = 1.0f - pC->br - pC2->br; pC->bg = 1.0f - pC->bg - pC2->bg; pC->bb = 1.0f - pC->bb - pC2->bb; pC->cr = 1.0f - pC->cr - pC2->cr; pC->cg = 1.0f - pC->cg - pC2->cg; pC->cb = 1.0f - pC->cb - pC2->cb; pC2->ar = pC2->ag = pC2->ab = 0.0f; pC2->br = pC2->bg = pC2->bb = 0.0f; pC2->cr = pC2->cg = pC2->cb = 0.0f; } if (glidestate.AlphaInvert) { pC->aa = 1.0f - pC->aa - pC2->aa; pC->ba = 1.0f - pC->ba - pC2->ba; pC->ca = 1.0f - pC->ca - pC2->ca; pC2->aa = pC2->ba = pC2->ca = 0.0f; } } } TVertexStruct* pV = &OGLRender.TVertex[ TriangleIndex ]; // Z-Buffering // @todo: check why this has been added , since it look s unnecessary if ((glidestate.DepthBufferMode == GR_DEPTHBUFFER_DISABLE) || (glidestate.DepthFunction == GR_CMP_ALWAYS)) { pV->az = 0.0f; pV->bz = 0.0f; pV->cz = 0.0f; } else if ( OpenGL.DepthBufferType ) { pV->az = a->ooz * D1OVER65536; pV->bz = b->ooz * D1OVER65536; pV->cz = c->ooz * D1OVER65536; } else { // // For silly values of oow, depth buffering doesn't // seem to work, so map them to a sensible z. When // games use these silly values, they probably don't // use z buffering anyway. // if ( a->oow > 1.0 ) { pV->az = pV->bz = pV->cz = 0.9f; } else if ( InternalConfig.PrecisionFix ) { pV->az = precision_fix(a->oow); pV->bz = precision_fix(b->oow); pV->cz = precision_fix(c->oow); } else { pV->az = a->oow; pV->bz = b->oow; pV->cz = c->oow; } } if ( ( unsnap ) && ( a->x > vertex_snap_compare ) ) { pV->ax = a->x - vertex_snap; pV->ay = a->y - vertex_snap; pV->bx = b->x - vertex_snap; pV->by = b->y - vertex_snap; pV->cx = c->x - vertex_snap; pV->cy = c->y - vertex_snap; } else { pV->ax = a->x; pV->ay = a->y; pV->bx = b->x; pV->by = b->y; pV->cx = c->x; pV->cy = c->y; } #ifdef OGL_DEBUG DEBUG_MIN_MAX( pC->ar, OGLRender.MaxR, OGLRender.MinR ); DEBUG_MIN_MAX( pC->br, OGLRender.MaxR, OGLRender.MinR ); DEBUG_MIN_MAX( pC->cr, OGLRender.MaxR, OGLRender.MinR ); DEBUG_MIN_MAX( pC->ag, OGLRender.MaxG, OGLRender.MinG ); DEBUG_MIN_MAX( pC->bg, OGLRender.MaxG, OGLRender.MinG ); DEBUG_MIN_MAX( pC->cg, OGLRender.MaxG, OGLRender.MinG ); DEBUG_MIN_MAX( pC->ab, OGLRender.MaxB, OGLRender.MinB ); DEBUG_MIN_MAX( pC->bb, OGLRender.MaxB, OGLRender.MinB ); DEBUG_MIN_MAX( pC->cb, OGLRender.MaxB, OGLRender.MinB ); DEBUG_MIN_MAX( pC->aa, OGLRender.MaxA, OGLRender.MinA ); DEBUG_MIN_MAX( pC->ba, OGLRender.MaxA, OGLRender.MinA ); DEBUG_MIN_MAX( pC->ca, OGLRender.MaxA, OGLRender.MinA ); DEBUG_MIN_MAX( pV->az, OGLRender.MaxZ, OGLRender.MinZ ); DEBUG_MIN_MAX( pV->bz, OGLRender.MaxZ, OGLRender.MinZ ); DEBUG_MIN_MAX( pV->cz, OGLRender.MaxZ, OGLRender.MinZ ); DEBUG_MIN_MAX( pV->ax, OGLRender.MaxX, OGLRender.MinX ); DEBUG_MIN_MAX( pV->bx, OGLRender.MaxX, OGLRender.MinX ); DEBUG_MIN_MAX( pV->cx, OGLRender.MaxX, OGLRender.MinX ); DEBUG_MIN_MAX( pV->ay, OGLRender.MaxY, OGLRender.MinY ); DEBUG_MIN_MAX( pV->by, OGLRender.MaxY, OGLRender.MinY ); DEBUG_MIN_MAX( pV->cy, OGLRender.MaxY, OGLRender.MinY ); OGLRender.FrameTriangles++; #endif bool generate_subtextures = OpenGL.Texture; if (OpenGL.Texture) { float atmuoow; float btmuoow; float ctmuoow; if ((glidestate.STWHint & GR_STWHINT_W_DIFF_TMU0) == 0) { atmuoow = a->oow; btmuoow = b->oow; ctmuoow = c->oow; } else { atmuoow = a->tmuvtx[ 0 ].oow; btmuoow = b->tmuvtx[ 0 ].oow; ctmuoow = c->tmuvtx[ 0 ].oow; } const float maxoow = 1.0f / max( atmuoow, max( btmuoow, ctmuoow ) ); generate_subtextures = InternalConfig.GenerateSubTextures && OpenGL.SClampMode != GL_REPEAT && OpenGL.TClampMode != GL_REPEAT; TTextureStruct* pTS = &OGLRender.TTexture[TriangleIndex]; if (generate_subtextures) { pTS->as = a->tmuvtx[ 0 ].sow / atmuoow; pTS->at = a->tmuvtx[ 0 ].tow / atmuoow; pTS->bs = b->tmuvtx[ 0 ].sow / btmuoow; pTS->bt = b->tmuvtx[ 0 ].tow / btmuoow; pTS->cs = c->tmuvtx[ 0 ].sow / ctmuoow; pTS->ct = c->tmuvtx[ 0 ].tow / ctmuoow; } else { const GLfloat hAspect = Textures->GetHAspect(); const GLfloat wAspect = Textures->GetWAspect(); pTS->as = a->tmuvtx[ 0 ].sow * wAspect * maxoow; pTS->at = a->tmuvtx[ 0 ].tow * hAspect * maxoow; pTS->bs = b->tmuvtx[ 0 ].sow * wAspect * maxoow; pTS->bt = b->tmuvtx[ 0 ].tow * hAspect * maxoow; pTS->cs = c->tmuvtx[ 0 ].sow * wAspect * maxoow; pTS->ct = c->tmuvtx[ 0 ].tow * hAspect * maxoow; } pTS->aoow = atmuoow * maxoow; pTS->boow = btmuoow * maxoow; pTS->coow = ctmuoow * maxoow; #ifdef OGL_DEBUG DEBUG_MIN_MAX( pTS->as, OGLRender.MaxS, OGLRender.MinS ); DEBUG_MIN_MAX( pTS->bs, OGLRender.MaxS, OGLRender.MinS ); DEBUG_MIN_MAX( pTS->cs, OGLRender.MaxS, OGLRender.MinS ); DEBUG_MIN_MAX( pTS->at, OGLRender.MaxT, OGLRender.MinT ); DEBUG_MIN_MAX( pTS->bt, OGLRender.MaxT, OGLRender.MinT ); DEBUG_MIN_MAX( pTS->ct, OGLRender.MaxT, OGLRender.MinT ); #endif #ifdef OGL_DEBUG_GLIDE_COORDS GlideMsg(a, maxoow); GlideMsg(b, maxoow); GlideMsg(c, maxoow); #endif #ifdef OGL_DEBUG_OPENGL_COORDS GlideMsg(pV, pTS); #endif } #if defined(OGL_DEBUG_GLIDE_COORDS) || defined(OGL_DEBUG_OPENGL_COORDS) else { #ifdef OGL_DEBUG_GLIDE_COORDS GlideMsg(a, 1.0f); GlideMsg(b, 1.0f); GlideMsg(c, 1.0f); #endif #ifdef OGL_DEBUG_OPENGL_COORDS GlideMsg(pV); #endif #if defined(OGL_DEBUG_GLIDE_COORDS) || defined(OGL_DEBUG_OPENGL_COORDS) } #endif #endif TFogStruct* pF = &OGLRender.TFog[TriangleIndex]; if(glidestate.FogMode) { if (glidestate.FogMode & GR_FOG_WITH_TABLE) { pF->af = (float) OpenGL.FogTable[(FxU16)(1.0f / a->oow) ] * D1OVER255; pF->bf = (float) OpenGL.FogTable[(FxU16)(1.0f / b->oow) ] * D1OVER255; pF->cf = (float) OpenGL.FogTable[(FxU16)(1.0f / c->oow) ] * D1OVER255; } else { pF->af = a->a * D1OVER255; pF->bf = b->a * D1OVER255; pF->cf = c->a * D1OVER255; } /* if ( glidestate.FogMode & GR_FOG_ADD2 ) { pF->af = 1.0f - pF->af; pF->bf = 1.0f - pF->bf; pF->cf = 1.0f - pF->cf; } */ #ifdef OGL_DEBUG DEBUG_MIN_MAX( pF->af, OGLRender.MaxF, OGLRender.MinF ); DEBUG_MIN_MAX( pF->bf, OGLRender.MaxF, OGLRender.MinF ); DEBUG_MIN_MAX( pF->bf, OGLRender.MaxF, OGLRender.MinF ); #endif } OGLRender.NumberOfTriangles++; if (generate_subtextures) { RenderDrawTriangles(); } else { // Check whether the current buffer is before the currently rendered buffer if (OGLRender.BufferLocked && OGLRender.BufferStart == 0 && OGLRender.NumberOfTriangles >= OGLRender.BufferLockedStart) { // Finish drawing of current render buffer RenderUnlockArrays(); OGLRender.BufferLocked = false; OGLRender.BufferLockedStart = OGLRender.RenderBufferSize; // Continue filling the buffer } else if (OGLRender.BufferStart + OGLRender.NumberOfTriangles >= OGLRender.RenderBufferSize - 1) { RenderDrawTriangles(); } } } void RenderAddPoint( const GrVertex *a, bool unsnap ) { #ifdef OGL_DEBUG OGLRender.OverallPoints++; #endif #ifdef OGL_ALL GlideMsg( "RenderAddPoint()\n"); #endif glReportErrors("RenderAddPoint"); // Peek to avoid updating the render state twice if (OGLRender.NumberOfTriangles) { RenderDrawTriangles_impl(); } else { // Finish rendering of last render buffer RenderUnlockArrays(); s_Framebuffer.OnRenderDrawTriangles(); // Update the state after processing the frame buffer because // the framebuffer class might request state changes as well // in order to restore the previous state RenderUpdateState(); } TColorStruct* pC = &OGLRender.TColor[OGLRender.RenderBufferSize]; TColorStruct* pC2; const GlideState glidestate = Glide.State; if (OpenGL.ColorAlphaUnit2) { { // Color pC->ar = a->r * D1OVER255; pC->ag = a->g * D1OVER255; pC->ab = a->b * D1OVER255; } // Alpha if (glidestate.AlphaLocal == GR_COMBINE_LOCAL_DEPTH) { // @todo: find out whether z has to be divided by 255 or by 65535 pC->aa = a->z * D1OVER255; } else { pC->aa = a->a * D1OVER255; } } else { pC2 = &OGLRender.TColor2[OGLRender.RenderBufferSize]; memset( pC2, 0, sizeof( TColorStruct ) ); // Color Stuff, need to optimize it if ( Glide.ALocal ) { switch (glidestate.AlphaLocal) { case GR_COMBINE_LOCAL_ITERATED: Local.aa = a->a * D1OVER255; break; case GR_COMBINE_LOCAL_CONSTANT: Local.aa = OpenGL.ConstantColor[3]; break; case GR_COMBINE_LOCAL_DEPTH: Local.aa = a->z; break; } } if ( Glide.AOther ) { switch (glidestate.AlphaOther) { case GR_COMBINE_OTHER_ITERATED: Other.aa = a->a * D1OVER255; break; case GR_COMBINE_OTHER_CONSTANT: Other.aa = OpenGL.ConstantColor[3]; break; case GR_COMBINE_OTHER_TEXTURE: Other.aa = 1.0f; break; } } if ( Glide.CLocal ) { switch (glidestate.ColorCombineLocal) { case GR_COMBINE_LOCAL_ITERATED: Local.ar = a->r * D1OVER255; Local.ag = a->g * D1OVER255; Local.ab = a->b * D1OVER255; break; case GR_COMBINE_LOCAL_CONSTANT: { GLfloat* color; if (glidestate.Delta0Mode) { color = &OpenGL.Delta0Color[0]; } else { color = &OpenGL.ConstantColor[0]; } Local.ar = color[0]; Local.ag = color[1]; Local.ab = color[2]; } break; } } if ( Glide.COther ) { switch (glidestate.ColorCombineOther) { case GR_COMBINE_OTHER_ITERATED: Other.ar = a->r * D1OVER255; Other.ag = a->g * D1OVER255; Other.ab = a->b * D1OVER255; break; case GR_COMBINE_OTHER_CONSTANT: { GLfloat* color; if (glidestate.Delta0Mode) { color = &OpenGL.Delta0Color[0]; } else { color = &OpenGL.ConstantColor[0]; } Other.ar = color[0]; Other.ag = color[1]; Other.ab = color[2]; } break; case GR_COMBINE_OTHER_TEXTURE: Other.ar = Other.ag = Other.ab = 1.0f; break; } } switch (glidestate.ColorCombineFunction) { case GR_COMBINE_FUNCTION_ZERO: pC->ar = pC->ag = pC->ab = 0.0f; break; case GR_COMBINE_FUNCTION_LOCAL: pC->ar = Local.ar; pC->ag = Local.ag; pC->ab = Local.ab; break; case GR_COMBINE_FUNCTION_LOCAL_ALPHA: pC->ar = pC->ag = pC->ab = Local.aa; break; case GR_COMBINE_FUNCTION_SCALE_OTHER: ColorFactor3Func( &CFactor, &Local, &Other ); pC->ar = CFactor.ar * Other.ar; pC->ag = CFactor.ag * Other.ag; pC->ab = CFactor.ab * Other.ab; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL: ColorFactor3Func( &CFactor, &Local, &Other ); pC->ar = CFactor.ar * Other.ar; pC->ag = CFactor.ag * Other.ag; pC->ab = CFactor.ab * Other.ab; pC2->ar = Local.ar; pC2->ag = Local.ag; pC2->ab = Local.ab; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA: ColorFactor3Func( &CFactor, &Local, &Other ); pC->ar = CFactor.ar * Other.ar; pC->ag = CFactor.ag * Other.ag; pC->ab = CFactor.ab * Other.ab; pC2->ar = pC2->ag = pC2->ab = Local.aa; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL: ColorFactor3Func( &CFactor, &Local, &Other ); pC->ar = CFactor.ar * (Other.ar - Local.ar); pC->ag = CFactor.ag * (Other.ag - Local.ag); pC->ab = CFactor.ab * (Other.ab - Local.ab); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL: if ((( glidestate.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_ALPHA ) || ( glidestate.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_RGB )) && ( glidestate.ColorCombineOther == GR_COMBINE_OTHER_TEXTURE ) ) { pC->ar = Local.ar; pC->ag = Local.ag; pC->ab = Local.ab; } else { ColorFactor3Func( &CFactor, &Local, &Other ); pC->ar = CFactor.ar * (Other.ar - Local.ar); pC->ag = CFactor.ag * (Other.ag - Local.ag); pC->ab = CFactor.ab * (Other.ab - Local.ab); pC2->ar = Local.ar; pC2->ag = Local.ag; pC2->ab = Local.ab; } break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA: if (((glidestate.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_ALPHA) || (glidestate.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_RGB)) && (glidestate.ColorCombineOther == GR_COMBINE_OTHER_TEXTURE)) { pC->ar = pC->ag = pC->ab = Local.aa; } else { ColorFactor3Func( &CFactor, &Local, &Other ); pC->ar = CFactor.ar * (Other.ar - Local.ar); pC->ag = CFactor.ag * (Other.ag - Local.ag); pC->ab = CFactor.ab * (Other.ab - Local.ab); pC2->ar = pC2->ag = pC2->ab = Local.aa; } break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL: ColorFactor3Func( &CFactor, &Local, &Other ); pC->ar = ( 1.0f - CFactor.ar ) * Local.ar; pC->ag = ( 1.0f - CFactor.ag ) * Local.ag; pC->ab = ( 1.0f - CFactor.ab ) * Local.ab; pC2->ar = Local.ar; pC2->ag = Local.ag; pC2->ab = Local.ab; break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA: ColorFactor3Func( &CFactor, &Local, &Other ); pC->ar = CFactor.ar * -Local.ar; pC->ag = CFactor.ag * -Local.ag; pC->ab = CFactor.ab * -Local.ab; pC2->ar = pC2->ag = pC2->ab = Local.aa; break; } switch (glidestate.AlphaFunction) { case GR_COMBINE_FUNCTION_ZERO: pC->aa = 0.0f; break; case GR_COMBINE_FUNCTION_LOCAL: case GR_COMBINE_FUNCTION_LOCAL_ALPHA: pC->aa = Local.aa; break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL: case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA: pC->aa = ((1.0f - AlphaFactorFunc( Local.aa, Other.aa )) * Local.aa); break; case GR_COMBINE_FUNCTION_SCALE_OTHER: pC->aa = (AlphaFactorFunc( Local.aa, Other.aa ) * Other.aa); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL: case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA: pC->aa = AlphaFactorFunc( Local.aa, Other.aa ) * Other.aa + Local.aa; // pC2->aa = Local.aa; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL: pC->aa = (AlphaFactorFunc( Local.aa, Other.aa ) * ( Other.aa - Local.aa )); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL: case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA: pC->aa = AlphaFactorFunc( Local.aa, Other.aa ) * ( Other.aa - Local.aa ) + Local.aa; // pC2->aa = Local.aa; break; } if (OpenGL.FogTextureUnit == 0) { if (glidestate.ColorCombineInvert) { pC->ar = 1.0f - pC->ar - pC2->ar; pC->ag = 1.0f - pC->ag - pC2->ag; pC->ab = 1.0f - pC->ab - pC2->ab; pC2->ar = pC2->ag = pC2->ab = 0.0f; } if (glidestate.AlphaInvert) { pC->aa = 1.0f - pC->aa - pC2->aa; pC2->aa = 0.0f; } } } TVertexStruct* pV = &OGLRender.TVertex[OGLRender.RenderBufferSize]; // Z-Buffering if ((glidestate.DepthBufferMode == GR_DEPTHBUFFER_DISABLE) || (glidestate.DepthBufferMode == GR_CMP_ALWAYS)) { pV->az = 0.0f; } else if ( OpenGL.DepthBufferType ) { pV->az = a->ooz * D1OVER65536; } else { // // For silly values of oow, depth buffering doesn't // seem to work, so map them to a sensible z. When // games use these silly values, they probably don't // use z buffering anyway. // if ( a->oow > 1.0 ) { pV->az = 0.9f; } else if ( InternalConfig.PrecisionFix ) { pV->az = precision_fix(a->oow); } else { pV->az = a->oow; } } if ( ( unsnap ) && ( a->x > vertex_snap_compare ) ) { pV->ax = a->x - vertex_snap; pV->ay = a->y - vertex_snap; } else { pV->ax = a->x; pV->ay = a->y; } TTextureStruct* pTS = &OGLRender.TTexture[OGLRender.RenderBufferSize]; if ( OpenGL.Texture ) { pTS->as = a->tmuvtx[0].sow * Textures->GetWAspect(); pTS->at = a->tmuvtx[0].tow * Textures->GetHAspect(); pTS->aoow = a->oow; #ifdef OGL_DEBUG_GLIDE_COORDS GlideMsg(a, a->oow); #endif } #ifdef OGL_DEBUG_GLIDE_COORDS else { GlideMsg(a, 1.0f); } #endif TFogStruct* pF = &OGLRender.TFog[OGLRender.RenderBufferSize]; if(glidestate.FogMode) { if (glidestate.FogMode & GR_FOG_WITH_TABLE) { pF->af = (float) OpenGL.FogTable[(FxU16)(1.0f / a->oow)] * D1OVER255; } else { pF->af = a->a * D1OVER255; } /* if ( glidestate.FogMode & GR_FOG_ADD2 ) { pF->af = 1.0f - pF->af; } */ #ifdef OGL_DEBUG DEBUG_MIN_MAX( pF->af, OGLRender.MaxF, OGLRender.MinF ); #endif } else /* if (OGLRender.UseEnvCombineFog) */ // env combine fog is the default { // Must provide dummy coords if fog is turned off but // the texture unit is active because of inveting color/alpha pF->af = 0.0; } #ifdef OGL_DEBUG DEBUG_MIN_MAX( pC->ar, OGLRender.MaxR, OGLRender.MinR ); DEBUG_MIN_MAX( pC->ag, OGLRender.MaxG, OGLRender.MinG ); DEBUG_MIN_MAX( pC->ab, OGLRender.MaxB, OGLRender.MinB ); DEBUG_MIN_MAX( pC->aa, OGLRender.MaxA, OGLRender.MinA ); DEBUG_MIN_MAX( pV->az, OGLRender.MaxZ, OGLRender.MinZ ); DEBUG_MIN_MAX( pV->ax, OGLRender.MaxX, OGLRender.MinX ); DEBUG_MIN_MAX( pV->ay, OGLRender.MaxY, OGLRender.MinY ); if (OpenGL.Texture) { DEBUG_MIN_MAX( pTS->as, OGLRender.MaxS, OGLRender.MinS ); DEBUG_MIN_MAX( pTS->at, OGLRender.MaxT, OGLRender.MinT ); } #endif #ifdef OGL_DEBUG_OPENGL_COORDS GlideMsg(pV, pTS); #endif RenderUpdateState(); if (OpenGL.Texture) { Textures->MakeReady(); } glBegin( GL_POINTS ); OpenGL.ChromaKey ? glColor3fv( &pC->ar ) : glColor4fv( &pC->ar ); if (InternalConfig.EXT_secondary_color) { glSecondaryColor3fvEXT( &pC2->ar ); } if (OpenGL.Texture) { glTexCoord4fv( &pTS->as ); if (OpenGL.ColorAlphaUnit2) { glMultiTexCoord4fvARB( OpenGL.ColorAlphaUnit2, &pTS->as ); } } if (glidestate.FogMode) { if (OGLRender.UseEnvCombineFog) { glMultiTexCoord1fARB( OpenGL.FogTextureUnit, pF->af ); } #ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD else if (InternalConfig.FogMode == OpenGLideFogEmulation_FogCoord) { glFogCoordfEXT( pF->af ); } #endif } glVertex3fv( &pV->ax ); glEnd(); glReportError(); s_Framebuffer.SetRenderBufferChanged(); VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); } // Color Factor functions void __fastcall ColorFactor3Zero( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ) { Result->ar = Result->ag = Result->ab = 0.0f; Result->br = Result->bg = Result->bb = 0.0f; Result->cr = Result->cg = Result->cb = 0.0f; } void __fastcall ColorFactor3Local( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ) { Result->ar = ColorComponent->ar; Result->ag = ColorComponent->ag; Result->ab = ColorComponent->ab; Result->br = ColorComponent->br; Result->bg = ColorComponent->bg; Result->bb = ColorComponent->bb; Result->cr = ColorComponent->cr; Result->cg = ColorComponent->cg; Result->cb = ColorComponent->cb; } void __fastcall ColorFactor3OtherAlpha( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ) { Result->ar = Result->ag = Result->ab = OtherAlpha->aa; Result->br = Result->bg = Result->bb = OtherAlpha->ba; Result->cr = Result->cg = Result->cb = OtherAlpha->ca; } void __fastcall ColorFactor3LocalAlpha( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ) { Result->ar = Result->ag = Result->ab = ColorComponent->aa; Result->br = Result->bg = Result->bb = ColorComponent->ba; Result->cr = Result->cg = Result->cb = ColorComponent->ca; } void __fastcall ColorFactor3OneMinusLocal( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ) { Result->ar = 1.0f - ColorComponent->ar; Result->ag = 1.0f - ColorComponent->ag; Result->ab = 1.0f - ColorComponent->ab; Result->br = 1.0f - ColorComponent->br; Result->bg = 1.0f - ColorComponent->bg; Result->bb = 1.0f - ColorComponent->bb; Result->cr = 1.0f - ColorComponent->cr; Result->cg = 1.0f - ColorComponent->cg; Result->cb = 1.0f - ColorComponent->cb; } void __fastcall ColorFactor3OneMinusOtherAlpha( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ) { Result->ar = Result->ag = Result->ab = 1.0f - OtherAlpha->aa; Result->br = Result->bg = Result->bb = 1.0f - OtherAlpha->ba; Result->cr = Result->cg = Result->cb = 1.0f - OtherAlpha->ca; } void __fastcall ColorFactor3OneMinusLocalAlpha( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ) { Result->ar = Result->ag = Result->ab = 1.0f - ColorComponent->aa; Result->br = Result->bg = Result->bb = 1.0f - ColorComponent->ba; Result->cr = Result->cg = Result->cb = 1.0f - ColorComponent->ca; } void __fastcall ColorFactor3One( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ) { Result->ar = Result->ag = Result->ab = 1.0f; Result->br = Result->bg = Result->bb = 1.0f; Result->cr = Result->cg = Result->cb = 1.0f; } // Alpha Factor functions float AlphaFactorZero( float LocalAlpha, float OtherAlpha ) { return 0.0f; } float AlphaFactorLocal( float LocalAlpha, float OtherAlpha ) { return LocalAlpha; } float AlphaFactorOther( float LocalAlpha, float OtherAlpha ) { return OtherAlpha; } float AlphaFactorOneMinusLocal( float LocalAlpha, float OtherAlpha ) { return 1.0f - LocalAlpha; } float AlphaFactorOneMinusOther( float LocalAlpha, float OtherAlpha ) { return 1.0f - OtherAlpha; } float AlphaFactorOne( float LocalAlpha, float OtherAlpha ) { return 1.0f; } // Color functions void ColorFunctionZero( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ) { pC->ar = pC->ag = pC->ab = 0.0f; pC->br = pC->bg = pC->bb = 0.0f; pC->cr = pC->cg = pC->cb = 0.0f; } void ColorFunctionLocal( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ) { pC->ar = Local->ar; pC->ag = Local->ag; pC->ab = Local->ab; pC->br = Local->br; pC->bg = Local->bg; pC->bb = Local->bb; pC->cr = Local->cr; pC->cg = Local->cg; pC->cb = Local->cb; } void ColorFunctionLocalAlpha( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ) { pC->ar = pC->ag = pC->ab = Local->aa; pC->br = pC->bg = pC->bb = Local->ba; pC->cr = pC->cg = pC->cb = Local->ca; } void ColorFunctionScaleOther( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ) { ColorFactor3Func( &CFactor, Local, Other ); pC->ar = CFactor.ar * Other->ar; pC->ag = CFactor.ag * Other->ag; pC->ab = CFactor.ab * Other->ab; pC->br = CFactor.br * Other->br; pC->bg = CFactor.bg * Other->bg; pC->bb = CFactor.bb * Other->bb; pC->cr = CFactor.cr * Other->cr; pC->cg = CFactor.cg * Other->cg; pC->cb = CFactor.cb * Other->cb; } void ColorFunctionScaleOtherAddLocal( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ) { ColorFactor3Func( &CFactor, Local, Other ); pC->ar = CFactor.ar * Other->ar; pC->ag = CFactor.ag * Other->ag; pC->ab = CFactor.ab * Other->ab; pC->br = CFactor.br * Other->br; pC->bg = CFactor.bg * Other->bg; pC->bb = CFactor.bb * Other->bb; pC->cr = CFactor.cr * Other->cr; pC->cg = CFactor.cg * Other->cg; pC->cb = CFactor.cb * Other->cb; pC2->ar = Local->ar; pC2->ag = Local->ag; pC2->ab = Local->ab; pC2->br = Local->br; pC2->bg = Local->bg; pC2->bb = Local->bb; pC2->cr = Local->cr; pC2->cg = Local->cg; pC2->cb = Local->cb; } void ColorFunctionScaleOtherAddLocalAlpha( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ) { ColorFactor3Func( &CFactor, Local, Other ); pC->ar = CFactor.ar * Other->ar; pC->ag = CFactor.ag * Other->ag; pC->ab = CFactor.ab * Other->ab; pC->br = CFactor.br * Other->br; pC->bg = CFactor.bg * Other->bg; pC->bb = CFactor.bb * Other->bb; pC->cr = CFactor.cr * Other->cr; pC->cg = CFactor.cg * Other->cg; pC->cb = CFactor.cb * Other->cb; pC2->ar = pC2->ag = pC2->ab = Local->aa; pC2->br = pC2->bg = pC2->bb = Local->ba; pC2->cr = pC2->cg = pC2->cb = Local->ca; } void ColorFunctionScaleOtherMinusLocal( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ) { ColorFactor3Func( &CFactor, Local, Other ); pC->ar = CFactor.ar * (Other->ar - Local->ar); pC->ag = CFactor.ag * (Other->ag - Local->ag); pC->ab = CFactor.ab * (Other->ab - Local->ab); pC->br = CFactor.br * (Other->br - Local->br); pC->bg = CFactor.bg * (Other->bg - Local->bg); pC->bb = CFactor.bb * (Other->bb - Local->bb); pC->cr = CFactor.cr * (Other->cr - Local->cr); pC->cg = CFactor.cg * (Other->cg - Local->cg); pC->cb = CFactor.cb * (Other->cb - Local->cb); } void ColorFunctionScaleOtherMinusLocalAddLocal( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ) { const GlideState glidestate = Glide.State; if (((glidestate.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_ALPHA) || (glidestate.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_RGB)) && (glidestate.ColorCombineOther == GR_COMBINE_OTHER_TEXTURE)) { pC->ar = Local->ar; pC->ag = Local->ag; pC->ab = Local->ab; pC->br = Local->br; pC->bg = Local->bg; pC->bb = Local->bb; pC->cr = Local->cr; pC->cg = Local->cg; pC->cb = Local->cb; } else { ColorFactor3Func( &CFactor, Local, Other ); pC->ar = CFactor.ar * (Other->ar - Local->ar); pC->ag = CFactor.ag * (Other->ag - Local->ag); pC->ab = CFactor.ab * (Other->ab - Local->ab); pC->br = CFactor.br * (Other->br - Local->br); pC->bg = CFactor.bg * (Other->bg - Local->bg); pC->bb = CFactor.bb * (Other->bb - Local->bb); pC->cr = CFactor.cr * (Other->cr - Local->cr); pC->cg = CFactor.cg * (Other->cg - Local->cg); pC->cb = CFactor.cb * (Other->cb - Local->cb); pC2->ar = Local->ar; pC2->ag = Local->ag; pC2->ab = Local->ab; pC2->br = Local->br; pC2->bg = Local->bg; pC2->bb = Local->bb; pC2->cr = Local->cr; pC2->cg = Local->cg; pC2->cb = Local->cb; } } void ColorFunctionScaleOtherMinusLocalAddLocalAlpha( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ) { const GlideState glidestate = Glide.State; if (((glidestate.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_ALPHA) || (glidestate.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_RGB)) && (glidestate.ColorCombineOther == GR_COMBINE_OTHER_TEXTURE)) { pC->ar = pC->ag = pC->ab = Local->aa; pC->br = pC->bg = pC->bb = Local->ba; pC->cr = pC->cg = pC->cb = Local->ca; } else { ColorFactor3Func( &CFactor, Local, Other ); pC->ar = CFactor.ar * (Other->ar - Local->ar); pC->ag = CFactor.ag * (Other->ag - Local->ag); pC->ab = CFactor.ab * (Other->ab - Local->ab); pC->br = CFactor.br * (Other->br - Local->br); pC->bg = CFactor.bg * (Other->bg - Local->bg); pC->bb = CFactor.bb * (Other->bb - Local->bb); pC->cr = CFactor.cr * (Other->cr - Local->cr); pC->cg = CFactor.cg * (Other->cg - Local->cg); pC->cb = CFactor.cb * (Other->cb - Local->cb); pC2->ar = pC2->ag = pC2->ab = Local->aa; pC2->br = pC2->bg = pC2->bb = Local->ba; pC2->cr = pC2->cg = pC2->cb = Local->ca; } } void ColorFunctionMinusLocalAddLocal( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ) { ColorFactor3Func( &CFactor, Local, Other ); pC->ar = ( 1.0f - CFactor.ar ) * Local->ar; pC->ag = ( 1.0f - CFactor.ag ) * Local->ag; pC->ab = ( 1.0f - CFactor.ab ) * Local->ab; pC->br = ( 1.0f - CFactor.br ) * Local->br; pC->bg = ( 1.0f - CFactor.bg ) * Local->bg; pC->bb = ( 1.0f - CFactor.bb ) * Local->bb; pC->cr = ( 1.0f - CFactor.cr ) * Local->cr; pC->cg = ( 1.0f - CFactor.cg ) * Local->cg; pC->cb = ( 1.0f - CFactor.cb ) * Local->cb; pC2->ar = Local->ar; pC2->ag = Local->ag; pC2->ab = Local->ab; pC2->br = Local->br; pC2->bg = Local->bg; pC2->bb = Local->bb; pC2->cr = Local->cr; pC2->cg = Local->cg; pC2->cb = Local->cb; } void ColorFunctionMinusLocalAddLocalAlpha( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ) { ColorFactor3Func( &CFactor, Local, Other ); pC->ar = CFactor.ar * -Local->ar; pC->ag = CFactor.ag * -Local->ag; pC->ab = CFactor.ab * -Local->ab; pC->br = CFactor.br * -Local->br; pC->bg = CFactor.bg * -Local->bg; pC->bb = CFactor.bb * -Local->bb; pC->cr = CFactor.cr * -Local->cr; pC->cg = CFactor.cg * -Local->cg; pC->cb = CFactor.cb * -Local->cb; pC2->ar = pC2->ag = pC2->ab = Local->aa; pC2->br = pC2->bg = pC2->bb = Local->ba; pC2->cr = pC2->cg = pC2->cb = Local->ca; }