mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-21 05:09:34 -06:00
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:
@ -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)
|
||||
|
Reference in New Issue
Block a user