Software Renderer



  • Hier gibts auch ein Tut:
    http://www.devmaster.net/articles/software-rendering/part1.php

    Allerdings verzichten die auf einen Z-Buffer, was nicht so toll ist, und rendern Objekte von hinten nach vorne.

    Bzw. bei einfachen Objekten wie einem Würfel braucht man keinen z-Buffer (allgemeiner: bei Objekten die konvex sind ist kein z-Buffer nötig), weil die Flächen, die nicht gezeichnet werden sollen eh gecullt werden - aber das nur am Rande - das fällt dir dann auf, wenn du deinen Z-Buffer mit einem Würfel testest 😉 hehe



  • BTW: http://tech.groups.yahoo.com/group/Software-Rendering/

    jaja... das Thema fasziniert mich halt 😉



  • Vertexwahn schrieb:

    Hab aufgehört daran zu arbeiten, weil mir dann klar war wie Gourad Shading, Phong Shading, TextureMapping usw. funktioniert bzw. die Fixed Pipeline

    Das is es mir auch alles - und ich hab nie nen Software Rasterizer geschrieben. 😉
    Also wenn man "nur" die Pipeline und Techniken verstehen will, bringt einem IMHO das Schreiben eines Software Rasterizers garnix. Man hält sich nur zulange mit für das Gesamtverständnis unwichtigen, frickeligen Details auf. Wenn man es wegen der Sache selber tun will, ok.



  • Computergrafik | ISBN: 3826609085

    Das Buch kann ich dir nur empfehlen. Das letzte mal als ich es einem Freund empfohlen habe, war es gerade im Ausverkauf bei Amazon für 10€ zu haben, also ein Preis den man nicht bereuen wird.


  • Mod

    Vertexwahn schrieb:

    Hab aufgehört daran zu arbeiten, weil mir dann klar war wie Gourad Shading, Phong Shading, TextureMapping usw. funktioniert bzw. die Fixed Pipeline

    [/quote]
    du weisst doch nun selbst, dass die theorie zu wissen nie die erfahrung der praxis ersetzen kann 😉

    btw scheint mir dein Hodgman-Sutherland nur 2d zu sein 😉

    ich schreib auch zwei bis drei rasterizer pro jahr :), macht soviel spass wie raytracer :).

    ist dein rasterizer immer wasserdicht und subpixel/texel genau? 😃



  • rapso schrieb:

    btw scheint mir dein Hodgman-Sutherland nur 2d zu sein 😉

    Clipping findet ja auch im Zweidimensionalen statt, nach der Projektion.


  • Mod

    TomasRiker schrieb:

    rapso schrieb:

    btw scheint mir dein Hodgman-Sutherland nur 2d zu sein 😉

    Clipping findet ja auch im Zweidimensionalen statt, nach der Projektion.

    nein, clipping findet im post-projective-space vor der projektion (also vorm divide) statt, ansonsten haettest du z waerte (edit: bzw w) die 0 oder <0 sind (jetzt auf einen positiven z-buffer bezogen), was zu extremen fehlern fuehren wuerde.



  • OK, stimmt, kommt auch drauf an was man unter der Projektion versteht.
    "Nach der Transformation durch die Projektionsmatrix" (im Clip Space ;))

    Das sind natürlich dann noch dreidimensionale Koordinaten.


  • Mod

    TomasRiker schrieb:

    OK, stimmt, kommt auch drauf an was man unter der Projektion versteht.
    "Nach der Transformation durch die Projektionsmatrix" (im Clip Space ;))

    egal was man darunter versteht, es bleibt clipping mit 3d-coordinaten, er hat in seinem paper leider nur 2d beschrieben.



  • Mein Weg vom Vertex zur Fensterkoordinate sieht nun so aus:

    void Renderer::TransformVertex(int* dst_x, int* dst_y, Vector4* src_vertex) {
    
    	// http://www.opengl.org/resources/faq/technical/transformations.htm
    
    	// Get clip coords
    	Vector4 eyeCoords = (*src_vertex) * this->worldMatrix;
    	Vector4 clipCoords = eyeCoords * this->projectionMatrix;
    
    	// Get normalized device coordinates
    	clipCoords.x /= clipCoords.w;
    	clipCoords.y /= clipCoords.w;
    	clipCoords.z /= clipCoords.w;
    
    	// Get window coordinates
    	*dst_x = (int)((clipCoords.x + 1.0f) * (this->viewportWidth / 2.0f) + this->viewportLeft);
    	*dst_y = (int)((clipCoords.y + 1.0f) * (this->viewportHeight / 2.0f) + this->viewportBottom);
    }
    

    Stimmt das vom Prinzip her? Weil ich glaube, dass meine Ausgabe falsch ist. Aus den Vertizes (-100 | 0 | 20) und (100 | 0 | 20) werden die Bildschirmkoordinaten (320 | 240) und (319 | 240). Der rechtere der beiden Vertizes ist am Ende der linke Pixel, da stimmt ja irgendwas nich...

    Wenn ich bei einem Vertex die y-Koordinate kleiner mache, ist die y-Koordinate des Pixels größer. Also auch vertauscht... Bzw, 0|0 ist normalerweise die linkere untere Ecke, oder? Dann liegt hier das Problem mit den y-Werten, weil 0|0 bei mir oben links liegt, aber das ist ja schnell gefixt...

    Meine Projektionsmatrix erstelle ich wie D3DXMatrixPerspectiveFovLH:

    void Renderer::SetPerspectiveProjection(float fovY, float aspect, float zNear, float zFar) {
    
    	float yScale = atan(fovY / 2.0f);
    	float xScale = yScale / aspect;
    
    	this->projectionMatrix.Zero();
    
    	this->projectionMatrix._11 = xScale;
    	this->projectionMatrix._22 = yScale;
    	this->projectionMatrix._33 = zFar / (zFar - zNear);
    	this->projectionMatrix._34 = 1.0f;
    	this->projectionMatrix._43 = -zNear * zFar / (zFar - zNear);
    }
    

    Meine Initialisierung sieht so aus:

    renderer.SetViewport(0, 0, 640, 480);
    	renderer.SetPerspectiveProjection(1.3f, (float)640 / 480, 0.1f, 100.0f);
    

    Vielen Dank,
    Tim



  • ... oben geändert


  • Mod

    xindon schrieb:

    // Get window coordinates
    	*dst_x = (int)((clipCoords.x + 1.0f) * (this->viewportWidth / 2.0f) + this->viewportLeft);
    	*dst_y = (int)((clipCoords.y + 1.0f) * (this->viewportHeight / 2.0f) + this->viewportBottom);
    }
    

    das glaub ich nicht Tim 😉
    *0.5+0.5f, dann sind die 0 bis 1 und dann * widht bzw height
    dein + * + kann ich nicht so recht nachvollziehen

    greets
    rapso



  • Ich hab das vom DGL Wiki: http://wiki.delphigl.com/index.php/GlViewport

    edit: Habs geändert, kommt exakt das selbe raus 🙂 Wenn dus ausmultiplizierst, siehstes 😉 Es ist letztendlich das selbe.

    Ich fass meine Fragen am besten nochmal zusammen 🙂 ... :

    1. Stimmt der Weg vom Vertex zum Pixel soweit (TransformVertex Methode)

    2. Ist der Bildschirmursprung unten links oder oben links?

    3. Setzen der Projektionsmatrix korrekt?

    Vielen Dank für Antworten 🙂





  • Hier mal mein Softwarerenderer aber in einer anderen Sprache:

    ; - Constants / Globals ------------------------------------
    ; Matrices
    Const SR_MODELVIEW  = 1
    Const SR_PROJECTION = 2
    
    ; Depthrange Far / Near
    Global gDepthRange#[1]
    
    ; Viewport X, Y, Width, Height
    Global gViewport[3]
    
    ; Matrices
    Global gModelview.TMatrix
    Global gProjection.TMatrix
    Global gMatrixMode
    Global gActMatrix.TMatrix
    
    ; Vertexpipeline
    Global gObject.TVector
    Global gEye.TVector
    Global gClip.TVector
    Global gDevice.TVector
    Global gWindow.TVector
    
    ; Temp
    Global gTmpVector.TVector
    Global gTmpMatrix.TMatrix
    Global gTmpMatrix2.TMatrix
    ; ----------------------------------------------------------
    
    ; - Functions ----------------------------------------------
    Function srInit()
    	gDepthRange[0] = 0.0
    	gDepthRange[1] = 1.0
    
    	gViewport[0] = 0
    	gViewport[1] = 0
    	gViewport[2] = GraphicsWidth()
    	gViewport[3] = GraphicsHeight()
    
    	gModelview  = New TMatrix
    	gProjection = New TMatrix
    	gMatrixMode = SR_MODELVIEW
    	gActMatrix  = gModelview
    
    	gObject = New TVector
    	gEye    = New TVector
    	gClip   = New TVector
    	gDevice = New TVector
    	gWindow = New TVector
    
    	gTmpVector  = New TVector
    	gTmpMatrix  = New TMatrix
    	gTmpMatrix2 = New TMatrix
    End Function
    
    Function srDestroy()
    	Delete gModelview
    	Delete gProjection
    	Delete gActMatrix
    
    	Delete gObject
    	Delete gEye
    	Delete gClip
    	Delete gDevice
    	Delete gWindow
    
    	Delete gTmpVector
    	Delete gTmpMatrix
    	Delete gTmpMatrix2
    End Function
    
    Function srDepthRange(Near#, Far#)
    	If Near < 0.0 Then Near = 0.0
    	If Near > 1.0 Then Near = 1.0
    	gDepthRange[0] = Near
    
    	If Far < 0.0 Then Far = 0.0
    	If Far > 1.0 Then Far = 1.0
    	gDepthRange[1] = Far
    End Function
    
    Function srViewport(X, Y, Width, Height)
    	gViewport[0] = X
    	gViewport[1] = X
    	gViewport[2] = Width
    	gViewport[3] = Height
    End Function
    
    Function srMatrixMode(Mode)
    	Select Mode
    		Case SR_MODELVIEW
    			gActMatrix = gModelview
    
    		Case SR_PROJECTION
    			gActMatrix = gProjection
    
    		Default
    			RuntimeError("Matrix mode does not exist")
    	End Select
    
    	gMatrixMode = Mode
    End Function
    
    Function srLoadIdentity()
    	MatrixIdentity(gActMatrix)
    End Function
    
    Function srRotate(Angle#, X#, Y#, Z#)
    	MatrixRotate(gTmpMatrix2, Angle, X, Y, Z)
    	MatrixMatrixMultiply(gTmpMatrix2, gActMatrix, gActMatrix)
    End Function
    
    Function srTranslate(X#, Y#, Z#)
    	MatrixTranslate(gTmpMatrix2, X, Y, Z)
    	MatrixMatrixMultiply(gTmpMatrix2, gActMatrix, gActMatrix)
    End Function
    
    Function srScale(X#, Y#, Z#)
    	MatrixScale(gTmpMatrix2, X, Y, Z)
    	MatrixMatrixMultiply(gTmpMatrix2, gActMatrix, gActMatrix)
    End Function
    
    Function srPerspective(Zoom#, Aspect#, Far#, Near#)
    	MatrixPerspective(gTmpMatrix2, Zoom, Aspect, Far, Near)
    	MatrixMatrixMultiply(gTmpMatrix2, gActMatrix, gActMatrix)
    End Function
    
    Function srDebugMatrix()
    	MatrixDebug(gActMatrix)
    End Function
    
    Function srVertex(X#, Y#, Z#, W#=1.0)
    	gObject\X = X
    	gObject\Y = Y
    	gObject\Z = Z
    	gObject\W = W
    	srVertexProcessor()
    End Function
    
    Function srDrawVertex()
    	WritePixel(gWindow\X, gWindow\Y, $FFFFFF)
    End Function
    
    Function srVertexProcessor()
    	Local OX, OY
    
    	; Eye = M x Object
    	MatrixVectorMultiply(gModelview, gObject, gEye)
    
    	; Clip = P x Object
    	MatrixVectorMultiply(gProjection, gEye, gClip)
    
    	; Normalized Device Coords
    	gDevice\X = gClip\X/gClip\W
    	gDevice\Y = gClip\Y/gClip\W
    	gDevice\Z = gClip\Z/gClip\W
    
    	; Viewport transformation
    	OX = gViewport[2]/2 + gViewport[0]
    	OY = gViewport[3]/2 + gViewport[1]
    
    	gWindow\X = (gViewport[2]/2.0)*gDevice\X + OX
    	gWindow\Y = (gViewport[3]/2.0)*-gDevice\Y + OY
    	gWindow\Z = ((gDepthRange[1] - gDepthRange[0])/2.0)*gDevice\Z + (gDepthRange[0] + gDepthRange[1])/2.0
    End Function
    ; ----------------------------------------------------------
    
    ; - Math ---------------------------------------------------
    Type TVector
    	Field X#
    	Field Y#
    	Field Z#
    	Field W#
    End Type
    
    Type TMatrix
    	Field AA#, AB#, AC#, AD#
    	Field BA#, BB#, BC#, BD#
    	Field CA#, CB#, CC#, CD#
    	Field DA#, DB#, DC#, DD#
    End Type
    
    Function MatrixIdentity(M.TMatrix)
    	M\AA = 1.0 : M\AB = 0.0 : M\AC = 0.0  : M\AD = 0.0
    	M\BA = 0.0 : M\BB = 1.0 : M\BC = 0.0  : M\BD = 0.0
    	M\CA = 0.0 : M\CB = 0.0 : M\CC = 1.0  : M\CD = 0.0
    	M\DA = 0.0 : M\DB = 0.0 : M\DC = 0.0  : M\DD = 1.0
    End Function
    
    Function MatrixRotate(M.TMatrix, Angle#, X#, Y#, Z#)
    	Local C#, S#, RLength#
    
    	C = Cos(Angle)
    	S = Sin(Angle)
    
    	; Normalize Vector
    	RLength = 1.0/Sqr(X*X + Y*Y + Z*Z)
    	X = X*RLength
    	Y = Y*RLength
    	Z = Z*RLength
    
    	M\AA = X*X*(1.0 - C) + C
    	M\AB = X*Y*(1.0 - C) - Z*S
    	M\AC = X*Z*(1.0 - C) + Y*S
    	M\AD = 0.0
    
    	M\BA = Y*X*(1.0 - C) + Z*S
    	M\BB = Y*Y*(1 - C) + C
    	M\BC = Y*Z*(1.0 - C) - X*S
    	M\BD = 0.0
    
    	M\CA = X*Z*(1.0 - C) - Y*S
    	M\CB = Y*Z*(1.0 - C) + X*S
    	M\CC = Z*Z*(1.0 - C) + C
    	M\CD = 0.0
    
    	M\DA = 0.0
    	M\DB = 0.0
    	M\DC = 0.0
    	M\DD = 1.0
    End Function
    
    Function MatrixTranslate(M.TMatrix, X#, Y#, Z#)
    	M\AA = 1.0 : M\AB = 0.0 : M\AC = 0.0  : M\AD = X
    	M\BA = 0.0 : M\BB = 1.0 : M\BC = 0.0  : M\BD = Y
    	M\CA = 0.0 : M\CB = 0.0 : M\CC = 1.0  : M\CD = Z
    	M\DA = 0.0 : M\DB = 0.0 : M\DC = 0.0  : M\DD = 1.0
    End Function
    
    Function MatrixScale(M.TMatrix, X#, Y#, Z#)
    	M\AA = X   : M\AB = 0.0 : M\AC = 0.0  : M\AD = 0.0
    	M\BA = 0.0 : M\BB = Y   : M\BC = 0.0  : M\BD = 0.0
    	M\CA = 0.0 : M\CB = 0.0 : M\CC = Z    : M\CD = 0.0
    	M\DA = 0.0 : M\DB = 0.0 : M\DC = 0.0  : M\DD = 1.0
    End Function
    
    Function MatrixPerspective(M.TMatrix, Zoom#, Aspect#, Near#, Far#)
    	M\AA = Zoom/Aspect : M\AB = 0.0  : M\AC = 0.0                       : M\AD = 0.0
    	M\BA = 0.0         : M\BB = Zoom : M\BC = 0.0                       : M\BD = 0.0
    	M\CA = 0.0         : M\CB = 0.0  : M\CC = (Far + Near)/(Near - Far) : M\CD = (2.0*Far*Near) / (Near - Far)
    	M\DA = 0.0         : M\DB = 0.0  : M\DC = -1.0                      : M\DD = 0.0
    End Function
    
    Function MatrixDebug(M.TMatrix)
    	DebugLog M\AA + " " + M\AB + " " + M\AC + " " + M\AD
    	DebugLog M\BA + " " + M\BB + " " + M\BC + " " + M\BD
    	DebugLog M\CA + " " + M\CB + " " + M\CC + " " + M\CD
    	DebugLog M\DA + " " + M\DB + " " + M\DC + " " + M\DD
    End Function
    
    Function MatrixMatrixMultiply(X.TMatrix, Y.TMatrix, R.TMatrix)
    	gTmpMatrix\AA = X\AA*Y\AA + X\AB*Y\BA + X\AC*Y\CA + X\AD*Y\DA
    	gTmpMatrix\AB = X\AA*Y\AB + X\AB*Y\BB + X\AC*Y\CB + X\AD*Y\DB
    	gTmpMatrix\AC = X\AA*Y\AC + X\AB*Y\BC + X\AC*Y\CC + X\AD*Y\DC
    	gTmpMatrix\AD = X\AA*Y\AD + X\AB*Y\BD + X\AC*Y\CD + X\AD*Y\DD
    
    	gTmpMatrix\BA = X\BA*Y\AA + X\BB*Y\BA + X\BC*Y\CA + X\BD*Y\DA
    	gTmpMatrix\BB = X\BA*Y\AB + X\BB*Y\BB + X\BC*Y\CB + X\BD*Y\DB
    	gTmpMatrix\BC = X\BA*Y\AC + X\BB*Y\BC + X\BC*Y\CC + X\BD*Y\DC
    	gTmpMatrix\BD = X\BA*Y\AD + X\BB*Y\BD + X\BC*Y\CD + X\BD*Y\DD
    
    	gTmpMatrix\CA = X\CA*Y\AA + X\CB*Y\BA + X\CC*Y\CA + X\CD*Y\DA
    	gTmpMatrix\CB = X\CA*Y\AB + X\CB*Y\BB + X\CC*Y\CB + X\CD*Y\DB
    	gTmpMatrix\CC = X\CA*Y\AC + X\CB*Y\BC + X\CC*Y\CC + X\CD*Y\DC
    	gTmpMatrix\CD = X\CA*Y\AD + X\CB*Y\BD + X\CC*Y\CD + X\CD*Y\DD
    
    	gTmpMatrix\DA = X\DA*Y\AA + X\DB*Y\BA + X\DC*Y\CA + X\DD*Y\DA
    	gTmpMatrix\DB = X\DA*Y\AB + X\DB*Y\BB + X\DC*Y\CB + X\DD*Y\DB
    	gTmpMatrix\DC = X\DA*Y\AC + X\DB*Y\BC + X\DC*Y\CC + X\DD*Y\DC
    	gTmpMatrix\DD = X\DA*Y\AD + X\DB*Y\BD + X\DC*Y\CD + X\DD*Y\DD
    
    	R\AA = gTmpMatrix\AA : R\AB = gTmpMatrix\AB : R\AC = gTmpMatrix\AC : R\AD = gTmpMatrix\AD
    	R\BA = gTmpMatrix\BA : R\BB = gTmpMatrix\BB : R\BC = gTmpMatrix\BC : R\BD = gTmpMatrix\BD
    	R\CA = gTmpMatrix\CA : R\CB = gTmpMatrix\CB : R\CC = gTmpMatrix\CC : R\CD = gTmpMatrix\CD
    	R\DA = gTmpMatrix\DA : R\DB = gTmpMatrix\DB : R\DC = gTmpMatrix\DC : R\DD = gTmpMatrix\DD
    End Function
    
    Function MatrixVectorMultiply(A.TMatrix, B.TVector, R.TVector)
    	gTmpVector\X = A\AA*B\X + A\AB*B\Y + A\AC*B\Z + A\AD*B\W
    	gTmpVector\Y = A\BA*B\X + A\BB*B\Y + A\BC*B\Z + A\BD*B\W
    	gTmpVector\Z = A\CA*B\X + A\CB*B\Y + A\CC*B\Z + A\CD*B\W
    	gTmpVector\W = A\DA*B\X + A\DB*B\Y + A\DC*B\Z + A\DD*B\W
    
    	R\X = gTmpVector\X
    	R\Y = gTmpVector\Y
    	R\Z = gTmpVector\Z
    	R\W = gTmpVector\W
    End Function
    ; ----------------------------------------------------------
    
    ; - Example ------------------------------------------------
    Global Angle#, Z#
    Global Stream%, Count%, Index%
    
    Graphics 640, 480, 0, 2
    SetBuffer BackBuffer()
    
    Stream = ReadFile("test.3d")
    Count = ReadInt(Stream)
    
    Dim Vertices#(Count - 1, 2)
    For Index = 0 To Count - 1
    	Vertices(Index, 0) = ReadFloat(Stream)
    	Vertices(Index, 2) = ReadFloat(Stream) ; kleiner Hack, weil 3DS ein anderes koor. system hat
    	Vertices(Index, 1) = ReadFloat(Stream)
    Next
    
    CloseFile Stream
    
    srInit()
    
    srMatrixMode(SR_PROJECTION)
    srLoadIdentity()
    srPerspective(1.0, 640.0/480.0, 0.1, 100.0)
    srDepthRange(0.0, 1.0)
    
    srMatrixMode(SR_MODELVIEW)
    Z = -30.0
    While Not KeyDown(1)
    	Angle = Angle + 2.0
    
    	Cls()
    
    	If KeyDown(200) Then Z = Z - 0.5
    	If KeyDown(208) Then Z = Z + 0.5
    
    	srLoadIdentity()
    	srRotate(Angle, 0.0, 1.0, 0.0)
    	srTranslate(0.0, 0.0, Z)
    
    	For Index = 0 To Count - 1
    		srVertex(Vertices(Index, 0), Vertices(Index, 1), Vertices(Index, 2))
    		srDrawVertex()
    	Next
    
    	Flip(0)
    Wend
    
    End
    ; ----------------------------------------------------------
    

    Ist OpenGL nach empfunden. Kann nur GL_POINTS rendern, wenn man das so will. Mit Scanlineimplentierung sind dann auch schnell Texturemapping, Lighting usw. realisiert, aber keine Zeit dafür 😛 Ist sicher nicht gerade die ideale Sprache dafür, aber das habe ich mal für jemanden als Hilfestellung geschrieben.

    >>Screenshot<<

    mfg olli



  • Okay danke 🙂 Mein Aufbau ist eigentlich der selbe, also hab ich vielleicht irgendwo en kleinen Fehler bei der Matrix Multiplikation oder so, ich schaus mir nochmal an.

    Vielen Dank auf jeden Fall. Ich find' die Sprache nur irgendwie... seltsam 😛



  • Wenn du einen Software Renderer schreiben willst, wie wär's, wenn der auf Raytracing basiert? Wäre auf jeden Fall mal was anderes als gewöhnliche Rasterizer, und wird in Zukunft wahrscheinlich an Bedeutung gewinnen. 🙂


  • Mod

    groovemaster schrieb:

    Wenn du einen Software Renderer schreiben willst, wie wär's, wenn der auf Raytracing basiert? Wäre auf jeden Fall mal was anderes als gewöhnliche Rasterizer

    wieso? die meisten schreiben einen raytracer weil es so trivial ist damit anzufangen, ein guter software renderer ist dagegen sehr selten und komplex.

    und wird in Zukunft wahrscheinlich an Bedeutung gewinnen. 🙂

    glaub nicht jedem marketing 😉



  • rüdiger schrieb:

    Computergrafik | ISBN: 3826609085

    Das Buch kann ich dir nur empfehlen. Das letzte mal als ich es einem Freund empfohlen habe, war es gerade im Ausverkauf bei Amazon für 10€ zu haben, also ein Preis den man nicht bereuen wird.

    http://www.terrashop.info/82660908/artikel.php



  • Blue-Tiger schrieb:

    rüdiger schrieb:

    Computergrafik | ISBN: 3826609085

    Das Buch kann ich dir nur empfehlen. Das letzte mal als ich es einem Freund empfohlen habe, war es gerade im Ausverkauf bei Amazon für 10€ zu haben, also ein Preis den man nicht bereuen wird.

    http://www.terrashop.info/82660908/artikel.php

    Ich hab mir das Buch da schon vorn paar Wochen für die 4€ gekauft 😛


Anmelden zum Antworten