Painting light in C + + (c)--dispersion

Source: Internet
Author: User
Tags square root

Write in front

Source: Https://github.com/bajdcc/GameFramework/blob/master/CCGameFramework/base/pe2d/Render2DScene5.cpp

The main content of this article:

    1. Rendering of triangles
    2. The implementation of the spotlight effect
    3. Simple version realization of dispersion
Rendering of triangles

In the previous article, the main introduction of the rectangular rendering, in fact, the triangle is similar to it, nothing more than to judge the relationship between line and line.

Data structures for triangles:

// 三角形class Geo2DTriangle : public Geo2DShape{public:    Geo2DTriangle(vector2 p1, vector2 p2, vector2 p3, color L, color R, float eta, color S);    ~Geo2DTriangle() = default;    Geo2DResult sample(vector2 ori, vector2 dir) const override;    vector2 get_center() const override;    vector2 center, p1, p2, p3;    vector2 n[3];};

Places to be aware of:

    1. The center point of the Triangle (centre of gravity) is calculated.
    2. Cache triangle three-edge normals
    3. Make sure that the three-point p1~p3 is arranged in a clockwise direction

Vertex sort and normal settings

//Assume that the three vertices are in the clockwise direction Const Auto p12 = P2-P1; Const Auto p13 = P3-P1; if //Make sure points 1, 2, 3 are clockwise {    constauto tmp = p2;    P2 = p3;    P3 = tmp;}  N[0] = p2-p1;n[0] = Normalize (Vector2 (N[0].Y,-n[0].x)); n[1] = p3-p2;n[1] = Normalize (Vector2 (N[1].Y,-n[1].x)); n[2] = P1-P3;N[2] = Normalize (Vector2 (N[2].Y,-n[2].x));

How do you know that three points are arranged in a clockwise order? is essentially the side of a line segment that is formed at a point at two other points.

Is the point p on the left or right side of the line L? Can be multiplied by the fork, we just know the cross-multiply the result of the symbol can be.

The sampling method of a triangle is similar to that of a rectangle:

