Toon posts:

[GLSL/OpenGL] Multipass shaders, hoe?

Pagina: 1
Acties:

Verwijderd

Topicstarter
hallo daarr

ik heb een shader die door alle lichten loopt en het bump/specular component voor een fragment daarmee berekent. alleen; als ik meer dan een lichtje of 2 a 3 loop komt mn shader resources te kort (zowel op mn radeon 9600xt als op mn geforce 6200; bij beide kaartjes een andere error maar allebei iets met een tekort aan registers zo lijkt het)

nu weet ik dat het wel kan, want ik zie wel eens spellen op mn kaartjes die toch een aardige lading lampen bump'ed met nog een shadowmapje er bij etc.. ik gok dat ze elk licht apart 'multipassen'? of is er nog een andere manier om om de beperkingen van de shader heen te komen?

in het geval van de multipass oplossing (die ik ff aanneem als plausibele oplossing); hoe gaat dat precies in z'n werk? moet ik dan bij eerst de scene 'kaal' renderen en dan per (zichtbaar) licht de bump/specular component, en dan over elkaar plakken? en zoja, moet ik de verschillende outputs-buffers handmatig over elkaar 'berekenen' of als opengl texture multitexturen? of zijn er nog andere manieren?

dit zodat ik niet nu begin aan een mogelijke oplossing om er vervolgens achter te komen dat het de verkeerde manier was ;)

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Je kan deferred shading doen (google maar ;) ) Render geometry normalen etc. naar FBOs, en pass daar dan overheen, min of meer.

Makkelijkste is denk ik gewoon een moderne GPU gebruiken die 'geen' limitaties heeft.

  • alx
  • Registratie: Maart 2002
  • Niet online

alx

Iedere extra rendering pass geeft extra vertraging. Volgens mij is het minimum aantal lampen dat OpenGL al sinds tijden ondersteunt 8, maar dat was met fixed-function rendering. Ik kan me nauwelijks voorstellen dat je multipass nodig hebt voor meer dan 2 a 3 lampen. De snelste manier om dat toch te doen is via FBOs, ja.
En waarom zou je extra registers nodig hebben voor meerdere lampen? Je rekent toch achter elkaar de licht contrib per lamp uit? Registers worden dan toch hergebruikt?

- Wat zijn de foutmeldingen precies?
- Kun je niet eens testen op een betere kaart? Mss geeft die ook wel een foutmelding en is je code gewoon niet goed.
- Gebruik je de nieuwste graphics drivers?

Ik ontwikkelde shaders altijd eerst in ATI Rendermonkey. Dan kon ik me op shaders concentreren ipv OGL code en shaders. En real-time licht constantes tunen. Zodra tevreden, overzetten door even enkele identifiers van built-in namen naar OGL namen te veranderen. Rendermonkey ondersteunt ook multipass rendering. Geen idee of het alleen onder Windows werkt.

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

alx schreef op zaterdag 24 mei 2008 @ 17:52:
En waarom zou je extra registers nodig hebben voor meerdere lampen? Je rekent toch achter elkaar de licht contrib per lamp uit? Registers worden dan toch hergebruikt?
Oude kaarten, zoals de geforce 6 voor zover ik weet, hebben een maximaal aantal instructies voor shader executables; verder worden op die kaarten loops unrolled, omdat er geen echte conditional instructies bestaan. Elke lamp voegt op die manier het hele code path toe, totdat je het maximum aantal instructies bereikt.

  • alx
  • Registratie: Maart 2002
  • Niet online

alx

Voor de Radeon 9600XT kan ik me daar nog iets bij voorstellen. Die is nog niet SM3.0, maar de GF 6200 doet wel SM3.0 (512 instr, max 65k executed). Lijkt me niet dat je daar bij >2-3 lampen al tegenaan loopt. Ik bedoel, je kunt het best voor elkaar krijgen, maar dan ligt het niet aan de lighting maar aan de grote hoeveelheid andere code.
Heeft ook niets met te kort aan registers te maken, maar goed, die precieze foutmeldingen hebben we niet.

Voor de duidelijkheid, ik neem aan dat we over zoiets dergelijks praten voor specular:
GLSL:
1
2
3
4
5
6
for (i = 0; i < nLights; i++) {
    reflec     = reflect(-lightDirec, gl_Normal.xyz);
    nEyeVector = normalize(eyeVector);
    RdotE      = max(dot(reflec, nEyeVector), 0.0);
    color.rgb += gl_FrontMaterial.specular * gl_LightSource[i].specular.rgb * pow(RdotE, gl_FrontMaterial.shininess);
}

