Line rasterizatio with anti-aliasing and z-test - blend with background color

This is a discussion on Line rasterizatio with anti-aliasing and z-test - blend with background color within the C++ Programming forums, part of the General Programming Boards category; Yes this is another homework post in the forum, but it seems that I run out of ideas :/ The ...

  1. #1
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694

    Line rasterizatio with anti-aliasing and z-test - blend with background color

    Yes this is another homework post in the forum, but it seems that I run out of ideas :/

    The scene is a red sphere, a green light that rotates around x axis. The background color is white. There is also some lighting.

    My basic idea was to found with which object (well it is one, but the point is that this can work in general I think..) the line intersects, and get the color of this object. This color would be the background of the line at this point.

    Below I will post the skeleton that was given, a header file and at last my attempts .

    skeleton CCanvas.cpp
    Code:
    #include "CCanvas.h"
    
    #include "Color.h"
    #include "Light.h"
    #include "Texture.h"
    
    #include "Object.h"
    #include "Sphere.h"
    
    using namespace std;
    
    double objectZ;
    
    /************************************************************************/
    /* Initializes the lights and objects																		*/
    /************************************************************************/
    void CCanvas::initScene() 
    {
    	static bool isInit = false;
    
      if (isInit)
        return;
    	
      //
      // material coefficients for the first object (a sphere)
      //
    	Material ObjMat;
    	ObjMat.ambient = Color3d(0.2, 0.2, 0.2);
      ObjMat.diffuse = Color3d(0.8, 0.2, 0.2);
      ObjMat.specular = Color3d(0.5, 0.5, 0.5);
      ObjMat.shininess = 10.0;
      ObjMat.reflectivity = 0.0;
    
    	Sphere* sphere = new Sphere(ObjMat);
      sphere->translate(0.0, 0.0, 10.0);
    	sphere->scale(2.0, 2.0, 2.0);
      
    	objects.push_back(sphere);
    
      //
      // light source 1 (white light from top left)
      //
      Material LightCol;
    	LightCol.ambient = Color3d(0.6, 0.6, 0.6);
    	LightCol.diffuse = Color3d(1.0, 1.0, 1.0);
    	LightCol.specular = Color3d(1.0, 1.0, 1.0);
    
      Point3d LightPos(-10.0, 5.0, -5.0);  
    
      Light* light = new Light(LightPos, LightCol);	
      light->setDirectional();
    
      lights.push_back(light);
    
    
      isInit = true;
      cout<<"Scene initialized..."<<endl;
    };
    
    /************************************************************************/
    /* For the given ray, this function finds the closest intersection with */
    /* the scene objects and returns a pointer to the nearest object.       */
    /************************************************************************/
    Object* CCanvas::findNearestObject(Ray ray)
    {
      Object* nearestObject = NULL;   // pointer to the nearest object
    
      // loop over all objects
      vector< Object* >::iterator object;
      for (object = objects.begin(); object < objects.end(); object++)
      {
        // ignore the current object (if any)
        // [useful for avoiding numerical problems when tracing shadow or reflection rays]
        if ( (*object) == currentObject )
          continue;
    
        // does the ray intersect with the current object?
        if ( (*object)->computeIntersection(ray) )
        {
          // is the intersection point closer than the currently closest (if there already is one)?
          if ( (nearestObject == NULL) || ( (*object)->getDistance() < nearestObject->getDistance() ) )
            nearestObject = *object;
        }
      }
    
      return nearestObject;
    }
    
    /************************************************************************/
    /* Tests, if point p is lit by light l, or if it lies in the shadow.    */
    /************************************************************************/
    bool CCanvas::inShadow(Point3d p, Light* l)
    {
      // set up the shadow ray
      Ray ray;
    	ray.origin    = p;
    	ray.direction = l->getLightVector(p);
    
      // find closest intersection point
      Object* nearestObject = findNearestObject(ray);
    
      // is there an intersection along the shadow ray?
    	if (nearestObject != NULL)
      {
        if (l->isDirectional)   // in case of a directional light, the intersected object
          return true;          // is always between p and the light
        
        // otherwise, check against the distance to the light
        double lightDistance = (l->getPosition() - p).norm();
        if (nearestObject->getDistance() < lightDistance)
          return true;
      }
    
      // either no intersection or object behind the light
      return false;
    }
    
    /************************************************************************/
    /* Function loops over all light sources and calculates the lighting  	*/
    /* for the surface point "p" with normal "n" of a visible object with   */
    /* material "mat"; the camera is in direction "v" (view vector)  			  */
    /************************************************************************/
    Color3d CCanvas::PhongLighting(Point3d p, Point3d n, Point3d v, Material mat)
    {
    	Color3d finalColor;	
    
      // loop over all light sources
      vector< Light* >::iterator light;
      for (light = lights.begin(); light < lights.end(); light++)
    	{
        // get the light's colour
    		Material lightColor = (*light)->getColor(p);
    
    		// compute light vector
    		Point3d l = (*light)->getLightVector(p);
    
    		// cosine of the angle between normal and light vector
    		double cos_phi = n*l;
    
        // in any case, the object receives the ambient light from the current light source
        Color3d color = mat.ambient * lightColor.ambient;
    
    		// check if light source is not hidden by the object itself or by some other object
        if ( ! ( (cos_phi < 0) || inShadow(p, *light) ) )
        {
          // compute and add diffuse reflection
    			color += mat.diffuse * lightColor.diffuse * cos_phi;		  
    	  
    			// compute and add specular reflection
    			Point3d r = 2*n*(n*l) - l;
    			r.normalize();
    			double cos_alpha = r*v;
    			if (cos_alpha < 0.0)
    				cos_alpha = 0.0;
    
    			color += mat.specular * lightColor.specular * pow(cos_alpha, mat.shininess);
    		}
    
    		color.clamped();
    
        // add up colours from all light sources
    		finalColor += color;
    	}
    
      // clamp colour
      finalColor.clamped();
    
    	return finalColor;
    }
    
    /************************************************************************/
    /* This function finds the closest object along the givevn ray and      */
    /* evokes the lighting calculation for the intersection point.          */
    /************************************************************************/
    Color3d CCanvas::trace(Ray ray, int cnt)
    {
      // termination criterion
      if (cnt > 3)
        return Color3d(0.0, 0.0, 0.0);
    
      // find closest intersection point
      Object* nearestObject = findNearestObject(ray);
    
      // compute lighting at this intersection point
    	if (nearestObject != NULL) 
    	{		
        IntersectionInfo intersection = nearestObject->getIntersectionInfo();
    
        if (cnt == 0)
          objectZ = intersection.point.z();
    
    		if (intersection.inside)
    		{
    			// if camera is inside some object, then no complex lighting calculation, just black colour
    			return Color3d(0.0, 0.0, 0.0);
    		}
    		else
    		{
    			// call "PhongLighting" for lighting calculation
          currentObject = nearestObject;
    			Color3d color = PhongLighting(intersection.point, intersection.normal, -ray.direction, nearestObject->getMaterial());
    
          // set up reflection ray
          Ray reflection;
          reflection.origin = intersection.point;
          reflection.direction = - 2.0 * intersection.normal * (intersection.normal * ray.direction) + ray.direction;
    
          // trace reflection ray and get reflected colour
          Color3d reflectionColor = nearestObject->getMaterial().reflectivity * trace(reflection, cnt+1);
          reflectionColor.clamped();
    
          // add up colours
          color += reflectionColor;
          color.clamped();
    
          return color;
    		}
    	}
    	else
    	{
    		// no object was intersected, so set the background colour for current pixel
    		return Color3d(1.0, 1.0, 1.0);
    	}
    }
    
    /************************************************************************/
    /* paint to the image                                                   */
    /************************************************************************/
    void CCanvas::paint()
    {
      // check if we have something to draw on
      if (!image) return;
     
    	// initialize objects and lights
    	initScene();
    
      // camera position
      Point3d camera (0.0, 0.0, 0.0);
    
      // screen resolution
      int w = image->width();
      int h = image->height();
    
      // horizontal opening angle
      double alpha = PI/2.0;
    
      // horizontal window dimension [-X,X]
      double X = tan(alpha/2.0);
    
      // pixel size
      double s = 2.0 * X / (double)w;
    
      // vertical window dimension [-Y,Y]
      double Y = s * h / 2.0;
    
      // animation parameter
      tau += 0.05;
    
      // z-Buffer
      vector<double> zBuffer(w*h);
    
      // loop through all pixels of the screen
      for (int i=0; i<w; i++) {
        for (int j=0; j<h; j++) {
    
          // coordinates (x,y,z) of pixel (i,j)
          double x = -X + (i+0.5) * s;
          double y =  Y - (j+0.5) * s;
          double z = 1.0;
    
          // ray through pixel (i,j): 
          // gamma(t) = t * d, where t >= 0 and ||d|| = 1
    			Ray ray;
    			ray.origin	  = Point3d(0.0, 0.0, 0.0);
    			ray.direction = Point3d(x,y,z);
          ray.direction.normalize();
    
          // trace the ray and get the colour of the nearest object
          currentObject = NULL;
          objectZ = -1.0;
    			Color3d color = trace(ray,0);
    
    			image->setPixel(i,j, qRgb( (int) 255*color.r(), (int) 255*color.g(), (int) 255*color.b() ));
    
          zBuffer[i+j*w] = 1.0 / objectZ;
    	  }
      }
    
      //
      // rasterize a line
      //
    
      // line from p1 to p2 in local coordinates
      Point3d p1 (-1.0, 0.0, 0.0);
      Point3d p2 ( 1.0, 0.0, 0.0);
    
      // transformations...
    	Matrix4d S  = Matrix4d::scaling (5.0, 1.0, 1.0);
    	Matrix4d R1 = Matrix4d::rotation (0.5,'z');
    	Matrix4d R2 = Matrix4d::rotation (tau,'x');
    	Matrix4d T  = Matrix4d::translation (0.0, 0.0, 8.0);	
    	Matrix4d P  = Matrix4d::projection (X,Y,s);	
    
      Matrix4d M  = P*T*R2*R1*S;
    
      p1 = M*p1;
      p2 = M*p2;
    
      // screen coordinates
      double x1 = p1.x();
      double y1 = p1.y();
      double z1 = p1.z();
    
      double x2 = p2.x();
      double y2 = p2.y();
      double z2 = p2.z();
    
      //
      // line rasterization algorithm with anti-aliasing and z-test
      // (for lines with slope between -1 and 1)
      //
      int x  = round(x1);
      int y  = round(y1);
    
      double I0 = 1.0;
      double m = (y2-y1) / (x2-x1);
    
      bool up = true;
      if (y2 < y1) {
        m = -m;
        I0 = 0.0;
        up = false;
      }
    
      int nextY;
      double z;
      for ( ; x<=x2; x++) {
        if (up)
          nextY = y+1;
        else
          nextY = y-1;
    
        // barycentric coordinates of the current point: (1-lambda, lambda),
        // i.e.: x = (1-lambda) x1 + lambda x2
        double lambda = (x-x1) / (x2-x1);
    
        // linear interpolation of the inverse z-values
        z = (1.0-lambda)*z1 + lambda*z2;
    
        if ( z > zBuffer[x+y*w] ) {
          int I = (int) 255*I0;
     	    image->setPixel( x, y,     qRgb( 255-I, 255, 255-I ) );
     	    image->setPixel( x, nextY, qRgb(     I, 255,     I ) );
        }
    
        if (m > I0) {
          y  = nextY;
          I0 += 1.0;
        }
        I0 -= m;
      }
    
    
      // repaint canvas
      repaint();
    }
    structs.h (Do not kill for using structs in C++ . The file was given)
    Code:
    #ifndef STRUCTS_h
    #define STRUCTS_h
    
    //-----------------------------------------------------------------------------
    /** Material structure that contains the four types of material coefficiants  *
      * Initilazes the material with a gray color																	*/
    #include "Color.h"
    #include "Point3.h"
    #include "Base.h"
    
    struct Material{
        Color3d ambient;
        Color3d diffuse;
        Color3d specular;
        double shininess;
        double reflectivity;
    };
    
    //-----------------------------------------------------------------------------
    /** The ray structure contains the origin and direction of the ray						*/  
    struct Ray{
        Point3d direction;
        Point3d origin;
    };
    
    //-----------------------------------------------------------------------------
    /** Simple intersection structure. Contains not only the intersection point,  
     *  but although if there is an intersection after all and if the camera
     *  is within the object																											*/
    struct IntersectionInfo{
        Point3d point;
        Point3d normal;
        double distance;
        bool intersect;
        bool inside;
    };
    
    #endif;

    Attempts (ok one of all)
    Code:
    Ray rayLine;
            rayLine.origin	  = Point3d(x,y,z1);//(p1.x(), p1.y(), p1.z());
            rayLine.direction = Point3d(x2,y2,z2);
            rayLine.direction.normalize();
    
    
            Color3d backgroundColor = trace(rayLine,0);
            Object* objInter = findNearestObject(rayLine);
            if(objInter!=NULL) cout<<"ok\n";
    
            int I = (int) 255*I0;
            if(backgroundColor.r() != 1.0 && backgroundColor.g() != 1.0
                    && backgroundColor.b() != 1.0)
                cout<<backgroundColor.r()<<" "<<backgroundColor.g()<<" "<<backgroundColor.b()<<endl;
            image->setPixel( x, y,     qRgb( (255-I) + (int)255 * backgroundColor.r(), 255 + (int)255* backgroundColor.g(), (255-I) + (int)255* backgroundColor.b() ) );
            image->setPixel( x, nextY, qRgb( I + (int)255 * backgroundColor.r(), 255 + (int)255* backgroundColor.g(), I + (int)255* backgroundColor.b()) );
    Hope somebody has something to say.

    PS - If you had seen a post done by me several weeks ago, it was the base code for going on.
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  2. #2
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    Maybe I should point out , that the only thing that needs to be modified is the code in lines 352, 353. There we draw the line, but we take into no consideration the background. The modification needed is to take into account the background color.

    Also an image of my output
    Name:  Screen Shot 2012-12-01 at 6.03.10 PM.jpg
Views: 179
Size:  27.9 KB
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  3. #3
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    Think I found a solution with declaring three 2D arrays and keep color state for every pixel when ray tracing.

    Eventually a question that I think you will like :

    I would like to declare a vector that will behave equivalently with the 2D array. Googling was not very clear for me. As you understand, I am an absolute beginner to vectors (!) and not going to be something else in the near future :P
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Anti-Aliasing Programming
    By yes i am a noob in forum C Programming
    Replies: 2
    Last Post: 08-31-2006, 11:27 PM
  2. Anti aliasing
    By arjunajay in forum Windows Programming
    Replies: 7
    Last Post: 08-15-2006, 08:24 PM
  3. static text color/background color
    By braindude in forum C++ Programming
    Replies: 1
    Last Post: 07-06-2003, 05:58 AM
  4. CEditView Background Color & Font Color :: MFC
    By kuphryn in forum Windows Programming
    Replies: 5
    Last Post: 05-30-2002, 09:44 AM
  5. anti aliasing
    By muttski in forum Game Programming
    Replies: 2
    Last Post: 03-16-2002, 05:55 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21