[iortcw] 243/497: All: Rend2: Support half floats for texcoords and vertex colors

Simon McVittie smcv at debian.org
Fri Sep 8 10:37:00 UTC 2017


This is an automated email from the git hooks/post-receive script.

smcv pushed a commit to annotated tag 1.42d
in repository iortcw.

commit 62de750f94ea2593040299e2fb9fac9398339bbb
Author: M4N4T4RMS at gmail.com <M4N4T4RMS at gmail.com@e65d2741-a53d-b2dc-ae96-bb75fa5e4c4a>
Date:   Wed Nov 5 23:19:33 2014 +0000

    All: Rend2: Support half floats for texcoords and vertex colors
---
 MP/code/rend2/tr_animation.c  |   4 +-
 MP/code/rend2/tr_extensions.c |  27 +++++-
 MP/code/rend2/tr_extramath.c  |  61 ++++++--------
 MP/code/rend2/tr_init.c       |   2 +
 MP/code/rend2/tr_local.h      |  11 ++-
 MP/code/rend2/tr_model.c      |  68 +++++----------
 MP/code/rend2/tr_model_iqm.c  |   4 +-
 MP/code/rend2/tr_shade_calc.c |   2 +-
 MP/code/rend2/tr_surface.c    |  24 +++---
 MP/code/rend2/tr_vbo.c        | 186 ++++++++++++++++++++++++------------------
 SP/code/rend2/tr_animation.c  |   4 +-
 SP/code/rend2/tr_extensions.c |  27 +++++-
 SP/code/rend2/tr_extramath.c  |  61 ++++++--------
 SP/code/rend2/tr_init.c       |   2 +
 SP/code/rend2/tr_local.h      |  11 ++-
 SP/code/rend2/tr_model.c      |  68 +++++----------
 SP/code/rend2/tr_model_iqm.c  |   4 +-
 SP/code/rend2/tr_shade_calc.c |   2 +-
 SP/code/rend2/tr_surface.c    |  24 +++---
 SP/code/rend2/tr_vbo.c        | 186 ++++++++++++++++++++++++------------------
 20 files changed, 414 insertions(+), 364 deletions(-)

diff --git a/MP/code/rend2/tr_animation.c b/MP/code/rend2/tr_animation.c
index f912366..4a26f4e 100644
--- a/MP/code/rend2/tr_animation.c
+++ b/MP/code/rend2/tr_animation.c
@@ -1187,7 +1187,7 @@ void RB_SurfaceAnim( mdsSurface_t *surface ) {
 
 		LocalMatrixTransformVector( v->normal, bones[v->weights[0].boneIndex].matrix, newNormal );
 		
-		*tempNormal = R_VaoPackNormal(newNormal);
+		R_VaoPackNormal((byte *)tempNormal, newNormal);
 
 		tess.texCoords[baseVertex + j][0][0] = v->texCoords[0];
 		tess.texCoords[baseVertex + j][0][1] = v->texCoords[1];
@@ -1756,7 +1756,7 @@ void RB_MDRSurfaceAnim( mdrSurface_t *surface )
 		tess.xyz[baseVertex + j][1] = tempVert[1];
 		tess.xyz[baseVertex + j][2] = tempVert[2];
 
-		tess.normal[baseVertex + j] = R_VaoPackNormal(tempNormal);
+		R_VaoPackNormal((byte *)&tess.normal[baseVertex + j], tempNormal);
 
 		tess.texCoords[baseVertex + j][0][0] = v->texCoords[0];
 		tess.texCoords[baseVertex + j][0][1] = v->texCoords[1];
diff --git a/MP/code/rend2/tr_extensions.c b/MP/code/rend2/tr_extensions.c
index b770e6c..c0f4d04 100644
--- a/MP/code/rend2/tr_extensions.c
+++ b/MP/code/rend2/tr_extensions.c
@@ -33,8 +33,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 void            (APIENTRY * qglDrawRangeElementsEXT) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
 
 // GL_EXT_multi_draw_arrays
-void (APIENTRY * qglMultiDrawArraysEXT) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
-void (APIENTRY * qglMultiDrawElementsEXT) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
+void            (APIENTRY * qglMultiDrawArraysEXT) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+void            (APIENTRY * qglMultiDrawElementsEXT) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
 
 // GL_ARB_vertex_shader
 void            (APIENTRY * qglBindAttribLocationARB) (GLhandleARB programObj, GLuint index, const GLcharARB * name);
@@ -709,4 +709,27 @@ void GLimp_InitExtraExtensions()
 		ri.Printf(PRINT_ALL, result[2], extension);
 	}
 
+	// GL_ARB_half_float_vertex
+	extension = "GL_ARB_half_float_vertex";
+	glRefConfig.packedTexcoordDataType = GL_FLOAT;
+	glRefConfig.packedTexcoordDataSize = sizeof(float) * 2;
+	glRefConfig.packedColorDataType    = GL_FLOAT;
+	glRefConfig.packedColorDataSize    = sizeof(float) * 4;
+	if( GLimp_HaveExtension( extension ) )
+	{
+		if (r_arb_half_float_vertex->integer)
+		{
+			glRefConfig.packedTexcoordDataType = GL_HALF_FLOAT;
+			glRefConfig.packedTexcoordDataSize = sizeof(uint16_t) * 2;
+			glRefConfig.packedColorDataType    = GL_HALF_FLOAT;
+			glRefConfig.packedColorDataSize    = sizeof(uint16_t) * 4;
+		}
+
+		ri.Printf(PRINT_ALL, result[r_arb_half_float_vertex->integer ? 1 : 0], extension);
+	}
+	else
+	{
+		ri.Printf(PRINT_ALL, result[2], extension);
+	}
+
 }
diff --git a/MP/code/rend2/tr_extramath.c b/MP/code/rend2/tr_extramath.c
index b844678..da9a94d 100644
--- a/MP/code/rend2/tr_extramath.c
+++ b/MP/code/rend2/tr_extramath.c
@@ -199,42 +199,35 @@ int NextPowerOfTwo(int in)
 	return out;
 }
 