Ik schat 15-20 shader instructies per light. Laten het er 25 zijn. Met een shader die behalve lighting niet absurd lang is, doen oudere kaarten dat ook nog met 8 lights. Los van de fps :)

Verwijderd

Topicstarter
bedankt voor de reacties!

@alx:
- Wat zijn de foutmeldingen precies?
op de radeon kreeg ik iets over 'exceeded maximum number of constants'
op de geforce is het 'cannot locate suitable resource to bind parameter "<null atom>"'
op beide kaarten gaan de foutmeldingen weg als ik maxlights lager maak (3 of 2)
- Gebruik je de nieuwste graphics drivers?
jep

denk niet dat er iets mis is met mn code, omdat die prima werkt met bijv maxlights = 2. hoewel; misschien kan mijn code wel optimaler, doe ik iets op een inefficiente manier?

ik gebruik zelf trouwens ShaderDesigner, een soort 'rendermonkey light'


@zoijar:

hoe kom ik met deferred shading langs de limieten van de shaders, en wat hebben de FBO's er mee te maken? snap niet helemaal wat je beoogt :)

de 6200 is SM3 trouwens idd, dus ik gok dat die loops inderdaad niet unrolled..? of is dat wat optimistisch..


hier de code:

vertex
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
#define maxlights 4

varying vec3 eyeVec[maxlights];
varying vec3 lightVec[maxlights];

uniform bool bool_map_normal;
uniform bool bool_map_specular;

void main(void) {
  int light;

  gl_TexCoord[0] = gl_MultiTexCoord0;
  gl_TexCoord[1] = gl_MultiTexCoord1;
  gl_Position = ftransform();

  vec3 n = normalize(gl_NormalMatrix * gl_Normal);
  vec3 t = normalize(gl_NormalMatrix * gl_MultiTexCoord4.xyz);
  vec3 b = normalize(gl_NormalMatrix * gl_MultiTexCoord5.xyz);

  vec3 vVertex = vec3(gl_ModelViewMatrix * gl_Vertex);
  
  for (light = 0; light < maxlights; light++) {
    vec3 tmpVec = gl_LightSource[light].position.xyz - vVertex;
  
    lightVec[light].x = dot(tmpVec, t);
    lightVec[light].y = dot(tmpVec, b);
    lightVec[light].z = dot(tmpVec, n);

    tmpVec = -vVertex;
    eyeVec[light].x = dot(tmpVec, t);
    eyeVec[light].y = dot(tmpVec, b);
    eyeVec[light].z = dot(tmpVec, n);
  }

}


fragment
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
#define maxlights 4

varying vec3 eyeVec[maxlights];
varying vec3 lightVec[maxlights];

uniform sampler2D map_texture;
uniform sampler2D map_light;
uniform sampler2D map_specular;
uniform sampler2D map_normal;

uniform bool bool_map_normal;
uniform bool bool_map_specular;

void main (void) {

  int light;

  vec4 base = texture2D(map_texture, gl_TexCoord[0].xy) *
              texture2D(map_light, gl_TexCoord[1].xy);
  
  float bump = 1.0;
  vec4 specular = vec4(0.0);
  
  if (bool_map_normal == true) {
    vec3 bumptex = normalize(texture2D(map_normal, gl_TexCoord[0].xy).xyz * 2.0 - 1.0);
    
    for (light = 0; light < maxlights; light++) {
      
      float distSqr =  dot(lightVec[light], lightVec[light]);
      vec3 lVec = lightVec[light] * inversesqrt(distSqr);
      vec3 vVec = normalize(eyeVec[light]);
      float att = clamp(1.0 - 0.002 * sqrt(distSqr), 0.0, 1.0);
        
      bump += (dot(lVec, bumptex) - dot(lVec, vec3(0.0, 0.0, 1.0))) * att;
      
      if (bool_map_specular == true) {
        float specularamount = pow(clamp(dot(reflect(-lVec, bumptex), vVec), 0.0, 1.0), gl_FrontMaterial.shininess);
        specular += gl_LightSource[light].specular * gl_FrontMaterial.specular * specularamount * texture2D(map_specular, gl_TexCoord[0].xy) * att * 2.0;
      }
    }
  }
  
  gl_FragColor = (base * bump) + specular;
}


