2016-04-17 7 views
1

Ich versuche, meiner Raytracing-Grafik-Engine Rasterisierungsunterstützung hinzuzufügen. Ich habe jedoch erwartet, dass ich unabhängig von der Vorgehensweise das gleiche Bild erhalte (natürlich ohne Schattierung).Wurfstrahl gegen projizierende Eckpunkte?

Stattdessen bekomme ich das Testmodell in zwei verschiedenen Größen gerendert, also nehme ich an, dass es etwas mit der Art zu tun hat, wie ich Strahlen für Raytracing oder die Art, wie ich die Projektionsmatrix für die Rasterung baue .

Hier ist mein „Kamera“ Konstruktor (zuständig für die Projektionsmatrix des Gebäudes):

Camera::Camera(float fLength, float fov, float targetRatio, float zNear, float zFar) 
{ 
    focalLength = fLength; 
    fieldOfView = fov; 
    aspectRatio = targetRatio; 
    scale = tan(fieldOfView * 0.5 * DEG_TO_RAD); 

    viewMatrix = Matrix4<float>(); 

    projectionMatrix = Matrix4<float>(); 

    float distance = zFar - zNear; 

    projectionMatrix.xx = scale/aspectRatio; 
    projectionMatrix.yy = scale; 
    projectionMatrix.zz = -(zFar + zNear)/distance; 
    projectionMatrix.zw = -1.0f; 
    projectionMatrix.wz = -2.0f * zNear * zFar/distance; 
    projectionMatrix.ww = 0.0; 

    //aperture = tan(fieldOfView/2 * DEG_TO_RAD) * focalLength * 2; 
    //fieldOfView = atan((aperture/2)/focalLength) * 2 * RAD_TO_DEG; 
} 

Dies ist, wie I-Strahlen geworfen basierend auf Bildpuffer Abmessungen und die aktuellen Pixelkoordinaten (I die Richtung berechnen und erhalten, die Kameraposition aus seiner letzten Matrixreihe):

Ray Camera::castRay(unsigned int width, unsigned int height, unsigned int x, unsigned int y) 
{ 
    float dirX = (2 * (x + 0.5)/(float)width - 1) * aspectRatio * scale; 
    float dirY = (1 - 2 * (y + 0.5)/(float)height) * scale; 

    Vector3<float> dir = (Vector3<float>(dirX, dirY, -1.0) * viewMatrix).normalize(); 

    return Ray(Vector3<float>(viewMatrix.wx, viewMatrix.wy, viewMatrix.wz), dir); 
} 

Auf der anderen Seite, das ist, wie I raster Vertices den Rasterungs Ansatz:

Vector4<float> vertexInRasterSpace; 
    Vector4<float> vertexInCameraSpace; 

    vertexInCameraSpace = currentVertex * camera.viewMatrix; 
    vertexInRasterSpace = vertexInCameraSpace * camera.projectionMatrix; 

    vertexInRasterSpace.x = std::min(width - 1, (int)((vertexInRasterSpace.x + 1) * 0.5 * width)); 
    vertexInRasterSpace.y = std::min(height - 1, (int)((1 - (vertexInRasterSpace.y + 1) * 0.5) * height)); 
    vertexInRasterSpace.z = -vertexInCameraSpace.z; 

Schließlich werden die Ergebnisse erhalten:

-Ray Verfolgung ->Ray tracing picture

-Rasterization ->Rasterization picture

Nadeln zu sagen, beide Bilder die gleiche Model-View-Matrix verwenden. War ich in meiner ursprünglichen Annahme falsch, dass ich das gleiche (Größen-) Bild bekommen würde?

~ Sky

Antwort

1

Hängt davon ab, was die Rasterung Algorithmus tut (Sie sind die Eckpunkte zu einer 3D-Grafik-API Fütterung oder Ihre eigene Rasterung tun?), Aber meine erst Verdächtigen sind:

Nach Multiplikation mit die Perspektive-Matrix, aber vor der Rasterung, müssen Sie die Perspektive dividieren: das heißt, die X-, Y- und Z-Komponenten Ihres Vektors durch die W-Komponente zu teilen. Das scheint zu fehlen.

Wenn Sie den Ausgang Eckpunkte zu einem 3D-Grafik-API einspeisen, dann für die Breite und Höhe des Fensters Buchhaltung kann nicht sein, was Sie wollen (das ist Teil des Ansichtsfensters verwandelt der Hardware Rendering-Pipeline).

+0

Vielen Dank für Ihre Antwort. Ich mache Software Rasterizarion. Ich hatte den Eindruck, dass die Teilung der Perspektive implizit ist, wenn man den Vertex mit der Projektionsmatrix multipliziert, aber nachdem ich deine Antwort gelesen habe, habe ich versucht, in Z zu übersetzen, und es hatte keinen Effekt! Ich werde mehr graben, weil das das Problem sein könnte. – SkyBladeCloud

+0

@SkyBladeCloud Ja. Die Matrixmultiplikationsoperation kann keine Division tatsächlich durchführen (das Beste, was sie tun kann, ist die Multiplikation mit 1/Konstante). Eine perspektivische Projektion in eine Matrix zu setzen, kann daher als ein cleverer Trick betrachtet werden: Ordne alles so an, dass der Wert, der im Nenner der Division sein soll, in der W-Komponente endet, und führe die Division am Ende manuell durch. (In Wirklichkeit machst du alles in einem 4D homogenen Raum, und die perspektivische Teilung am Ende projiziert zurück in 3D euklidischen Raum.) –

+0

Nun, ich muss es dir übergeben, Kumpel, du hast Recht auf alles. Es gelang mir schließlich, die gleichen Transformationen sowohl bei der Raytracing- als auch bei der Rasterisierung zu erzielen. Die fehlende perspektivische Trennung war in der Tat das Problem. RayTracing -> http://i.imgur.com/tHLMbvg.png. Rasterisierung -> http://i.imgur.com/dMmPvzz.png. Nochmals vielen Dank: ~ Himmel – SkyBladeCloud