[OpenGL] Normals doen raar op heightmap

Pagina: 1
Acties:

  • phaas
  • Registratie: Augustus 2001
  • Laatst online: 23-01-2025
Hallo!

Ik ben bezig met het leren van OpenGL en was begonnen aan een leuk heightmap-probeersel.
Het wireframe zit er goed uit, bij de normals gaat het echter helemaal de mist in.
Afbeeldingslocatie: http://edukitty.org/~barry/rot_normals.png
Zoals je ziet, ziet het er ondanks de smooth-shading nogal brak en brokkerig uit.
De blauwe lijntjes zijn de berekende normals.

En hier de relevante code:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
glTranslatef( -heightMapWidth / 2, 0, -heightMapHeight / 2 );
        glLightfv( GL_LIGHT0, GL_POSITION, light0_pos );
        
        for( int y =0; y < heightMapHeight-1; ++y )
        {
            
            for( int x =0; x < heightMapWidth-1; ++x )
            {
                float height[4] = { 0, 0, 0, 0 };
                height[0] =heightMapData[heightMapWidth*y +x] / heightDiv;
                height[1] =heightMapData[heightMapWidth*(y+1) +x]/ heightDiv;
                height[2] =heightMapData[heightMapWidth*y +x+1]/ heightDiv;
                height[3] =heightMapData[heightMapWidth*(y+1) +x+1]/ heightDiv;
                
                float point1[3] = { x, height[0], y };
                float point2[3] = { x, height[1], y+1 };
                float point3[3] = { x+1, height[2], y };
                float point4[3] = { x+1, height[3], y+1 };
                float norm1[3] = { 0, 0, 0 };
                float norm2[3] = { 0, 0, 0 };
                
                calcNormal( point1, point2, point3, norm1 );
                calcNormal( point3, point2, point4, norm2 );
                
                
                glEnable( GL_LIGHTING );
                glBegin( GL_TRIANGLES );
                    glNormal3fv( norm1 );   
                    glVertex3fv( point1 );
                    glVertex3fv( point2 );
                    glVertex3fv( point3 );
                glEnd( );
                
                glBegin( GL_TRIANGLES );
                    glNormal3fv( norm2 );
                    glVertex3fv( point3 );
                    glVertex3fv( point2 );
                    glVertex3fv( point4 );
                glEnd( );
                
                
                float plane1[3][3] =
                    { { point1[0], point1[1], point1[2] },  
                    { point2[0], point2[1], point2[2] },
                    { point3[0], point3[1], point3[2] } };
                    
                float plane2[3][3] =
                    { { point3[0], point3[1], point3[2] },  
                    { point2[0], point2[1], point2[2] },
                    { point4[0], point4[1], point4[2] } };
                    
                float linePoint1[3];
                float linePoint2[3];
                
                glDisable( GL_LIGHTING );
                qglColor( blue );
                glBegin( GL_LINES );
                
                    lineNormal( plane1, norm1, linePoint1, linePoint2 );
                    glVertex3fv( linePoint1 );
                    glVertex3fv( linePoint2 );
                    
                    lineNormal( plane2, norm2, linePoint1, linePoint2 );
                    glVertex3fv( linePoint1 );
                    glVertex3fv( linePoint2 );
                    
                glEnd( );
            }
        }


Weet iemand wat ik fout doe? De berekende normals zien er toch goed uit?

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 04-05 14:55

Janoz

Moderator Devschuur®

!litemod

Die normals zien er inderdaad keurig uit. De kleur die de vlakken krijgen trouwens ook. De normaal geldt voor het hele vlak, dus het hele vlak krijgt dezelfde kleur. Het naastliggende vlak heeft een andere normaal en deze krijgt dus een andere kleur.

Wil je een mooi soepel kleurverloop, dan zul je gouraud shading moeten gebruiken. Hierbij worden de normalen niet per vlak, maar per vertex berekent. De normaal wordt dan over het vlak geinterpoleert tussen de drie normalen op de hoek.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • D4Skunk
  • Registratie: Juni 2003
  • Laatst online: 20-10-2025

D4Skunk

Kind of Blue

in plaats van 1 normal per plane/quad, moet je per vertex je normal definiëren.
Dit kan je benaderen door het gemiddelde te nemen van alle normals van de planes die die vertex gebruiken.

offtopic:
Dus net zoals janoz zegt, maar dan zonder dt-fouten :-p

[ Voor 17% gewijzigd door D4Skunk op 30-05-2005 19:04 . Reden: 2e... ]


  • phaas
  • Registratie: Augustus 2001
  • Laatst online: 23-01-2025
Oké, bedankt iedereen.
Ik heb er even (diep) over nagedacht en ben tot het volgende scenario gekomen:
Stap 1, terrein maken:
-> eerst het terrein genereren zoals het nu is, dus met plane-normals en losse triangles
-> dit geheel opslaan in een mesh-structuur
Stap 2, vertex-normals berekenen:
-> de mesh doorlopen en een lijst maken van alle identieke vertices (dus remove doubles)
-> in deze lijst per vertex de normals opslaan van alle planes waar de vertex deel van uitmaakt / aan grenst
-> per vertex de gemiddelde normal berekenen aan de hand van de eerder gemaakte lijst.
Stap 3, renderen met vertex-normals
-> Per gerenderde triangle elke vertex opzoeken in de lijst en zo de berekende normal op de vertex toepassen.

:*)
Heeft dit een kans van slagen, of zijn er simpelere wegen? Bij een terrain heb je natuurlijk een vast grid en weet je dus welke planes aan welke vertex grenzen. Maargoed, ik wilde het graag een beetje algemeen maken, das meteen een mooie oefening :)

  • D4Skunk
  • Registratie: Juni 2003
  • Laatst online: 20-10-2025

D4Skunk

Kind of Blue

phaas schreef op maandag 30 mei 2005 @ 22:18:
...

:*)
Heeft dit een kans van slagen, of zijn er simpelere wegen? Bij een terrain heb je natuurlijk een vast grid en weet je dus welke planes aan welke vertex grenzen. Maargoed, ik wilde het graag een beetje algemeen maken, das meteen een mooie oefening :)
Als je het niet te algemeen wilt maken, en je lightning blijft constant, kan je het veel eenvoudiger doen met een lightmap.