ps; als mn bumping er wat vreemd uitziet; dat komt omdat ik de basic lighting al in een texture heb (map_light) ;)

[ Voor 3% gewijzigd door Verwijderd op 25-05-2008 14:08 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22:10

.oisyn

Moderator Devschuur®

Demotivational Speaker

Let je op het aantal interpolators? SM 2.0 heeft er maar 10: 2 colors, en 8 texcoords. Je gebruikt 2 texcoords en 2 interpolators per light (eyeVec en lightVec). Voor 3 lights is dat dus al 8.

Dan heeft de pixelshader ook nog max. 32 constanten. Ik weet niet hoe slim de GLSL compiler is in het wegwerken van niet-gebruikte constanten, maar je indexeert in je pixelshader wel gl_LightSource, terwijl je alleen de specular gebruikt. Wellicht dat hij toch alle properties van elke gl_LightSource in de pixelshader constants probeert te zetten.

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

Topicstarter
dank je voor de tip, heb de specular gefixed maar nog steeds hetzelfde probleem..
maar zelfs als ik alles hyperefficient doe; het lijkt me, gezien die limieten, dat meer dan 4 a 5 lights vrij lastig wordt.. ben nog op zoek naar een oplossing (die moet er zijn.. toch? :P)

btw; 6200 is wel SM3.0 he.. heb ik dan ook meer interpolators?

*edit: domdomdom! eyeVec hoeft natuurlijk geen array te zijn, je hebt meestal maar 1 oog :P nu zit ik op 5 lights... dat is op zich voorlopig wel genoeg.. maar blijf toch benieuwd hoe het moet als je er meer zou willen :)

[ Voor 34% gewijzigd door Verwijderd op 25-05-2008 15:55 ]


  • alx
  • Registratie: Maart 2002
  • Niet online

alx

Waarom kun je op de 6200 (10 interpolators) dan niet max 7 lights aan? 7*lightvec + 1*eyevec + 2*texcoord <= 10 interpolated regs. (#const regs limiet is 224, #temp regs limiet is 32)

Als de interpolators nog steeds de beperking vormen en je wilt meer in 1 pass, moet je corners cutten. Als de objecten voor deze shader altijd vrij klein op het scherm komen, kun je besluiten geen interpolator te nemen voor de eyevec. (Maar als dat zo is, lijkt me > 4 specular lights ook al veel.) Of je moet je texture en lightmap samen kunnen voegen voor een extra light voor SM >=3.0 kaarten. Anders blijft multi pass rendering over.

[ Voor 3% gewijzigd door alx op 25-05-2008 16:56 ]


Verwijderd

Topicstarter
ik weet ook niet waarom het er niet meer kunnen zijn.. (die atom error komt dan)

en die multipass rendering, hoe gaat dat in z'n werk? wat hebben FBO's er mee van doen? :)

  • alx
  • Registratie: Maart 2002
  • Niet online

alx

Framebuffer Object @ Wikipedia. In dit geval render je dan naar een FBO. De volgende pass(es) laad je niet je texture en lightmap maar de texture van de vorige pass en voeg je daar het effect van nog meer lampen aan toe. In de laatste pass render je naar de framebuffer.

Verwijderd

Topicstarter
*bump* (<-- slechte woordgrap alert :P)

tnx mensen, heb het voor elkaar met de fbo's :)
ik render nu eerst de 'kale' scene, daarna render ik (pingpong) voor elk licht de bump/specular van de 'affected' triangles er overheen. als laatste een shader met fog. ziet er prima uit!

vind de renderopzet nu alleen niet zo netjes; ik render de hele zooi, alle iterations, in een grote loop; het lijkt me netter om de shaders bijv in de materialen te stoppen. zo kan ik sommige materialen met bump/spec doen, andere met een procedural shaders, nog andere met weer andere shaders (en andere shader volgorden etc)

ik zit er dan aan te denken om elke triangle apart te pingpongen, achter elkaar. dus eerste triangle 1 (of alle triangles met materiaal x): render pass 1, pass 2, pass 3 etc, dan hups naar het volgende materiaal/triangle en daarmee vrolijk door pingpongen. punt is dan wel dat ik welhaast oneindig vaak de fbo pingpong; ik vraag me af of hier niet al teveel overhead in gaat zitten? op zich hoeft hij natuurlijk niets te kopieren (ik swap gewoon de write/read) maar wilde me toch even orienteren voordat ik aan deze methode begin.

