struct NVSGLight { float4 ambient; //!< Specifies the ambient RGBA intensity of the light. float4 diffuse; //!< Specifies the diffuse RGBA intensity of the light. float4 specular; //!< Specifies the specular RGBA intensity of the light. float4 position; //!< Specifies the light position in world coordinates. float4 direction; //!< Specifies the light direction in world coordinates. float spotExponent; //!< Specifies the intensity distribution of the light. float spotCutoff; //!< Specifies the maximum spread angle of the light. float constantAttenuation; //!< Specifies the constant light attenuation factor. float linearAttenuation; //!< Specifies the linear light attenuation factor. float quadraticAttenuation; //!< Specifies the quadratic light attenuation factor. }; float4x4 world : World; float4x4 worldViewProj : WorldViewProjection; texture ColorTexture : Diffuse; sampler2D ColorSampler = sampler_state { Texture = ; MinFilter = Linear; MagFilter = Linear; }; NVSGLight Light[8]; void vertexProgram(float4 position : POSITION, uniform NVSGLight light[8], out float4 outPosition : POSITION, out float4 outTexcoord0 : TEXCOORD0 ) { float4x4 translateMatrix = {{1, 0, 0, -light[1].position.x}, {0, 1, 0, -light[1].position.y}, {0, 0, 1, -light[1].position.z}, {0, 0, 0, 1}}; float pan = atan2(-light[1].direction.x, -light[1].direction.z); float sinPan; float cosPan; sincos(-pan, sinPan, cosPan); float4x4 rotatePanMatrix = {{cosPan, 0, sinPan, 0}, {0, 1, 0, 0}, {-sinPan, 0, cosPan, 0}, {0, 0, 0, 1}}; float tilt = atan2(light[1].direction.y, sqrt(light[1].direction.z * light[1].direction.z + light[1].direction.x * light[1].direction.x)); float sinTilt; float cosTilt; sincos(-tilt, sinTilt, cosTilt); float4x4 rotateTiltMatrix = {{1, 0, 0, 0}, {0, cosTilt, -sinTilt, 0}, {0, sinTilt, cosTilt, 0}, {0, 0, 0, 1}}; float near = 10.f; float far = 10000.f; float tangent = tan(radians(light[1].spotCutoff * (9.0 / 16.0))); float height = near * tangent; float width = height * (16.f/9.f); float4x4 projectionMatrix = {{(2 * near) / (2 * width), 0, 0, 0}, {0, (2 * near) / (2 * height), 0, 0}, {0, 0, -(far + near) / (far - near), -(2 * far * near) / (far - near)}, {0, 0, -1, 0}}; float4x4 biasMatrix = {{0.5, 0, 0, 0.5}, {0, 0.5, 0, 0.5}, {0, 0, 0.5, 0.5}, {0, 0, 0, 1}}; outPosition = mul(worldViewProj, position); position = mul(world, position); position = mul(translateMatrix, position); position = mul(rotatePanMatrix, position); position = mul(rotateTiltMatrix, position); position = mul(projectionMatrix, position); outTexcoord0 = mul(biasMatrix, position); } void fragmentProgram(uniform sampler2D colorSampler, float4 texcoord0 : TEXCOORD0, out float4 outColor : COLOR ) { outColor = float4(0.0, 0.0, 0.0, 0.0); float2 texcoord = float2(texcoord0.x / texcoord0.w, texcoord0.y / texcoord0.w); if((texcoord.x >= 0.0) && (texcoord.y >= 0.0) && (texcoord.x <= 1.0) && (texcoord.y <= 1.0)) { outColor = tex2D(colorSampler, texcoord); } } technique main { pass p0 { VertexProgram = compile arbvp1 vertexProgram(Light); FragmentProgram = compile arbfp1 fragmentProgram(ColorSampler); } }