private HdrColor(HdrColor copy) { this.a = copy.a; this.r = copy.r; this.g = copy.g; this.b = copy.b; }
public static HdrColor operator *(HdrColor left, double scale) { HdrColor answer = new HdrColor(left); answer.a *= scale; answer.r *= scale; answer.g *= scale; answer.b *= scale; return(answer); }
public static HdrColor operator *(HdrColor left, HdrColor right) { HdrColor answer = new HdrColor(left); answer.a *= right.a; answer.r *= right.r; answer.g *= right.g; answer.b *= right.b; return(answer); }
public static HdrColor operator +(HdrColor left, HdrColor right) { HdrColor answer = new HdrColor(left); answer.a += right.a; answer.r += right.r; answer.g += right.g; answer.b += right.b; return(answer); }
/// <summary> /// Gouraud shading computes lighting per-vertex, in this method. /// Final pixel values are gathered from interpolating between pixels. /// Lighting is precomputed in this step per material. /// </summary> /// <param name="v">Input/Output per-vertex data.</param> protected override void ComputeVertexProgram(Vertex v) { // No color here ... v.Color = emptyColor; // Tolerance v.ColorTolerance = emptyColor; v.PrecomputedLight = new Color[textures.Length]; v.PrecomputedLightTolerance = new Color[textures.Length]; int textureIndex = 0; Point3D position = v.PositionAsPoint3D; Vector3D normal = v.Normal; // Precompute lighting for all textures foreach (TextureFilter texture in textures) { HdrColor color = emptyColor; HdrColor tolerance = emptyColor; if (texture != null) { // Lighting is done in Premultiplied color space. // // - BIG NOTE! - We do not actually premultiply the light contribution // because lighting is always opaque and premultiplying opaque colors // is a no-op. // // - Tolerance CANNOT be done in Premultiplied color space because // it needs to know the final pixel color in order to premultiply properly. // We won't know the final pixel color until ComputePixelProgram is called. // We ignore Alpha values during the computation and set the final value to // materialColor.A at the end. This is why you will not see any clamping of // light values, etc in the code below. Color materialColor = ColorOperations.PreMultiplyColor(texture.MaterialColor); switch (texture.MaterialType) { case MaterialType.Diffuse: foreach (LightEquation light in lightEquations) { Color lightContribution = light.IluminateDiffuse(position, normal); if (light is AmbientLightEquation) { // AmbientColor knobs are reminiscent of additive material passes // because the alpha value will not be considered in the final color value // (i.e. premultiply to scale RGB by alpha, then never use alpha again) Color ambientColor = ColorOperations.PreMultiplyColor(texture.AmbientColor); color += ColorOperations.Modulate(lightContribution, ambientColor); } else { color += ColorOperations.Modulate(lightContribution, materialColor); } tolerance += light.GetLastError(); } break; case MaterialType.Specular: foreach (LightEquation light in lightEquations) { // Don't need to check light equation type, since Ambient will return black Color lightContribution = light.IluminateSpecular(position, normal, texture.SpecularPower); color += ColorOperations.Modulate(lightContribution, materialColor); tolerance += light.GetLastError(); } break; case MaterialType.Emissive: color = materialColor; break; } // Alpha is only considered at the end. Overwrite whatever happened during the precomputation. // - Note that the alpha of the AmbientColor knob is NOT considered in the final value. color.A = ColorOperations.ByteToDouble(materialColor.A); } v.PrecomputedLight[textureIndex] = color.ClampedValue; v.PrecomputedLightTolerance[textureIndex] = tolerance.ClampedValue; textureIndex++; } }
public static HdrColor WeightedSum(HdrColor c1, HdrColor c2, HdrColor c3, Weights weights) { return((c1 * weights.W1) + (c2 * weights.W2) + (c3 * weights.W3)); }