is dit een veelgebruikte methode of zie ik een logischere over het hoofd?

hier wat plaatjes hoe het er nu uit ziet, om even trots/stoer te doen :P pic1 pic2

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22:10

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op donderdag 12 juni 2008 @ 17:11:
ik zit er dan aan te denken om elke triangle apart te pingpongen, achter elkaar. dus eerste triangle 1 (of alle triangles met materiaal x): render pass 1, pass 2, pass 3 etc, dan hups naar het volgende materiaal/triangle en daarmee vrolijk door pingpongen.
Dus per triangle een paar draw calls? Mijn god. Alsjeblieft niet :). Batching, batching, batching!!!

Daarnaast is het switchen van rendertarget ook niet een hele goedkope operatie. Laat staan het feit dat je overdraw ook nog eens superduur wordt. Idealiter render je eerst van tevoren een z-pass (dus alleen z-buffer vullen, geen colorwrites en een minimale pixelshader). Daarnaast je passes gaan doen met z-test op equal. Dit maakt overdraw door early z rejection zo goed als gratis (je hebt namelijk geen overdraw meer)

[ Voor 26% gewijzigd door .oisyn op 12-06-2008 17:23 ]

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

Topicstarter
idd, die tip had ik al eerder van je, working on it! krijg het nog niet aan de praat met de fbo's.

probleem is dat ik voor het pingpongen 2 color component buffers heb in mn fbo, maar ik kan maar 1 depth component buffer maken voor zover ik weet, dus kan ik lastig de z pingpongen - schrijven in pass 1 en daarna lezen in de shaders en die laten failen op nonequal :s (any tips?)

maar over het batchen; als ik bijv van elke triangle met materiaal x, of elke triangle in een bepaald gedeelte van het level een list of een buffer (of hoe heet dat) maak render ik sowieso wat teveel.. (immers, misschien zie je niet elke triangle in die bepaalde list, toch moet je em dan renderen omdatie in een grotere batch zit). of maakt dat niet zoveel uit als de z-pass werkt?

en nog een probleem met die batches; elke triangle 'weet' door welke lichten hij wordt geaffect; als ik een hele batch er doorheen jaag moet ik dus voor een aantal triangles een paar lichten teveel renderen (immers, ik kan dan niet per triangle de juiste lichten doorlopen)

ik zal iig ff dat linkje van je lezen; misschien heldert dat wat op. heb iig het idee dat ik nog niet helemaal snap hoe de meeste engines hun render opzet hebben..

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22:10

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op donderdag 12 juni 2008 @ 17:38:
idd, die tip had ik al eerder van je, working on it! krijg het nog niet aan de praat met de fbo's.

probleem is dat ik voor het pingpongen 2 color component buffers heb in mn fbo, maar ik kan maar 1 depth component buffer maken voor zover ik weet, dus kan ik lastig de z pingpongen - schrijven in pass 1 en daarna lezen in de shaders en die laten failen op nonequal :s (any tips?)
Waarom wil je de z lezen eigenlijk? Ben je toch met deferred shading bezig? Of begrijp ik je gewoon verkeerd? :)
In feite hoef je ook maar 1 zbuffer te hebben terwijl je de twee FBO's gebruikt. Of zit de zbuffer gekoppeld aan een FBO? Ik ken OpenGL niet zo goed wat dat betreft.

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

Topicstarter
in de fbo zitten 2 normale buffers die ik pingpong read/write (color_componentX) en 1 depth buffer (depth_component)

