Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #439 from degasus/lighting-fix
Lighting cleanup
  • Loading branch information
neobrain committed Jun 21, 2014
2 parents ddadb4f + 924ad1e commit fbca397
Show file tree
Hide file tree
Showing 15 changed files with 158 additions and 197 deletions.
5 changes: 3 additions & 2 deletions Source/Core/VideoBackends/D3D/Render.cpp
Expand Up @@ -1087,8 +1087,9 @@ void Renderer::ApplyState(bool bUseDstAlpha)
SetLogicOpMode();
}

D3D::context->PSSetConstantBuffers(0, 1, &PixelShaderCache::GetConstantBuffer());
D3D::context->VSSetConstantBuffers(0, 1, &VertexShaderCache::GetConstantBuffer());
ID3D11Buffer* const_buffers[2] = {PixelShaderCache::GetConstantBuffer(), VertexShaderCache::GetConstantBuffer()};
D3D::context->PSSetConstantBuffers(0, 1 + g_ActiveConfig.bEnablePixelLighting, const_buffers);
D3D::context->VSSetConstantBuffers(0, 1, const_buffers+1);

D3D::context->PSSetShader(PixelShaderCache::GetActiveShader(), nullptr, 0);
D3D::context->VSSetShader(VertexShaderCache::GetActiveShader(), nullptr, 0);
Expand Down
6 changes: 3 additions & 3 deletions Source/Core/VideoBackends/Software/TransformUnit.cpp
Expand Up @@ -210,7 +210,7 @@ inline float SafeDivide(float n, float d)

