Lambertian Model using OpenCV C++

Simple Lambertian model which says that intensity of light at a point is directly proportional to the cosine of angle between angle of incidence and the normal of the surface. OpenCV 3.4.3 is used here to create a artificial moon using C++. If you want to replicate the result then hopefully this blog article may be useful for you.
//Author : Subha Sarkar

#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<math.h>
#include<stdio.h>
#include<stdlib.h>

#define RADIUS 150
#define CENTER_Y (IMAGE_HEIGHT/2)
#define CENTER_X (IMAGE_WIDTH/2)
#define IMAGE_HEIGHT 400
#define IMAGE_WIDTH 400
#define WINDOW_NAME "SHADER (ARTIFICIAL MOON) USING C++"

using namespace std;
using namespace cv;

typedef struct
{
	double cos_alpha;
	double cos_beta;
	double cos_gamma;
}cosines;

typedef struct
{
	double x;
	double y;
	double z;
}vect;

Mat image(IMAGE_WIDTH, IMAGE_HEIGHT, CV_8UC1, Scalar(0));
int slider;
const int SLIDER_MAX = 180;
cosines shader[IMAGE_HEIGHT][IMAGE_WIDTH] = { 0 };

double cosz(double, double);
int assign_shader_vector(cosines(*)[IMAGE_WIDTH]);

void slider_function(int, void*);


int main()
{
	//int i, j;
	namedWindow(WINDOW_NAME);
	//imshow(WINDOW_NAME, image);
	//radius of the circle is 150 pixels
	//Creating the Look up array for the 3D shade effect
	assign_shader_vector(shader);
	slider = 0;
	
	createTrackbar("ADJUST", WINDOW_NAME, &slider, SLIDER_MAX, slider_function);
	while (char(waitKey(1)) != 'q');
	return 0;
}

double cosz(double cosx, double cosy)
{
	double temp = 0;
	temp = 1.00 - cosx*cosx - cosy*cosy;
	temp = sqrt(temp);
	return temp;
}

int assign_shader_vector(cosines(*shader)[IMAGE_WIDTH])
{
	int i = 0;
	int j = 0;
	for (j = 0;j < IMAGE_HEIGHT;j++)
	{
		for (i = 0;i < IMAGE_WIDTH;i++)
		{
			if ((RADIUS * RADIUS) >((i - CENTER_X)*(i - CENTER_X) + (j - CENTER_Y)*(j - CENTER_Y))) // means that the point is inside the circle
			{
				(*(*(shader + j) + i)).cos_alpha = ((double)i - CENTER_X) / RADIUS;
				(*(*(shader + j) + i)).cos_beta = ((double)j - CENTER_Y) / RADIUS;
				(*(*(shader + j) + i)).cos_gamma = cosz(((double)i - CENTER_X) / RADIUS, ((double)j - CENTER_Y) / RADIUS);
			}
		}
	}
	return 0;
}


void slider_function(int position, void*)
{
	double temp;
	int i = 0;
	int j = 0;
	vect v = { 0,0,0 };
	v.x = (double)SLIDER_MAX / 2 - (double)position;
	v.y = 0.00;
	v.z = -(double)30; //this decides the region upto which the artificial light is adjustable
	temp = sqrt(v.x*v.x + v.z*v.z);
	v.x = v.x / temp;
	v.z = v.z / temp;
	for (j = 0;j<IMAGE_HEIGHT;j++)
	{
		for (i = 0;i<IMAGE_WIDTH;i++)
		{
			if ((*(*(shader + j) + i)).cos_alpha != 0.00 || (*(*(shader + j) + i)).cos_beta != 0.00 || (*(*(shader + j) + i)).cos_gamma != 0.00)
			{
				temp = (-v.x * ((*(*(shader + j) + i)).cos_alpha) - v.y*((*(*(shader + j) + i)).cos_beta) - v.z*((*(*(shader + j) + i)).cos_gamma));
				if (temp > 0.00)
				{
					image.at<uchar>(j, i) = temp * 255.0;
				}
				else
				{
					image.at<uchar>(j, i) = 0;
				}
			}
		}
	}
	imshow(WINDOW_NAME, image);
	return;
}

Demonstration of the Artificial Moon

The above image shows the result of the aforementioned code compiled successfully in Raspberry Pi 2, OpenCV 3.4.3.

CMake File (CMakeLists.txt)

cmake_minimum_required(VERSION 3.0)
project( ArtificialMoon )
find_package( OpenCV REQUIRED )
add_executable( ArtificialMoon ArtificialMoon.cpp )
target_link_libraries( ArtificialMoon ${OpenCV_LIBS} )