Wat je zeker zou kunnen doen is eens zoeken op flipcode.com/nehe.gamedev.net naar tutorials e.a.

  • EfBe
  • Registratie: Januari 2000
  • Niet online
phaas schreef op maandag 30 mei 2005 @ 22:18:
Oké, bedankt iedereen.
Ik heb er even (diep) over nagedacht en ben tot het volgende scenario gekomen:
Stap 1, terrein maken:
-> eerst het terrein genereren zoals het nu is, dus met plane-normals en losse triangles
-> dit geheel opslaan in een mesh-structuur
Stap 2, vertex-normals berekenen:
-> de mesh doorlopen en een lijst maken van alle identieke vertices (dus remove doubles)
-> in deze lijst per vertex de normals opslaan van alle planes waar de vertex deel van uitmaakt / aan grenst
-> per vertex de gemiddelde normal berekenen aan de hand van de eerder gemaakte lijst.
Stap 3, renderen met vertex-normals
-> Per gerenderde triangle elke vertex opzoeken in de lijst en zo de berekende normal op de vertex toepassen.

:*)
Heeft dit een kans van slagen, of zijn er simpelere wegen? Bij een terrain heb je natuurlijk een vast grid en weet je dus welke planes aan welke vertex grenzen. Maargoed, ik wilde het graag een beetje algemeen maken, das meteen een mooie oefening :)
Ja dat zou moeten werken denk ik.

Hier mijn normalize routine voor het berekenen van vertexnormals uit face normals. Het is nogal oude code en ik zag dat ik een smoothing angle gebruik, ik heb echter geen idee meer waarom, wellicht dat je er nog achter kan komen, zie maar ;)
(edit), weet het alweer, was om te bepalen of de normals in dezelfde smoothing group zitten. Deze code komt uit mn ASE (3dstudiomax) converter.

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// Now, walk all vertices. Per vertex, we'll calculate for each face this vertex is in, the vertexnormal,
// by averaging the facenormals of all the faces that are in the same smoothgroup. faces are in the same
// smoothgroup when the angle between the normals of these faces is < ANGLE_SMOOTH. We determine the angle
// with the dotproduct (which results in the cos(angle) * length A * length B. Since length of the normals
// is 1.0, we leave these out of it).
for(iVertexCnt=0;iVertexCnt<pTheModel->m_iAmVertices;iVertexCnt++)
{
    
    for(iFaceCnt=0;iFaceCnt<arrpiAmFacesPerVertex[iVertexCnt];iFaceCnt++)
    {
        // Store face normal as startvalue in the vTmpResult vector which will contain the
        // calculation result for this vertex-face combination
        vTmpResult[0]=pTheModel->m_pFaces[arrpiFacesPerVertex[iVertexCnt][iFaceCnt]].m_vFaceNormal[0];
        vTmpResult[1]=pTheModel->m_pFaces[arrpiFacesPerVertex[iVertexCnt][iFaceCnt]].m_vFaceNormal[1];
        vTmpResult[2]=pTheModel->m_pFaces[arrpiFacesPerVertex[iVertexCnt][iFaceCnt]].m_vFaceNormal[2];

        // Walk the complete facelist of this vertex again, and check whether the facenormal of
        // each face should be averaged with the vTmpResult. This will only be done when the angle
        // between the normal of the face iFaceCnt and the face iFaceCnt2 < ANGLE_SMOOTH, AND iFaceCnt != iFaceCnt2
        for(iFaceCnt2=0;iFaceCnt2<arrpiAmFacesPerVertex[iVertexCnt];iFaceCnt2++)
        {
            if(iFaceCnt==iFaceCnt2)
            {
                // the same, skip
                continue;
            }
            // Test if the angle between the facenormals is < ANGLE_SMOOTH
            dAngle=DotProductVect3(pTheModel->m_pFaces[arrpiFacesPerVertex[iVertexCnt][iFaceCnt]].m_vFaceNormal,
                        pTheModel->m_pFaces[arrpiFacesPerVertex[iVertexCnt][iFaceCnt2]].m_vFaceNormal);
            dAngle=(acos(dAngle)/ PI) * 180.0;
            // now test if this angle is smaller than fSmoothingAngle. more than 1 angle can result in the same
            // cosine value, but this doesn't matter since 2 normals who opposite eachother have the maximum angle, 180
            // degrees, and in that range, no double cosine values occure for the same angle.
            if(dAngle < fSmoothingAngle)
            {
                // this face (iFaceCnt2) is part of a smooth surface together with face (iFaceCnt).
                Vector3Add(vTmpResult, pTheModel->m_pFaces[arrpiFacesPerVertex[iVertexCnt][iFaceCnt2]].m_vFaceNormal,
                                vTmpResult);
            }
        }
        // make the vector again of length 1
        Vector3Normalize(vTmpResult);
        // store vTmpResult in the right VertexNormal slot for the vertex iVertexCnt. only 3 slots available, so
        // we do a dirty if then else thingy. If stored, move on with the next face!
        if(pTheModel->m_pFaces[arrpiFacesPerVertex[iVertexCnt][iFaceCnt]].m_iVertexIndices[0]==iVertexCnt)
        {
            pTheModel->m_pFaces[arrpiFacesPerVertex[iVertexCnt][iFaceCnt]].m_vVertexNormals[0][0]=vTmpResult[0];
            pTheModel->m_pFaces[arrpiFacesPerVertex[iVertexCnt][iFaceCnt]].m_vVertexNormals[0][1]=vTmpResult[1];
            pTheModel->m_pFaces[arrpiFacesPerVertex[iVertexCnt][iFaceCnt]].m_vVertexNormals[0][2]=vTmpResult[2];
            // continue with next face
            continue;
        }
        if(pTheModel->m_pFaces[arrpiFacesPerVertex[iVertexCnt][iFaceCnt]].m_iVertexIndices[1]==iVertexCnt)
        {
            pTheModel->m_pFaces[arrpiFacesPerVertex[iVertexCnt][iFaceCnt]].m_vVertexNormals[1][0]=vTmpResult[0];
            pTheModel->m_pFaces[arrpiFacesPerVertex[iVertexCnt][iFaceCnt]].m_vVertexNormals[1][1]=vTmpResult[1];
            pTheModel->m_pFaces[arrpiFacesPerVertex[iVertexCnt][iFaceCnt]].m_vVertexNormals[1][2]=vTmpResult[2];
            // continue with next face
            continue;
        }
        if(pTheModel->m_pFaces[arrpiFacesPerVertex[iVertexCnt][iFaceCnt]].m_iVertexIndices[2]==iVertexCnt)
        {
            pTheModel->m_pFaces[arrpiFacesPerVertex[iVertexCnt][iFaceCnt]].m_vVertexNormals[2][0]=vTmpResult[0];
            pTheModel->m_pFaces[arrpiFacesPerVertex[iVertexCnt][iFaceCnt]].m_vVertexNormals[2][1]=vTmpResult[1];
            pTheModel->m_pFaces[arrpiFacesPerVertex[iVertexCnt][iFaceCnt]].m_vVertexNormals[2][2]=vTmpResult[2];
        }
    }
}