ik dacht dat ik die z nodig had voor die z-pass waar je het over hebt (dus in de shader discard()'en als de z == anders dan de vorige z (van die 1e pass))

of heb ik dat idee helemaal verkeerd?

[ Voor 4% gewijzigd door Verwijderd op 12-06-2008 17:55 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22:10

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op donderdag 12 juni 2008 @ 17:54:
ik dacht dat ik die z nodig had voor die z-pass waar je het over hebt (dus in de shader discard()'en als de z == anders dan de vorige z (van die 1e pass))
Nee, je moet gewoon de z-depth functie instellen als renderstate :)

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

Topicstarter
ah lol, dat maken ze wel weer makkelijk :p werkt dat ook wel zo simpel met m'n render to fbo gebeuren?

wat je trouwens vroeg; ik weet eigenlijk niet of ik nu 'deferred' render.. snap de definitie van wikipedia iig niet helemaal :P ik render wel x keer de hele geometry over elkaar heen, elke pass gebruik ik dus de input van de vorige als input.. (dus in de specular shader: outputfragment = sourcefragment + specular etc). ik lees in de wiki iets over dat bij deferred rendering alleen in de eerste pass geometry wordt gestuurd..

iig, ik zit nu te denken hoe ik alles goed batch. ik neem aan dat daarbij eerst chunks van geometry moeten worden gemaakt, maar dat die hierna alleen nog maar in hun geheel kunnen worden gerendered; zoja, sorteer ik mn batches op gebruikte texture/shader of op hun positie, of misschien zelfs op welke lichten er in de buurt zijn? (dan hoef ik per bepaalde batch maar een aantal lichten te iteraten qua shader)

ik heb het idee dat ik in de basis iets niet goed doorheb, want ik kom zo niet echt op een goede architectuur.. :/

Verwijderd

Topicstarter
nog even een rare gedachte... als ik geen vertex buffers/gl lijsten maak maar alles als triangles stuur (maar dan wel gesorteerd per shader/texture etc) is het allemaal een stuk beter te overzien... en het scheelt een hoop overdraw (ook al maakt dat al niet zoveel meer uit met de z-pass).. alleen is het natuurlijk wat trager door de bus..

zou de winst van minder overdraw + overzichterlijkere engine opwegen tegen het snelheidsverlies? (zal wel niet, maar worth a try ;))

ps. het gaat hier om triangles, gesorteerd in een octree, dus ik kan ze heel goedkoop filteren op 'zichtbaarheid door camera' etc

[ Voor 12% gewijzigd door Verwijderd op 13-06-2008 00:25 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22:10

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op vrijdag 13 juni 2008 @ 00:08:
wat je trouwens vroeg; ik weet eigenlijk niet of ik nu 'deferred' render.. snap de definitie van wikipedia iig niet helemaal :P ik render wel x keer de hele geometry over elkaar heen, elke pass gebruik ik dus de input van de vorige als input.. (dus in de specular shader: outputfragment = sourcefragment + specular etc). ik lees in de wiki iets over dat bij deferred rendering alleen in de eerste pass geometry wordt gestuurd..
Hmm, ik weet eigenlijk sowieso niet of dat wel handig is. In feite zijn lichten additief, je kunt dus beter gewoon een alpha-blend functie gebruiken (src_color + dest_color)
iig, ik zit nu te denken hoe ik alles goed batch. ik neem aan dat daarbij eerst chunks van geometry moeten worden gemaakt, maar dat die hierna alleen nog maar in hun geheel kunnen worden gerendered; zoja, sorteer ik mn batches op gebruikte texture/shader of op hun positie, of misschien zelfs op welke lichten er in de buurt zijn? (dan hoef ik per bepaalde batch maar een aantal lichten te iteraten qua shader)
Sorteer ze (op volgorde van belangrijkheid): rendertarget (geen issue, is toch allemaal hetzelfde), vertex buffer, textures, overige render states.

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

Topicstarter
dank je, heb het nu - na lang klooien :P - helemaal voor elkaar. wat ik niet doorhad is dat je bij een vbo een stukje kunt renderen; dacht dat je dat hele ding (net als bij lists) alleen in zn geheel kon renderen :)

iig een frame rate boost van x2 :D (en nog niet eens 100% goed gesorteerd op die states)

nu het blenden; ik dacht veel te moeilijk met het gepingpong, kan idd gewoon blenden met de specular :) loop alleen tegen een probleem aan met de bump. omdat ik met prerendered lightmaps werk is mn bumpsysteem een beetje een hack; ik neem de uitgepoepte kleur en vermenigvuldig die met de bump; die loopt van ongeveer 0 tot 2 (normaal volledig van het licht af / volledig naar het licht toe gericht). klopt natuurlijk niets van maar ziet er aardig realistisch uit :P ik tel daar in de shader ook nog de specular bij op; dus:

(texture * lightmapcolor) * bump + specular
^^^^^^^ shader 1 ^^^^^^^^ _ ^^^^ shader 2 ^^^^