Geo2dresult geo2dtriangle::sample (vector2 ori, Vector2 dir)Const{ConstVector2 Pts[3] = {P1,P2,P3};Static intM[3][2] = {{0,1},{},{2,0}};floatT[2]; Vector2 p[2];intIDS[2];intCNT = 0; for(inti = 0; I < 3 && cnt < 2; i++) {if(Intersectwithlineab (Ori, dir, pts[m[i][0], pts[m[i][1]], t[cnt], p[cnt]))        {ids[cnt++] = i; }    }if(cnt = = 2) {Const Autotd = ((T[0] >= 0? 1:0) << 1) | (T[1] >= 0? 1:0);Switch(TD) { Case0://Double counter, no intersection, outside             Break; Case1://t[1], with intersection, inside            returnGeo2dresult ( This,true, Geo2dpoint (T[0], p[0], N[ids[0]]), Geo2dpoint (T[1], p[1], n[ids[1])); Case2://t[0], with intersection, inside            returnGeo2dresult ( This,true, Geo2dpoint (T[1], p[1], n[ids[1]]), Geo2dpoint (T[0], p[0], n[ids[0])); Case3://Double positive, with intersection, outside            if(T[0] > T[1]) {returnGeo2dresult ( This,false, Geo2dpoint (T[1], p[1], n[ids[1]]), Geo2dpoint (T[0], p[0], n[ids[0])); }Else{returnGeo2dresult ( This,false, Geo2dpoint (T[0], p[0], N[ids[0]]), Geo2dpoint (T[1], p[1], n[ids[1])); }default: Break; }    }returnGeo2dresult ();}
Spotlight Effect

To do a dispersion will be a bunch of parallel light, the implementation is very simple, limiting angle!

In the round sampling method, we make a judgment: when the light angle is not within the spotlight's active range, it returns to black.

Geo2dresult geo2dcircle::sample (vector2 ori, Vector2 dir)Const{Autov = ori-center;Autoa0 = squaremagnitude (v)-rsq;AutoDdotv = DotProduct (dir, v);//if (Ddotv <= 0){AutoDISCR = (DDOTV * ddotv)-A0;calculation in//square root        if(DISCR >= 0) {//non-negative equations have solutions, intersect established            //R (t) = O + t.d            AutoDistance =-ddotv-sqrtf (DISCR);//Derive t, that is, the distance from the camera's light to its intersection with the Circle            AutoDistance2 =-ddotv + sqrtf (DISCR);AutoPosition = ori + dir * distance;//Enter the linear equation to obtain the intersection position            AutoPosition2 = ori + dir * DISTANCE2;Autonormal = Normalize (Position-center);//Normal vector = end of Ray (ball to spot)-Globe coordinates            AutoNormal2 = Normalize (Position2-center);if(a0 > 0 && Angle &&!)            (a1.x * Dir.y < A1.Y * dir.x && a2.x * dir.y > A2.Y * dir.x)) {//Determine the order of the hour between three lines                returnGeo2dresult (); }returnGeo2dresult ((a0 <= 0 | | distance >= 0)? This: nullptr, A0 <= 0, Geo2dpoint (distance, position, normal), Geo2dpoint (Distance2, Positio        N2, Normal2)); }    }returnGeo2dresult ();//fail, disjoint}
Dispersion effect

Dispersion is actually different frequency of light in the medium of the refractive index is different, we simplify, according to RGB modified refractive index, such as: red light = The original refractive index, green = The original refractive index +0.1, and so on.

For a graph that does not explicitly modify the index of refraction (default 1.0), it does not have a dispersion check.

if(R.body->eta = = 1.0f)//non-refraction{//According to the previous refraction method, unchanged! }Else //Dispersion test{Const AutoETA = r.inside? R.body->eta: (1.0f/r.body->eta);Const Autok = 1.0f-eta * ETA * (1.0F-IDOTN * idotn);if(k >= 0.0f)//Can refract, not full reflection{Const AutoA = ETA * Idotn + sqrtf (k);Const AutoRefraction = ETA * d-a * normal;Const AutoCosi =-(DotProduct (d, Normal));Const AutoCost =-(DotProduct (refraction, normal));        REFL = Refl * (r.inside Fresnel (Cosi, cost, ETA, 1.0f): Fresnel (Cosi, cost, 1.0f, ETA)); Refl. Normalize ();//The following is differentColor par;//Ask for three dimensions of components andSum. Set (0.0f);//light of light is not included in the calculationPar. ADD (Trace5 (Pos-bias * Normal, refraction, depth + 1));//plus the Red component        Auton = par. Valid ()?        1:0; PAR.G *= ETAS;//etas=0.1 The red component, the green and blue components cut itPar.b *= ETAS; for(inti = 1; I < 3; ++i)//blue light and green component{//etad=0.1 refractive index: green = red +0.1 blue = Red +0.2            Const AutoETA0 = R.inside? (R.body->eta + ETAD * i): (1.0f/(R.body->eta + ETAD * i));Const AutoK0 = 1.0f-eta0 * ETA0 * (1.0F-IDOTN * idotn);if(k >= 0.0f)//Can refract, not full reflection{Const Autoa0 = eta0 * Idotn + sqrtf (k0);Const AutoRefraction0 = eta0 * d-a0 * normal;Autoc = Trace5 (Pos-bias * Normal, Refraction0, depth + 1);//Do refraction calculation                if(C.valid ()) {if(i = = 1) {C.R *= ETAS;//Cut two other color componentsC.B *= ETAS; }Else{C.R *= ETAS;                    C.G *= ETAS; } n++;//If this component is not black, it will be effective, plus one, originally to add the final value to do under the average, and now temporarily do not use it} par. ADD (c);//plus blue and green components}} sum. Add ((REFL. Negative (1.0f)) * par);//Plus three refractive components and}Else //non-refraction is full internal reflectionRefl. Set (1.0f);
Local scan

When the light source is very bright (rgb>10f), only 256 of the sampling can not have a good effect, using the following method:

StaticColor Sample5 (floatXfloatY) {color sum; for(Autoi = 0; i < N; i++) {Const AutoA = PI2 * (i +float(rand ())/Rand_max)/N;Const Autoc = Trace5 (Vector2 (x, y), Vector2 (COSF (a), Sinf (a));if(C.valid ()) {color par; for(Autoj = 0; J < NP; J + +) {//Further calculation                Const Autoa0 = PI2 * (i + (j +float(rand ())/Rand_max)/NP)/N;Const AutoC0 = Trace5 (Vector2 (x, y), Vector2 (COSF (A0), Sinf (a0))); Par.            ADD (C0); } sum.        ADD (PAR * (1.0F/NP)); }    }returnSum * (1.0f/n);}

When the first layer jitter sampling result is valid, the second layer jitter sampling is done, and the accuracy is higher.

The final result is 1080P, one-layer sampling = 512, two-tier sampling = 8, and a dual-core four-thread rendering takes approximately half an hour.

Further more true, I only want to add some more refraction test, the original RGB component expanded to seven color, conversion with the RGB and HSL, the problem is that the seven color components are not orthogonal, how to integrate them is still to be studied.

The graph is set to the RGB component's index of refraction is incremented to 0.1, that is 1.4~1.6, the color cut is 0.1. In addition, the light of the light source is not a strict parallel light, better effect also need to constantly adjust the parameters.

Backed up by https://zhuanlan.zhihu.com/p/32486185.

Painting light in C + + (c)--dispersion

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.