-unsigned short FloatToHalf(float in)
-{
-	unsigned short out;
-	
-	union
-	{
-		float f;
-		unsigned int i;
-	} f32;
-
-	int sign, inExponent, inFraction;
-	int outExponent, outFraction;
+union f32_u {
+	float f;
+	uint32_t i;
+	struct {
+		unsigned int fraction:23;
+		unsigned int exponent:8;
+		unsigned int sign:1;
+	} pack;
+};
+
+union f16_u {
+	uint16_t i;
+	struct {
+		unsigned int fraction:10;
+		unsigned int exponent:5;
+		unsigned int sign:1;
+	} pack;
+};
+
+uint16_t FloatToHalf(float in)
+{
+	union f32_u f32;
+	union f16_u f16;
 
 	f32.f = in;
 
-	sign       = (f32.i & 0x80000000) >> 31;
-	inExponent = (f32.i & 0x7F800000) >> 23;
-	inFraction =  f32.i & 0x007FFFFF;
-
-	outExponent = CLAMP(inExponent - 127, -15, 16) + 15;
-
-	outFraction = 0;
-	if (outExponent == 0x1F)
-	{
-		if (inExponent == 0xFF && inFraction != 0)
-			outFraction = 0x3FF;
-	}
-	else if (outExponent == 0x00)
-	{
-		if (inExponent == 0x00 && inFraction != 0)
-			outFraction = 0x3FF;
-	}
-	else
-		outFraction = inFraction >> 13;
-
-	out = (sign << 15) | (outExponent << 10) | outFraction;
+	f16.pack.exponent = CLAMP(f32.pack.exponent - 112, 0, 31);
+	f16.pack.fraction = f32.pack.fraction >> 13;
+	f16.pack.sign     = f32.pack.sign;
 
-	return out;
+	return f16.i;
 }
diff --git a/MP/code/rend2/tr_init.c b/MP/code/rend2/tr_init.c
index b85963f..a3bf09e 100644
--- a/MP/code/rend2/tr_init.c
+++ b/MP/code/rend2/tr_init.c
@@ -121,6 +121,7 @@ cvar_t  *r_ext_multi_draw_arrays;
 cvar_t  *r_ext_framebuffer_object;
 cvar_t  *r_ext_texture_float;
 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;
@@ -1255,6 +1256,7 @@ void R_Register( void ) {
 	r_ext_framebuffer_object = ri.Cvar_Get( "r_ext_framebuffer_object", "1", CVAR_ARCHIVE | CVAR_LATCH);
 	r_ext_texture_float = ri.Cvar_Get( "r_ext_texture_float", "1", CVAR_ARCHIVE | CVAR_LATCH);
 	r_arb_half_float_pixel = ri.Cvar_Get( "r_arb_half_float_pixel", "1", CVAR_ARCHIVE | CVAR_LATCH);
+	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);
diff --git a/MP/code/rend2/tr_local.h b/MP/code/rend2/tr_local.h
index bf97a1d..96c70a1 100644
--- a/MP/code/rend2/tr_local.h
+++ b/MP/code/rend2/tr_local.h
@@ -1545,6 +1545,10 @@ typedef struct {
 	qboolean seamlessCubeMap;
 
 	GLenum packedNormalDataType;
+	GLenum packedTexcoordDataType;
+	GLenum packedColorDataType;
+	int packedTexcoordDataSize;
+	int packedColorDataSize;
 
 	qboolean floatLightmap;
 	qboolean vertexArrayObject;
@@ -1890,6 +1894,7 @@ extern  cvar_t  *r_ext_multi_draw_arrays;
 extern  cvar_t  *r_ext_framebuffer_object;
 extern  cvar_t  *r_ext_texture_float;
 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;
@@ -2415,8 +2420,10 @@ VERTEX BUFFER OBJECTS
 ============================================================
 */
 
-uint32_t R_VaoPackTangent(vec4_t v);
-uint32_t R_VaoPackNormal(vec3_t v);
+int R_VaoPackTangent(byte *out, vec4_t v);
+int R_VaoPackNormal(byte *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);
 
diff --git a/MP/code/rend2/tr_model.c b/MP/code/rend2/tr_model.c
index dda845d..876a487 100644
--- a/MP/code/rend2/tr_model.c
+++ b/MP/code/rend2/tr_model.c
@@ -941,10 +941,10 @@ static qboolean R_LoadMDC( model_t *mod, int lod, void *buffer, const char *modN
 			{
 				// vertex animation, store texcoords first, then position/normal/tangents
 				offset_st      = 0;
-				offset_xyz     = surf->numVerts * sizeof(vec2_t);
+				offset_xyz     = surf->numVerts * glRefConfig.packedTexcoordDataSize;
 				offset_normal  = offset_xyz + sizeof(vec3_t);
 				offset_tangent = offset_normal + sizeof(uint32_t);
-				stride_st  = sizeof(vec2_t);
+				stride_st  = glRefConfig.packedTexcoordDataSize;
 				stride_xyz = sizeof(vec3_t) + sizeof(uint32_t);
 #ifdef USE_VERT_TANGENT_SPACE
 				stride_xyz += sizeof(uint32_t);
@@ -958,7 +958,7 @@ static qboolean R_LoadMDC( model_t *mod, int lod, void *buffer, const char *modN
 				// no animation, interleave everything
 				offset_xyz     = 0;
 				offset_st      = offset_xyz + sizeof(vec3_t);
-				offset_normal  = offset_st + sizeof(vec2_t);
+				offset_normal  = offset_st + glRefConfig.packedTexcoordDataSize;
 				offset_tangent = offset_normal + sizeof(uint32_t);
 #ifdef USE_VERT_TANGENT_SPACE
 				stride_xyz = offset_tangent + sizeof(uint32_t);
@@ -978,8 +978,7 @@ static qboolean R_LoadMDC( model_t *mod, int lod, void *buffer, const char *modN
 			{
 				st = surf->st;
 				for ( j = 0 ; j < surf->numVerts ; j++, st++ ) {
-					memcpy(data + dataOfs, &st->st, sizeof(vec2_t));
-					dataOfs += sizeof(vec2_t);
+					dataOfs += R_VaoPackTexCoord(data + dataOfs, st->st);
 				}
 
 				v = surf->verts;
@@ -989,16 +988,12 @@ static qboolean R_LoadMDC( model_t *mod, int lod, void *buffer, const char *modN
 					vec3_t nxt;
 					vec4_t tangent;
 #endif
-					uint32_t *p;
-
 					// xyz
 					memcpy(data + dataOfs, &v->xyz, sizeof(vec3_t));
 					dataOfs += sizeof(vec3_t);
 
 					// normal
-					p = (uint32_t *)(data + dataOfs);
-					*p = R_VaoPackNormal(v->normal);
-					dataOfs += sizeof(uint32_t);
+					dataOfs += R_VaoPackNormal(data + dataOfs, v->normal);
 
 #ifdef USE_VERT_TANGENT_SPACE
 					CrossProduct(v->normal, v->tangent, nxt);
@@ -1006,9 +1001,7 @@ static qboolean R_LoadMDC( model_t *mod, int lod, void *buffer, const char *modN
 					tangent[3] = (DotProduct(nxt, v->bitangent) < 0.0f) ? -1.0f : 1.0f;
 
 					// tangent
-					p = (uint32_t *)(data + dataOfs);
-					*p = R_VaoPackTangent(tangent);
-					dataOfs += sizeof(uint32_t);
+					dataOfs += R_VaoPackTangent(data + dataOfs, tangent);
 #endif
 				}
 			}
@@ -1022,20 +1015,15 @@ static qboolean R_LoadMDC( model_t *mod, int lod, void *buffer, const char *modN
 					vec3_t nxt;
 					vec4_t tangent;
 #endif
-					uint32_t *p;
-
 					// xyz
 					memcpy(data + dataOfs, &v->xyz, sizeof(vec3_t));
 					dataOfs += sizeof(v->xyz);
 
 					// st
-					memcpy(data + dataOfs, &st->st, sizeof(vec2_t));
-					dataOfs += sizeof(st->st);
+					dataOfs += R_VaoPackTexCoord(data + dataOfs, st->st);
 
 					// normal
-					p = (uint32_t *)(data + dataOfs);
-					*p = R_VaoPackNormal(v->normal);
-					dataOfs += sizeof(uint32_t);
+					dataOfs += R_VaoPackNormal(data + dataOfs, v->normal);
 
 #ifdef USE_VERT_TANGENT_SPACE
 					CrossProduct(v->normal, v->tangent, nxt);
@@ -1043,9 +1031,7 @@ static qboolean R_LoadMDC( model_t *mod, int lod, void *buffer, const char *modN
 					tangent[3] = (DotProduct(nxt, v->bitangent) < 0.0f) ? -1.0f : 1.0f;
 
 					// tangent
-					p = (uint32_t *)(data + dataOfs);
-					*p = R_VaoPackTangent(tangent);
-					dataOfs += sizeof(uint32_t);
+					dataOfs += R_VaoPackTangent(data + dataOfs, tangent);
 #endif
 				}
 			}
@@ -1073,7 +1059,7 @@ static qboolean R_LoadMDC( model_t *mod, int lod, void *buffer, const char *modN
 			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].count = 4;
 
 			vaoSurf->vao->attribs[ATTR_INDEX_POSITION].type = GL_FLOAT;
-			vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].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;
 
@@ -1449,10 +1435,10 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN
 			{
 				// vertex animation, store texcoords first, then position/normal/tangents
 				offset_st      = 0;
-				offset_xyz     = surf->numVerts * sizeof(vec2_t);
+				offset_xyz     = surf->numVerts * glRefConfig.packedTexcoordDataSize;
 				offset_normal  = offset_xyz + sizeof(vec3_t);
 				offset_tangent = offset_normal + sizeof(uint32_t);
-				stride_st  = sizeof(vec2_t);
+				stride_st  = glRefConfig.packedTexcoordDataSize;
 				stride_xyz = sizeof(vec3_t) + sizeof(uint32_t);
 #ifdef USE_VERT_TANGENT_SPACE
 				stride_xyz += sizeof(uint32_t);
@@ -1466,7 +1452,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN
 				// no animation, interleave everything
 				offset_xyz     = 0;
 				offset_st      = offset_xyz + sizeof(vec3_t);
-				offset_normal  = offset_st + sizeof(vec2_t);
+				offset_normal  = offset_st + glRefConfig.packedTexcoordDataSize;
 				offset_tangent = offset_normal + sizeof(uint32_t);
 #ifdef USE_VERT_TANGENT_SPACE
 				stride_xyz = offset_tangent + sizeof(uint32_t);
@@ -1486,8 +1472,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN
 			{
 				st = surf->st;
 				for ( j = 0 ; j < surf->numVerts ; j++, st++ ) {
-					memcpy(data + dataOfs, &st->st, sizeof(vec2_t));
-					dataOfs += sizeof(vec2_t);
+					dataOfs += R_VaoPackTexCoord(data + dataOfs, st->st);
 				}
 
 				v = surf->verts;
@@ -1497,16 +1482,12 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN
 					vec3_t nxt;
 					vec4_t tangent;
 #endif
-					uint32_t *p;
-
 					// xyz
 					memcpy(data + dataOfs, &v->xyz, sizeof(vec3_t));
 					dataOfs += sizeof(vec3_t);
 
 					// normal
-					p = (uint32_t *)(data + dataOfs);
-					*p = R_VaoPackNormal(v->normal);
-					dataOfs += sizeof(uint32_t);
+					dataOfs += R_VaoPackNormal(data + dataOfs, v->normal);
 
 #ifdef USE_VERT_TANGENT_SPACE
 					CrossProduct(v->normal, v->tangent, nxt);
@@ -1514,9 +1495,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN
 					tangent[3] = (DotProduct(nxt, v->bitangent) < 0.0f) ? -1.0f : 1.0f;
 
 					// tangent
-					p = (uint32_t *)(data + dataOfs);
-					*p = R_VaoPackTangent(tangent);
-					dataOfs += sizeof(uint32_t);
+					dataOfs += R_VaoPackTangent(data + dataOfs, tangent);
 #endif
 				}
 			}
@@ -1530,20 +1509,15 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN
 					vec3_t nxt;
 					vec4_t tangent;
 #endif
-					uint32_t *p;
-
 					// xyz
 					memcpy(data + dataOfs, &v->xyz, sizeof(vec3_t));
 					dataOfs += sizeof(v->xyz);
 
 					// st
-					memcpy(data + dataOfs, &st->st, sizeof(vec2_t));
-					dataOfs += sizeof(st->st);
+					dataOfs += R_VaoPackTexCoord(data + dataOfs, st->st);
 
 					// normal
-					p = (uint32_t *)(data + dataOfs);
-					*p = R_VaoPackNormal(v->normal);
-					dataOfs += sizeof(uint32_t);
+					dataOfs += R_VaoPackNormal(data + dataOfs, v->normal);
 
 #ifdef USE_VERT_TANGENT_SPACE
 					CrossProduct(v->normal, v->tangent, nxt);
@@ -1551,9 +1525,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN
 					tangent[3] = (DotProduct(nxt, v->bitangent) < 0.0f) ? -1.0f : 1.0f;
 
 					// tangent
-					p = (uint32_t *)(data + dataOfs);
-					*p = R_VaoPackTangent(tangent);
-					dataOfs += sizeof(uint32_t);
+					dataOfs += R_VaoPackTangent(data + dataOfs, tangent);
 #endif
 				}
 			}
@@ -1581,7 +1553,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN
 			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].count = 4;
 
 			vaoSurf->vao->attribs[ATTR_INDEX_POSITION].type = GL_FLOAT;
-			vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].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;
 
diff --git a/MP/code/rend2/tr_model_iqm.c b/MP/code/rend2/tr_model_iqm.c
index 79ac510..6095a39 100644
--- a/MP/code/rend2/tr_model_iqm.c
+++ b/MP/code/rend2/tr_model_iqm.c
@@ -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]);
 
