- Texture offsets: models are now decoded for each individual texture offset state and texture coordinates are adjusted while generating the vertex data.

- Model LUT now capable of differentiating between texture offset states (linked list of different texture offsets for each model address).
- Removed texOffset uniform attribute from vertex shader -- no longer needed.
This commit is contained in:
Bart Trzynadlowski 2011-07-21 08:12:16 +00:00
parent c5c518390a
commit a033058deb
4 changed files with 129 additions and 83 deletions

View file

@ -23,6 +23,11 @@
* Models.cpp * Models.cpp
* *
* Model parsing, caching, and drawing. * Model parsing, caching, and drawing.
*
* TO-DO List:
* -----------
* - More should be predecoded into the polygon structures, so that things like
* texture base coordinates are not re-decoded in two different places!
*/ */
#include <math.h> #include <math.h>
@ -132,7 +137,6 @@ void CRender3D::DrawDisplayList(ModelCache *Cache, POLY_STATE state)
else else
{ {
glUniformMatrix4fv(modelViewMatrixLoc, 1, GL_FALSE, D->Data.Model.modelViewMatrix); glUniformMatrix4fv(modelViewMatrixLoc, 1, GL_FALSE, D->Data.Model.modelViewMatrix);
glUniform2fv(texOffsetLoc, 1, D->Data.Model.texOffset);
glDrawArrays(GL_TRIANGLES, D->Data.Model.index, D->Data.Model.numVerts); glDrawArrays(GL_TRIANGLES, D->Data.Model.index, D->Data.Model.numVerts);
} }
@ -141,7 +145,7 @@ void CRender3D::DrawDisplayList(ModelCache *Cache, POLY_STATE state)
} }
// Appends an instance of a model or viewport to the display list, copying over the required state information // Appends an instance of a model or viewport to the display list, copying over the required state information
BOOL CRender3D::AppendDisplayList(ModelCache *Cache, BOOL isViewport, int modelNum) BOOL CRender3D::AppendDisplayList(ModelCache *Cache, BOOL isViewport, const struct VBORef *Model)
{ {
int lm, i; int lm, i;
@ -173,21 +177,17 @@ BOOL CRender3D::AppendDisplayList(ModelCache *Cache, BOOL isViewport, int modelN
// Copy projection matrix // Copy projection matrix
glGetFloatv(GL_PROJECTION_MATRIX, Cache->List[lm].Data.Viewport.projectionMatrix); glGetFloatv(GL_PROJECTION_MATRIX, Cache->List[lm].Data.Viewport.projectionMatrix);
} }
else if (Cache->Models[modelNum].numVerts[i] > 0) // vertices exist for this state else if (Model->numVerts[i] > 0) // vertices exist for this state
{ {
// Get index for new display list item and advance to next one // Get index for new display list item and advance to next one
lm = Cache->listSize++; lm = Cache->listSize++;
// Point to VBO for current model and state // Point to VBO for current model and state
Cache->List[lm].Data.Model.index = Cache->Models[modelNum].index[i]; Cache->List[lm].Data.Model.index = Model->index[i];
Cache->List[lm].Data.Model.numVerts = Cache->Models[modelNum].numVerts[i]; Cache->List[lm].Data.Model.numVerts = Model->numVerts[i];
// Copy modelview matrix // Copy modelview matrix
glGetFloatv(GL_MODELVIEW_MATRIX, Cache->List[lm].Data.Model.modelViewMatrix); glGetFloatv(GL_MODELVIEW_MATRIX, Cache->List[lm].Data.Model.modelViewMatrix);
// Texture offset
Cache->List[lm].Data.Model.texOffset[0] = texOffset[0];
Cache->List[lm].Data.Model.texOffset[1] = texOffset[1];
} }
else // nothing to do, continue loop else // nothing to do, continue loop
continue; continue;
@ -252,8 +252,8 @@ void CRender3D::InsertVertex(ModelCache *Cache, const Vertex *V, const Poly *P,
texWidth = (GLfloat) (32<<((P->header[3]>>3)&7)); texWidth = (GLfloat) (32<<((P->header[3]>>3)&7));
texHeight = (GLfloat) (32<<((P->header[3]>>0)&7)); texHeight = (GLfloat) (32<<((P->header[3]>>0)&7));
texPage = (P->header[4]&0x40) ? 1024 : 0; // treat texture page as Y coordinate texPage = (P->header[4]&0x40) ? 1024 : 0; // treat texture page as Y coordinate
texBaseX = (GLfloat) (32*(((P->header[4]&0x1F)<<1)|((P->header[5]>>7)&1))); texBaseX = (GLfloat) (32*(((P->header[4]&0x1F)<<1)|((P->header[5]>>7)&1))) + texOffsetXY[0];
texBaseY = (GLfloat) (32*(P->header[5]&0x1F)+texPage); texBaseY = (GLfloat) (32*(P->header[5]&0x1F)+texPage) + texOffsetXY[1];
/* /*
* Lighting and Color Modulation: * Lighting and Color Modulation:
@ -494,43 +494,55 @@ BOOL CRender3D::BeginModel(ModelCache *Cache)
} }
// Uploads all vertices from the local vertex buffer to the VBO, sets up the VBO reference, updates the LUT // Uploads all vertices from the local vertex buffer to the VBO, sets up the VBO reference, updates the LUT
void CRender3D::EndModel(ModelCache *Cache, int lutIdx) struct VBORef *CRender3D::EndModel(ModelCache *Cache, int lutIdx, UINT16 texOffset)
{ {
struct VBORef *Model;
int m; int m;
m = Cache->numModels++; m = Cache->numModels++;
Model = &(Cache->Models[m]);
// Record the number of vertices, completing the VBORef // Record the number of vertices, completing the VBORef
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
Cache->Models[m].numVerts[i] = Cache->curVertIdx[i]; Model->numVerts[i] = Cache->curVertIdx[i];
// First alpha polygon immediately follows the normal polygons // First alpha polygon immediately follows the normal polygons
Cache->Models[m].index[POLY_STATE_ALPHA] = Cache->Models[m].index[POLY_STATE_NORMAL]+Cache->Models[m].numVerts[POLY_STATE_NORMAL]; Model->index[POLY_STATE_ALPHA] = Model->index[POLY_STATE_NORMAL] + Model->numVerts[POLY_STATE_NORMAL];
// Upload from local vertex buffer to real VBO // Upload from local vertex buffer to real VBO
glBindBuffer(GL_ARRAY_BUFFER, Cache->vboID); glBindBuffer(GL_ARRAY_BUFFER, Cache->vboID);
if (Cache->Models[m].numVerts[POLY_STATE_NORMAL] > 0) if (Model->numVerts[POLY_STATE_NORMAL] > 0)
glBufferSubData(GL_ARRAY_BUFFER, Cache->Models[m].index[POLY_STATE_NORMAL]*VBO_VERTEX_SIZE*sizeof(GLfloat), Cache->curVertIdx[POLY_STATE_NORMAL]*VBO_VERTEX_SIZE*sizeof(GLfloat), Cache->verts[POLY_STATE_NORMAL]); glBufferSubData(GL_ARRAY_BUFFER, Model->index[POLY_STATE_NORMAL]*VBO_VERTEX_SIZE*sizeof(GLfloat), Cache->curVertIdx[POLY_STATE_NORMAL]*VBO_VERTEX_SIZE*sizeof(GLfloat), Cache->verts[POLY_STATE_NORMAL]);
if (Cache->Models[m].numVerts[POLY_STATE_ALPHA] > 0) if (Model->numVerts[POLY_STATE_ALPHA] > 0)
glBufferSubData(GL_ARRAY_BUFFER, Cache->Models[m].index[POLY_STATE_ALPHA]*VBO_VERTEX_SIZE*sizeof(GLfloat), Cache->curVertIdx[POLY_STATE_ALPHA]*VBO_VERTEX_SIZE*sizeof(GLfloat), Cache->verts[POLY_STATE_ALPHA]); glBufferSubData(GL_ARRAY_BUFFER, Model->index[POLY_STATE_ALPHA]*VBO_VERTEX_SIZE*sizeof(GLfloat), Cache->curVertIdx[POLY_STATE_ALPHA]*VBO_VERTEX_SIZE*sizeof(GLfloat), Cache->verts[POLY_STATE_ALPHA]);
// Update the LUT
Cache->lut[lutIdx] = m;
// Record LUT index in the model VBORef // Record LUT index in the model VBORef
Cache->Models[m].lutIdx = lutIdx; Model->lutIdx = lutIdx;
// Texture offset of this model state
Model->texOffset = texOffset;
// Update the LUT and link up to any existing model that already exists here
if (Cache->lut[lutIdx] >= 0) // another texture offset state already cached
Model->nextTexOffset = &(Cache->Models[Cache->lut[lutIdx]]);
Cache->lut[lutIdx] = m;
// Return a pointer to the cached model's VBO reference
return Model;
} }
/* /*
* CacheModel(): * CacheModel():
* *
* Decodes and caches a complete model. Returns FAIL if any sort of overflow in * Decodes and caches a complete model. Returns NULL if any sort of overflow in
* the cache occurred. In this case, the model cache should be cleared before * the cache occurred. In this case, the model cache should be cleared before
* being used again because an incomplete model will be stored, wasting vertex * being used again because an incomplete model will be stored, wasting vertex
* buffer space. * buffer space.
*
* A pointer to the VBO reference for the cached model is returned when
* successful.
*/ */
struct VBORef *CRender3D::CacheModel(ModelCache *Cache, int lutIdx, UINT16 texOffset, const UINT32 *data)
BOOL CRender3D::CacheModel(ModelCache *Cache, int lutIdx, const UINT32 *data)
{ {
Vertex Prev[4]; // previous vertices Vertex Prev[4]; // previous vertices
int numPolys = 0; int numPolys = 0;
@ -541,11 +553,11 @@ BOOL CRender3D::CacheModel(ModelCache *Cache, int lutIdx, const UINT32 *data)
// return FAIL; // return FAIL;
if (data == NULL) if (data == NULL)
return FAIL; return NULL;
// Start constructing a new model // Start constructing a new model
if (FAIL == BeginModel(Cache)) if (FAIL == BeginModel(Cache))
return FAIL; // too many models! return NULL; // too many models!
// Cache all polygons // Cache all polygons
while (!done) while (!done)
@ -572,8 +584,10 @@ BOOL CRender3D::CacheModel(ModelCache *Cache, int lutIdx, const UINT32 *data)
texWidth = (32<<((P.header[3]>>3)&7)); texWidth = (32<<((P.header[3]>>3)&7));
texHeight = (32<<((P.header[3]>>0)&7)); texHeight = (32<<((P.header[3]>>0)&7));
texPage = (P.header[4]&0x40) ? 1024 : 0; // treat texture page as Y coordinate texPage = (P.header[4]&0x40) ? 1024 : 0; // treat texture page as Y coordinate
texBaseX = (32*(((P.header[4]&0x1F)<<1)|((P.header[5]>>7)&1))); texBaseX = (32*(((P.header[4]&0x1F)<<1)|((P.header[5]>>7)&1))) + (int)texOffsetXY[0];
texBaseY = (32*(P.header[5]&0x1F)+texPage); texBaseY = (32*(P.header[5]&0x1F)+texPage) + (int)texOffsetXY[1];
texBaseX &= 2047;
texBaseY &= 2047;
uvScale = (P.header[1]&0x40)?1.0f:(1.0f/8.0f); uvScale = (P.header[1]&0x40)?1.0f:(1.0f/8.0f);
// Determine whether this is an alpha polygon // Determine whether this is an alpha polygon
@ -599,7 +613,7 @@ BOOL CRender3D::CacheModel(ModelCache *Cache, int lutIdx, const UINT32 *data)
} }
// Decode the texture // Decode the texture
DecodeTexture(texFormat, texBaseX+(int)texOffset[0], texBaseY+(int)texOffset[1], texWidth, texHeight); DecodeTexture(texFormat, texBaseX, texBaseY, texWidth, texHeight);
// Polygon normal is in upper 24 bits: sign + 1.22 fixed point // Polygon normal is in upper 24 bits: sign + 1.22 fixed point
P.n[0] = (GLfloat) (((INT32)P.header[1])>>8) * (1.0f/4194304.0f); P.n[0] = (GLfloat) (((INT32)P.header[1])>>8) * (1.0f/4194304.0f);
@ -661,16 +675,13 @@ BOOL CRender3D::CacheModel(ModelCache *Cache, int lutIdx, const UINT32 *data)
// Copy this polygon into the model buffer // Copy this polygon into the model buffer
if (OKAY != InsertPolygon(Cache,&P)) if (OKAY != InsertPolygon(Cache,&P))
return FAIL; return NULL;
++numPolys; ++numPolys;
} }
StopDecoding:
// Finish model and enter it into the LUT // Finish model and enter it into the LUT
EndModel(Cache,lutIdx); return EndModel(Cache,lutIdx,texOffset);
return OKAY;
} }
@ -678,12 +689,26 @@ StopDecoding:
Cache Management Cache Management
******************************************************************************/ ******************************************************************************/
// Use this to determine if a model needs to be cached (returns TRUE if so) /*
BOOL CRender3D::NeedToCache(ModelCache *Cache, int lutIdx) * Look up a model. Use this to determine if a model needs to be cached
* (returns NULL if so).
*/
struct VBORef *CRender3D::LookUpModel(ModelCache *Cache, int lutIdx, UINT16 texOffset)
{ {
//if (Cache->dynamic) // never permanently store models in dynamic caches int m = Cache->lut[lutIdx];
// return TRUE;
return (Cache->lut[lutIdx]<0) ? TRUE : FALSE; // Has any state associated with this model LUT index been cached at all?
if (m < 0)
return NULL;
// Has the specified texture offset been cached?
for (struct VBORef *Model = &(Cache->Models[m]); Model != NULL; Model = Model->nextTexOffset)
{
if (Model->texOffset == texOffset)
return Model;
}
return NULL; // no match found, we must cache this new model state
} }
// Discard all models in the cache and the display list // Discard all models in the cache and the display list

