i know still a lot to fix and much work to do but sometimes experiments are fun :)

for all the plugins implemented per pixel lighting, this will make games that uses lighting  a lot nice. (just look at mario sunshine and compare :))
for dx9: implemented temporal anaglyph stereo: just grab your red-cyan glasses  and enjoy.
stereo calibration: use stereo separation ( distance of the point from you are looking) and Focal Angle: the angle necessary to focus in one particular object.
this settings are different in every games as they use different depth ranges.
please for any regression and bug introduced by this commit.
if you ask why i did not implement stereo in dx11 and opengl the reason is one: they don't work right when i have more time will try to find a way to make them work.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6224 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Rodolfo Osvaldo Bogado
2010-09-23 02:17:48 +00:00
parent 5e806eb7b2
commit e641323de2
30 changed files with 558 additions and 79 deletions

View File

@ -24,6 +24,8 @@
#include "PixelShaderGen.h"
#include "XFMemory.h" // for texture projection mode
#include "BPMemory.h"
#include "VideoConfig.h"
#include "NativeVertexFormat.h"
PIXELSHADERUID last_pixel_shader_uid;
@ -57,15 +59,26 @@ void GetPixelShaderId(PIXELSHADERUID *uid, u32 dstAlphaEnable)
for (int i = 0; i < 8; i += 2)
((u8*)&uid->values[1])[i / 2] = (bpmem.tevksel[i].hex & 0xf) | ((bpmem.tevksel[i + 1].hex & 0xf) << 4);
uid->values[2] = 0;
u32 enableZTexture = (!bpmem.zcontrol.zcomploc && bpmem.zmode.testenable && bpmem.zmode.updateenable)?1:0;
uid->values[3] = (u32)bpmem.fog.c_proj_fsel.fsel |
uid->values[2] = (u32)bpmem.fog.c_proj_fsel.fsel |
((u32)bpmem.fog.c_proj_fsel.proj << 3) |
((u32)enableZTexture << 4);
int hdr = 4;
if(g_ActiveConfig.bEnablePixelLigting)
{
for (int i = 0; i < 2; ++i) {
uid->values[3 + i] = xfregs.colChans[i].color.enablelighting ?
(u32)xfregs.colChans[i].color.hex :
(u32)xfregs.colChans[i].color.matsource;
uid->values[3 + i] |= (xfregs.colChans[i].alpha.enablelighting ?
(u32)xfregs.colChans[i].alpha.hex :
(u32)xfregs.colChans[i].alpha.matsource) << 15;
}
}
uid->values[4] |= g_ActiveConfig.bEnablePixelLigting << 31;
int hdr = 5;
u32 *pcurvalue = &uid->values[hdr];
for (u32 i = 0; i < numstages; ++i)
{
@ -135,7 +148,8 @@ void GetPixelShaderId(PIXELSHADERUID *uid, u32 dstAlphaEnable)
}
// yeah, well ....
uid->indstages = (u32)(pcurvalue - &uid->values[0] - (hdr - 1) - uid->tevstages);
uid->indstages = (u32)(pcurvalue - &uid->values[0] - (hdr - 1) - uid->tevstages);
}
// old tev->pixelshader notes
@ -366,7 +380,69 @@ static void BuildSwapModeTable()
}
}
const char *GeneratePixelShaderCode(bool dstAlphaEnable, API_TYPE ApiType)
char *GeneratePixelLightShader(char *p, int index, const LitChannel& chan, const char *dest, int coloralpha)
{
const char* swizzle = "xyzw";
if (coloralpha == 1 ) swizzle = "xyz";
else if (coloralpha == 2 ) swizzle = "w";
if (!(chan.attnfunc & 1)) {
// atten disabled
switch (chan.diffusefunc) {
case LIGHTDIF_NONE:
WRITE(p, "%s.%s += "I_PLIGHTS".lights[%d].col.%s;\n", dest, swizzle, index, swizzle);
break;
case LIGHTDIF_SIGN:
case LIGHTDIF_CLAMP:
WRITE(p, "ldir = normalize("I_PLIGHTS".lights[%d].pos.xyz - pos.xyz);\n", index);
WRITE(p, "%s.%s += %sdot(ldir, _norm0)) * "I_PLIGHTS".lights[%d].col.%s;\n",
dest, swizzle, chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0f," :"(", index, swizzle);
break;
default: _assert_(0);
}
}
else { // spec and spot
if (chan.attnfunc == 3)
{ // spot
WRITE(p, "ldir = "I_PLIGHTS".lights[%d].pos.xyz - pos.xyz;\n", index);
WRITE(p, "dist2 = dot(ldir, ldir);\n"
"dist = sqrt(dist2);\n"
"ldir = ldir / dist;\n"
"attn = max(0.0f, dot(ldir, "I_PLIGHTS".lights[%d].dir.xyz));\n",index);
WRITE(p, "attn = max(0.0f, dot("I_PLIGHTS".lights[%d].cosatt.xyz, float3(1.0f, attn, attn*attn))) / dot("I_PLIGHTS".lights[%d].distatt.xyz, float3(1.0f,dist,dist2));\n", index, index);
}
else if (chan.attnfunc == 1)
{ // specular
WRITE(p, "ldir = normalize("I_PLIGHTS".lights[%d].pos.xyz);\n",index);
WRITE(p, "attn = (dot(_norm0,ldir) > 0.0f) ? max(0.0f, dot(_norm0, "I_PLIGHTS".lights[%d].dir.xyz)) : 0.0f;\n", index);
WRITE(p, "attn = max(0.0f, dot("I_PLIGHTS".lights[%d].cosatt.xyz, float3(1,attn,attn*attn))) / dot("I_PLIGHTS".lights[%d].distatt.xyz, float3(1,attn,attn*attn));\n", index, index);
}
switch (chan.diffusefunc)
{
case LIGHTDIF_NONE:
WRITE(p, "%s.%s += attn * "I_PLIGHTS".lights[%d].col.%s;\n", dest, swizzle, index, swizzle);
break;
case LIGHTDIF_SIGN:
case LIGHTDIF_CLAMP:
WRITE(p, "%s.%s += attn * %sdot(ldir, _norm0)) * "I_PLIGHTS".lights[%d].col.%s;\n",
dest,
swizzle,
chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0f," :"(",
index,
swizzle);
break;
default: _assert_(0);
}
}
WRITE(p, "\n");
return p;
}
const char *GeneratePixelShaderCode(bool dstAlphaEnable, API_TYPE ApiType,u32 components)
{
setlocale(LC_NUMERIC, "C"); // Reset locale for compilation
text[sizeof(text) - 1] = 0x7C; // canary
@ -431,10 +507,18 @@ const char *GeneratePixelShaderCode(bool dstAlphaEnable, API_TYPE ApiType)
WRITE(p, "uniform float4 "I_INDTEXSCALE"[2] : register(c%d);\n", C_INDTEXSCALE);
WRITE(p, "uniform float4 "I_INDTEXMTX"[6] : register(c%d);\n", C_INDTEXMTX);
WRITE(p, "uniform float4 "I_FOG"[2] : register(c%d);\n", C_FOG);
if(g_ActiveConfig.bEnablePixelLigting)
{
WRITE(p,"typedef struct { float4 col; float4 cosatt; float4 distatt; float4 pos; float4 dir; } Light;\n");
WRITE(p,"typedef struct { Light lights[8]; } s_"I_PLIGHTS";\n");
WRITE(p, "uniform s_"I_PLIGHTS" "I_PLIGHTS" : register(c%d);\n", C_PLIGHTS);
WRITE(p, "typedef struct { float4 C0, C1, C2, C3; } s_"I_PMATERIALS";\n");
WRITE(p, "uniform s_"I_PMATERIALS" "I_PMATERIALS" : register(c%d);\n", C_PMATERIALS);
}
WRITE(p, "void main(\n");
if(ApiType != API_D3D11)
WRITE(p, " out float4 ocol0 : COLOR0,%s\n in float4 rawpos : POSITION,\n",DepthTextureEnable ? "\n out float depth : DEPTH," : "");
WRITE(p, " out float4 ocol0 : COLOR0,%s\n in float4 rawpos : %s,\n",DepthTextureEnable ? "\n out float depth : DEPTH," : "", ApiType == API_OPENGL ? "WPOS" : "POSITION");
else
WRITE(p, " out float4 ocol0 : SV_Target,%s\n in float4 rawpos : SV_Position,\n",DepthTextureEnable ? "\n out float depth : SV_Depth," : "");
@ -446,14 +530,14 @@ const char *GeneratePixelShaderCode(bool dstAlphaEnable, API_TYPE ApiType)
{
for (int i = 0; i < numTexgen; ++i)
WRITE(p, ",\n in float3 uv%d : TEXCOORD%d", i, i);
WRITE(p, ",\n in float4 clipPos : TEXCOORD%d", numTexgen);
WRITE(p, ",\n in float4 Normal : TEXCOORD%d", numTexgen + 1);
}
else
{
// wpos is in w of first 4 texcoords
for (int i = 0; i < numTexgen; ++i)
WRITE(p, ",\n in float%d uv%d : TEXCOORD%d", i<4?4:3, i, i);
for (int i = 0; i < 8; ++i)
WRITE(p, ",\n in float4 uv%d : TEXCOORD%d", i, i);
}
WRITE(p, " ) {\n");
@ -466,7 +550,138 @@ const char *GeneratePixelShaderCode(bool dstAlphaEnable, API_TYPE ApiType)
" float3 tevcoord;\n"
" float2 wrappedcoord, tempcoord;\n"
" float4 cc0, cc1, cc2, cprev,crastemp,ckonsttemp;\n\n");
if(g_ActiveConfig.bEnablePixelLigting)
{
if (xfregs.numTexGens < 7)
{
WRITE(p,"float3 _norm0 = normalize(Normal.xyz);\n\n");
WRITE(p,"float3 pos = float3(clipPos.x,clipPos.y,Normal.w);\n");
}
else
{
WRITE(p," float3 _norm0 = normalize(float3(uv4.w,uv5.w,uv6.w));\n\n");
WRITE(p,"float3 pos = float3(uv0.w,uv1.w,uv7.w);\n");
}
WRITE(p, "float4 mat, lacc;\n"
"float3 ldir, h;\n"
"float dist, dist2, attn;\n");
// lights/colors
for (int j = 0; j < xfregs.nNumChans; j++)
{
const LitChannel& color = xfregs.colChans[j].color;
const LitChannel& alpha = xfregs.colChans[j].alpha;
WRITE(p, "{\n");
if (color.matsource) {// from vertex
if (components & (VB_HAS_COL0 << j))
WRITE(p, "mat = colors_%d;\n", j);
else if (components & VB_HAS_COL0)
WRITE(p, "mat = colors_0;\n");
else
WRITE(p, "mat = float4(1.0f, 1.0f, 1.0f, 1.0f);\n");
}
else // from color
WRITE(p, "mat = "I_PMATERIALS".C%d;\n", j+2);
if (color.enablelighting) {
if (color.ambsource) { // from vertex
if (components & (VB_HAS_COL0<<j) )
WRITE(p, "lacc = colors_%d;\n", j);
else if (components & VB_HAS_COL0 )
WRITE(p, "lacc = colors_0;\n");
else
WRITE(p, "lacc = float4(0.0f, 0.0f, 0.0f, 0.0f);\n");
}
else // from color
WRITE(p, "lacc = "I_PMATERIALS".C%d;\n", j);
}
else
{
WRITE(p, "lacc = float4(1.0f, 1.0f, 1.0f, 1.0f);\n");
}
// check if alpha is different
if (alpha.matsource != color.matsource) {
if (alpha.matsource) {// from vertex
if (components & (VB_HAS_COL0<<j))
WRITE(p, "mat.w = colors_%d.w;\n", j);
else if (components & VB_HAS_COL0)
WRITE(p, "mat.w = colors_0.w;\n");
else WRITE(p, "mat.w = 1.0f;\n");
}
else // from color
WRITE(p, "mat.w = "I_PMATERIALS".C%d.w;\n", j+2);
}
if (alpha.enablelighting)
{
if (alpha.ambsource) {// from vertex
if (components & (VB_HAS_COL0<<j) )
WRITE(p, "lacc.w = colors_%d.w;\n", j);
else if (components & VB_HAS_COL0 )
WRITE(p, "lacc.w = colors_0.w;\n");
else
WRITE(p, "lacc.w = 0.0f;\n");
}
else // from color
WRITE(p, "lacc.w = "I_PMATERIALS".C%d.w;\n", j);
}
else
{
WRITE(p, "lacc.w = 1.0f;\n");
}
if(color.enablelighting && alpha.enablelighting)
{
// both have lighting, test if they use the same lights
int mask = 0;
if(color.lightparams == alpha.lightparams)
{
mask = color.GetFullLightMask() & alpha.GetFullLightMask();
if(mask)
{
for (int i = 0; i < 8; ++i)
{
if (mask & (1<<i))
p = GeneratePixelLightShader(p, i, color, "lacc", 3);
}
}
}
// no shared lights
for (int i = 0; i < 8; ++i)
{
if (!(mask&(1<<i)) && (color.GetFullLightMask() & (1<<i)))
p = GeneratePixelLightShader(p, i, color, "lacc", 1);
if (!(mask&(1<<i)) && (alpha.GetFullLightMask() & (1<<i)))
p = GeneratePixelLightShader(p, i, alpha, "lacc", 2);
}
}
else if (color.enablelighting || alpha.enablelighting)
{
// lights are disabled on one channel so process only the active ones
LitChannel workingchannel = color.enablelighting ? color : alpha;
int coloralpha = color.enablelighting ? 1 : 2;
for (int i = 0; i < 8; ++i)
{
if (workingchannel.GetFullLightMask() & (1<<i))
p = GeneratePixelLightShader(p, i, workingchannel, "lacc", coloralpha);
}
}
WRITE(p, "colors_%d = mat * saturate(lacc);\n", j);
WRITE(p, "}\n");
}
}
if (numTexgen < 7)
WRITE(p, "clipPos = float4(rawpos.x, rawpos.y, clipPos.z, clipPos.w);\n");
else
WRITE(p, "float4 clipPos = float4(rawpos.x, rawpos.y, uv2.w, uv3.w);\n");
// HACK to handle cases where the tex gen is not enabled
if (numTexgen == 0)
{
@ -479,8 +694,7 @@ const char *GeneratePixelShaderCode(bool dstAlphaEnable, API_TYPE ApiType)
// optional perspective divides
if (xfregs.texcoords[i].texmtxinfo.projection == XF_TEXPROJ_STQ)
WRITE(p, "uv%d.xy = uv%d.xy/uv%d.z;\n", i, i, i);
// scale texture coordinates
WRITE(p, "uv%d.xy = uv%d.xy * "I_TEXDIMS"[%d].zw;\n", i, i, i);
}
}
@ -552,8 +766,7 @@ const char *GeneratePixelShaderCode(bool dstAlphaEnable, API_TYPE ApiType)
{
if((bpmem.fog.c_proj_fsel.fsel != 0) || DepthTextureEnable)
{
if (numTexgen >= 7)
WRITE(p, "float4 clipPos = float4(uv0.w, uv1.w, uv2.w, uv3.w);\n");
// the screen space depth value = far z + (clip z / clip w) * z range
WRITE(p, "float zCoord = "I_ZBIAS"[1].x + (clipPos.z / clipPos.w) * "I_ZBIAS"[1].y;\n");
}
@ -579,7 +792,7 @@ const char *GeneratePixelShaderCode(bool dstAlphaEnable, API_TYPE ApiType)
{
WriteFog(p);
WRITE(p, " ocol0 = prev;\n");
}
}
}
WRITE(p, "}\n");
if (text[sizeof(text) - 1] != 0x7C)