| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- #include "$ENGINE$\GBuffer.bslinc"
- #include "$ENGINE$\PerCameraData.bslinc"
- Parameters =
- {
- Sampler2D gGBufferASamp : alias("gGBufferATex");
- Sampler2D gGBufferBSamp : alias("gGBufferBTex");
- Sampler2D gDepthBufferSamp : alias("gDepthBufferTex");
-
- Texture2D gGBufferATex : auto("GBufferA");
- Texture2D gGBufferBTex : auto("GBufferB");
- Texture2D gDepthBufferTex : auto("GBufferDepth");
- };
- Blocks =
- {
- Block PerCamera : auto("PerCamera");
- Block PerLight : auto("PerLight");
- };
- Technique
- : base("DeferredLightPass")
- : inherits("GBuffer")
- : inherits("PerCameraData") =
- {
- Language = "HLSL11";
-
- Pass =
- {
- Target =
- {
- Blend = true;
- Color = { ONE, ONE, ADD };
- WriteMask = RGB;
- };
-
- DepthWrite = false;
- Common =
- {
- #define PI 3.1415926
- #define HALF_PI 1.5707963
-
- cbuffer PerLight
- {
- // x, y, z - World position of the lightData
- // w - Type type - Directional = 0, Point = >0, Spot = >0.5
- float4 gLightPositionAndType;
- float4 gLightColorAndIntensity;
- // x - outerAngle in radians, y - cos(outerAngle), z - 1.0f/(cos(innerAngle) - cos(outerAngle)), w - inverse point light radius
- float4 gLightSpotAnglesAndSqrdInvRadius;
- float3 gLightDirection;
-
- // x - Num sides (zero for point lights)
- // y - Num slices (zero for point lights)
- // z - Sphere radius for point lights
- // w - Cone radius for spot lights
- float4 gLightGeometry;
- float4x4 gMatConeTransform;
- }
-
- struct LightData
- {
- float3 position;
- float3 direction;
- float intensity;
- bool isSpot;
- bool isPoint;
- float3 spotAngles;
- float3 color;
- float radiusSqrdInv;
- };
-
- float convertFromDeviceZ(float deviceZ)
- {
- return (1.0f / (deviceZ + gDeviceZToWorldZ.y)) * gDeviceZToWorldZ.x;
- }
-
- GBufferData decodeGBuffer(float4 GBufferAData, float4 GBufferBData, float deviceZ)
- {
- GBufferData output;
-
- output.albedo.xyz = GBufferAData.xyz;
- output.albedo.w = 1.0f;
- output.worldNormal = GBufferBData * float4(2, 2, 2, 1) - float4(1, 1, 1, 0);
- output.worldNormal.xyz = normalize(output.worldNormal.xyz);
- output.depth = convertFromDeviceZ(deviceZ);
-
- return output;
- }
-
- LightData getLightData()
- {
- LightData output;
-
- output.position = gLightPositionAndType.xyz;
- output.direction = gLightDirection;
- output.color = gLightColorAndIntensity.rgb;
- output.intensity = gLightColorAndIntensity.w;
- output.isPoint = gLightPositionAndType.w > 0.0f;
- output.isSpot = gLightPositionAndType.w > 0.5f;
- output.spotAngles = gLightSpotAnglesAndSqrdInvRadius.xyz;
- output.radiusSqrdInv = gLightSpotAnglesAndSqrdInvRadius.w;
-
- return output;
- }
-
- float getSpotAttenuation(float3 worldPosToLight, float3 direction, float3 angles)
- {
- float output = saturate((dot(-worldPosToLight, direction) - angles.y) * angles.z);
- return output * output;
- }
-
- float4 getLighting(float3 worldPosition, float2 uv, GBufferData gBuffer, LightData lightData)
- {
- float3 N = gBuffer.worldNormal.xyz;
- float NoL = 1.0f;
-
- float distanceAttenuation = 1.0f;
- float spotFalloff = 1.0f;
- float radiusAttenuation = 1.0f;
- if (lightData.isPoint)
- {
- float3 L = lightData.position - worldPosition;
-
- float distanceSqrd = dot(L, L);
- distanceAttenuation = 1/(distanceSqrd + 1);
-
- L = normalize(L);
- NoL = saturate(dot(N, L)); // TODO - Add bias here?
- radiusAttenuation = distanceSqrd * lightData.radiusSqrdInv;
- radiusAttenuation *= radiusAttenuation;
- radiusAttenuation = saturate(1.0f - radiusAttenuation);
- radiusAttenuation *= radiusAttenuation;
-
- if (lightData.isSpot)
- spotFalloff = getSpotAttenuation(L, lightData.direction, lightData.spotAngles);
- }
- else
- {
- float3 L = -lightData.direction;
- NoL = saturate(dot(N, L)); // TODO - Add bias here?
- }
- float attenuation = distanceAttenuation * spotFalloff * radiusAttenuation;
- float3 diffuse = gBuffer.albedo.xyz / PI; // TODO - Add better lighting model later
- float4 output = float4(lightData.color * lightData.intensity * ((NoL * attenuation) * diffuse), 1);
- return output;
- }
- };
-
- Fragment =
- {
- SamplerState gGBufferASamp : register(s0);
- SamplerState gGBufferBSamp : register(s1);
- SamplerState gDepthBufferSamp : register(s2);
-
- Texture2D gGBufferATex : register(t0);
- Texture2D gGBufferBTex : register(t1);
- Texture2D gDepthBufferTex : register(t2);
-
- GBufferData getGBufferData(float2 uv)
- {
- float4 GBufferAData = gGBufferATex.SampleLevel(gGBufferASamp, uv, 0);
- float4 GBufferBData = gGBufferBTex.SampleLevel(gGBufferBSamp, uv, 0);
- float deviceZ = gDepthBufferTex.SampleLevel(gDepthBufferSamp, uv, 0).r;
-
- return decodeGBuffer(GBufferAData, GBufferBData, deviceZ);
- }
- };
- };
- };
- Technique
- : base("DeferredLightPass")
- : inherits("GBuffer")
- : inherits("PerCameraData") =
- {
- Language = "GLSL";
-
- Pass =
- {
- Target =
- {
- Blend = true;
- Color = { ONE, ONE, ADD };
- WriteMask = RGB;
- };
-
- DepthWrite = false;
- Common =
- {
- #define PI 3.1415926
- #define HALF_PI 1.5707963
-
- layout(std140) uniform PerLight
- {
- // x, y, z - World position of the lightData
- // w - Type type - Directional = 0, Point = >0, Spot = >0.5
- vec4 gLightPositionAndType;
- vec4 gLightColorAndIntensity;
- // x - outerAngle in radians, y - cos(outerAngle), z - 1.0f/(cos(innerAngle) - cos(outerAngle)), w - inverse point light radius
- vec4 gLightSpotAnglesAndSqrdInvRadius;
- vec3 gLightDirection;
-
- // x - Num sides (zero for point lights)
- // y - Num slices (zero for point lights)
- // z - Sphere radius for point lights
- // w - Cone radius for spot lights
- vec4 gLightGeometry;
- mat4 gMatConeTransform;
- };
-
- struct LightData
- {
- vec3 position;
- vec3 direction;
- float intensity;
- bool isSpot;
- bool isPoint;
- vec3 spotAngles;
- vec3 color;
- float radiusSqrdInv;
- };
-
- float convertFromDeviceZ(float deviceZ)
- {
- return (1.0f / (deviceZ + gDeviceZToWorldZ.y)) * gDeviceZToWorldZ.x;
- }
-
- GBufferData decodeGBuffer(vec4 GBufferAData, vec4 GBufferBData, float deviceZ)
- {
- GBufferData gBufferData;
-
- gBufferData.albedo.xyz = GBufferAData.xyz;
- gBufferData.albedo.w = 1.0f;
- gBufferData.worldNormal = GBufferBData * vec4(2, 2, 2, 1) - vec4(1, 1, 1, 0);
- gBufferData.worldNormal.xyz = normalize(gBufferData.worldNormal.xyz);
- gBufferData.depth = convertFromDeviceZ(deviceZ);
-
- return gBufferData;
- }
-
- LightData getLightData()
- {
- LightData lightData;
-
- lightData.position = gLightPositionAndType.xyz;
- lightData.direction = gLightDirection;
- lightData.color = gLightColorAndIntensity.rgb;
- lightData.intensity = gLightColorAndIntensity.w;
- lightData.isPoint = gLightPositionAndType.w > 0.0f;
- lightData.isSpot = gLightPositionAndType.w > 0.5f;
- lightData.spotAngles = gLightSpotAnglesAndSqrdInvRadius.xyz;
- lightData.radiusSqrdInv = gLightSpotAnglesAndSqrdInvRadius.w;
-
- return lightData;
- }
-
- float getSpotAttenuation(vec3 worldPosToLight, vec3 direction, vec3 angles)
- {
- float atten = clamp((dot(-worldPosToLight, direction) - angles.y) * angles.z, 0.0, 1.0);
- return atten * atten;
- }
-
- vec4 getLighting(vec3 worldPosition, vec2 uv, GBufferData gBuffer, LightData lightData)
- {
- vec3 N = gBuffer.worldNormal.xyz;
- float NoL = 1.0f;
-
- float distanceAttenuation = 1.0f;
- float spotFalloff = 1.0f;
- float radiusAttenuation = 1.0f;
- if (lightData.isPoint)
- {
- vec3 L = lightData.position - worldPosition;
-
- float distanceSqrd = dot(L, L);
- distanceAttenuation = 1/(distanceSqrd + 1);
-
- L = normalize(L);
- NoL = clamp(dot(N, L), 0.0, 1.0); // TODO - Add bias here?
- radiusAttenuation = distanceSqrd * lightData.radiusSqrdInv;
- radiusAttenuation *= radiusAttenuation;
- radiusAttenuation = clamp(1.0f - radiusAttenuation, 0.0, 1.0);
- radiusAttenuation *= radiusAttenuation;
-
- if (lightData.isSpot)
- spotFalloff = getSpotAttenuation(L, lightData.direction, lightData.spotAngles);
- }
- else
- {
- vec3 L = -lightData.direction;
- NoL = clamp(dot(N, L), 0.0, 1.0); // TODO - Add bias here?
- }
- float attenuation = distanceAttenuation * spotFalloff * radiusAttenuation;
- vec3 diffuse = gBuffer.albedo.xyz / PI; // TODO - Add better lighting model later
- vec4 lighting = vec4(lightData.color * lightData.intensity * ((NoL * attenuation) * diffuse), 1);
- return lighting;
- }
- };
-
- Fragment =
- {
- uniform sampler2D gGBufferATex;
- uniform sampler2D gGBufferBTex;
- uniform sampler2D gDepthBufferTex;
-
- GBufferData getGBufferData(vec2 uv)
- {
- vec4 GBufferAData = textureLod(gGBufferATex, uv, 0);
- vec4 GBufferBData = textureLod(gGBufferBTex, uv, 0);
- float deviceZ = textureLod(gDepthBufferTex, uv, 0).r;
-
- return decodeGBuffer(GBufferAData, GBufferBData, deviceZ);
- }
- };
- };
- };
|