-			*outNormal = R_VaoPackNormal(normal);
+			R_VaoPackNormal((byte *)outNormal, normal);
 
 #ifdef USE_VERT_TANGENT_SPACE
 			tangent[0] = DotProduct(&nrmMat[0], &data->tangents[4*vtx]);
@@ -1138,7 +1138,7 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
 			tangent[2] = DotProduct(&nrmMat[6], &data->tangents[4*vtx]);
 			tangent[3] = data->tangents[4*vtx+3];
 
-			*outTangent++ = R_VaoPackTangent(tangent);
+			R_VaoPackTangent((byte *)outTangent++, tangent);
 #endif
 		}
 
diff --git a/MP/code/rend2/tr_shade_calc.c b/MP/code/rend2/tr_shade_calc.c
index cb96aa0..7d6ab09 100644
--- a/MP/code/rend2/tr_shade_calc.c
+++ b/MP/code/rend2/tr_shade_calc.c
@@ -244,7 +244,7 @@ void RB_CalcDeformNormals( deformStage_t *ds ) {
 
 		VectorNormalizeFast( fNormal );
 
-		*normal = R_VaoPackNormal(fNormal);
+		R_VaoPackNormal((byte *)normal, fNormal);
 	}
 }
 
diff --git a/MP/code/rend2/tr_surface.c b/MP/code/rend2/tr_surface.c
index df5ae0c..d22cc2c 100644
--- a/MP/code/rend2/tr_surface.c
+++ b/MP/code/rend2/tr_surface.c
@@ -94,6 +94,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;
 	int ndx;
 
 	RB_CHECKOVERFLOW( 4, 6 );
@@ -129,10 +130,11 @@ 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] = R_VaoPackNormal(normal);
+	tess.normal[ndx+3] = pNormal;
 
 	// standard square texture coordinates
 	VectorSet2(tess.texCoords[ndx  ][0], s1, t1);
@@ -374,7 +376,7 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIn
 		dv = verts;
 		normal = &tess.normal[ tess.numVertexes ];
 		for ( i = 0 ; i < numVerts ; i++, dv++, normal++ )
-			*normal = R_VaoPackNormal(dv->normal);
+			R_VaoPackNormal((byte *)normal, dv->normal);
 	}
 
 #ifdef USE_VERT_TANGENT_SPACE
@@ -383,7 +385,7 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIn
 		dv = verts;
 		tangent = &tess.tangent[ tess.numVertexes ];
 		for ( i = 0 ; i < numVerts ; i++, dv++, tangent++ )
-			*tangent = R_VaoPackTangent(dv->tangent);
+			R_VaoPackTangent((byte *)tangent, dv->tangent);
 	}
 #endif
 
@@ -416,7 +418,7 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIn
 		dv = verts;
 		lightdir = &tess.lightdir[ tess.numVertexes ];
 		for ( i = 0 ; i < numVerts ; i++, dv++, lightdir++ )
-			*lightdir = R_VaoPackNormal(dv->lightdir);
+			R_VaoPackNormal((byte *)lightdir, dv->lightdir);
 	}
 
 #if 0  // nothing even uses vertex dlightbits
@@ -1172,7 +1174,7 @@ static void LerpMeshVertexes_scalar(mdvSurface_t *surf, float backlerp)
 			VectorCopy(newVerts->xyz,    outXyz);
 			VectorCopy(newVerts->normal, normal);
 
-			*outNormal = R_VaoPackNormal(normal);
+			R_VaoPackNormal((byte *)outNormal, normal);
 
 			newVerts++;
 			outXyz += 4;
@@ -1197,7 +1199,7 @@ static void LerpMeshVertexes_scalar(mdvSurface_t *surf, float backlerp)
 			VectorLerp(newVerts->normal, oldVerts->normal, backlerp, normal);
 			VectorNormalize(normal);
 
-			*outNormal = R_VaoPackNormal(normal);
+			R_VaoPackNormal((byte *)outNormal, normal);
 
 			newVerts++;
 			oldVerts++;
