OpenGL2: Store normals/tangents as int16_t[4].

This commit is contained in:
SmileTheory 2016-09-06 00:57:15 -07:00
parent 762f50757d
commit dfbaf50324
13 changed files with 288 additions and 1042 deletions

View file

@ -412,7 +412,7 @@ void RB_MDRSurfaceAnim( mdrSurface_t *surface )
tess.xyz[baseVertex + j][1] = tempVert[1];
tess.xyz[baseVertex + j][2] = tempVert[2];
R_VaoPackNormal((byte *)&tess.normal[baseVertex + j], tempNormal);
R_VaoPackNormal(tess.normal[baseVertex + j], tempNormal);
tess.texCoords[baseVertex + j][0][0] = v->texCoords[0];
tess.texCoords[baseVertex + j][0][1] = v->texCoords[1];

View file

@ -667,6 +667,63 @@ static shader_t *ShaderForShaderNum( int shaderNum, int lightmapNum ) {
return shader;
}
void LoadDrawVertToSrfVert(srfVert_t *s, drawVert_t *d, int realLightmapNum, float hdrVertColors[3])
{
vec4_t v;
s->xyz[0] = LittleFloat(d->xyz[0]);
s->xyz[1] = LittleFloat(d->xyz[1]);
s->xyz[2] = LittleFloat(d->xyz[2]);
s->st[0] = LittleFloat(d->st[0]);
s->st[1] = LittleFloat(d->st[1]);
if (realLightmapNum >= 0)
{
s->lightmap[0] = FatPackU(LittleFloat(d->lightmap[0]), realLightmapNum);
s->lightmap[1] = FatPackV(LittleFloat(d->lightmap[1]), realLightmapNum);
}
else
{
s->lightmap[0] = LittleFloat(d->lightmap[0]);
s->lightmap[1] = LittleFloat(d->lightmap[1]);
}
v[0] = LittleFloat(d->normal[0]);
v[1] = LittleFloat(d->normal[1]);
v[2] = LittleFloat(d->normal[2]);
R_VaoPackNormal(s->normal, v);
if (hdrVertColors)
{
v[0] = hdrVertColors[0];
v[1] = hdrVertColors[1];
v[2] = hdrVertColors[2];
}
else
{
//hack: convert LDR vertex colors to HDR
if (r_hdr->integer)
{
v[0] = MAX(d->color[0], 0.499f);
v[1] = MAX(d->color[1], 0.499f);
v[2] = MAX(d->color[2], 0.499f);
}
else
{
v[0] = d->color[0];
v[1] = d->color[1];
v[2] = d->color[2];
}
}
v[3] = d->color[3] / 255.0f;
R_ColorShiftLightingFloats(v, s->vertexColors, 1.0f / 255.0f);
}
/*
===============
ParseFace
@ -714,50 +771,7 @@ static void ParseFace( dsurface_t *ds, drawVert_t *verts, float *hdrVertColors,
ClearBounds(surf->cullinfo.bounds[0], surf->cullinfo.bounds[1]);
verts += LittleLong(ds->firstVert);
for(i = 0; i < numVerts; i++)
{
vec4_t color;
for(j = 0; j < 3; j++)
{
cv->verts[i].xyz[j] = LittleFloat(verts[i].xyz[j]);
cv->verts[i].normal[j] = LittleFloat(verts[i].normal[j]);
}
AddPointToBounds(cv->verts[i].xyz, surf->cullinfo.bounds[0], surf->cullinfo.bounds[1]);
for(j = 0; j < 2; j++)
{
cv->verts[i].st[j] = LittleFloat(verts[i].st[j]);
//cv->verts[i].lightmap[j] = LittleFloat(verts[i].lightmap[j]);
}
cv->verts[i].lightmap[0] = FatPackU(LittleFloat(verts[i].lightmap[0]), realLightmapNum);
cv->verts[i].lightmap[1] = FatPackV(LittleFloat(verts[i].lightmap[1]), realLightmapNum);
if (hdrVertColors)
{
color[0] = hdrVertColors[(ds->firstVert + i) * 3 ];
color[1] = hdrVertColors[(ds->firstVert + i) * 3 + 1];
color[2] = hdrVertColors[(ds->firstVert + i) * 3 + 2];
}
else
{
//hack: convert LDR vertex colors to HDR
if (r_hdr->integer)
{
color[0] = MAX(verts[i].color[0], 0.499f);
color[1] = MAX(verts[i].color[1], 0.499f);
color[2] = MAX(verts[i].color[2], 0.499f);
}
else
{
color[0] = verts[i].color[0];
color[1] = verts[i].color[1];
color[2] = verts[i].color[2];
}
}
color[3] = verts[i].color[3] / 255.0f;
R_ColorShiftLightingFloats( color, cv->verts[i].vertexColors, 1.0f / 255.0f );
}
LoadDrawVertToSrfVert(&cv->verts[i], &verts[i], realLightmapNum, hdrVertColors ? hdrVertColors + (ds->firstVert + i) * 3 : NULL);
// copy triangles
badTriangles = 0;
@ -823,7 +837,7 @@ ParseMesh
*/
static void ParseMesh ( dsurface_t *ds, drawVert_t *verts, float *hdrVertColors, msurface_t *surf ) {
srfBspSurface_t *grid = (srfBspSurface_t *)surf->data;
int i, j;
int i;
int width, height, numPoints;
srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE];
vec3_t bounds[2];
@ -858,49 +872,7 @@ static void ParseMesh ( dsurface_t *ds, drawVert_t *verts, float *hdrVertColors,
verts += LittleLong( ds->firstVert );
numPoints = width * height;
for(i = 0; i < numPoints; i++)
{
vec4_t color;
for(j = 0; j < 3; j++)
{
points[i].xyz[j] = LittleFloat(verts[i].xyz[j]);
points[i].normal[j] = LittleFloat(verts[i].normal[j]);
}
for(j = 0; j < 2; j++)
{
points[i].st[j] = LittleFloat(verts[i].st[j]);
//points[i].lightmap[j] = LittleFloat(verts[i].lightmap[j]);
}
points[i].lightmap[0] = FatPackU(LittleFloat(verts[i].lightmap[0]), realLightmapNum);
points[i].lightmap[1] = FatPackV(LittleFloat(verts[i].lightmap[1]), realLightmapNum);
if (hdrVertColors)
{
color[0] = hdrVertColors[(ds->firstVert + i) * 3 ];
color[1] = hdrVertColors[(ds->firstVert + i) * 3 + 1];
color[2] = hdrVertColors[(ds->firstVert + i) * 3 + 2];
}
else
{
//hack: convert LDR vertex colors to HDR
if (r_hdr->integer)
{
color[0] = MAX(verts[i].color[0], 0.499f);
color[1] = MAX(verts[i].color[1], 0.499f);
color[2] = MAX(verts[i].color[2], 0.499f);
}
else
{
color[0] = verts[i].color[0];
color[1] = verts[i].color[1];
color[2] = verts[i].color[2];
}
}
color[3] = verts[i].color[3] / 255.0f;
R_ColorShiftLightingFloats( color, points[i].vertexColors, 1.0f / 255.0f );
}
LoadDrawVertToSrfVert(&points[i], &verts[i], realLightmapNum, hdrVertColors ? hdrVertColors + (ds->firstVert + i) * 3 : NULL);
// pre-tesseleate
R_SubdividePatchToGrid( grid, width, height, points );
@ -964,49 +936,7 @@ static void ParseTriSurf( dsurface_t *ds, drawVert_t *verts, float *hdrVertColor
ClearBounds(surf->cullinfo.bounds[0], surf->cullinfo.bounds[1]);
verts += LittleLong(ds->firstVert);
for(i = 0; i < numVerts; i++)
{
vec4_t color;
for(j = 0; j < 3; j++)
{
cv->verts[i].xyz[j] = LittleFloat(verts[i].xyz[j]);
cv->verts[i].normal[j] = LittleFloat(verts[i].normal[j]);
}
AddPointToBounds( cv->verts[i].xyz, surf->cullinfo.bounds[0], surf->cullinfo.bounds[1] );
for(j = 0; j < 2; j++)
{
cv->verts[i].st[j] = LittleFloat(verts[i].st[j]);
cv->verts[i].lightmap[j] = LittleFloat(verts[i].lightmap[j]);
}
if (hdrVertColors)
{
color[0] = hdrVertColors[(ds->firstVert + i) * 3 ];
color[1] = hdrVertColors[(ds->firstVert + i) * 3 + 1];
color[2] = hdrVertColors[(ds->firstVert + i) * 3 + 2];
}
else
{
//hack: convert LDR vertex colors to HDR
if (r_hdr->integer)
{
color[0] = MAX(verts[i].color[0], 0.499f);
color[1] = MAX(verts[i].color[1], 0.499f);
color[2] = MAX(verts[i].color[2], 0.499f);
}
else
{
color[0] = verts[i].color[0];
color[1] = verts[i].color[1];
color[2] = verts[i].color[2];
}
}
color[3] = verts[i].color[3] / 255.0f;
R_ColorShiftLightingFloats( color, cv->verts[i].vertexColors, 1.0f / 255.0f );
}
LoadDrawVertToSrfVert(&cv->verts[i], &verts[i], -1, hdrVertColors ? hdrVertColors + (ds->firstVert + i) * 3 : NULL);
// copy triangles
badTriangles = 0;
@ -1849,8 +1779,8 @@ static void CopyVert(const srfVert_t * in, srfVert_t * out)
#ifdef USE_VERT_TANGENT_SPACE
VectorCopy4(in->tangent, out->tangent);
#endif
VectorCopy(in->normal, out->normal);
VectorCopy(in->lightdir, out->lightdir);
VectorCopy4(in->normal, out->normal);
VectorCopy4(in->lightdir, out->lightdir);
VectorCopy2(in->st, out->st);
VectorCopy2(in->lightmap, out->lightmap);
@ -3193,7 +3123,14 @@ void R_CalcVertexLightDirs( void )
case SF_GRID:
case SF_TRIANGLES:
for(i = 0; i < bspSurf->numVerts; i++)
R_LightDirForPoint( bspSurf->verts[i].xyz, bspSurf->verts[i].lightdir, bspSurf->verts[i].normal, &s_worldData );
{
vec3_t lightDir;
vec3_t normal;
R_VaoUnpackNormal(normal, bspSurf->verts[i].normal);
R_LightDirForPoint( bspSurf->verts[i].xyz, lightDir, normal, &s_worldData );
R_VaoPackNormal(bspSurf->verts[i].lightdir, lightDir);
}
break;

View file

@ -207,7 +207,11 @@ static int neighbors[8][2] = {
//if ( count == 0 ) {
// printf("bad normal\n");
//}
VectorNormalize2( sum, dv->normal );
{
vec3_t fNormal;
VectorNormalize2(sum, fNormal);
R_VaoPackNormal(dv->normal, fNormal);
}
}
}
}

