EvelynEve Posted June 28, 2016 Share Posted June 28, 2016 I'm rather new to Pixi.js, so please bear with me! I'm converting WebGL into Pixi due to a number of factors. In the WebGL code, we use a shader to "scale" or "zoom" in on relevant data. When I made this into a custom filter, it caused a lot of blurry lines (using Graphics objects to draw a bunch of non-static lines, real time data) and makes it unusable. This was not the case in WebGL, which simply draws the points at their relative locations (the shader is just normalizing these points around the min/max of the data). Am I doing something wrong or should I be doing something differently? Here is the relevant snippet of code for the shader: float xNorm = (aVertexPosition.x - xMin) / (xMax - xMin); float yNorm = (aVertexPosition.y - yMin) / (yMax - yMin); gl_Position = vec4( xNorm * 2.0 - 1.0, yNorm * 2.0 - 1.0, 0.0, 1.0); Thank you for any help or advice! Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted June 28, 2016 Share Posted June 28, 2016 That is big problem, but I studied it. The best way to get that data is to multiply by some matrix. If you are talking about custom filters, please look at their code and which matrices do they use, which helper methods provide them. Please use DisplacementFilter and TwistFilter as a reference. You dont have to calculate the matrix or all these yMax/yMin values, just find already existant helper method that provides it. One of the main problems is that target framebuffer for a filter in pixi-v4 is power-of-two texture and its larger than your working area. Please checkout latest version from DEV branch to find that code: https://github.com/pixijs/pixi.js/tree/dev And may "filterTransforms.js" be with you. Quote Link to comment Share on other sites More sharing options...
EvelynEve Posted June 28, 2016 Author Share Posted June 28, 2016 Hello. I figured there was some matrix transformation method I was just missing. As I said before, the filter works just fine. It does what I expect it to do in terms of scaling/zooming the data correctly. The issue is that it becomes too blurry/the quality degrades on the graphics object. I'm not sure what you mean by the target framebuffer. Could you please clarify? EDIT: Also the way we're handling the xMin/xMax values are important to the functionality of the overall ... object? Game? Module? Not sure what to call it haha. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted June 28, 2016 Share Posted June 28, 2016 Filter manager pools pow2 framebuffers, so when you render 400x400 container with 6 padding, it takes 512x512 texture instead of 412x412. That changes gl_Position. If you really need xMin/xMax , you make it two points "min" and "max" and apply some matrix to them. You may show me screenshots of original and pixi demos, I cant figure out what's your problem yet. All words I wrote are just my experience with it Quote Link to comment Share on other sites More sharing options...
EvelynEve Posted June 28, 2016 Author Share Posted June 28, 2016 10 minutes ago, ivan.popelyshev said: Filter manager pools pow2 framebuffers, so when you render 400x400 container with 6 padding, it takes 512x512 texture instead of 412x412. That changes gl_Position. If you really need xMin/xMax , you make it two points "min" and "max" and apply some matrix to them. You may show me screenshots of original and pixi demos, I cant figure out what's your problem yet. All I wrote are just my experience with it I think I understand. I'm still no closer to understanding where that matrix transformation should be happening. Here is the picture of what it looked like before: And this is what it looks like with pixi (minus some padding that is added to the before picture that I hadn't gotten around to doing in the after picture yet): Quote Link to comment Share on other sites More sharing options...
EvelynEve Posted June 28, 2016 Author Share Posted June 28, 2016 @ivan.popelyshev suggested I try overriding the primitive shader to get the desired effect. I did so with some slight modifications to allow the translations and now don't see anything. Here is the shader I am using: function PrimitiveShader(shaderManager) { Shader.call(this, shaderManager, // vertex shader [ 'attribute vec2 aVertexPosition;', 'attribute vec4 aColor;', 'uniform mat3 translationMatrix;', 'uniform mat3 projectionMatrix;', 'uniform float xMin;', 'uniform float xMax;', 'uniform float yMin;', 'uniform float yMax;', 'uniform float alpha;', 'uniform float flipY;', 'uniform vec3 tint;', 'varying vec4 vColor;', 'void main(void) {', 'float xNorm = (aVertexPosition.x - xMin) / (xMax - xMin);', 'float yNorm = (aVertexPosition.y - yMin) / (yMax - yMin);', 'gl_PointSize = 8.0;', 'gl_Position = vec4(', '(projectionMatrix * translationMatrix * ' + 'vec3(' + 'xNorm * 2.0 - 1.0,' + 'yNorm * 2.0 - 1.0,' + '1.0)).xy,', '0.0,', '1.0);', 'vColor = aColor * vec4(tint * alpha, alpha);', '}' ].join('\n'), // [ // 'attribute vec2 aVertexPosition;', // 'attribute vec4 aColor;', // // 'uniform mat3 translationMatrix;', // 'uniform mat3 projectionMatrix;', // // 'uniform float alpha;', // 'uniform float flipY;', // 'uniform vec3 tint;', // // 'varying vec4 vColor;', // // 'void main(void){', // ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', // ' vColor = aColor * vec4(tint * alpha, alpha);', // '}' // ].join('\n'), // fragment shader [ 'precision mediump float;', 'varying vec4 vColor;', 'void main(void){', ' gl_FragColor = vColor;', '}' ].join('\n'), // custom uniforms { tint: { type: '3f', value: [0, 0, 0] }, alpha: { type: '1f', value: 0 }, translationMatrix: { type: 'mat3', value: new Float32Array(9) }, projectionMatrix: { type: 'mat3', value: new Float32Array(9) }, xMin: { type: 'f', value: 0 }, xMax: { type: 'f', value: 100 }, yMin: { type: 'f', value: 0 }, yMax: { type: 'f', value: 100 } }, // custom attributes { aVertexPosition:0, aColor:0 } ); } This is what I am seeing: This is what I see if I allow the original shader to run: And this is what I am expecting to see (more or less): Does anyone have any advice? Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted June 28, 2016 Share Posted June 28, 2016 I believe that yours minX, maxX things can be embedded into matrices (projectionMatrix and translationMatrix). Can you just position your Graphics element that way it fits (0, 0) - (renderer.width, renderer.height) ? PIXI projects (0,0)-(renderer.width,renderer.height) to (-1,-1)-(1,1) and that's what projectionMatrix for. You can change Graphics position and scale that way (minX,minY)-(maxX,maxY) will be transformed into (0,0)-(renderer.width,renderer.height) by translationMatrix. Quote Link to comment Share on other sites More sharing options...
EvelynEve Posted June 28, 2016 Author Share Posted June 28, 2016 4 minutes ago, ivan.popelyshev said: I believe that yours minX, maxX things can be embedded into matrices (projectionMatrix and translationMatrix). Can you just position your Graphics element that way it fits (0, 0) - (renderer.width, renderer.height) ? PIXI projects (0,0)-(renderer.width,renderer.height) to (-1,-1)-(1,1) and that's what projectionMatrix for. You can change Graphics position and scale that way (minX,minY)-(maxX,maxY) will be transformed into (0,0)-(renderer.width,renderer.height) by translationMatrix. Could you point me to some resources about the projection matrix so I can better understand what value is where for manipulation? I understand you're saying to just throw it in there, but the question is where and how. I can't find anything about it beyond people mentioning it exists and code references within the source. Preferably a tutorial with some examples of projection matrix transformations. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted June 28, 2016 Share Posted June 28, 2016 8 minutes ago, EvelynEve said: Could you point me to some resources about the projection matrix so I can better understand what value is where for manipulation? I understand you're saying to just throw it in there, but the question is where and how. I can't find anything about it beyond people mentioning it exists and code references within the source. Preferably a tutorial with some examples of projection matrix transformations. Basically, if you multiply your result by projectionMatrix, then you can use SCREEN coordinates (0,0)-(renderer.width, renderer.height) instead of standart webgl (-1,-1) - (1,1) , (btw, its reverted by Y axis) If you want to move graphics around, use its position and scale, that will modify translationMatrix. If you want just animate some lines, do it in SCREEN coordinates, forget about your min-max stuff. Quote Link to comment Share on other sites More sharing options...
EvelynEve Posted June 28, 2016 Author Share Posted June 28, 2016 1 minute ago, ivan.popelyshev said: Basically, if you multiply your result by projectionMatrix, then you can use SCREEN coordinates (0,0)-(renderer.width, renderer.height) instead of standart webgl (-1,-1) - (1,1) If you want to move graphics around, use its position and scale. If you want just animate some lines, do it in SCREEN coordinates, forget about your min-max stuff. The problem is the data sets I am using. I can't use screen coordinates, I need to use WebGL coordinates. I can't forget the min/max stuff, it's the whole reason the program even works. I'm not really sure what you mean by result (vague). I have been trying to scale and the scaling has the same problems as the filters. It doesn't fix anything and I'm pretty sure it's slower. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted June 28, 2016 Share Posted June 28, 2016 OK, use standart shader and graphics object, and try this: graphics.pivot.set(minX, maxY); graphics.scale.set((maxX-minX) / renderer.width, (maxY - minY) / renderer.height); Oh wait, i've got it . your lines will have wrong thickness that way. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted June 28, 2016 Share Posted June 28, 2016 You didnt say what kind of lines do you use with graphics: lines of rectangles? Anyway, you are giving too few info for me to work with. Either lets chat somewhere, either post complete code of the example. Quote Link to comment Share on other sites More sharing options...
EvelynEve Posted June 28, 2016 Author Share Posted June 28, 2016 4 minutes ago, ivan.popelyshev said: OK, use standart shader and graphics object, and try this: graphics.pivot.set(minX, maxY); graphics.scale.set((maxX-minX) / renderer.width, (maxY - minY) / renderer.height); No luck. Nothing shows up. Just a black box. EDIT: I am using a polygon to draw the array of x and y points. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted June 28, 2016 Share Posted June 28, 2016 Sorry , my bad. graphics.pivot.set(minX, maxY); graphics.scale.set((maxX-minX) / renderer.width, (minY - maxY) / renderer.height); Please post your example somewhere (jsfiddle?) Quote Link to comment Share on other sites More sharing options...
EvelynEve Posted June 28, 2016 Author Share Posted June 28, 2016 1 minute ago, ivan.popelyshev said: Sorry , my bad. graphics.pivot.set(minX, maxY); graphics.scale.set((maxX-minX) / renderer.width, (minY - maxY) / renderer.height); Please post your example somewhere (jsfiddle?) It's too large and sensitive to post somewhere, sorry. Still no luck with that. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted June 28, 2016 Share Posted June 28, 2016 graphics.pivot.set(minX, maxY); graphics.scale.set(renderer.width/(maxX-minX), renderer.height/(minY - maxY)); Please DO NOT USE that shader hack, just put all coordinates in graphics and add these two lines. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted June 28, 2016 Share Posted June 28, 2016 OK, I think you have mistaken in resizing canvas or something like that, otherwise i dont know how did you get that kind of effect on line. Please post minimal demo, just make it from scratch and post in jsfiddle. That's normal practice for consultations about sensitive stuff - you make a demo and then we fix it and show how it really must be done Quote Link to comment Share on other sites More sharing options...
EvelynEve Posted June 28, 2016 Author Share Posted June 28, 2016 6 minutes ago, ivan.popelyshev said: graphics.pivot.set(minX, maxY); graphics.scale.set(renderer.width/(maxX-minX), renderer.width/(minY - maxY)); Please do not use your shader AT ALL, just put all coordinates in graphics and add these two lines. I am not using the shader at all. I'm using the normal/default shader. These are all more or less things I have already tried to do unsuccessfully. Also, I missed the result of the last try. It gives me this: There's a teensy triangle of lines at the top. That last bit of math is better, but still has an issue with the scaling of the lines which worries me that it could cause other problems later. Much better than what was happening before though: EDIT: I'd still just prefer using my own shader, however. It's more reliable and faster. I'll be dealing with a lot of data. I'd prefer just trying to figure out why the primitive shader override is simply not working as opposed to using both scaling and setting the pivot. All the things drawn on my canvases will require this type of scaling, so I don't see it being a problem unless there is something I am missing or changes have been made to scaling which I did not read about previously. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted June 28, 2016 Share Posted June 28, 2016 OK, then I have better solution for you function getX(u) { return (u-minX) / (maxX-minX) * renderer.width; } function getY(v) { return (v-maxY) / (minY - maxY) * renderer.height; } use it every time when you pass coords to graphics. Its working differently because "graphics.lineTo(getX(x), getY(y)) wont change the width of line, while scale is actually doing it You can even hook it in graphics: make your own lineTo moveTo that will take into account your min-max transformation. Pass width and height too By the way, THATS A FREAKING AWESOME IDEA: "plotTransform" that changes point coords by does not scale lines width Quote Link to comment Share on other sites More sharing options...
EvelynEve Posted June 28, 2016 Author Share Posted June 28, 2016 9 minutes ago, ivan.popelyshev said: OK, then I have better solution for you function getX(u) { return (u-minX) / (maxX-minX) * renderer.width; } function getY(v) { return (v-maxY) / (minY - maxY) * renderer.height; } use it every time when you pass coords to graphics. Its working differently because "graphics.lineTo(getX(x), getY(y)) wont change the width of line, while scale is actually doing it You can even hook it in graphics: make your own lineTo moveTo that will take into account your min-max transformation. Pass width and height too By the way, THATS A FREAKING AWESOME IDEA: "plotTransform" that changes point coords by does not scale lines width Good idea! Unfortunately, I'm dealing with a LOT of data. I'm not using the native lineTo/moveTo methods. I am, instead, using the polygon and passing it an array of x and y coordinates, as I mentioned before. Sadly, that would be a LOT of extra load to process, which is why I was hoping to just do it via GPU shaders that can leave the CPU alone. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted June 28, 2016 Share Posted June 28, 2016 The problem with lines in Graphics - they do not exist. Every stroked line is made of triangles, because lineWidth needs to be taken into account. Did you use gl.LINES in original code? If so, then I can help you to make an object (not graphics!) with its own renderer and shader that will do it. Anyway, can we please move it to chat? please send me your email in PM, I wlil add you to pixi slack and we'll solve your issue Quote Link to comment Share on other sites More sharing options...
EvelynEve Posted June 28, 2016 Author Share Posted June 28, 2016 Just now, ivan.popelyshev said: The problem with lines in Graphics - they do not exist. Every stroked line is made of triangles, because lineWidth needs to be taken into account. Did you use gl.LINES in original code? If so, then I can help you to make an object (not graphics!) with its own renderer and shader that will do it. Yes. I know that. I did originally use gl.LINES. If you have any resources you could point me to, I would greatly appreciate it. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted June 28, 2016 Share Posted June 28, 2016 We can copy src/Mesh and make a thing that works with your data, it wont be that difficult Do you want me to do it? That way you'll have super-speedy webgl solution that will beat your original solution by usability Quote Link to comment Share on other sites More sharing options...
EvelynEve Posted June 28, 2016 Author Share Posted June 28, 2016 Just now, ivan.popelyshev said: We can copy src/Mesh and make a thing that works with your data, it wont be that difficult Do you want me to do it? That way you'll have super-speedy webgl solution that will beat your original solution by usability I'd prefer to do it myself since I need to know how to use this stuff. Are you think of copying Mesh.js or is there another file I should be looking at? Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted June 28, 2016 Share Posted June 28, 2016 1. copy the mesh, name it "MegaLine". You can use the same shader as mesh. just call gl.LINES instead of gl.TRIANGLES. You can even hack original mesh that way it can choose between LINES and TRIANGLES. you can pass empty array as uvs. 2. make a container , use that trick: plotContainer.pivot.set(minX, maxY); plotContainer.scale.set(renderer.width / (maxX-minX), renderer.height / (minY - maxY)); 3. for every plot line, add a modified mesh inside the container. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.