@@ -1364,7 +1366,7 @@ static void LerpCMeshVertexes( mdcSurface_t *surf, float backlerp ) {
 				fNormal[2] = tr.sinTable[( lng + ( FUNCTABLE_SIZE / 4 ) ) & FUNCTABLE_MASK];
 			}
 
-			*outNormal = R_VaoPackNormal(fNormal);
+			R_VaoPackNormal((byte *)outNormal, fNormal);
 		}
 	} else {
 		//
@@ -1434,7 +1436,7 @@ static void LerpCMeshVertexes( mdcSurface_t *surf, float backlerp ) {
 
 			VectorNormalize( fNormal );
 			
-			*outNormal = R_VaoPackNormal(fNormal);
+			R_VaoPackNormal((byte *)outNormal, fNormal);
 		}
 	}
 }
@@ -1662,13 +1664,13 @@ static void RB_SurfaceGrid( srfBspSurface_t *srf ) {
 
 				if ( tess.shader->vertexAttribs & ATTR_NORMAL )
 				{
-					*normal++ = R_VaoPackNormal(dv->normal);
+					R_VaoPackNormal((byte *)normal++, dv->normal);
 				}
 
 #ifdef USE_VERT_TANGENT_SPACE
 				if ( tess.shader->vertexAttribs & ATTR_TANGENT )
 				{
-					*tangent++ = R_VaoPackTangent(dv->tangent);
+					R_VaoPackTangent((byte *)tangent++, dv->tangent);
 				}
 #endif
 
@@ -1692,7 +1694,7 @@ static void RB_SurfaceGrid( srfBspSurface_t *srf ) {
 
 				if ( tess.shader->vertexAttribs & ATTR_LIGHTDIRECTION )
 				{
-					*lightdir++ = R_VaoPackNormal(dv->lightdir);
+					R_VaoPackNormal((byte *)lightdir++, dv->lightdir);
 				}
 
 				//*vDlightBits++ = dlightBits;
diff --git a/MP/code/rend2/tr_vbo.c b/MP/code/rend2/tr_vbo.c
index 981741f..8f9ba66 100644
--- a/MP/code/rend2/tr_vbo.c
+++ b/MP/code/rend2/tr_vbo.c
@@ -44,81 +44,122 @@ union pack8_u {
 };
 
 
-uint32_t R_VaoPackTangent(vec4_t v)
+int R_VaoPackTangent(byte *out, vec4_t v)
 {
 	if (glRefConfig.packedNormalDataType == GL_INT_2_10_10_10_REV)
 	{
-		union pack10_u num;
+		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];
+		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;
+}
+
+int R_VaoPackNormal(byte *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;
 
-		return num.i;
+		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;
+}
+
+int R_VaoPackTexCoord(byte *out, vec2_t st)
+{
+	if (glRefConfig.packedTexcoordDataType == GL_HALF_FLOAT)
+	{
+		uint16_t *num = (uint16_t *)out;
+
+		*num++ = FloatToHalf(st[0]);
+		*num++ = FloatToHalf(st[1]);
+
+		return sizeof(*num) * 2;
 	}
 	else
 	{
-		union pack8_u num;
+		float *num = (float *)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;
+		*num++ = st[0];
+		*num++ = st[1];
 
-		return num.i;
+		return sizeof(*num) * 2;
 	}
 }
 
-uint32_t R_VaoPackNormal(vec3_t v)
+int R_VaoPackColors(byte *out, vec4_t color)
 {
-	if (glRefConfig.packedNormalDataType == GL_INT_2_10_10_10_REV)
+	if (glRefConfig.packedTexcoordDataType == GL_HALF_FLOAT)
 	{
-		union pack10_u num;
+		uint16_t *num = (uint16_t *)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;
+		*num++ = FloatToHalf(color[0]);
+		*num++ = FloatToHalf(color[1]);
+		*num++ = FloatToHalf(color[2]);
+		*num++ = FloatToHalf(color[3]);
 
-		return num.i;
+		return sizeof(*num) * 4;
 	}
 	else
 	{
-		union pack8_u num;
+		float *num = (float *)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;
+		*num++ = color[0];
+		*num++ = color[1];
+		*num++ = color[2];
+		*num++ = color[3];
 
-		return num.i;
+		return sizeof(*num) * 4;
 	}
 }
 
+
 void R_VaoUnpackTangent(vec4_t v, uint32_t b)
 {
 	if (glRefConfig.packedNormalDataType == GL_INT_2_10_10_10_REV)
 	{
-		union pack10_u num;
+		union pack10_u *num = (union pack10_u *)&b;
 
-		num.i = 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; 
+		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;
-
-		num.i = b;
+		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] = 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; 
 	}
 }
 
@@ -126,23 +167,19 @@ void R_VaoUnpackNormal(vec3_t v, uint32_t b)
 {
 	if (glRefConfig.packedNormalDataType == GL_INT_2_10_10_10_REV)
 	{
-		union pack10_u num;
+		union pack10_u *num = (union pack10_u *)&b;
 
-		num.i = b;
-
-		v[0] = num.pack.x / 511.0f;
-		v[1] = num.pack.y / 511.0f;
-		v[2] = num.pack.z / 511.0f;
+		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;
-
-		num.i = b;
+		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] = num->pack.x / 127.0f;
+		v[1] = num->pack.y / 127.0f;
+		v[2] = num->pack.z / 127.0f;
 	}
 }
 
@@ -312,9 +349,9 @@ vao_t *R_CreateVao2(const char *name, int numVertexes, srfVert_t *verts, int num
 	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_TEXCOORD      ].type = GL_FLOAT;
