d3d9: Make the vertex shaders more similar.

This commit is contained in:
Unknown W. Brackets 2014-09-20 23:55:48 -07:00
parent dda3ca3d5f
commit 6f38c21ccc
3 changed files with 62 additions and 48 deletions

View File

@ -269,10 +269,17 @@ void GenerateFragmentShaderDX9(char *buffer) {
}
if (gstate.isTextureMapEnabled()) {
const char *texcoord = "In.v_texcoord";
if (doTextureProjection && gstate_c.flipTexture) {
// Since we need to flip v, we project manually.
WRITE(p, " float2 fixedcoord = float2(v_texcoord.x / v_texcoord.z, 1.0 - (v_texcoord.y / v_texcoord.z));\n");
texcoord = "fixedcoord";
doTextureProjection = false;
}
if (doTextureProjection) {
WRITE(p, " float4 t = tex2Dproj(tex, float4(In.v_texcoord.x, In.v_texcoord.y, 0, In.v_texcoord.z))%s;\n", gstate_c.bgraTexture ? ".bgra" : "");
} else {
WRITE(p, " float4 t = tex2D(tex, In.v_texcoord.xy)%s;\n", gstate_c.bgraTexture ? ".bgra" : "");
WRITE(p, " float4 t = tex2D(tex, %s.xy)%s;\n", texcoord, gstate_c.bgraTexture ? ".bgra" : "");
}
WRITE(p, " float4 p = In.v_color0;\n");

View File

@ -28,6 +28,7 @@
#include "Core/Config.h"
#include "GPU/Directx9/VertexShaderGeneratorDX9.h"
#include "GPU/Common/VertexDecoderCommon.h"
#undef WRITE
@ -41,16 +42,9 @@ bool CanUseHardwareTransformDX9(int prim) {
return !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES;
}
int TranslateNumBonesDX9(int bones) {
if (!bones) return 0;
if (bones < 4) return 4;
// if (bones < 8) return 8; I get drawing problems in FF:CC with this!
return bones;
}
// prim so we can special case for RECTANGLES :(
void ComputeVertexShaderIDDX9(VertexShaderIDDX9 *id, u32 vertType, int prim, bool useHWTransform) {
int doTexture = gstate.isTextureMapEnabled() && !gstate.isModeClear();
bool doTexture = gstate.isTextureMapEnabled() && !gstate.isModeClear();
bool doTextureProjection = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX;
bool doShadeMapping = gstate.getUVGenMode() == GE_TEXMAP_ENVIRONMENT_MAP;
@ -60,54 +54,65 @@ void ComputeVertexShaderIDDX9(VertexShaderIDDX9 *id, u32 vertType, int prim, boo
bool enableFog = gstate.isFogEnabled() && !gstate.isModeThrough() && !gstate.isModeClear();
bool lmode = gstate.isUsingSecondaryColor() && gstate.isLightingEnabled();
memset(id->d, 0, sizeof(id->d));
id->d[0] = lmode & 1;
id->d[0] |= ((int)gstate.isModeThrough()) << 1;
id->d[0] |= ((int)enableFog) << 2;
id->d[0] |= doTexture << 3;
id->d[0] |= (hasColor & 1) << 4;
int id0 = 0;
int id1 = 0;
id0 = lmode & 1;
id0 |= (gstate.isModeThrough() & 1) << 1;
id0 |= (enableFog & 1) << 2;
id0 |= (hasColor & 1) << 3;
if (doTexture) {
id->d[0] |= (gstate_c.flipTexture & 1) << 5;
id->d[0] |= (doTextureProjection & 1) << 6;
id0 |= 1 << 4;
id0 |= (gstate_c.flipTexture & 1) << 5;
id0 |= (doTextureProjection & 1) << 6;
}
if (useHWTransform) {
id->d[0] |= 1 << 8;
id->d[0] |= (hasNormal & 1) << 9;
id0 |= 1 << 8;
id0 |= (hasNormal & 1) << 9;
// UV generation mode
id->d[0] |= gstate.getUVGenMode() << 16;
id0 |= gstate.getUVGenMode() << 16;
// The next bits are used differently depending on UVgen mode
if (doTextureProjection) {
id->d[0] |= gstate.getUVProjMode() << 18;
id0 |= gstate.getUVProjMode() << 18;
} else if (doShadeMapping) {
id->d[0] |= gstate.getUVLS0() << 18;
id->d[0] |= gstate.getUVLS1() << 20;
id0 |= gstate.getUVLS0() << 18;
id0 |= gstate.getUVLS1() << 20;
}
// Bones
if (vertTypeIsSkinningEnabled(vertType))
id->d[0] |= (TranslateNumBonesDX9(vertTypeGetNumBoneWeights(vertType)) - 1) << 22;
id0 |= (TranslateNumBones(vertTypeGetNumBoneWeights(vertType)) - 1) << 22;
// Okay, d[1] coming up. ==============
if (gstate.isLightingEnabled() || doShadeMapping) {
// Light bits
for (int i = 0; i < 4; i++) {
id->d[1] |= gstate.getLightComputation(i) << (i * 4);
id->d[1] |= gstate.getLightType(i) << (i * 4 + 2);
id1 |= gstate.getLightComputation(i) << (i * 4);
id1 |= gstate.getLightType(i) << (i * 4 + 2);
}
id->d[1] |= (gstate.materialupdate & 7) << 16;
id1 |= (gstate.materialupdate & 7) << 16;
for (int i = 0; i < 4; i++) {
id->d[1] |= (gstate.isLightChanEnabled(i) & 1) << (20 + i);
id1 |= (gstate.isLightChanEnabled(i) & 1) << (20 + i);
}
// doShadeMapping is stored as UVGenMode, so this is enough for isLightingEnabled.
id1 |= 1 << 24;
}
// 2 bits.
id1 |= (vertTypeGetWeightMask(vertType) >> GE_VTYPE_WEIGHT_SHIFT) << 25;
id1 |= (gstate.areNormalsReversed() & 1) << 27;
if (doTextureProjection && gstate.getUVProjMode() == GE_PROJMAP_UV) {
id1 |= ((vertType & GE_VTYPE_TC_MASK) >> GE_VTYPE_TC_SHIFT) << 28; // two bits
} else {
id1 |= (hasTexcoord & 1) << 28;
}
id->d[1] |= gstate.isLightingEnabled() << 24;
id->d[1] |= (vertTypeGetWeightMask(vertType) >> GE_VTYPE_WEIGHT_SHIFT) << 25;
id->d[1] |= gstate.areNormalsReversed() << 26;
id->d[1] |= (hasTexcoord & 1) << 27;
}
id->d[0] = id0;
id->d[1] = id1;
}
static const char * const boneWeightAttrDecl[9] = {
@ -132,8 +137,8 @@ void GenerateVertexShaderDX9(int prim, char *buffer, bool useHWTransform) {
char *p = buffer;
const u32 vertType = gstate.vertType;
int lmode = gstate.isUsingSecondaryColor() && gstate.isLightingEnabled();
int doTexture = gstate.isTextureMapEnabled() && !gstate.isModeClear();
bool lmode = gstate.isUsingSecondaryColor() && gstate.isLightingEnabled();
bool doTexture = gstate.isTextureMapEnabled() && !gstate.isModeClear();
bool doTextureProjection = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX;
bool doShadeMapping = gstate.getUVGenMode() == GE_TEXMAP_ENVIRONMENT_MAP;
@ -144,7 +149,7 @@ void GenerateVertexShaderDX9(int prim, char *buffer, bool useHWTransform) {
bool throughmode = (vertType & GE_VTYPE_THROUGH_MASK) != 0;
bool flipV = gstate_c.flipTexture;
bool flipNormal = gstate.areNormalsReversed();
bool prescale = g_Config.bPrescaleUV && !throughmode && gstate.getTextureFunction() == 0;
bool prescale = g_Config.bPrescaleUV && !throughmode && (gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_COORDS || gstate.getUVGenMode() == GE_TEXMAP_UNKNOWN);
DoLightComputation doLight[4] = {LIGHT_OFF, LIGHT_OFF, LIGHT_OFF, LIGHT_OFF};
if (useHWTransform) {
@ -177,10 +182,10 @@ void GenerateVertexShaderDX9(int prim, char *buffer, bool useHWTransform) {
// When transforming by hardware, we need a great deal more uniforms...
WRITE(p, "float4x3 u_world : register(c%i);\n", CONST_VS_WORLD);
WRITE(p, "float4x3 u_view : register(c%i);\n", CONST_VS_VIEW);
if (gstate.getUVGenMode() == 1)
if (doTextureProjection)
WRITE(p, "float4x3 u_texmtx : register(c%i);\n", CONST_VS_TEXMTX);
if (vertTypeIsSkinningEnabled(vertType)) {
int numBones = TranslateNumBonesDX9(vertTypeGetNumBoneWeights(vertType));
int numBones = TranslateNumBones(vertTypeGetNumBoneWeights(vertType));
#ifdef USE_BONE_ARRAY
WRITE(p, "float4x3 u_bone[%i] : register(c%i);\n", numBones, CONST_VS_BONE0);
#else
@ -189,7 +194,7 @@ void GenerateVertexShaderDX9(int prim, char *buffer, bool useHWTransform) {
}
#endif
}
if (doTexture) {
if (doTexture && (flipV || !prescale || gstate.getUVGenMode() == GE_TEXMAP_ENVIRONMENT_MAP || gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX)) {
WRITE(p, "float4 u_uvscaleoffset : register(c%i);\n", CONST_VS_UVSCALEOFFSET);
}
for (int i = 0; i < 4; i++) {
@ -228,7 +233,7 @@ void GenerateVertexShaderDX9(int prim, char *buffer, bool useHWTransform) {
if (useHWTransform) {
WRITE(p, "struct VS_IN { \n");
if (vertTypeIsSkinningEnabled(vertType)) {
WRITE(p, "%s", boneWeightAttrDecl[TranslateNumBonesDX9(vertTypeGetNumBoneWeights(vertType))]);
WRITE(p, "%s", boneWeightAttrDecl[TranslateNumBones(vertTypeGetNumBoneWeights(vertType))]);
}
if (doTexture && hasTexcoord) {
if (doTextureProjection)
@ -306,11 +311,11 @@ void GenerateVertexShaderDX9(int prim, char *buffer, bool useHWTransform) {
// No skinning, just standard T&L.
WRITE(p, " float3 worldpos = mul(float4(In.position.xyz, 1.0), u_world);\n");
if (hasNormal)
WRITE(p, " float3 worldnormal = normalize( mul(float4(In.normal, 0.0), u_world));\n", flipNormal ? "-" : "");
WRITE(p, " float3 worldnormal = normalize( mul(float4(%sIn.normal, 0.0), u_world));\n", flipNormal ? "-" : "");
else
WRITE(p, " float3 worldnormal = float3(0.0, 0.0, 1.0);\n");
} else {
int numWeights = TranslateNumBonesDX9(vertTypeGetNumBoneWeights(vertType));
int numWeights = TranslateNumBones(vertTypeGetNumBoneWeights(vertType));
static const char * const boneWeightAttr[8] = {
"a_w1.x", "a_w1.y", "a_w1.z", "a_w1.w",
@ -449,6 +454,8 @@ void GenerateVertexShaderDX9(int prim, char *buffer, bool useHWTransform) {
if (poweredDiffuse) {
WRITE(p, " float dot%i = pow(dot(toLight, worldnormal), u_matspecular.a);\n", i);
// TODO: Somehow the NaN check from GLES seems unnecessary here?
// If it returned 0, it'd be wrong, so that's strange.
} else {
WRITE(p, " float dot%i = dot(toLight, worldnormal);\n", i);
}
@ -464,6 +471,7 @@ void GenerateVertexShaderDX9(int prim, char *buffer, bool useHWTransform) {
WRITE(p, " lightScale = clamp(1.0 / dot(u_lightatt%i, float3(1.0, distance, distance*distance)), 0.0, 1.0);\n", i);
break;
case GE_LIGHTTYPE_SPOT:
case GE_LIGHTTYPE_UNKNOWN:
WRITE(p, " float angle%i = dot(normalize(u_lightdir%i), toLight);\n", i, i);
WRITE(p, " if (angle%i >= u_lightangle%i) {\n", i, i);
WRITE(p, " lightScale = clamp(1.0 / dot(u_lightatt%i, float3(1.0, distance, distance*distance)), 0.0, 1.0) * pow(angle%i, u_lightspotCoef%i);\n", i, i, i);
@ -518,7 +526,7 @@ void GenerateVertexShaderDX9(int prim, char *buffer, bool useHWTransform) {
switch (gstate.getUVGenMode()) {
case GE_TEXMAP_TEXTURE_COORDS: // Scale-offset. Easy.
case GE_TEXMAP_UNKNOWN: // Not sure what this is, but Riviera uses it. Treating as coords works.
if (prescale) {
if (prescale && !flipV) {
if (hasTexcoord) {
WRITE(p, " Out.v_texcoord = In.texcoord;\n");
} else {
@ -562,9 +570,9 @@ void GenerateVertexShaderDX9(int prim, char *buffer, bool useHWTransform) {
temp_tc = "float4(0.0, 0.0, 1.0, 1.0)";
break;
}
// Transform by texture matrix. XYZ as we are doing projection mapping.
WRITE(p, " Out.v_texcoord.xyz = mul(%s,u_texmtx) * float3(u_uvscaleoffset.xy, 1.0);\n", temp_tc.c_str());
}
// Transform by texture matrix. XYZ as we are doing projection mapping.
break;
case GE_TEXMAP_ENVIRONMENT_MAP: // Shade mapping - use dots from light sources.
@ -576,17 +584,16 @@ void GenerateVertexShaderDX9(int prim, char *buffer, bool useHWTransform) {
break;
}
if (flipV)
// Will flip in the fragment for GE_TEXMAP_TEXTURE_MATRIX.
if (flipV && gstate.getUVGenMode() != GE_TEXMAP_TEXTURE_MATRIX)
WRITE(p, " Out.v_texcoord.y = 1.0 - Out.v_texcoord.y;\n");
}
// Compute fogdepth
if (enableFog)
WRITE(p, " Out.v_fogdepth.x = (viewPos.z + u_fogcoef.x) * u_fogcoef.y;\n");
}
// WRITE(p, "Out.gl_Position.z = (Out.gl_Position.z + Out.gl_Position.w) * 0.5f;");
WRITE(p, " return Out;\n");
WRITE(p, "}\n");
}

View File

@ -60,7 +60,7 @@ void ComputeVertexShaderID(VertexShaderID *id, u32 vertType, int prim, bool useH
bool lmode = gstate.isUsingSecondaryColor() && gstate.isLightingEnabled();
int id0 = 0;
int id1 = 1;
int id1 = 0;
id0 = lmode & 1;
id0 |= (gstate.isModeThrough() & 1) << 1;
@ -209,7 +209,7 @@ void GenerateVertexShader(int prim, u32 vertType, char *buffer, bool useHWTransf
boneWeightDecl = boneWeightInDecl;
}
int lmode = gstate.isUsingSecondaryColor() && gstate.isLightingEnabled();
bool lmode = gstate.isUsingSecondaryColor() && gstate.isLightingEnabled();
bool doTexture = gstate.isTextureMapEnabled() && !gstate.isModeClear();
bool doTextureProjection = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX;
bool doShadeMapping = gstate.getUVGenMode() == GE_TEXMAP_ENVIRONMENT_MAP;