[ Voor 3% gewijzigd door EfBe op 31-05-2005 13:22 ]

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 05-05 18:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

phaas schreef op maandag 30 mei 2005 @ 22:18:
Oké, bedankt iedereen.
Ik heb er even (diep) over nagedacht en ben tot het volgende scenario gekomen:
Stap 1, terrein maken:
-> eerst het terrein genereren zoals het nu is, dus met plane-normals en losse triangles
-> dit geheel opslaan in een mesh-structuur
Waarom niet gewoon een 2d grid maken van vertices, en vandaaruit de triangles genereren? Vertex normals berekenen is vrij simpel, voor de lengterichting zijn ze afhankelijk van het verschil in hoogte tussen de vorige en de volgende vertex in die richting. Hetzelfde geldt voor de breedterichting. Ik had hier ooit eens een simpel stukje code gepost, ik zal er eens naar zoeken. Het voordeel hiervan is dat je direct connectiviteit kunt afleiden zonder dat deze daadwerkelijk in de datastructuur is opgenomen (Immers, je weet dat rechts van vertex i vertex i+1 zit, en eronder zit vertex i+width), en dat je dus niet meer "dubbele" vertices hoeft te collapsen.
D4Skunk schreef op dinsdag 31 mei 2005 @ 12:55:
en je lightning blijft constant
lighting, geen bliksem ;)

.edit: ah hier: [rml].oisyn in "[ DirectX/VC] Grote ellende met de Vertex..."[/rml]
C++:
1
2
3
4
5
6
function calcNormal (v) 
{ 
    nx = (left(v).y - right(v).y) / (right(v).x - left(v).x); 
    nz = (up(v).y - down(v).y) / (down(v).z - up(v).z); 
    return normalize (nx, 1, nz); 
}


left(v) geeft de vertex links van v, etc.. Verder ga ik ervan uit dat y positief omhoog wijst, x postitief naar rechts en z positief naar voren (het scherm 'in'). In opengl is dat laatste andersom; z positief wijst naar achteren, dus waarschijnlijk zul je het teken van nz om moeten draaien.

[ Voor 20% gewijzigd door .oisyn op 31-05-2005 13:52 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 05-05 18:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

EfBe schreef op dinsdag 31 mei 2005 @ 13:20:

Hier mijn normalize routine voor het berekenen van vertexnormals uit face normals.
*bibber*, een O(n2) algoritme terwijl O(n) prima kan door gewoon de vertices van de faces af te lopen ipv de faces van de vertices ;)

De "domme" methode: zet de vertex normal van elke vertex op (0, 0, 0). Loop nu alle faces af, en voor elke vertex van elke face tel je de facenormal bij de vertexnormal op. Aan het eind normalizeer je alle vertex normals.

Dit is de meest gebruikte methode, hij is echter niet correct. De vertex normals zijn nogal afhankelijk van de hoeveelheid faces die aan een vertex grenzen. Als je een willekeurige face verder gaat subdividen betekent dat dat die originele face ineens meer mee gaat tellen in de uiteindelijke face normal, terwijl de daadwerkelijke surface die gerepresenteerd wordt door die faces niet verandert.

Handiger is dus om de facenormal die je bij de vertex op gaat tellen te vermenigvuldigen met de hoek die de 2 edges maken. Een face met een hoek van 90 graden opdelen in 2 faces met hoeken van 45 graden blijven zal nu gelijke resultaten opleveren

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

phaas schreef op maandag 30 mei 2005 @ 18:52:
En hier de relevante code:
C:
1
2
3
4
5
6
7
8
9
10
11
                calcNormal( point1, point2, point3, norm1 );
                calcNormal( point3, point2, point4, norm2 );
                
                glEnable( GL_LIGHTING );
                glBegin( GL_TRIANGLES );
                    glNormal3fv( norm1 );   
                    glVertex3fv( point1 );
                    glVertex3fv( point2 );
                    glVertex3fv( point3 );
                glEnd( );
                
Je kunt proberen om glNormal3fv na glVertex3fv te zetten. Dus:


C:
1
2
3
4
5
6
7
                glBegin( GL_TRIANGLES );
                    glVertex3fv( point1 );
                    glVertex3fv( point2 );
                    glVertex3fv( point3 );
                    glNormal3fv( norm1 );
                glEnd( );
                


Als ik me goed herinner geeft dit een soort smooth shading (Als je glNormal ervoor zet wordt dezelfde waarde voor alle daarop volgende vertices gebruikt; als je glNormal achteraf zet, interpreteert OpenGL het iets anders).

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 05-05 18:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

Nee, je moet per vertex een vertexnormal meegeven, niet per face een facenormal, dan pas kan er goed belicht worden.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

normaal per pixel met deferred lighting ;)

offtopic:
256kbs adsl in india, wie had dat gedacht

[ Voor 40% gewijzigd door Zoijar op 31-05-2005 17:57 ]


Verwijderd

.oisyn schreef op dinsdag 31 mei 2005 @ 14:43:
Nee, je moet per vertex een vertexnormal meegeven, niet per face een facenormal, dan pas kan er goed belicht worden.
Mee eens. Echter, in het verleden heb ik eens de volgorde omgedraaid (dus glvertex, glnormal, glvertex, glnormal, etc) en dat gaf toen een soort smooth shading... Nu ik er nog eens naar kijk, is dat heel vaag, want het slaat nergens op 8)7 (waarschijnlijk de normals aan verkeerde vertices gekoppeld...)

  • EfBe
  • Registratie: Januari 2000
  • Niet online
