DrawToScreenSpaceForeground Rendered View issue

I compiled a plugin that creates a legend described here:

Most things work fine, except when entering Rendered View, then the colors get distorted. I thought the method is drawing over the screen and thus should not be affected by what view mode is selected?


Interestingly this happens only to the Legend being drawn in the foreground…

1 Like

You need to correct colors for gamma:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;

using Rhino;
using Rhino.Geometry;

using Grasshopper;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Data;
using Grasshopper.Kernel.Types;

using System.IO;
using System.Linq;
using System.Data;
using System.Reflection;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
using System.Runtime.InteropServices;

using Rhino.DocObjects;
using Rhino.Collections;
using GH_IO;
using GH_IO.Serialization;

/*
Aufgaben
- Bilschirmskalierung anpassen (für Retina und Nicht-Retina)
- ViewCapture to File Option hinzufügen
- Veränderbare Farben

*/
public class Script_Instance : GH_ScriptInstance
{
  /* 
    Members:
      RhinoDoc RhinoDocument
      GH_Document GrasshopperDocument
      IGH_Component Component
      int Iteration

    Methods (Virtual & overridable):
      Print(string text)
      Print(string format, params object[] args)
      Reflect(object obj)
      Reflect(object obj, string method_name)
  */

  private Color GammaCorrect(Color originalColor, double gamma)
  {
    double R = originalColor.R / 255.0;
    double G = originalColor.G / 255.0;
    double B = originalColor.B / 255.0;

    double _correctedR = System.Math.Pow(R, gamma) * 255.0;
    double _correctedG = System.Math.Pow(G, gamma) * 255.0;
    double _correctedB = System.Math.Pow(B, gamma) * 255.0;
    
    Color _correctedColor = System.Drawing.Color.FromArgb((int)_correctedR, (int)_correctedG, (int)_correctedB);
    return _correctedColor;
  }
  
  private void RunScript(string txt, Interval valDomain)
  {
    Print("Running script");
    List<System.Drawing.Color> colorsList = new List<System.Drawing.Color>
    { //Taken from Alpaca4D color componennt.
      System.Drawing.Color.FromArgb(5, 48, 97),
      System.Drawing.Color.FromArgb(33, 102, 172),
      System.Drawing.Color.FromArgb(67, 147, 195),
      System.Drawing.Color.FromArgb(146, 197, 222),
      System.Drawing.Color.FromArgb(209, 229, 240),
      System.Drawing.Color.FromArgb(255, 255, 255),
      System.Drawing.Color.FromArgb(253, 219, 199),
      System.Drawing.Color.FromArgb(244, 165, 130),
      System.Drawing.Color.FromArgb(214, 96, 77),
      System.Drawing.Color.FromArgb(178, 24, 43),
      System.Drawing.Color.FromArgb(103, 0, 31)
    };

    factor = 0.75;
    title = txt;
    divisions = colorsList.Count;

    double gamma = 2.2;
    for (int i=0; i<(colorsList.Count); i++)
    {
        plotColors.Add(colorsList[i]);
    }
    
    for(int i=0; i<(colorsList.Count+1); i++)
    {   double roundVal = Math.Round((valDomain.T0 + i * (valDomain.Length / (colorsList.Count))),3);
        plotValues.Add(roundVal);
    }

  }
  List<double> plotValues = new List<double>();
  List<System.Drawing.Color> plotColors = new List<System.Drawing.Color>();
  double factor;
  int divisions;
  string title;
  List<string> toCorrectFor = new List<string> {
      "Rendered",
      "Raytraced"
  };

  BoundingBox box;

  public override void BeforeRunScript()
  {
    box = BoundingBox.Empty;

    // Unregister & register new event
    Rhino.Display.DisplayPipeline.DrawForeground -= DrawForeground;
    Rhino.Display.DisplayPipeline.DrawForeground += DrawForeground;
  }

  public override BoundingBox ClippingBox { get{ return box; } }

  // Event function
  private void DrawForeground(object sender, Rhino.Display.DrawEventArgs e)
  {
    DrawLegend(e);
  }

  private void DrawLegend(Rhino.Display.DrawEventArgs pipeline)
  {
    if (pipeline.Viewport.Id == pipeline.RhinoDoc.Views.ActiveView.ActiveViewportID
        &&
        !this.Component.Hidden
    )
    {
      var viewport = pipeline.Viewport;
      var colsToUse = plotColors;
      bool correctForGamma = toCorrectFor.Contains(viewport.DisplayMode.EnglishName);
      double _gamma = correctForGamma ?
                          pipeline.RhinoDoc.RenderSettings.LinearWorkflow.PostProcessGamma
                          : 1.0;

      var viewportHeight = viewport.Size.Height;
      int barHeight = (int)(viewportHeight * factor);

      //legend properties

      int plotWidth = (int)(barHeight * 0.05);
      int xStart = (int)(plotWidth * 0.75);

      //posY 
      int posY = (int)(viewportHeight * ((1 - factor) / 2));

      List<int> yPositions = new List<int>(); ;

      for (int i = 0; i < divisions + 1; i++)
      {
        yPositions.Add(posY + i * (barHeight / (divisions)));
      }

      List<Rectangle> colRectangles = new List<Rectangle>();
      for (int i = 0; i < (divisions); i++)
      {
        Rectangle tempRec = new Rectangle(xStart, yPositions[i], plotWidth, barHeight / (divisions - 1));

        Color correctedColor = GammaCorrect(colsToUse[i], _gamma);

        pipeline.Display.Draw2dRectangle(tempRec, Color.Black, 1, correctedColor);
      }

      int plotValuesHeight = (int)(plotWidth * 0.5);

      for (int i = 0; i < divisions + 1; i++)
      {
        var p3 = new System.Drawing.Point(xStart + (int)(plotWidth * 0.666), yPositions[i]);
        var p4 = new System.Drawing.Point(xStart + plotWidth, yPositions[i]);
        pipeline.Display.Draw2dLine(p3, p4, Color.Black, 3);

        pipeline.Display.Draw2dText(plotValues[i].ToString(), Color.Black, new Point2d(xStart + (int)(plotWidth * 1.2), yPositions[i] - (int)(plotValuesHeight * 0.4)), false, plotValuesHeight, "NewComputerModernMath"); //why factor 0.4 here? not perfect vertival alignment
      }

      pipeline.Display.Draw2dText(title, Color.Black, new Point2d(xStart, (yPositions[0] - (int)(plotWidth * 1.2))), false, (int)(plotWidth), "NewComputerModernMath");
    }

  }
}

I’ve added a gamma correction function for color. I also adapted the drawing code to do this for both Rendered and Raytraced.

2 Likes

Amazing, it worked, and I learned sth about Gamma.

There is a micro detail left: for some reason, the rectangle borders now get drawn differently. But there are set to black, so the Gamma correction would not be necessary…

Strange behavior, but not that important.

I did not change the colors of the borders, only the fill color.

Yes I know, they are still changing by themself when switching to Rendered View

Looks like you need to restart Rhino every now and then. It appears that after a while somehow the draw handler doesn’t get updated properly.