View file

@ -188,8 +188,8 @@ void CRender3D::DecodeTexture(int format, int x, int y, int width, int height)
UINT16 texel; UINT16 texel;
GLfloat c, a; GLfloat c, a;
x %= 2048; x &= 2047;
y %= 2048; y &= 2047;
if ((x+width)>2048 || (y+height)>2048) if ((x+width)>2048 || (y+height)>2048)
return; return;
@ -616,12 +616,16 @@ void CRender3D::ClearStack(void)
* buffer overflows and display list overflows will be detected. An attempt is * buffer overflows and display list overflows will be detected. An attempt is
* made to salvage the situation if this occurs, so if DrawModel() returns * made to salvage the situation if this occurs, so if DrawModel() returns
* FAIL, it is a serious matter and rendering should be aborted for the frame. * FAIL, it is a serious matter and rendering should be aborted for the frame.
*
* The current texture offset state, texOffset, is also used. Models are cached
* for each unique texOffset.
*/ */
BOOL CRender3D::DrawModel(UINT32 modelAddr) BOOL CRender3D::DrawModel(UINT32 modelAddr)
{ {
ModelCache *Cache; ModelCache *Cache;
const UINT32 *model; const UINT32 *model;
int lutIdx; int lutIdx;
struct VBORef *ModelRef;
//if (modelAddr==0x7FFF00) // Fighting Vipers (this is not polygon data!) //if (modelAddr==0x7FFF00) // Fighting Vipers (this is not polygon data!)
// return; // return;
@ -637,10 +641,12 @@ BOOL CRender3D::DrawModel(UINT32 modelAddr)
// Look up the model in the LUT and cache it if necessary // Look up the model in the LUT and cache it if necessary
lutIdx = modelAddr&0xFFFFFF; lutIdx = modelAddr&0xFFFFFF;
if (NeedToCache(Cache, lutIdx)) ModelRef = LookUpModel(Cache, lutIdx, texOffset);
if (NULL == ModelRef)
{ {
// Attempt to cache the model // Attempt to cache the model
if (CacheModel(Cache, lutIdx, model) != OKAY) ModelRef = CacheModel(Cache, lutIdx, texOffset, model);
if (NULL == ModelRef)
{ {
// Model could not be cached. Render what we have so far and try again. // Model could not be cached. Render what we have so far and try again.
DrawDisplayList(&VROMCache, POLY_STATE_NORMAL); DrawDisplayList(&VROMCache, POLY_STATE_NORMAL);
@ -651,13 +657,14 @@ BOOL CRender3D::DrawModel(UINT32 modelAddr)
ClearModelCache(&PolyCache); ClearModelCache(&PolyCache);
// Try caching again... // Try caching again...
if (CacheModel(Cache, lutIdx, model) != OKAY) ModelRef = CacheModel(Cache, lutIdx, texOffset, model);
if (NULL == ModelRef)
return ErrorUnableToCacheModel(modelAddr); // nothing we can do :( return ErrorUnableToCacheModel(modelAddr); // nothing we can do :(
} }
} }
// Add to display list // Add to display list
return AppendDisplayList(Cache, FALSE, Cache->lut[lutIdx]); return AppendDisplayList(Cache, FALSE, ModelRef);
} }
// Descends into a 10-word culling node // Descends into a 10-word culling node
@ -667,6 +674,7 @@ void CRender3D::DescendCullingNode(UINT32 addr)
UINT32 matrixOffset, node1Ptr, node2Ptr; UINT32 matrixOffset, node1Ptr, node2Ptr;
float x, y, z, oldTexOffsetX, oldTexOffsetY; float x, y, z, oldTexOffsetX, oldTexOffsetY;
int tx, ty; int tx, ty;
UINT16 oldTexOffset;
++stackDepth; ++stackDepth;
// Stack depth of 64 is too small for Star Wars Trilogy (Hoth) // Stack depth of 64 is too small for Star Wars Trilogy (Hoth)
@ -696,15 +704,20 @@ void CRender3D::DescendCullingNode(UINT32 addr)
z = *(float *) &node[0x06-offset]; z = *(float *) &node[0x06-offset];
// Texture offset? // Texture offset?
oldTexOffsetX = texOffset[0]; // save old offsets oldTexOffsetX = texOffsetXY[0]; // save old offsets
oldTexOffsetY = texOffset[1]; oldTexOffsetY = texOffsetXY[1];
oldTexOffset = texOffset;
if (!offset) // Step 1.5+
{
tx = 32*((node[0x02]>>7)&0x3F); tx = 32*((node[0x02]>>7)&0x3F);
ty = 32*(node[0x02]&0x3F) + ((node[0x02]&0x4000)?1024:0); ty = 32*(node[0x02]&0x3F) + ((node[0x02]&0x4000)?1024:0); // TODO: 5 or 6 bits for Y coord?
if ((node[0x02]&0x8000)) // apply texture offsets, else retain current ones if ((node[0x02]&0x8000)) // apply texture offsets, else retain current ones
{ {
texOffset[0] = (GLfloat) tx; texOffsetXY[0] = (GLfloat) tx;
texOffset[1] = (GLfloat) ty; texOffsetXY[1] = (GLfloat) ty;
//printf("Tex Offset: %d, %d (%08X %08X)\n", tx, ty, node[0x02], node[0x00]); texOffset = node[0x02]&0x7FFF;
//printf("Tex Offset: %d, %d (%08X %08X)\n", tx, ty, node[0x02], node1Ptr);
}
} }
// Apply matrix and translation // Apply matrix and translation
@ -735,8 +748,9 @@ void CRender3D::DescendCullingNode(UINT32 addr)
--stackDepth; --stackDepth;
// Restore old texture offsets // Restore old texture offsets
texOffset[0] = oldTexOffsetX; texOffsetXY[0] = oldTexOffsetX;
texOffset[1] = oldTexOffsetY; texOffsetXY[1] = oldTexOffsetY;
texOffset = oldTexOffset;
} }
// A list of pointers. MAME assumes that these may only point to culling nodes. // A list of pointers. MAME assumes that these may only point to culling nodes.
@ -1119,8 +1133,9 @@ void CRender3D::RenderViewport(UINT32 addr, int pri)
//printf("Fog: R=%02X G=%02X B=%02X density=%g (%X) %d start=%g\n", ((vpnode[0x22]>>16)&0xFF), ((vpnode[0x22]>>8)&0xFF), ((vpnode[0x22]>>0)&0xFF), fogParams[3], vpnode[0x23], (fogParams[3]==fogParams[3]), fogParams[4]); //printf("Fog: R=%02X G=%02X B=%02X density=%g (%X) %d start=%g\n", ((vpnode[0x22]>>16)&0xFF), ((vpnode[0x22]>>8)&0xFF), ((vpnode[0x22]>>0)&0xFF), fogParams[3], vpnode[0x23], (fogParams[3]==fogParams[3]), fogParams[4]);
// Clear texture offsets before proceeding // Clear texture offsets before proceeding
texOffset[0] = 0.0; texOffsetXY[0] = 0.0;
texOffset[1] = 0.0; texOffsetXY[1] = 0.0;
texOffset = 0x0000;
// Set up coordinate system and base matrix // Set up coordinate system and base matrix
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
@ -1329,7 +1344,6 @@ BOOL CRender3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned
spotEllipseLoc = glGetUniformLocation(shaderProgram, "spotEllipse"); spotEllipseLoc = glGetUniformLocation(shaderProgram, "spotEllipse");
spotRangeLoc = glGetUniformLocation(shaderProgram, "spotRange"); spotRangeLoc = glGetUniformLocation(shaderProgram, "spotRange");
spotColorLoc = glGetUniformLocation(shaderProgram, "spotColor"); spotColorLoc = glGetUniformLocation(shaderProgram, "spotColor");
texOffsetLoc = glGetUniformLocation(shaderProgram, "texOffset");
// Get locations of custom vertex attributes // Get locations of custom vertex attributes
subTextureLoc = glGetAttribLocation(shaderProgram,"subTexture"); subTextureLoc = glGetAttribLocation(shaderProgram,"subTexture");