-	vao->attribs[ATTR_INDEX_LIGHTCOORD    ].type = GL_FLOAT;
-	vao->attribs[ATTR_INDEX_COLOR         ].type = GL_FLOAT;
+	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_POSITION      ].normalized = GL_FALSE;
@@ -330,9 +367,9 @@ vao_t *R_CreateVao2(const char *name, int numVertexes, srfVert_t *verts, int num
 #ifdef USE_VERT_TANGENT_SPACE
 	vao->attribs[ATTR_INDEX_TANGENT       ].offset = dataSize; dataSize += sizeof(uint32_t);
 #endif
-	vao->attribs[ATTR_INDEX_TEXCOORD      ].offset = dataSize; dataSize += sizeof(verts[0].st);
-	vao->attribs[ATTR_INDEX_LIGHTCOORD    ].offset = dataSize; dataSize += sizeof(verts[0].lightmap);
-	vao->attribs[ATTR_INDEX_COLOR         ].offset = dataSize; dataSize += sizeof(verts[0].vertexColors);
+	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_POSITION      ].stride = dataSize;
@@ -358,40 +395,29 @@ vao_t *R_CreateVao2(const char *name, int numVertexes, srfVert_t *verts, int num
 
 	for (i = 0; i < numVertexes; i++)
 	{
-		uint32_t *p;
-
 		// xyz
 		memcpy(data + dataOfs, &verts[i].xyz, sizeof(verts[i].xyz));
 		dataOfs += sizeof(verts[i].xyz);
 
 		// normal
-		p = (uint32_t *)(data + dataOfs);
-		*p = R_VaoPackNormal(verts[i].normal);
-		dataOfs += sizeof(uint32_t);
+		dataOfs += R_VaoPackNormal(data + dataOfs, verts[i].normal);
 
 #ifdef USE_VERT_TANGENT_SPACE
 		// tangent
-		p = (uint32_t *)(data + dataOfs);
-		*p = R_VaoPackTangent(verts[i].tangent);
-		dataOfs += sizeof(uint32_t);
+		dataOfs += R_VaoPackTangent(data + dataOfs, verts[i].tangent);
 #endif
 
-		// vertex texcoords
-		memcpy(data + dataOfs, &verts[i].st, sizeof(verts[i].st));
-		dataOfs += sizeof(verts[i].st);
+		// texcoords
+		dataOfs += R_VaoPackTexCoord(data + dataOfs, verts[i].st);
 
-		// feed vertex lightmap texcoords
-		memcpy(data + dataOfs, &verts[i].lightmap, sizeof(verts[i].lightmap));
-		dataOfs += sizeof(verts[i].lightmap);
+		// lightmap texcoords
+		dataOfs += R_VaoPackTexCoord(data + dataOfs, verts[i].lightmap);
 
-		// feed vertex colors
-		memcpy(data + dataOfs, &verts[i].vertexColors, sizeof(verts[i].vertexColors));
-		dataOfs += sizeof(verts[i].vertexColors);
+		// colors
+		dataOfs += R_VaoPackColors(data + dataOfs, verts[i].vertexColors);
 
-		// feed vertex light directions
-		p = (uint32_t *)(data + dataOfs);
-		*p = R_VaoPackNormal(verts[i].lightdir);
-		dataOfs += sizeof(uint32_t);
+		// light directions
+		dataOfs += R_VaoPackNormal(data + dataOfs, verts[i].lightdir);
 	}
 
 	vao->vertexesSize = dataSize;
diff --git a/SP/code/rend2/tr_animation.c b/SP/code/rend2/tr_animation.c
index e4f27ca..f2f777c 100644
--- a/SP/code/rend2/tr_animation.c
+++ b/SP/code/rend2/tr_animation.c
@@ -1198,7 +1198,7 @@ void RB_SurfaceAnim( mdsSurface_t *surface ) {
 		}
 		LocalMatrixTransformVector( v->normal, bones[v->weights[0].boneIndex].matrix, newNormal );
 		
-		*tempNormal = R_VaoPackNormal(newNormal);
+		R_VaoPackNormal((byte *)tempNormal, newNormal);
 
 		tess.texCoords[baseVertex + j][0][0] = v->texCoords[0];
 		tess.texCoords[baseVertex + j][0][1] = v->texCoords[1];
@@ -1748,7 +1748,7 @@ void RB_MDRSurfaceAnim( mdrSurface_t *surface )
 		tess.xyz[baseVertex + j][1] = tempVert[1];
 		tess.xyz[baseVertex + j][2] = tempVert[2];
 
-		tess.normal[baseVertex + j] = R_VaoPackNormal(tempNormal);
+		R_VaoPackNormal((byte *)&tess.normal[baseVertex + j], tempNormal);
 
 		tess.texCoords[baseVertex + j][0][0] = v->texCoords[0];
 		tess.texCoords[baseVertex + j][0][1] = v->texCoords[1];
diff --git a/SP/code/rend2/tr_extensions.c b/SP/code/rend2/tr_extensions.c
index b770e6c..c0f4d04 100644
--- a/SP/code/rend2/tr_extensions.c
+++ b/SP/code/rend2/tr_extensions.c
@@ -33,8 +33,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 void            (APIENTRY * qglDrawRangeElementsEXT) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
 
 // GL_EXT_multi_draw_arrays
-void (APIENTRY * qglMultiDrawArraysEXT) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
-void (APIENTRY * qglMultiDrawElementsEXT) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
+void            (APIENTRY * qglMultiDrawArraysEXT) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+void            (APIENTRY * qglMultiDrawElementsEXT) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
 
 // GL_ARB_vertex_shader
 void            (APIENTRY * qglBindAttribLocationARB) (GLhandleARB programObj, GLuint index, const GLcharARB * name);
@@ -709,4 +709,27 @@ void GLimp_InitExtraExtensions()
 		ri.Printf(PRINT_ALL, result[2], extension);
 	}
 
+	// GL_ARB_half_float_vertex
+	extension = "GL_ARB_half_float_vertex";
+	glRefConfig.packedTexcoordDataType = GL_FLOAT;
+	glRefConfig.packedTexcoordDataSize = sizeof(float) * 2;
+	glRefConfig.packedColorDataType    = GL_FLOAT;
+	glRefConfig.packedColorDataSize    = sizeof(float) * 4;
+	if( GLimp_HaveExtension( extension ) )
+	{
+		if (r_arb_half_float_vertex->integer)
+		{
+			glRefConfig.packedTexcoordDataType = GL_HALF_FLOAT;
+			glRefConfig.packedTexcoordDataSize = sizeof(uint16_t) * 2;
+			glRefConfig.packedColorDataType    = GL_HALF_FLOAT;
+			glRefConfig.packedColorDataSize    = sizeof(uint16_t) * 4;
+		}
+
+		ri.Printf(PRINT_ALL, result[r_arb_half_float_vertex->integer ? 1 : 0], extension);
+	}
+	else
+	{
+		ri.Printf(PRINT_ALL, result[2], extension);
+	}
+
 }
diff --git a/SP/code/rend2/tr_extramath.c b/SP/code/rend2/tr_extramath.c
index b844678..da9a94d 100644
--- a/SP/code/rend2/tr_extramath.c
+++ b/SP/code/rend2/tr_extramath.c
@@ -199,42 +199,35 @@ int NextPowerOfTwo(int in)
 	return out;
 }
 