.oisyn schreef op dinsdag 31 mei 2005 @ 13:35:
[...]
*bibber*, een O(n2) algoritme terwijl O(n) prima kan door gewoon de vertices van de faces af te lopen ipv de faces van de vertices ;)
hehe ja, maar het was een algo voor een converter, boeie hoe lang het duurt ;). Hij zit in dezelfde routine die eerst de face normals maakt, dus ach... Maar had inderdaad sneller gekund, maar ben niet zo onderlegd in 3D truuks, ik meer verstand van databases :P

[ Voor 4% gewijzigd door EfBe op 01-06-2005 09:31 ]

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • D4Skunk
  • Registratie: Juni 2003
  • Laatst online: 20-10-2025

D4Skunk

Kind of Blue

EfBe schreef op woensdag 01 juni 2005 @ 09:25:
[...]

hehe ja, maar het was een algo voor een converter, boeie hoe lang het duurt ;). Hij zit in dezelfde routine die eerst de face normals maakt, dus ach... Maar had inderdaad sneller gekund, maar ben niet zo onderlegd in 3D truuks, ik meer verstand van databases :P
offtopic:
* D4Skunk kijkt reik rijk halzend vol verwachting uit naar je eerste boek :p : c# Business App development : a practical approach
(ik zou ook gerust wel een hoofdstukje willen schrijven...)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 05-05 18:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op dinsdag 31 mei 2005 @ 21:50:
[...]


Mee eens. Echter, in het verleden heb ik eens de volgorde omgedraaid (dus glvertex, glnormal, glvertex, glnormal, etc) en dat gaf toen een soort smooth shading... Nu ik er nog eens naar kijk, is dat heel vaag, want het slaat nergens op 8)7 (waarschijnlijk de normals aan verkeerde vertices gekoppeld...)
Nee dat slaat niet nergens op, behalve dat je idd de normals aan de verkeerde vertices koppelt. Dat neemt echter niet weg dat er geen smooth shading is, hij klopt alleen niet, that's all. In dit voorbeeld krijgen 3 vertices echter dezelfde normal, waardoor elke pixel op de face op dezelfde manier belicht wordt, vandaar dat het lijkt dat er geen gouraud shading plaats vindt

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • EfBe
  • Registratie: Januari 2000
  • Niet online
.oisyn schreef op woensdag 01 juni 2005 @ 11:54:
[...]
Nee dat slaat niet nergens op, behalve dat je idd de normals aan de verkeerde vertices koppelt. Dat neemt echter niet weg dat er geen smooth shading is, hij klopt alleen niet, that's all. In dit voorbeeld krijgen 3 vertices echter dezelfde normal, waardoor elke pixel op de face op dezelfde manier belicht wordt, vandaar dat het lijkt dat er geen gouraud shading plaats vindt
En ach... 'klopt alleen niet', is op zich niet zo belangrijk, als het visueel maar oogt alsof het klopt. Iedere demoscener weet dat wat getoond wordt zelden klopt, maar wel lijkt alsof het klopt ;).

(maar in een engine wil je natuurlijk wel vaak dat het klopt, omdat je later ongetwijfeld narigheid daarvan krijgt ;))
D4Skunk schreef op woensdag 01 juni 2005 @ 09:52:
offtopic:
* D4Skunk kijkt reik rijk halzend vol verwachting uit naar je eerste boek :p : c# Business App development : a practical approach
(ik zou ook gerust wel een hoofdstukje willen schrijven...)
offtopic:
een boek schrijven? Nee dat zit er de komende tijd niet in. Het is nogal veel werk en die publishers zijn slavendrijvers dat wil je niet weten: ik ben nu de technical reviewer van een .NET boek en die arme schrijver moet dus elke 7 dagen een hoofdstuk opleveren van bv 50 paginas. Ik schrijf liever code ;)

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 05-05 18:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

EfBe schreef op woensdag 01 juni 2005 @ 12:04:

En ach... 'klopt alleen niet', is op zich niet zo belangrijk, als het visueel maar oogt alsof het klopt. Iedere demoscener weet dat wat getoond wordt zelden klopt, maar wel lijkt alsof het klopt ;).
Ik bedoelde met "het klopt niet" ook alleen dat de vertices feitelijk de verkeerde normals hebben, maar dat het er wel degelijk smooth uitziet (hoewel je natuurlijk wel kans hebt op discrepanties bij de edge tussen twee faces als je gebruik maakt van de immediate mode (glVertex() & co) en consequent de glVertex en glNormal call omdraait).
(maar in een engine wil je natuurlijk wel vaak dat het klopt, omdat je later ongetwijfeld narigheid daarvan krijgt ;))
Valt op zich nog wel mee, zo gaan we bijvoorbeeld stencil shadows soft maken door de stencilbuffer te blurren (wel rekening houdend met de depth buffer). Klopt geen zak van omdat de softheid van een schaduw afhangt van de vorm van de area-light (there's no such thing as point light) en de verhouding tussen de afstanden van de shadowreceiver tot de shadowcaster en de shadowcaster tot de lightsource. Maar 't ziet er wel aardig uit ;). Wat overigens wel zo is, hoe dichter je de realiteit nadert, hoe duidelijker incorrectheden opvallen. Aan de andere kant is het verbazingwekkend hoe simpele dingen als noise, blur en bloom post-process filters het er veel realistischer uit laten zien.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

.oisyn schreef op woensdag 01 juni 2005 @ 12:33:
Valt op zich nog wel mee, zo gaan we bijvoorbeeld stencil shadows soft maken door de stencilbuffer te blurren (wel rekening houdend met de depth buffer). Klopt geen zak van omdat de softheid van een schaduw afhangt van de vorm van de area-light
Soort percentage closer filtering? Aliasing en shadow acne etc zien er ook niet echt realistisch uit :) Maar realtime radiosity zit er bijna aan te komen, heb al interessant snelle full hardware implementaties gezien...

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 05-05 18:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

Een goed blur filter zorgt niet voor aliasing, en het is sowieso geen 2x2 pixel kernel :). Realtime radiosity? Mwoa, leuk dat ze dat in de acedemische wereld doen maar in games heb je nog talloze andere dingen om mee bezig te zijn :). PRT is wel leuk though, we zitten nu daadwerkelijk te discussieren over het feit dat TR7 op de PS2 met PRT lighting er vaak beter uitziet dan op de Xbox 360 met realtime per-pixel lighting, go figure 8)7

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • phaas
  • Registratie: Augustus 2001
  • Laatst online: 23-01-2025