vraag is dus; mijn shader wil doen: * bump + specular, maar met blending kan ik dus maar 1 value multiplyen/optellen/whatever bij het resultaat van de 1e shader (texture * lightmapcolor). dus zou ik het (correct me if i'm wrong) sowieso moeten splitsen in 2 shaders, omdat ik 1 value (bump) wil multiplyen en 1 (specular) wil optellen; en zelfs dan; ik neem aan dat een shader alleen maar kleuren van 0 .. 1 kan uitpoepen en niet 0 .. 2, dus de bump blijft een probleem. enig idee hoe ik dit oplos?

btw oisyn, ik heb het vast vaker gezegd, maar je bent een geweldige hulp als ik weer eens vastloop. waar haal je toch de tijd vandaan om skills te verwerven en er ook nog eens anderen mee te helpen :D

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22:10

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je bump is een scalar neem ik aan, terwijl specular een vector3 is? Dan kan het heel simpel met een blend function: src_color + dest_color*src_alpha. In je tweede shader output je dus de specular (dat wordt src_color) in je rgb, en de bump waarde in je alpha.

Maar zo'n hele ingewikkelde operatie is het niet in totaal. Waarom doe je het in meerdere shaders? Ik zou zeggen dat je iig 1 volledige lighting pass doet per shader (dus bump mapped diffuse en specular per licht)

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

Topicstarter
bump in alpha, goed punt :) weer eens helemaal niet aan gedacht. ga er nu mee bezig :)

Verwijderd

Topicstarter
sorry dat ik nu alweer loop te vragen, maar heb na 5 1/2 uur hard zoeken nog steeds niet gevonden hoe ik die blending equation

src_color + dest_color * src_alpha

in opengl fix..

de specular (in rgb) bij de pixel optellen gaat prima, maar hoe ik de normal (in alpha) vermenigvuldig met de pixel in dezelfde pass kan ik maar niet vinden.. any pointers?

ps. de diffuse ook in die ene shader kan wel, maar ik moest toch een z-pass doen, dus daar diffuse kwam ook wel uit.. (moet natuurlijk eigenlijk nog een echte textureloze z-pass voor ;))

zo is het nu dus/wil ik het voor elkaar krijgen:

code:
1
2
3
4
5
6
7
8
blend(uit)
render(alles) met shader(diffuse + lightmap)

for (0 to lights) {
  blend(vorige.rgb += komende.rgb) // specular
  blend(vorige.rgb *= komende.a) // bump <-- dit lukt me dus maar niet
  render(alles in de buurt van licht) met shader(bump + specular)
}

[ Voor 42% gewijzigd door Verwijderd op 17-06-2008 00:47 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22:10

.oisyn

Moderator Devschuur®

Demotivational Speaker

de normal (in alpha)
Is dat een typo? Een normal is natuurlijk een vector, die kan niet in de alpha (wat een scalar is).

Maar glBlendFunc(GL_SRC_COLOR, GL_SRC_ALPHA) is toch gewoon wat je moet hebben?

.edit: euh nee, excuus, ik denk verkeerd. Met de blendfunctie doe je effectief src*x + dest*y, waarbij je x en y in kunt stellen met glBlendFunc. Aangezien je de specular in je src hebt staan is x is gelijk aan 1, en dest wil je met 'bump' vermenigvuldigen die in je src alpha staat, moet je dus instellen:
glBlendFunc(GL_ONE, GL_SRC_ALPHA)

[ Voor 45% gewijzigd door .oisyn op 17-06-2008 01:35 ]

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

Topicstarter
met normal bedoelde ik idd de kleurwaarde (bump)

het 'werkt' idd, nu ik goed kijk; die alpha wordt zo met de framebuffer rgb gemultiplied; probleem is alleen dat mn bump van -1 tot 1 ranged; de destination moet er donkerder of lichter van worden (afhankelijk van de normalmap op dat punt)

alleen de alpha gaat natuurlijk maar van 0 tot 1.. want ik dus eigenlijk wil is een multiply met (a * 2 - 1) ipv met (a) ... kan dat?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22:10

.oisyn

Moderator Devschuur®

Demotivational Speaker

de destination moet er donkerder of lichter van worden (afhankelijk van de normalmap op dat punt)
Dus eigenlijk is je bump tussen 0 en 2 (en niet -1 en 1). Wordt wat lastig. Je kan in je vorige pass twee keer zo hoge waarden outputten, maar dan zit je wel met precision loss (wat je sowieso wel krijgt bij multipass rendering als je gewoon R8G8B8 buffers gebruikt, maar dat terzijde).

Maar goed, ik blijf erbij dat dat wat je nu in twee passes probeert te doen ook makkelijk in 1 kan :)

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

