1 /******************************************************************************
2 * Arachnoid Graphics Plugin for Mupen64Plus
3 * http://bitbucket.org/wahrhaft/mupen64plus-video-arachnoid/
5 * Copyright (C) 2009 Jon Ring
6 * Copyright (C) 2007 Kristofer Karlsson, Rickard Niklasson
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 *****************************************************************************/
27 #include "OpenGLRenderer.h"
28 #include "OpenGLManager.h"
31 #include "TextureCache.h"
34 //#include "CombinerManager.h"
35 #include "AdvancedCombinerManager.h"
36 #include "FogManager.h"
37 #include "ExtensionChecker.h"
38 #include "MultiTexturingExt.h"
39 #include "SecondaryColorExt.h"
44 GLenum glsav_col_type;
45 GLsizei glsav_col_stride;
46 GLvoid* glsav_col_array;
49 GLenum glsav_vtx_type;
50 GLsizei glsav_vtx_stride;
51 GLvoid* glsav_vtx_array;
54 GLenum glsav_tex_type;
55 GLsizei glsav_tex_stride;
56 GLvoid* glsav_tex_array;
58 GLint glsav_tex1_size;
59 GLenum glsav_tex1_type;
60 GLsizei glsav_tex1_stride;
61 GLvoid* glsav_tex1_array;
66 #ifndef GL_CLAMP_TO_EDGE
67 #define GL_CLAMP_TO_EDGE 0x812F
70 bool ARB_multitexture = false;
71 bool EXT_secondary_color = false;
73 //-----------------------------------------------------------------------------
75 //-----------------------------------------------------------------------------
76 OpenGLRenderer::OpenGLRenderer()
81 //-----------------------------------------------------------------------------
83 //-----------------------------------------------------------------------------
84 OpenGLRenderer::~OpenGLRenderer()
89 //-----------------------------------------------------------------------------
91 //! Saves pointers and setup render OpenGl pointers to vertex data.
92 //-----------------------------------------------------------------------------
93 bool OpenGLRenderer::initialize(RSP* rsp, RDP* rdp, TextureCache* textureCache, VI* vi, FogManager* fogMgr)
97 m_textureCache = textureCache;
104 //Init multitexturing
105 ARB_multitexture = initializeMultiTexturingExtensions();
106 EXT_secondary_color = initializeSecondaryColorExtension();
109 glVertexPointer(4, GL_FLOAT, sizeof(GLVertex), &m_vertices[0].x );
110 glEnableClientState( GL_VERTEX_ARRAY );
113 glColorPointer(4, GL_FLOAT, sizeof(GLVertex), &m_vertices[0].color.r);
114 glEnableClientState( GL_COLOR_ARRAY );
117 if ( EXT_secondary_color)
119 glSecondaryColorPointerEXT( 3, GL_FLOAT, sizeof( GLVertex ), &m_vertices[0].secondaryColor.r );
120 glEnableClientState( GL_SECONDARY_COLOR_ARRAY_EXT );
124 glClientActiveTextureARB( GL_TEXTURE0_ARB );
125 glTexCoordPointer( 2, GL_FLOAT, sizeof( GLVertex ), &m_vertices[0].s0 );
126 glEnableClientState( GL_TEXTURE_COORD_ARRAY );
129 glClientActiveTextureARB( GL_TEXTURE1_ARB );
130 glTexCoordPointer( 2, GL_FLOAT, sizeof( GLVertex ), &m_vertices[0].s1 );
131 glEnableClientState( GL_TEXTURE_COORD_ARRAY );
134 m_fogMgr->setFogCoordPointer(GL_FLOAT, sizeof(GLVertex), &m_vertices[0].fog);
135 m_fogMgr->enableFogCoordArray();
136 m_fogMgr->setLinearFog();
141 glsav_col_type = GL_FLOAT;
142 glsav_col_stride = sizeof(GLVertex);
143 glsav_col_array = &m_vertices[0].color.r;
146 glsav_vtx_type = GL_FLOAT;
147 glsav_vtx_stride = sizeof(GLVertex);
148 glsav_vtx_array = &m_vertices[0].x;
151 glsav_tex_type = GL_FLOAT;
152 glsav_tex_stride = sizeof(GLVertex);
153 glsav_tex_array = &m_vertices[0].s0;
156 glsav_tex1_type = GL_FLOAT;
157 glsav_tex1_stride = sizeof(GLVertex);
158 glsav_tex1_array = &m_vertices[0].s1;
167 //-----------------------------------------------------------------------------
169 //-----------------------------------------------------------------------------
170 void OpenGLRenderer::addTriangle( SPVertex *vertices, int v0, int v1, int v2 )
172 int v[] = { v0, v1, v2 };
175 m_rdp->updateStates();
177 //For each vertex in triangle
178 for (int i=0; i<3; ++i)
181 m_vertices[m_numVertices].x = vertices[v[i]].x;
182 m_vertices[m_numVertices].y = vertices[v[i]].y;
183 m_vertices[m_numVertices].z = m_rdp->getDepthSource() == G_ZS_PRIM ? m_rdp->getPrimitiveZ() * vertices[v[i]].w : vertices[v[i]].z;
184 m_vertices[m_numVertices].w = vertices[v[i]].w;
187 m_vertices[m_numVertices].color.r = vertices[v[i]].r;
188 m_vertices[m_numVertices].color.g = vertices[v[i]].g;
189 m_vertices[m_numVertices].color.b = vertices[v[i]].b;
190 m_vertices[m_numVertices].color.a = vertices[v[i]].a;
191 m_rdp->getCombinerMgr()->getCombinerColor( &m_vertices[m_numVertices].color.r );
193 if ( EXT_secondary_color )
195 m_vertices[m_numVertices].secondaryColor.r = 0.0f;//lod_fraction; //vertices[v[i]].r;
196 m_vertices[m_numVertices].secondaryColor.g = 0.0f;//lod_fraction; //vertices[v[i]].g;
197 m_vertices[m_numVertices].secondaryColor.b = 0.0f;//lod_fraction; //vertices[v[i]].b;
198 m_vertices[m_numVertices].secondaryColor.a = 1.0f;
199 m_rdp->getCombinerMgr()->getSecondaryCombinerColor( &m_vertices[m_numVertices].secondaryColor.r );
203 if ( OpenGLManager::getSingleton().getFogEnabled() )
205 if (vertices[v[i]].z < -vertices[v[i]].w)
207 m_vertices[m_numVertices].fog = max(0.0f, -m_fogMgr->getMultiplier() + m_fogMgr->getOffset() );
211 m_vertices[m_numVertices].fog = max(0.0f, vertices[v[i]].z / vertices[v[i]].w * m_fogMgr->getMultiplier() + m_fogMgr->getOffset());
216 if ( m_rdp->getCombinerMgr()->getUsesTexture0() )
218 RSPTexture& rspTexture = m_rsp->getTexture();
219 CachedTexture* cacheTexture = m_textureCache->getCurrentTexture(0);
220 RDPTile* rspTile = m_rsp->getTile(0);
223 m_vertices[m_numVertices].s0 = (vertices[v[i]].s * cacheTexture->shiftScaleS * rspTexture.scaleS - rspTile->fuls + cacheTexture->offsetS) * cacheTexture->scaleS;
224 m_vertices[m_numVertices].t0 = (vertices[v[i]].t * cacheTexture->shiftScaleT * rspTexture.scaleT - rspTile->fult + cacheTexture->offsetT) * cacheTexture->scaleT;
228 m_vertices[m_numVertices].s0 = (vertices[v[i]].s * rspTexture.scaleS - rspTile->fuls );
229 m_vertices[m_numVertices].t0 = (vertices[v[i]].t * rspTexture.scaleT - rspTile->fult );
233 if ( m_rdp->getCombinerMgr()->getUsesTexture1() )
235 RSPTexture& rspTexture = m_rsp->getTexture();
236 CachedTexture* cache = m_textureCache->getCurrentTexture(1);
237 RDPTile* rspTile = m_rsp->getTile(1);
238 if ( cache && rspTile )
240 m_vertices[m_numVertices].s1 = (vertices[v[i]].s * cache->shiftScaleS * rspTexture.scaleS - rspTile->fuls + cache->offsetS) * cache->scaleS;
241 m_vertices[m_numVertices].t1 = (vertices[v[i]].t * cache->shiftScaleT * rspTexture.scaleT - rspTile->fult + cache->offsetT) * cache->scaleT;
249 if ( m_numVertices >= 255 )
252 Logger::getSingleton().printMsg("RENDER VERTICES!!! :)", M64MSG_ERROR);
253 OpenGLRenderer::getSingleton().render();
257 //-----------------------------------------------------------------------------
259 //-----------------------------------------------------------------------------
260 void OpenGLRenderer::render()
262 glDrawArrays(GL_TRIANGLES, 0, m_numVertices);
263 m_numTriangles = m_numVertices = 0;
266 //-----------------------------------------------------------------------------
267 // Render Texture Rectangle
268 //-----------------------------------------------------------------------------
269 void OpenGLRenderer::renderTexRect( float ulx, float uly, //Upper left vertex
270 float lrx, float lry, //Lower right vertex
271 float uls, float ult, //Upper left texcoord
272 float lrs, float lrt, //Lower right texcoord
275 //Initialize first vertex (upper left vertex)
279 rect[0].z = m_rdp->getDepthSource() == 1 ? m_rdp->getPrimitiveZ() : 0.0f; //FIXME: Use viewport.nearz?
281 rect[0].color.r = 1.0f;
282 rect[0].color.g = 1.0f;
283 rect[0].color.b = 1.0f;
284 rect[0].color.a = 0.0f;
285 rect[0].secondaryColor.r = 1.0f;
286 rect[0].secondaryColor.g = 1.0f;
287 rect[0].secondaryColor.b = 1.0f;
288 rect[0].secondaryColor.a = 1.0f;
295 //Initialize second vertex (lower right vertex)
298 rect[1].z = m_rdp->getDepthSource() == 1 ? m_rdp->getPrimitiveZ() : 0.0f; //FIXME: Use viewport.nearz?
300 rect[1].color.r = 1.0f;
301 rect[1].color.g = 1.0f;
302 rect[1].color.b = 1.0f;
303 rect[1].color.a = 0.0f;
304 rect[1].secondaryColor.r = 1.0f;
305 rect[1].secondaryColor.g = 1.0f;
306 rect[1].secondaryColor.b = 1.0f;
307 rect[1].secondaryColor.a = 1.0f;
314 glDisable( GL_CULL_FACE );
315 glMatrixMode( GL_PROJECTION );
318 //glOrtho( 0, m_vi->getWidth(), m_vi->getHeight(), 0, 1.0f, -1.0f );
319 glOrtho( 0, m_vi->getWidth(), m_vi->getHeight(), 0, 1.0f, -1.0f );
320 //glOrtho( 0, OpenGLManager::getSingleton().getWidth(), OpenGLManager::getSingleton().getHeight(), 0, 1.0f, -1.0f );
321 //glViewport( 0, 0, m_vi->getWidth(), m_vi->getHeight() );
322 //glViewport( 0, 0, 320, 240 );
323 //glViewport( 0, 0, OpenGLManager::getSingleton().getWidth(), OpenGLManager::getSingleton().getHeight());
325 if ( m_rdp->getCombinerMgr()->getUsesTexture0() )
327 rect[0].s0 = rect[0].s0 * m_textureCache->getCurrentTexture(0)->shiftScaleS - m_rsp->getTile(0)->fuls;
328 rect[0].t0 = rect[0].t0 * m_textureCache->getCurrentTexture(0)->shiftScaleT - m_rsp->getTile(0)->fult;
329 rect[1].s0 = (rect[1].s0 + 1.0f) * m_textureCache->getCurrentTexture(0)->shiftScaleS - m_rsp->getTile(0)->fuls;
330 rect[1].t0 = (rect[1].t0 + 1.0f) * m_textureCache->getCurrentTexture(0)->shiftScaleT - m_rsp->getTile(0)->fult;
332 if ((m_textureCache->getCurrentTexture(0)->maskS) && (fmod( rect[0].s0, m_textureCache->getCurrentTexture(0)->width ) == 0.0f) && !(m_textureCache->getCurrentTexture(0)->mirrorS))
334 rect[1].s0 -= rect[0].s0;
338 if ((m_textureCache->getCurrentTexture(0)->maskT) && (fmod( rect[0].t0, m_textureCache->getCurrentTexture(0)->height ) == 0.0f) && !(m_textureCache->getCurrentTexture(0)->mirrorT))
340 rect[1].t0 -= rect[0].t0;
344 // if (OGL.ARB_multitexture)
345 glActiveTextureARB( GL_TEXTURE0_ARB );
347 if ((rect[0].s0 >= 0.0f) && (rect[1].s0 <= m_textureCache->getCurrentTexture(0)->width))
348 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
350 if ((rect[0].t0 >= 0.0f) && (rect[1].t0 <= m_textureCache->getCurrentTexture(0)->height))
351 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
354 rect[0].s0 *= m_textureCache->getCurrentTexture(0)->scaleS;
355 rect[0].t0 *= m_textureCache->getCurrentTexture(0)->scaleT;
356 rect[1].s0 *= m_textureCache->getCurrentTexture(0)->scaleS;
357 rect[1].t0 *= m_textureCache->getCurrentTexture(0)->scaleT;
360 if ( m_rdp->getCombinerMgr()->getUsesTexture1() )
362 rect[0].s1 = rect[0].s1 * m_textureCache->getCurrentTexture(1)->shiftScaleS - m_rsp->getTile(1)->fuls;
363 rect[0].t1 = rect[0].t1 * m_textureCache->getCurrentTexture(1)->shiftScaleT - m_rsp->getTile(1)->fult;
364 rect[1].s1 = (rect[1].s1 + 1.0f) * m_textureCache->getCurrentTexture(1)->shiftScaleS - m_rsp->getTile(1)->fuls;
365 rect[1].t1 = (rect[1].t1 + 1.0f) * m_textureCache->getCurrentTexture(1)->shiftScaleT - m_rsp->getTile(1)->fult;
367 if ((m_textureCache->getCurrentTexture(1)->maskS) && (fmod( rect[0].s1, m_textureCache->getCurrentTexture(1)->width ) == 0.0f) && !(m_textureCache->getCurrentTexture(1)->mirrorS))
369 rect[1].s1 -= rect[0].s1;
373 if ((m_textureCache->getCurrentTexture(1)->maskT) && (fmod( rect[0].t1, m_textureCache->getCurrentTexture(1)->height ) == 0.0f) && !(m_textureCache->getCurrentTexture(1)->mirrorT))
375 rect[1].t1 -= rect[0].t1;
379 glActiveTextureARB( GL_TEXTURE1_ARB );
381 if ((rect[0].s1 == 0.0f) && (rect[1].s1 <= m_textureCache->getCurrentTexture(1)->width))
382 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
384 if ((rect[0].t1 == 0.0f) && (rect[1].t1 <= m_textureCache->getCurrentTexture(1)->height))
385 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
387 rect[0].s1 *= m_textureCache->getCurrentTexture(1)->scaleS;
388 rect[0].t1 *= m_textureCache->getCurrentTexture(1)->scaleT;
389 rect[1].s1 *= m_textureCache->getCurrentTexture(1)->scaleS;
390 rect[1].t1 *= m_textureCache->getCurrentTexture(1)->scaleT;
394 if ( m_rdp->m_otherMode.cycleType == G_CYC_COPY ) /*&& !OGL.forceBilinear )*/
396 //if (OGL.ARB_multitexture)
397 glActiveTextureARB( GL_TEXTURE0_ARB );
399 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
400 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
403 // SetConstant( rect[0].color, combiner.vertex.color, combiner.vertex.alpha );
404 //rdp.updateStates();
405 m_rdp->getCombinerMgr()->getCombinerColor(&rect[0].color.r);
407 //if (OGL.EXT_secondary_color)
408 m_rdp->getCombinerMgr()->getSecondaryCombinerColor(&rect[0].secondaryColor.r);
409 // SetConstant( rect[0].secondaryColor, combiner.vertex.secondaryColor, combiner.vertex.alpha );
413 rect[0].color.r, rect[0].color.g, rect[0].color.b, rect[0].color.a,
414 rect[0].color.r, rect[0].color.g, rect[0].color.b, rect[0].color.a,
415 rect[0].color.r, rect[0].color.g, rect[0].color.b, rect[0].color.a,
416 rect[0].color.r, rect[0].color.g, rect[0].color.b, rect[0].color.a
420 rect[0].s0, rect[0].t0,
421 rect[1].s0, rect[0].t0,
422 rect[1].s0, rect[1].t0,
423 rect[0].s0, rect[1].t0
426 rect[0].s1, rect[0].t1,
427 rect[1].s1, rect[0].t1,
428 rect[1].s1, rect[1].t1,
429 rect[0].s1, rect[1].t1
433 rect[0].x, rect[0].y, rect[0].z, 1.0f,
434 rect[1].x, rect[0].y, rect[0].z, 1.0f,
435 rect[1].x, rect[1].y, rect[0].z, 1.0f,
436 rect[0].x, rect[1].y, rect[0].z, 1.0f
438 // Setup pointer array
439 glColorPointer(4, GL_FLOAT, 0, &col );
440 glVertexPointer(4,GL_FLOAT, 0,&vtx);
441 glClientActiveTexture( GL_TEXTURE1 );
442 glTexCoordPointer(2, GL_FLOAT, 0, &tex1);
443 glClientActiveTexture( GL_TEXTURE0 );
444 glTexCoordPointer(2, GL_FLOAT, 0, &tex);
446 glDrawArrays(GL_TRIANGLE_FAN,0,4);
447 // Restaure default pointer
448 glVertexPointer(4, GL_FLOAT, sizeof(GLVertex), &m_vertices[0].x );
449 glColorPointer(4, GL_FLOAT, sizeof(GLVertex), &m_vertices[0].color.r);
450 glClientActiveTexture( GL_TEXTURE1 );
451 glTexCoordPointer( 2, GL_FLOAT, sizeof( GLVertex ), &m_vertices[0].s1 );
452 glClientActiveTexture( GL_TEXTURE0 );
453 glTexCoordPointer( 2, GL_FLOAT, sizeof( GLVertex ), &m_vertices[0].s0 );
457 glColor4f( rect[0].color.r, rect[0].color.g, rect[0].color.b, rect[0].color.a );
459 //if (OGL.EXT_secondary_color)
460 glSecondaryColor3fEXT( rect[0].secondaryColor.r, rect[0].secondaryColor.g, rect[0].secondaryColor.b );
462 //if (OGL.ARB_multitexture)
464 // glMultiTexCoord2fARB( GL_TEXTURE0_ARB, rect[0].s0, rect[0].t0 );
465 // glMultiTexCoord2fARB( GL_TEXTURE1_ARB, rect[0].s1, rect[0].t1 );
466 // glVertex4f( rect[0].x, rect[0].y, rect[0].z, 1.0f );
468 // glMultiTexCoord2fARB( GL_TEXTURE0_ARB, rect[1].s0, rect[0].t0 );
469 // glMultiTexCoord2fARB( GL_TEXTURE1_ARB, rect[1].s1, rect[0].t1 );
470 // glVertex4f( rect[1].x, rect[0].y, rect[0].z, 1.0f );
472 // glMultiTexCoord2fARB( GL_TEXTURE0_ARB, rect[1].s0, rect[1].t0 );
473 // glMultiTexCoord2fARB( GL_TEXTURE1_ARB, rect[1].s1, rect[1].t1 );
474 // glVertex4f( rect[1].x, rect[1].y, rect[0].z, 1.0f );
476 // glMultiTexCoord2fARB( GL_TEXTURE0_ARB, rect[0].s0, rect[1].t0 );
477 // glMultiTexCoord2fARB( GL_TEXTURE1_ARB, rect[0].s1, rect[1].t1 );
478 // glVertex4f( rect[0].x, rect[1].y, rect[0].z, 1.0f );
484 Logger::getSingleton() << "\n\nTexRect x0=" << rect[0].x << " y0=" << rect[0].y <<
485 " x1=" << rect[1].x << "y1=" << rect[1].y <<
486 " t0u0=" << rect[0].s0 << " t0v0=" << rect[0].t0 <<
487 " t0u1=" << rect[1].s0 << " t0v1=" << rect[1].t0 << "\n";
489 glTexCoord2f(rect[0].s0, rect[0].t0 );
490 //glTexCoord2f(rect[0].s1, rect[0].t1 );
491 glVertex4f( rect[0].x, rect[0].y, rect[0].z, 1.0f );
493 glTexCoord2f(rect[1].s0, rect[0].t0 );
494 //glTexCoord2f(rect[1].s1, rect[0].t1 );
495 glVertex4f( rect[1].x, rect[0].y, rect[0].z, 1.0f );
497 glTexCoord2f(rect[1].s0, rect[1].t0 );
498 //glTexCoord2f(rect[1].s1, rect[1].t1 );
499 glVertex4f( rect[1].x, rect[1].y, rect[0].z, 1.0f );
501 glTexCoord2f(rect[0].s0, rect[1].t0 );
502 //glTexCoord2f(rect[0].s1, rect[1].t1 );
503 glVertex4f( rect[0].x, rect[1].y, rect[0].z, 1.0f );
507 /* glTexCoord2f( rect[0].s0, rect[0].t0 );
508 glVertex4f( rect[0].x, rect[0].y, rect[0].z, 1.0f );
511 glTexCoord2f( rect[1].s0, rect[0].t0 );
513 glTexCoord2f( rect[0].s0, rect[1].t0 );
515 glVertex4f( rect[1].x, rect[0].y, rect[0].z, 1.0f );
517 glTexCoord2f( rect[1].s0, rect[1].t0 );
518 glVertex4f( rect[1].x, rect[1].y, rect[0].z, 1.0f );
521 glTexCoord2f( rect[1].s0, rect[0].t0 );
523 glTexCoord2f( rect[1].s0, rect[0].t0 );
524 glVertex4f( rect[0].x, rect[1].y, rect[0].z, 1.0f );*/
529 //OGL_UpdateCullFace();
530 //OGL_UpdateViewport();