Jee, daar is 'ie dan :Y)

Afbeeldingslocatie: http://edukitty.org/~barry/terrain_smooth.png

De reflectie met de stencil buffer heb ik er maar even ingehackt dus er zitten hier en daar wat lelijke randjes - maja, tis mn eerste keer stencilbuffer dus het valt nog wel mee :)

In de glInit functie wordt de mesh eenmalig berekend:
C++:
1
2
3
4
5
6
loadHeightMap( );
    initTerrain( );
    buildTerrain( );
    calcBoundingSize( &terrainMesh );
    generateVertexNormals( &terrainNormals, &terrainMesh );
    generateGouraudMesh( &terrainGouraudMesh, &terrainMesh, &terrainNormals );


Het berekenen van de mesh kost ongv. 7-10sec op een P3 1000mhz, de heightmap die gebruikte was 64x64 en dus 63x63x2 triangles.

Dit is de double-remover
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
void QGLExample::generateVertexNormals( NormalMap* normals, Mesh* src )
{   
    /*
     * Make a list of vertices with a list of adjacent normals.
     */
     
    cout << "Generating vertex normals... ";
    
    //uint i, n, e;
    
    for( uint i =0; i < src->size; ++i )
    {
        for( uint n =0; n < 3; ++n )
        {
            bool newVertex =true;
            int size =normals->size;
            for( uint e =0; e < size; ++e )
            {
                //cout << "e=" << e << endl;
                if( vec3cmp( src->plane[i].vert[n].coords, normals->vertList[e].coords ) )
                {
                    /* We have a vertex that is already in the list, add the normal of the corresponding plane.
                    */
                    uint idx =normals->normals[e].size;
                    vec3cpy ( normals->normals[e].normal[idx].coords, src->plane[i].normal.coords );
                    normals->normals[e].size++;
                    newVertex =false;
                    //break;
                }
            }
            
            if( newVertex )
            {
                /* We have a new vertex, add it including the normal of the corresponding plane.
                */
                uint indx =normals->size;
                //normals->vertList[indx] = new Vertex( );
                
                vec3cpy( normals->vertList[indx].coords, src->plane[i].vert[n].coords );
                
                vec3cpy( normals->normals[indx].normal[0].coords, src->plane[i].normal.coords );
                
                normals->size++;
                normals->normals[indx].size =0;
            }
        }
    }

}


En de functie voor het berekenen van de vertexnormals uit deze lijst:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
void QGLExample::generateGouraudMesh( GouraudMesh *dest, Mesh* mesh, NormalMap* normals )
{
    cout << "Generating gouraud mesh... " << endl;
    uint i, n, e, k;
    
    for( i =0; i < mesh->size; ++i )
    {
        
        for( n =0; n < 3; ++n )
        {
            
            float vNormals[32][3];
            uint numNormals =0;
            
            for( e =0; e < normals->size; ++e )
            {
                if( vec3cmp( mesh->plane[i].vert[n].coords, normals->vertList[e].coords ) )
                {
                    for( k =0; k < normals->normals[e].size; ++k )
                    {
                        vec3cpy( vNormals[numNormals++], normals->normals[e].normal[k].coords );
                    }
                    break;
                }
            }
            
            
            if( numNormals == 0 )
                vec3cpy( dest->plane[i].normal[n].coords, mesh->plane[i].normal.coords );
                
            else
            {
                float vNormal[3];
                normalAverage( vNormal, vNormals, numNormals );
                vec3cpy( dest->plane[i].normal[n].coords, vNormal );
            }
            vec3cpy( dest->plane[i].vert[n].coords, mesh->plane[i].vert[n].coords );
        }
    }
    
    vec3cpy( dest->drawScale, mesh->drawScale );
    dest->box.xs =mesh->box.xs;
    dest->box.ys =mesh->box.ys;
    dest->box.zs =mesh->box.zs;

}


De structuur die ik gebruikt heb is vrij lelijk, maar goed, het was ook maar een oefening :)
Ik hoop dat er mensen zijn die er evt. ook wat van kunnen leren, voor de volledige code kun je hier terecht:
Klikkie

So far bedankt voor iedereens bijdrage, ik sta uiteraard open voor optimalisaties :) - hoewel het mij dus ging om een algemene manier op vnormals te bereken, de terrain-map wat in die zin maar bijzaak.

[ Voor 5% gewijzigd door phaas op 02-06-2005 11:21 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 05-05 18:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

normalAverage( vNormal, vNormals, numNormals );
Normals kun je niet "averagen", normals moet je normaliseren. Als je 2 faces hebt, een met normal (1, 0, 0) en een met (0, 1, 0), dan is de average daartussen (0.5, 0.5, 0). Dat is echter geen normal met lengte 1, dus je moet 'm nog normaliseren. Maar als je 'm normaliseert is het nogal onzin om die deling van de average te doen, aangezien een normalisatie ook maar een deling is door de lengte van de normaal. Je krijgt dan:

normal = (vector / aantal) / length(vector / aantal)

Maar een vector met lengte x delen door een factor f geeft natuurlijk een vector van lengte x/f. Je kunt die hele deling dus wegstrepen aangezien het in het normaliseren toch al gebeurt ;)

Waarom heb je trouwens niet gewoon een vector class gemaakt met de benodigde functionaliteit ipv die c-style vec3cpy functies e.d.?

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • phaas
  • Registratie: Augustus 2001
  • Laatst online: 23-01-2025
Dat klopt, ik normalize um dan ook nadat ik het gemiddelde berekend heb:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void QGLExample::normalAverage( float vec[3], float vecs[][3], uint size )
{
    vec[0] = vec[1] = vec[2] =0;
    for( uint i =0; i < size; ++i )
    {
        vec[0] += vecs[i][0];
        vec[1] += vecs[i][1];
        vec[2] += vecs[i][2];
    }

/* Die kunnen dus eigenlijk weg */
//  vec[0] /= (float)size;
//  vec[1] /= (float)size;
//  vec[2] /= (float)size;
    
    normalize( vec );
}