View file

@ -295,23 +295,6 @@ void GLimp_InitExtraExtensions()
ri.Printf(PRINT_ALL, result[2], extension);
}
// GL_ARB_vertex_type_2_10_10_10_rev
extension = "GL_ARB_vertex_type_2_10_10_10_rev";
glRefConfig.packedNormalDataType = GL_BYTE;
if( GLimp_HaveExtension( extension ) )
{
qboolean useExt = !!r_arb_vertex_type_2_10_10_10_rev->integer;
if (useExt)
glRefConfig.packedNormalDataType = GL_INT_2_10_10_10_REV;
ri.Printf(PRINT_ALL, result[useExt], extension);
}
else
{
ri.Printf(PRINT_ALL, result[2], extension);
}
// use float lightmaps?
glRefConfig.floatLightmap = (glRefConfig.textureFloat && glRefConfig.halfFloatPixel && r_floatLightmap->integer && r_hdr->integer);

View file

@ -106,7 +106,6 @@ cvar_t *r_arb_half_float_pixel;
cvar_t *r_arb_half_float_vertex;
cvar_t *r_ext_framebuffer_multisample;
cvar_t *r_arb_seamless_cube_map;
cvar_t *r_arb_vertex_type_2_10_10_10_rev;
cvar_t *r_arb_vertex_array_object;
cvar_t *r_ext_direct_state_access;
@ -1168,7 +1167,6 @@ void R_Register( void )
r_arb_half_float_vertex = ri.Cvar_Get( "r_arb_half_float_vertex", "1", CVAR_ARCHIVE | CVAR_LATCH);
r_ext_framebuffer_multisample = ri.Cvar_Get( "r_ext_framebuffer_multisample", "0", CVAR_ARCHIVE | CVAR_LATCH);
r_arb_seamless_cube_map = ri.Cvar_Get( "r_arb_seamless_cube_map", "0", CVAR_ARCHIVE | CVAR_LATCH);
r_arb_vertex_type_2_10_10_10_rev = ri.Cvar_Get( "r_arb_vertex_type_2_10_10_10_rev", "1", CVAR_ARCHIVE | CVAR_LATCH);
r_arb_vertex_array_object = ri.Cvar_Get( "r_arb_vertex_array_object", "1", CVAR_ARCHIVE | CVAR_LATCH);
r_ext_direct_state_access = ri.Cvar_Get("r_ext_direct_state_access", "1", CVAR_ARCHIVE | CVAR_LATCH);

View file