View file

@ -60,12 +60,20 @@ struct Poly
const UINT32 *header; // pointer to Real3D 7-word polygon header const UINT32 *header; // pointer to Real3D 7-word polygon header
}; };
// References to model polygons stored in a VBO /*
* VBORef:
*
* Reference to model polygons stored in a VBO. Each reference has two sets of
* vertices: normal and alpha. Copies of the model with different texture
* offsets applied are searchable via the linked list of texture offset states.
*/
struct VBORef struct VBORef
{ {
unsigned index[2]; // index of model polygons in VBO unsigned index[2]; // index of model polygons in VBO
unsigned numVerts[2];// number of vertices unsigned numVerts[2];// number of vertices
unsigned lutIdx; // LUT index associated with this model (for fast LUT clearing) unsigned lutIdx; // LUT index associated with this model (for fast LUT clearing)
struct VBORef *nextTexOffset; // linked list of models with different texture offset states
UINT16 texOffset; // texture offset data for this model
}; };
// Display list items: model instances and viewport settings // Display list items: model instances and viewport settings
@ -92,7 +100,6 @@ struct DisplayList
struct struct
{ {
GLfloat modelViewMatrix[4*4]; // model-view matrix GLfloat modelViewMatrix[4*4]; // model-view matrix
GLfloat texOffset[2]; // texture offset (X, Y)
unsigned index; // index in VBO unsigned index; // index in VBO
unsigned numVerts; // number of vertices unsigned numVerts; // number of vertices
} Model; } Model;
@ -282,14 +289,14 @@ private:
// Model caching and display list management // Model caching and display list management
void DrawDisplayList(ModelCache *Cache, POLY_STATE state); void DrawDisplayList(ModelCache *Cache, POLY_STATE state);
BOOL AppendDisplayList(ModelCache *Cache, BOOL isViewport, int modelNum); BOOL AppendDisplayList(ModelCache *Cache, BOOL isViewport, const struct VBORef *Model);
void ClearDisplayList(ModelCache *Cache); void ClearDisplayList(ModelCache *Cache);
BOOL InsertPolygon(ModelCache *cache, const Poly *p); BOOL InsertPolygon(ModelCache *cache, const Poly *p);
void InsertVertex(ModelCache *cache, const Vertex *v, const Poly *p, float normFlip); void InsertVertex(ModelCache *cache, const Vertex *v, const Poly *p, float normFlip);
BOOL BeginModel(ModelCache *cache); BOOL BeginModel(ModelCache *cache);
void EndModel(ModelCache *cache, int lutIdx); struct VBORef *EndModel(ModelCache *cache, int lutIdx, UINT16 texOffset);
BOOL CacheModel(ModelCache *cache, int lutIdx, const UINT32 *data); struct VBORef *CacheModel(ModelCache *cache, int lutIdx, UINT16 texOffset, const UINT32 *data);
BOOL NeedToCache(ModelCache *cache, int lutIdx); struct VBORef *LookUpModel(ModelCache *cache, int lutIdx, UINT16 texOffset);
void ClearModelCache(ModelCache *cache); void ClearModelCache(ModelCache *cache);
BOOL CreateModelCache(ModelCache *cache, unsigned vboMaxVerts, unsigned localMaxVerts, unsigned maxNumModels, unsigned numLUTEntries, unsigned displayListSize, BOOL isDynamic); BOOL CreateModelCache(ModelCache *cache, unsigned vboMaxVerts, unsigned localMaxVerts, unsigned maxNumModels, unsigned numLUTEntries, unsigned displayListSize, BOOL isDynamic);
void DestroyModelCache(ModelCache *cache); void DestroyModelCache(ModelCache *cache);
@ -359,7 +366,8 @@ private:
int stackDepth; // for debugging and error handling purposes int stackDepth; // for debugging and error handling purposes
// Texture offset (during scene graph processing) // Texture offset (during scene graph processing)
GLfloat texOffset[2]; // X, Y GLfloat texOffsetXY[2]; // decoded X, Y offsets
UINT16 texOffset; // raw texture offset data as it appears in culling node
// Resolution scaling factors (to support resolutions higher than 496x384) and offsets // Resolution scaling factors (to support resolutions higher than 496x384) and offsets
GLfloat xRatio, yRatio; GLfloat xRatio, yRatio;
@ -379,7 +387,6 @@ private:
GLuint spotEllipseLoc; // uniform GLuint spotEllipseLoc; // uniform
GLuint spotRangeLoc; // uniform GLuint spotRangeLoc; // uniform
GLuint spotColorLoc; // uniform GLuint spotColorLoc; // uniform
GLuint texOffsetLoc; // uniform
GLuint subTextureLoc; // attribute GLuint subTextureLoc; // attribute
GLuint texParamsLoc; // attribute GLuint texParamsLoc; // attribute
GLuint texFormatLoc; // attribute GLuint texFormatLoc; // attribute