Edit: je hebt idd gelijk, het delen door de lengte mag er gewoon uit :)

Verder heb ik die c-functies gebruikt omdat ik het ff snel wilde proberen. Ik ben nu bezig met het maken van een low-end 3d-engine voor graphics in programma's voor het basisonderwijs, daarin gaat het uiteraard helemaal volgens het boekje :)
Natuurlijk eerst nog even wat oefeningentjes doen :P

[ Voor 34% gewijzigd door phaas op 02-06-2005 13:07 ]


  • EfBe
  • Registratie: Januari 2000
  • Niet online
.oisyn schreef op woensdag 01 juni 2005 @ 12:33:
[engine precisie nodig]
Valt op zich nog wel mee, zo gaan we bijvoorbeeld stencil shadows soft maken door de stencilbuffer te blurren (wel rekening houdend met de depth buffer). Klopt geen zak van omdat de softheid van een schaduw afhangt van de vorm van de area-light (there's no such thing as point light) en de verhouding tussen de afstanden van de shadowreceiver tot de shadowcaster en de shadowcaster tot de lightsource. Maar 't ziet er wel aardig uit ;). Wat overigens wel zo is, hoe dichter je de realiteit nadert, hoe duidelijker incorrectheden opvallen. Aan de andere kant is het verbazingwekkend hoe simpele dingen als noise, blur en bloom post-process filters het er veel realistischer uit laten zien.
heh inderdaad :) en hoe meer actie in beeld, hoe minder men het echt interesseert.

Wat ik me wel eens afgevraagd heb mbt soft shadows is, waarom men nooit dit doet (even 2D plaatje, maar je snapt het idee:
Afbeeldingslocatie: http://www.xs4all.nl/~perseus/softshadow.gif
Welnu, je berekent de projectie van het element (dat lijntje wat rechtop staat) op het projectievlak (vloer in dit geval). Je doet dit voor 2 punten, nl. voor de ray A en voor de ray B. Van element tot A is de schaduw 'hard'. Van B tot A gebruik je de hardware van de kaart door simpelweg te faden van alpha 0 (A) naar alpha 255 (B ). Voila softshadow.

[ Voor 3% gewijzigd door EfBe op 02-06-2005 13:49 ]

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • phaas
  • Registratie: Augustus 2001
  • Laatst online: 23-01-2025
EfBe schreef op donderdag 02 juni 2005 @ 13:49:
[...]

heh inderdaad :) en hoe meer actie in beeld, hoe minder men het echt interesseert.

Wat ik me wel eens afgevraagd heb mbt soft shadows is, waarom men nooit dit doet (even 2D plaatje, maar je snapt het idee:
[afbeelding]
Welnu, je berekent de projectie van het element (dat lijntje wat rechtop staat) op het projectievlak (vloer in dit geval). Je doet dit voor 2 punten, nl. voor de ray A en voor de ray B. Van element tot A is de schaduw 'hard'. Van B tot A gebruik je de hardware van de kaart door simpelweg te faden van alpha 0 (A) naar alpha 255 (B ). Voila softshadow.
Hoe wilde je dat met de stencil buffer voorelkaar krijgen? Ik denk dat de SB nl. één van de weinige manieren is op in games een goede performance te krijgen bij het casten van (dynamische) schaduwen.
Volgens mij is 'echte' soft-shadow calculatie voorlopig nog toekomstmuziek.

Verwijderd

Semi offtopic

Ik ben een tijdje terug ook bezig geweest met een terrain renderer, maar de performance was bar slecht. Ik heb maar gewoon een Dell Laptopje met zo'n Radeon Mobility kaart, dus ik haalde -zelfs met view culling- net iets boven de 30 FPS (wel met 'terrain splatting', transparant water & een aantal decoratie meshes). Ik ben er maar even mee gestopt om nog het een en ander bij te leren, want ik zag de bui al hangen als hier nog animaties, pathfinding etc bij moet...

M'n vraag:

Wat is nou ongeveer het minimum FPS wat je met een terrain renderer op een low-end grafische kaart (m'n Radeon Mobility) nodig hebt om nog een beetje RTS erop te kunnen bouwen?

Tis misschien een beetje een vage vraag, maar misschien kan iemand met wat ervaring op dit gebied hier wat zinnigs over zeggen. Hoe meer hoe beter natuurlijk, maar zou 60 FPS voor een 'kaal' terrein goed genoeg zijn?

En ja, ik weet dat een full-blown RTS heeeeel veel werk is, maar ik wou gewoon een beetje gaan prutsen om DX te leren en om weer wat motivatie voor m'n wiskunde hers op te doen. Je moet ergens beginnen, he :)

  • EfBe
  • Registratie: Januari 2000
  • Niet online
phaas schreef op donderdag 02 juni 2005 @ 14:06:
[...]
Hoe wilde je dat met de stencil buffer voorelkaar krijgen? Ik denk dat de SB nl. één van de weinige manieren is op in games een goede performance te krijgen bij het casten van (dynamische) schaduwen.
Volgens mij is 'echte' soft-shadow calculatie voorlopig nog toekomstmuziek.
Niet met de stencilbuffer, maar met extra 1-kleur, non-textured polies. Is wel wat extra werk, maar op zich niet zoveel meer werk, immers de contouren van de models moet je al berekenen voor selfshadowing als ik het goed heb.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 05-05 18:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

EfBe schreef op donderdag 02 juni 2005 @ 13:49:
[...]

heh inderdaad :) en hoe meer actie in beeld, hoe minder men het echt interesseert.

Wat ik me wel eens afgevraagd heb mbt soft shadows is, waarom men nooit dit doet (even 2D plaatje, maar je snapt het idee:
[afbeelding]
Welnu, je berekent de projectie van het element (dat lijntje wat rechtop staat) op het projectievlak (vloer in dit geval). Je doet dit voor 2 punten, nl. voor de ray A en voor de ray B. Van element tot A is de schaduw 'hard'. Van B tot A gebruik je de hardware van de kaart door simpelweg te faden van alpha 0 (A) naar alpha 255 (B ). Voila softshadow.
Sure, maar leg dan eens uit hoe jij dat zou implementeren in een 3d omgeving? ;) Er zitten wat haken en ogen aan. Die 'muur' is namelijk slechts een streepje, maar in de werkelijkheid is het natuurlijk een 3d model. Het punt dat je krijgt is dat de ene kant van het licht een hele andere schaduw kan werken dan de andere kant. Je zult dus de intersecties moeten berekenen, die in elkaar moeten gaan leggen om zo de binnenste en de buitenste rand te bepalen en uiteindelijk de geometrie daadwerkelijk op de delen zodat je de individuele stukjes apart kunt renderen. Niet echt een proces waar je vrolijk van wordt in real-time :).

