私はC++を使ってレイトレーサに取り組んでいますが、これまでは拡散、鏡面、周囲のコンポーネントに基づいて照明モデルを計算できました。私は私のシーンに影を追加しようとしたとき、私の問題が現れた:シーンは本当にめちゃくちゃ取得:レイトレーサの影を計算するときに予期しない結果が発生しました
次のように私のコードが分割されています。
- 私は、基本クラスを持っている「シーンオブジェクト」これは、計算されたt値、ヒットポイント、およびオブジェクトの法線の引数を返すだけでなく、光線(原点と方向によって定義される)をとりブール値を出力する仮想メソッドintersect()を持ちます。
- "Material"クラスには、specularとdiffuseの色(ベクトル)とphong指数(int)の値が含まれています。
- 私は、上記のSceneObject:plane、triangle、sphereクラスの3つの派生クラスを持っています。それぞれは、基本クラスで定義された交差の独自のバージョンです。
- 私は、オブジェクトの法線、ヒットポイント、光源とオブジェクトの材質を使って、与えられたピクセルの出力色を計算する関数を持っています。
- レンダリングするすべてのオブジェクトはベクトルに格納されます。 ここ
私の派生クラス、トライアングルの一つである:
class Triangle: public SceneObject{
public:
Triangle (vec3 a, vec3 b, vec3 c, Material mat){
name = "Triangle";
p0 = a;
p1 = b;
p2 = c;
objectMaterial = mat;
normal = normalize(cross(p0-p1, p0-p2));
}
//Möller-Trumbore algorithm
bool intersect(Ray aRay, float &t, vec3 &hitPoint, vec3 &n){//we will use ray-plane intersection and barycentric coords:
bool returnValue = false;
//first we need to get a t of intersection between the passed ray and the triangle
vec3 v0v1 = p1-p0;
vec3 v0v2 = p2-p0;
vec3 pvec = cross(aRay.getDirection(), v0v2);
float det = dot(v0v1, pvec);
if (det >= 1e-6){ // Only draw if not backfacing
float invDet = 1/det;
float u = dot(-p0, pvec) * invDet;
// No intersection if u < 0 or u > 1
if (u >=0 && u <= 1) {
vec3 qvec = cross(-p0, v0v1);
float v = dot(aRay.getDirection(), qvec) * invDet;
// No intersection if v < 0 or u + v > 1
if (v >=0 && (u + v) <= 1){
t = dot(v0v2, qvec) * invDet;
returnValue = true;
hitPoint = aRay.getOrigin() + (t*aRay.getDirection());
n = normal;
//calculated_Out_Colour = calculateOutputColour(normal, aRay, lightSource, objectMaterial, t, hitPoint);
}
}
}
return returnValue;
}
private:
vec3 p0;
vec3 p1;
vec3 p2;
vec3 normal;
};
そして、これは私が私の窓の画素ごとにすべての私の光線を生成する私のメインループであり、そして色を決定し、現在の場合ポジションが日陰であるかどうか:
for(int i=0;i<imageBuffer.Height();i++){
for(int j=0;j<imageBuffer.Width();j++){
float currentX = ((float)i-256);
float currentY = ((float)j-256);
//cout << currentX << ", " << currentY << ", " << currentZ << endl;
//make a ray for this pixel (i,j)
glm::vec3 rayDirection = glm::normalize(glm::vec3(currentX, currentY, -d));
//make a ray for this pixel (i,j)
Ray currentRay(vec3(0,0,0), rayDirection);
vec3 hitPoint;
vec3 normalAtHit;
float tnear = 999; // closest intersection, set to INFINITY to start with
SceneObject* object = NULL;
for (int k = 0; k < objects.size(); k++) {
float t; // intersection to the current object if any
if (objects[k]->intersect(currentRay, t, hitPoint, normalAtHit) && t < tnear) {
object = objects[k].get();
tnear = t;
vec3 shadowRayDirection = normalize(light1.getLightOrigin()-hitPoint);
Ray shadowRay(hitPoint+vec3(0.03, 0.03,0.03), shadowRayDirection);
float shadowT;
vec3 shadowHitPoint;
vec3 shadowN;
for (int m = 0; m < objects.size(); ++m) {
if (objects[m]->intersect(shadowRay, shadowT, shadowHitPoint, shadowN)) {
imageBuffer.SetPixel(i, j, ambientColour*ambientIntensity);
break;
} else {
imageBuffer.SetPixel(i, j, calculateOutputColour(normalAtHit, currentRay, light1, objects[k]->getMaterial(), hitPoint));
}
}
}
}
}
}
私は正直なところここにいるが、なぜこれが起こっているのか分からない。私はhereのアルゴリズムを使ってみましたが、画像に示されているのと同じ結果が得られます。私はこの事をデバッグしようとする際に任意のヘルプをお願い
:私はループを取ると影を確認する場合は参考のために、私のシーンはこのようになります。ありがとう。
あなたのシャドウレイについては、レイの起源に対して 'hitPoint + 0.03 * shadowRayDirection'または' hitPoint + 0.03 * normalAtHit'を使用する必要があります(どちらも動作可能です;どちらの方法でも引数を取ることができます)。 – Cornstalks
を float shadowOffset = 0に修正しました。05; Ray shadowRay(hitPoint + shadowOffset * shadowRayDirection、shadowRayDirection); しかし、それは同じ結果を生成します:-( – jjcastil
't'を計算する方法は間違っているかもしれませんが(正しいかもしれません;私は分かりません)私は光線トレーサで異なっています:' vec3 n = cross (v0v1、v0v2); float num = dot(n、p0-aRay.getOrigin()); float den = dot(n、aRay.getDirection()); t = num/den; ' = 0'で除算する)あなたは 't'値が正しいかどうかをテストするために行うことができる深さイメージを出力するので、計算された交差点があなたのものと一致するかどうかを見ることができます期待している。 – Cornstalks