-unsigned short FloatToHalf(float in)
-{
-	unsigned short out;
-	
-	union
-	{
-		float f;
-		unsigned int i;
-	} f32;
-
-	int sign, inExponent, inFraction;
-	int outExponent, outFraction;
+union f32_u {
+	float f;
+	uint32_t i;
+	struct {
+		unsigned int fraction:23;
+		unsigned int exponent:8;
+		unsigned int sign:1;
+	} pack;
+};
+
+union f16_u {
+	uint16_t i;
+	struct {
+		unsigned int fraction:10;
+		unsigned int exponent:5;
+		unsigned int sign:1;
+	} pack;
+};
+
+uint16_t FloatToHalf(float in)
+{
+	union f32_u f32;
+	union f16_u f16;
 
 	f32.f = in;
 
-	sign       = (f32.i & 0x80000000) >> 31;
-	inExponent = (f32.i & 0x7F800000) >> 23;
-	inFraction =  f32.i & 0x007FFFFF;
-
-	outExponent = CLAMP(inExponent - 127, -15, 16) + 15;
-
-	outFraction = 0;
-	if (outExponent == 0x1F)
-	{
-		if (inExponent == 0xFF && inFraction != 0)
-			outFraction = 0x3FF;
-	}
-	else if (outExponent == 0x00)
-	{
-		if (inExponent == 0x00 && inFraction != 0)
-			outFraction = 0x3FF;
-	}
-	else
-		outFraction = inFraction >> 13;
-
-	out = (sign << 15) | (outExponent << 10) | outFraction;
+	f16.pack.exponent = CLAMP(f32.pack.exponent - 112, 0, 31);
+	f16.pack.fraction = f32.pack.fraction >> 13;
+	f16.pack.sign     = f32.pack.sign;
 
-	return out;
+	return f16.i;
 }
diff --git a/SP/code/rend2/tr_init.c b/SP/code/rend2/tr_init.c
index df826b2..0e99183 100644
--- a/SP/code/rend2/tr_init.c
+++ b/SP/code/rend2/tr_init.c
@@ -127,6 +127,7 @@ cvar_t  *r_ext_multi_draw_arrays;
 cvar_t  *r_ext_framebuffer_object;
 cvar_t  *r_ext_texture_float;
 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;
@@ -1272,6 +1273,7 @@ void R_Register( void ) {
 	r_ext_framebuffer_object = ri.Cvar_Get( "r_ext_framebuffer_object", "1", CVAR_ARCHIVE | CVAR_LATCH);
 	r_ext_texture_float = ri.Cvar_Get( "r_ext_texture_float", "1", CVAR_ARCHIVE | CVAR_LATCH);
 	r_arb_half_float_pixel = ri.Cvar_Get( "r_arb_half_float_pixel", "1", CVAR_ARCHIVE | CVAR_LATCH);
+	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);
diff --git a/SP/code/rend2/tr_local.h b/SP/code/rend2/tr_local.h
index 35169aa..567e40a 100644
--- a/SP/code/rend2/tr_local.h
+++ b/SP/code/rend2/tr_local.h
@@ -1558,6 +1558,10 @@ typedef struct {
 	qboolean seamlessCubeMap;
 
 	GLenum packedNormalDataType;
+	GLenum packedTexcoordDataType;
+	GLenum packedColorDataType;
+	int packedTexcoordDataSize;
+	int packedColorDataSize;
 
 	qboolean floatLightmap;
 	qboolean vertexArrayObject;
@@ -1914,6 +1918,7 @@ extern  cvar_t  *r_ext_multi_draw_arrays;
 extern  cvar_t  *r_ext_framebuffer_object;
 extern  cvar_t  *r_ext_texture_float;
 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;
@@ -2443,8 +2448,10 @@ VERTEX BUFFER OBJECTS
 ============================================================
 */
 
-uint32_t R_VaoPackTangent(vec4_t v);
-uint32_t R_VaoPackNormal(vec3_t v);
+int R_VaoPackTangent(byte *out, vec4_t v);
+int R_VaoPackNormal(byte *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);
 
diff --git a/SP/code/rend2/tr_model.c b/SP/code/rend2/tr_model.c
index 435915b..2504d06 100644
--- a/SP/code/rend2/tr_model.c
+++ b/SP/code/rend2/tr_model.c
@@ -943,10 +943,10 @@ static qboolean R_LoadMDC( model_t *mod, int lod, void *buffer, const char *modN
 			{
 				// vertex animation, store texcoords first, then position/normal/tangents
 				offset_st      = 0;
-				offset_xyz     = surf->numVerts * sizeof(vec2_t);
+				offset_xyz     = surf->numVerts * glRefConfig.packedTexcoordDataSize;
 				offset_normal  = offset_xyz + sizeof(vec3_t);
 				offset_tangent = offset_normal + sizeof(uint32_t);
-				stride_st  = sizeof(vec2_t);
+				stride_st  = glRefConfig.packedTexcoordDataSize;
 				stride_xyz = sizeof(vec3_t) + sizeof(uint32_t);
 #ifdef USE_VERT_TANGENT_SPACE
 				stride_xyz += sizeof(uint32_t);
@@ -960,7 +960,7 @@ static qboolean R_LoadMDC( model_t *mod, int lod, void *buffer, const char *modN
 				// no animation, interleave everything
 				offset_xyz     = 0;
 				offset_st      = offset_xyz + sizeof(vec3_t);
-				offset_normal  = offset_st + sizeof(vec2_t);
+				offset_normal  = offset_st + glRefConfig.packedTexcoordDataSize;
 				offset_tangent = offset_normal + sizeof(uint32_t);
 #ifdef USE_VERT_TANGENT_SPACE
 				stride_xyz = offset_tangent + sizeof(uint32_t);
@@ -980,8 +980,7 @@ static qboolean R_LoadMDC( model_t *mod, int lod, void *buffer, const char *modN
 			{
 				st = surf->st;
 				for ( j = 0 ; j < surf->numVerts ; j++, st++ ) {
-					memcpy(data + dataOfs, &st->st, sizeof(vec2_t));
-					dataOfs += sizeof(vec2_t);
+					dataOfs += R_VaoPackTexCoord(data + dataOfs, st->st);
 				}
 
 				v = surf->verts;
@@ -991,16 +990,12 @@ static qboolean R_LoadMDC( model_t *mod, int lod, void *buffer, const char *modN
 					vec3_t nxt;
 					vec4_t tangent;
 #endif
-					uint32_t *p;
-
 					// xyz
 					memcpy(data + dataOfs, &v->xyz, sizeof(vec3_t));
 					dataOfs += sizeof(vec3_t);
 
 					// normal
-					p = (uint32_t *)(data + dataOfs);
-					*p = R_VaoPackNormal(v->normal);
-					dataOfs += sizeof(uint32_t);
+					dataOfs += R_VaoPackNormal(data + dataOfs, v->normal);
 
 #ifdef USE_VERT_TANGENT_SPACE
 					CrossProduct(v->normal, v->tangent, nxt);
@@ -1008,9 +1003,7 @@ static qboolean R_LoadMDC( model_t *mod, int lod, void *buffer, const char *modN
 					tangent[3] = (DotProduct(nxt, v->bitangent) < 0.0f) ? -1.0f : 1.0f;
 
 					// tangent
-					p = (uint32_t *)(data + dataOfs);
-					*p = R_VaoPackTangent(tangent);
-					dataOfs += sizeof(uint32_t);
+					dataOfs += R_VaoPackTangent(data + dataOfs, tangent);
 #endif
 				}
 			}
@@ -1024,20 +1017,15 @@ static qboolean R_LoadMDC( model_t *mod, int lod, void *buffer, const char *modN
 					vec3_t nxt;
 					vec4_t tangent;
 #endif
-					uint32_t *p;
-
 					// xyz
 					memcpy(data + dataOfs, &v->xyz, sizeof(vec3_t));
 					dataOfs += sizeof(v->xyz);
 
 					// st
-					memcpy(data + dataOfs, &st->st, sizeof(vec2_t));
-					dataOfs += sizeof(st->st);
+					dataOfs += R_VaoPackTexCoord(data + dataOfs, st->st);
 
 					// normal
-					p = (uint32_t *)(data + dataOfs);
-					*p = R_VaoPackNormal(v->normal);
-					dataOfs += sizeof(uint32_t);
+					dataOfs += R_VaoPackNormal(data + dataOfs, v->normal);
 
 #ifdef USE_VERT_TANGENT_SPACE
 					CrossProduct(v->normal, v->tangent, nxt);
@@ -1045,9 +1033,7 @@ static qboolean R_LoadMDC( model_t *mod, int lod, void *buffer, const char *modN
 					tangent[3] = (DotProduct(nxt, v->bitangent) < 0.0f) ? -1.0f : 1.0f;
 
 					// tangent
-					p = (uint32_t *)(data + dataOfs);
-					*p = R_VaoPackTangent(tangent);
-					dataOfs += sizeof(uint32_t);
+					dataOfs += R_VaoPackTangent(data + dataOfs, tangent);
 #endif
 				}
 			}
@@ -1075,7 +1061,7 @@ static qboolean R_LoadMDC( model_t *mod, int lod, void *buffer, const char *modN
 			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].count = 4;
 
 			vaoSurf->vao->attribs[ATTR_INDEX_POSITION].type = GL_FLOAT;
-			vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].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;
 
@@ -1451,10 +1437,10 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN
 			{
 				// vertex animation, store texcoords first, then position/normal/tangents
 				offset_st      = 0;
-				offset_xyz     = surf->numVerts * sizeof(vec2_t);
+				offset_xyz     = surf->numVerts * glRefConfig.packedTexcoordDataSize;
 				offset_normal  = offset_xyz + sizeof(vec3_t);
 				offset_tangent = offset_normal + sizeof(uint32_t);
-				stride_st  = sizeof(vec2_t);
+				stride_st  = glRefConfig.packedTexcoordDataSize;
 				stride_xyz = sizeof(vec3_t) + sizeof(uint32_t);
 #ifdef USE_VERT_TANGENT_SPACE
 				stride_xyz += sizeof(uint32_t);
@@ -1468,7 +1454,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN
 				// no animation, interleave everything
 				offset_xyz     = 0;
 				offset_st      = offset_xyz + sizeof(vec3_t);
-				offset_normal  = offset_st + sizeof(vec2_t);
+				offset_normal  = offset_st + glRefConfig.packedTexcoordDataSize;
 				offset_tangent = offset_normal + sizeof(uint32_t);
 #ifdef USE_VERT_TANGENT_SPACE
 				stride_xyz = offset_tangent + sizeof(uint32_t);
@@ -1488,8 +1474,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN
 			{
 				st = surf->st;
 				for ( j = 0 ; j < surf->numVerts ; j++, st++ ) {
-					memcpy(data + dataOfs, &st->st, sizeof(vec2_t));
-					dataOfs += sizeof(vec2_t);
+					dataOfs += R_VaoPackTexCoord(data + dataOfs, st->st);
 				}
 
 				v = surf->verts;
@@ -1499,16 +1484,12 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN
 					vec3_t nxt;
 					vec4_t tangent;
 #endif
-					uint32_t *p;
-
 					// xyz
 					memcpy(data + dataOfs, &v->xyz, sizeof(vec3_t));
 					dataOfs += sizeof(vec3_t);
 
 					// normal
-					p = (uint32_t *)(data + dataOfs);
-					*p = R_VaoPackNormal(v->normal);
-					dataOfs += sizeof(uint32_t);
+					dataOfs += R_VaoPackNormal(data + dataOfs, v->normal);
 
 #ifdef USE_VERT_TANGENT_SPACE
 					CrossProduct(v->normal, v->tangent, nxt);
@@ -1516,9 +1497,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN
 					tangent[3] = (DotProduct(nxt, v->bitangent) < 0.0f) ? -1.0f : 1.0f;
 
 					// tangent
-					p = (uint32_t *)(data + dataOfs);
-					*p = R_VaoPackTangent(tangent);
-					dataOfs += sizeof(uint32_t);
+					dataOfs += R_VaoPackTangent(data + dataOfs, tangent);
 #endif
 				}
 			}
@@ -1532,20 +1511,15 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN
 					vec3_t nxt;
 					vec4_t tangent;
 #endif
-					uint32_t *p;
-
 					// xyz
 					memcpy(data + dataOfs, &v->xyz, sizeof(vec3_t));
 					dataOfs += sizeof(v->xyz);
 
 					// st
-					memcpy(data + dataOfs, &st->st, sizeof(vec2_t));
-					dataOfs += sizeof(st->st);
+					dataOfs += R_VaoPackTexCoord(data + dataOfs, st->st);
 
 					// normal
-					p = (uint32_t *)(data + dataOfs);
-					*p = R_VaoPackNormal(v->normal);
-					dataOfs += sizeof(uint32_t);
+					dataOfs += R_VaoPackNormal(data + dataOfs, v->normal);
 
 #ifdef USE_VERT_TANGENT_SPACE
 					CrossProduct(v->normal, v->tangent, nxt);
@@ -1553,9 +1527,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN
 					tangent[3] = (DotProduct(nxt, v->bitangent) < 0.0f) ? -1.0f : 1.0f;
 
 					// tangent
-					p = (uint32_t *)(data + dataOfs);
-					*p = R_VaoPackTangent(tangent);
-					dataOfs += sizeof(uint32_t);
+					dataOfs += R_VaoPackTangent(data + dataOfs, tangent);
 #endif
 				}
 			}
@@ -1583,7 +1555,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN
 			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].count = 4;
 
 			vaoSurf->vao->attribs[ATTR_INDEX_POSITION].type = GL_FLOAT;
-			vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].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;
 
diff --git a/SP/code/rend2/tr_model_iqm.c b/SP/code/rend2/tr_model_iqm.c
index 0079506..4e51c18 100644
--- a/SP/code/rend2/tr_model_iqm.c
+++ b/SP/code/rend2/tr_model_iqm.c
@@ -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]);
 