En zet dat tegenover: standaard stencil shadows tekenen, nieuwe rendertarget vullen met een screenwide poly waarbij je de delen in het licht wegmaskt met de stencilbuffer, en die rendertarget gaat blurren rekening houdend met de z-waarde van elke pixel (om te zorgen dat de blur niet voorbij de edges gaat van objecten). Dit proces is een stuk goedkoper en erg lelijk ziet het er niet eens uit.
EfBe schreef op donderdag 02 juni 2005 @ 15:50:
[...]

Niet met de stencilbuffer, maar met extra 1-kleur, non-textured polies. Is wel wat extra werk, maar op zich niet zoveel meer werk, immers de contouren van de models moet je al berekenen voor selfshadowing als ik het goed heb.
Selfshadowing kan prima met standaard stencilbuffer shadows, of met shadowmaps (dus niet de tegenhanger van lightmaps maar een texture gerenderd vanuit de viewpoint van de lightsource met depth informatie van elke pixel tot de lightsource die je projecteert op je geometrie en dat gebruikt om te testen of een pixel in de schaduw valt)

[ Voor 18% gewijzigd door .oisyn op 02-06-2005 16:43 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 05-05 18:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op donderdag 02 juni 2005 @ 15:19:
Wat is nou ongeveer het minimum FPS wat je met een terrain renderer op een low-end grafische kaart (m'n Radeon Mobility) nodig hebt om nog een beetje RTS erop te kunnen bouwen?
Simpel: dat is niet echt te beantwoorden, het hangt nogal af van je specs en hoe je het geheel naar je videokaart stuurt. Het beste wat je kunt doen is gewoon zulke games die overeen komen met je specs runnen op je laptop en kijken wat die doen. En zelfs dan nog betekent dat niet dat je maar maximaal die framerate kunt halen.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • phaas
  • Registratie: Augustus 2001
  • Laatst online: 23-01-2025
@websjwans: Je zou misschien gewoon lightmapping kunnen gebruiken voor je terrein en deze gewoon tijdens het laden laten berekenen. Een gewoon terrein heeft lijkt me toch niet meer dan één lichtbron nodig dus zo moeilijk zou het niet moeten zijn. (edit: je zei realtime :) )
Verder zijn gewone (niet soft-) shadows met de stencil buffer niet zo moeilijk en al helemaal niet zwaar, zoals .oisyn al zei.

Nu we het toch over shadowen hebben: weet iemand hoe groot de performance verschillen zijn tussen shadow-mapping en shadows met de OpenGL stencil buffer? Ik heb nul ervaring met beide eigenlijk ;) Shadow-mapping klinkt eigenlijk best goed voor wat ik er tot nu toe over gelezen heb - behalve dan natuurlijk dat je er inprinciepe een extensie (ARB_SHADOW in OGL) voor nodig hebt.
Ik zou nl. graag een vorm van shadowing in mijn toekomstige low-end engine implementeren maar ik ben bang dat het weinig zin gaat hebben op een partij oude school bakken met een TNT2 oid >:)

[ Voor 18% gewijzigd door phaas op 02-06-2005 17:35 ]


  • D4Skunk
  • Registratie: Juni 2003
  • Laatst online: 20-10-2025

D4Skunk

Kind of Blue

.oisyn schreef op donderdag 02 juni 2005 @ 10:05:
Een goed blur filter zorgt niet voor aliasing, en het is sowieso geen 2x2 pixel kernel :). Realtime radiosity? Mwoa, leuk dat ze dat in de acedemische wereld doen maar in games heb je nog talloze andere dingen om mee bezig te zijn :). PRT is wel leuk though, we zitten nu daadwerkelijk te discussieren over het feit dat TR7 op de PS2 met PRT lighting er vaak beter uitziet dan op de Xbox 360 met realtime per-pixel lighting, go figure 8)7
Van PRT ken ik min of meer het achterliggende idee, maar wat is in godsnaam TR7 ?

Nu valt m'n euro : Tomb raider 7 :+

[ Voor 4% gewijzigd door D4Skunk op 02-06-2005 19:58 ]


Verwijderd

@ .oisyn

Ik was al bang dat hier geen simpel antwoord op te geven zou zijn, tis eigenlijk net zo'n discussie als een tijdje terug over 'gezonde rendertime' van een webpagina... Dit is een beetje mijn grootste gebrek als programmeur... Ik sleutel over het algemeen wel mooie dingen in korte tijd in elkaar, maar daarna moet ik me nog wel eens buigen over de performance :P

Voor m'n gewone applicatie ontwikkelingen heb ik dit probleem voor mezelf opgelost door zo snel mogelijk een werkend prototype te maken en van hieruit verder te werken, terwijl ik de performance goed in de gaten houd.

Hoe gaat dit in z'n werk in de gevestigde '3D industrie'? Bij een gewone app heb je over het algemeen de DB interactie en een paar algortimes die je performance beinvloeden, maar bij 3D applicaties/spellen slurpt zo'n beetje alles performance op. Pathfinding, 'picking', renderen, AI, netwerk traffic...

Hoe gaan game programmeurs nou te werk om dit allemaal goed en snel samen te laten werken? Ik kom net kijken op dit gebied, dus ik heb geen idee waar ik precies zou moeten beginnen. De graphics engine lijkt me, maar de ontwikkeling hiervan hangt nauw samen met de rest van de engine. Heeft iemand wat info of een link over hoe een game project typisch wordt uitgevoerd?

@ phaas

Sorry voor de thread hijack :+

