// buffer_lighting.cg - Cg 2.0 example demonstrating use of buffers to // contain uniform material, transform, and lighting // parameters #define MAX_LIGHTS 2 typedef struct { float4 ambient; float4 diffuse; float4 specular; float4 shine; } Material; typedef struct { float4x4 modelview; float4x4 inverse_modelview; float4x4 modelview_projection; } Transform; typedef struct { bool enabled; float3 ambient; float3 diffuse; float3 specular; float k0, k1, k2; } LightSourceStatic; // Light data that is mostly static typedef struct { float3 global_ambient; LightSourceStatic source[MAX_LIGHTS]; } LightSetStatic; typedef struct { float4 position; } LightSourcePerView; // Light data that changes as the view changes typedef struct { LightSourcePerView source[MAX_LIGHTS]; } LightSetPerView; // Compute the squared distance a direction vector covers. float lengthSquared(float3 v) { return dot(v,v); } void vertex_lighting(float4 position_obj : POSITION, float3 normal_obj : NORMAL, out float4 oPosition : POSITION, out float4 oColor : COLOR, uniform Material material : BUFFER[0], uniform Transform transform : BUFFER[1], uniform LightSetStatic lightSet : BUFFER[2], uniform LightSetPerView lightSetPerView : BUFFER[3]) { float4 vertex_eye = mul(transform.modelview, position_obj); float3 position_eye = vertex_eye.xyz / vertex_eye.w; float3 normal_eye = mul(float3x3(transform.inverse_modelview), normal_obj); float3 surface_normal = normalize(normal_eye); float3 totalRadiance = lightSet.global_ambient; int i; for (i=0; i<2; i++) { const LightSourceStatic source = lightSet.source[i]; const float4 light_position = lightSetPerView.source[i].position; if (source.enabled) { float3 light_vector; float attenuation; if (light_position.w != 0.0) { // Positional (finite) light light_vector = light_position.xyz/light_position.w - position_eye; attenuation = 1.0 / (source.k0 + source.k1*length(light_vector) + source.k2*lengthSquared(light_vector)); } else { // Direction (infinite) light light_vector = light_position.xyz; attenuation = 1.0; } float3 light_direction = normalize(light_vector.xyz); float3 view_direction = normalize(-position_eye.xyz); float3 half_angle_direction = normalize(view_direction + light_direction); float LdotN = dot(light_direction, surface_normal); float diffuse = max(0.0, LdotN); float HdotN = dot(half_angle_direction, surface_normal); float specular = (LdotN > 0) ? pow(max(0.0, HdotN), material.shine.x) : 0; float3 lighting = material.ambient.rgb * source.ambient.rgb + diffuse * material.diffuse.rgb * source.diffuse.rgb + specular * material.specular.rgb * source.specular.rgb; float3 radiance; radiance = attenuation * lighting; totalRadiance += radiance; } } oPosition = mul(transform.modelview_projection, position_obj); oColor = float4(totalRadiance, material.diffuse.a); } void vertex_transform(float4 position_obj : POSITION, float4 color : COLOR, float3 normal_obj : NORMAL, out float4 oPosition : POSITION, out float4 oColor : COLOR, uniform Material material : BUFFER[0], uniform Transform transform : BUFFER[1], uniform LightSetStatic lightSet : BUFFER[2], uniform LightSetPerView lightSetPerView : BUFFER[3]) { oColor = color; oPosition = mul(transform.modelview_projection, position_obj); }