|
Hi!
thanks to you, from all you're articles, I learned ray tracing. Nom I'm just asking about getcoordinate() function, in some algorithms we use :
double px=(2 * ((x + 0.5) / imageWidth) - 1) * tan(fov / 2 * M_PI / 180) * imageAspectRatio;
doubl py = (1 - 2 * ((y + 0.5) / imageHeight) * tan(fov / 2 * M_PI / 180);
but you was using fmax instead of tan(fov/2*M_PI / 180)
is it the same ?
do fmax mean focal max ?
what is this function relation have with 3d perspective projection ?
at all, how did you get the formula, ((p - i1) / (i2 - i1)) * (w2 - w1) + w1; ?
|
|
|
|
|
... how this can be approved as an article.
Nevertheless good Information
modified 19-Jan-21 21:04pm.
|
|
|
|
|
Hi,
I'm make the backgammon game and I want to add some property in Piece.
One of them, Reflection Light Effect like yours. I download your project but it's not runnig. I wonder, how can do this effect?
Thank you in advance for your help.
|
|
|
|
|
Hi there what is the error you have?
BR
|
|
|
|
|
I want to make Ambient+Diffuse effect in my project. For this, I download your project but it's not running. I'm try to open the project, it's throw exception.
Now, I have the "Checker Custom Control" and it's like your "Ambient Effect". I want to change it with your Ambient+Diffuse Effect. But I can't do this. Please help me. Thanks for helping.Good Day 
|
|
|
|
|
I think the exception is due to the input text file.
But you can workaround commenting the radiosity test lines.
Are you able to locate this?
BR
|
|
|
|
|
Yes, it's work. Thanks or interesting 
|
|
|
|
|
<%@ Page Language="c#" Debug="true" Explicit="True" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.OleDb" %>
<%@ Import Namespace="System.Data.OleDb" %>
<%@ Import Namespace="System.Drawing" %>
<%@ Import Namespace="System.Web.Mail" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="Microsoft.CSharp" %>
<%@ Import Namespace="System.Drawing.Imaging" %>
<%@ Import Namespace="System.CodeDom.Compiler" %>
<%@ Import Namespace="System.Reflection" %>
<%@ Import Namespace="System.Collections" %>
public class tAlgebra
{
public tAlgebra()
{
}
public static void Cross3(double ax, double ay, double az,
double bx, double by, double bz,
ref double outx, ref double outy, ref double outz)
{
outx = ay * bz - az * by;
outy = az * bx - ax * bz;
outz = ax * by - ay * bx;
}
public static void Reflect(double inx, double iny, double inz,
double mirrorx, double mirrory, double mirrorz,
ref double outx, ref double outy, ref double outz)
{
double perp1x = 0.0, perp1y = 0.0, perp1z = 0.0;
double perp2x = 0.0, perp2y = 0.0, perp2z = 0.0;
Cross3(inx, iny, inz, mirrorx, mirrory, mirrorz,
ref perp1x, ref perp1y, ref perp1z);
Normalize(ref perp1x, ref perp1y, ref perp1z);
Cross3(perp1x, perp1y, perp1z, mirrorx, mirrory, mirrorz,
ref perp2x, ref perp2y, ref perp2z);
Normalize(ref perp2x, ref perp2y, ref perp2z);
double a = mirrorx;
double b = perp2x;
double c = inx;
double x = mirrory;
double y = perp2y;
double z = iny;
double i = mirrorz;
double j = perp2z;
double k = inz;
double n = 0.0, m = 0.0;
double eps = 1.0E-5;
if (Math.Abs(a) < eps)
{
if (Math.Abs(i) < eps)
{
outx = -inx;
outy = iny;
outz = -inz;
return;
}
else
{
double dn = (y - (x * j) / i);
if (Math.Abs(dn) < eps)
{
outx = -inx;
outy = iny;
outz = -inz;
return;
}
n = (z - (x * k) / i) / dn;
m = (k - (j * n)) / i;
}
}
else
{
double dn = (y - (x * b) / a);
if (Math.Abs(dn) < eps)
{
outx = -inx;
outy = iny;
outz = -inz;
return;
}
n = (z - (x * c) / a) / dn;
m = (c - (b * n)) / a;
}
double v1x = mirrorx;
double v1y = mirrory;
double v1z = mirrorz;
double v2x = perp2x;
double v2y = perp2y;
double v2z = perp2z;
v1x *= m;
v1y *= m;
v1z *= m;
v2x *= n;
v2y *= n;
v2z *= n;
outx = v1x - v2x;
outy = v1y - v2y;
outz = v1z - v2z;
return;
}
public static double Dot3(double x1, double y1, double z1, double x2, double y2, double z2)
{
return ((x1 * x2) + (y1 * y2) + (z1 * z2));
}
public static double GetCosAngleV1V2(double v1x, double v1y, double v1z, double v2x, double v2y, double v2z)
{
// cos(t) = (v.w) / (|v|.|w|) = (v.w) / 1
return Dot3(v1x, v1y, v1z, v2x, v2y, v2z);
}
public static double modv(double vx, double vy, double vz)
{
return System.Math.Sqrt(vx * vx + vy * vy + vz * vz);
}
public static bool Normalize(ref double vx, ref double vy, ref double vz)
{
double mod_v = tAlgebra.modv(vx, vy, vz);
double eps = 1.0E-20;
if (Math.Abs(mod_v) < eps)
return true;
vx = vx / mod_v;
vy = vy / mod_v;
vz = vz / mod_v;
return false;
}
}
public class tObject
{
public tObject()
{
}
// Final illumination of a point (vertex) = ambient + diffuse + specular
/*
Ambient Light Contribution
Ambient light = background light
Light that is scattered by the environment
Frequently assumed to be constant
Very simple approximation of global illumination
No direction: independent of light position, object
orientation, observer’s position or orientation
*/
// ambient RGBA reflectance of the material default = (0.2, 0.2, 0.2, 1.0)
public double ambientR, ambientG, ambientB, ambientA;
/*
Diffuse Light Calculation
Need to decide how much light the object point receive
from the light source – based on Lambert’s Law
Lambert’s law: the radiant energy D that a small surface
patch receives from a light source is:
D = I x cos (q)
*/
// diffuse RGBA reflectance of the material default = (0.8, 0.8, 0.8, 1.0)
public double diffuseR, diffuseG, diffuseB, diffuseA;
// specular RGBA reflectance of the material default = (0.0, 0.0, 0.0, 1.0)
// Fresnel factor, which depends on angle of incidence and refractive index
// of material (which in turn depends on wavelength of light)
// The overall effect is that the specular reflection does depend on the angle
// of incidence of the light (it is brighter for grazing angles of incidence),
// and it does reflect the material colour (more so if the light is nearly
// normal to surface)
/*
Specular light contribution
The bright spot on the object
The result of total reflection of
the incident light in a concentrate
specular = Ks x I x cos(f)^n
* */
public double specularR, specularG, specularB, specularA;
// RGBA emitted light intensity of the material default = (0.0, 0.0, 0.0, 1.0)
public double emissionR, emissionG, emissionB, emissionA;
// specifies the RGBA specular exponent of the material default = 0
public double shininess;
/*
Illumination from each light: (*sum all)
Illum = ambient + diffuse + specular
= Ka x I + Kd x I x ( cos q) + Ks x I x cos(f)^n
q = angle between light vector and normal to surface
f is the angle between reflection light and viewer direction
n = shininess
*/
}
public class tSphere : tObject
{
public tSphere(double x, double y, double z, double r, double clr, double clg, double clb)
{
cx = x;
cy = y;
cz = z;
radius = r;
clR = clr;
clG = clg;
clB = clb;
}
public static double GetCoord(double i1, double i2, double w1, double w2, double p)
{
return ((p - i1) / (i2 - i1)) * (w2 - w1) + w1;
}
void Move(double vx, double vy, double vz)
{
cx += vx;
cy += vy;
cz += vz;
}
void MoveTo(double vx, double vy, double vz)
{
cx = vx;
cy = vy;
cz = vz;
}
void RotX(double angle)
{
double y = cy * System.Math.Cos(angle) - cz * System.Math.Sin(angle);
double z = cy * System.Math.Sin(angle) + cz * System.Math.Cos(angle);
cy = y;
cz = z;
}
void RotY(double angle)
{
double x = cx * System.Math.Cos(angle) - cz * System.Math.Sin(angle);
double z = cx * System.Math.Sin(angle) + cz * System.Math.Cos(angle);
cx = x;
cz = z;
}
public static double GetSphereIntersec(double cx, double cy, double cz, double radius,
double px, double py, double pz, double vx, double vy, double vz)
{
// x-xo 2 + y-yo 2 + z-zo 2 = r 2
// x,y,z = p+tv
// At2 + Bt + C = 0
double A = (vx * vx + vy * vy + vz * vz);
double B = 2.0 * (px * vx + py * vy + pz * vz - vx * cx - vy * cy - vz * cz);
double C = px * px - 2 * px * cx + cx * cx + py * py - 2 * py * cy + cy * cy + pz * pz - 2 * pz * cz + cz * cz - radius * radius;
double D = B * B - 4 * A * C;
double t = -1.0;
if (D >= 0)
{
double t1 = (-B - System.Math.Sqrt(D)) / (2.0 * A);
double t2 = (-B + System.Math.Sqrt(D)) / (2.0 * A);
if (t1 < t2) t = t1; else t = t2;
}
return t;
}
public void getNormal(double x1, double y1, double z1, ref double vx1, ref double vy1, ref double vz1)
{
vx1 = x1 - cx;
vy1 = y1 - cy;
vz1 = z1 - cz;
}
public double cx, cy, cz, radius, clR, clG, clB;
}
private void Page_Load(object sender, System.EventArgs e)
{
Bitmap newBitmap = new Bitmap(200, 200, PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(newBitmap);
Pen blackPen = new Pen(Color.Black);
Color clrBackground = Color.Black;
g.FillRectangle(new SolidBrush(clrBackground), new Rectangle(0, 0, 200, 200));
Rectangle rect = new Rectangle(0, 0, 200, 200);
///////////////////////////////////////
System.Collections.ArrayList obj3dArrayList;
obj3dArrayList = new System.Collections.ArrayList();
tSphere sph1 = new tSphere(0.01, 0.001, 10, 200.0, 0.0, 0.0, 255.0);
// ambient properties for the material
sph1.ambientR = 0.329412;
sph1.ambientG = 0.223529;
sph1.ambientB = 0.027451;
// specular properties for the material
sph1.specularR = 0.992157;
sph1.specularG = 0.941176;
sph1.specularB = 0.807843;
sph1.shininess = 27.8974;
sph1.diffuseR = 0.780392;
sph1.diffuseG = 0.568627;
sph1.diffuseB = 0.113725;
obj3dArrayList.Add(sph1);
Graphics graphics = g;
double px = 0.0;
double py = 0.0;
double pz = 600.0;
double lpx = -500;// 200.0;
double lpy = -500;// 200.0;
double lpz = 400.0;
double fMax = 320.0;
for (int i = rect.Left; i <= rect.Right; i++)
{
double x = tSphere.GetCoord(rect.Left, rect.Right, -fMax, fMax, i);
for (int j = rect.Top; j <= rect.Bottom; j++)
{
double y = tSphere.GetCoord(rect.Top, rect.Bottom, fMax, -fMax, j);
double t = 1.0E10;
double vx = x - px, vy = y - py, vz = -pz;
double mod_v = tAlgebra.modv(vx, vy, vz);
vx = vx / mod_v;
vy = vy / mod_v;
vz = vz / mod_v;
bool bShadow = false;
tSphere spherehit = null;
for (int k = 0; k < (int)obj3dArrayList.Count; k++)
{
tSphere sphn = (tSphere)obj3dArrayList[k];
double taux = tSphere.GetSphereIntersec(sphn.cx, sphn.cy, sphn.cz, sphn.radius, px, py, pz, vx, vy, vz);
if (taux < 0) continue;
if (taux > 0 && taux < t)
{
t = taux;
spherehit = sphn;
}
}
Color color = Color.FromArgb(0, 0, 0);
if (spherehit != null)
{
double intersx = px + t * vx,
intersy = py + t * vy,
intersz = pz + t * vz;
double normalX = intersx - spherehit.cx,
normalY = intersy - spherehit.cy,
normalZ = intersz - spherehit.cz;
double lvX = lpx - intersx,
lvY = lpy - intersy,
lvZ = lpz - intersz;
tAlgebra.Normalize(ref normalX, ref normalY, ref normalZ);
tAlgebra.Normalize(ref lvX, ref lvY, ref lvZ);
double cost = tAlgebra.GetCosAngleV1V2(lvX, lvY, lvZ,
normalX, normalY, normalZ);
double cosf = 0;
double vReflX = 0, vReflY = 0, vReflZ = 0;
tAlgebra.Reflect(-lvX, -lvY, -lvZ,
normalX, normalY, normalZ,
ref vReflX, ref vReflY, ref vReflZ);
tAlgebra.Normalize(ref vReflX, ref vReflY, ref vReflZ);
tAlgebra.Normalize(ref vx, ref vy, ref vz);
cosf = tAlgebra.GetCosAngleV1V2(vx, vy, vz, vReflX, vReflY, vReflZ);
double result1 = Math.Max(0, cost) * 255.0;
double result2 = Math.Pow(Math.Max(0, cosf), spherehit.shininess) * 255.0;
double rgbR = (spherehit.ambientR * 255.0) + (spherehit.diffuseR * result1) + (spherehit.specularR * result2);
double rgbG = (spherehit.ambientG * 255.0) + (spherehit.diffuseG * result1) + (spherehit.specularG * result2);
double rgbB = (spherehit.ambientB * 255.0) + (spherehit.diffuseB * result1) + (spherehit.specularB * result2);
rgbR = Math.Min(rgbR, 255);
rgbG = Math.Min(rgbG, 255);
rgbB = Math.Min(rgbB, 255);
rgbR = Math.Max(0, rgbR);
rgbG = Math.Max(0, rgbG);
rgbB = Math.Max(0, rgbB);
color = Color.FromArgb((int)rgbR, (int)rgbG, (int)rgbB);
}
Brush brs = new SolidBrush(color);
graphics.FillRectangle(brs, i, j, 1, 1);
brs.Dispose();
}// for pixels lines
}// for pixels columns
///////////////////////////////////////
MemoryStream tempStream = new MemoryStream();
newBitmap.Save(tempStream, ImageFormat.Png);
Response.ClearContent();
Response.ContentType = "image/png";
Response.BinaryWrite(tempStream.ToArray());
Response.Flush();
}
<title>Raytracing
_uacct = "UA-2275356-1";
urchinTracker();
|
|
|
|
|
|
you can run in visual studio or in a website...
Project new website...
Create new webform uncheck (place code in separate file)
Paste the code in the file
run the project
let me know if works
|
|
|
|
|
|
Last article currently available: http://www.codeproject.com/KB/graphics/Simple_Ray_Tracing_in_C7.aspx
Anderson J. Almeida
Systems Analyst
TIHunter
http://www.tihunter.com
|
|
|
|
|
Hi.
I didn't dive into the article and sample project too deep, but from my first glance at the provided images I wondered why the specular lighting is not (or seems not to be) related to the direction of the light in any way.
On the screenshot it looks like the bright highlight is caused directly by the camera.
If the light comes from aside, the highlight cannot be in the center of the sphere's visible area. And imagine a scene similar to a solar eclipse: The light is behind the sphere - no specular highlight at all would be visible.
Anyways it's nice to have some CG topics covered here!
|
|
|
|
|
Hi,
the observer and light are on same side of object for those tracings...
Follows the settings:
// observer/eye/camera
double px = 0.0;
double py = 0.0;
double pz = 600.0;
// light position
double lpx = 200.0;
double lpy = 200.0;
double lpz = 200.0;
// sphere centered at (0,0,90) radius=100
tSphere sph1 = new tSphere(0.0, 0.0, 90.0, 100.0, 0.0, 0.0, 255.0);
// ambient properties for the material
sph1.ambientR = 0.329412;
sph1.ambientG = 0.223529;
sph1.ambientB = 0.027451;
// specular properties for the material
sph1.specularR = 0.992157;
sph1.specularG = 0.941176;
sph1.specularB = 0.807843;
sph1.shininess = 27.8974;
sph1.diffuseR = 0.780392;
sph1.diffuseG = 0.568627;
sph1.diffuseB = 0.113725;
double intersx = px + t * vx, intersy = py + t * vy,
intersz = pz + t * vz;
double vNormalX = intersx - spherehit.cx, vNormalY=intersy -
spherehit.cy, vNormalZ=intersz - spherehit.cz;
//diffuse calculation: based on the angle theta (the angle between
ray direction and surface normal at intersection)
double cost = tAlgebra.GetCosAngleV1V2(lvx, lvy, lvz, vNormalX,
vNormalY, vNormalZ);
double vReflX = 0, vReflY = 0, vReflZ = 0;
double vEye2IntersX = px - intersx, vEye2IntersY = py - intersy,
vEye2IntersZ = pz - intersz;
tAlgebra.Reflect(lvx,lvy,lvz, vNormalX,vNormalY,vNormalZ,ref vReflX,
ref vReflY, ref vReflZ);
// specular calculation: based on the angle phi (the angle between
viewing direction and reflected ray direction)
double cosf = tAlgebra.GetCosAngleV1V2(vReflX, vReflY, vReflZ,
vEye2IntersX, vEye2IntersY, vEye2IntersZ);
Anyway, i have applied some rotation to the final points in some shots
Anderson J. Almeida
Systems Analyst
SimSysBr
|
|
|
|
|
Wow. Thank you for your fast reply.
As the code you just provided makes clear - as far as I can see (not that far ) that the specularity does not take the exact position of the light source into consideration.
This is not the way mother nature (and leading 3D applications) do their calculations.
I prepared a little image with two spheres - one diffuse only and one diffuse+secular and a light source coming from the bottom left and a bit from the front (where the camera is located).
http://img181.imageshack.us/img181/3341/3ddemo1np4.jpg
I included one of your images as reference. You can see that the "real" specularity lies not in the sphere's center but is halfway moved to where the light source is located.
Hope it got clearer what I treid to express. 
|
|
|
|
|
You are right, i will change my model to fit the real calculation
Anderson J. Almeida
Systems Analyst
SimSysBr
|
|
|
|
|
It is fixed now. I helped me also to find an issue in my algebra class, thanks so much.
Anderson J. Almeida
Systems Analyst
SimSysBr
|
|
|
|
|
thats what i was looking for but for a cube
It is Good to be Important but!
it is more Important to be Good
|
|
|
|
|
Hi,
I just finished a new algorith of ray tracing with triangles and a cube as model, will post here
Anderson J. Almeida
Systems Analyst
SimSysBr
|
|
|
|
|