@ -895,11 +895,11 @@ typedef struct
vec3_t xyz;
vec2_t st;
vec2_t lightmap;
vec3_t normal;
int16_t normal[4];
#ifdef USE_VERT_TANGENT_SPACE
vec4_t tangent;
int16_t tangent[4];
#endif
vec3_t lightdir;
int16_t lightdir[4];
vec4_t vertexColors;
#if DEBUG_OPTIMIZEVERTICES
@ -908,9 +908,9 @@ typedef struct
} srfVert_t;
#ifdef USE_VERT_TANGENT_SPACE
#define srfVert_t_cleared(x) srfVert_t (x) = {{0, 0, 0}, {0, 0}, {0, 0}, {0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0}, {0, 0, 0, 0}}
#define srfVert_t_cleared(x) srfVert_t (x) = {{0, 0, 0}, {0, 0}, {0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}
#else
#define srfVert_t_cleared(x) srfVert_t (x) = {{0, 0, 0}, {0, 0}, {0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0, 0}}
#define srfVert_t_cleared(x) srfVert_t (x) = {{0, 0, 0}, {0, 0}, {0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}
#endif
// srfBspSurface_t covers SF_GRID, SF_TRIANGLES, SF_POLY, and SF_VAO_MESH
@ -1201,10 +1201,9 @@ typedef struct
typedef struct
{
vec3_t xyz;
vec3_t normal;
int16_t normal[4];
#ifdef USE_VERT_TANGENT_SPACE
vec3_t tangent;
vec3_t bitangent;
int16_t tangent[4];
#endif
} mdvVertex_t;
@ -1411,7 +1410,6 @@ typedef struct {
qboolean depthClamp;
qboolean seamlessCubeMap;
GLenum packedNormalDataType;
GLenum packedTexcoordDataType;
GLenum packedColorDataType;
int packedTexcoordDataSize;
@ -1718,7 +1716,6 @@ extern cvar_t *r_arb_half_float_pixel;
extern cvar_t *r_arb_half_float_vertex;
extern cvar_t *r_ext_framebuffer_multisample;
extern cvar_t *r_arb_seamless_cube_map;
extern cvar_t *r_arb_vertex_type_2_10_10_10_rev;
extern cvar_t *r_arb_vertex_array_object;
extern cvar_t *r_ext_direct_state_access;
@ -1861,7 +1858,7 @@ void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader,
void R_CalcTexDirs(vec3_t sdir, vec3_t tdir, const vec3_t v1, const vec3_t v2,
const vec3_t v3, const vec2_t w1, const vec2_t w2, const vec2_t w3);
void R_CalcTbnFromNormalAndTexDirs(vec3_t tangent, vec3_t bitangent, vec3_t normal, vec3_t sdir, vec3_t tdir);
vec_t R_CalcTangentSpace(vec3_t tangent, vec3_t bitangent, const vec3_t normal, const vec3_t sdir, const vec3_t tdir);
qboolean R_CalcTangentVectors(srfVert_t * dv[3]);
#define CULL_IN 0 // completely unclipped
@ -2008,13 +2005,13 @@ typedef struct shaderCommands_s
{
glIndex_t indexes[SHADER_MAX_INDEXES] QALIGN(16);
vec4_t xyz[SHADER_MAX_VERTEXES] QALIGN(16);
uint32_t normal[SHADER_MAX_VERTEXES] QALIGN(16);
int16_t normal[SHADER_MAX_VERTEXES][4] QALIGN(16);
#ifdef USE_VERT_TANGENT_SPACE
uint32_t tangent[SHADER_MAX_VERTEXES] QALIGN(16);
int16_t tangent[SHADER_MAX_VERTEXES][4] QALIGN(16);
#endif
vec2_t texCoords[SHADER_MAX_VERTEXES][2] QALIGN(16);
vec4_t vertexColors[SHADER_MAX_VERTEXES] QALIGN(16);
uint32_t lightdir[SHADER_MAX_VERTEXES] QALIGN(16);
int16_t lightdir[SHADER_MAX_VERTEXES][4] QALIGN(16);
//int vertexDlightBits[SHADER_MAX_VERTEXES] QALIGN(16);
void *attribPointers[ATTR_INDEX_COUNT];
@ -2178,12 +2175,12 @@ VERTEX BUFFER OBJECTS
============================================================
*/
int R_VaoPackTangent(byte *out, vec4_t v);
int R_VaoPackNormal(byte *out, vec3_t v);
void R_VaoPackTangent(int16_t *out, vec4_t v);
void R_VaoPackNormal(int16_t *out, vec3_t v);
int R_VaoPackTexCoord(byte *out, vec2_t st);
int R_VaoPackColors(byte *out, vec4_t color);
void R_VaoUnpackTangent(vec4_t v, uint32_t b);
void R_VaoUnpackNormal(vec3_t v, uint32_t b);
void R_VaoUnpackTangent(vec4_t v, int16_t *pack);
void R_VaoUnpackNormal(vec3_t v, int16_t *pack);
vao_t *R_CreateVao(const char *name, byte *vertexes, int vertexesSize, byte *indexes, int indexesSize, vaoUsage_t usage);
vao_t *R_CreateVao2(const char *name, int numVertexes, srfVert_t *verts, int numIndexes, glIndex_t *inIndexes);

View file

@ -70,230 +70,11 @@ qboolean R_CompareVert(srfVert_t * v1, srfVert_t * v2, qboolean checkST)
/*
=============
R_CalcNormalForTriangle
R_CalcTexDirs
Lengyel, Eric. Computing Tangent Space Basis Vectors for an Arbitrary Mesh. Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html
=============
*/
void R_CalcNormalForTriangle(vec3_t normal, const vec3_t v0, const vec3_t v1, const vec3_t v2)
{
vec3_t udir, vdir;
// compute the face normal based on vertex points
VectorSubtract(v2, v0, udir);
VectorSubtract(v1, v0, vdir);
CrossProduct(udir, vdir, normal);
VectorNormalize(normal);
}
/*
=============
R_CalcTangentsForTriangle
http://members.rogers.com/deseric/tangentspace.htm
=============
*/
void R_CalcTangentsForTriangle(vec3_t tangent, vec3_t bitangent,
const vec3_t v0, const vec3_t v1, const vec3_t v2,
const vec2_t t0, const vec2_t t1, const vec2_t t2)
{
int i;
vec3_t planes[3];
vec3_t u, v;
for(i = 0; i < 3; i++)
{
VectorSet(u, v1[i] - v0[i], t1[0] - t0[0], t1[1] - t0[1]);
VectorSet(v, v2[i] - v0[i], t2[0] - t0[0], t2[1] - t0[1]);
VectorNormalize(u);
VectorNormalize(v);
CrossProduct(u, v, planes[i]);
}
//So your tangent space will be defined by this :
//Normal = Normal of the triangle or Tangent X Bitangent (careful with the cross product,
// you have to make sure the normal points in the right direction)
//Tangent = ( dp(Fx(s,t)) / ds, dp(Fy(s,t)) / ds, dp(Fz(s,t)) / ds ) or ( -Bx/Ax, -By/Ay, - Bz/Az )
//Bitangent = ( dp(Fx(s,t)) / dt, dp(Fy(s,t)) / dt, dp(Fz(s,t)) / dt ) or ( -Cx/Ax, -Cy/Ay, -Cz/Az )
// tangent...
tangent[0] = -planes[0][1] / planes[0][0];
tangent[1] = -planes[1][1] / planes[1][0];
tangent[2] = -planes[2][1] / planes[2][0];
VectorNormalize(tangent);
// bitangent...
bitangent[0] = -planes[0][2] / planes[0][0];
bitangent[1] = -planes[1][2] / planes[1][0];
bitangent[2] = -planes[2][2] / planes[2][0];
VectorNormalize(bitangent);
}
/*
=============
R_CalcTangentSpace
=============
*/
void R_CalcTangentSpace(vec3_t tangent, vec3_t bitangent, vec3_t normal,
const vec3_t v0, const vec3_t v1, const vec3_t v2, const vec2_t t0, const vec2_t t1, const vec2_t t2)
{
vec3_t cp, u, v;
vec3_t faceNormal;
VectorSet(u, v1[0] - v0[0], t1[0] - t0[0], t1[1] - t0[1]);
VectorSet(v, v2[0] - v0[0], t2[0] - t0[0], t2[1] - t0[1]);
CrossProduct(u, v, cp);
if(fabs(cp[0]) > 10e-6)
{
tangent[0] = -cp[1] / cp[0];
bitangent[0] = -cp[2] / cp[0];
}
u[0] = v1[1] - v0[1];
v[0] = v2[1] - v0[1];
CrossProduct(u, v, cp);
if(fabs(cp[0]) > 10e-6)
{
tangent[1] = -cp[1] / cp[0];
bitangent[1] = -cp[2] / cp[0];
}
u[0] = v1[2] - v0[2];
v[0] = v2[2] - v0[2];
CrossProduct(u, v, cp);
if(fabs(cp[0]) > 10e-6)
{
tangent[2] = -cp[1] / cp[0];
bitangent[2] = -cp[2] / cp[0];
}
VectorNormalize(tangent);
VectorNormalize(bitangent);
// compute the face normal based on vertex points
if ( normal[0] == 0.0f && normal[1] == 0.0f && normal[2] == 0.0f )
{
VectorSubtract(v2, v0, u);
VectorSubtract(v1, v0, v);
CrossProduct(u, v, faceNormal);
}
else
{
VectorCopy(normal, faceNormal);
}
VectorNormalize(faceNormal);
#if 1
// Gram-Schmidt orthogonalize
//tangent[a] = (t - n * Dot(n, t)).Normalize();
VectorMA(tangent, -DotProduct(faceNormal, tangent), faceNormal, tangent);
VectorNormalize(tangent);
// compute the cross product B=NxT
//CrossProduct(normal, tangent, bitangent);
#else
// normal, compute the cross product N=TxB
CrossProduct(tangent, bitangent, normal);
VectorNormalize(normal);
if(DotProduct(normal, faceNormal) < 0)
{
//VectorInverse(normal);
//VectorInverse(tangent);
//VectorInverse(bitangent);
// compute the cross product T=BxN
CrossProduct(bitangent, faceNormal, tangent);
// compute the cross product B=NxT
//CrossProduct(normal, tangent, bitangent);
}
#endif
VectorCopy(faceNormal, normal);
}
void R_CalcTangentSpaceFast(vec3_t tangent, vec3_t bitangent, vec3_t normal,
const vec3_t v0, const vec3_t v1, const vec3_t v2, const vec2_t t0, const vec2_t t1, const vec2_t t2)
{
vec3_t cp, u, v;
vec3_t faceNormal;
VectorSet(u, v1[0] - v0[0], t1[0] - t0[0], t1[1] - t0[1]);
VectorSet(v, v2[0] - v0[0], t2[0] - t0[0], t2[1] - t0[1]);
CrossProduct(u, v, cp);
if(fabs(cp[0]) > 10e-6)
{
tangent[0] = -cp[1] / cp[0];
bitangent[0] = -cp[2] / cp[0];
}
u[0] = v1[1] - v0[1];
v[0] = v2[1] - v0[1];
CrossProduct(u, v, cp);
if(fabs(cp[0]) > 10e-6)
{
tangent[1] = -cp[1] / cp[0];
bitangent[1] = -cp[2] / cp[0];
}
u[0] = v1[2] - v0[2];
v[0] = v2[2] - v0[2];
CrossProduct(u, v, cp);
if(fabs(cp[0]) > 10e-6)
{
tangent[2] = -cp[1] / cp[0];
bitangent[2] = -cp[2] / cp[0];
}
VectorNormalizeFast(tangent);
VectorNormalizeFast(bitangent);
// compute the face normal based on vertex points
VectorSubtract(v2, v0, u);
VectorSubtract(v1, v0, v);
CrossProduct(u, v, faceNormal);
VectorNormalizeFast(faceNormal);
#if 0
// normal, compute the cross product N=TxB
CrossProduct(tangent, bitangent, normal);
VectorNormalizeFast(normal);
if(DotProduct(normal, faceNormal) < 0)
{
VectorInverse(normal);
//VectorInverse(tangent);
//VectorInverse(bitangent);
CrossProduct(normal, tangent, bitangent);
}
VectorCopy(faceNormal, normal);
#else
// Gram-Schmidt orthogonalize
//tangent[a] = (t - n * Dot(n, t)).Normalize();
VectorMA(tangent, -DotProduct(faceNormal, tangent), faceNormal, tangent);
VectorNormalizeFast(tangent);
#endif
VectorCopy(faceNormal, normal);
}
/*
http://www.terathon.com/code/tangent.html
*/
void R_CalcTexDirs(vec3_t sdir, vec3_t tdir, const vec3_t v1, const vec3_t v2,
const vec3_t v3, const vec2_t w1, const vec2_t w2, const vec2_t w3)
{
@ -312,13 +93,21 @@ void R_CalcTexDirs(vec3_t sdir, vec3_t tdir, const vec3_t v1, const vec3_t v2,
t1 = w2[1] - w1[1];
t2 = w3[1] - w1[1];
r = 1.0f / (s1 * t2 - s2 * t1);
r = s1 * t2 - s2 * t1;
if (r) r = 1.0f / r;
VectorSet(sdir, (t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
VectorSet(tdir, (s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
}
void R_CalcTbnFromNormalAndTexDirs(vec3_t tangent, vec3_t bitangent, vec3_t normal, vec3_t sdir, vec3_t tdir)
/*
=============
R_CalcTangentSpace
Lengyel, Eric. Computing Tangent Space Basis Vectors for an Arbitrary Mesh. Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html
=============
*/
vec_t R_CalcTangentSpace(vec3_t tangent, vec3_t bitangent, const vec3_t normal, const vec3_t sdir, const vec3_t tdir)
{
vec3_t n_cross_t;
vec_t n_dot_t, handedness;
@ -332,113 +121,13 @@ void R_CalcTbnFromNormalAndTexDirs(vec3_t tangent, vec3_t bitangent, vec3_t norm
CrossProduct(normal, sdir, n_cross_t);
handedness = (DotProduct(n_cross_t, tdir) < 0.0f) ? -1.0f : 1.0f;
// Calculate bitangent
CrossProduct(normal, tangent, bitangent);
VectorScale(bitangent, handedness, bitangent);
// Calculate orthogonal bitangent, if necessary
if (bitangent)
CrossProduct(normal, tangent, bitangent);
return handedness;
}
void R_CalcTBN2(vec3_t tangent, vec3_t bitangent, vec3_t normal,
const vec3_t v1, const vec3_t v2, const vec3_t v3, const vec2_t t1, const vec2_t t2, const vec2_t t3)
{
vec3_t v2v1;
vec3_t v3v1;
float c2c1_T;
float c2c1_B;
float c3c1_T;
float c3c1_B;
float denominator;
float scale1, scale2;
vec3_t T, B, N, C;
// Calculate the tangent basis for each vertex of the triangle
// UPDATE: In the 3rd edition of the accompanying article, the for-loop located here has
// been removed as it was redundant (the entire TBN matrix was calculated three times
// instead of just one).
//
// Please note, that this function relies on the fact that the input geometry are triangles
// and the tangent basis for each vertex thus is identical!
//
// Calculate the vectors from the current vertex to the two other vertices in the triangle
VectorSubtract(v2, v1, v2v1);
VectorSubtract(v3, v1, v3v1);
// The equation presented in the article states that:
// c2c1_T = V2.texcoord.x - V1.texcoord.x
// c2c1_B = V2.texcoord.y - V1.texcoord.y
// c3c1_T = V3.texcoord.x - V1.texcoord.x
// c3c1_B = V3.texcoord.y - V1.texcoord.y
// Calculate c2c1_T and c2c1_B
c2c1_T = t2[0] - t1[0];
c2c1_B = t2[1] - t2[1];
// Calculate c3c1_T and c3c1_B
c3c1_T = t3[0] - t1[0];
c3c1_B = t3[1] - t1[1];
denominator = c2c1_T * c3c1_B - c3c1_T * c2c1_B;
//if(ROUNDOFF(fDenominator) == 0.0f)
if(denominator == 0.0f)
{
// We won't risk a divide by zero, so set the tangent matrix to the identity matrix
VectorSet(tangent, 1, 0, 0);
VectorSet(bitangent, 0, 1, 0);
VectorSet(normal, 0, 0, 1);
}
else
{
// Calculate the reciprocal value once and for all (to achieve speed)
scale1 = 1.0f / denominator;
// T and B are calculated just as the equation in the article states
VectorSet(T, (c3c1_B * v2v1[0] - c2c1_B * v3v1[0]) * scale1,
(c3c1_B * v2v1[1] - c2c1_B * v3v1[1]) * scale1,
(c3c1_B * v2v1[2] - c2c1_B * v3v1[2]) * scale1);
VectorSet(B, (-c3c1_T * v2v1[0] + c2c1_T * v3v1[0]) * scale1,
(-c3c1_T * v2v1[1] + c2c1_T * v3v1[1]) * scale1,
(-c3c1_T * v2v1[2] + c2c1_T * v3v1[2]) * scale1);
// The normal N is calculated as the cross product between T and B
CrossProduct(T, B, N);
#if 0
VectorCopy(T, tangent);
VectorCopy(B, bitangent);
VectorCopy(N, normal);
#else
// Calculate the reciprocal value once and for all (to achieve speed)
scale2 = 1.0f / ((T[0] * B[1] * N[2] - T[2] * B[1] * N[0]) +
(B[0] * N[1] * T[2] - B[2] * N[1] * T[0]) +
(N[0] * T[1] * B[2] - N[2] * T[1] * B[0]));
// Calculate the inverse if the TBN matrix using the formula described in the article.
// We store the basis vectors directly in the provided TBN matrix: pvTBNMatrix
CrossProduct(B, N, C); tangent[0] = C[0] * scale2;
CrossProduct(N, T, C); tangent[1] = -C[0] * scale2;
CrossProduct(T, B, C); tangent[2] = C[0] * scale2;
VectorNormalize(tangent);
CrossProduct(B, N, C); bitangent[0] = -C[1] * scale2;
CrossProduct(N, T, C); bitangent[1] = C[1] * scale2;
CrossProduct(T, B, C); bitangent[2] = -C[1] * scale2;
VectorNormalize(bitangent);
CrossProduct(B, N, C); normal[0] = C[2] * scale2;
CrossProduct(N, T, C); normal[1] = -C[2] * scale2;
CrossProduct(T, B, C); normal[2] = C[2] * scale2;
VectorNormalize(normal);
#endif
}
}
#ifdef USE_VERT_TANGENT_SPACE
qboolean R_CalcTangentVectors(srfVert_t * dv[3])
{
@ -455,7 +144,8 @@ qboolean R_CalcTangentVectors(srfVert_t * dv[3])
/* do each vertex */
for(i = 0; i < 3; i++)
{
vec3_t bitangent, nxt;
vec4_t tangent;
vec3_t normal, bitangent, nxt;
// calculate s tangent vector
s = dv[i]->st[0] + 10.0f;
@ -464,12 +154,12 @@ qboolean R_CalcTangentVectors(srfVert_t * dv[3])
bary[1] = ((dv[2]->st[0] - s) * (dv[0]->st[1] - t) - (dv[0]->st[0] - s) * (dv[2]->st[1] - t)) / bb;
bary[2] = ((dv[0]->st[0] - s) * (dv[1]->st[1] - t) - (dv[1]->st[0] - s) * (dv[0]->st[1] - t)) / bb;
dv[i]->tangent[0] = bary[0] * dv[0]->xyz[0] + bary[1] * dv[1]->xyz[0] + bary[2] * dv[2]->xyz[0];
dv[i]->tangent[1] = bary[0] * dv[0]->xyz[1] + bary[1] * dv[1]->xyz[1] + bary[2] * dv[2]->xyz[1];
dv[i]->tangent[2] = bary[0] * dv[0]->xyz[2] + bary[1] * dv[1]->xyz[2] + bary[2] * dv[2]->xyz[2];
tangent[0] = bary[0] * dv[0]->xyz[0] + bary[1] * dv[1]->xyz[0] + bary[2] * dv[2]->xyz[0];
tangent[1] = bary[0] * dv[0]->xyz[1] + bary[1] * dv[1]->xyz[1] + bary[2] * dv[2]->xyz[1];
tangent[2] = bary[0] * dv[0]->xyz[2] + bary[1] * dv[1]->xyz[2] + bary[2] * dv[2]->xyz[2];
VectorSubtract(dv[i]->tangent, dv[i]->xyz, dv[i]->tangent);
VectorNormalize(dv[i]->tangent);
VectorSubtract(tangent, dv[i]->xyz, tangent);
VectorNormalize(tangent);
// calculate t tangent vector
s = dv[i]->st[0];
@ -486,8 +176,11 @@ qboolean R_CalcTangentVectors(srfVert_t * dv[3])
VectorNormalize(bitangent);
// store bitangent handedness
CrossProduct(dv[i]->normal, dv[i]->tangent, nxt);
dv[i]->tangent[3] = (DotProduct(nxt, bitangent) < 0.0f) ? -1.0f : 1.0f;
R_VaoUnpackNormal(normal, dv[i]->normal);
CrossProduct(normal, tangent, nxt);
tangent[3] = (DotProduct(nxt, bitangent) < 0.0f) ? -1.0f : 1.0f;
R_VaoPackTangent(dv[i]->tangent, tangent);
// debug code
//% Sys_FPrintf( SYS_VRB, "%d S: (%f %f %f) T: (%f %f %f)\n", i,

View file

@ -350,17 +350,21 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
// The offset is added in the vertex normal vector direction
// so all triangles will still fit together.
// The 2 unit offset should avoid pretty much all LOD problems.
vec3_t fNormal;
numClipPoints = 3;
dv = cv->verts + m * cv->width + n;
VectorCopy(dv[0].xyz, clipPoints[0][0]);
VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[0].normal, clipPoints[0][0]);
R_VaoUnpackNormal(fNormal, dv[0].normal);
VectorMA(clipPoints[0][0], MARKER_OFFSET, fNormal, clipPoints[0][0]);
VectorCopy(dv[cv->width].xyz, clipPoints[0][1]);
VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]);
R_VaoUnpackNormal(fNormal, dv[cv->width].normal);
VectorMA(clipPoints[0][1], MARKER_OFFSET, fNormal, clipPoints[0][1]);
VectorCopy(dv[1].xyz, clipPoints[0][2]);
VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[1].normal, clipPoints[0][2]);
R_VaoUnpackNormal(fNormal, dv[1].normal);
VectorMA(clipPoints[0][2], MARKER_OFFSET, fNormal, clipPoints[0][2]);
// check the normal of this triangle
VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
@ -380,11 +384,14 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
}
VectorCopy(dv[1].xyz, clipPoints[0][0]);
VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[1].normal, clipPoints[0][0]);
R_VaoUnpackNormal(fNormal, dv[1].normal);
VectorMA(clipPoints[0][0], MARKER_OFFSET, fNormal, clipPoints[0][0]);
VectorCopy(dv[cv->width].xyz, clipPoints[0][1]);
VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]);
R_VaoUnpackNormal(fNormal, dv[cv->width].normal);
VectorMA(clipPoints[0][1], MARKER_OFFSET, fNormal, clipPoints[0][1]);
VectorCopy(dv[cv->width+1].xyz, clipPoints[0][2]);
VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[cv->width+1].normal, clipPoints[0][2]);
R_VaoUnpackNormal(fNormal, dv[cv->width + 1].normal);
VectorMA(clipPoints[0][2], MARKER_OFFSET, fNormal, clipPoints[0][2]);
// check the normal of this triangle
VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
@ -441,8 +448,10 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
{
for(j = 0; j < 3; j++)
{
vec3_t fNormal;
v = surf->verts[tri[j]].xyz;
VectorMA(v, MARKER_OFFSET, surf->verts[tri[j]].normal, clipPoints[0][j]);
R_VaoUnpackNormal(fNormal, surf->verts[tri[j]].normal);
VectorMA(v, MARKER_OFFSET, fNormal, clipPoints[0][j]);
}
// add the fragments of this face

View file

@ -564,6 +564,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
{
unsigned lat, lng;
unsigned short normal;
vec3_t fNormal;
v->xyz[0] = LittleShort(md3xyz->xyz[0]) * MD3_XYZ_SCALE;
v->xyz[1] = LittleShort(md3xyz->xyz[1]) * MD3_XYZ_SCALE;
@ -580,9 +581,11 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
// decode Y as sin( lat ) * sin( long )
// decode Z as cos( long )
v->normal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
v->normal[1] = tr.sinTable[lat] * tr.sinTable[lng];
v->normal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
fNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
fNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
fNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
R_VaoPackNormal(v->normal, fNormal);
}
// swap all the ST
@ -598,10 +601,13 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
#ifdef USE_VERT_TANGENT_SPACE
// calc tangent spaces
{
vec3_t *sdirs = ri.Malloc(sizeof(*sdirs) * surf->numVerts * mdvModel->numFrames);
vec3_t *tdirs = ri.Malloc(sizeof(*tdirs) * surf->numVerts * mdvModel->numFrames);
for(j = 0, v = surf->verts; j < (surf->numVerts * mdvModel->numFrames); j++, v++)
{
VectorClear(v->tangent);
VectorClear(v->bitangent);
VectorClear(sdirs[j]);
VectorClear(tdirs[j]);
}
for(f = 0; f < mdvModel->numFrames; f++)
@ -626,27 +632,32 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
R_CalcTexDirs(sdir, tdir, v0, v1, v2, t0, t1, t2);
VectorAdd(sdir, surf->verts[index0].tangent, surf->verts[index0].tangent);
VectorAdd(sdir, surf->verts[index1].tangent, surf->verts[index1].tangent);
VectorAdd(sdir, surf->verts[index2].tangent, surf->verts[index2].tangent);
VectorAdd(tdir, surf->verts[index0].bitangent, surf->verts[index0].bitangent);
VectorAdd(tdir, surf->verts[index1].bitangent, surf->verts[index1].bitangent);
VectorAdd(tdir, surf->verts[index2].bitangent, surf->verts[index2].bitangent);
VectorAdd(sdir, sdirs[index0], sdirs[index0]);
VectorAdd(sdir, sdirs[index1], sdirs[index1]);
VectorAdd(sdir, sdirs[index2], sdirs[index2]);
VectorAdd(tdir, tdirs[index0], tdirs[index0]);
VectorAdd(tdir, tdirs[index1], tdirs[index1]);
VectorAdd(tdir, tdirs[index2], tdirs[index2]);
}
}
for(j = 0, v = surf->verts; j < (surf->numVerts * mdvModel->numFrames); j++, v++)
{
vec3_t sdir, tdir;
vec3_t normal;
vec4_t tangent;
VectorCopy(v->tangent, sdir);
VectorCopy(v->bitangent, tdir);
VectorNormalize(sdirs[j]);
VectorNormalize(tdirs[j]);
VectorNormalize(sdir);
VectorNormalize(tdir);
R_VaoUnpackNormal(normal, v->normal);
R_CalcTbnFromNormalAndTexDirs(v->tangent, v->bitangent, v->normal, sdir, tdir);
tangent[3] = R_CalcTangentSpace(tangent, NULL, normal, sdirs[j], tdirs[j]);
R_VaoPackTangent(v->tangent, tangent);
}
ri.Free(sdirs);
ri.Free(tdirs);
}
#endif
@ -676,11 +687,11 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
offset_st = 0;
offset_xyz = surf->numVerts * glRefConfig.packedTexcoordDataSize;
offset_normal = offset_xyz + sizeof(vec3_t);
offset_tangent = offset_normal + sizeof(uint32_t);
offset_tangent = offset_normal + sizeof(int16_t) * 4;
stride_st = glRefConfig.packedTexcoordDataSize;
stride_xyz = sizeof(vec3_t) + sizeof(uint32_t);
stride_xyz = sizeof(vec3_t) + sizeof(int16_t) * 4;
#ifdef USE_VERT_TANGENT_SPACE
stride_xyz += sizeof(uint32_t);
stride_xyz += sizeof(int16_t) * 4;
#endif
stride_normal = stride_tangent = stride_xyz;
@ -692,11 +703,11 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
offset_xyz = 0;
offset_st = offset_xyz + sizeof(vec3_t);
offset_normal = offset_st + glRefConfig.packedTexcoordDataSize;
offset_tangent = offset_normal + sizeof(uint32_t);
offset_tangent = offset_normal + sizeof(int16_t) * 4;
#ifdef USE_VERT_TANGENT_SPACE
stride_xyz = offset_tangent + sizeof(uint32_t);
stride_xyz = offset_tangent + sizeof(int16_t) * 4;
#else
stride_xyz = offset_normal + sizeof(uint32_t);
stride_xyz = offset_normal + sizeof(int16_t) * 4;
#endif
stride_st = stride_normal = stride_tangent = stride_xyz;
@ -717,24 +728,18 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
v = surf->verts;
for ( j = 0; j < surf->numVerts * mdvModel->numFrames ; j++, v++ )
{
#ifdef USE_VERT_TANGENT_SPACE
vec3_t nxt;
vec4_t tangent;
#endif
// xyz
memcpy(data + dataOfs, &v->xyz, sizeof(vec3_t));
dataOfs += sizeof(vec3_t);
// normal
dataOfs += R_VaoPackNormal(data + dataOfs, v->normal);
memcpy(data + dataOfs, &v->normal, sizeof(int16_t) * 4);
dataOfs += sizeof(int16_t) * 4;
#ifdef USE_VERT_TANGENT_SPACE
CrossProduct(v->normal, v->tangent, nxt);
VectorCopy(v->tangent, tangent);
tangent[3] = (DotProduct(nxt, v->bitangent) < 0.0f) ? -1.0f : 1.0f;
// tangent
dataOfs += R_VaoPackTangent(data + dataOfs, tangent);
memcpy(data + dataOfs, &v->tangent, sizeof(int16_t) * 4);
dataOfs += sizeof(int16_t) * 4;
#endif
}
}
@ -744,10 +749,6 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
st = surf->st;
for ( j = 0; j < surf->numVerts; j++, v++, st++ )
{
#ifdef USE_VERT_TANGENT_SPACE
vec3_t nxt;
vec4_t tangent;
#endif
// xyz
memcpy(data + dataOfs, &v->xyz, sizeof(vec3_t));
dataOfs += sizeof(v->xyz);
@ -756,15 +757,13 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
dataOfs += R_VaoPackTexCoord(data + dataOfs, st->st);
// normal
dataOfs += R_VaoPackNormal(data + dataOfs, v->normal);
memcpy(data + dataOfs, &v->normal, sizeof(int16_t) * 4);
dataOfs += sizeof(int16_t) * 4;
#ifdef USE_VERT_TANGENT_SPACE
CrossProduct(v->normal, v->tangent, nxt);
VectorCopy(v->tangent, tangent);
tangent[3] = (DotProduct(nxt, v->bitangent) < 0.0f) ? -1.0f : 1.0f;
// tangent
dataOfs += R_VaoPackTangent(data + dataOfs, tangent);
memcpy(data + dataOfs, &v->tangent, sizeof(int16_t) * 4);
dataOfs += sizeof(int16_t) * 4;
#endif
}
}
@ -794,8 +793,8 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
vaoSurf->vao->attribs[ATTR_INDEX_POSITION].type = GL_FLOAT;
vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].type = glRefConfig.packedTexcoordDataType;
vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].type = glRefConfig.packedNormalDataType;
vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].type = glRefConfig.packedNormalDataType;
vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].type = GL_SHORT;
vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].type = GL_SHORT;
vaoSurf->vao->attribs[ATTR_INDEX_POSITION].normalized = GL_FALSE;
vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].normalized = GL_FALSE;

