+1
This commit is contained in:
@@ -116,11 +116,8 @@ ComputeZBounds(
|
|||||||
float laneMinZ = cameraFar;
|
float laneMinZ = cameraFar;
|
||||||
float laneMaxZ = cameraNear;
|
float laneMaxZ = cameraNear;
|
||||||
for (uniform int32 y = tileStartY; y < tileEndY; ++y) {
|
for (uniform int32 y = tileStartY; y < tileEndY; ++y) {
|
||||||
// foreach (x = tileStartX ... tileEndX)
|
foreach (x = tileStartX ... tileEndX)
|
||||||
for (uniform int xb = tileStartX; xb < tileEndX; xb += programCount)
|
|
||||||
{
|
{
|
||||||
const int x = xb + programIndex;
|
|
||||||
if (x >= tileEndX) break;
|
|
||||||
// Unproject depth buffer Z value into view space
|
// Unproject depth buffer Z value into view space
|
||||||
float z = zBuffer[y * gBufferWidth + x];
|
float z = zBuffer[y * gBufferWidth + x];
|
||||||
float viewSpaceZ = cameraProj_43 / (z - cameraProj_33);
|
float viewSpaceZ = cameraProj_43 / (z - cameraProj_33);
|
||||||
@@ -182,10 +179,8 @@ IntersectLightsWithTileMinMax(
|
|||||||
|
|
||||||
uniform int32 tileNumLights = 0;
|
uniform int32 tileNumLights = 0;
|
||||||
|
|
||||||
// foreach (lightIndex = 0 ... numLights)
|
foreach (lightIndex = 0 ... numLights)
|
||||||
for (uniform int lightIndexB = 0; lightIndexB < numLights; lightIndexB += programCount)
|
|
||||||
{
|
{
|
||||||
const int lightIndex = lightIndexB + programIndex;
|
|
||||||
float light_positionView_z = light_positionView_z_array[lightIndex];
|
float light_positionView_z = light_positionView_z_array[lightIndex];
|
||||||
float light_attenuationEnd = light_attenuationEnd_array[lightIndex];
|
float light_attenuationEnd = light_attenuationEnd_array[lightIndex];
|
||||||
float light_attenuationEndNeg = -light_attenuationEnd;
|
float light_attenuationEndNeg = -light_attenuationEnd;
|
||||||
@@ -292,11 +287,8 @@ ShadeTile(
|
|||||||
if (tileNumLights == 0 || visualizeLightCount) {
|
if (tileNumLights == 0 || visualizeLightCount) {
|
||||||
uniform unsigned int8 c = (unsigned int8)(min(tileNumLights << 2, 255));
|
uniform unsigned int8 c = (unsigned int8)(min(tileNumLights << 2, 255));
|
||||||
for (uniform int32 y = tileStartY; y < tileEndY; ++y) {
|
for (uniform int32 y = tileStartY; y < tileEndY; ++y) {
|
||||||
// foreach (x = tileStartX ... tileEndX)
|
foreach (x = tileStartX ... tileEndX)
|
||||||
for (uniform int xb = tileStartX ; xb < tileEndX; xb += programCount)
|
|
||||||
{
|
{
|
||||||
const int x = xb + programIndex;
|
|
||||||
if (x >= tileEndX) continue;
|
|
||||||
int32 framebufferIndex = (y * gBufferWidth + x);
|
int32 framebufferIndex = (y * gBufferWidth + x);
|
||||||
framebuffer_r[framebufferIndex] = c;
|
framebuffer_r[framebufferIndex] = c;
|
||||||
framebuffer_g[framebufferIndex] = c;
|
framebuffer_g[framebufferIndex] = c;
|
||||||
@@ -310,10 +302,7 @@ ShadeTile(
|
|||||||
for (uniform int32 y = tileStartY; y < tileEndY; ++y) {
|
for (uniform int32 y = tileStartY; y < tileEndY; ++y) {
|
||||||
uniform float positionScreen_y = -(((0.5f + y) * twoOverGBufferHeight) - 1.f);
|
uniform float positionScreen_y = -(((0.5f + y) * twoOverGBufferHeight) - 1.f);
|
||||||
|
|
||||||
// foreach (x = tileStartX ... tileEndX) {
|
foreach (x = tileStartX ... tileEndX) {
|
||||||
for (uniform int xb = tileStartX ; xb < tileEndX; xb += programCount)
|
|
||||||
{
|
|
||||||
const int x = xb + programIndex;
|
|
||||||
int32 gBufferOffset = y * gBufferWidth + x;
|
int32 gBufferOffset = y * gBufferWidth + x;
|
||||||
|
|
||||||
// Reconstruct position and (negative) view vector from G-buffer
|
// Reconstruct position and (negative) view vector from G-buffer
|
||||||
|
|||||||
@@ -127,19 +127,20 @@ ComputeZBounds(
|
|||||||
// Find Z bounds
|
// Find Z bounds
|
||||||
float laneMinZ = cameraFar;
|
float laneMinZ = cameraFar;
|
||||||
float laneMaxZ = cameraNear;
|
float laneMaxZ = cameraNear;
|
||||||
foreach_tiled (y = tileStartY ... tileEndY, x = tileStartX ... tileEndX)
|
for (uniform int32 y = tileStartY; y < tileEndY; ++y)
|
||||||
{
|
foreach (x = tileStartX ... tileEndX)
|
||||||
// Unproject depth buffer Z value into view space
|
{
|
||||||
float z = zBuffer[y * gBufferWidth + x];
|
// Unproject depth buffer Z value into view space
|
||||||
float viewSpaceZ = cameraProj_43 / (z - cameraProj_33);
|
float z = zBuffer[y * gBufferWidth + x];
|
||||||
|
float viewSpaceZ = cameraProj_43 / (z - cameraProj_33);
|
||||||
|
|
||||||
// Work out Z bounds for our samples
|
// Work out Z bounds for our samples
|
||||||
// Avoid considering skybox/background or otherwise invalid pixels
|
// Avoid considering skybox/background or otherwise invalid pixels
|
||||||
if ((viewSpaceZ < cameraFar) && (viewSpaceZ >= cameraNear)) {
|
if ((viewSpaceZ < cameraFar) && (viewSpaceZ >= cameraNear)) {
|
||||||
laneMinZ = min(laneMinZ, viewSpaceZ);
|
laneMinZ = min(laneMinZ, viewSpaceZ);
|
||||||
laneMaxZ = max(laneMaxZ, viewSpaceZ);
|
laneMaxZ = max(laneMaxZ, viewSpaceZ);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
minZ = reduce_min(laneMinZ);
|
minZ = reduce_min(laneMinZ);
|
||||||
maxZ = reduce_max(laneMaxZ);
|
maxZ = reduce_max(laneMaxZ);
|
||||||
}
|
}
|
||||||
@@ -297,160 +298,163 @@ ShadeTile(
|
|||||||
{
|
{
|
||||||
if (tileNumLights == 0 || visualizeLightCount) {
|
if (tileNumLights == 0 || visualizeLightCount) {
|
||||||
uniform unsigned int8 c = (unsigned int8)(min(tileNumLights << 2, 255));
|
uniform unsigned int8 c = (unsigned int8)(min(tileNumLights << 2, 255));
|
||||||
foreach_tiled (y = tileStartY ... tileEndY, x = tileStartX ... tileEndX)
|
for (uniform int32 y = tileStartY; y < tileEndY; ++y)
|
||||||
{
|
foreach (x = tileStartX ... tileEndX)
|
||||||
int32 framebufferIndex = (y * gBufferWidth + x);
|
{
|
||||||
framebuffer_r[framebufferIndex] = c;
|
int32 framebufferIndex = (y * gBufferWidth + x);
|
||||||
framebuffer_g[framebufferIndex] = c;
|
framebuffer_r[framebufferIndex] = c;
|
||||||
framebuffer_b[framebufferIndex] = c;
|
framebuffer_g[framebufferIndex] = c;
|
||||||
}
|
framebuffer_b[framebufferIndex] = c;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
uniform float twoOverGBufferWidth = 2.0f / gBufferWidth;
|
uniform float twoOverGBufferWidth = 2.0f / gBufferWidth;
|
||||||
uniform float twoOverGBufferHeight = 2.0f / gBufferHeight;
|
uniform float twoOverGBufferHeight = 2.0f / gBufferHeight;
|
||||||
|
|
||||||
foreach_tiled (y = tileStartY ... tileEndY, x = tileStartX ... tileEndX)
|
for (uniform int32 y = tileStartY; y < tileEndY; ++y) {
|
||||||
{
|
uniform float positionScreen_y = -(((0.5f + y) * twoOverGBufferHeight) - 1.f);
|
||||||
float positionScreen_y = -(((0.5f + y) * twoOverGBufferHeight) - 1.f);
|
|
||||||
int32 gBufferOffset = y * gBufferWidth + x;
|
|
||||||
|
|
||||||
// Reconstruct position and (negative) view vector from G-buffer
|
foreach (x = tileStartX ... tileEndX) {
|
||||||
float surface_positionView_x, surface_positionView_y, surface_positionView_z;
|
int32 gBufferOffset = y * gBufferWidth + x;
|
||||||
float Vneg_x, Vneg_y, Vneg_z;
|
|
||||||
|
|
||||||
float z = inputData.zBuffer[gBufferOffset];
|
// Reconstruct position and (negative) view vector from G-buffer
|
||||||
|
float surface_positionView_x, surface_positionView_y, surface_positionView_z;
|
||||||
|
float Vneg_x, Vneg_y, Vneg_z;
|
||||||
|
|
||||||
// Compute screen/clip-space position
|
float z = inputData.zBuffer[gBufferOffset];
|
||||||
// NOTE: Mind DX11 viewport transform and pixel center!
|
|
||||||
float positionScreen_x = (0.5f + (float)(x)) *
|
|
||||||
twoOverGBufferWidth - 1.0f;
|
|
||||||
|
|
||||||
// Unproject depth buffer Z value into view space
|
// Compute screen/clip-space position
|
||||||
surface_positionView_z = cameraProj_43 / (z - cameraProj_33);
|
// NOTE: Mind DX11 viewport transform and pixel center!
|
||||||
surface_positionView_x = positionScreen_x * surface_positionView_z /
|
float positionScreen_x = (0.5f + (float)(x)) *
|
||||||
cameraProj_11;
|
twoOverGBufferWidth - 1.0f;
|
||||||
surface_positionView_y = positionScreen_y * surface_positionView_z /
|
|
||||||
cameraProj_22;
|
|
||||||
|
|
||||||
// We actually end up with a vector pointing *at* the
|
// Unproject depth buffer Z value into view space
|
||||||
// surface (i.e. the negative view vector)
|
surface_positionView_z = cameraProj_43 / (z - cameraProj_33);
|
||||||
normalize3(surface_positionView_x, surface_positionView_y,
|
surface_positionView_x = positionScreen_x * surface_positionView_z /
|
||||||
surface_positionView_z, Vneg_x, Vneg_y, Vneg_z);
|
cameraProj_11;
|
||||||
|
surface_positionView_y = positionScreen_y * surface_positionView_z /
|
||||||
|
cameraProj_22;
|
||||||
|
|
||||||
// Reconstruct normal from G-buffer
|
// We actually end up with a vector pointing *at* the
|
||||||
float surface_normal_x, surface_normal_y, surface_normal_z;
|
// surface (i.e. the negative view vector)
|
||||||
float normal_x = half_to_float(inputData.normalEncoded_x[gBufferOffset]);
|
normalize3(surface_positionView_x, surface_positionView_y,
|
||||||
float normal_y = half_to_float(inputData.normalEncoded_y[gBufferOffset]);
|
surface_positionView_z, Vneg_x, Vneg_y, Vneg_z);
|
||||||
|
|
||||||
float f = (normal_x - normal_x * normal_x) + (normal_y - normal_y * normal_y);
|
// Reconstruct normal from G-buffer
|
||||||
float m = sqrt(4.0f * f - 1.0f);
|
float surface_normal_x, surface_normal_y, surface_normal_z;
|
||||||
|
float normal_x = half_to_float(inputData.normalEncoded_x[gBufferOffset]);
|
||||||
|
float normal_y = half_to_float(inputData.normalEncoded_y[gBufferOffset]);
|
||||||
|
|
||||||
surface_normal_x = m * (4.0f * normal_x - 2.0f);
|
float f = (normal_x - normal_x * normal_x) + (normal_y - normal_y * normal_y);
|
||||||
surface_normal_y = m * (4.0f * normal_y - 2.0f);
|
float m = sqrt(4.0f * f - 1.0f);
|
||||||
surface_normal_z = 3.0f - 8.0f * f;
|
|
||||||
|
|
||||||
// Load other G-buffer parameters
|
surface_normal_x = m * (4.0f * normal_x - 2.0f);
|
||||||
float surface_specularAmount =
|
surface_normal_y = m * (4.0f * normal_y - 2.0f);
|
||||||
half_to_float(inputData.specularAmount[gBufferOffset]);
|
surface_normal_z = 3.0f - 8.0f * f;
|
||||||
float surface_specularPower =
|
|
||||||
half_to_float(inputData.specularPower[gBufferOffset]);
|
|
||||||
float surface_albedo_x = Unorm8ToFloat32(inputData.albedo_x[gBufferOffset]);
|
|
||||||
float surface_albedo_y = Unorm8ToFloat32(inputData.albedo_y[gBufferOffset]);
|
|
||||||
float surface_albedo_z = Unorm8ToFloat32(inputData.albedo_z[gBufferOffset]);
|
|
||||||
|
|
||||||
float lit_x = 0.0f;
|
// Load other G-buffer parameters
|
||||||
float lit_y = 0.0f;
|
float surface_specularAmount =
|
||||||
float lit_z = 0.0f;
|
half_to_float(inputData.specularAmount[gBufferOffset]);
|
||||||
for (uniform int32 tileLightIndex = 0; tileLightIndex < tileNumLights;
|
float surface_specularPower =
|
||||||
++tileLightIndex) {
|
half_to_float(inputData.specularPower[gBufferOffset]);
|
||||||
uniform int32 lightIndex = tileLightIndices[tileLightIndex];
|
float surface_albedo_x = Unorm8ToFloat32(inputData.albedo_x[gBufferOffset]);
|
||||||
|
float surface_albedo_y = Unorm8ToFloat32(inputData.albedo_y[gBufferOffset]);
|
||||||
|
float surface_albedo_z = Unorm8ToFloat32(inputData.albedo_z[gBufferOffset]);
|
||||||
|
|
||||||
// Gather light data relevant to initial culling
|
float lit_x = 0.0f;
|
||||||
uniform float light_positionView_x =
|
float lit_y = 0.0f;
|
||||||
inputData.lightPositionView_x[lightIndex];
|
float lit_z = 0.0f;
|
||||||
uniform float light_positionView_y =
|
for (uniform int32 tileLightIndex = 0; tileLightIndex < tileNumLights;
|
||||||
inputData.lightPositionView_y[lightIndex];
|
++tileLightIndex) {
|
||||||
uniform float light_positionView_z =
|
uniform int32 lightIndex = tileLightIndices[tileLightIndex];
|
||||||
inputData.lightPositionView_z[lightIndex];
|
|
||||||
uniform float light_attenuationEnd =
|
|
||||||
inputData.lightAttenuationEnd[lightIndex];
|
|
||||||
|
|
||||||
// Compute light vector
|
// Gather light data relevant to initial culling
|
||||||
float L_x = light_positionView_x - surface_positionView_x;
|
uniform float light_positionView_x =
|
||||||
float L_y = light_positionView_y - surface_positionView_y;
|
inputData.lightPositionView_x[lightIndex];
|
||||||
float L_z = light_positionView_z - surface_positionView_z;
|
uniform float light_positionView_y =
|
||||||
|
inputData.lightPositionView_y[lightIndex];
|
||||||
|
uniform float light_positionView_z =
|
||||||
|
inputData.lightPositionView_z[lightIndex];
|
||||||
|
uniform float light_attenuationEnd =
|
||||||
|
inputData.lightAttenuationEnd[lightIndex];
|
||||||
|
|
||||||
float distanceToLight2 = dot3(L_x, L_y, L_z, L_x, L_y, L_z);
|
// Compute light vector
|
||||||
|
float L_x = light_positionView_x - surface_positionView_x;
|
||||||
|
float L_y = light_positionView_y - surface_positionView_y;
|
||||||
|
float L_z = light_positionView_z - surface_positionView_z;
|
||||||
|
|
||||||
// Clip at end of attenuation
|
float distanceToLight2 = dot3(L_x, L_y, L_z, L_x, L_y, L_z);
|
||||||
float light_attenutaionEnd2 = light_attenuationEnd * light_attenuationEnd;
|
|
||||||
|
|
||||||
cif (distanceToLight2 < light_attenutaionEnd2) {
|
// Clip at end of attenuation
|
||||||
float distanceToLight = sqrt(distanceToLight2);
|
float light_attenutaionEnd2 = light_attenuationEnd * light_attenuationEnd;
|
||||||
|
|
||||||
// HLSL "rcp" is allowed to be fairly inaccurate
|
cif (distanceToLight2 < light_attenutaionEnd2) {
|
||||||
float distanceToLightRcp = rcp(distanceToLight);
|
float distanceToLight = sqrt(distanceToLight2);
|
||||||
L_x *= distanceToLightRcp;
|
|
||||||
L_y *= distanceToLightRcp;
|
|
||||||
L_z *= distanceToLightRcp;
|
|
||||||
|
|
||||||
// Start computing brdf
|
// HLSL "rcp" is allowed to be fairly inaccurate
|
||||||
float NdotL = dot3(surface_normal_x, surface_normal_y,
|
float distanceToLightRcp = rcp(distanceToLight);
|
||||||
surface_normal_z, L_x, L_y, L_z);
|
L_x *= distanceToLightRcp;
|
||||||
|
L_y *= distanceToLightRcp;
|
||||||
|
L_z *= distanceToLightRcp;
|
||||||
|
|
||||||
// Clip back facing
|
// Start computing brdf
|
||||||
cif (NdotL > 0.0f) {
|
float NdotL = dot3(surface_normal_x, surface_normal_y,
|
||||||
uniform float light_attenuationBegin =
|
surface_normal_z, L_x, L_y, L_z);
|
||||||
inputData.lightAttenuationBegin[lightIndex];
|
|
||||||
|
|
||||||
// Light distance attenuation (linstep)
|
// Clip back facing
|
||||||
float lightRange = (light_attenuationEnd - light_attenuationBegin);
|
cif (NdotL > 0.0f) {
|
||||||
float falloffPosition = (light_attenuationEnd - distanceToLight);
|
uniform float light_attenuationBegin =
|
||||||
float attenuation = min(falloffPosition / lightRange, 1.0f);
|
inputData.lightAttenuationBegin[lightIndex];
|
||||||
|
|
||||||
float H_x = (L_x - Vneg_x);
|
// Light distance attenuation (linstep)
|
||||||
float H_y = (L_y - Vneg_y);
|
float lightRange = (light_attenuationEnd - light_attenuationBegin);
|
||||||
float H_z = (L_z - Vneg_z);
|
float falloffPosition = (light_attenuationEnd - distanceToLight);
|
||||||
normalize3(H_x, H_y, H_z, H_x, H_y, H_z);
|
float attenuation = min(falloffPosition / lightRange, 1.0f);
|
||||||
|
|
||||||
float NdotH = dot3(surface_normal_x, surface_normal_y,
|
float H_x = (L_x - Vneg_x);
|
||||||
surface_normal_z, H_x, H_y, H_z);
|
float H_y = (L_y - Vneg_y);
|
||||||
NdotH = max(NdotH, 0.0f);
|
float H_z = (L_z - Vneg_z);
|
||||||
|
normalize3(H_x, H_y, H_z, H_x, H_y, H_z);
|
||||||
|
|
||||||
float specular = pow(NdotH, surface_specularPower);
|
float NdotH = dot3(surface_normal_x, surface_normal_y,
|
||||||
float specularNorm = (surface_specularPower + 2.0f) *
|
surface_normal_z, H_x, H_y, H_z);
|
||||||
(1.0f / 8.0f);
|
NdotH = max(NdotH, 0.0f);
|
||||||
float specularContrib = surface_specularAmount *
|
|
||||||
specularNorm * specular;
|
|
||||||
|
|
||||||
float k = attenuation * NdotL * (1.0f + specularContrib);
|
float specular = pow(NdotH, surface_specularPower);
|
||||||
|
float specularNorm = (surface_specularPower + 2.0f) *
|
||||||
|
(1.0f / 8.0f);
|
||||||
|
float specularContrib = surface_specularAmount *
|
||||||
|
specularNorm * specular;
|
||||||
|
|
||||||
uniform float light_color_x = inputData.lightColor_x[lightIndex];
|
float k = attenuation * NdotL * (1.0f + specularContrib);
|
||||||
uniform float light_color_y = inputData.lightColor_y[lightIndex];
|
|
||||||
uniform float light_color_z = inputData.lightColor_z[lightIndex];
|
|
||||||
|
|
||||||
float lightContrib_x = surface_albedo_x * light_color_x;
|
uniform float light_color_x = inputData.lightColor_x[lightIndex];
|
||||||
float lightContrib_y = surface_albedo_y * light_color_y;
|
uniform float light_color_y = inputData.lightColor_y[lightIndex];
|
||||||
float lightContrib_z = surface_albedo_z * light_color_z;
|
uniform float light_color_z = inputData.lightColor_z[lightIndex];
|
||||||
|
|
||||||
lit_x += lightContrib_x * k;
|
float lightContrib_x = surface_albedo_x * light_color_x;
|
||||||
lit_y += lightContrib_y * k;
|
float lightContrib_y = surface_albedo_y * light_color_y;
|
||||||
lit_z += lightContrib_z * k;
|
float lightContrib_z = surface_albedo_z * light_color_z;
|
||||||
|
|
||||||
|
lit_x += lightContrib_x * k;
|
||||||
|
lit_y += lightContrib_y * k;
|
||||||
|
lit_z += lightContrib_z * k;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gamma correct
|
||||||
|
// These pows are pretty slow right now, but we can do
|
||||||
|
// something faster if really necessary to squeeze every
|
||||||
|
// last bit of performance out of it
|
||||||
|
float gamma = 1.0 / 2.2f;
|
||||||
|
lit_x = pow(clamp(lit_x, 0.0f, 1.0f), gamma);
|
||||||
|
lit_y = pow(clamp(lit_y, 0.0f, 1.0f), gamma);
|
||||||
|
lit_z = pow(clamp(lit_z, 0.0f, 1.0f), gamma);
|
||||||
|
|
||||||
|
framebuffer_r[gBufferOffset] = Float32ToUnorm8(lit_x);
|
||||||
|
framebuffer_g[gBufferOffset] = Float32ToUnorm8(lit_y);
|
||||||
|
framebuffer_b[gBufferOffset] = Float32ToUnorm8(lit_z);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gamma correct
|
|
||||||
// These pows are pretty slow right now, but we can do
|
|
||||||
// something faster if really necessary to squeeze every
|
|
||||||
// last bit of performance out of it
|
|
||||||
float gamma = 1.0 / 2.2f;
|
|
||||||
lit_x = pow(clamp(lit_x, 0.0f, 1.0f), gamma);
|
|
||||||
lit_y = pow(clamp(lit_y, 0.0f, 1.0f), gamma);
|
|
||||||
lit_z = pow(clamp(lit_z, 0.0f, 1.0f), gamma);
|
|
||||||
|
|
||||||
framebuffer_r[gBufferOffset] = Float32ToUnorm8(lit_x);
|
|
||||||
framebuffer_g[gBufferOffset] = Float32ToUnorm8(lit_y);
|
|
||||||
framebuffer_b[gBufferOffset] = Float32ToUnorm8(lit_z);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user