micha_i Opublikowano 2 Marca 2014 Udostępnij Opublikowano 2 Marca 2014 Witam, Dzisiaj zacząłem sobie pisać shader, który miał mi świecić naokoło kursora. Wszystko pięknie działało. Ale postanowiłem pójść o krok dalej i dodać cienie. Postanowiłem zrobić to lekko topornym ray-tracing'iem (Od pixela do źródła światła sprawdzasz, czy jest wolna droga). Po wielu próbach i przekleństwach, wreszcie zaczęło działać. Ale były 2 szkopuły: 1. Tło musiało mieć jednolity kolor z którym porównywałem. 2. Mój kod nie wydala nawet 30fps. Na razie zostawiłem problem nr 2 i zacząłem bawić się problemem 1. Okazało się, że po dodaniu samplera od tła, połowa ekranu(dolna) pozostaje czarna. Uznałem, że to coś z normalizacją sampla czy czymś tam. Ale po zmianie wielkości view'a znów pojawiły się problemy, gdyż światło nie podąża za kursorem. A fps'y dalej się nie podnoszą. Dlatego proszę was o pomoc, ponieważ nie mam pojęcia gdzie może być błąd. Vertex Shader: GML attribute vec3 in_Position; // (x,y,z) attribute vec4 in_Colour; // (r,g,b,a) attribute vec2 in_TextureCoord; // (u,v) varying vec2 v_vTexcoord; varying vec4 v_vColour; varying vec2 v_vPosition; void main() { vec4 object_space_pos = vec4( in_Position.x, in_Position.y, in_Position.z, 1.0); gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * object_space_pos; v_vPosition = (gm_Matrices[MATRIX_WORLD] * object_space_pos).xy; v_vColour = in_Colour; v_vTexcoord = in_TextureCoord; } Fragment Shader: GML varying vec2 v_vTexcoord; varying vec4 v_vColour; varying vec2 v_vPosition; uniform sampler2D worldTexture; uniform sampler2D backTexture; uniform float TextureSizeX; uniform float TextureSizeY; uniform float BackgroundSizeX; uniform float BackgroundSizeY; uniform float light_x; uniform float light_y; uniform float light_r; uniform float light_g; uniform float light_b; uniform float light_pow; vec4 addColor(vec4 colour,vec3 co){ co=normalize(co); colour=normalize(colour); return normalize(vec4(co-colour.rgb,colour.a)); } void main() { vec4 colour=v_vColour; vec2 coord=v_vTexcoord; vec2 Position=v_vPosition; vec2 Texture=vec2(TextureSizeX,TextureSizeY); vec2 Light=vec2(light_x,light_y); vec2 ray=Position-Light; colour=addColor(colour,vec3(light_r,light_g,light_b));//Tu jest dodawanie światła colour*=light_pow/distance(Position,Light);//A tu przyciemnianie wraz z dystansem for (float i=0.01;i<1.0;i+=0.02){//Tu jest pętla od promieni. Aktualnie jest 1/0.2=5 punktów sprawdzania vec2 pomoc=(ray*i)+Light; vec4 col=texture2D(worldTexture,vec2(pomoc/Texture)); vec4 col2=texture2D(backTexture,vec2(pomoc/Texture)); if (int(col.r*255.0)!=int(col2.r*255.0) || int(col.g*255.0)!=int(col2.g*255.0) || int(col.b*255.0)!=int(col2.b*255.0)){//Porównanie koloru pixela z kolorem tła. colour.rgb=vec3(0.0,0.0,0.0); break; } } gl_FragColor =colour*texture2D(gm_BaseTexture,coord); } Obiekt Controller: GML Information about object: Controller Create Event: execute code: global.viewsurface=surface_create(view_wview[0],view_hview[0]); view_surface_id[0]=global.viewsurface; Other Event: Game End: execute code: surface_free(global.viewsurface); Draw Event: execute code: draw_self(); draw_text(100,100,fps); Draw GUI Event: execute code: if (!surface_exists(global.viewsurface)){ global.viewsurface=surface_create(view_wview[0],view_hview[0]); view_surface_id[0]=global.viewsurface; } time1=shader_get_uniform(LightShader,"game_time1"); time2=shader_get_uniform(LightShader,"game_time2"); msx=shader_get_uniform(LightShader,"light_x"); msy=shader_get_uniform(LightShader,"light_y"); tex=shader_get_uniform(LightShader,"TextureSizeX"); tey=shader_get_uniform(LightShader,"TextureSizeY"); bex=shader_get_uniform(LightShader,"BackgroundSizeX"); bey=shader_get_uniform(LightShader,"BackgroundSizeY"); pow=shader_get_uniform(LightShader,"light_pow"); lr=shader_get_uniform(LightShader,"light_r"); lg=shader_get_uniform(LightShader,"light_g"); lb=shader_get_uniform(LightShader,"light_b"); gamma=shader_get_uniform(LightShader,"gamma"); world = shader_get_sampler_index(LightShader, "worldTexture"); back = shader_get_sampler_index(LightShader, "backTexture"); shader_set(LightShader); texture_set_stage(world, surface_get_texture(view_surface_id[0])); texture_set_stage(back, background_get_texture(background0)); shader_set_uniform_f(tex,view_wview[0]); shader_set_uniform_f(tey,view_hview[0]); shader_set_uniform_f(bex,view_wview[0]); shader_set_uniform_f(bey,view_hview[0]); shader_set_uniform_f(msx,mouse_x); shader_set_uniform_f(msy,mouse_y); shader_set_uniform_f(pow,100); shader_set_uniform_f(lr,55.0); shader_set_uniform_f(lg,55.0); shader_set_uniform_f(lb,55.0); draw_surface(global.viewsurface,view_xview[0],view_yview[0]); shader_reset(); Key Release Event for Key: end the game Btw. Room ma view0 1024x1024(rozmiary room'a), background0 jest cały biały. Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
PsichiX Opublikowano 2 Marca 2014 Udostępnij Opublikowano 2 Marca 2014 na te chwile nie mam mozliwosci odpalenia i sprawdzenia tego, ale rzuca sie pare rzeczy: 1. O majn got - uniformy możesz wrzucać do shadera także w formie vec2, vec3, vec4 - nie tylko float. pointless ze wzgledu ze niepotrzebnie sie potem to skleja w shaderze, tj. marnuje jego obliczenia. 2. dzielenie - jesli musisz uzyc uniforma do dzielenia to przekazuj to do shadera juz jako 1.0/wartosc. dzielenie to jedna z kilku najbardziej kosztownych operacji - poteg tym bardziej unikaj. 3. to sprawdzanie koloru to najgorsza mozliwa forma jaka widzialem, zdecydowanie lepiej zrob to tak: const PIX_TRESHOLD = 1.0 / 255.0; if( dot( col.xyz, col2.xyz ) < PIX_TRESHOLD ) {} 4. unikaj wszelkiego for i if - for jest dobrym wyjsciem tylko gdy wszelkie podawane w nim wartosci to constanty, wtedy shader jedynie rozwinie jego zawartosc, wiec to u Ciebie jest znosne jeszcze, ale zamiast ifa rob arytmetycznego ifa. przyklad: const PIX_TRESHOLD = 1.0 / 255.0; if( dot( col.xyz, col2.xyz ) < PIX_TRESHOLD ) colour.xyz = vec3( 0.0 ); mozna zamienic na: const PIX_TRESHOLD = 1.0 / 255.0; float f = ceil( PIX_TRESHOLD - dot( col.xyz, col2.xyz ) ); colour.xyz = mix( colour.xyz, vec3( 0.0 ), f ); roznica jest taka, ze jesli niedaj boze trafisz na GPU, ktore obsluguje dobrze dynamic branching to arytmetyczny if to zforsuje na static branching, co zapewni dzialanie tak samo na lepszych i gorszych GPU. Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Administratorzy gnysek Opublikowano 3 Marca 2014 Administratorzy Udostępnij Opublikowano 3 Marca 2014 Apostrof – znak pisarski w kształcie przecinka, umieszczany w górnym indeksie: ’. W języku polskim służy do oznaczenia, że litera (najczęściej samogłoska) występująca przed nim jest niewymawiana. Np. w przypadku nazwiska Morse [mɔːs] ostatnia litera e nie jest wymawiana; Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
PsichiX Opublikowano 3 Marca 2014 Udostępnij Opublikowano 3 Marca 2014 gnysek: twój post jest tak wartościowy jak kalejdoskop dla ślepca :* Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
szmalu Opublikowano 3 Marca 2014 Udostępnij Opublikowano 3 Marca 2014 gnysek: twój post jest tak wartościowy jak kalejdoskop dla ślepca :* Czyli nie wolno już kogoś poprawić gdy zrobi błąd? W szczególności gdy jest on nawet w tytule posta? Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
PsichiX Opublikowano 3 Marca 2014 Udostępnij Opublikowano 3 Marca 2014 wolno, ale jesli nie wnosi sie nic wiecej, to takie rzeczy pisze sie w edicie posta ktory popelnil blad Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
szmalu Opublikowano 3 Marca 2014 Udostępnij Opublikowano 3 Marca 2014 Faktycznie, masz rację Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Rekomendowane odpowiedzi
Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto
Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.
Zarejestruj nowe konto
Załóż nowe konto. To bardzo proste!
Zarejestruj sięZaloguj się
Posiadasz już konto? Zaloguj się poniżej.
Zaloguj się