10bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
30bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// Licensed under the Apache License, Version 2.0 (the "License");
40bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// you may not use this file except in compliance with the License.
50bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// You may obtain a copy of the License at
6894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
70bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens//    http://www.apache.org/licenses/LICENSE-2.0
8894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
90bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// Unless required by applicable law or agreed to in writing, software
100bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// distributed under the License is distributed on an "AS IS" BASIS,
110bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
120bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// See the License for the specific language governing permissions and
130bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// limitations under the License.
14894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
15894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "VertexPipeline.hpp"
16894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
17708c24b3cd03b68aa98b29a9099d6a9ce96eca16Nicolas Capens#include "Renderer/Vertex.hpp"
18708c24b3cd03b68aa98b29a9099d6a9ce96eca16Nicolas Capens#include "Renderer/Renderer.hpp"
19708c24b3cd03b68aa98b29a9099d6a9ce96eca16Nicolas Capens#include "Common/Debug.hpp"
20894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
21894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include <string.h>
22894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include <stdlib.h>
23894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include <stdio.h>
24894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
25894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#undef max
26894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#undef min
27894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
28894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumannamespace sw
29894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman{
3044ffb65ecb2638a3062a13d2fc3beb23a534b40dNicolas Capens	extern bool secondaryColor;
3144ffb65ecb2638a3062a13d2fc3beb23a534b40dNicolas Capens
3219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	VertexPipeline::VertexPipeline(const VertexProcessor::State &state) : VertexRoutine(state, 0)
33894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
34894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
35894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
36894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	VertexPipeline::~VertexPipeline()
37894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
38894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
39894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
40b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	Vector4f VertexPipeline::transformBlend(const Register &src, const Pointer<Byte> &matrix, bool homogeneous)
41894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
4219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Vector4f dst;
43894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
44894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(state.vertexBlendMatrixCount == 0)
45894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
46894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			dst = transform(src, matrix, homogeneous);
47894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
48894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
49894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
50894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			UInt index0[4];
51894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			UInt index1[4];
52894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			UInt index2[4];
53894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			UInt index3[4];
54894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
55894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(state.indexedVertexBlendEnable)
56894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
57894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				for(int i = 0; i < 4; i++)
58894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
597551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					Float4 B = v[BlendIndices].x;
60894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					UInt indices;
61b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
62894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					switch(i)
63894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
6419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					case 0: indices = As<UInt>(Float(B.x)); break;
6519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					case 1: indices = As<UInt>(Float(B.y)); break;
6619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					case 2: indices = As<UInt>(Float(B.z)); break;
6719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					case 3: indices = As<UInt>(Float(B.w)); break;
68894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
69894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
7066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman					index0[i] = (indices & 0x000000FF) << 6;
7166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman					index1[i] = (indices & 0x0000FF00) >> 2;
7266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman					index2[i] = (indices & 0x00FF0000) >> 10;
7366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman					index3[i] = (indices & 0xFF000000) >> 18;
74894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
75894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
76894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else
77894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
78894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				for(int i = 0; i < 4; i++)
79894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
8066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman					index0[i] = 0 * 64;
8166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman					index1[i] = 1 * 64;
8266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman					index2[i] = 2 * 64;
8366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman					index3[i] = 3 * 64;
84894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
85894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
86894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
87894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Float4 weight0;
88894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Float4 weight1;
89894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Float4 weight2;
90894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Float4 weight3;
91894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
92894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			switch(state.vertexBlendMatrixCount)
93894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
947551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			case 4: weight2 = v[BlendWeight].z;
957551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			case 3: weight1 = v[BlendWeight].y;
967551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			case 2: weight0 = v[BlendWeight].x;
97894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			case 1:
98894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				break;
99894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
100894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
101894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(state.vertexBlendMatrixCount == 1)
102894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
103894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				dst = transform(src, matrix, index0, homogeneous);
104894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
105894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(state.vertexBlendMatrixCount == 2)
106894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
107894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				weight1 = Float4(1.0f) - weight0;
108894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
10919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				Vector4f pos0;
11019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				Vector4f pos1;
111894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
112894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				pos0 = transform(src, matrix, index0, homogeneous);
113894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				pos1 = transform(src, matrix, index1, homogeneous);
114894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
11519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				dst.x = pos0.x * weight0 + pos1.x * weight1;   // FIXME: Vector4f operators
116894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				dst.y = pos0.y * weight0 + pos1.y * weight1;
117894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				dst.z = pos0.z * weight0 + pos1.z * weight1;
118894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				dst.w = pos0.w * weight0 + pos1.w * weight1;
119894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
120894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(state.vertexBlendMatrixCount == 3)
121894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
122894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				weight2 = Float4(1.0f) - (weight0 + weight1);
123894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
12419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				Vector4f pos0;
12519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				Vector4f pos1;
12619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				Vector4f pos2;
127894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
128894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				pos0 = transform(src, matrix, index0, homogeneous);
129894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				pos1 = transform(src, matrix, index1, homogeneous);
130894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				pos2 = transform(src, matrix, index2, homogeneous);
131894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
132894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				dst.x = pos0.x * weight0 + pos1.x * weight1 + pos2.x * weight2;
133894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				dst.y = pos0.y * weight0 + pos1.y * weight1 + pos2.y * weight2;
134894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				dst.z = pos0.z * weight0 + pos1.z * weight1 + pos2.z * weight2;
135894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				dst.w = pos0.w * weight0 + pos1.w * weight1 + pos2.w * weight2;
136894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
137894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(state.vertexBlendMatrixCount == 4)
138894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
139894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				weight3 = Float4(1.0f) - (weight0 + weight1 + weight2);
140894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
14119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				Vector4f pos0;
14219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				Vector4f pos1;
14319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				Vector4f pos2;
14419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				Vector4f pos3;
145894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
146894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				pos0 = transform(src, matrix, index0, homogeneous);
147894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				pos1 = transform(src, matrix, index1, homogeneous);
148894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				pos2 = transform(src, matrix, index2, homogeneous);
149894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				pos3 = transform(src, matrix, index3, homogeneous);
150894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
151894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				dst.x = pos0.x * weight0 + pos1.x * weight1 + pos2.x * weight2 + pos3.x * weight3;
152894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				dst.y = pos0.y * weight0 + pos1.y * weight1 + pos2.y * weight2 + pos3.y * weight3;
153894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				dst.z = pos0.z * weight0 + pos1.z * weight1 + pos2.z * weight2 + pos3.z * weight3;
154894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				dst.w = pos0.w * weight0 + pos1.w * weight1 + pos2.w * weight2 + pos3.w * weight3;
155894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
156894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
157894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
158894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		return dst;
159894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
160894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
161877ddfc51400030afd2804a23b132ed87a2f8d2fAlexis Hetu	void VertexPipeline::pipeline(UInt &index)
162894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
16319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Vector4f position;
16419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Vector4f normal;
165894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
166894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(!state.preTransformed)
167894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1687551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			position = transformBlend(v[Position], Pointer<Byte>(data + OFFSET(DrawData,ff.transformT)), true);
169894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
170894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
171894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1727551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			position = v[PositionT];
173894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
174894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1757551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		o[Pos].x = position.x;
1767551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		o[Pos].y = position.y;
1777551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		o[Pos].z = position.z;
1787551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		o[Pos].w = position.w;
179894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1807551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Vector4f vertexPosition = transformBlend(v[Position], Pointer<Byte>(data + OFFSET(DrawData,ff.cameraTransformT)), true);
181a36f3f9a6e33f451f3e8a9a61363d57ca91c46e5Nicolas Capens
182894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(state.vertexNormalActive)
183894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1847551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			normal = transformBlend(v[Normal], Pointer<Byte>(data + OFFSET(DrawData,ff.normalTransformT)), false);
185894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
186894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(state.normalizeNormals)
187894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
188894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				normal = normalize(normal);
189894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
190894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
191894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
192894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(!state.vertexLightingActive)
193894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
194894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			// FIXME: Don't process if not used at all
195894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(state.diffuseActive && state.input[Color0])
196894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1977551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				Vector4f diffuse = v[Color0];
198894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
199995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C0].x = diffuse.x;
200995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C0].y = diffuse.y;
201995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C0].z = diffuse.z;
202995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C0].w = diffuse.w;
203894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
204894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else
205894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
206995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C0].x = Float4(1.0f);
207995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C0].y = Float4(1.0f);
208995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C0].z = Float4(1.0f);
209995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C0].w = Float4(1.0f);
210894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
211894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
212894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			// FIXME: Don't process if not used at all
213894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(state.specularActive && state.input[Color1])
214894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
2157551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				Vector4f specular = v[Color1];
216894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
217995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C1].x = specular.x;
218995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C1].y = specular.y;
219995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C1].z = specular.z;
220995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C1].w = specular.w;
221894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
222894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else
223894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
224995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C1].x = Float4(0.0f);
225995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C1].y = Float4(0.0f);
226995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C1].z = Float4(0.0f);
227995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C1].w = Float4(1.0f);
228894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
229894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
230894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
231894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
232995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens			o[C0].x = Float4(0.0f);
233995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens			o[C0].y = Float4(0.0f);
234995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens			o[C0].z = Float4(0.0f);
235995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens			o[C0].w = Float4(0.0f);
236894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
237995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens			o[C1].x = Float4(0.0f);
238995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens			o[C1].y = Float4(0.0f);
239995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens			o[C1].z = Float4(0.0f);
240995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens			o[C1].w = Float4(0.0f);
241894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2426aea1b274d591a8f5fcd4cf3f5f75637ba34a1a5Nicolas Capens			Vector4f ambient;
2437551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			Float4 globalAmbient = *Pointer<Float4>(data + OFFSET(DrawData,ff.globalAmbient));   // FIXME: Unpack
2446aea1b274d591a8f5fcd4cf3f5f75637ba34a1a5Nicolas Capens
2456aea1b274d591a8f5fcd4cf3f5f75637ba34a1a5Nicolas Capens			ambient.x = globalAmbient.x;
2466aea1b274d591a8f5fcd4cf3f5f75637ba34a1a5Nicolas Capens			ambient.y = globalAmbient.y;
2476aea1b274d591a8f5fcd4cf3f5f75637ba34a1a5Nicolas Capens			ambient.z = globalAmbient.z;
248894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
249894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			for(int i = 0; i < 8; i++)
250894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
251894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(!(state.vertexLightActive & (1 << i)))
252894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
253894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					continue;
254894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
255894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
25619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				Vector4f L;    // Light vector
257894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				Float4 att;   // Attenuation
258894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
259894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				// Attenuation
260894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
261894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					Float4 d;   // Distance
262894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2637551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					L.x = L.y = L.z = *Pointer<Float4>(data + OFFSET(DrawData,ff.lightPosition[i]));   // FIXME: Unpack
264894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					L.x = L.x.xxxx;
265894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					L.y = L.y.yyyy;
266894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					L.z = L.z.zzzz;
267894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
268894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					L.x -= vertexPosition.x;
269894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					L.y -= vertexPosition.y;
270894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					L.z -= vertexPosition.z;
271894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					d = dot3(L, L);
272894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					d = RcpSqrt_pp(d);     // FIXME: Sufficient precision?
273894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					L.x *= d;
274894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					L.y *= d;
275894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					L.z *= d;
276894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					d = Rcp_pp(d);       // FIXME: Sufficient precision?
277894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2787551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					Float4 q = *Pointer<Float4>(data + OFFSET(DrawData,ff.attenuationQuadratic[i]));
2797551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					Float4 l = *Pointer<Float4>(data + OFFSET(DrawData,ff.attenuationLinear[i]));
2807551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					Float4 c = *Pointer<Float4>(data + OFFSET(DrawData,ff.attenuationConstant[i]));
281894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
282894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					att = Rcp_pp((q * d + l) * d + c);
283894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
284894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
285894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				// Ambient per light
286894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
2877551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					Float4 lightAmbient = *Pointer<Float4>(data + OFFSET(DrawData,ff.lightAmbient[i]));   // FIXME: Unpack
288894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2896aea1b274d591a8f5fcd4cf3f5f75637ba34a1a5Nicolas Capens					ambient.x = ambient.x + lightAmbient.x * att;
2906aea1b274d591a8f5fcd4cf3f5f75637ba34a1a5Nicolas Capens					ambient.y = ambient.y + lightAmbient.y * att;
2916aea1b274d591a8f5fcd4cf3f5f75637ba34a1a5Nicolas Capens					ambient.z = ambient.z + lightAmbient.z * att;
292894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
293894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
294894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				// Diffuse
295894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(state.vertexNormalActive)
296894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
297894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					Float4 dot;
298894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
299894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					dot = dot3(L, normal);
30019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					dot = Max(dot, Float4(0.0f));
301894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					dot *= att;
302894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
30319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					Vector4f diff;
304894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
305a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens					if(state.vertexDiffuseMaterialSourceActive == MATERIAL_MATERIAL)
306894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
3077551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						diff.x = diff.y = diff.z = *Pointer<Float4>(data + OFFSET(DrawData,ff.materialDiffuse));   // FIXME: Unpack
308894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						diff.x = diff.x.xxxx;
309894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						diff.y = diff.y.yyyy;
310894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						diff.z = diff.z.zzzz;
311894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
312a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens					else if(state.vertexDiffuseMaterialSourceActive == MATERIAL_COLOR1)
313894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
3147551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						diff = v[Color0];
315894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
316a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens					else if(state.vertexDiffuseMaterialSourceActive == MATERIAL_COLOR2)
317894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
3187551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						diff = v[Color1];
319894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
320894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					else ASSERT(false);
321894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
3227551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					Float4 lightDiffuse = *Pointer<Float4>(data + OFFSET(DrawData,ff.lightDiffuse[i]));
323894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
324995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens					o[C0].x = o[C0].x + diff.x * dot * lightDiffuse.x;   // FIXME: Clamp first?
325995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens					o[C0].y = o[C0].y + diff.y * dot * lightDiffuse.y;   // FIXME: Clamp first?
326995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens					o[C0].z = o[C0].z + diff.z * dot * lightDiffuse.z;   // FIXME: Clamp first?
327894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
328894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
329894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				// Specular
330894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(state.vertexSpecularActive)
331894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
33219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					Vector4f S;
33319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					Vector4f C;   // Camera vector
334894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					Float4 pow;
335894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
3367551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					pow = *Pointer<Float>(data + OFFSET(DrawData,ff.materialShininess));
337894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
33819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					S.x = Float4(0.0f) - vertexPosition.x;
33919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					S.y = Float4(0.0f) - vertexPosition.y;
34019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					S.z = Float4(0.0f) - vertexPosition.z;
341894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					C = normalize(S);
342894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
343894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					S.x = L.x + C.x;
344894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					S.y = L.y + C.y;
345894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					S.z = L.z + C.z;
346894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					C = normalize(S);
347894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
348894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					Float4 dot = Max(dot3(C, normal), Float4(0.0f));   // FIXME: max(dot3(C, normal), 0)
349894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
350894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					Float4 P = power(dot, pow);
351894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					P *= att;
352894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
35319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					Vector4f spec;
354894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
355a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens					if(state.vertexSpecularMaterialSourceActive == MATERIAL_MATERIAL)
356894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
3577551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						Float4 materialSpecular = *Pointer<Float4>(data + OFFSET(DrawData,ff.materialSpecular));   // FIXME: Unpack
358894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
359894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						spec.x = materialSpecular.x;
360894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						spec.y = materialSpecular.y;
361894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						spec.z = materialSpecular.z;
362894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
363a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens					else if(state.vertexSpecularMaterialSourceActive == MATERIAL_COLOR1)
364894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
3657551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						spec = v[Color0];
366894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
367a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens					else if(state.vertexSpecularMaterialSourceActive == MATERIAL_COLOR2)
368894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
3697551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						spec = v[Color1];
370894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
371894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					else ASSERT(false);
372894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
3737551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					Float4 lightSpecular = *Pointer<Float4>(data + OFFSET(DrawData,ff.lightSpecular[i]));
374894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
375894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					spec.x *= lightSpecular.x;
376894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					spec.y *= lightSpecular.y;
377894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					spec.z *= lightSpecular.z;
378894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
379894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					spec.x *= P;
380894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					spec.y *= P;
381894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					spec.z *= P;
382894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
38319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					spec.x = Max(spec.x, Float4(0.0f));
38419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					spec.y = Max(spec.y, Float4(0.0f));
38519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					spec.z = Max(spec.z, Float4(0.0f));
386894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
38744ffb65ecb2638a3062a13d2fc3beb23a534b40dNicolas Capens					if(secondaryColor)
38844ffb65ecb2638a3062a13d2fc3beb23a534b40dNicolas Capens					{
389995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens						o[C1].x = o[C1].x + spec.x;
390995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens						o[C1].y = o[C1].y + spec.y;
391995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens						o[C1].z = o[C1].z + spec.z;
39244ffb65ecb2638a3062a13d2fc3beb23a534b40dNicolas Capens					}
39344ffb65ecb2638a3062a13d2fc3beb23a534b40dNicolas Capens					else
39444ffb65ecb2638a3062a13d2fc3beb23a534b40dNicolas Capens					{
395995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens						o[C0].x = o[C0].x + spec.x;
396995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens						o[C0].y = o[C0].y + spec.y;
397995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens						o[C0].z = o[C0].z + spec.z;
39844ffb65ecb2638a3062a13d2fc3beb23a534b40dNicolas Capens					}
399894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
400894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
401894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
402a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens			if(state.vertexAmbientMaterialSourceActive == MATERIAL_MATERIAL)
403894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
4047551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				Float4 materialAmbient = *Pointer<Float4>(data + OFFSET(DrawData,ff.materialAmbient));   // FIXME: Unpack
405894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
4066aea1b274d591a8f5fcd4cf3f5f75637ba34a1a5Nicolas Capens				ambient.x = ambient.x * materialAmbient.x;
4076aea1b274d591a8f5fcd4cf3f5f75637ba34a1a5Nicolas Capens				ambient.y = ambient.y * materialAmbient.y;
4086aea1b274d591a8f5fcd4cf3f5f75637ba34a1a5Nicolas Capens				ambient.z = ambient.z * materialAmbient.z;
409894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
410a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens			else if(state.vertexAmbientMaterialSourceActive == MATERIAL_COLOR1)
411894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
4127551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				Vector4f materialDiffuse = v[Color0];
413894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
4146aea1b274d591a8f5fcd4cf3f5f75637ba34a1a5Nicolas Capens				ambient.x = ambient.x * materialDiffuse.x;
4156aea1b274d591a8f5fcd4cf3f5f75637ba34a1a5Nicolas Capens				ambient.y = ambient.y * materialDiffuse.y;
4166aea1b274d591a8f5fcd4cf3f5f75637ba34a1a5Nicolas Capens				ambient.z = ambient.z * materialDiffuse.z;
417894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
418a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens			else if(state.vertexAmbientMaterialSourceActive == MATERIAL_COLOR2)
419894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
4207551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				Vector4f materialSpecular = v[Color1];
421894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
4226aea1b274d591a8f5fcd4cf3f5f75637ba34a1a5Nicolas Capens				ambient.x = ambient.x * materialSpecular.x;
4236aea1b274d591a8f5fcd4cf3f5f75637ba34a1a5Nicolas Capens				ambient.y = ambient.y * materialSpecular.y;
4246aea1b274d591a8f5fcd4cf3f5f75637ba34a1a5Nicolas Capens				ambient.z = ambient.z * materialSpecular.z;
425894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
426894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else ASSERT(false);
427894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
428995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens			o[C0].x = o[C0].x + ambient.x;
429995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens			o[C0].y = o[C0].y + ambient.y;
430995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens			o[C0].z = o[C0].z + ambient.z;
431894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
432894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			// Emissive
433a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens			if(state.vertexEmissiveMaterialSourceActive == MATERIAL_MATERIAL)
434894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
4357551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				Float4 materialEmission = *Pointer<Float4>(data + OFFSET(DrawData,ff.materialEmission));   // FIXME: Unpack
436894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
437995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C0].x = o[C0].x + materialEmission.x;
438995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C0].y = o[C0].y + materialEmission.y;
439995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C0].z = o[C0].z + materialEmission.z;
440894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
441a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens			else if(state.vertexEmissiveMaterialSourceActive == MATERIAL_COLOR1)
442894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
4437551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				Vector4f materialSpecular = v[Color0];
444894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
445995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C0].x = o[C0].x + materialSpecular.x;
446995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C0].y = o[C0].y + materialSpecular.y;
447995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C0].z = o[C0].z + materialSpecular.z;
448894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
449a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens			else if(state.vertexEmissiveMaterialSourceActive == MATERIAL_COLOR2)
450894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
4517551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				Vector4f materialSpecular = v[Color1];
452894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
453995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C0].x = o[C0].x + materialSpecular.x;
454995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C0].y = o[C0].y + materialSpecular.y;
455995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C0].z = o[C0].z + materialSpecular.z;
456894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
457894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else ASSERT(false);
458894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
459894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			// Diffuse alpha component
460a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens			if(state.vertexDiffuseMaterialSourceActive == MATERIAL_MATERIAL)
461894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
462995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C0].w = Float4(*Pointer<Float4>(data + OFFSET(DrawData,ff.materialDiffuse[0]))).wwww;   // FIXME: Unpack
463894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
464a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens			else if(state.vertexDiffuseMaterialSourceActive == MATERIAL_COLOR1)
465894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
4667551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				Vector4f alpha = v[Color0];
467995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C0].w = alpha.w;
468894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
469a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens			else if(state.vertexDiffuseMaterialSourceActive == MATERIAL_COLOR2)
470894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
4717551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				Vector4f alpha = v[Color1];
472995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens				o[C0].w = alpha.w;
473894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
474894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else ASSERT(false);
475894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
476894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(state.vertexSpecularActive)
477894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
478894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				// Specular alpha component
479a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens				if(state.vertexSpecularMaterialSourceActive == MATERIAL_MATERIAL)
480894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
481995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens					o[C1].w = Float4(*Pointer<Float4>(data + OFFSET(DrawData,ff.materialSpecular[3]))).wwww;   // FIXME: Unpack
482894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
483a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens				else if(state.vertexSpecularMaterialSourceActive == MATERIAL_COLOR1)
484894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
4857551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					Vector4f alpha = v[Color0];
486995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens					o[C1].w = alpha.w;
487894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
488a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens				else if(state.vertexSpecularMaterialSourceActive == MATERIAL_COLOR2)
489894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
4907551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					Vector4f alpha = v[Color1];
491995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens					o[C1].w = alpha.w;
492894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
493894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				else ASSERT(false);
494894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
495894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
496894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
497894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(state.fogActive)
498894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
499a36f3f9a6e33f451f3e8a9a61363d57ca91c46e5Nicolas Capens			Float4 f;
500a36f3f9a6e33f451f3e8a9a61363d57ca91c46e5Nicolas Capens
501a36f3f9a6e33f451f3e8a9a61363d57ca91c46e5Nicolas Capens			if(!state.rangeFogActive)
502a36f3f9a6e33f451f3e8a9a61363d57ca91c46e5Nicolas Capens			{
503a36f3f9a6e33f451f3e8a9a61363d57ca91c46e5Nicolas Capens				f = Abs(vertexPosition.z);
504a36f3f9a6e33f451f3e8a9a61363d57ca91c46e5Nicolas Capens			}
505a36f3f9a6e33f451f3e8a9a61363d57ca91c46e5Nicolas Capens			else
506a36f3f9a6e33f451f3e8a9a61363d57ca91c46e5Nicolas Capens			{
507a36f3f9a6e33f451f3e8a9a61363d57ca91c46e5Nicolas Capens				f = Sqrt(dot3(vertexPosition, vertexPosition));   // FIXME: f = length(vertexPosition);
508a36f3f9a6e33f451f3e8a9a61363d57ca91c46e5Nicolas Capens			}
509a36f3f9a6e33f451f3e8a9a61363d57ca91c46e5Nicolas Capens
510894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			switch(state.vertexFogMode)
511894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
512a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens			case FOG_NONE:
513894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(state.specularActive)
514894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
515995ddeae528ffa617a1f0bdc377f96c25a7e3887Nicolas Capens					o[Fog].x = o[C1].w;
516894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
517894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				else
518894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
5197551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[Fog].x = Float4(0.0f);
520894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
521894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				break;
522a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens			case FOG_LINEAR:
5237551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				o[Fog].x = f * *Pointer<Float4>(data + OFFSET(DrawData,fog.scale)) + *Pointer<Float4>(data + OFFSET(DrawData,fog.offset));
524a36f3f9a6e33f451f3e8a9a61363d57ca91c46e5Nicolas Capens				break;
525a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens			case FOG_EXP:
5267551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				o[Fog].x = exponential2(f * *Pointer<Float4>(data + OFFSET(DrawData,fog.densityE)), true);
527a36f3f9a6e33f451f3e8a9a61363d57ca91c46e5Nicolas Capens				break;
528a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens			case FOG_EXP2:
5297551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				o[Fog].x = exponential2((f * f) * *Pointer<Float4>(data + OFFSET(DrawData,fog.density2E)), true);
530894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				break;
531894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			default:
532894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				ASSERT(false);
533894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
534894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
535894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
536894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int stage = 0; stage < 8; stage++)
537894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
538b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			processTextureCoordinate(stage, normal, position);
539894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
540894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
541b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		processPointSize();
542894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
543894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
544b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexPipeline::processTextureCoordinate(int stage, Vector4f &normal, Vector4f &position)
545894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
546894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(state.output[T0 + stage].write)
547894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
548894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			int i = state.textureState[stage].texCoordIndexActive;
549894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
550894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			switch(state.textureState[stage].texGenActive)
551894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
55270583fac46d30da9b527220e42f0533359784b16Nicolas Capens			case TEXGEN_NONE:
55370583fac46d30da9b527220e42f0533359784b16Nicolas Capens				{
5547551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					Vector4f &&varying = v[TexCoord0 + i];
55570583fac46d30da9b527220e42f0533359784b16Nicolas Capens
5567551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[T0 + stage].x = varying.x;
5577551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[T0 + stage].y = varying.y;
5587551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[T0 + stage].z = varying.z;
5597551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[T0 + stage].w = varying.w;
56070583fac46d30da9b527220e42f0533359784b16Nicolas Capens				}
56170583fac46d30da9b527220e42f0533359784b16Nicolas Capens				break;
562a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens			case TEXGEN_PASSTHRU:
563894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
5647551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					Vector4f &&varying = v[TexCoord0 + i];
565894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
5667551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[T0 + stage].x = varying.x;
5677551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[T0 + stage].y = varying.y;
5687551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[T0 + stage].z = varying.z;
5697551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[T0 + stage].w = varying.w;
570894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
57119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(state.input[TexCoord0 + i])
572894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
573894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						switch(state.input[TexCoord0 + i].count)
574894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						{
575894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						case 1:
5767551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							o[T0 + stage].y = Float4(1.0f);
5777551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							o[T0 + stage].z = Float4(0.0f);
5787551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							o[T0 + stage].w = Float4(0.0f);
579894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							break;
580894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						case 2:
5817551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							o[T0 + stage].z = Float4(1.0f);
5827551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							o[T0 + stage].w = Float4(0.0f);
583894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							break;
584894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						case 3:
5857551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							o[T0 + stage].w = Float4(1.0f);
586894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							break;
587894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						case 4:
588894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							break;
589894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						default:
590894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							ASSERT(false);
591894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
592894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
593894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
594894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				break;
595a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens			case TEXGEN_NORMAL:
596894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
59719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					Vector4f Nc;   // Normal vector in camera space
598894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
599894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					if(state.vertexNormalActive)
600894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
601894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						Nc = normal;
602894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
603894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					else
604894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
60519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						Nc.x = Float4(0.0f);
60619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						Nc.y = Float4(0.0f);
60719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						Nc.z = Float4(0.0f);
608894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
609894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
61019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					Nc.w = Float4(1.0f);
611b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
6127551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[T0 + stage].x = Nc.x;
6137551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[T0 + stage].y = Nc.y;
6147551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[T0 + stage].z = Nc.z;
6157551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[T0 + stage].w = Nc.w;
616894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
617894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				break;
618a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens			case TEXGEN_POSITION:
619894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
6207551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					Vector4f Pn = transformBlend(v[Position], Pointer<Byte>(data + OFFSET(DrawData,ff.cameraTransformT)), true);   // Position in camera space
621894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
62219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					Pn.w = Float4(1.0f);
623b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
6247551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[T0 + stage].x = Pn.x;
6257551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[T0 + stage].y = Pn.y;
6267551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[T0 + stage].z = Pn.z;
6277551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[T0 + stage].w = Pn.w;
628894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
629894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				break;
630a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens			case TEXGEN_REFLECTION:
631894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
63219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					Vector4f R;   // Reflection vector
633894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
634894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					if(state.vertexNormalActive)
635894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
63619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						Vector4f Nc;   // Normal vector in camera space
637894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
638894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						Nc = normal;
639894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
640894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						if(state.localViewerActive)
641894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						{
64219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							Vector4f Ec;   // Eye vector in camera space
64319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							Vector4f N2;
644894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
6457551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							Ec = transformBlend(v[Position], Pointer<Byte>(data + OFFSET(DrawData,ff.cameraTransformT)), true);
646894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							Ec = normalize(Ec);
647894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
648894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							// R = E - 2 * N * (E . N)
64919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							Float4 dot = Float4(2.0f) * dot3(Ec, Nc);
650894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
651894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							R.x = Ec.x - Nc.x * dot;
652894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							R.y = Ec.y - Nc.y * dot;
653894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							R.z = Ec.z - Nc.z * dot;
654894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
655894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						else
656894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						{
657894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							// u = -2 * Nz * Nx
658894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							// v = -2 * Nz * Ny
659894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							// w = 1 - 2 * Nz * Nz
660894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
66119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							R.x = -Float4(2.0f) * Nc.z * Nc.x;
66219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							R.y = -Float4(2.0f) * Nc.z * Nc.y;
66319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							R.z = Float4(1.0f) - Float4(2.0f) * Nc.z * Nc.z;
664894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
665894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
666894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					else
667894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
66819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						R.x = Float4(0.0f);
66919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						R.y = Float4(0.0f);
67019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						R.z = Float4(0.0f);
671894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
672894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
67319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					R.w = Float4(1.0f);
674894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
6757551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[T0 + stage].x = R.x;
6767551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[T0 + stage].y = R.y;
6777551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[T0 + stage].z = R.z;
6787551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[T0 + stage].w = R.w;
679894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
680894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				break;
681a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens			case TEXGEN_SPHEREMAP:
682894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
68319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					Vector4f R;   // Reflection vector
684894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
685894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					if(state.vertexNormalActive)
686894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
68719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						Vector4f Nc;   // Normal vector in camera space
688894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
689894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						Nc = normal;
690894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
691894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						if(state.localViewerActive)
692894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						{
69319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							Vector4f Ec;   // Eye vector in camera space
69419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							Vector4f N2;
695894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
6967551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							Ec = transformBlend(v[Position], Pointer<Byte>(data + OFFSET(DrawData,ff.cameraTransformT)), true);
697894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							Ec = normalize(Ec);
698894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
699894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							// R = E - 2 * N * (E . N)
70019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							Float4 dot = Float4(2.0f) * dot3(Ec, Nc);
701b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
702894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							R.x = Ec.x - Nc.x * dot;
703894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							R.y = Ec.y - Nc.y * dot;
704894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							R.z = Ec.z - Nc.z * dot;
705894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
706894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						else
707894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						{
708894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							// u = -2 * Nz * Nx
709894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							// v = -2 * Nz * Ny
710894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							// w = 1 - 2 * Nz * Nz
711894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
71219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							R.x = -Float4(2.0f) * Nc.z * Nc.x;
71319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							R.y = -Float4(2.0f) * Nc.z * Nc.y;
71419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							R.z = Float4(1.0f) - Float4(2.0f) * Nc.z * Nc.z;
715894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
716894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
717894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					else
718894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
71919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						R.x = Float4(0.0f);
72019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						R.y = Float4(0.0f);
72119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						R.z = Float4(0.0f);
722894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
723894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
72419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					R.z -= Float4(1.0f);
725894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					R = normalize(R);
72619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					R.x = Float4(0.5f) * R.x + Float4(0.5f);
72719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					R.y = Float4(0.5f) * R.y + Float4(0.5f);
728894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
72919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					R.z = Float4(1.0f);
73019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					R.w = Float4(0.0f);
731894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
7327551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[T0 + stage].x = R.x;
7337551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[T0 + stage].y = R.y;
7347551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[T0 + stage].z = R.z;
7357551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[T0 + stage].w = R.w;
736894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
737894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				break;
738894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			default:
739894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				ASSERT(false);
740894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
741894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
74219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			Vector4f texTrans0;
74319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			Vector4f texTrans1;
74419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			Vector4f texTrans2;
74519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			Vector4f texTrans3;
746894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
74719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			Vector4f T;
74819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			Vector4f t;
749894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
7507551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			T.x = o[T0 + stage].x;
7517551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			T.y = o[T0 + stage].y;
7527551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			T.z = o[T0 + stage].z;
7537551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			T.w = o[T0 + stage].w;
754894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
755894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			switch(state.textureState[stage].textureTransformCountActive)
756894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
757894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			case 4:
7587551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				texTrans3.x = texTrans3.y = texTrans3.z = texTrans3.w = *Pointer<Float4>(data + OFFSET(DrawData,ff.textureTransform[stage][3]));   // FIXME: Unpack
759894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				texTrans3.x = texTrans3.x.xxxx;
760894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				texTrans3.y = texTrans3.y.yyyy;
761894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				texTrans3.z = texTrans3.z.zzzz;
762894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				texTrans3.w = texTrans3.w.wwww;
763894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				t.w = dot4(T, texTrans3);
764894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			case 3:
7657551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				texTrans2.x = texTrans2.y = texTrans2.z = texTrans2.w = *Pointer<Float4>(data + OFFSET(DrawData,ff.textureTransform[stage][2]));   // FIXME: Unpack
766894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				texTrans2.x = texTrans2.x.xxxx;
767894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				texTrans2.y = texTrans2.y.yyyy;
768894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				texTrans2.z = texTrans2.z.zzzz;
769894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				texTrans2.w = texTrans2.w.wwww;
770894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				t.z = dot4(T, texTrans2);
771894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			case 2:
7727551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				texTrans1.x = texTrans1.y = texTrans1.z = texTrans1.w = *Pointer<Float4>(data + OFFSET(DrawData,ff.textureTransform[stage][1]));   // FIXME: Unpack
773894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				texTrans1.x = texTrans1.x.xxxx;
774894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				texTrans1.y = texTrans1.y.yyyy;
775894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				texTrans1.z = texTrans1.z.zzzz;
776894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				texTrans1.w = texTrans1.w.wwww;
777894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				t.y = dot4(T, texTrans1);
778894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			case 1:
7797551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				texTrans0.x = texTrans0.y = texTrans0.z = texTrans0.w = *Pointer<Float4>(data + OFFSET(DrawData,ff.textureTransform[stage][0]));   // FIXME: Unpack
780894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				texTrans0.x = texTrans0.x.xxxx;
781894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				texTrans0.y = texTrans0.y.yyyy;
782894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				texTrans0.z = texTrans0.z.zzzz;
783894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				texTrans0.w = texTrans0.w.wwww;
784894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				t.x = dot4(T, texTrans0);
785894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
7867551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				o[T0 + stage].x = t.x;
7877551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				o[T0 + stage].y = t.y;
7887551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				o[T0 + stage].z = t.z;
7897551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				o[T0 + stage].w = t.w;
790894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			case 0:
791894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				break;
792894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			default:
793894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				ASSERT(false);
794894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
795894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
796894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
797894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
798b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexPipeline::processPointSize()
799894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
800894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(!state.pointSizeActive)
801894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
802894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			return;   // Use global pointsize
803894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
804894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
80566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		if(state.input[PointSize])
806894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
8077551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			o[Pts].y = v[PointSize].x;
808894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
809894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
810894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
8117551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			o[Pts].y = *Pointer<Float4>(data + OFFSET(DrawData,point.pointSize));
812894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
813894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
814894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(state.pointScaleActive && !state.preTransformed)
815894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
8167551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			Vector4f p = transformBlend(v[Position], Pointer<Byte>(data + OFFSET(DrawData,ff.cameraTransformT)), true);
817894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
818894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Float4 d = Sqrt(dot3(p, p));   // FIXME: length(p);
819894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
8207551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			Float4 A = *Pointer<Float>(data + OFFSET(DrawData,point.pointScaleA));   // FIXME: Unpack
8217551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			Float4 B = *Pointer<Float>(data + OFFSET(DrawData,point.pointScaleB));   // FIXME: Unpack
8227551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			Float4 C = *Pointer<Float>(data + OFFSET(DrawData,point.pointScaleC));   // FIXME: Unpack
823894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
824894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			A = RcpSqrt_pp(A + d * (B + d * C));
825894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
8267551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			o[Pts].y = o[Pts].y * Float4(*Pointer<Float>(data + OFFSET(DrawData,viewportHeight))) * A;   // FIXME: Unpack
827894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
828894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
829894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
83066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman	Vector4f VertexPipeline::transform(const Register &src, const Pointer<Byte> &matrix, bool homogeneous)
831894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
83219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Vector4f dst;
833894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
834894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(homogeneous)
835894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
836894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Float4 m[4][4];
837894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
838894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			for(int j = 0; j < 4; j++)
839894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
840894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				for(int i = 0; i < 4; i++)
841894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
842894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					m[j][i].x = *Pointer<Float>(matrix + 16 * i + 4 * j);
843894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					m[j][i].y = *Pointer<Float>(matrix + 16 * i + 4 * j);
844894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					m[j][i].z = *Pointer<Float>(matrix + 16 * i + 4 * j);
845894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					m[j][i].w = *Pointer<Float>(matrix + 16 * i + 4 * j);
846894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
847894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
848894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
84948621bd2da0c2314ad6563142286e300f3fd13f1Nicolas Capens			dst.x = src.x * m[0][0] + src.y * m[0][1] + src.z * m[0][2] + src.w * m[0][3];
85048621bd2da0c2314ad6563142286e300f3fd13f1Nicolas Capens			dst.y = src.x * m[1][0] + src.y * m[1][1] + src.z * m[1][2] + src.w * m[1][3];
85148621bd2da0c2314ad6563142286e300f3fd13f1Nicolas Capens			dst.z = src.x * m[2][0] + src.y * m[2][1] + src.z * m[2][2] + src.w * m[2][3];
85248621bd2da0c2314ad6563142286e300f3fd13f1Nicolas Capens			dst.w = src.x * m[3][0] + src.y * m[3][1] + src.z * m[3][2] + src.w * m[3][3];
853894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
854894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
855894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
856894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Float4 m[3][3];
857894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
858894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			for(int j = 0; j < 3; j++)
859894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
860894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				for(int i = 0; i < 3; i++)
861894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
862894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					m[j][i].x = *Pointer<Float>(matrix + 16 * i + 4 * j);
863894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					m[j][i].y = *Pointer<Float>(matrix + 16 * i + 4 * j);
864894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					m[j][i].z = *Pointer<Float>(matrix + 16 * i + 4 * j);
865894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					m[j][i].w = *Pointer<Float>(matrix + 16 * i + 4 * j);
866894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
867894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
868894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
869894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			dst.x = src.x * m[0][0] + src.y * m[0][1] + src.z * m[0][2];
870894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			dst.y = src.x * m[1][0] + src.y * m[1][1] + src.z * m[1][2];
871894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			dst.z = src.x * m[2][0] + src.y * m[2][1] + src.z * m[2][2];
872894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
873894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
874894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		return dst;
875894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
876894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
87766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman	Vector4f VertexPipeline::transform(const Register &src, const Pointer<Byte> &matrix, UInt index[4], bool homogeneous)
878894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
87919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Vector4f dst;
880894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
881894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(homogeneous)
882894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
883894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Float4 m[4][4];
884894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
885894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			for(int j = 0; j < 4; j++)
886894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
887894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				for(int i = 0; i < 4; i++)
888894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
889894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					m[j][i].x = *Pointer<Float>(matrix + 16 * i + 4 * j + index[0]);
890894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					m[j][i].y = *Pointer<Float>(matrix + 16 * i + 4 * j + index[1]);
891894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					m[j][i].z = *Pointer<Float>(matrix + 16 * i + 4 * j + index[2]);
892894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					m[j][i].w = *Pointer<Float>(matrix + 16 * i + 4 * j + index[3]);
893894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
894894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
895894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
896894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			dst.x = src.x * m[0][0] + src.y * m[0][1] + src.z * m[0][2] + m[0][3];
897894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			dst.y = src.x * m[1][0] + src.y * m[1][1] + src.z * m[1][2] + m[1][3];
898894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			dst.z = src.x * m[2][0] + src.y * m[2][1] + src.z * m[2][2] + m[2][3];
899894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			dst.w = src.x * m[3][0] + src.y * m[3][1] + src.z * m[3][2] + m[3][3];
900894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
901894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
902894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
903894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Float4 m[3][3];
904894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
905894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			for(int j = 0; j < 3; j++)
906894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
907894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				for(int i = 0; i < 3; i++)
908894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
909894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					m[j][i].x = *Pointer<Float>(matrix + 16 * i + 4 * j + index[0]);
910894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					m[j][i].y = *Pointer<Float>(matrix + 16 * i + 4 * j + index[1]);
911894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					m[j][i].z = *Pointer<Float>(matrix + 16 * i + 4 * j + index[2]);
912894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					m[j][i].w = *Pointer<Float>(matrix + 16 * i + 4 * j + index[3]);
913894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
914894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
915894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
916894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			dst.x = src.x * m[0][0] + src.y * m[0][1] + src.z * m[0][2];
917894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			dst.y = src.x * m[1][0] + src.y * m[1][1] + src.z * m[1][2];
918894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			dst.z = src.x * m[2][0] + src.y * m[2][1] + src.z * m[2][2];
919894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
920894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
921894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		return dst;
922894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
923894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
92419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	Vector4f VertexPipeline::normalize(Vector4f &src)
925894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
92619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Vector4f dst;
927894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
928894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Float4 rcpLength = RcpSqrt_pp(dot3(src, src));
929b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
930894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.x = src.x * rcpLength;
931894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.y = src.y * rcpLength;
932894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.z = src.z * rcpLength;
933894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
934894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		return dst;
935894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
936894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
937894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	Float4 VertexPipeline::power(Float4 &src0, Float4 &src1)
938894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
939894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Float4 dst = src0;
940b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
941894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst = dst * dst;
942894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst = dst * dst;
94319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		dst = Float4(As<Int4>(dst) - As<Int4>(Float4(1.0f)));
944b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
945894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst *= src1;
946894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
94719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		dst = As<Float4>(Int4(dst) + As<Int4>(Float4(1.0f)));
948894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst = RcpSqrt_pp(dst);
949894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst = RcpSqrt_pp(dst);
950894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
951894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		return dst;
952894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
953894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
954