-			*outNormal = R_VaoPackNormal(normal);
+			R_VaoPackNormal((byte *)outNormal, normal);
 
 #ifdef USE_VERT_TANGENT_SPACE
 			tangent[0] = DotProduct(&nrmMat[0], &data->tangents[4*vtx]);
@@ -1138,7 +1138,7 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
 			tangent[2] = DotProduct(&nrmMat[6], &data->tangents[4*vtx]);
 			tangent[3] = data->tangents[4*vtx+3];
 
-			*outTangent++ = R_VaoPackTangent(tangent);
+			R_VaoPackTangent((byte *)outTangent++, tangent);
 #endif
 		}
 
diff --git a/SP/code/rend2/tr_shade_calc.c b/SP/code/rend2/tr_shade_calc.c
index 4bfad4c..d1e6b44 100644
--- a/SP/code/rend2/tr_shade_calc.c
+++ b/SP/code/rend2/tr_shade_calc.c
@@ -244,7 +244,7 @@ void RB_CalcDeformNormals( deformStage_t *ds ) {
 
 		VectorNormalizeFast( fNormal );
 
-		*normal = R_VaoPackNormal(fNormal);
+		R_VaoPackNormal((byte *)normal, fNormal);
 	}
 }
 
diff --git a/SP/code/rend2/tr_surface.c b/SP/code/rend2/tr_surface.c
index f3afa01..7c9bc05 100644
--- a/SP/code/rend2/tr_surface.c
+++ b/SP/code/rend2/tr_surface.c
@@ -94,6 +94,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;
 	int ndx;
 
 	RB_CHECKOVERFLOW( 4, 6 );
@@ -129,10 +130,11 @@ 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] = R_VaoPackNormal(normal);
+	tess.normal[ndx+3] = pNormal;
 
 	// standard square texture coordinates
 	VectorSet2(tess.texCoords[ndx  ][0], s1, t1);
@@ -374,7 +376,7 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIn
 		dv = verts;
 		normal = &tess.normal[ tess.numVertexes ];
 		for ( i = 0 ; i < numVerts ; i++, dv++, normal++ )
-			*normal = R_VaoPackNormal(dv->normal);
+			R_VaoPackNormal((byte *)normal, dv->normal);
 	}
 
 #ifdef USE_VERT_TANGENT_SPACE
@@ -383,7 +385,7 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIn
 		dv = verts;
 		tangent = &tess.tangent[ tess.numVertexes ];
 		for ( i = 0 ; i < numVerts ; i++, dv++, tangent++ )
-			*tangent = R_VaoPackTangent(dv->tangent);
+			R_VaoPackTangent((byte *)tangent, dv->tangent);
 	}
 #endif
 
@@ -416,7 +418,7 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIn
 		dv = verts;
 		lightdir = &tess.lightdir[ tess.numVertexes ];
 		for ( i = 0 ; i < numVerts ; i++, dv++, lightdir++ )
-			*lightdir = R_VaoPackNormal(dv->lightdir);
+			R_VaoPackNormal((byte *)lightdir, dv->lightdir);
 	}
 
 #if 0  // nothing even uses vertex dlightbits
@@ -1170,7 +1172,7 @@ static void LerpMeshVertexes_scalar(mdvSurface_t *surf, float backlerp)
 			VectorCopy(newVerts->xyz,    outXyz);
 			VectorCopy(newVerts->normal, normal);
 
-			*outNormal = R_VaoPackNormal(normal);
+			R_VaoPackNormal((byte *)outNormal, normal);
 
 			newVerts++;
 			outXyz += 4;
@@ -1195,7 +1197,7 @@ static void LerpMeshVertexes_scalar(mdvSurface_t *surf, float backlerp)
 			VectorLerp(newVerts->normal, oldVerts->normal, backlerp, normal);
 			VectorNormalize(normal);
 
-			*outNormal = R_VaoPackNormal(normal);
+			R_VaoPackNormal((byte *)outNormal, normal);
 
 			newVerts++;
 			oldVerts++;
@@ -1362,7 +1364,7 @@ static void LerpCMeshVertexes( mdcSurface_t *surf, float backlerp ) {
 				fNormal[2] = tr.sinTable[( lng + ( FUNCTABLE_SIZE / 4 ) ) & FUNCTABLE_MASK];
 			}
 
-			*outNormal = R_VaoPackNormal(fNormal);
+			R_VaoPackNormal((byte *)outNormal, fNormal);
 		}
 	} else {
 		//
@@ -1432,7 +1434,7 @@ static void LerpCMeshVertexes( mdcSurface_t *surf, float backlerp ) {
 
 			VectorNormalize( fNormal );
 			
-			*outNormal = R_VaoPackNormal(fNormal);
+			R_VaoPackNormal((byte *)outNormal, fNormal);
 		}
 	}
 }