void LightColor(const Vec3 &pos, const Vec3 &normal, u8 lightNum, const LitChannel &chan, Vec3 &lightCol)
{
const LightPointer *light = (const LightPointer*)&xfmem.lights[0x10*lightNum];
const LightPointer *light = (const LightPointer*)&xfmem.lights[lightNum];

if (!(chan.attnfunc & 1))
{
Expand Down Expand Up @@ -295,7 +295,7 @@ void LightColor(const Vec3 &pos, const Vec3 &normal, u8 lightNum, const LitChann

void LightAlpha(const Vec3 &pos, const Vec3 &normal, u8 lightNum, const LitChannel &chan, float &lightCol)
{
const LightPointer *light = (const LightPointer*)&xfmem.lights[0x10*lightNum];
const LightPointer *light = (const LightPointer*)&xfmem.lights[lightNum];

if (!(chan.attnfunc & 1))
{
Expand Down Expand Up @@ -476,7 +476,7 @@ void TransformTexCoord(const InputVertexData *src, OutputVertexData *dst, bool s
break;
case XF_TEXGEN_EMBOSS_MAP:
{
const LightPointer *light = (const LightPointer*)&xfmem.lights[0x10*texinfo.embosslightshift];
const LightPointer *light = (const LightPointer*)&xfmem.lights[texinfo.embosslightshift];

Vec3 ldir = (light->pos - dst->mvPosition).normalized();
float d1 = ldir * dst->normal[1];
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/VideoBackends/Software/XFMemLoader.cpp
Expand Up @@ -23,7 +23,7 @@ void XFWritten(u32 transferSize, u32 baseAddress)
// fix lights so invalid values don't trash the lighting computations
if (baseAddress <= 0x067f && topAddress >= 0x0604)
{
u32* x = xfmem.lights;
u32* x = (u32*)xfmem.lights;

// go through all lights
for (int light = 0; light < 8; light++)
Expand Down
16 changes: 9 additions & 7 deletions Source/Core/VideoCommon/ConstantManager.h
Expand Up @@ -21,23 +21,25 @@ struct PixelShaderConstants
int4 fogcolor;
int4 fogi;
float4 fogf[2];

// For pixel lighting
int4 plight_colors[8];
float4 plights[32];
int4 pmaterials[4];
};

struct VertexShaderConstants
{
float4 posnormalmatrix[6];
float4 projection[4];
int4 materials[4];
int4 light_colors[8]; // 8 lights
float4 lights[32]; // 8 lights * 4 parameters
struct Light
{
int4 color;
float4 cosatt;
float4 distatt;
float4 pos;
float4 dir;
} lights [8];
float4 texmatrices[24];
float4 transformmatrices[64];
float4 normalmatrices[32];
float4 posttransformmatrices[64];
float4 depthparams;
};

73 changes: 41 additions & 32 deletions Source/Core/VideoCommon/LightingShaderGen.h
Expand Up @@ -4,25 +4,26 @@

#pragma once

#include "VideoCommon/ConstantManager.h"
#include "VideoCommon/NativeVertexFormat.h"
#include "VideoCommon/ShaderGenCommon.h"
#include "VideoCommon/XFMemory.h"


#define LIGHT_COL "%s[%d].%s"
#define LIGHT_COL_PARAMS(lightsColName, index, swizzle) (lightsColName), (index), (swizzle)
#define LIGHT_COL "%s[%d].color.%s"
#define LIGHT_COL_PARAMS(index, swizzle) (I_LIGHTS), (index), (swizzle)

#define LIGHT_COSATT "%s[4*%d]"
#define LIGHT_COSATT_PARAMS(lightsName, index) (lightsName), (index)
#define LIGHT_COSATT "%s[%d].cosatt"
#define LIGHT_COSATT_PARAMS(index) (I_LIGHTS), (index)

#define LIGHT_DISTATT "%s[4*%d+1]"
#define LIGHT_DISTATT_PARAMS(lightsName, index) (lightsName), (index)
#define LIGHT_DISTATT "%s[%d].distatt"
#define LIGHT_DISTATT_PARAMS(index) (I_LIGHTS), (index)

#define LIGHT_POS "%s[4*%d+2]"
#define LIGHT_POS_PARAMS(lightsName, index) (lightsName), (index)
#define LIGHT_POS "%s[%d].pos"
#define LIGHT_POS_PARAMS(index) (I_LIGHTS), (index)

#define LIGHT_DIR "%s[4*%d+3]"
#define LIGHT_DIR_PARAMS(lightsName, index) (lightsName), (index)
#define LIGHT_DIR "%s[%d].dir"
#define LIGHT_DIR_PARAMS(index) (I_LIGHTS), (index)

/**
* Common uid data used for shader generators that use lighting calculations.
Expand All @@ -37,9 +38,17 @@ struct LightingUidData
u32 light_mask : 32; // 4x8 bits
};

static const char s_lighting_struct[] =
"struct Light {\n"
"\tint4 color;\n"
"\tfloat4 cosatt;\n"
"\tfloat4 distatt;\n"
"\tfloat4 pos;\n"
"\tfloat4 dir;\n"
"};\n";

template<class T>
static void GenerateLightShader(T& object, LightingUidData& uid_data, int index, int litchan_index, const char* lightsColName, const char* lightsName, int coloralpha)
static void GenerateLightShader(T& object, LightingUidData& uid_data, int index, int litchan_index, int coloralpha)
{
const LitChannel& chan = (litchan_index > 1) ? xfmem.alpha[litchan_index-2] : xfmem.color[litchan_index];
const char* swizzle = (coloralpha == 1) ? "xyz" : (coloralpha == 2) ? "w" : "xyzw";
Expand All @@ -53,14 +62,14 @@ static void GenerateLightShader(T& object, LightingUidData& uid_data, int index,
switch (chan.diffusefunc)
{
case LIGHTDIF_NONE:
object.Write("lacc.%s += " LIGHT_COL";\n", swizzle, LIGHT_COL_PARAMS(lightsColName, index, swizzle));
object.Write("lacc.%s += " LIGHT_COL";\n", swizzle, LIGHT_COL_PARAMS(index, swizzle));
break;
case LIGHTDIF_SIGN:
case LIGHTDIF_CLAMP:
object.Write("ldir = normalize(" LIGHT_POS".xyz - pos.xyz);\n", LIGHT_POS_PARAMS(lightsName, index));
object.Write("ldir = normalize(" LIGHT_POS".xyz - pos.xyz);\n", LIGHT_POS_PARAMS(index));
object.Write("lacc.%s += int%s(round(%sdot(ldir, _norm0)) * float%s(" LIGHT_COL")));\n",
swizzle, swizzle_components, chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0," :"(",
swizzle_components, LIGHT_COL_PARAMS(lightsColName, index, swizzle));
swizzle_components, LIGHT_COL_PARAMS(index, swizzle));
break;
default: _assert_(0);
}
Expand All @@ -69,39 +78,39 @@ static void GenerateLightShader(T& object, LightingUidData& uid_data, int index,
{
if (chan.attnfunc == 3)
{ // spot
object.Write("ldir = " LIGHT_POS".xyz - pos.xyz;\n", LIGHT_POS_PARAMS(lightsName, index));
object.Write("ldir = " LIGHT_POS".xyz - pos.xyz;\n", LIGHT_POS_PARAMS(index));
object.Write("dist2 = dot(ldir, ldir);\n"
"dist = sqrt(dist2);\n"
"ldir = ldir / dist;\n"
"attn = max(0.0, dot(ldir, " LIGHT_DIR".xyz));\n",
LIGHT_DIR_PARAMS(lightsName, index));
LIGHT_DIR_PARAMS(index));
// attn*attn may overflow
object.Write("attn = max(0.0, " LIGHT_COSATT".x + " LIGHT_COSATT".y*attn + " LIGHT_COSATT".z*attn*attn) / dot(" LIGHT_DISTATT".xyz, float3(1.0,dist,dist2));\n",
LIGHT_COSATT_PARAMS(lightsName, index), LIGHT_COSATT_PARAMS(lightsName, index), LIGHT_COSATT_PARAMS(lightsName, index), LIGHT_DISTATT_PARAMS(lightsName, index));
LIGHT_COSATT_PARAMS(index), LIGHT_COSATT_PARAMS(index), LIGHT_COSATT_PARAMS(index), LIGHT_DISTATT_PARAMS(index));
}
else if (chan.attnfunc == 1)
{ // specular
object.Write("ldir = normalize(" LIGHT_POS".xyz);\n", LIGHT_POS_PARAMS(lightsName, index));
object.Write("attn = (dot(_norm0,ldir) >= 0.0) ? max(0.0, dot(_norm0, " LIGHT_DIR".xyz)) : 0.0;\n", LIGHT_DIR_PARAMS(lightsName, index));
object.Write("ldir = normalize(" LIGHT_POS".xyz);\n", LIGHT_POS_PARAMS(index));
object.Write("attn = (dot(_norm0,ldir) >= 0.0) ? max(0.0, dot(_norm0, " LIGHT_DIR".xyz)) : 0.0;\n", LIGHT_DIR_PARAMS(index));
// attn*attn may overflow
object.Write("attn = max(0.0, " LIGHT_COSATT".x + " LIGHT_COSATT".y*attn + " LIGHT_COSATT".z*attn*attn) / (" LIGHT_DISTATT".x + " LIGHT_DISTATT".y*attn + " LIGHT_DISTATT".z*attn*attn);\n",
LIGHT_COSATT_PARAMS(lightsName, index), LIGHT_COSATT_PARAMS(lightsName, index), LIGHT_COSATT_PARAMS(lightsName, index),
LIGHT_DISTATT_PARAMS(lightsName, index), LIGHT_DISTATT_PARAMS(lightsName, index), LIGHT_DISTATT_PARAMS(lightsName, index));
LIGHT_COSATT_PARAMS(index), LIGHT_COSATT_PARAMS(index), LIGHT_COSATT_PARAMS(index),
LIGHT_DISTATT_PARAMS(index), LIGHT_DISTATT_PARAMS(index), LIGHT_DISTATT_PARAMS(index));
}

switch (chan.diffusefunc)
{
case LIGHTDIF_NONE:
object.Write("lacc.%s += int%s(round(attn * float%s(" LIGHT_COL")));\n",
swizzle, swizzle_components,
swizzle_components, LIGHT_COL_PARAMS(lightsColName, index, swizzle));
swizzle_components, LIGHT_COL_PARAMS(index, swizzle));
break;
case LIGHTDIF_SIGN:
case LIGHTDIF_CLAMP:
object.Write("lacc.%s += int%s(round(attn * %sdot(ldir, _norm0)) * float%s(" LIGHT_COL")));\n",
swizzle, swizzle_components,
chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0," :"(",
swizzle_components, LIGHT_COL_PARAMS(lightsColName, index, swizzle));
swizzle_components, LIGHT_COL_PARAMS(index, swizzle));
break;
default: _assert_(0);
}
Expand All @@ -115,7 +124,7 @@ static void GenerateLightShader(T& object, LightingUidData& uid_data, int index,
// inColorName is color in vs and colors_ in ps
// dest is o.colors_ in vs and colors_ in ps
template<class T>
static void GenerateLightingShader(T& object, LightingUidData& uid_data, int components, const char* materialsName, const char* lightsColName, const char* lightsName, const char* inColorName, const char* dest)
static void GenerateLightingShader(T& object, LightingUidData& uid_data, int components, const char* inColorName, const char* dest)
{
for (unsigned int j = 0; j < xfmem.numChan.numColorChans; j++)
{
Expand All @@ -136,7 +145,7 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
}
else // from color
{
object.Write("int4 mat = %s[%d];\n", materialsName, j+2);
object.Write("int4 mat = %s[%d];\n", I_MATERIALS, j+2);
}

uid_data.enablelighting |= xfmem.color[j].enablelighting << j;
Expand All @@ -157,7 +166,7 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
}
else // from color
{
object.Write("lacc = %s[%d];\n", materialsName, j);
object.Write("lacc = %s[%d];\n", I_MATERIALS, j);
}
}
else
Expand All @@ -179,7 +188,7 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
}
else // from color
{
object.Write("mat.w = %s[%d].w;\n", materialsName, j+2);
object.Write("mat.w = %s[%d].w;\n", I_MATERIALS, j+2);
}
}

Expand All @@ -199,7 +208,7 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
}
else // from color
{
object.Write("lacc.w = %s[%d].w;\n", materialsName, j);
object.Write("lacc.w = %s[%d].w;\n", I_MATERIALS, j);
}
}
else
Expand All @@ -226,7 +235,7 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
{
if (mask & (1<<i))
{
GenerateLightShader<T>(object, uid_data, i, j, lightsColName, lightsName, 3);
GenerateLightShader<T>(object, uid_data, i, j, 3);
}
}
}
Expand All @@ -236,9 +245,9 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
for (int i = 0; i < 8; ++i)
{
if (!(mask&(1<<i)) && (color.GetFullLightMask() & (1<<i)))
GenerateLightShader<T>(object, uid_data, i, j, lightsColName, lightsName, 1);
GenerateLightShader<T>(object, uid_data, i, j, 1);
if (!(mask&(1<<i)) && (alpha.GetFullLightMask() & (1<<i)))
GenerateLightShader<T>(object, uid_data, i, j+2, lightsColName, lightsName, 2);
GenerateLightShader<T>(object, uid_data, i, j+2, 2);
}
}
else if (color.enablelighting || alpha.enablelighting)
Expand All @@ -252,7 +261,7 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
for (int i = 0; i < 8; ++i)
{
if (workingchannel.GetFullLightMask() & (1<<i))
GenerateLightShader<T>(object, uid_data, i, lit_index, lightsColName, lightsName, coloralpha);
GenerateLightShader<T>(object, uid_data, i, lit_index, coloralpha);
}
}
object.Write("lacc = clamp(lacc, 0, 255);");
Expand Down
46 changes: 36 additions & 10 deletions Source/Core/VideoCommon/PixelShaderGen.cpp
Expand Up @@ -11,6 +11,7 @@
#endif

#include "VideoCommon/BPMemory.h"
#include "VideoCommon/ConstantManager.h"
#include "VideoCommon/LightingShaderGen.h"
#include "VideoCommon/NativeVertexFormat.h"
#include "VideoCommon/PixelShaderGen.h"
Expand Down Expand Up @@ -218,9 +219,13 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
out.Write("\n");

if (ApiType == API_OPENGL)
{
out.Write("layout(std140%s) uniform PSBlock {\n", g_ActiveConfig.backend_info.bSupportsBindingLayout ? ", binding = 1" : "");
}
else
out.Write("cbuffer PSBlock {\n");
{
out.Write("cbuffer PSBlock : register(b0) {\n");
}
out.Write(
"\tint4 " I_COLORS"[4];\n"
"\tint4 " I_KCOLORS"[4];\n"
Expand All @@ -232,13 +237,32 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
"\tint4 " I_FOGCOLOR";\n"
"\tint4 " I_FOGI";\n"
"\tfloat4 " I_FOGF"[2];\n"

// For pixel lighting - TODO: Should only be defined when per pixel lighting is enabled!
"\tint4 " I_PLIGHT_COLORS"[8];\n"
"\tfloat4 " I_PLIGHTS"[32];\n"
"\tint4 " I_PMATERIALS"[4];\n"
"};\n");

if (g_ActiveConfig.bEnablePixelLighting)
{
out.Write("%s", s_lighting_struct);

if (ApiType == API_OPENGL)
{
out.Write("layout(std140%s) uniform VSBlock {\n", g_ActiveConfig.backend_info.bSupportsBindingLayout ? ", binding = 2" : "");
}
else
{
out.Write("cbuffer VSBlock : register(b1) {\n");
}
out.Write(
"\tfloat4 " I_POSNORMALMATRIX"[6];\n"
"\tfloat4 " I_PROJECTION"[4];\n"
"\tint4 " I_MATERIALS"[4];\n"
"\tLight " I_LIGHTS"[8];\n"
"\tfloat4 " I_TEXMATRICES"[24];\n"
"\tfloat4 " I_TRANSFORMMATRICES"[64];\n"
"\tfloat4 " I_NORMALMATRICES"[32];\n"
"\tfloat4 " I_POSTTRANSFORMMATRICES"[64];\n"
"\tfloat4 " I_DEPTHPARAMS";\n"
"};\n");
}
const bool forced_early_z = g_ActiveConfig.backend_info.bSupportsEarlyZ && bpmem.UseEarlyDepthTest() && (g_ActiveConfig.bFastDepthCalc || bpmem.alpha_test.TestResult() == AlphaTest::UNDETERMINED);
const bool per_pixel_depth = (bpmem.ztex2.op != ZTEXTURE_DISABLE && bpmem.UseLateDepthTest()) || (!g_ActiveConfig.bFastDepthCalc && bpmem.zmode.testenable && !forced_early_z);

Expand Down Expand Up @@ -351,11 +375,13 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
"\tfloat3 ldir, h;\n"
"\tfloat dist, dist2, attn;\n");

out.SetConstantsUsed(C_PLIGHT_COLORS, C_PLIGHT_COLORS+7); // TODO: Can be optimized further
out.SetConstantsUsed(C_PLIGHTS, C_PLIGHTS+31); // TODO: Can be optimized further
out.SetConstantsUsed(C_PMATERIALS, C_PMATERIALS+3);
// TODO: Our current constant usage code isn't able to handle more than one buffer.
// So we can't mark the VS constant as used here. But keep them here as reference.
//out.SetConstantsUsed(C_PLIGHT_COLORS, C_PLIGHT_COLORS+7); // TODO: Can be optimized further
//out.SetConstantsUsed(C_PLIGHTS, C_PLIGHTS+31); // TODO: Can be optimized further
//out.SetConstantsUsed(C_PMATERIALS, C_PMATERIALS+3);
uid_data.components = components;
GenerateLightingShader<T>(out, uid_data.lighting, components, I_PMATERIALS, I_PLIGHT_COLORS, I_PLIGHTS, "colors_", "colors_");
GenerateLightingShader<T>(out, uid_data.lighting, components, "colors_", "colors_");
}

// HACK to handle cases where the tex gen is not enabled
Expand Down
19 changes: 1 addition & 18 deletions Source/Core/VideoCommon/PixelShaderGen.h
Expand Up @@ -9,20 +9,6 @@
#include "VideoCommon/ShaderGenCommon.h"
#include "VideoCommon/VideoCommon.h"

#define I_COLORS "color"
#define I_KCOLORS "k"
#define I_ALPHA "alphaRef"
#define I_TEXDIMS "texdim"
#define I_ZBIAS "czbias"
#define I_INDTEXSCALE "cindscale"
#define I_INDTEXMTX "cindmtx"
#define I_FOGCOLOR "cfogcolor"
#define I_FOGI "cfogi"
#define I_FOGF "cfogf"
#define I_PLIGHT_COLORS "cPLightColors"
#define I_PLIGHTS "cPLights"
#define I_PMATERIALS "cPmtrl"

// TODO: get rid of them as they aren't used
#define C_COLORMATRIX 0 // 0
#define C_COLORS 0 // 0
Expand All @@ -36,10 +22,7 @@
#define C_FOGI (C_FOGCOLOR + 1) //28
#define C_FOGF (C_FOGI + 1) //29

#define C_PLIGHT_COLORS (C_FOGF + 2)
#define C_PLIGHTS (C_PLIGHT_COLORS + 8)
#define C_PMATERIALS (C_PLIGHTS + 32)
#define C_PENVCONST_END (C_PMATERIALS + 4)
#define C_PENVCONST_END (C_FOGF + 2)

// Different ways to achieve rendering with destination alpha
enum DSTALPHA_MODE
Expand Down

0 comments on commit fbca397

Please sign in to comment.