View file

@ -1024,9 +1024,9 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
int i;
vec4_t *outXYZ;
uint32_t *outNormal;
int16_t *outNormal;
#ifdef USE_VERT_TANGENT_SPACE
uint32_t *outTangent;
int16_t *outTangent;
#endif
vec2_t (*outTexCoord)[2];
vec4_t *outColor;
@ -1042,9 +1042,9 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
RB_CHECKOVERFLOW( surf->num_vertexes, surf->num_triangles * 3 );
outXYZ = &tess.xyz[tess.numVertexes];
outNormal = &tess.normal[tess.numVertexes];
outNormal = tess.normal[tess.numVertexes];
#ifdef USE_VERT_TANGENT_SPACE
outTangent = &tess.tangent[tess.numVertexes];
outTangent = tess.tangent[tess.numVertexes];
#endif
outTexCoord = &tess.texCoords[tess.numVertexes];
outColor = &tess.vertexColors[tess.numVertexes];
@ -1056,7 +1056,7 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
// transform vertexes and fill other data
for( i = 0; i < surf->num_vertexes;
i++, outXYZ++, outNormal++, outTexCoord++, outColor++ ) {
i++, outXYZ++, outNormal+=4, outTexCoord++, outColor++ ) {
int j, k;
float vtxMat[12];
float nrmMat[9];
@ -1130,7 +1130,7 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
normal[1] = DotProduct(&nrmMat[3], &data->normals[3*vtx]);
normal[2] = DotProduct(&nrmMat[6], &data->normals[3*vtx]);
R_VaoPackNormal((byte *)outNormal, normal);
R_VaoPackNormal(outNormal, normal);
#ifdef USE_VERT_TANGENT_SPACE
tangent[0] = DotProduct(&nrmMat[0], &data->tangents[4*vtx]);
@ -1138,7 +1138,8 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
tangent[2] = DotProduct(&nrmMat[6], &data->tangents[4*vtx]);
tangent[3] = data->tangents[4*vtx+3];
R_VaoPackTangent((byte *)outTangent++, tangent);
R_VaoPackTangent(outTangent, tangent);
outTangent+=4;
#endif
}