View file

@ -34,7 +34,7 @@ uniform vec3 lighting[2]; // lighting state (lighting[0] = sun direction, light
uniform vec4 spotEllipse; // spotlight ellipse position: .x=X position (normalized device coordinates), .y=Y position, .z=half-width, .w=half-height) uniform vec4 spotEllipse; // spotlight ellipse position: .x=X position (normalized device coordinates), .y=Y position, .z=half-width, .w=half-height)
uniform vec2 spotRange; // spotlight Z range: .x=start (viewspace coordinates), .y=limit uniform vec2 spotRange; // spotlight Z range: .x=start (viewspace coordinates), .y=limit
uniform vec3 spotColor; // spotlight RGB color uniform vec3 spotColor; // spotlight RGB color
uniform vec2 texOffset; // offset (within 2048x2048 texture sheet) to apply to texture base coordinates //uniform vec2 texOffset; // offset (within 2048x2048 texture sheet) to apply to texture base coordinates
// Custom vertex attributes // Custom vertex attributes
attribute vec4 subTexture; // .x=texture X, .y=texture Y, .z=texture width, .w=texture height (all in texels) attribute vec4 subTexture; // .x=texture X, .y=texture Y, .z=texture width, .w=texture height (all in texels)
@ -139,7 +139,7 @@ void main(void)
// Pass remaining parameters to fragment shader // Pass remaining parameters to fragment shader
gl_TexCoord[0] = gl_MultiTexCoord0; gl_TexCoord[0] = gl_MultiTexCoord0;
fsSubTexture = subTexture; fsSubTexture = subTexture;
fsSubTexture.xy += texOffset; // apply texture offset //fsSubTexture.xy += texOffset; // apply texture offset
fsTexParams = texParams; fsTexParams = texParams;
fsTransLevel = transLevel; fsTransLevel = transLevel;
fsTexFormat = texFormat; fsTexFormat = texFormat;