[ Voor 6% gewijzigd door Verwijderd op 03-06-2005 09:13 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 05-05 18:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

phaas schreef op donderdag 02 juni 2005 @ 17:32:
@websjwans: Je zou misschien gewoon lightmapping kunnen gebruiken voor je terrein en deze gewoon tijdens het laden laten berekenen. Een gewoon terrein heeft lijkt me toch niet meer dan één lichtbron nodig dus zo moeilijk zou het niet moeten zijn. (edit: je zei realtime :) )
Weet je wat extreem handig is voor terrain? Normal maps :). Aangezien elke normalmap duur slechts een enkel stukje landschap wordt gebruikt, kun je de normals in world space in de normal maps zetten. Tijdens het renderen gebruik je gewoon deze normals als surfacenormals voor je lichtberekeningen (scheelt ook weer vertex normal informatie in je vertexbuffers). Het mooie hiervan is dat je LODing kunt toepassing zonder dat dit je lichtberekeningen beïnvloed (wat weer popping artifacts in de lighting voorkomt), omdat je gewoon een heel gedetailleerde dataset hebt over hoe het landschap er in vol detail uitziet.
Nu we het toch over shadowen hebben: weet iemand hoe groot de performance verschillen zijn tussen shadow-mapping en shadows met de OpenGL stencil buffer? Ik heb nul ervaring met beide eigenlijk ;) Shadow-mapping klinkt eigenlijk best goed voor wat ik er tot nu toe over gelezen heb - behalve dan natuurlijk dat je er inprinciepe een extensie (ARB_SHADOW in OGL) voor nodig hebt.
Ik zou nl. graag een vorm van shadowing in mijn toekomstige low-end engine implementeren maar ik ben bang dat het weinig zin gaat hebben op een partij oude school bakken met een TNT2 oid >:)
Vergeet niet dat stencilbuffers omnidirectional zijn, terwijl je voor een shadowmap moet renderen naar een texture, waardoor je dus altijd slechts een deel van de ruimte om de lichtbron heen kunt "zien". Als je echt de volledige om de lichtbron heen wilt zul je dus effectief 6 textures moeten gebruiken die als een kubus om het licht heen zitten. Shadowmaps zijn eigenlijk alleen handig voor dingen als spotlights of licht dat door een raam heen komt oid.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 05-05 18:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

D4Skunk schreef op donderdag 02 juni 2005 @ 19:56:
Nu valt m'n euro : Tomb raider 7 :+
choeso jei ;)
Verwijderd schreef op vrijdag 03 juni 2005 @ 09:12:
@ .oisyn
Hoe gaat dit in z'n werk in de gevestigde '3D industrie'? Bij een gewone app heb je over het algemeen de DB interactie en een paar algortimes die je performance beinvloeden, maar bij 3D applicaties/spellen slurpt zo'n beetje alles performance op. Pathfinding, 'picking', renderen, AI, netwerk traffic...

Hoe gaan game programmeurs nou te werk om dit allemaal goed en snel samen te laten werken? Ik kom net kijken op dit gebied, dus ik heb geen idee waar ik precies zou moeten beginnen. De graphics engine lijkt me, maar de ontwikkeling hiervan hangt nauw samen met de rest van de engine. Heeft iemand wat info of een link over hoe een game project typisch wordt uitgevoerd?
Mja, meestal begin je niet from scratch maar heb je al een bestaande codebase van een vorige game of probeersels. Daarnaast werk je niet met een klein team aan één onderdeel maar met een groot team aan meerdere onderdelen. Maar er zijn natuurlijk wel wat dependencies; gamelogic kun je eigenlijk pas echt gaan schrijven op het moment dat je een beetje een werkend systeem hebt wat graphics betreft. En dat heeft weer een renderer, exporters, cookers, animation system, physics, etc. nodig, al dan niet in een onvolwassen staat, zolang het maar werkt. Pas als je alles een beetje hebt draaien ga je kijken wat je verkeerd doet aan de hand van een profiler, dus nauwkeurig meten hoe lang elk specifiek onderdeel duurt en in welk opzicht je dat kan verbeteren. En je hebt vaak ook wel een target: x% mag naar de renderer, y% naar de AI, enzovoorts. Dat zijn uiteraard geen harde getallen, en ook iets wat echt pas tot stand komt tijdens de development (en ervaringen uit het verleden).

De xbox 360 is ook leuk met z'n 3 cpu's en hyperthreading, hier zijn de subteams onderling aan het vechten over wie een hele core tot z'n beschikking krijgt en wie moet delen :+

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

.oisyn schreef op vrijdag 03 juni 2005 @ 11:22:
Vergeet niet dat stencilbuffers omnidirectional zijn, terwijl je voor een shadowmap moet renderen naar een texture, waardoor je dus altijd slechts een deel van de ruimte om de lichtbron heen kunt "zien". Als je echt de volledige om de lichtbron heen wilt zul je dus effectief 6 textures moeten gebruiken die als een kubus om het licht heen zitten. Shadowmaps zijn eigenlijk alleen handig voor dingen als spotlights of licht dat door een raam heen komt oid.
Shadowmaps zijn echter weer onafhankelijk van geometrie; een of andere raytraced patch, of dynamisch gras/bladeren kan je simpel shadowmappen maar lastig stencil shadowen. @phaas: beiden hebben voor en nadelen, en worden gebruikt in verschillende situaties. @efbe: die methode voor softshadows bestaat al heel lang, en is ook nog behoorlijk optimized met slimme trucks ed. Meestal komt het echter niet verder dan een leuke phd thesis...het is niet bruikbaar. @oisyn: het ontgaat me waarom je realtime dynamische radiosity niet interessant vind, maar PRT wel. Dat is een simpele vorm van statische radiosity. Mij lijkt het de heilige graal als het realtime werkt, volledig dynamisch licht/shaduw, (indirecte) softshadows, color bleeding, elke vorm licht die je maar wenst...maar het is (nog) iets te traag. Precomputed radiosity zoals in bv de swat serie ziet er al erg goed uit. Ik denk sowieso dat renderen er enigszins uit gaat in de toekomst en veelal vervangen gaat worden door parallel raytracing.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 05-05 18:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

Zoijar schreef op vrijdag 03 juni 2005 @ 14:44:
@oisyn: het ontgaat me waarom je realtime dynamische radiosity niet interessant vind, maar PRT wel.
Ik zeg niet dat ik het niet interessant vind, ik zeg slechts dat ik dynamische radiosity nog niet snel gebruikt zie worden in games, terwijl PRT al vollop gebruikt wordt en zelfs op de wat langzamere platforms (ps2, xbox)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1