View file

@ -116,16 +116,16 @@ void RB_CalcDeformVertexes( deformStage_t *ds )
vec3_t offset;
float scale;
float *xyz = ( float * ) tess.xyz;
uint32_t *normal = tess.normal;
int16_t *normal = tess.normal[0];
float *table;
if ( ds->deformationWave.frequency == 0 )
{
scale = EvalWaveForm( &ds->deformationWave );
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal++ )
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 )
{
R_VaoUnpackNormal(offset, *normal);
R_VaoUnpackNormal(offset, normal);
xyz[0] += offset[0] * scale;
xyz[1] += offset[1] * scale;
@ -136,7 +136,7 @@ void RB_CalcDeformVertexes( deformStage_t *ds )
{
table = TableForFunc( ds->deformationWave.func );
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal++ )
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 )
{
float off = ( xyz[0] + xyz[1] + xyz[2] ) * ds->deformationSpread;
@ -145,7 +145,7 @@ void RB_CalcDeformVertexes( deformStage_t *ds )
ds->deformationWave.phase + off,
ds->deformationWave.frequency );
R_VaoUnpackNormal(offset, *normal);
R_VaoUnpackNormal(offset, normal);
xyz[0] += offset[0] * scale;
xyz[1] += offset[1] * scale;
@ -165,12 +165,12 @@ void RB_CalcDeformNormals( deformStage_t *ds ) {
int i;
float scale;
float *xyz = ( float * ) tess.xyz;
uint32_t *normal = tess.normal;
int16_t *normal = tess.normal[0];
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal++ ) {
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 ) {
vec3_t fNormal;
R_VaoUnpackNormal(fNormal, *normal);
R_VaoUnpackNormal(fNormal, normal);
scale = 0.98f;
scale = R_NoiseGet4f( xyz[0] * scale, xyz[1] * scale, xyz[2] * scale,
@ -189,7 +189,7 @@ void RB_CalcDeformNormals( deformStage_t *ds ) {
VectorNormalizeFast( fNormal );
R_VaoPackNormal((byte *)normal, fNormal);
R_VaoPackNormal(normal, fNormal);
}
}
@ -203,17 +203,17 @@ void RB_CalcBulgeVertexes( deformStage_t *ds ) {
int i;
const float *st = ( const float * ) tess.texCoords[0];
float *xyz = ( float * ) tess.xyz;
uint32_t *normal = tess.normal;
int16_t *normal = tess.normal[0];
float now;
now = backEnd.refdef.time * ds->bulgeSpeed * 0.001f;
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, st += 4, normal++ ) {
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, st += 4, normal += 4 ) {
int off;
float scale;
vec3_t fNormal;
R_VaoUnpackNormal(fNormal, *normal);
R_VaoUnpackNormal(fNormal, normal);
off = (float)( FUNCTABLE_SIZE / (M_PI*2) ) * ( st[0] * ds->bulgeWidth + now );

View file

@ -88,7 +88,7 @@ RB_AddQuadStampExt
*/
void RB_AddQuadStampExt( vec3_t origin, vec3_t left, vec3_t up, float color[4], float s1, float t1, float s2, float t2 ) {
vec3_t normal;
uint32_t pNormal;
int16_t iNormal[4];
int ndx;
RB_CheckVao(tess.vao);
@ -126,11 +126,12 @@ void RB_AddQuadStampExt( vec3_t origin, vec3_t left, vec3_t up, float color[4],
// constant normal all the way around
VectorSubtract( vec3_origin, backEnd.viewParms.or.axis[0], normal );
R_VaoPackNormal((byte *)&pNormal, normal);
tess.normal[ndx] =
tess.normal[ndx+1] =
tess.normal[ndx+2] =
tess.normal[ndx+3] = pNormal;
R_VaoPackNormal(iNormal, normal);
VectorCopy4(tess.normal[ndx], iNormal);
VectorCopy4(tess.normal[ndx+1], iNormal);
VectorCopy4(tess.normal[ndx+2], iNormal);
VectorCopy4(tess.normal[ndx+3], iNormal);
// standard square texture coordinates
VectorSet2(tess.texCoords[ndx ][0], s1, t1);
@ -320,10 +321,10 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIn
glIndex_t *inIndex;
srfVert_t *dv;
float *xyz, *texCoords, *lightCoords;
uint32_t *lightdir;
uint32_t *normal;
int16_t *lightdir;
int16_t *normal;
#ifdef USE_VERT_TANGENT_SPACE
uint32_t *tangent;
int16_t *tangent;
#endif
glIndex_t *outIndex;
float *color;
@ -350,18 +351,18 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIn
if ( tess.shader->vertexAttribs & ATTR_NORMAL )
{
dv = verts;
normal = &tess.normal[ tess.numVertexes ];
for ( i = 0 ; i < numVerts ; i++, dv++, normal++ )
R_VaoPackNormal((byte *)normal, dv->normal);
normal = tess.normal[ tess.numVertexes ];
for ( i = 0 ; i < numVerts ; i++, dv++, normal+=4 )
VectorCopy4(dv->normal, normal);
}
#ifdef USE_VERT_TANGENT_SPACE
if ( tess.shader->vertexAttribs & ATTR_TANGENT )
{
dv = verts;
tangent = &tess.tangent[ tess.numVertexes ];
for ( i = 0 ; i < numVerts ; i++, dv++, tangent++ )
R_VaoPackTangent((byte *)tangent, dv->tangent);
tangent = tess.tangent[ tess.numVertexes ];
for ( i = 0 ; i < numVerts ; i++, dv++, tangent+=4 )
VectorCopy4(dv->tangent, tangent);
}
#endif
@ -392,9 +393,9 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIn
if ( tess.shader->vertexAttribs & ATTR_LIGHTDIRECTION )
{
dv = verts;
lightdir = &tess.lightdir[ tess.numVertexes ];
for ( i = 0 ; i < numVerts ; i++, dv++, lightdir++ )
R_VaoPackNormal((byte *)lightdir, dv->lightdir);
lightdir = tess.lightdir[ tess.numVertexes ];
for ( i = 0 ; i < numVerts ; i++, dv++, lightdir+=4 )
VectorCopy4(dv->lightdir, lightdir);
}
#if 0 // nothing even uses vertex dlightbits
@ -841,308 +842,19 @@ static void RB_SurfaceLightningBolt( void ) {
}
}
#if 0
/*
** VectorArrayNormalize
*
* The inputs to this routing seem to always be close to length = 1.0 (about 0.6 to 2.0)
* This means that we don't have to worry about zero length or enormously long vectors.
*/
static void VectorArrayNormalize(vec4_t *normals, unsigned int count)
static void LerpMeshVertexes(mdvSurface_t *surf, float backlerp)
{
// assert(count);
#if idppc
{
register float half = 0.5;
register float one = 1.0;
float *components = (float *)normals;
// Vanilla PPC code, but since PPC has a reciprocal square root estimate instruction,
// runs *much* faster than calling sqrt(). We'll use a single Newton-Raphson
// refinement step to get a little more precision. This seems to yeild results
// that are correct to 3 decimal places and usually correct to at least 4 (sometimes 5).
// (That is, for the given input range of about 0.6 to 2.0).
do {
float x, y, z;
float B, y0, y1;
x = components[0];
y = components[1];
z = components[2];
components += 4;
B = x*x + y*y + z*z;
#ifdef __GNUC__
asm("frsqrte %0,%1" : "=f" (y0) : "f" (B));
#else
y0 = __frsqrte(B);
#endif
y1 = y0 + half*y0*(one - B*y0*y0);
x = x * y1;
y = y * y1;
components[-4] = x;
z = z * y1;
components[-3] = y;
components[-2] = z;
} while(count--);
}
#else // No assembly version for this architecture, or C_ONLY defined
// given the input, it's safe to call VectorNormalizeFast
while (count--) {
VectorNormalizeFast(normals[0]);
normals++;
}
#endif
}
#endif
/*
** LerpMeshVertexes
*/
#if 0
#if idppc_altivec
static void LerpMeshVertexes_altivec(md3Surface_t *surf, float backlerp)
{
short *oldXyz, *newXyz, *oldNormals, *newNormals;
float *outXyz, *outNormal;
float oldXyzScale QALIGN(16);
float newXyzScale QALIGN(16);
float oldNormalScale QALIGN(16);
float newNormalScale QALIGN(16);
int vertNum;
unsigned lat, lng;
int numVerts;
outXyz = tess.xyz[tess.numVertexes];
outNormal = tess.normal[tess.numVertexes];
newXyz = (short *)((byte *)surf + surf->ofsXyzNormals)
+ (backEnd.currentEntity->e.frame * surf->numVerts * 4);
newNormals = newXyz + 3;
newXyzScale = MD3_XYZ_SCALE * (1.0 - backlerp);
newNormalScale = 1.0 - backlerp;
numVerts = surf->numVerts;
if ( backlerp == 0 ) {
vector signed short newNormalsVec0;
vector signed short newNormalsVec1;
vector signed int newNormalsIntVec;
vector float newNormalsFloatVec;
vector float newXyzScaleVec;
vector unsigned char newNormalsLoadPermute;
vector unsigned char newNormalsStorePermute;
vector float zero;
newNormalsStorePermute = vec_lvsl(0,(float *)&newXyzScaleVec);
newXyzScaleVec = *(vector float *)&newXyzScale;
newXyzScaleVec = vec_perm(newXyzScaleVec,newXyzScaleVec,newNormalsStorePermute);
newXyzScaleVec = vec_splat(newXyzScaleVec,0);
newNormalsLoadPermute = vec_lvsl(0,newXyz);
newNormalsStorePermute = vec_lvsr(0,outXyz);
zero = (vector float)vec_splat_s8(0);
//
// just copy the vertexes
//
for (vertNum=0 ; vertNum < numVerts ; vertNum++,
newXyz += 4, newNormals += 4,
outXyz += 4, outNormal += 4)
{
newNormalsLoadPermute = vec_lvsl(0,newXyz);
newNormalsStorePermute = vec_lvsr(0,outXyz);
newNormalsVec0 = vec_ld(0,newXyz);
newNormalsVec1 = vec_ld(16,newXyz);
newNormalsVec0 = vec_perm(newNormalsVec0,newNormalsVec1,newNormalsLoadPermute);
newNormalsIntVec = vec_unpackh(newNormalsVec0);
newNormalsFloatVec = vec_ctf(newNormalsIntVec,0);
newNormalsFloatVec = vec_madd(newNormalsFloatVec,newXyzScaleVec,zero);
newNormalsFloatVec = vec_perm(newNormalsFloatVec,newNormalsFloatVec,newNormalsStorePermute);
//outXyz[0] = newXyz[0] * newXyzScale;
//outXyz[1] = newXyz[1] * newXyzScale;
//outXyz[2] = newXyz[2] * newXyzScale;
lat = ( newNormals[0] >> 8 ) & 0xff;
lng = ( newNormals[0] & 0xff );
lat *= (FUNCTABLE_SIZE/256);
lng *= (FUNCTABLE_SIZE/256);
// decode X as cos( lat ) * sin( long )
// decode Y as sin( lat ) * sin( long )
// decode Z as cos( long )
outNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
outNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
outNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
vec_ste(newNormalsFloatVec,0,outXyz);
vec_ste(newNormalsFloatVec,4,outXyz);
vec_ste(newNormalsFloatVec,8,outXyz);
}
} else {
//
// interpolate and copy the vertex and normal
//
oldXyz = (short *)((byte *)surf + surf->ofsXyzNormals)
+ (backEnd.currentEntity->e.oldframe * surf->numVerts * 4);
oldNormals = oldXyz + 3;
oldXyzScale = MD3_XYZ_SCALE * backlerp;
oldNormalScale = backlerp;
for (vertNum=0 ; vertNum < numVerts ; vertNum++,
oldXyz += 4, newXyz += 4, oldNormals += 4, newNormals += 4,
outXyz += 4, outNormal += 4)
{
vec3_t uncompressedOldNormal, uncompressedNewNormal;
// interpolate the xyz
outXyz[0] = oldXyz[0] * oldXyzScale + newXyz[0] * newXyzScale;
outXyz[1] = oldXyz[1] * oldXyzScale + newXyz[1] * newXyzScale;
outXyz[2] = oldXyz[2] * oldXyzScale + newXyz[2] * newXyzScale;
// FIXME: interpolate lat/long instead?
lat = ( newNormals[0] >> 8 ) & 0xff;
lng = ( newNormals[0] & 0xff );
lat *= 4;
lng *= 4;
uncompressedNewNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
uncompressedNewNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
uncompressedNewNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
lat = ( oldNormals[0] >> 8 ) & 0xff;
lng = ( oldNormals[0] & 0xff );
lat *= 4;
lng *= 4;
uncompressedOldNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
uncompressedOldNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
uncompressedOldNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
outNormal[0] = uncompressedOldNormal[0] * oldNormalScale + uncompressedNewNormal[0] * newNormalScale;
outNormal[1] = uncompressedOldNormal[1] * oldNormalScale + uncompressedNewNormal[1] * newNormalScale;
outNormal[2] = uncompressedOldNormal[2] * oldNormalScale + uncompressedNewNormal[2] * newNormalScale;
// VectorNormalize (outNormal);
}
VectorArrayNormalize((vec4_t *)tess.normal[tess.numVertexes], numVerts);
}
}
#endif
#endif
static void LerpMeshVertexes_scalar(mdvSurface_t *surf, float backlerp)
{
#if 0
short *oldXyz, *newXyz, *oldNormals, *newNormals;
float *outXyz, *outNormal;
float oldXyzScale, newXyzScale;
float oldNormalScale, newNormalScale;
int vertNum;
unsigned lat, lng;
int numVerts;
outXyz = tess.xyz[tess.numVertexes];
outNormal = tess.normal[tess.numVertexes];
newXyz = (short *)((byte *)surf + surf->ofsXyzNormals)
+ (backEnd.currentEntity->e.frame * surf->numVerts * 4);
newNormals = newXyz + 3;
newXyzScale = MD3_XYZ_SCALE * (1.0 - backlerp);
newNormalScale = 1.0 - backlerp;
numVerts = surf->numVerts;
if ( backlerp == 0 ) {
//
// just copy the vertexes
//
for (vertNum=0 ; vertNum < numVerts ; vertNum++,
newXyz += 4, newNormals += 4,
outXyz += 4, outNormal += 4)
{
outXyz[0] = newXyz[0] * newXyzScale;
outXyz[1] = newXyz[1] * newXyzScale;
outXyz[2] = newXyz[2] * newXyzScale;
lat = ( newNormals[0] >> 8 ) & 0xff;
lng = ( newNormals[0] & 0xff );
lat *= (FUNCTABLE_SIZE/256);
lng *= (FUNCTABLE_SIZE/256);
// decode X as cos( lat ) * sin( long )
// decode Y as sin( lat ) * sin( long )
// decode Z as cos( long )
outNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
outNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
outNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
}
} else {
//
// interpolate and copy the vertex and normal
//
oldXyz = (short *)((byte *)surf + surf->ofsXyzNormals)
+ (backEnd.currentEntity->e.oldframe * surf->numVerts * 4);
oldNormals = oldXyz + 3;
oldXyzScale = MD3_XYZ_SCALE * backlerp;
oldNormalScale = backlerp;
for (vertNum=0 ; vertNum < numVerts ; vertNum++,
oldXyz += 4, newXyz += 4, oldNormals += 4, newNormals += 4,
outXyz += 4, outNormal += 4)
{
vec3_t uncompressedOldNormal, uncompressedNewNormal;
// interpolate the xyz
outXyz[0] = oldXyz[0] * oldXyzScale + newXyz[0] * newXyzScale;
outXyz[1] = oldXyz[1] * oldXyzScale + newXyz[1] * newXyzScale;
outXyz[2] = oldXyz[2] * oldXyzScale + newXyz[2] * newXyzScale;
// FIXME: interpolate lat/long instead?
lat = ( newNormals[0] >> 8 ) & 0xff;
lng = ( newNormals[0] & 0xff );
lat *= 4;
lng *= 4;
uncompressedNewNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
uncompressedNewNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
uncompressedNewNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
lat = ( oldNormals[0] >> 8 ) & 0xff;
lng = ( oldNormals[0] & 0xff );
lat *= 4;
lng *= 4;
uncompressedOldNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
uncompressedOldNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
uncompressedOldNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
outNormal[0] = uncompressedOldNormal[0] * oldNormalScale + uncompressedNewNormal[0] * newNormalScale;
outNormal[1] = uncompressedOldNormal[1] * oldNormalScale + uncompressedNewNormal[1] * newNormalScale;
outNormal[2] = uncompressedOldNormal[2] * oldNormalScale + uncompressedNewNormal[2] * newNormalScale;
// VectorNormalize (outNormal);
}
VectorArrayNormalize((vec4_t *)tess.normal[tess.numVertexes], numVerts);
}
#endif
float *outXyz;
uint32_t *outNormal;
int16_t *outNormal, *outTangent;
mdvVertex_t *newVerts;
int vertNum;
newVerts = surf->verts + backEnd.currentEntity->e.frame * surf->numVerts;
outXyz = tess.xyz[tess.numVertexes];
outNormal = &tess.normal[tess.numVertexes];
outXyz = tess.xyz[tess.numVertexes];
outNormal = tess.normal[tess.numVertexes];
outTangent = tess.tangent[tess.numVertexes];
if (backlerp == 0)
{
@ -1152,16 +864,14 @@ static void LerpMeshVertexes_scalar(mdvSurface_t *surf, float backlerp)
for (vertNum=0 ; vertNum < surf->numVerts ; vertNum++)
{
vec3_t normal;
VectorCopy(newVerts->xyz, outXyz);
VectorCopy(newVerts->normal, normal);
R_VaoPackNormal((byte *)outNormal, normal);
VectorCopy4(newVerts->normal, outNormal);
VectorCopy4(newVerts->tangent, outTangent);
newVerts++;
outXyz += 4;
outNormal++;
outNormal += 4;
outTangent += 4;
}
}
else
@ -1176,37 +886,28 @@ static void LerpMeshVertexes_scalar(mdvSurface_t *surf, float backlerp)
for (vertNum=0 ; vertNum < surf->numVerts ; vertNum++)
{
vec3_t normal;
VectorLerp(newVerts->xyz, oldVerts->xyz, backlerp, outXyz);
VectorLerp(newVerts->normal, oldVerts->normal, backlerp, normal);
VectorNormalize(normal);
R_VaoPackNormal((byte *)outNormal, normal);
outNormal[0] = (int16_t)(newVerts->normal[0] * (1.0f - backlerp) + oldVerts->normal[0] * backlerp);
outNormal[1] = (int16_t)(newVerts->normal[1] * (1.0f - backlerp) + oldVerts->normal[1] * backlerp);
outNormal[2] = (int16_t)(newVerts->normal[2] * (1.0f - backlerp) + oldVerts->normal[2] * backlerp);
outNormal[3] = 0;
outTangent[0] = (int16_t)(newVerts->tangent[0] * (1.0f - backlerp) + oldVerts->tangent[0] * backlerp);
outTangent[1] = (int16_t)(newVerts->tangent[1] * (1.0f - backlerp) + oldVerts->tangent[1] * backlerp);
outTangent[2] = (int16_t)(newVerts->tangent[2] * (1.0f - backlerp) + oldVerts->tangent[2] * backlerp);
outTangent[3] = newVerts->tangent[3];
newVerts++;
oldVerts++;
outXyz += 4;
outNormal++;
outNormal += 4;
outTangent += 4;
}
}
}
static void LerpMeshVertexes(mdvSurface_t *surf, float backlerp)
{
#if 0
#if idppc_altivec
if (com_altivec->integer) {
// must be in a seperate function or G3 systems will crash.
LerpMeshVertexes_altivec( surf, backlerp );
return;
}
#endif // idppc_altivec
#endif
LerpMeshVertexes_scalar( surf, backlerp );
}
/*
=============
@ -1311,12 +1012,12 @@ static void RB_SurfaceGrid( srfBspSurface_t *srf ) {
int i, j;
float *xyz;
float *texCoords, *lightCoords;
uint32_t *normal;
int16_t *normal;
#ifdef USE_VERT_TANGENT_SPACE
uint32_t *tangent;
int16_t *tangent;
#endif
float *color;
uint32_t *lightdir;
int16_t *lightdir;
srfVert_t *dv;
int rows, irows, vrows;
int used;
@ -1401,14 +1102,14 @@ static void RB_SurfaceGrid( srfBspSurface_t *srf ) {
numVertexes = tess.numVertexes;
xyz = tess.xyz[numVertexes];
normal = &tess.normal[numVertexes];
normal = tess.normal[numVertexes];
#ifdef USE_VERT_TANGENT_SPACE
tangent = &tess.tangent[numVertexes];
tangent = tess.tangent[numVertexes];
#endif
texCoords = tess.texCoords[numVertexes][0];
lightCoords = tess.texCoords[numVertexes][1];
color = tess.vertexColors[numVertexes];
lightdir = &tess.lightdir[numVertexes];
lightdir = tess.lightdir[numVertexes];
//vDlightBits = &tess.vertexDlightBits[numVertexes];
for ( i = 0 ; i < rows ; i++ ) {
@ -1424,13 +1125,15 @@ static void RB_SurfaceGrid( srfBspSurface_t *srf ) {
if ( tess.shader->vertexAttribs & ATTR_NORMAL )
{
R_VaoPackNormal((byte *)normal++, dv->normal);
VectorCopy4(normal, dv->normal);
normal += 4;
}
#ifdef USE_VERT_TANGENT_SPACE
if ( tess.shader->vertexAttribs & ATTR_TANGENT )
{
R_VaoPackTangent((byte *)tangent++, dv->tangent);
VectorCopy4(tangent, dv->tangent);
tangent += 4;
}
#endif
if ( tess.shader->vertexAttribs & ATTR_TEXCOORD )
@ -1453,7 +1156,8 @@ static void RB_SurfaceGrid( srfBspSurface_t *srf ) {
if ( tess.shader->vertexAttribs & ATTR_LIGHTDIRECTION )
{
R_VaoPackNormal((byte *)lightdir++, dv->lightdir);
VectorCopy4(lightdir, dv->lightdir);
lightdir += 4;
}
//*vDlightBits++ = dlightBits;

View file

@ -23,73 +23,20 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "tr_local.h"
union pack10_u {
struct {
signed int x:10;
signed int y:10;
signed int z:10;
signed int w:2;
} pack;
uint32_t i;
};
union pack8_u {
struct {
signed int x:8;
signed int y:8;
signed int z:8;
signed int w:8;
} pack;
uint32_t i;
};
int R_VaoPackTangent(byte *out, vec4_t v)
void R_VaoPackTangent(int16_t *out, vec4_t v)
{
if (glRefConfig.packedNormalDataType == GL_INT_2_10_10_10_REV)
{
union pack10_u *num = (union pack10_u *)out;
num->pack.x = v[0] * 511.0f;
num->pack.y = v[1] * 511.0f;
num->pack.z = v[2] * 511.0f;
num->pack.w = v[3];
}
else
{
union pack8_u *num = (union pack8_u *)out;
num->pack.x = v[0] * 127.0f;
num->pack.y = v[1] * 127.0f;
num->pack.z = v[2] * 127.0f;
num->pack.w = v[3] * 127.0f;
}
return 4;
out[0] = v[0] * 32767.0f + (v[0] > 0.0f ? 0.5f : -0.5f);
out[1] = v[1] * 32767.0f + (v[1] > 0.0f ? 0.5f : -0.5f);
out[2] = v[2] * 32767.0f + (v[2] > 0.0f ? 0.5f : -0.5f);
out[3] = v[3] * 32767.0f + (v[3] > 0.0f ? 0.5f : -0.5f);
}
int R_VaoPackNormal(byte *out, vec3_t v)
void R_VaoPackNormal(int16_t *out, vec3_t v)
{
if (glRefConfig.packedNormalDataType == GL_INT_2_10_10_10_REV)
{
union pack10_u *num = (union pack10_u *)out;
num->pack.x = v[0] * 511.0f;
num->pack.y = v[1] * 511.0f;
num->pack.z = v[2] * 511.0f;
num->pack.w = 0;
}
else
{
union pack8_u *num = (union pack8_u *)out;
num->pack.x = v[0] * 127.0f;
num->pack.y = v[1] * 127.0f;
num->pack.z = v[2] * 127.0f;
num->pack.w = 0;
}
return 4;
out[0] = v[0] * 32767.0f + (v[0] > 0.0f ? 0.5f : -0.5f);
out[1] = v[1] * 32767.0f + (v[1] > 0.0f ? 0.5f : -0.5f);
out[2] = v[2] * 32767.0f + (v[2] > 0.0f ? 0.5f : -0.5f);
out[3] = 0;
}
int R_VaoPackTexCoord(byte *out, vec2_t st)
@ -140,50 +87,21 @@ int R_VaoPackColors(byte *out, vec4_t color)
}
}
void R_VaoUnpackTangent(vec4_t v, uint32_t b)
void R_VaoUnpackTangent(vec4_t v, int16_t *pack)
{
if (glRefConfig.packedNormalDataType == GL_INT_2_10_10_10_REV)
{
union pack10_u *num = (union pack10_u *)&b;
v[0] = num->pack.x / 511.0f;
v[1] = num->pack.y / 511.0f;
v[2] = num->pack.z / 511.0f;
v[3] = num->pack.w;
}
else
{
union pack8_u *num = (union pack8_u *)&b;
v[0] = num->pack.x / 127.0f;
v[1] = num->pack.y / 127.0f;
v[2] = num->pack.z / 127.0f;
v[3] = num->pack.w / 127.0f;
}
v[0] = pack[0] / 32767.0f;
v[1] = pack[1] / 32767.0f;
v[2] = pack[2] / 32767.0f;
v[3] = pack[3] / 32767.0f;
}
void R_VaoUnpackNormal(vec3_t v, uint32_t b)
void R_VaoUnpackNormal(vec3_t v, int16_t *pack)
{
if (glRefConfig.packedNormalDataType == GL_INT_2_10_10_10_REV)
{
union pack10_u *num = (union pack10_u *)&b;
v[0] = num->pack.x / 511.0f;
v[1] = num->pack.y / 511.0f;
v[2] = num->pack.z / 511.0f;
}
else
{
union pack8_u *num = (union pack8_u *)&b;
v[0] = num->pack.x / 127.0f;
v[1] = num->pack.y / 127.0f;
v[2] = num->pack.z / 127.0f;
}
v[0] = pack[0] / 32767.0f;
v[1] = pack[1] / 32767.0f;
v[2] = pack[2] / 32767.0f;
}
void Vao_SetVertexPointers(vao_t *vao)
{
int attribIndex;
@ -347,12 +265,12 @@ vao_t *R_CreateVao2(const char *name, int numVertexes, srfVert_t *verts, int num
vao->attribs[ATTR_INDEX_LIGHTDIRECTION].count = 4;
vao->attribs[ATTR_INDEX_POSITION ].type = GL_FLOAT;
vao->attribs[ATTR_INDEX_NORMAL ].type = glRefConfig.packedNormalDataType;
vao->attribs[ATTR_INDEX_TANGENT ].type = glRefConfig.packedNormalDataType;
vao->attribs[ATTR_INDEX_NORMAL ].type = GL_SHORT;
vao->attribs[ATTR_INDEX_TANGENT ].type = GL_SHORT;
vao->attribs[ATTR_INDEX_TEXCOORD ].type = glRefConfig.packedTexcoordDataType;
vao->attribs[ATTR_INDEX_LIGHTCOORD ].type = glRefConfig.packedTexcoordDataType;
vao->attribs[ATTR_INDEX_COLOR ].type = glRefConfig.packedColorDataType;
vao->attribs[ATTR_INDEX_LIGHTDIRECTION].type = glRefConfig.packedNormalDataType;
vao->attribs[ATTR_INDEX_LIGHTDIRECTION].type = GL_SHORT;
vao->attribs[ATTR_INDEX_POSITION ].normalized = GL_FALSE;
vao->attribs[ATTR_INDEX_NORMAL ].normalized = GL_TRUE;
@ -363,14 +281,14 @@ vao_t *R_CreateVao2(const char *name, int numVertexes, srfVert_t *verts, int num
vao->attribs[ATTR_INDEX_LIGHTDIRECTION].normalized = GL_TRUE;
vao->attribs[ATTR_INDEX_POSITION ].offset = 0; dataSize = sizeof(verts[0].xyz);
vao->attribs[ATTR_INDEX_NORMAL ].offset = dataSize; dataSize += sizeof(uint32_t);
vao->attribs[ATTR_INDEX_NORMAL ].offset = dataSize; dataSize += sizeof(verts[0].normal);
#ifdef USE_VERT_TANGENT_SPACE
vao->attribs[ATTR_INDEX_TANGENT ].offset = dataSize; dataSize += sizeof(uint32_t);
vao->attribs[ATTR_INDEX_TANGENT ].offset = dataSize; dataSize += sizeof(verts[0].tangent);
#endif
vao->attribs[ATTR_INDEX_TEXCOORD ].offset = dataSize; dataSize += glRefConfig.packedTexcoordDataSize;
vao->attribs[ATTR_INDEX_LIGHTCOORD ].offset = dataSize; dataSize += glRefConfig.packedTexcoordDataSize;
vao->attribs[ATTR_INDEX_COLOR ].offset = dataSize; dataSize += glRefConfig.packedColorDataSize;
vao->attribs[ATTR_INDEX_LIGHTDIRECTION].offset = dataSize; dataSize += sizeof(uint32_t);
vao->attribs[ATTR_INDEX_LIGHTDIRECTION].offset = dataSize; dataSize += sizeof(verts[0].lightdir);
vao->attribs[ATTR_INDEX_POSITION ].stride = dataSize;
vao->attribs[ATTR_INDEX_NORMAL ].stride = dataSize;
@ -400,11 +318,13 @@ vao_t *R_CreateVao2(const char *name, int numVertexes, srfVert_t *verts, int num
dataOfs += sizeof(verts[i].xyz);
// normal
dataOfs += R_VaoPackNormal(data + dataOfs, verts[i].normal);
memcpy(data + dataOfs, &verts[i].normal, sizeof(verts[i].normal));
dataOfs += sizeof(verts[i].normal);
#ifdef USE_VERT_TANGENT_SPACE
// tangent
dataOfs += R_VaoPackTangent(data + dataOfs, verts[i].tangent);
memcpy(data + dataOfs, &verts[i].tangent, sizeof(verts[i].tangent));
dataOfs += sizeof(verts[i].tangent);
#endif
// texcoords
@ -417,7 +337,8 @@ vao_t *R_CreateVao2(const char *name, int numVertexes, srfVert_t *verts, int num
dataOfs += R_VaoPackColors(data + dataOfs, verts[i].vertexColors);
// light directions
dataOfs += R_VaoPackNormal(data + dataOfs, verts[i].lightdir);
memcpy(data + dataOfs, &verts[i].lightdir, sizeof(verts[i].lightdir));
dataOfs += sizeof(verts[i].lightdir);
}
vao->vertexesSize = dataSize;
@ -581,12 +502,12 @@ void R_InitVaos(void)
tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].count = 4;
tess.vao->attribs[ATTR_INDEX_POSITION ].type = GL_FLOAT;
tess.vao->attribs[ATTR_INDEX_NORMAL ].type = glRefConfig.packedNormalDataType;
tess.vao->attribs[ATTR_INDEX_TANGENT ].type = glRefConfig.packedNormalDataType;
tess.vao->attribs[ATTR_INDEX_NORMAL ].type = GL_SHORT;
tess.vao->attribs[ATTR_INDEX_TANGENT ].type = GL_SHORT;
tess.vao->attribs[ATTR_INDEX_TEXCOORD ].type = GL_FLOAT;
tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].type = GL_FLOAT;
tess.vao->attribs[ATTR_INDEX_COLOR ].type = GL_FLOAT;
tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].type = glRefConfig.packedNormalDataType;
tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].type = GL_SHORT;
tess.vao->attribs[ATTR_INDEX_POSITION ].normalized = GL_FALSE;
tess.vao->attribs[ATTR_INDEX_NORMAL ].normalized = GL_TRUE;