@@ -1659,13 +1661,13 @@ static void RB_SurfaceGrid( srfBspSurface_t *srf ) {
 
 				if ( tess.shader->vertexAttribs & ATTR_NORMAL )
 				{
-					*normal++ = R_VaoPackNormal(dv->normal);
+					R_VaoPackNormal((byte *)normal++, dv->normal);
 				}
 
 #ifdef USE_VERT_TANGENT_SPACE
 				if ( tess.shader->vertexAttribs & ATTR_TANGENT )
 				{
-					*tangent++ = R_VaoPackTangent(dv->tangent);
+					R_VaoPackTangent((byte *)tangent++, dv->tangent);
 				}
 #endif
 
@@ -1689,7 +1691,7 @@ static void RB_SurfaceGrid( srfBspSurface_t *srf ) {
 
 				if ( tess.shader->vertexAttribs & ATTR_LIGHTDIRECTION )
 				{
-					*lightdir++ = R_VaoPackNormal(dv->lightdir);
+					R_VaoPackNormal((byte *)lightdir++, dv->lightdir);
 				}
 
 				//*vDlightBits++ = dlightBits;
diff --git a/SP/code/rend2/tr_vbo.c b/SP/code/rend2/tr_vbo.c
index 981741f..8f9ba66 100644
--- a/SP/code/rend2/tr_vbo.c
+++ b/SP/code/rend2/tr_vbo.c
@@ -44,81 +44,122 @@ union pack8_u {
 };
 
 
-uint32_t R_VaoPackTangent(vec4_t v)
+int R_VaoPackTangent(byte *out, vec4_t v)
 {
 	if (glRefConfig.packedNormalDataType == GL_INT_2_10_10_10_REV)
 	{
-		union pack10_u num;
+		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];
+		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;
+}
+
+int R_VaoPackNormal(byte *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;
 
-		return num.i;
+		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;
+}
+
+int R_VaoPackTexCoord(byte *out, vec2_t st)
+{
+	if (glRefConfig.packedTexcoordDataType == GL_HALF_FLOAT)
+	{
+		uint16_t *num = (uint16_t *)out;
+
+		*num++ = FloatToHalf(st[0]);
+		*num++ = FloatToHalf(st[1]);
+
+		return sizeof(*num) * 2;
 	}
 	else
 	{
-		union pack8_u num;
+		float *num = (float *)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;
+		*num++ = st[0];
+		*num++ = st[1];
 
-		return num.i;
+		return sizeof(*num) * 2;
 	}
 }
 
-uint32_t R_VaoPackNormal(vec3_t v)
+int R_VaoPackColors(byte *out, vec4_t color)
 {
-	if (glRefConfig.packedNormalDataType == GL_INT_2_10_10_10_REV)
+	if (glRefConfig.packedTexcoordDataType == GL_HALF_FLOAT)
 	{
-		union pack10_u num;
+		uint16_t *num = (uint16_t *)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;
+		*num++ = FloatToHalf(color[0]);
+		*num++ = FloatToHalf(color[1]);
+		*num++ = FloatToHalf(color[2]);
+		*num++ = FloatToHalf(color[3]);
 
-		return num.i;
+		return sizeof(*num) * 4;
 	}
 	else
 	{
-		union pack8_u num;
+		float *num = (float *)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;
+		*num++ = color[0];
+		*num++ = color[1];
+		*num++ = color[2];
+		*num++ = color[3];
 
-		return num.i;
+		return sizeof(*num) * 4;
 	}
 }
 
+
 void R_VaoUnpackTangent(vec4_t v, uint32_t b)
 {
 	if (glRefConfig.packedNormalDataType == GL_INT_2_10_10_10_REV)
 	{
-		union pack10_u num;
+		union pack10_u *num = (union pack10_u *)&b;
 
-		num.i = 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; 
+		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;
-
-		num.i = b;
+		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] = 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; 
 	}
 }
 
@@ -126,23 +167,19 @@ void R_VaoUnpackNormal(vec3_t v, uint32_t b)
 {
 	if (glRefConfig.packedNormalDataType == GL_INT_2_10_10_10_REV)
 	{
-		union pack10_u num;
+		union pack10_u *num = (union pack10_u *)&b;
 
-		num.i = b;
-
-		v[0] = num.pack.x / 511.0f;
-		v[1] = num.pack.y / 511.0f;
-		v[2] = num.pack.z / 511.0f;
+		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;
-
-		num.i = b;
+		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] = num->pack.x / 127.0f;
+		v[1] = num->pack.y / 127.0f;
+		v[2] = num->pack.z / 127.0f;
 	}
 }
 
@@ -312,9 +349,9 @@ vao_t *R_CreateVao2(const char *name, int numVertexes, srfVert_t *verts, int num
 	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_TEXCOORD      ].type = GL_FLOAT;
-	vao->attribs[ATTR_INDEX_LIGHTCOORD    ].type = GL_FLOAT;
-	vao->attribs[ATTR_INDEX_COLOR         ].type = GL_FLOAT;
+	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_POSITION      ].normalized = GL_FALSE;
@@ -330,9 +367,9 @@ vao_t *R_CreateVao2(const char *name, int numVertexes, srfVert_t *verts, int num
 #ifdef USE_VERT_TANGENT_SPACE
 	vao->attribs[ATTR_INDEX_TANGENT       ].offset = dataSize; dataSize += sizeof(uint32_t);
 #endif
-	vao->attribs[ATTR_INDEX_TEXCOORD      ].offset = dataSize; dataSize += sizeof(verts[0].st);
-	vao->attribs[ATTR_INDEX_LIGHTCOORD    ].offset = dataSize; dataSize += sizeof(verts[0].lightmap);
-	vao->attribs[ATTR_INDEX_COLOR         ].offset = dataSize; dataSize += sizeof(verts[0].vertexColors);
+	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_POSITION      ].stride = dataSize;
@@ -358,40 +395,29 @@ vao_t *R_CreateVao2(const char *name, int numVertexes, srfVert_t *verts, int num
 
 	for (i = 0; i < numVertexes; i++)
 	{
-		uint32_t *p;
-
 		// xyz
 		memcpy(data + dataOfs, &verts[i].xyz, sizeof(verts[i].xyz));
 		dataOfs += sizeof(verts[i].xyz);
 
 		// normal
-		p = (uint32_t *)(data + dataOfs);
-		*p = R_VaoPackNormal(verts[i].normal);
-		dataOfs += sizeof(uint32_t);
+		dataOfs += R_VaoPackNormal(data + dataOfs, verts[i].normal);
 
 #ifdef USE_VERT_TANGENT_SPACE
 		// tangent
-		p = (uint32_t *)(data + dataOfs);
-		*p = R_VaoPackTangent(verts[i].tangent);
-		dataOfs += sizeof(uint32_t);
+		dataOfs += R_VaoPackTangent(data + dataOfs, verts[i].tangent);
 #endif
 
-		// vertex texcoords
-		memcpy(data + dataOfs, &verts[i].st, sizeof(verts[i].st));
-		dataOfs += sizeof(verts[i].st);
+		// texcoords
+		dataOfs += R_VaoPackTexCoord(data + dataOfs, verts[i].st);
 
-		// feed vertex lightmap texcoords
-		memcpy(data + dataOfs, &verts[i].lightmap, sizeof(verts[i].lightmap));
-		dataOfs += sizeof(verts[i].lightmap);
+		// lightmap texcoords
+		dataOfs += R_VaoPackTexCoord(data + dataOfs, verts[i].lightmap);
 
-		// feed vertex colors
-		memcpy(data + dataOfs, &verts[i].vertexColors, sizeof(verts[i].vertexColors));
-		dataOfs += sizeof(verts[i].vertexColors);
+		// colors
+		dataOfs += R_VaoPackColors(data + dataOfs, verts[i].vertexColors);
 
-		// feed vertex light directions
-		p = (uint32_t *)(data + dataOfs);
-		*p = R_VaoPackNormal(verts[i].lightdir);
-		dataOfs += sizeof(uint32_t);
+		// light directions
+		dataOfs += R_VaoPackNormal(data + dataOfs, verts[i].lightdir);
 	}
 
 	vao->vertexesSize = dataSize;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/iortcw.git



More information about the Pkg-games-commits mailing list