Skocz do zawartości

Problem z Shader'em.


Rekomendowane odpowiedzi

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

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

  • Administratorzy
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

gnysek: twój post jest tak wartościowy jak kalejdoskop dla ślepca :*

Odnośnik do komentarza
Udostępnij na innych stronach

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

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ę
  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...