mirror of https://github.com/xemu-project/xemu.git
Unify VP/FFP and fog for VP
This commit is contained in:
parent
28347fe179
commit
3f1b18378f
|
@ -226,17 +226,13 @@ static void append_skinning_code(QString* str, bool mix,
|
|||
}
|
||||
}
|
||||
|
||||
static QString* generate_fixed_function(const ShaderState state,
|
||||
char out_prefix)
|
||||
static void generate_fixed_function(const ShaderState state,
|
||||
QString *header, QString *body)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
/* generate vertex shader mimicking fixed function */
|
||||
QString* h = qstring_new();
|
||||
QString* s = qstring_new();
|
||||
qstring_append(h,
|
||||
"#version 330\n"
|
||||
"\n"
|
||||
qstring_append(header,
|
||||
"#define position v0\n"
|
||||
"#define weight v1\n"
|
||||
"#define normal v2.xyz\n"
|
||||
|
@ -255,22 +251,8 @@ static QString* generate_fixed_function(const ShaderState state,
|
|||
"#define reserved3 v15\n"
|
||||
"\n");
|
||||
|
||||
for(i = 0; i < 16; i++) {
|
||||
qstring_append_fmt(h, "in vec4 v%d;\n", i);
|
||||
}
|
||||
|
||||
qstring_append(h, "\n"
|
||||
STRUCT_VERTEX_DATA);
|
||||
qstring_append_fmt(h, "noperspective out VertexData %c_vtx;\n", out_prefix);
|
||||
qstring_append_fmt(h, "#define vtx %c_vtx", out_prefix);
|
||||
|
||||
|
||||
qstring_append(h,
|
||||
"\n"
|
||||
qstring_append(header,
|
||||
/* FIXME: Add these uniforms using code when they are used */
|
||||
"uniform vec4 fogColor;\n"
|
||||
"uniform vec4 fogPlane;\n"
|
||||
"uniform float fogParam[2];\n"
|
||||
"uniform vec4 texPlaneS0;\n"
|
||||
"uniform vec4 texPlaneT0;\n"
|
||||
"uniform vec4 texPlaneQ0;\n"
|
||||
|
@ -326,26 +308,24 @@ static QString* generate_fixed_function(const ShaderState state,
|
|||
assert(false);
|
||||
break;
|
||||
}
|
||||
qstring_append_fmt(s, "/* Skinning mode %d */\n",
|
||||
qstring_append_fmt(body, "/* Skinning mode %d */\n",
|
||||
state.skinning);
|
||||
|
||||
append_skinning_code(s, mix, count, "vec4",
|
||||
append_skinning_code(body, mix, count, "vec4",
|
||||
"tPosition", "position",
|
||||
"modelViewMat", "xyzw");
|
||||
append_skinning_code(s, mix, count, "vec3",
|
||||
append_skinning_code(body, mix, count, "vec3",
|
||||
"tNormal", "vec4(normal, 0.0)",
|
||||
"invModelViewMat", "xyz");
|
||||
|
||||
/* Normalization */
|
||||
if (state.normalization) {
|
||||
qstring_append(s, "tNormal = normalize(tNormal);\n");
|
||||
qstring_append(body, "tNormal = normalize(tNormal);\n");
|
||||
}
|
||||
|
||||
/* Texgen */
|
||||
for (i = 0; i < 4 /* FIXME: NV2A_MAX_TEXTURES */; i++) {
|
||||
qstring_append_fmt(s, "/* Texgen for stage %d */\n",
|
||||
i);
|
||||
qstring_append_fmt(s, "vec4 tTexture%d;\n",
|
||||
qstring_append_fmt(body, "/* Texgen for stage %d */\n",
|
||||
i);
|
||||
/* Set each component individually */
|
||||
/* FIXME: could be nicer if some channels share the same texgen */
|
||||
|
@ -355,25 +335,25 @@ static QString* generate_fixed_function(const ShaderState state,
|
|||
char cSuffix = "STRQ"[j];
|
||||
switch (state.texgen[i][j]) {
|
||||
case TEXGEN_DISABLE:
|
||||
qstring_append_fmt(s, "tTexture%d.%c = texture%d.%c;\n",
|
||||
qstring_append_fmt(body, "oT%d.%c = texture%d.%c;\n",
|
||||
i, c, i, c);
|
||||
break;
|
||||
case TEXGEN_EYE_LINEAR:
|
||||
qstring_append_fmt(s, "tTexture%d.%c = dot(texPlane%c%d, tPosition);\n",
|
||||
qstring_append_fmt(body, "oT%d.%c = dot(texPlane%c%d, tPosition);\n",
|
||||
i, c, cSuffix, i);
|
||||
break;
|
||||
case TEXGEN_OBJECT_LINEAR:
|
||||
qstring_append_fmt(s, "tTexture%d.%c = dot(texPlane%c%d, position);\n",
|
||||
qstring_append_fmt(body, "oT%d.%c = dot(texPlane%c%d, position);\n",
|
||||
i, c, cSuffix, i);
|
||||
assert(false); /* Untested */
|
||||
break;
|
||||
case TEXGEN_SPHERE_MAP:
|
||||
assert(i < 2); /* Channels S,T only! */
|
||||
qstring_append(s, "{\n");
|
||||
qstring_append(body, "{\n");
|
||||
/* FIXME: u, r and m only have to be calculated once */
|
||||
qstring_append(s, " vec3 u = normalize(tPosition.xyz);\n");
|
||||
qstring_append(body, " vec3 u = normalize(tPosition.xyz);\n");
|
||||
//FIXME: tNormal before or after normalization? Always normalize?
|
||||
qstring_append(s, " vec3 r = reflect(u, tNormal);\n");
|
||||
qstring_append(body, " vec3 r = reflect(u, tNormal);\n");
|
||||
|
||||
/* FIXME: This would consume 1 division fewer and *might* be
|
||||
* faster than length:
|
||||
|
@ -382,25 +362,25 @@ static QString* generate_fixed_function(const ShaderState state,
|
|||
* 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_fmt(s, " tTexture%d.%c = r.%c * invM + 0.5;\n",
|
||||
qstring_append(body, " float invM = 1.0 / (2.0 * length(r + vec3(0.0, 0.0, 1.0)));\n");
|
||||
qstring_append_fmt(body, " oT%d.%c = r.%c * invM + 0.5;\n",
|
||||
i, c, c);
|
||||
qstring_append(s, "}\n");
|
||||
qstring_append(body, "}\n");
|
||||
assert(false); /* Untested */
|
||||
break;
|
||||
case TEXGEN_REFLECTION_MAP:
|
||||
assert(i < 3); /* Channels S,T,R only! */
|
||||
qstring_append(s, "{\n");
|
||||
qstring_append(body, "{\n");
|
||||
/* FIXME: u and r only have to be calculated once, can share the one from SPHERE_MAP */
|
||||
qstring_append(s, " vec3 u = normalize(tPosition.xyz);\n");
|
||||
qstring_append(s, " vec3 r = reflect(u, tNormal);\n");
|
||||
qstring_append_fmt(s, " tTexture%d.%c = r.%c;\n",
|
||||
qstring_append(body, " vec3 u = normalize(tPosition.xyz);\n");
|
||||
qstring_append(body, " vec3 r = reflect(u, tNormal);\n");
|
||||
qstring_append_fmt(body, " oT%d.%c = r.%c;\n",
|
||||
i, c, c);
|
||||
qstring_append(s, "}\n");
|
||||
qstring_append(body, "}\n");
|
||||
break;
|
||||
case TEXGEN_NORMAL_MAP:
|
||||
assert(i < 3); /* Channels S,T,R only! */
|
||||
qstring_append_fmt(s, "tTexture%d.%c = tNormal.%c;\n",
|
||||
qstring_append_fmt(body, "oT%d.%c = tNormal.%c;\n",
|
||||
i, c, c);
|
||||
break;
|
||||
default:
|
||||
|
@ -413,8 +393,8 @@ static QString* generate_fixed_function(const ShaderState state,
|
|||
/* Apply texture matrices */
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (state.texture_matrix_enable[i]) {
|
||||
qstring_append_fmt(s,
|
||||
"tTexture%d = tTexture%d * texMat%d;\n",
|
||||
qstring_append_fmt(body,
|
||||
"oT%d = oT%d * texMat%d;\n",
|
||||
i, i, i);
|
||||
}
|
||||
}
|
||||
|
@ -423,12 +403,12 @@ static QString* generate_fixed_function(const ShaderState state,
|
|||
if (state.lighting) {
|
||||
|
||||
//FIXME: Do 2 passes if we want 2 sided-lighting?
|
||||
qstring_append_fmt(h, "uniform vec3 sceneAmbientColor;\n");
|
||||
qstring_append(s, "vec4 tD0 = vec4(sceneAmbientColor, diffuse.a);\n");
|
||||
qstring_append(s, "vec4 tD1 = vec4(0.0, 0.0, 0.0, specular.a);\n");
|
||||
qstring_append_fmt(header, "uniform vec3 sceneAmbientColor;\n");
|
||||
qstring_append(body, "oD0 = vec4(sceneAmbientColor, diffuse.a);\n");
|
||||
qstring_append(body, "oD1 = vec4(0.0, 0.0, 0.0, specular.a);\n");
|
||||
|
||||
/* FIXME: Only add if necessary */
|
||||
qstring_append(h,
|
||||
qstring_append(header,
|
||||
"uniform vec4 eyePosition;\n");
|
||||
|
||||
for (i = 0; i < NV2A_MAX_LIGHTS; i++) {
|
||||
|
@ -436,7 +416,7 @@ static QString* generate_fixed_function(const ShaderState state,
|
|||
continue;
|
||||
}
|
||||
|
||||
qstring_append_fmt(h,
|
||||
qstring_append_fmt(header,
|
||||
"uniform vec3 lightAmbientColor%d;\n"
|
||||
"uniform vec3 lightDiffuseColor%d;\n"
|
||||
"uniform vec3 lightSpecularColor%d;\n",
|
||||
|
@ -448,19 +428,19 @@ static QString* generate_fixed_function(const ShaderState state,
|
|||
* colors
|
||||
*/
|
||||
|
||||
qstring_append_fmt(s, "/* Light %d */ {\n", i);
|
||||
qstring_append_fmt(body, "/* Light %d */ {\n", i);
|
||||
|
||||
qstring_append_fmt(h,
|
||||
qstring_append_fmt(header,
|
||||
"uniform float lightLocalRange%d;\n", i);
|
||||
|
||||
if (state.light[i] == LIGHT_LOCAL
|
||||
|| state.light[i] == LIGHT_SPOT) {
|
||||
|
||||
qstring_append_fmt(h,
|
||||
qstring_append_fmt(header,
|
||||
"uniform vec3 lightLocalPosition%d;\n"
|
||||
"uniform vec3 lightLocalAttenuation%d;\n",
|
||||
i, i);
|
||||
qstring_append_fmt(s,
|
||||
qstring_append_fmt(body,
|
||||
" vec3 VP = lightLocalPosition%d - tPosition.xyz/tPosition.w;\n"
|
||||
" float d = length(VP);\n"
|
||||
//FIXME: if (d > lightLocalRange) { .. don't process this light .. } /* inclusive?! */ - what about directional lights?
|
||||
|
@ -480,11 +460,11 @@ static QString* generate_fixed_function(const ShaderState state,
|
|||
|
||||
/* lightLocalRange will be 1e+30 here */
|
||||
|
||||
qstring_append_fmt(h,
|
||||
qstring_append_fmt(header,
|
||||
"uniform vec3 lightInfiniteHalfVector%d;\n"
|
||||
"uniform vec3 lightInfiniteDirection%d;\n",
|
||||
i, i);
|
||||
qstring_append_fmt(s,
|
||||
qstring_append_fmt(body,
|
||||
" float attenuation = 1.0;\n"
|
||||
" float nDotVP = max(0.0, dot(tNormal, normalize(vec3(lightInfiniteDirection%d))));\n"
|
||||
" float nDotHV = max(0.0, dot(tNormal, vec3(lightInfiniteHalfVector%d)));\n",
|
||||
|
@ -499,7 +479,7 @@ static QString* generate_fixed_function(const ShaderState state,
|
|||
/* Everything done already */
|
||||
break;
|
||||
case LIGHT_SPOT:
|
||||
qstring_append_fmt(h,
|
||||
qstring_append_fmt(header,
|
||||
"uniform vec3 lightSpotFalloff%d;\n"
|
||||
"uniform vec4 lightSpotDirection%d;\n",
|
||||
i, i);
|
||||
|
@ -511,7 +491,7 @@ static QString* generate_fixed_function(const ShaderState state,
|
|||
break;
|
||||
}
|
||||
|
||||
qstring_append_fmt(s,
|
||||
qstring_append_fmt(body,
|
||||
" float pf;\n"
|
||||
" if (nDotVP == 0.0) {\n"
|
||||
" pf = 0.0;\n"
|
||||
|
@ -523,22 +503,23 @@ static QString* generate_fixed_function(const ShaderState state,
|
|||
" vec3 lightSpecular = lightSpecularColor%d * pf;\n",
|
||||
i, i, i);
|
||||
|
||||
qstring_append(s,
|
||||
" tD0.xyz += lightAmbient;\n");
|
||||
qstring_append(body,
|
||||
" oD0.xyz += lightAmbient;\n");
|
||||
|
||||
qstring_append(s,
|
||||
" tD0.xyz += diffuse.xyz * lightDiffuse;\n");
|
||||
qstring_append(body,
|
||||
" oD0.xyz += diffuse.xyz * lightDiffuse;\n");
|
||||
|
||||
qstring_append(s,
|
||||
" tD1.xyz += specular.xyz * lightSpecular;\n"
|
||||
"}\n");
|
||||
qstring_append(body,
|
||||
" oD1.xyz += specular.xyz * lightSpecular;\n");
|
||||
|
||||
qstring_append(body, "}\n");
|
||||
}
|
||||
} else {
|
||||
qstring_append(s, "vec4 tD0 = diffuse;\n");
|
||||
qstring_append(s, "vec4 tD1 = specular;\n");
|
||||
qstring_append(body, " oD0 = diffuse;\n");
|
||||
qstring_append(body, " oD1 = specular;\n");
|
||||
}
|
||||
qstring_append(s, "vec4 tB0 = backDiffuse;\n");
|
||||
qstring_append(s, "vec4 tB1 = backSpecular;\n");
|
||||
qstring_append(body, " oB0 = backDiffuse;\n");
|
||||
qstring_append(body, " oB1 = backSpecular;\n");
|
||||
|
||||
/* Fog */
|
||||
if (state.fog_enable) {
|
||||
|
@ -549,28 +530,28 @@ static QString* generate_fixed_function(const ShaderState state,
|
|||
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");
|
||||
qstring_append(body, " float fogDistance = clamp(specular.a, 0.0, 1.0);\n");
|
||||
} else if (state.vertex_program) {
|
||||
qstring_append(s, "float fogDistance = oD1.a;\n");
|
||||
qstring_append(body, " float fogDistance = oD1.a;\n");
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
break;
|
||||
case FOGGEN_RADIAL:
|
||||
qstring_append(s, "float fogDistance = length(tPosition.xyz)");
|
||||
qstring_append(body, " 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");
|
||||
qstring_append(body, " float fogDistance = dot(fogPlane.xyz, tPosition.xyz) + fogPlane.w;\n");
|
||||
if (state.foggen == FOGGEN_ABS_PLANAR) {
|
||||
qstring_append(s, "fogDistance = abs(fogDistance);\n");
|
||||
qstring_append(body, " fogDistance = abs(fogDistance);\n");
|
||||
}
|
||||
break;
|
||||
case FOGGEN_FOG_X:
|
||||
if (state.fixed_function) {
|
||||
qstring_append(s, "float fogDistance = fogCoord;\n");
|
||||
qstring_append(body, " float fogDistance = fogCoord;\n");
|
||||
} else if (state.vertex_program) {
|
||||
qstring_append(s, "float fogDistance = oFog.x;\n");
|
||||
qstring_append(body, " float fogDistance = oFog.x;\n");
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
|
@ -580,7 +561,94 @@ static QString* generate_fixed_function(const ShaderState state,
|
|||
break;
|
||||
}
|
||||
|
||||
//FIXME: Do this per pixel?
|
||||
}
|
||||
|
||||
/* If skinning is off the composite matrix already includes the MV matrix */
|
||||
if (state.skinning == SKINNING_OFF) {
|
||||
qstring_append(body, " tPosition = position;\n");
|
||||
}
|
||||
|
||||
qstring_append(body,
|
||||
" oPos = invViewport * (tPosition * compositeMat);\n"
|
||||
" oPos.z = oPos.z * 2.0 - oPos.w;\n");
|
||||
|
||||
qstring_append(body, " vtx.inv_w = 1.0 / oPos.w;\n");
|
||||
|
||||
}
|
||||
|
||||
static QString *generate_vertex_shader(const ShaderState state,
|
||||
char vtx_prefix)
|
||||
{
|
||||
int i;
|
||||
QString *header = qstring_from_str("#version 330\n"
|
||||
"\n"
|
||||
"uniform vec2 clipRange;\n"
|
||||
"uniform vec2 surfaceSize;\n"
|
||||
"\n"
|
||||
/* All constants in 1 array declaration */
|
||||
"layout(shared) uniform VertexConstants {\n"
|
||||
" uniform vec4 c[192];\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
/* FIXME: Most [all?] of these are probably part of the constant space */
|
||||
"uniform vec4 fogColor;\n"
|
||||
"uniform vec4 fogPlane;\n"
|
||||
"uniform float fogParam[2];\n"
|
||||
"\n"
|
||||
"vec4 oPos = vec4(0.0,0.0,0.0,1.0);\n"
|
||||
"vec4 oD0 = vec4(0.0,0.0,0.0,1.0);\n"
|
||||
"vec4 oD1 = vec4(0.0,0.0,0.0,1.0);\n"
|
||||
"vec4 oB0 = vec4(0.0,0.0,0.0,1.0);\n"
|
||||
"vec4 oB1 = vec4(0.0,0.0,0.0,1.0);\n"
|
||||
"vec4 oPts = vec4(0.0,0.0,0.0,1.0);\n"
|
||||
"vec4 oFog = vec4(0.0,0.0,0.0,1.0);\n"
|
||||
"vec4 oT0 = vec4(0.0,0.0,0.0,1.0);\n"
|
||||
"vec4 oT1 = vec4(0.0,0.0,0.0,1.0);\n"
|
||||
"vec4 oT2 = vec4(0.0,0.0,0.0,1.0);\n"
|
||||
"vec4 oT3 = vec4(0.0,0.0,0.0,1.0);\n"
|
||||
"\n"
|
||||
STRUCT_VERTEX_DATA);
|
||||
qstring_append_fmt(header, "noperspective out VertexData %c_vtx;\n",
|
||||
vtx_prefix);
|
||||
qstring_append_fmt(header, "#define vtx %c_vtx\n",
|
||||
vtx_prefix);
|
||||
qstring_append(header, "\n");
|
||||
for(i = 0; i < 16; i++) {
|
||||
qstring_append_fmt(header, "in vec4 v%d;\n", i);
|
||||
}
|
||||
qstring_append(header, "\n");
|
||||
|
||||
QString *body = qstring_from_str("void main() {\n");
|
||||
|
||||
if (state.fixed_function) {
|
||||
generate_fixed_function(state, header, body);
|
||||
|
||||
} else if (state.vertex_program) {
|
||||
vsh_translate(VSH_VERSION_XVS,
|
||||
(uint32_t*)state.program_data,
|
||||
state.program_length,
|
||||
header, body);
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
|
||||
/* Fog */
|
||||
|
||||
if (state.fog_enable) {
|
||||
|
||||
if (state.vertex_program) {
|
||||
/* FIXME: Does foggen do something here? Let's do some tracking..
|
||||
*
|
||||
* "RollerCoaster Tycoon" has
|
||||
* state.vertex_program = true; state.foggen == FOGGEN_PLANAR
|
||||
* but expects oFog.x as fogdistance?! Writes oFog.xyzw = v0.z
|
||||
*/
|
||||
qstring_append(body, " float fogDistance = oFog.x;\n");
|
||||
}
|
||||
|
||||
/* FIXME: Do this per pixel? */
|
||||
|
||||
switch (state.fog_mode) {
|
||||
case FOG_MODE_LINEAR:
|
||||
case FOG_MODE_LINEAR_ABS:
|
||||
|
@ -590,8 +658,8 @@ static QString* generate_fixed_function(const ShaderState state,
|
|||
* 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?!! */
|
||||
qstring_append(body, " float fogFactor = fogParam[0] + fogDistance * fogParam[1];\n");
|
||||
qstring_append(body, " fogFactor -= 1.0;\n"); /* FIXME: WHHYYY?!! */
|
||||
break;
|
||||
case FOG_MODE_EXP:
|
||||
case FOG_MODE_EXP_ABS:
|
||||
|
@ -601,8 +669,8 @@ static QString* generate_fixed_function(const ShaderState state,
|
|||
* 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?!! */
|
||||
qstring_append(body, " float fogFactor = fogParam[0] + exp2(fogDistance * fogParam[1] * 16.0);\n");
|
||||
qstring_append(body, " fogFactor -= 1.5;\n"); /* FIXME: WHHYYY?!! */
|
||||
break;
|
||||
case FOG_MODE_EXP2:
|
||||
case FOG_MODE_EXP2_ABS:
|
||||
|
@ -612,8 +680,8 @@ static QString* generate_fixed_function(const ShaderState state,
|
|||
* 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?!! */
|
||||
qstring_append(body, " float fogFactor = fogParam[0] + exp2(-fogDistance * fogDistance * fogParam[1] * fogParam[1] * 32.0);\n");
|
||||
qstring_append(body, " fogFactor -= 1.5;\n"); /* FIXME: WHHYYY?!! */
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
|
@ -624,50 +692,41 @@ static QString* generate_fixed_function(const ShaderState state,
|
|||
case FOG_MODE_LINEAR_ABS:
|
||||
case FOG_MODE_EXP_ABS:
|
||||
case FOG_MODE_EXP2_ABS:
|
||||
qstring_append(s, "fogFactor = abs(fogFactor);\n");
|
||||
qstring_append(body, " fogFactor = abs(fogFactor);\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* FIXME: What about fog alpha?! */
|
||||
qstring_append(s, "float tFog = fogFactor;\n");
|
||||
qstring_append(body, " oFog.xyzw = vec4(fogFactor);\n");
|
||||
} else {
|
||||
/* FIXME: Is the fog still calculated / passed somehow?!
|
||||
*/
|
||||
qstring_append(s, "float tFog = 0.0;\n");
|
||||
qstring_append(body, " oFog.xyzw = vec4(1.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");
|
||||
}
|
||||
/* Set outputs */
|
||||
qstring_append(body, "\n"
|
||||
" vtx.D0 = clamp(oD0, 0.0, 1.0) * vtx.inv_w;\n"
|
||||
" vtx.D1 = clamp(oD1, 0.0, 1.0) * vtx.inv_w;\n"
|
||||
" vtx.B0 = clamp(oB0, 0.0, 1.0) * vtx.inv_w;\n"
|
||||
" vtx.B1 = clamp(oB1, 0.0, 1.0) * vtx.inv_w;\n"
|
||||
" vtx.Fog = oFog.x * vtx.inv_w;\n"
|
||||
" vtx.T0 = oT0 * vtx.inv_w;\n"
|
||||
" vtx.T1 = oT1 * vtx.inv_w;\n"
|
||||
" vtx.T2 = oT2 * vtx.inv_w;\n"
|
||||
" vtx.T3 = oT3 * vtx.inv_w;\n"
|
||||
" gl_Position = oPos;\n"
|
||||
" gl_PointSize = oPts.x;\n"
|
||||
"\n"
|
||||
"}\n");
|
||||
|
||||
qstring_append(s,
|
||||
" gl_Position = invViewport * (tPosition * compositeMat);\n"
|
||||
/* temp hack: the composite matrix includes the view transform... */
|
||||
//" gl_Position = position * compositeMat;\n"
|
||||
//" gl_Position.x = (gl_Position.x - 320.0) / 320.0;\n"
|
||||
//" gl_Position.y = -(gl_Position.y - 240.0) / 240.0;\n"
|
||||
" gl_Position.z = gl_Position.z * 2.0 - gl_Position.w;\n");
|
||||
|
||||
qstring_append(s, "vtx.inv_w = 1.0/gl_Position.w;\n");
|
||||
qstring_append(s, "vtx.D0 = clamp(tD0, 0.0, 1.0) * vtx.inv_w;\n");
|
||||
qstring_append(s, "vtx.D1 = clamp(tD1, 0.0, 1.0) * vtx.inv_w;\n");
|
||||
qstring_append(s, "vtx.B0 = clamp(tB0, 0.0, 1.0) * vtx.inv_w;\n");
|
||||
qstring_append(s, "vtx.B1 = clamp(tB1, 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");
|
||||
qstring_append(s, "vtx.T3 = tTexture3 * vtx.inv_w;\n");
|
||||
/* Return combined header + source */
|
||||
qstring_append(header, qstring_get_str(body));
|
||||
QDECREF(body);
|
||||
return header;
|
||||
|
||||
qstring_append(h,"void main() {\n");
|
||||
qstring_append(h, qstring_get_str(s));
|
||||
qstring_append(h, "}\n");
|
||||
|
||||
QDECREF(s);
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
static GLuint create_gl_shader(GLenum gl_shader_type,
|
||||
|
@ -737,28 +796,12 @@ ShaderBinding* generate_shaders(const ShaderState state)
|
|||
|
||||
/* create the vertex shader */
|
||||
|
||||
QString *s = NULL;
|
||||
if (state.fixed_function) {
|
||||
s = generate_fixed_function(state, vtx_prefix);
|
||||
|
||||
} else if (state.vertex_program) {
|
||||
s = vsh_translate(VSH_VERSION_XVS, (uint32_t*)state.program_data,
|
||||
state.program_length,
|
||||
vtx_prefix);
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
if (s) {
|
||||
const char* s_str = qstring_get_str(s);
|
||||
|
||||
GLuint vertex_shader = create_gl_shader(GL_VERTEX_SHADER,
|
||||
s_str,
|
||||
"vertex shader");
|
||||
glAttachShader(program, vertex_shader);
|
||||
|
||||
QDECREF(s);
|
||||
}
|
||||
QString *vertex_shader_code = generate_vertex_shader(state, vtx_prefix);
|
||||
GLuint vertex_shader = create_gl_shader(GL_VERTEX_SHADER,
|
||||
qstring_get_str(vertex_shader_code),
|
||||
"vertex shader");
|
||||
glAttachShader(program, vertex_shader);
|
||||
QDECREF(vertex_shader_code);
|
||||
|
||||
|
||||
/* Bind attributes for vertices */
|
||||
|
|
|
@ -516,37 +516,9 @@ static QString* decode_token(const uint32_t *shader_token)
|
|||
}
|
||||
|
||||
static const char* vsh_header =
|
||||
"in vec4 v0;\n"
|
||||
"in vec4 v1;\n"
|
||||
"in vec4 v2;\n"
|
||||
"in vec4 v3;\n"
|
||||
"in vec4 v4;\n"
|
||||
"in vec4 v5;\n"
|
||||
"in vec4 v6;\n"
|
||||
"in vec4 v7;\n"
|
||||
"in vec4 v8;\n"
|
||||
"in vec4 v9;\n"
|
||||
"in vec4 v10;\n"
|
||||
"in vec4 v11;\n"
|
||||
"in vec4 v12;\n"
|
||||
"in vec4 v13;\n"
|
||||
"in vec4 v14;\n"
|
||||
"in vec4 v15;\n"
|
||||
"\n"
|
||||
"int A0 = 0;\n"
|
||||
"\n"
|
||||
"vec4 oPos = vec4(0.0,0.0,0.0,1.0);\n"
|
||||
"vec4 oD0 = vec4(0.0,0.0,0.0,1.0);\n"
|
||||
"vec4 oD1 = vec4(0.0,0.0,0.0,1.0);\n"
|
||||
"vec4 oB0 = vec4(0.0,0.0,0.0,1.0);\n"
|
||||
"vec4 oB1 = vec4(0.0,0.0,0.0,1.0);\n"
|
||||
"vec4 oPts = vec4(0.0,0.0,0.0,1.0);\n"
|
||||
"vec4 oFog = vec4(0.0,0.0,0.0,1.0);\n"
|
||||
"vec4 oT0 = vec4(0.0,0.0,0.0,1.0);\n"
|
||||
"vec4 oT1 = vec4(0.0,0.0,0.0,1.0);\n"
|
||||
"vec4 oT2 = vec4(0.0,0.0,0.0,1.0);\n"
|
||||
"vec4 oT3 = vec4(0.0,0.0,0.0,1.0);\n"
|
||||
"\n"
|
||||
"vec4 R0 = vec4(0.0,0.0,0.0,0.0);\n"
|
||||
"vec4 R1 = vec4(0.0,0.0,0.0,0.0);\n"
|
||||
"vec4 R2 = vec4(0.0,0.0,0.0,0.0);\n"
|
||||
|
@ -562,15 +534,6 @@ static const char* vsh_header =
|
|||
"#define R12 oPos\n" /* R12 is a mirror of oPos */
|
||||
"\n"
|
||||
|
||||
|
||||
/* All constants in 1 array declaration */
|
||||
"layout(shared) uniform VertexConstants {\n"
|
||||
" uniform vec4 c[192];\n"
|
||||
"};"
|
||||
"\n"
|
||||
"uniform vec2 clipRange;\n"
|
||||
"uniform vec2 surfaceSize;\n"
|
||||
|
||||
/* See:
|
||||
* http://msdn.microsoft.com/en-us/library/windows/desktop/bb174703%28v=vs.85%29.aspx
|
||||
* https://www.opengl.org/registry/specs/NV/vertex_program1_1.txt
|
||||
|
@ -726,30 +689,23 @@ static const char* vsh_header =
|
|||
" return t;\n"
|
||||
"}\n";
|
||||
|
||||
QString* vsh_translate(uint16_t version,
|
||||
void vsh_translate(uint16_t version,
|
||||
const uint32_t *tokens,
|
||||
unsigned int length,
|
||||
char out_prefix)
|
||||
QString *header, QString *body)
|
||||
{
|
||||
|
||||
QString* header = qstring_from_str("#version 330\n\n");
|
||||
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"
|
||||
"uniform mat4 texMat2;\n"
|
||||
"uniform mat4 texMat3;\n");
|
||||
"uniform mat4 texMat0;\n"
|
||||
"uniform mat4 texMat1;\n"
|
||||
"uniform mat4 texMat2;\n"
|
||||
"uniform mat4 texMat3;\n");
|
||||
qstring_append(header, vsh_header);
|
||||
|
||||
QString *body = qstring_from_str("\n");
|
||||
qstring_append(body," oFog.x = 1.0;\n"); /* FIXME: Use foggen? */
|
||||
|
||||
bool has_final = false;
|
||||
int slot;
|
||||
for (slot=0; slot<length; slot++) {
|
||||
for (slot=0; slot < length; slot++) {
|
||||
const uint32_t* cur_token = &tokens[slot * VSH_TOKEN_SIZE];
|
||||
QString *token_str = decode_token(cur_token);
|
||||
qstring_append_fmt(body,
|
||||
|
@ -772,58 +728,35 @@ QString* vsh_translate(uint16_t version,
|
|||
* interpolation manually. OpenGL can't, since we give it a W of 1 to work
|
||||
* around the perspective divide */
|
||||
qstring_append(body,
|
||||
"if (oPos.w == 0.0 || isinf(oPos.w)) {\n"
|
||||
" vtx.inv_w = 1.0;\n"
|
||||
"} else {\n"
|
||||
" vtx.inv_w = 1.0 / oPos.w;\n"
|
||||
"}\n");
|
||||
qstring_append(body, "vtx.D0 = clamp(oD0, 0.0, 1.0) * vtx.inv_w;\n");
|
||||
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.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");
|
||||
qstring_append(body, "vtx.T3 = oT3 * vtx.inv_w;\n");
|
||||
" if (oPos.w == 0.0 || isinf(oPos.w)) {\n"
|
||||
" vtx.inv_w = 1.0;\n"
|
||||
" } else {\n"
|
||||
" vtx.inv_w = 1.0 / oPos.w;\n"
|
||||
" }\n");
|
||||
|
||||
qstring_append(body,
|
||||
/* the shaders leave the result in screen space, while
|
||||
* opengl expects it in clip space.
|
||||
* TODO: the pixel-center co-ordinate differences should handled
|
||||
*/
|
||||
"oPos.x = 2.0 * (oPos.x - surfaceSize.x * 0.5) / surfaceSize.x;\n"
|
||||
"oPos.y = -2.0 * (oPos.y - surfaceSize.y * 0.5) / surfaceSize.y;\n"
|
||||
"if (clipRange.y != clipRange.x) {\n"
|
||||
" oPos.z = (oPos.z - 0.5 * (clipRange.x + clipRange.y)) / (0.5 * (clipRange.y - clipRange.x));\n"
|
||||
"}\n"
|
||||
" oPos.x = 2.0 * (oPos.x - surfaceSize.x * 0.5) / surfaceSize.x;\n"
|
||||
" oPos.y = -2.0 * (oPos.y - surfaceSize.y * 0.5) / surfaceSize.y;\n"
|
||||
" if (clipRange.y != clipRange.x) {\n"
|
||||
" oPos.z = (oPos.z - 0.5 * (clipRange.x + clipRange.y)) / (0.5 * (clipRange.y - clipRange.x));\n"
|
||||
" }\n"
|
||||
|
||||
/* Correct for the perspective divide */
|
||||
"if (oPos.w < 0.0) {\n"
|
||||
" if (oPos.w < 0.0) {\n"
|
||||
/* undo the perspective divide in the case where the point would be
|
||||
* clipped so opengl can clip it correctly */
|
||||
" oPos.xyz *= oPos.w;\n"
|
||||
"} else {\n"
|
||||
" oPos.xyz *= oPos.w;\n"
|
||||
" } else {\n"
|
||||
/* we don't want the OpenGL perspective divide to happen, but we
|
||||
* can't multiply by W because it could be meaningless here */
|
||||
" oPos.w = 1.0;\n"
|
||||
"}\n"
|
||||
" oPos.w = 1.0;\n"
|
||||
" }\n"
|
||||
|
||||
/* Set outputs */
|
||||
" gl_Position = oPos;\n"
|
||||
" gl_PointSize = oPts.x;\n"
|
||||
"\n"
|
||||
);
|
||||
|
||||
QString *ret = qstring_new();
|
||||
qstring_append(ret, qstring_get_str(header));
|
||||
qstring_append(ret,"\n"
|
||||
"void main(void)\n"
|
||||
"{\n");
|
||||
qstring_append(ret, qstring_get_str(body));
|
||||
qstring_append(ret,"}\n");
|
||||
QDECREF(header);
|
||||
QDECREF(body);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -131,10 +131,10 @@ typedef enum {
|
|||
|
||||
uint8_t vsh_get_field(const uint32_t *shader_token, VshFieldName field_name);
|
||||
|
||||
QString* vsh_translate(uint16_t version,
|
||||
const uint32_t *tokens,
|
||||
unsigned int length,
|
||||
char out_prefix);
|
||||
void vsh_translate(uint16_t version,
|
||||
const uint32_t *tokens,
|
||||
unsigned int length,
|
||||
QString *header, QString *body);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue