GLSL Shaders in BlitzMAX
BlitzMax Forums/BlitzMax Programming/GLSL Shaders in BlitzMAX
| ||
Been trying to learn shaders and incorporate them into Max2D. Been learning a lot about them. Came up with a type to help with them. The type is far from complete. I'll add to it as I learn more. Shader Type.bmx Demo Circles.bmx Usage is simple. First you must set BM to use OpenGL with SetGraphicsDriver GLMax2DDriver() Then set your graphics mode as usual. Graphics Width, Height Then you need to create your shader with TShader.Create() Local Shader:TShader = TShader(VertexShaderSource,PixelShaderSource,Name) VertexShaderSource and PixelShaderSource are strings containing the GLSL source of your shaders. Name is a name you give to this shader for the debug logging. Now to use the shader, you just use Shader.Start() To stop shader processing, just use TShader.Stop() If you need to send data to the shader from BMax, use Local Location:Int = Shader.GetUniform(UniformName) Shader.SetUniform1f(Location,Value) UniformName is the name of the variable in the shader. Currently, I have only implemented sending 1 float value at a time. Other types will be added over time. That's about it. Look at my demo for an example of how to use the methods. :) This post will be updated as I learn more and implement more into the Type. |
| ||
That's pretty f-ing awesome, nice work! |
| ||
Getting textures to work. A fluttering flag example. Don't forget to copy the "Shader Type.bmx" file to the directory containing this source (or just Copy/Paste the whole thing where Include "Shader Type.bmx" is located). |
| ||
Works well here. I realise it's very early days, but do you think it might be possible to do any of: 1) Apply shader to TImage or TPixel; 2) Apply to backbuffer (or copy of same)? 3) Include checks for necessary GL version? That'd be my little wishlist anyway! |
| ||
Tried adding Klepto's RendertoTexture routine from here OpenGL Render2Texture (FBOs) to apply a shader to an entire rendered scene, but it seems to only render to half the frame. Any ideas? |
| ||
Ok, if I change line 71 from glOrtho 0,Image.Width,Image.Width,0,-1,1 to glOrtho 0,Image.Width,Image.Height,0,-1,1 then it renders as expected. A bug in the Render2Texture routine? |
| ||
Ok, also had to add the glScalef(1,-1,1) and the glScalfef(1,1,1) in the BindBuffer and UnbindBuffer methods respectively to avoid flipping the texture as per reply in the line above. |
| ||
This is just wonderful. |
| ||
@bug Yes this is a bug in the routine, I had added the fix to the r2t-examples I gave to dw' in one of his threads (including a bit more "oop" for the types). I think at least the glscalef-thing was appended to the codearchive-entry of klepto2. Hope you enjoy the tinker time. bye Ron |
| ||
Nice screensaver kinda thing :) Decided to C&P the TShader type into the source, that way if I change the Type in post #1, I won't risk making all these samples unrunnable. |
| ||
Great swimmers, TomToad ! This VertexSource and PixelSource is very new to me though. I'm still waiting for full-screen random pixels with this new GL stuff. I might be able to understand it. |
| ||
full-screen random pixels |
| ||
Okay, thank you ! Can you make them colored please ? R G B (0-255). Do that and I'll get my magnifying glass out and try to see what's going on there. Oh, and before you get too busy, is this the fastest way to stuff colored pixels on the screen ? (Benchmarks ?) |
| ||
Awesome stuff there. Is it doable in Dx ? |
| ||
Okay, thank you ! Can you make them colored please ? R G B (0-255). Do that and I'll get my magnifying glass out and try to see what's going on there. Yeah, a little bug in my program. GLSL doesn't allow for a static type. Globals are reinitialized every frame. So a proper Rnd() function cannot be created on GLSL. I did find one online, but you must provide the seed for every call. I just use the x,y coordinates added to a randomly generated float passed on the CPU side. That is the reason for the Random = Rnd(0,1) in the above code. The bug comes in to the fact that I pass the exact same seed for red, green, blue components creating various shades of grey. If you replace " gl_FragColor = vec4(rand(coord.xy),rand(coord.xy),rand(coord.xy),1.0);~n" + .. with " gl_FragColor = vec4(rand(coord.xy),rand(coord.xy+.01),rand(coord.xy+.02),1.0);~n" + .. Then you will get a nice random color screen. Oh, and before you get too busy, is this the fastest way to stuff colored pixels on the screen ? (Benchmarks ?) Yes and No. As shown in many examples here, and examples in your Lights Fantastic thread, Doing per pixel calculations and pushing them to the screen can be quite fast. Unfortunately, there is no way to store a pixel table in the shader so pixels can be manipulated on CPU side. You could use a texture for a table, but as a texture is already a type of table anyway, updating them would be no faster than other, non shader versions. Problably some render2Texture code would be your best bet. I did have an idea to just push a pixel queue (an array full of pixel data) to the shader, so if you are manipulating only a few pixels, there would be no need to push the entire texture across the graphics bus. It theoretically should be at least 2X faster even when changing all pixels in a texture as the transfer would be only one way. Unfortunately, GLSL 1,2 has no way of rendering to the texture directly that I can find. Maybe a higher version of GLSL will allow it, still reading and learning. |
| ||
The more I am hearing about pushing pixels in a queue, Tom, it sounds very familiar to getting HAM graphics on the Commodore Amiga. https://en.wikipedia.org/wiki/Hold-And-Modify Gosh I hope it doesn't get this complex ! :/ |
| ||
Ultimately with pushing pixels they have to cross the cpu gpu barrier somewhere....unless you do all or most processing on the gpu itself with minimal instructions sent across. |
| ||
This is really interesting, I've often wanted to dive into shaders, what are your reading/learning sources? |
| ||
[quoteThis is really interesting, I've often wanted to dive into shaders, what are your reading/learning sources? [/quote] http://www.lighthouse3d.com/tutorials/glsl-12-tutorial/ http://nehe.gamedev.net/article/glsl_an_introduction/25007/ And a bit of googling. |
| ||
Now messing with the vertex shaders. Made a nice sine scroller. |
| ||
Trying out your code. ?? HOW are you doing this,Tom ? I see DrawText() and no other code in the main. All I can figure is you somehow managed to reposition all the pixels on the screen to a wave pattern so anything that is plotted will be skewed from its original, meaning of course no straight lines via drawline(). Oddly enough trying to add any graphics around the DrawText() does not appear. Lines, rectangle, or ovals. Tricky stuff. I remember in S2 I had an icon a picture of a fish and when you used it in your command set, the screen and sprites would become all wavy like that like you were underwater. :) |
| ||
In the Nice Screensaver Kinda Thing above, go to lines 116 and 117 and change the *20.0 in both strings to *2.0. Go to line 147 and change the Time :+ .001 to Time :+ .01. Now you have a wavy underwater thing. :) Reason why you don't see anything in the main program is because the code to modify the text is actually being run on the graphics card itself. When a shader is created, you effectively bypass the rendering pipeline. This gives you opportunity to modify the vertices and pixels before they actually reach the screen. for the wavy text, the shader is moving the corners of each letter up and down on the y axis depending on its position on the x axis. The blue and white stripes are created by modifying the pixels based on its y position on the letter. Reason why circles and lines are not showing up is because the shaders operate on 3D objects. Since TImages are simply 3D rectangles that are always facing the camera to appear 2D, shaders will work on them. Circles and lines are 2D constructs which shaders don't support (at least I have found none in the research I have done so far). In order to draw the 2D primitives, you must disable the running shaders to allow the normal pipeline to render them. A few small modifications to the main function will do. |
| ||
Well now that you are mentioned it, Tom. Is there a simple way to take a TIMAGE or PIXMAP and display it as a parallelogram. Where it appears something like this: [IMAGE] And would appear as if it were 3-dimensionally tilted away from the camera ? |