Merge pull request #35 from JayFoxRox/fog-rebased

Fog
This commit is contained in:
espes 2015-08-20 11:54:55 +10:00
commit 61789be0c4
7 changed files with 312 additions and 9 deletions

View File

@ -261,9 +261,19 @@
# define NV_PGRAPH_CHANNEL_CTX_TRIGGER_WRITE_OUT (1 << 1)
#define NV_PGRAPH_CSV0_D 0x00000FB4
# define NV_PGRAPH_CSV0_D_RANGE_MODE (1 << 18)
# define NV_PGRAPH_CSV0_D_FOGENABLE (1 << 19)
# define NV_PGRAPH_CSV0_D_TEXGEN_REF (1 << 20)
# define NV_PGRAPH_CSV0_D_TEXGEN_REF_LOCAL_VIEWER 0
# define NV_PGRAPH_CSV0_D_TEXGEN_REF_INFINITE_VIEWER 1
# define NV_PGRAPH_CSV0_D_FOG_MODE (1 << 21)
# define NV_PGRAPH_CSV0_D_FOG_MODE_LINEAR 0
# define NV_PGRAPH_CSV0_D_FOG_MODE_EXP 1
# define NV_PGRAPH_CSV0_D_FOGGENMODE 0x01C00000
# define NV_PGRAPH_CSV0_D_FOGGENMODE_SPEC_ALPHA 0
# define NV_PGRAPH_CSV0_D_FOGGENMODE_RADIAL 1
# define NV_PGRAPH_CSV0_D_FOGGENMODE_PLANAR 2
# define NV_PGRAPH_CSV0_D_FOGGENMODE_ABS_PLANAR 3
# define NV_PGRAPH_CSV0_D_FOGGENMODE_FOG_X 4
# define NV_PGRAPH_CSV0_D_MODE 0xC0000000
# define NV_PGRAPH_CSV0_D_SKIN 0x1C000000
# define NV_PGRAPH_CSV0_D_SKIN_OFF 0
@ -405,6 +415,22 @@
# define NV_PGRAPH_CONTROL_2_STENCIL_OP_V_INVERT 6
# define NV_PGRAPH_CONTROL_2_STENCIL_OP_V_INCR 7
# define NV_PGRAPH_CONTROL_2_STENCIL_OP_V_DECR 8
#define NV_PGRAPH_CONTROL_3 0x00001958
# define NV_PGRAPH_CONTROL_3_FOGENABLE (1 << 8)
# define NV_PGRAPH_CONTROL_3_FOG_MODE 0x00070000
# define NV_PGRAPH_CONTROL_3_FOG_MODE_LINEAR 0
# define NV_PGRAPH_CONTROL_3_FOG_MODE_EXP 1
# define NV_PGRAPH_CONTROL_3_FOG_MODE_EXP2 3
# define NV_PGRAPH_CONTROL_3_FOG_MODE_EXP_ABS 5
# define NV_PGRAPH_CONTROL_3_FOG_MODE_EXP2_ABS 7
# define NV_PGRAPH_CONTROL_3_FOG_MODE_LINEAR_ABS 4
#define NV_PGRAPH_FOGCOLOR 0x00001980
# define NV_PGRAPH_FOGCOLOR_RED 0x00FF0000
# define NV_PGRAPH_FOGCOLOR_GREEN 0x0000FF00
# define NV_PGRAPH_FOGCOLOR_BLUE 0x000000FF
# define NV_PGRAPH_FOGCOLOR_ALPHA 0xFF000000
#define NV_PGRAPH_FOGPARAM0 0x00001984
#define NV_PGRAPH_FOGPARAM1 0x00001988
#define NV_PGRAPH_SETUPRASTER 0x00001990
# define NV_PGRAPH_SETUPRASTER_FRONTFACEMODE 0x00000003
# define NV_PGRAPH_SETUPRASTER_FRONTFACEMODE_FILL 0
@ -716,6 +742,25 @@
# define NV097_SET_CONTROL0 0x00970290
# define NV097_SET_CONTROL0_STENCIL_WRITE_ENABLE (1 << 0)
# define NV097_SET_CONTROL0_Z_FORMAT (1 << 12)
# define NV097_SET_FOG_MODE 0x0097029C
# define NV097_SET_FOG_MODE_V_LINEAR 0x2601
# define NV097_SET_FOG_MODE_V_EXP 0x800
# define NV097_SET_FOG_MODE_V_EXP2 0x801
# define NV097_SET_FOG_MODE_V_EXP_ABS 0x802
# define NV097_SET_FOG_MODE_V_EXP2_ABS 0x803
# define NV097_SET_FOG_MODE_V_LINEAR_ABS 0x804
# define NV097_SET_FOG_GEN_MODE 0x009702A0
# define NV097_SET_FOG_GEN_MODE_V_SPEC_ALPHA 0
# define NV097_SET_FOG_GEN_MODE_V_RADIAL 1
# define NV097_SET_FOG_GEN_MODE_V_PLANAR 2
# define NV097_SET_FOG_GEN_MODE_V_ABS_PLANAR 3
# define NV097_SET_FOG_GEN_MODE_V_FOG_X 6
# define NV097_SET_FOG_ENABLE 0x009702A4
# define NV097_SET_FOG_COLOR 0x009702A8
# define NV097_SET_FOG_COLOR_RED 0x000000FF
# define NV097_SET_FOG_COLOR_GREEN 0x0000FF00
# define NV097_SET_FOG_COLOR_BLUE 0x00FF0000
# define NV097_SET_FOG_COLOR_ALPHA 0xFF000000
# define NV097_SET_ALPHA_TEST_ENABLE 0x00970300
# define NV097_SET_BLEND_ENABLE 0x00970304
# define NV097_SET_CULL_FACE_ENABLE 0x00970308
@ -825,9 +870,11 @@
# define NV097_SET_INVERSE_MODEL_VIEW_MATRIX 0x00970580
# define NV097_SET_COMPOSITE_MATRIX 0x00970680
# define NV097_SET_TEXTURE_MATRIX 0x009706C0
# define NV097_SET_FOG_PARAMS 0x009709C0
# define NV097_SET_TEXGEN_VIEW_MODEL 0x009709CC
# define NV097_SET_TEXGEN_VIEW_MODEL_LOCAL_VIEWER 0
# define NV097_SET_TEXGEN_VIEW_MODEL_INFINITE_VIEWER 1
# define NV097_SET_FOG_PLANE 0x009709D0
# define NV097_SET_VIEWPORT_OFFSET 0x00970A20
# define NV097_SET_COMBINER_FACTOR0 0x00970A60
# define NV097_SET_COMBINER_FACTOR1 0x00970A80
@ -1452,6 +1499,9 @@ typedef struct PGRAPHState {
float inverse_model_view_matrix[4][16]; /* 4 weights with 4x4 matrix each */
float model_view_matrix[4][16]; /* 4 weights with 4x4 matrix each */
/* FIXME: Also in vshader consts? */
float fog_plane[4];
/* FIXME: Move to NV_PGRAPH_BUMPMAT... */
float bump_env_matrix[3][4]; /* 4 stages with 2x2 matrix each */
@ -2788,6 +2838,21 @@ static void pgraph_bind_shaders(PGRAPHState *pg)
}
}
/* Fog */
state.fog_enable = pg->regs[NV_PGRAPH_CONTROL_3]
& NV_PGRAPH_CONTROL_3_FOGENABLE;
if (state.fog_enable) {
/*FIXME: Use CSV0_D? */
state.fog_mode = GET_MASK(pg->regs[NV_PGRAPH_CONTROL_3],
NV_PGRAPH_CONTROL_3_FOG_MODE);
state.foggen = GET_MASK(pg->regs[NV_PGRAPH_CSV0_D],
NV_PGRAPH_CSV0_D_FOGGENMODE);
} else {
/* FIXME: Do we still pass the fogmode? */
state.fog_mode = 0;
state.foggen = 0;
}
/* Texture matrices */
for (i = 0; i < 4; i++) {
state.texture_matrix_enable[i] = pg->texture_matrix_enable[i];
@ -2912,6 +2977,39 @@ static void pgraph_bind_shaders(PGRAPHState *pg)
}
/* Fog */
{
GLint loc;
uint32_t fog_color = pg->regs[NV_PGRAPH_FOGCOLOR];
loc = glGetUniformLocation(pg->shader_binding->gl_program, "fogColor");
if (loc != -1) {
glUniform4f(loc,
GET_MASK(fog_color, NV_PGRAPH_FOGCOLOR_RED) / 255.0,
GET_MASK(fog_color, NV_PGRAPH_FOGCOLOR_GREEN) / 255.0,
GET_MASK(fog_color, NV_PGRAPH_FOGCOLOR_BLUE) / 255.0,
GET_MASK(fog_color, NV_PGRAPH_FOGCOLOR_ALPHA) / 255.0);
}
/* FIXME: PGRAPH regs have a 16 byte stride in emulation! can't just
* upload this as an array =(
*/
loc = glGetUniformLocation(pg->shader_binding->gl_program,
"fogParam[0]");
if (loc != -1) {
glUniform1f(loc, *(float*)&pg->regs[NV_PGRAPH_FOGPARAM0]);
}
loc = glGetUniformLocation(pg->shader_binding->gl_program,
"fogParam[1]");
if (loc != -1) {
glUniform1f(loc, *(float*)&pg->regs[NV_PGRAPH_FOGPARAM1]);
}
loc = glGetUniformLocation(pg->shader_binding->gl_program, "fogPlane");
if (loc != -1) {
glUniform4fv(loc, 1, pg->fog_plane);
}
}
/* For each vertex weight */
for (i = 0; i < 4; i++) {
char name[32];
@ -3907,6 +4005,71 @@ static void pgraph_method(NV2AState *d,
break;
}
case NV097_SET_FOG_MODE: {
/* FIXME: There is also NV_PGRAPH_CSV0_D_FOG_MODE */
unsigned int mode;
switch (parameter) {
case NV097_SET_FOG_MODE_V_LINEAR:
mode = NV_PGRAPH_CONTROL_3_FOG_MODE_LINEAR; break;
case NV097_SET_FOG_MODE_V_EXP:
mode = NV_PGRAPH_CONTROL_3_FOG_MODE_EXP; break;
case NV097_SET_FOG_MODE_V_EXP2:
mode = NV_PGRAPH_CONTROL_3_FOG_MODE_EXP2; break;
case NV097_SET_FOG_MODE_V_EXP_ABS:
mode = NV_PGRAPH_CONTROL_3_FOG_MODE_EXP_ABS; break;
case NV097_SET_FOG_MODE_V_EXP2_ABS:
mode = NV_PGRAPH_CONTROL_3_FOG_MODE_EXP2_ABS; break;
case NV097_SET_FOG_MODE_V_LINEAR_ABS:
mode = NV_PGRAPH_CONTROL_3_FOG_MODE_LINEAR_ABS; break;
default:
assert(false);
break;
}
SET_MASK(pg->regs[NV_PGRAPH_CONTROL_3], NV_PGRAPH_CONTROL_3_FOG_MODE,
mode);
break;
}
case NV097_SET_FOG_GEN_MODE: {
unsigned int mode;
switch (parameter) {
case NV097_SET_FOG_GEN_MODE_V_SPEC_ALPHA:
mode = NV_PGRAPH_CSV0_D_FOGGENMODE_SPEC_ALPHA; break;
case NV097_SET_FOG_GEN_MODE_V_RADIAL:
mode = NV_PGRAPH_CSV0_D_FOGGENMODE_RADIAL; break;
case NV097_SET_FOG_GEN_MODE_V_PLANAR:
mode = NV_PGRAPH_CSV0_D_FOGGENMODE_PLANAR; break;
case NV097_SET_FOG_GEN_MODE_V_ABS_PLANAR:
mode = NV_PGRAPH_CSV0_D_FOGGENMODE_ABS_PLANAR; break;
case NV097_SET_FOG_GEN_MODE_V_FOG_X:
mode = NV_PGRAPH_CSV0_D_FOGGENMODE_FOG_X; break;
default:
assert(false);
break;
}
SET_MASK(pg->regs[NV_PGRAPH_CSV0_D], NV_PGRAPH_CSV0_D_FOGGENMODE, mode);
break;
}
case NV097_SET_FOG_ENABLE:
/*
FIXME: There is also:
SET_MASK(pg->regs[NV_PGRAPH_CSV0_D], NV_PGRAPH_CSV0_D_FOGENABLE,
parameter);
*/
SET_MASK(pg->regs[NV_PGRAPH_CONTROL_3], NV_PGRAPH_CONTROL_3_FOGENABLE,
parameter);
break;
case NV097_SET_FOG_COLOR: {
/* PGRAPH channels are ARGB, parameter channels are ABGR */
uint8_t red = GET_MASK(parameter, NV097_SET_FOG_COLOR_RED);
uint8_t green = GET_MASK(parameter, NV097_SET_FOG_COLOR_GREEN);
uint8_t blue = GET_MASK(parameter, NV097_SET_FOG_COLOR_BLUE);
uint8_t alpha = GET_MASK(parameter, NV097_SET_FOG_COLOR_ALPHA);
SET_MASK(pg->regs[NV_PGRAPH_FOGCOLOR], NV_PGRAPH_FOGCOLOR_RED, red);
SET_MASK(pg->regs[NV_PGRAPH_FOGCOLOR], NV_PGRAPH_FOGCOLOR_GREEN, green);
SET_MASK(pg->regs[NV_PGRAPH_FOGCOLOR], NV_PGRAPH_FOGCOLOR_BLUE, blue);
SET_MASK(pg->regs[NV_PGRAPH_FOGCOLOR], NV_PGRAPH_FOGCOLOR_ALPHA, alpha);
break;
}
case NV097_SET_ALPHA_TEST_ENABLE:
SET_MASK(pg->regs[NV_PGRAPH_CONTROL_0],
NV_PGRAPH_CONTROL_0_ALPHATESTENABLE, parameter);
@ -4240,11 +4403,26 @@ static void pgraph_method(NV2AState *d,
pg->texture_matrix[slot / 16][slot % 16] = *(float*)&parameter;
break;
case NV097_SET_FOG_PARAMS ...
NV097_SET_FOG_PARAMS + 8:
slot = (class_method - NV097_SET_FOG_PARAMS) / 4;
if (slot < 2) {
pg->regs[NV_PGRAPH_FOGPARAM0 + slot*4] = parameter;
} else {
/* FIXME: No idea where slot = 2 is */
}
break;
case NV097_SET_TEXGEN_VIEW_MODEL:
SET_MASK(pg->regs[NV_PGRAPH_CSV0_D], NV_PGRAPH_CSV0_D_TEXGEN_REF,
parameter);
break;
case NV097_SET_FOG_PLANE ...
NV097_SET_FOG_PLANE + 12:
slot = (class_method - NV097_SET_FOG_PLANE) / 4;
pg->fog_plane[slot] = *(float*)&parameter;
break;
case NV097_SET_VIEWPORT_OFFSET ...
NV097_SET_VIEWPORT_OFFSET + 12:
@ -6657,7 +6835,7 @@ static void pgraph_method_log(unsigned int subchannel,
static unsigned int last = 0;
static unsigned int count = 0;
if (last == 0x1800 && method != last) {
NV2A_DPRINTF("pgraph method (%d) 0x%x * %d",
NV2A_GL_DPRINTF(true, "pgraph method (%d) 0x%x * %d",
subchannel, last, count);
}
if (method != 0x1800) {

View File

@ -280,9 +280,8 @@ static QString* get_var(struct PixelShader *ps, int reg, bool is_dest)
return qstring_from_str("c_0_1");
}
break;
case PS_REGISTER_FOG: // TODO
//return qstring_from_str("fog");
return qstring_from_str("vec4(1.0)");
case PS_REGISTER_FOG:
return qstring_from_str("pFog");
case PS_REGISTER_V0:
return qstring_from_str("v0");
case PS_REGISTER_V1:
@ -540,6 +539,7 @@ static QString* psh_convert(struct PixelShader *ps)
qstring_append(preflight, "\n");
qstring_append(preflight, "out vec4 fragColor;\n");
qstring_append(preflight, "\n");
qstring_append(preflight, "uniform vec4 fogColor;\n");
/* calculate perspective-correct inputs */
QString *vars = qstring_new();
@ -547,7 +547,7 @@ static QString* psh_convert(struct PixelShader *ps)
qstring_append(vars, "vec4 pD1 = vtx.D1 / vtx.inv_w;\n");
qstring_append(vars, "vec4 pB0 = vtx.B0 / vtx.inv_w;\n");
qstring_append(vars, "vec4 pB1 = vtx.B1 / vtx.inv_w;\n");
qstring_append(vars, "vec4 pFog = vtx.Fog / vtx.inv_w;\n");
qstring_append(vars, "vec4 pFog = vec4(fogColor.rgb, clamp(vtx.Fog / vtx.inv_w, 0.0, 1.0));\n");
qstring_append(vars, "vec4 pT0 = vtx.T0 / vtx.inv_w;\n");
qstring_append(vars, "vec4 pT1 = vtx.T1 / vtx.inv_w;\n");
qstring_append(vars, "vec4 pT2 = vtx.T2 / vtx.inv_w;\n");
@ -555,7 +555,6 @@ static QString* psh_convert(struct PixelShader *ps)
qstring_append(vars, "\n");
qstring_append(vars, "vec4 v0 = pD0;\n");
qstring_append(vars, "vec4 v1 = pD1;\n");
qstring_append(vars, "float fog = pFog.x;\n");
ps->code = qstring_new();

View File

@ -115,6 +115,9 @@ static QString* generate_fixed_function(const ShaderState state,
qstring_append(s,
"\n"
/* FIXME: Add these uniforms using code when they are used */
"uniform vec4 fogColor;\n"
"uniform vec4 fogPlane;\n"
"uniform float fogParam[2];\n"
"uniform mat4 texMat0;\n"
"uniform mat4 texMat1;\n"
"uniform mat4 texMat2;\n"
@ -255,6 +258,103 @@ static QString* generate_fixed_function(const ShaderState state,
}
}
/* Fog */
if (state.fog_enable) {
/* From: https://www.opengl.org/registry/specs/NV/fog_distance.txt */
switch(state.foggen) {
case FOGGEN_SPEC_ALPHA:
assert(false); /* FIXME: Do this before or after calculations in VSH? */
if (state.fixed_function) {
/* FIXME: Do we have to clamp here? */
qstring_append(s, "float fogDistance = clamp(specular.a, 0.0, 1.0);\n");
} else if (state.vertex_program) {
qstring_append(s, "float fogDistance = oD1.a;\n");
} else {
assert(false);
}
break;
case FOGGEN_RADIAL:
qstring_append(s, "float fogDistance = length(tPosition.xyz)");
break;
case FOGGEN_PLANAR:
case FOGGEN_ABS_PLANAR:
qstring_append(s, "float fogDistance = dot(fogPlane.xyz, tPosition.xyz) + fogPlane.w;\n");
if (state.foggen == FOGGEN_ABS_PLANAR) {
qstring_append(s, "fogDistance = abs(fogDistance);\n");
}
break;
case FOGGEN_FOG_X:
if (state.fixed_function) {
qstring_append(s, "float fogDistance = fogCoord;\n");
} else if (state.vertex_program) {
qstring_append(s, "float fogDistance = oFog.x;\n");
} else {
assert(false);
}
break;
default:
assert(false);
break;
}
//FIXME: Do this per pixel?
switch (state.fog_mode) {
case FOG_MODE_LINEAR:
case FOG_MODE_LINEAR_ABS:
/* f = (end - d) / (end - start)
* fogParam[1] = 1 / (end - start)
* fogParam[0] = 1 + end * fogParam[1];
*/
qstring_append(s, "float fogFactor = fogParam[0] + fogDistance * fogParam[1];\n");
qstring_append(s, "fogFactor -= 1.0;\n"); /* FIXME: WHHYYY?!! */
break;
case FOG_MODE_EXP:
case FOG_MODE_EXP_ABS:
/* f = 1 / (e^(d * density))
* fogParam[1] = -density / (2 * ln(256))
* fogParam[0] = 1.5
*/
qstring_append(s, "float fogFactor = fogParam[0] + exp2(fogDistance * fogParam[1] * 16.0);\n");
qstring_append(s, "fogFactor -= 1.5;\n"); /* FIXME: WHHYYY?!! */
break;
case FOG_MODE_EXP2:
case FOG_MODE_EXP2_ABS:
/* f = 1 / (e^((d * density)^2))
* fogParam[1] = -density / (2 * sqrt(ln(256)))
* fogParam[0] = 1.5
*/
qstring_append(s, "float fogFactor = fogParam[0] + exp2(-fogDistance * fogDistance * fogParam[1] * fogParam[1] * 32.0);\n");
qstring_append(s, "fogFactor -= 1.5;\n"); /* FIXME: WHHYYY?!! */
break;
default:
assert(false);
break;
}
/* Calculate absolute for the modes which need it */
switch (state.fog_mode) {
case FOG_MODE_LINEAR_ABS:
case FOG_MODE_EXP_ABS:
case FOG_MODE_EXP2_ABS:
qstring_append(s, "fogFactor = abs(fogFactor);\n");
break;
default:
break;
}
/* FIXME: What about fog alpha?! */
qstring_append(s, "float tFog = fogFactor;\n");
} else {
/* FIXME: Is the fog still calculated / passed somehow?!
*/
qstring_append(s, "float tFog = 0.0;\n");
}
/* If skinning is off the composite matrix already includes the MV matrix */
if (state.skinning == SKINNING_OFF) {
qstring_append(s, "tPosition = position;\n");
@ -273,7 +373,7 @@ static QString* generate_fixed_function(const ShaderState state,
qstring_append(s, "vtx.D1 = specular * vtx.inv_w;\n");
qstring_append(s, "vtx.B0 = backDiffuse * vtx.inv_w;\n");
qstring_append(s, "vtx.B1 = backSpecular * vtx.inv_w;\n");
qstring_append(s, "vtx.Fog = vec4(0.0,0.0,0.0,1.0) * vtx.inv_w;\n");
qstring_append(s, "vtx.Fog = tFog * vtx.inv_w;\n");
qstring_append(s, "vtx.T0 = tTexture0 * vtx.inv_w;\n");
qstring_append(s, "vtx.T1 = tTexture1 * vtx.inv_w;\n");
qstring_append(s, "vtx.T2 = tTexture2 * vtx.inv_w;\n");

View File

@ -65,6 +65,10 @@ typedef struct ShaderState {
bool texture_matrix_enable[4];
enum VshTexgen texgen[4][4];
bool fog_enable;
enum VshFoggen foggen;
enum VshFogMode fog_mode;
enum VshSkinning skinning;
bool normalization;

View File

@ -27,7 +27,7 @@
" vec4 D1;\n" \
" vec4 B0;\n" \
" vec4 B1;\n" \
" vec4 Fog;\n" \
" float Fog;\n" \
" vec4 T0;\n" \
" vec4 T1;\n" \
" vec4 T2;\n" \

View File

@ -737,6 +737,7 @@ QString* vsh_translate(uint16_t version,
qstring_append(header, STRUCT_VERTEX_DATA);
qstring_append_fmt(header, "noperspective out VertexData %c_vtx;\n", out_prefix);
qstring_append_fmt(header, "#define vtx %c_vtx", out_prefix);
qstring_append(header, "\n"
"uniform mat4 texMat0;\n"
"uniform mat4 texMat1;\n"
@ -780,7 +781,7 @@ QString* vsh_translate(uint16_t version,
qstring_append(body, "vtx.D1 = clamp(oD1, 0.0, 1.0) * vtx.inv_w;\n");
qstring_append(body, "vtx.B0 = clamp(oB0, 0.0, 1.0) * vtx.inv_w;\n");
qstring_append(body, "vtx.B1 = clamp(oB1, 0.0, 1.0) * vtx.inv_w;\n");
qstring_append(body, "vtx.Fog = oFog * vtx.inv_w;\n");
qstring_append(body, "vtx.Fog = oFog.x * vtx.inv_w;\n");
qstring_append(body, "vtx.T0 = oT0 * vtx.inv_w;\n");
qstring_append(body, "vtx.T1 = oT1 * vtx.inv_w;\n");
qstring_append(body, "vtx.T2 = oT2 * vtx.inv_w;\n");

View File

@ -33,6 +33,27 @@ enum VshTexgen {
TEXGEN_REFLECTION_MAP,
};
enum VshFogMode {
FOG_MODE_LINEAR,
FOG_MODE_EXP,
FOG_MODE_ERROR2, /* Doesn't exist */
FOG_MODE_EXP2,
FOG_MODE_LINEAR_ABS,
FOG_MODE_EXP_ABS,
FOG_MODE_ERROR6, /* Doesn't exist */
FOG_MODE_EXP2_ABS
};
enum VshFoggen {
FOGGEN_SPEC_ALPHA,
FOGGEN_RADIAL,
FOGGEN_PLANAR,
FOGGEN_ABS_PLANAR,
FOGGEN_ERROR4,
FOGGEN_ERROR5,
FOGGEN_FOG_X
};
enum VshSkinning {
SKINNING_OFF,
SKINNING_1WEIGHTS,