|
Need some help with shaders |
TorgaW
Member #23,803
August 2023
|
Hello everyone! 1al_use_shader(noise_shader);
2al_set_shader_sampler("tex1", grass_tex, 1);
3al_draw_scaled_bitmap(result_bitmap, 0, 0, 32, 32, 1024, 512, 256, 256, 0);
4al_use_shader(nullptr); //disable shader for the next objects
My result is inconsistent, sometimes I get a black screen with nothing, and sometimes all my text that is drawn with al_draw_text turns into colorful rectangles. I have checked all possible "dummy" mistakes: bitmaps are not nullptr, shader is also not nullptr, everything works fine until al_set_shader_sampler() function. Maybe there is an obvious solution to the problem, but I can not find it. Maybe I'm using shaders incorrectly or do I need to use some special flags for the display and bitmaps? My shaders code is here: Vertex: 1varying vec2 tex_uv;
2void main()
3{
4 tex_uv = gl_MultiTexCoord0.xy;
5 gl_Position = ftransform();
6}
Fragment: 1#ifdef GL_ES
2precision mediump float;
3#endif
4
5uniform sampler2D al_tex;
6uniform sampler2D tex1;
7uniform sampler2D tex2;
8varying vec2 tex_uv;
9
10vec2 random(vec2 uv) {
11 uv = vec2(dot(uv, vec2(121.1, 311.7)), dot(uv, vec2(262.5, 183.3)));
12 return -1.0 + 2.0 * fract(sin(uv) * 3.0);
13}
14
15float noise(vec2 uv) {
16 vec2 uv_index = floor(uv);
17 vec2 uv_fract = fract(uv);
18
19 vec2 blur = smoothstep(0.0, 1.0, uv_fract);
20
21 return mix(mix(dot(random(uv_index + vec2(0.0, 0.0)), uv_fract - vec2(0.0, 0.0)), dot(random(uv_index + vec2(1.0, 0.0)), uv_fract - vec2(1.0, 0.0)), blur.x), mix(dot(random(uv_index + vec2(0.0, 1.0)), uv_fract - vec2(0.0, 1.0)), dot(random(uv_index + vec2(1.0, 1.0)), uv_fract - vec2(1.0, 1.0)), blur.x), blur.y) + 0.5;
22}
23
24const int max_octaves = 6;
25
26float FBM(vec2 uv)
27{
28 float result = 0.0;
29 float ampl = 1.0;
30 float freq = 0.005;
31
32 for(int oct = 0; oct < max_octaves; oct++)
33 {
34 result += ampl * noise(uv * freq);
35 ampl *= 0.5;
36 freq *= 2.0;
37 }
38
39 return result;
40}
41
42void main(void) {
43 float t = 0.0;
44 t = FBM(tex_uv.xy * 100.0);
45 vec4 color = texture2D(tex1, tex_uv);
46 gl_FragColor = color * t;
47}
I apologize if my question is not clear or contains insufficient information. Please tell me about what you need and I will send you more code or screenshots. P.S. |
Mark Oates
Member #1,146
March 2001
|
Can you provide more context about your ftransform() function? There could be an issue there. Also, the FBM() and noise() functions seems to be doing a lot, so it's difficult for me to parse out if there could be an error there. In these types of situations, I would start by simplifying the problem to a shader that takes 2 textures and blends them based on some blend value [0.0-1.0]. Also in your source, I notice you are not binding to tex2 and it doesn't look like you are sampling from either al_tex or tex2 in the fragment shader. Sometimes visuals can provide clues. If you don't mind posting some screenshots that could help. -- |
TorgaW
Member #23,803
August 2023
|
Thanks for reply, Mark! 1. ftransform function - I have found it on reddit, this function is equivalent to gl_ModelViewProjectionMatrix * gl_Vertex. I can't tell you more, because I don't know what it does exactly . But I tried to test tex_uv property and it works fine. I tried to color my bitmap like gl_FragColor = vec4(tex_uv.x, tex_uv.y, 0.0, 1.0) and my bitmap had red-green gradient with black point on the lower left corner. https://i.ibb.co/7RTSs0X/tex-uv-gradient.png 2. FBM function - It combines multiple octaves of perlin noise. This function is well-tested and works fine. It outputs values between 0.0 and 1.0 based on tex_uv. https://i.ibb.co/r6BQdTV/FBM-result.png 3. About sampling - I have not yet implemented my blending code, because it's not working and I can't go to this stage. I think it will be like mix(texture2d, texture2d, blend_value). 4. And finally my results after calling al_set_shader_sampler("tex1", grass_tex, 1): just a black screen without any yellow text, that I have P.S. Changing unit value from 1 to 10 in al_set_shader_sampler made this: |
Dizzy Egg
Member #10,824
March 2009
|
Not sure if it will help, but here is my standard Allegro vertex code: attribute vec4 al_pos; attribute vec4 al_color; attribute vec2 al_texcoord; uniform mat4 al_projview_matrix; varying vec4 varying_color; varying vec2 varying_texcoord; void main() { varying_color = al_color; varying_texcoord = al_texcoord; gl_Position = al_projview_matrix * al_pos; } Then in your fragment I would use: varying vec2 varying_texcoord; //Your functions here... void main(void) { float t = 0.0; t = FBM(varying_texcoord.xy * 100.0); vec4 color = texture2D(tex1, varying_textcoord); gl_FragColor = color * t; } EDIT: Ok, got it working. You need to mix the texture you're drawing (with al_draw_bitmap) with the texture you send in: 1#ifdef GL_ES
2precision mediump float;
3#endif
4
5uniform sampler2D al_tex; //texture used in al_draw_bitmap
6varying vec4 varying_color;
7varying vec2 varying_texcoord;
8uniform sampler2D tex1;
9uniform sampler2D tex2;
10varying vec2 tex_uv;
11
12vec2 random(vec2 uv) {
13 uv = vec2(dot(uv, vec2(121.1, 311.7)), dot(uv, vec2(262.5, 183.3)));
14 return -1.0 + 2.0 * fract(sin(uv) * 3.0);
15}
16
17float noise(vec2 uv) {
18 vec2 uv_index = floor(uv);
19 vec2 uv_fract = fract(uv);
20
21 vec2 blur = smoothstep(0.0, 1.0, uv_fract);
22
23 return mix(mix(dot(random(uv_index + vec2(0.0, 0.0)), uv_fract - vec2(0.0, 0.0)), dot(random(uv_index + vec2(1.0, 0.0)), uv_fract - vec2(1.0, 0.0)), blur.x), mix(dot(random(uv_index + vec2(0.0, 1.0)), uv_fract - vec2(0.0, 1.0)), dot(random(uv_index + vec2(1.0, 1.0)), uv_fract - vec2(1.0, 1.0)), blur.x), blur.y) + 0.5;
24}
25
26const int max_octaves = 6;
27
28float FBM(vec2 uv)
29{
30 float result = 0.0;
31 float ampl = 1.0;
32 float freq = 0.005;
33
34 for(int oct = 0; oct < max_octaves; oct++)
35 {
36 result += ampl * noise(uv * freq);
37 ampl *= 0.5;
38 freq *= 2.0;
39 }
40
41 return result;
42}
43
44void main(void) {
45 float t = 0.0;
46 t = FBM(varying_texcoord.xy * 100.0);
47 vec4 color = texture2D(al_tex, varying_texcoord.xy);
48 vec4 texture_color = texture2D(tex1, varying_texcoord.xy) * t;
49 gl_FragColor = mix(color, texture_color, texture_color.a);
50}
Using this vertex shader: 1attribute vec4 al_pos;
2attribute vec4 al_color;
3attribute vec2 al_texcoord;
4uniform mat4 al_projview_matrix;
5varying vec4 varying_color;
6varying vec2 varying_texcoord;
7
8
9void main()
10{
11 varying_color = al_color;
12 varying_texcoord = al_texcoord;
13 gl_Position = al_projview_matrix * al_pos;
14}
Getting better/worse result by playing with values in your functions!
---------------------------------------------------- |
TorgaW
Member #23,803
August 2023
|
Thanks for reply, Dizzy! Unfortunately it doesn't help. I setup vertex shader as yours and my result was just black bitmap. With gl_Position I have result, that only upper right quarter of the bitmap is affected and it is stretched to the full game window, but should be only 512x512 pixels. I draw my bitmap with this code: 1//enable ALLEGRO_PROGRAMMABLE_PIPELINE option.
2//while loop ...
3//...
4//create result bitmap 512x512.
5//fill it with al_clear_to_color(/*black color*/).
6//...
7//...
8al_use_shader(noise_shader); //enable shader. it is not null.
9al_draw_bitmap(result_bitmap, 0, 0, 0); //draw bitmap on screen (backbuffer is a target bitmap). also not null.
10al_use_shader(nullptr); //disable shader for next bitmaps in a queue.
For some reasons next bitmaps also black or glitched like my screen text. If someone want to see entire project code, I can create github repo with it and share. Edit. Thanks, Dizzy! I will try your new code. Edit #2. Result is the same: https://i.ibb.co/wh6bGcJ/image.png |
Dizzy Egg
Member #10,824
March 2009
|
Are you using my vertex shader and fragment shader?? EDIT: Probably best to show all your code! EDIT2: You need to set the texture: al_set_shader_sampler("tex1", grass_tex, 1);
---------------------------------------------------- |
TorgaW
Member #23,803
August 2023
|
I'm using both shaders. My code: https://github.com/TorgaW/shader_trouble_allegro5 If you see some bad code or inefficient way of doing something, please, let me know! I would be really appreciate! Edit I did it, but it is not working. |
Dizzy Egg
Member #10,824
March 2009
|
noise_shader = ShaderManager::GetShader("PerlinNoise"); Shouldn't that be: noise_shader = ShaderManager::GetShader("PerlinNoise.glsl"); ?? Or even: noise_shader = ShaderManager::GetShader("Resources/Shaders/PerlinNoise.glsl");
---------------------------------------------------- |
TorgaW
Member #23,803
August 2023
|
No, because it is stored in the std::map and “PerlinNoise” is a key to get pointer to the shader struct. If you change Perlin.glsl to |
Dizzy Egg
Member #10,824
March 2009
|
Nevermind, I can see you set the render target to backbuffer. In order for the shader to work with the 2 textures, we would need to change the fragment shader MAIN to this: void main(void) { float t = 0.0; t = FBM(varying_texcoord.xy * 100.0); vec4 texture_1_color = texture2D(tex1, varying_texcoord.xy); vec4 texture_2_color = texture2D(tex2, varying_texcoord.xy) * t; gl_FragColor = mix(texture_1_color, texture_2_color, texture_2_color.a); } Also I noticed your sprites are very small - you would need to do some scaling or it won't look great! I've attached my result using your sprites, drawn to 256 x 256. {"name":"613342","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/7\/b\/7bec85543c7831f15971703668b4eca9.png","w":257,"h":256,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/7\/b\/7bec85543c7831f15971703668b4eca9"}
---------------------------------------------------- |
TorgaW
Member #23,803
August 2023
|
Hello, Dizzy! Thanks for reply! I set up your code and have this result: https://i.postimg.cc/QdC77wLf/image.png Grass texture is blending with white color (why? ). Fragment: float t = 0.0; t = FBM(varying_texcoord.xy * 200.0); vec4 texture_1_color = texture2D(tex1, varying_texcoord.xy); vec4 texture_2_color = texture2D(tex2, varying_texcoord.xy) * t; gl_FragColor = mix(texture_1_color, texture_2_color, texture_2_color.a); Vertex: varying_color = al_color; varying_texcoord = gl_MultiTexCoord0.xy; gl_Position = ftransform(); C++: //creating bitmap before loop result_bitmap = al_create_bitmap(256, 256); //create bitmap al_set_target_bitmap(result_bitmap); //set as target al_clear_to_color(al_map_rgb_f(1.0, 1.0, 1.0)); //fill bitmap with white color Render::SetViewportAsRenderTarget(); //set backbuffer as render target //.. //in loop al_use_shader(noise_shader); al_set_shader_sampler("tex1", grass_tex, 1); al_set_shader_sampler("tex2", dirt_tex, 2); al_draw_bitmap(result_bitmap, 0, 0, 0); al_use_shader(nullptr); I have no ideas what is going on Result image in attachments. |
Dizzy Egg
Member #10,824
March 2009
|
Make sure your vertex shader looks like this: 1attribute vec4 al_pos;
2attribute vec4 al_color;
3attribute vec2 al_texcoord;
4uniform mat4 al_projview_matrix;
5varying vec4 varying_color;
6varying vec2 varying_texcoord;
7
8
9void main()
10{
11 varying_color = al_color;
12 varying_texcoord = al_texcoord;
13 gl_Position = al_projview_matrix * al_pos;
14
15}
Also, you're drawing result_bitmap at 0,0 - are you sure you're not drawing it over your text?? EDIT: Ok, I finally got your engine up and running! I had to change some bits. In Game.cpp I changed your display setup to this: al_set_new_display_flags(ALLEGRO_FULLSCREEN | ALLEGRO_PROGRAMMABLE_PIPELINE | ALLEGRO_OPENGL); al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 4, ALLEGRO_SUGGEST); al_set_new_display_option(ALLEGRO_SAMPLES, 16, ALLEGRO_SUGGEST); al_set_new_display_option(ALLEGRO_RENDER_METHOD, 1, ALLEGRO_SUGGEST); al_set_new_display_option(ALLEGRO_SUPPORT_NPOT_BITMAP, 1, ALLEGRO_SUGGEST); game_display = al_create_display(1920, 1080); And here is the result: {"name":"613344","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/4\/9\/4921614292aa1f86fbe2017d1f856353.png","w":1030,"h":692,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/4\/9\/4921614292aa1f86fbe2017d1f856353"} I have attched the shaders as well. I had to change the clocks in Benchmark.hpp to this: 1class Benchmark
2{
3private:
4 std::chrono::steady_clock::time_point start;
5 std::chrono::steady_clock::time_point end;
6public:
7 Benchmark(){};
8 ~Benchmark(){};
9 inline void Start()
10 {
11 start = std::chrono::high_resolution_clock::now();
12 };
13 inline void Stop()
14 {
15 end = std::chrono::high_resolution_clock::now();
16 };
17 inline uint64_t GetTimeNano()
18 {
19 return std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count();
20 };
21 inline uint64_t GetTimeMicro()
22 {
23 return std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
24 };
25 inline uint64_t GetTimeMili()
26 {
27 return std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
28 };
29};
As I couldn't use the _V2 in chrono (but that might just be a Windows thing)
---------------------------------------------------- |
TorgaW
Member #23,803
August 2023
|
Thank you, Dizzy!! IT IS WORKING!!!! FINALLY!!! I will read about this magic flags to know more! You are the best!! Thank you!!! |
Dizzy Egg
Member #10,824
March 2009
|
Awesome! You’re welcome, glad it’s working!
---------------------------------------------------- |
Mark Oates
Member #1,146
March 2001
|
@TorgaW, Could you post your final result code please? 🙂🙏 -- |
|