1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4(Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org
6
7Copyright (c) 2000-2014 Torus Knot Software Ltd
8Permission is hereby granted, free of charge, to any person obtaining a copy
9of this software and associated documentation files (the "Software"), to deal
10in the Software without restriction, including without limitation the rights
11to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12copies of the Software, and to permit persons to whom the Software is
13furnished to do so, subject to the following conditions:
14
15The above copyright notice and this permission notice shall be included in
16all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24THE SOFTWARE.
25-----------------------------------------------------------------------------
26*/
27
28//-----------------------------------------------------------------------------
29// Program Name: SGXLib_Lighting
30// Program Desc: Per pixel lighting functions.
31// Program Type: Vertex/Pixel shader
32// Language: HLSL
33//-----------------------------------------------------------------------------
34
35//-----------------------------------------------------------------------------
36void SGX_TransformNormal(in float4x4 m,
37				   in float3 v,
38				   out float3 vOut)
39{
40	vOut = mul((float3x3)m, v);
41}
42
43//-----------------------------------------------------------------------------
44void SGX_TransformPosition(in float4x4 mWorldView,
45				   in float4 vPos,
46				   out float3 vOut)
47{
48	vOut = mul(mWorldView, vPos).xyz;
49}
50
51//-----------------------------------------------------------------------------
52void SGX_Light_Directional_Diffuse(
53				   in float3 vNormal,
54				   in float3 vNegLightDirView,
55				   in float3 vDiffuseColour,
56				   in float3 vBaseColour,
57				   out float3 vOut)
58{
59	float3 vNormalView = normalize(vNormal);
60	float nDotL = dot(vNormalView, vNegLightDirView);
61
62	vOut = vBaseColour + vDiffuseColour * saturate(nDotL);
63}
64
65//-----------------------------------------------------------------------------
66void SGX_Light_Directional_DiffuseSpecular(
67					in float3 vNormal,
68					in float3 vViewPos,
69					in float3 vNegLightDirView,
70					in float3 vDiffuseColour,
71					in float3 vSpecularColour,
72					in float fSpecularPower,
73					in float3 vBaseDiffuseColour,
74					in float3 vBaseSpecularColour,
75					out float3 vOutDiffuse,
76					out float3 vOutSpecular)
77{
78	vOutDiffuse  = vBaseDiffuseColour;
79	vOutSpecular = vBaseSpecularColour;
80
81	float3 vNormalView = normalize(vNormal);
82	float nDotL		   = dot(vNormalView, vNegLightDirView);
83	float3 vView       = -normalize(vViewPos);
84	float3 vHalfWay    = normalize(vView + vNegLightDirView);
85	float nDotH        = dot(vNormalView, vHalfWay);
86
87	if (nDotL > 0)
88	{
89		vOutDiffuse  += vDiffuseColour * nDotL;
90		vOutSpecular += vSpecularColour * pow(saturate(nDotH), fSpecularPower);
91	}
92}
93
94//-----------------------------------------------------------------------------
95void SGX_Light_Point_Diffuse(
96				    in float3 vNormal,
97				    in float3 vViewPos,
98				    in float3 vLightPosView,
99				    in float4 vAttParams,
100				    in float3 vDiffuseColour,
101				    in float3 vBaseColour,
102				    out float3 vOut)
103{
104	vOut = vBaseColour;
105
106	float3 vLightView  = vLightPosView - vViewPos;
107	float fLightD      = length(vLightView);
108	float3 vNormalView = normalize(vNormal);
109	float nDotL        = dot(vNormalView, normalize(vLightView));
110
111	if (nDotL > 0 && fLightD <= vAttParams.x)
112	{
113		float fAtten	   = 1 / (vAttParams.y + vAttParams.z*fLightD + vAttParams.w*fLightD*fLightD);
114
115		vOut += vDiffuseColour * nDotL * fAtten;
116	}
117}
118
119
120
121//-----------------------------------------------------------------------------
122void SGX_Light_Point_DiffuseSpecular(
123				    in float3 vNormal,
124				    in float3 vViewPos,
125				    in float3 vLightPosView,
126				    in float4 vAttParams,
127				    in float3 vDiffuseColour,
128				    in float3 vSpecularColour,
129					in float fSpecularPower,
130				    in float3 vBaseDiffuseColour,
131					in float3 vBaseSpecularColour,
132					out float3 vOutDiffuse,
133					out float3 vOutSpecular)
134{
135	vOutDiffuse  = vBaseDiffuseColour;
136	vOutSpecular = vBaseSpecularColour;
137
138	float3 vLightView  = vLightPosView - vViewPos;
139	float fLightD      = length(vLightView);
140	vLightView		   = normalize(vLightView);
141	float3 vNormalView = normalize(vNormal);
142	float nDotL        = dot(vNormalView, vLightView);
143
144	if (nDotL > 0 && fLightD <= vAttParams.x)
145	{
146		float3 vView       = -normalize(vViewPos);
147		float3 vHalfWay    = normalize(vView + vLightView);
148		float nDotH        = dot(vNormalView, vHalfWay);
149		float fAtten	   = 1 / (vAttParams.y + vAttParams.z*fLightD + vAttParams.w*fLightD*fLightD);
150
151		vOutDiffuse  += vDiffuseColour * nDotL * fAtten;
152		vOutSpecular += vSpecularColour * pow(saturate(nDotH), fSpecularPower) * fAtten;
153	}
154}
155
156//-----------------------------------------------------------------------------
157void SGX_Light_Spot_Diffuse(
158				    in float3 vNormal,
159				    in float3 vViewPos,
160				    in float3 vLightPosView,
161				    in float3 vNegLightDirView,
162				    in float4 vAttParams,
163				    in float3 vSpotParams,
164				    in float3 vDiffuseColour,
165				    in float3 vBaseColour,
166				    out float3 vOut)
167{
168	vOut = vBaseColour;
169
170	float3 vLightView  = vLightPosView - vViewPos;
171	float fLightD      = length(vLightView);
172	vLightView		   = normalize(vLightView);
173	float3 vNormalView = normalize(vNormal);
174	float nDotL        = dot(vNormalView, vLightView);
175
176	if (nDotL > 0 && fLightD <= vAttParams.x)
177	{
178		float fAtten	= 1 / (vAttParams.y + vAttParams.z*fLightD + vAttParams.w*fLightD*fLightD);
179		float rho		= dot(vNegLightDirView, vLightView);
180		float fSpotE	= saturate((rho - vSpotParams.y) / (vSpotParams.x - vSpotParams.y));
181		float fSpotT	= pow(fSpotE, vSpotParams.z);
182
183		vOut += vDiffuseColour * nDotL * fAtten * fSpotT;
184	}
185}
186
187//-----------------------------------------------------------------------------
188void SGX_Light_Spot_DiffuseSpecular(
189				    in float3 vNormal,
190				    in float3 vViewPos,
191				    in float3 vLightPosView,
192				    in float3 vNegLightDirView,
193				    in float4 vAttParams,
194				    in float3 vSpotParams,
195				    in float3 vDiffuseColour,
196				    in float3 vSpecularColour,
197					in float fSpecularPower,
198				    in float3 vBaseDiffuseColour,
199					in float3 vBaseSpecularColour,
200					out float3 vOutDiffuse,
201					out float3 vOutSpecular)
202{
203	vOutDiffuse  = vBaseDiffuseColour;
204	vOutSpecular = vBaseSpecularColour;
205
206	float3 vLightView  = vLightPosView - vViewPos;
207	float fLightD      = length(vLightView);
208	vLightView		   = normalize(vLightView);
209	float3 vNormalView = normalize(vNormal);
210	float nDotL        = dot(vNormalView, vLightView);
211
212
213	if (nDotL > 0 && fLightD <= vAttParams.x)
214	{
215		float3 vView       = -normalize(vViewPos);
216		float3 vHalfWay    = normalize(vView + vLightView);
217		float nDotH        = dot(vNormalView, vHalfWay);
218		float fAtten	= 1 / (vAttParams.y + vAttParams.z*fLightD + vAttParams.w*fLightD*fLightD);
219		float rho		= dot(vNegLightDirView, vLightView);
220		float fSpotE	= saturate((rho - vSpotParams.y) / (vSpotParams.x - vSpotParams.y));
221		float fSpotT	= pow(fSpotE, vSpotParams.z);
222
223		vOutDiffuse  += vDiffuseColour * nDotL * fAtten * fSpotT;
224		vOutSpecular += vSpecularColour * pow(saturate(nDotH), fSpecularPower) * fAtten * fSpotT;
225	}
226}
227