Topicstarter
ik ga maar voor die manier dan :)

[ Voor 11% gewijzigd door Verwijderd op 17-06-2008 03:49 ]


Verwijderd

Topicstarter
ok, geimplementeerd, werkt idd beter zo :) tnx!

nu moet alleen de framerate nog wat omhoog. voor een kamer met een triangle of 100 haal ik maar iets van 15 fps, das niet genoeg natuurlijk :)

als ik glDepthFunc(GL_EQUAL); op GL_LEQUAL zet krijg ik geen snelheidswinst. betekent dat dat mn z-pass niet goed werkt, of is het verschil niet zo groot dat het altijd te zien is? op zich; als ik in het 'niets' kijk haal ik wel 300fps, dus hij lijkt wel te negeren wat niet op het beeld te zien is, maar ook dat veranderd niet als ik em op LEQUAL zet. vergeet ik iets?

nog andere tips voor snelheidswinst? ik ga zelf iig ff mn hele code minitueus optimizen, maar de grote bottleneck zit em nog in de shaders.

ik teken overigens per light ook daadwerkelijk alleen de triangles in de buurt van dat licht, dus daar valt denk ik weinig snelheidswinst meer aan te halen.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22:10

.oisyn

Moderator Devschuur®

Demotivational Speaker

als ik glDepthFunc(GL_EQUAL); op GL_LEQUAL zet krijg ik geen snelheidswinst.
Nee, het maakt ook geen zak uit. De fragments die gereject worden zijn juist degene met z-waarden groter dan die in de z-buffer staan. Je hebt in feite geen fragments meer met een z kleiner dan die in de z-buffer, omdat je de minimale z voor elke fragment al bepaald hebt in je z-pass :)

Gebruik je wel mipmaps voor al je textures?

[ Voor 5% gewijzigd door .oisyn op 18-06-2008 18:18 ]

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

Topicstarter
@zpass: k prima dan :)
@mipmaps: jep, als het goed is wel (zal ff controleren voor de zekerheid *edit: jep, overal mipmaps)

als ik trouwens GL_LINEAR_MIPMAP_NEAREST gebruik ipv GL_LINEAR_MIPMAP_LINEAR krijg ik wel een bijna x2 snelheidswinst! terwijl het er nagenoeg even goed uitziet. vreemd?

[ Voor 10% gewijzigd door Verwijderd op 18-06-2008 18:43 ]


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Die eerste doet gewoon bilinear interpolatie op het dichtsbijzijnde mipmap level (3 lerps dus), die tweede interpoleert tussen twee bilinear mipmaps (7 lerps dus) (hoewel de traagheid waarschijnlijk in 4 vs 8 texture lookups zit... ligt ook aan je hardware paths)

(je kan overigens ook anisoptropic filtering aanzetten met GL_EXT_texture_filter_anisotropic... of het zelf doen in shaders, dan kan je het nog beter doen... niet echt nuttig)

[ Voor 47% gewijzigd door Zoijar op 18-06-2008 19:16 ]


Verwijderd

Topicstarter
k, ik zie iig 0 verschil, dus ik vind het een mooie optimisation :P
toch moet het nog veel sneller kunnen :/ (lijkt me)

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Je ziet wel verschil als je bv een lange muur rendered met bakstenen, en daar met een redelijk grote hoek (met de normaal) tegenaan kijkt.

(maar mijn eerste optimialisatie als ik een spel speel tegenwoordig is ook altijd anisotropic filtering uit zetten. Zie ook nooit zo veel verschil)

[ Voor 35% gewijzigd door Zoijar op 18-06-2008 19:12 ]


Verwijderd

Topicstarter
ah mijn opengl settings stonden ook nog wat hoog.. AA en AF idd :) haal nu zo'n 42 fps, toch redelijk voor mn 6600 (2e handsje, goeie kaart trouwens (y)) :)

[ Voor 14% gewijzigd door Verwijderd op 19-06-2008 04:06 ]

Pagina: 1