7
2013
Basic Illumination Model C#
Converted this script to unity: Basic Illumination Model by andalmeida.
Problems / info:
– Converted most of the values to floats.. because Mathf.Max() didnt like doubles.. i guess could had made some extension to it.. (maybe thats why there are some artifacts)
– Specularity didnt work at first, but there was new code clip in the comments section of that link ^
– Rendering is currently done with invidual setpixel()’s on a plane..(texture size 200×200)
Webplayer:
http://unitycoder.com/upload/demos/BasicIlluminationModelRender/
Source: ()
// Original source : http://www.codeproject.com/Articles/19767/Basic-Illumination-Model-in-C // converted to Unity: @unitycoder_com using UnityEngine; using System.Collections; public class DiffuseRender : MonoBehaviour { public Transform shaderObject; // not really needed, just for testing private Texture2D tex; private bool ambientti = false; private bool spec = false; private Vector3 mpos; // Use this for initialization void Start () { // create texture tex = new Texture2D(200, 200, TextureFormat.ARGB32, false); renderer.material.mainTexture = tex; //renderer.material.mainTexture.filterMode = FilterMode.Point; Page_Load(); } void Update() { // if properties changed, render again if (Input.GetMouseButton(0)) { mpos = Input.mousePosition; } if (Input.GetKeyDown("1")) { shaderObject.renderer.material.SetColor("_DiffuseColor", new Color(Random.value,Random.value,Random.value,1)); } if (Input.GetKeyDown("2")) { ambientti=!ambientti; if (ambientti) { shaderObject.renderer.material.SetColor("_AmbientColor", new Color(0,0,0,1)); }else{ shaderObject.renderer.material.SetColor("_AmbientColor", new Color(0.05f,0.03f,0.01f,1.0f)); } } if (Input.GetKeyDown("3")) { spec=!spec; if (spec) { shaderObject.renderer.material.SetFloat("_Shininess", 0.6f); }else{ shaderObject.renderer.material.SetFloat("_Shininess", 0.0f); } } Page_Load(); } 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 (Mathf.Abs((float)a) < eps) { if (Mathf.Abs((float)i) < eps) { outx = -inx; outy = iny; outz = -inz; return; } else { double dn = (y - (x * j) / i); if (Mathf.Abs((float)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 (Mathf.Abs((float)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.Mathf.Sqrt(vx * vx + vy * vy + vz * vz); return Mathf.Sqrt((float)(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 (Mathf.Abs((float)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 * Mathf.Cos((float)angle) - cz * Mathf.Sin((float)angle); double z = cy * Mathf.Sin((float)angle) + cz * Mathf.Cos((float)angle); cy = y; cz = z; } void RotY(double angle) { double x = cx * Mathf.Cos((float)angle) - cz * Mathf.Sin((float)angle); double z = cx * Mathf.Sin((float)angle) + cz * Mathf.Cos((float)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 - Mathf.Sqrt((float)D)) / (2.0 * A); double t2 = (-B + Mathf.Sqrt((float)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) private void Page_Load() { // 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); Color mDiffuse = shaderObject.renderer.material.GetColor("_DiffuseColor"); Color mAmbient = shaderObject.renderer.material.GetColor("_AmbientColor"); Color mSpecular = shaderObject.renderer.material.GetColor("_SpecularColor"); float mShininess = shaderObject.renderer.material.GetFloat("_Shininess"); //tSphere sph1 = new tSphere(0.01, 0.001, 10, 200.0, 1.0, 1.0, 1.0); tSphere sph1 = new tSphere(0.0, 0.0, 10, 200.0, mDiffuse.r,mDiffuse.g,mDiffuse.b); //tSphere sph2 = new tSphere(-50, 0.001, 350, 30.0, mDiffuse.r,mDiffuse.g,mDiffuse.b); //Debug.Log(mSpecular); /* // 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; */ // ambient properties for the material sph1.ambientR = mAmbient.r; sph1.ambientG = mAmbient.g; sph1.ambientB = mAmbient.b; // specular properties for the material sph1.specularR = mSpecular.r; sph1.specularG = mSpecular.g; sph1.specularB = mSpecular.b; sph1.shininess = mShininess; sph1.diffuseR = mDiffuse.r; sph1.diffuseG = mDiffuse.g; sph1.diffuseB = mDiffuse.b; /* sph2.ambientR = mAmbient.r; sph2.ambientG = mAmbient.g; sph2.ambientB = mAmbient.b; // specular properties for the material sph2.specularR = mSpecular.r; sph2.specularG = mSpecular.g; sph2.specularB = mSpecular.b; sph2.shininess = mShininess; sph2.diffuseR = mDiffuse.r; sph2.diffuseG = mDiffuse.g; sph2.diffuseB = mDiffuse.b; */ obj3dArrayList.Add(sph1); // obj3dArrayList.Add(sph2); //Graphics graphics = g; double px = 0.0; double py = 0.0; double pz = 600.0; // light? // double lpx = 200.0; // double lpy = 200.0; // double lpz = 200.0; // get mousePos //Vector3 = Camera.main.ViewportToScreenPoint(Input.MousePosition); double lpx = (mpos.x-Screen.width*0.5f)*2; double lpy = (Screen.height-(mpos.y*2))*2; //-Screen.height*0.5f); double lpz = 400.0; double fMax = 320.0; //for (int i = rect.Left; i <= rect.Right; i++) for (int i = 0; i <= 200; i++) { //double x = Sphere.GetCoord(rect.Left, rect.Right, -fMax, fMax, i); double x = Sphere.GetCoord(0, 200, -fMax, fMax, i); //for (int j = rect.Top; j <= rect.Bottom; j++) for (int j = 0; j <= 200; j++) { //double y = Sphere.GetCoord(rect.Top, rect.Bottom, fMax, -fMax, j); double y = Sphere.GetCoord(0,200, 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); Color color = new Color(0,0,0,1); 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; double vEye2IntersX = px - intersx, vEye2IntersY = py - intersy, vEye2IntersZ = pz - intersz; // tAlgebra.Reflect(-lvX, -lvY, -lvZ, // normalX, normalY, normalZ, // ref vReflX, ref vReflY, ref vReflZ); tAlgebra.Reflect(lvX,lvY,lvZ, normalX,normalY,normalZ,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); 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 = Mathf.Max(0.0f, (float)cost) * 255.0; double result2 = Mathf.Pow(Mathf.Max(0, (float)cosf), (float)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 = Mathf.Min((float)rgbR, 255); rgbG = Mathf.Min((float)rgbG, 255); rgbB = Mathf.Min((float)rgbB, 255); rgbR = Mathf.Max(0, (float)rgbR); rgbG = Mathf.Max(0, (float)rgbG); rgbB = Mathf.Max(0, (float)rgbB); //color = Color.FromArgb((int)rgbR, (int)rgbG, (int)rgbB); color = new Color((int)rgbR/255, (int)rgbG/255, (int)rgbB/255);*/ double result1 = Mathf.Max(0.0f, (float)cost); double result2 = Mathf.Pow(Mathf.Max(0.0f, (float)cosf), (float)spherehit.shininess); double rgbR = (spherehit.ambientR) + (spherehit.diffuseR * result1) + (spherehit.specularR * result2); double rgbG = (spherehit.ambientG) + (spherehit.diffuseG * result1) + (spherehit.specularG * result2); double rgbB = (spherehit.ambientB) + (spherehit.diffuseB * result1) + (spherehit.specularB * result2); rgbR = Mathf.Min((float)rgbR, 1.0f); rgbG = Mathf.Min((float)rgbG, 1.0f); rgbB = Mathf.Min((float)rgbB, 1.0f); rgbR = Mathf.Max(0, (float)rgbR); rgbG = Mathf.Max(0, (float)rgbG); rgbB = Mathf.Max(0, (float)rgbB); //color = Color.FromArgb((int)rgbR, (int)rgbG, (int)rgbB); color = new Color((float)rgbR, (float)rgbG, (float)rgbB, 1.0f); } tex.SetPixel(i,j,color); //Brush brs = new SolidBrush(color); //graphics.FillRectangle(brs, i, j, 1, 1); //brs.Dispose(); }// for pixels lines }// for pixels columns /////////////////////////////////////// tex.Apply(false); } }
Related Posts
1 Comment + Add Comment
Leave a comment
Recent posts
- MotionVector Effect: Object “disappears” when paused
- [GreaseMonkey] Unity Forum Fixer
- UnityHub: Make Hub application background Translucent
- Customize SpriteShapeRenderer quality (but has issues)
- Editor tool: Copy selected gameobject’s names into clipboard as rows (for Excel)
- Editor tool: Replace string in selected gameobject’s names
- UnityHub: Enable built-in Login Dialog (no more browser login/logout issues!)
- Use TikTok-TTS in Unity (with WebRequest)
- Create Scene Thumbnail Image using OnSceneSaved & OnPreviewGUI
- webgl+javascript TTS
- Using Moonsharp (LUA) + Unity Webgl
- Using 3D gameobject prefabs with Unity Tilemap + NavMesh Surface
Recent Comments
- [Asset Store] Point Cloud Viewer & Tools on
- [Asset Store] Point Cloud Viewer & Tools on
- Vector3 maths for dummies! on
- UnityHub: Make Hub application background Translucent on
- UnityHub: Make Hub application background Translucent on
- Install Android SDK+JDK+NDK for Unity (without AndroidStudio or Unity Hub) on
- Install Android SDK+JDK+NDK for Unity (without AndroidStudio or Unity Hub) on
- [Asset Store] Point Cloud Viewer & Tools on
^ source added