Support for texgen planes

This commit is contained in:
Jannik Vogel 2015-07-27 20:18:04 +02:00
parent 6655d711eb
commit d2fa51bb82
2 changed files with 95 additions and 53 deletions

View File

@ -825,6 +825,10 @@
# define NV097_SET_INVERSE_MODEL_VIEW_MATRIX 0x00970580 # define NV097_SET_INVERSE_MODEL_VIEW_MATRIX 0x00970580
# define NV097_SET_COMPOSITE_MATRIX 0x00970680 # define NV097_SET_COMPOSITE_MATRIX 0x00970680
# define NV097_SET_TEXTURE_MATRIX 0x009706C0 # define NV097_SET_TEXTURE_MATRIX 0x009706C0
# define NV097_SET_TEXGEN_PLANE_S 0x00970840
# define NV097_SET_TEXGEN_PLANE_T 0x00970850
# define NV097_SET_TEXGEN_PLANE_R 0x00970860
# define NV097_SET_TEXGEN_PLANE_Q 0x00970870
# define NV097_SET_TEXGEN_VIEW_MODEL 0x009709CC # define NV097_SET_TEXGEN_VIEW_MODEL 0x009709CC
# define NV097_SET_TEXGEN_VIEW_MODEL_LOCAL_VIEWER 0 # define NV097_SET_TEXGEN_VIEW_MODEL_LOCAL_VIEWER 0
# define NV097_SET_TEXGEN_VIEW_MODEL_INFINITE_VIEWER 1 # define NV097_SET_TEXGEN_VIEW_MODEL_INFINITE_VIEWER 1
@ -1446,14 +1450,15 @@ typedef struct PGRAPHState {
float composite_matrix[16]; float composite_matrix[16];
/* FIXME: These are probably stored in the vshader consts */ /* FIXME: These are probably stored in the vshader consts */
bool texture_matrix_enable[4]; bool texture_matrix_enable[NV2A_MAX_TEXTURES];
float texture_matrix[4][16]; /* 4 stages with 4x4 matrix each */ float texture_matrix[NV2A_MAX_TEXTURES][16]; /* 4 stages with 4x4 matrix each */
float texture_plane[NV2A_MAX_TEXTURES][4][4]; /* 4 stages, 4 components + plane for each */
float projection_matrix[16]; float projection_matrix[16];
float inverse_model_view_matrix[4][16]; /* 4 weights with 4x4 matrix each */ 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 */ float model_view_matrix[4][16]; /* 4 weights with 4x4 matrix each */
/* FIXME: Move to NV_PGRAPH_BUMPMAT... */ /* FIXME: Move to NV_PGRAPH_BUMPMAT... */
float bump_env_matrix[3][4]; /* 4 stages with 2x2 matrix each */ float bump_env_matrix[NV2A_MAX_TEXTURES-1][4]; /* 3 allowed stages with 2x2 matrix each */
GloContext *gl_context; GloContext *gl_context;
GLuint gl_framebuffer; GLuint gl_framebuffer;
@ -2874,7 +2879,7 @@ static void pgraph_bind_shaders(PGRAPHState *pg)
} }
/* For each texture stage */ /* For each texture stage */
for (i = 0; i < 4; i++) { for (i = 0; i < NV2A_MAX_TEXTURES; i++) {
char name[32]; char name[32];
GLint loc; GLint loc;
@ -2910,6 +2915,16 @@ static void pgraph_bind_shaders(PGRAPHState *pg)
glUniformMatrix4fv(loc, 1, GL_FALSE, pg->texture_matrix[i]); glUniformMatrix4fv(loc, 1, GL_FALSE, pg->texture_matrix[i]);
} }
/* TexGen planes */
for(j = 0; j < 4; j++) {
char cSuffix = "STRQ"[j];
snprintf(name, sizeof(name), "texPlane%c%d", cSuffix, i);
loc = glGetUniformLocation(pg->shader_binding->gl_program, name);
if (loc != -1) {
glUniform4fv(loc, 1, pg->texture_plane[i][j]);
}
}
} }
/* For each vertex weight */ /* For each vertex weight */
@ -4240,6 +4255,15 @@ static void pgraph_method(NV2AState *d,
pg->texture_matrix[slot / 16][slot % 16] = *(float*)&parameter; pg->texture_matrix[slot / 16][slot % 16] = *(float*)&parameter;
break; break;
/* Handles NV097_SET_TEXGEN_PLANE_S,T,R,Q */
case NV097_SET_TEXGEN_PLANE_S ...
NV097_SET_TEXGEN_PLANE_S + 0xfc: {
slot = (class_method - NV097_SET_TEXGEN_PLANE_S) / 4;
unsigned int part = slot % 16;
pg->texture_plane[slot / 16][part / 4][part % 4] = *(float*)&parameter;
break;
}
case NV097_SET_TEXGEN_VIEW_MODEL: case NV097_SET_TEXGEN_VIEW_MODEL:
SET_MASK(pg->regs[NV_PGRAPH_CSV0_D], NV_PGRAPH_CSV0_D_TEXGEN_REF, SET_MASK(pg->regs[NV_PGRAPH_CSV0_D], NV_PGRAPH_CSV0_D_TEXGEN_REF,
parameter); parameter);

View File

@ -72,7 +72,43 @@ static QString* generate_geometry_shader(enum ShaderPrimitiveMode primitive_mode
return s; return s;
} }
static void pgraph_append_skinning_code(QString* str, bool mix,
unsigned int count, const char* type,
const char* output, const char* input,
const char* matrix, const char* swizzle)
{
if (count == 0) {
qstring_append_fmt(str, "%s %s = (%s * %s0).%s;\n",
type, output, input, matrix, swizzle);
} else {
qstring_append_fmt(str, "%s %s = %s(0.0);\n", type, output, type);
if (mix) {
/* Tweening */
if (count == 2) {
qstring_append_fmt(str,
"%s += mix((%s * %s1).%s,\n"
" (%s * %s0).%s, weight.x);\n",
output,
input, matrix, swizzle,
input, matrix, swizzle);
} else {
/* FIXME: Not sure how blend weights are calculated */
assert(false);
}
} else {
/* Individual matrices */
int i;
for (i = 0; i < count; i++) {
char c = "xyzw"[i];
qstring_append_fmt(str, "%s += (%s * %s%d * weight.%c).%s;\n",
output, input, matrix, i, c,
swizzle);
}
assert(false); /* FIXME: Untested */
}
}
}
static QString* generate_fixed_function(const ShaderState state, static QString* generate_fixed_function(const ShaderState state,
char out_prefix) char out_prefix)
@ -154,7 +190,7 @@ static QString* generate_fixed_function(const ShaderState state,
bool mix; bool mix;
switch (state.skinning) { switch (state.skinning) {
case SKINNING_OFF: case SKINNING_OFF:
count = 0; break; mix = false; count = 0; break;
case SKINNING_1WEIGHTS: case SKINNING_1WEIGHTS:
mix = true; count = 2; break; mix = true; count = 2; break;
case SKINNING_2WEIGHTS: case SKINNING_2WEIGHTS:
@ -173,37 +209,27 @@ static QString* generate_fixed_function(const ShaderState state,
} }
qstring_append_fmt(s, "/* Skinning mode %d */\n", qstring_append_fmt(s, "/* Skinning mode %d */\n",
state.skinning); state.skinning);
if (count == 0) {
qstring_append(s, "vec4 tPosition = position * modelViewMat0;\n"); pgraph_append_skinning_code(s, mix, count, "vec4",
/* FIXME: Is the normal still transformed? */ "tPosition", "position",
qstring_append(s, "vec3 tNormal = (vec4(normal, 0.0) * invModelViewMat0).xyz;\n"); "modelViewMat", "xyzw");
} else { pgraph_append_skinning_code(s, mix, count, "vec3",
qstring_append(s, "vec4 tPosition = vec4(0.0);\n"); "tNormal", "vec4(normal, 0.0)",
qstring_append(s, "vec3 tNormal = vec3(0.0);\n"); "invModelViewMat", "xyz");
if (mix) {
/* Tweening */ for(i = 0; i < 4 /* FIXME: NV2A_MAX_TEXTURES*/; i++) {
if (count == 2) { for(j = 0; j < 4; j++) {
qstring_append(s,
"tPosition += mix(position * modelViewMat1,\n" /* FIXME: Only do these if necessary */
" position * modelViewMat0, weight.x);\n"
"tNormal += mix((vec4(normal, 0.0) * invModelViewMat1).xyz,\n" char output[16];
" (vec4(normal, 0.0) * invModelViewMat0).xyz, weight.x);\n"); char input[16];
} else { char cSuffix = "STRQ"[j];
/* FIXME: Not sure how blend weights are calculated */ snprintf(output, sizeof(output), "tTexPlane%c%d", cSuffix, i);
assert(false); snprintf(input, sizeof(input), "texPlane%c%d", cSuffix, i);
} pgraph_append_skinning_code(s, mix, count,
} else { "vec4", output, input,
/* Individual matrices */ "invModelViewMat", "xyzw");
for (i = 0; i < count; i++) {
char c = "xyzw"[i];
qstring_append_fmt(s,
"tPosition += position * modelViewMat%d * weight.%c;\n",
i, c);
qstring_append_fmt(s,
"tNormal += (vec4(normal, 0.0) * invModelViewMat%d * weight.%c).xyz;\n",
i, c);
}
assert(false); /* FIXME: Untested */
} }
} }
@ -213,7 +239,7 @@ static QString* generate_fixed_function(const ShaderState state,
} }
/* Texgen */ /* Texgen */
for (i = 0; i < 4; i++) { for (i = 0; i < 4 /* NV2A_MAX_TEXTURES */; i++) {
qstring_append_fmt(s, "/* Texgen for stage %d */\n", qstring_append_fmt(s, "/* Texgen for stage %d */\n",
i); i);
qstring_append_fmt(s, "vec4 tTexture%d;\n", qstring_append_fmt(s, "vec4 tTexture%d;\n",
@ -221,24 +247,15 @@ static QString* generate_fixed_function(const ShaderState state,
/* Set each component individually */ /* Set each component individually */
/* FIXME: could be nicer if some channels share the same texgen */ /* FIXME: could be nicer if some channels share the same texgen */
for (j = 0; j < 4; j++) { for (j = 0; j < 4; j++) {
/* TODO: TexGen View Model missing! */
char c = "xyzw"[j]; char c = "xyzw"[j];
char cSuffix = "STRQ"[i]; char cSuffix = "STRQ"[j];
switch (state.texgen[i][j]) { switch (state.texgen[i][j]) {
case TEXGEN_DISABLE: case TEXGEN_DISABLE:
qstring_append_fmt(s, "tTexture%d.%c = texture%d.%c;\n", qstring_append_fmt(s, "tTexture%d.%c = texture%d.%c;\n",
i, c, i, c); i, c, i, c);
break; break;
case TEXGEN_EYE_LINEAR: case TEXGEN_EYE_LINEAR:
/* FIXME: This might not have to be done? {
* FIXME: calculate tTexPlane[STRQ][0-3] - I guess this happens skinned?
* tTexPlane[STRQ][0-3] = texPlane[STRQ][0-3] * invModelViewMat[%d or 0?!] probably
* }
*/
qstring_append_fmt(s, "vec4 tTexPlane%c%d = texPlane%c%d * invModelViewMat0;\n",
cSuffix, i, cSuffix, i);
qstring_append_fmt(s, "tTexture%d.%c = dot(tTexPlane%c%d, tPosition);\n", qstring_append_fmt(s, "tTexture%d.%c = dot(tTexPlane%c%d, tPosition);\n",
i, c, cSuffix, i); i, c, cSuffix, i);
break; break;
@ -254,11 +271,12 @@ static QString* generate_fixed_function(const ShaderState state,
//FIXME: tNormal before or after normalization? Always normalize? //FIXME: tNormal before or after normalization? Always normalize?
qstring_append(s, " vec3 r = reflect(u, tNormal);\n"); qstring_append(s, " vec3 r = reflect(u, tNormal);\n");
/* FIXME: This would consume 1 division fewer and *might* be faster than length: /* FIXME: This would consume 1 division fewer and *might* be
* // [z=1/(2*x) => z=1/x*0.5] * faster than `length`:
* vec3 ro = r + vec3(0.0, 0.0, 1.0); * // [z=1/(2*x) => z=1/x*0.5]
* float m = inversesqrt(dot(ro,ro))*0.5; * vec3 ro = r + vec3(0.0, 0.0, 1.0);
*/ * float m = inversesqrt(dot(ro,ro))*0.5;
*/
qstring_append(s, " float invM = 1.0 / (2.0 * length(r + vec3(0.0, 0.0, 1.0)));\n"); qstring_append(s, " float invM = 1.0 / (2.0 * length(r + vec3(0.0, 0.0, 1.0)));\n");
qstring_append_fmt(s, " tTexture%d.%c = r.%c * invM + 0.5;\n", qstring_append_fmt(s, " tTexture%d.%c = r.%c * invM + 0.5;\n",