[HELP] OpenGL Shaders BitmapData Scaling (ibilon base code) [SOLVED]

especially @TommyXXX, @ibilon
I’m very sorry to bother you again but I need a little bit of help (a lot easier now) on a different but similar problem.

My objective now is scaling the bitmapData I’ve AntiAliased before with openfl shaders
(I am using the Ibilon’s OpenGL Shader BitmapData example https://github.com/ibilon/BitmapDataShaders with some customizations of mine)

As I know, to scale I need to do something in the Vertex Shader (obviously since the Fragment one basically works per pixel).

I’ve prepared this piece of code

		var shader = "
			#version 120
			varying vec2 vTexCoord;
			uniform sampler2D uImage0; //redered scene texture

			void main()
				gl_FragColor = texture2D(uImage0, vTexCoord.xy);

		var vertex = "
			attribute vec4 aPosition;
			attribute vec2 aTexCoord;
			varying vec2 vTexCoord;

			uniform mat4 uMatrix;

			void main (void) {

				vTexCoord = vec2 (aTexCoord.x, 1.0-aTexCoord.y); // flip y
				vec4 a = aPosition;
				gl_Position = uMatrix * a;


So basically the fragment shader (var shader) do nothing.
The vertex shader (var vertex) execute a transformation scaling to 25% of the original one.

I have modified the code to accept a custom vertex shader at the INIT function
ShaderCompositing.init(bitmapdata.width, bitmapdata.height, vertex);
so I can pass a custom one that override the default one.

It works.

Problems: the picture is scaled but instead of having the new scaled texture at 0,0
I get it anchored to bottom left of the original boundaries.


I don’t understand why…
I also don’t understand the reason of the flipping
vTexCoord = vec2 (aTexCoord.x, 1.0-aTexCoord.y); // flip y
since if I set vTexCoord = aTexCoord the result is EXACTLY the same

Second problem:
I’ve tried to parametrize the scaling
Basically I wrote this

		var vertex = "
		attribute vec4 aPosition;
		attribute vec2 aTexCoord;
		varying vec2 vTexCoord;

		uniform mat4 uMatrix;
		uniform float uScale;

		void main (void) {

			vTexCoord = vec2 (aTexCoord.x, 1.0-aTexCoord.y); // flip y
			vec4 a = aPosition;
			gl_Position = uMatrix * a;


And then I pass to the composite function the parameter

    bp = ShaderCompositing.compositeParams(composite, shader,
[{name: "uScale", value: scale, type: Float}]);

I know this was intended for the Fragment Shader
but I don’t see why it doesn’t work for the Vertex Shader as well since it is the same GLProgram.
Am I missing something?
The result is always no image (like if uScale is == 0.0 and the scaling is factor 0)

Third problem:

I need in the end to CROP the bitmapData (or to get selective part of the GLView to the BitmapData)
Like customizing this to the resulting size.

GL.readPixels (0, 0, group.width, group.height, GL.RGBA, GL.UNSIGNED_BYTE, result_rgba);

It is early to think about this now. I have some ideas how to solve it efficiently anyway.

PS: I know I can scale the Bitmap with OpenFL instead of OpenGL, but there is no comparison in the results. The OpenGL scaling is way better and smoother.

Only made a really really quick read of your post so I may answer completely wrong,
but what about initing it at 0.25 of the size?
ShaderCompositing.init (bitmapdata.width*0.25, bitmapdata.height*0.25);

If I remember correctly that should only change the size of the framebuffer,
so you’d get back only the part with your scaled down image (or another corner if we’re unlucky).

OpenGL’s origin is at the bottom left by default, not the top left. If you want to change this, either invert the viewport or the projection matrix.

I would suggest that you try ibilon’s method. Initializing the ShaderCompositing with different sizes, and uses the default vertex shader and the simplest fragment shader

varying vec2 vTexCoord;
uniform sampler2D uImage0;
void main (void)
    gl_FragColor = texture2D(uImage0, vTexCoord);

And since vTexCoord is from 0-1 anyways, you will get an image that is scaled to the size you ve initialized (presumably). And then just position the bitmapData anywhere you want.

All right.
That was the right track!

All I needed was to force the viewport set like this in the code
GL.viewport (0, 0, group.width, group.height);
to my maxWidth and minWidth given to the init

The vertex and fragment can be standard pass-thru (or actually this can be done at the same time as the fxaa I was applying before)

Thanks to everybody and sorry if I am so bloody newbie on OpenGL.

Have a good one.

Hi @yupswing, do you think your implementation of scaling by shader could be made more generally available? Maybe as a library for OpenFL or Haxe?

I created an issue for my request yesterday, but found your topic here just now :stuck_out_tongue:

It is a class you can use yourself :wink:
You can find it here.

Here’s an easy example to use it by yourself to scale.
I haven’t test it but it should work.

// Let's assume your original picture is
// in the variable source:BitmapData

//Know if OpenGL is supported
var supportOpenGL = openfl.display.OpenGLView.isSupported;

var output:BitmapData = source;
var scaleFactor:Float = 0.5; //50%

if (supportOpenGL) {
    output = postfx.PostFX.scale(source, scaleFactor);

Hmm it has compile errors, both for Legacy and Next :frowning:

Is the project up-to-date for Lime and OpenFL?

Obviously not, it is code not maintained written one year ago.

Oh well. Looking into fixing it would take me longer than I have :stuck_out_tongue: Thank you for offering up your code, maybe sometime later I’ll get around to looking into getting it to work with current Lime and OpenFL :slight_smile: