Syntopia
|
|
« Reply #15 on: August 11, 2013, 12:11:11 AM » |
|
modelViewProjectMatrixInverse.multiplyMatrices(camera.matrixWorldInverse, mesh.matrixWorld).multiply(camera.projectionMatrix) The order seems wrong: I think the matrix you need to invert is: camera.projectionMatrix * camera.matrixWorldInverse * mesh.matrixWorld
|
|
|
Logged
|
|
|
|
itistoday
Forums Freshman
Posts: 15
|
|
« Reply #16 on: August 11, 2013, 12:14:21 AM » |
|
The order seems wrong: I think the matrix you need to invert is: camera.projectionMatrix * camera.matrixWorldInverse * mesh.matrixWorld In what order should that be done? Also, one thing to keep in mind is that the controls do not update the camera's position, but the object's. The camera's position stays fixed, but because the model is being moved and rotated, it gives the illusion that the camera is flying around.
|
|
|
Logged
|
|
|
|
itistoday
Forums Freshman
Posts: 15
|
|
« Reply #17 on: August 11, 2013, 12:20:56 AM » |
|
In what order should that be done?
Also, one thing to keep in mind is that the controls do not update the camera's position, but the object's. The camera's position stays fixed, but because the model is being moved and rotated, it gives the illusion that the camera is flying around.
I just tried multiplying it like this: modelViewProjectMatrixInverse.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse).multiply(mesh.matrixWorld); And that didn't fix it, it just made the controls super sensitive. I'll mention this again just in case you didn't see it, as I think it's what's causing the problem: "Also, one thing to keep in mind is that the controls do not update the camera's position, but the object's. The camera's position stays fixed, but because the model is being moved and rotated, it gives the illusion that the camera is flying around."
|
|
|
Logged
|
|
|
|
itistoday
Forums Freshman
Posts: 15
|
|
« Reply #18 on: August 11, 2013, 01:09:50 AM » |
|
I'm thinking that perhaps somewhere in the vertex shader something along these lines needs to be done: vec4 WPpos = modelViewProjectMatrixInverse * gl_Position; WPpos /= WPpos.w; rayDir = WPpos.xyz - modelMatrix[3].xyz; In otherwords, making use of "modelMatrix[3].xyz" instead of the camera position to figure out the ray direction, because the camera position is a constant. None of my foolings-around have made anything that looks correct, however. EDIT: of course, there's also this: rayDir = (modelViewMatrix * gl_Position).xyz; But that just produces the same strange warped scaling effect when you rotate.
|
|
« Last Edit: August 11, 2013, 01:29:10 AM by itistoday »
|
Logged
|
|
|
|
Syntopia
|
|
« Reply #19 on: August 11, 2013, 09:03:07 AM » |
|
In what order should that be done?
In the order stated. Matrix multiplication is associative, so (AB)C=A(BC) Also, one thing to keep in mind is that the controls do not update the camera's position, but the object's. The camera's position stays fixed, but because the model is being moved and rotated, it gives the illusion that the camera is flying around.
I think you should use FlyControls on the camera instead of the object. Btw, looking at your code, I realized this is based on Tom Beddards PixelBender script. Be sure to include his copyright notice and license conditions in your shader code.
|
|
|
Logged
|
|
|
|
itistoday
Forums Freshman
Posts: 15
|
|
« Reply #20 on: August 11, 2013, 04:13:11 PM » |
|
In the order stated. Matrix multiplication is associative, so (AB)C=A(BC) K, I was wondering whether to read it from left-to-right or right-to-left. I assume you meant left-to-right. I think you should use FlyControls on the camera instead of the object. Yes, I was doing that originally but because things weren't working very well I changed it (and it improved the situation, but did not fix other problems). Changing the controls to manipulate the camera has fixed the crazy stretching problem! The problem now is that for some reason movement via the controls is very jittery. Try it out.. I'm not sure why this is happening. Any more help appreciated! It's almost perfect. I decided to remove the phasing for now (you can add it back by editing the fragment shader) because it's just too ugly with the DE function from your blog and the one here on the forums, but I'd rather use those because they're much faster. Btw, looking at your code, I realized this is based on Tom Beddards PixelBender script. Be sure to include his copyright notice and license conditions in your shader code. Thanks for pointing that out! I had a link to the original file where you could find the copyright notice but at your suggestion I've copied that into the file itself. Note that the original file doesn't include the license conditions verbatim either, but rather a link to the MIT license.
|
|
|
Logged
|
|
|
|
itistoday
Forums Freshman
Posts: 15
|
|
« Reply #21 on: August 11, 2013, 04:43:52 PM » |
|
One observation: the epileptic jitteriness is only caused by the WASD keys that affect the position/translation of the object, while the arrow keys, which only affect the rotation, do not cause any jitteriness.
|
|
|
Logged
|
|
|
|
knighty
Fractal Iambus
Posts: 819
|
|
« Reply #22 on: August 11, 2013, 09:15:28 PM » |
|
Yay! it works! i've modified the intersect sphere: bool intersectBoundingSphere(vec3 origin, vec3 direction, out float tmin, out float tmax) { bool hit = false;
float b = dot(origin, direction); float c = dot(origin, origin) - bounding*bounding; float disc = b*b - c; // discriminant tmin = tmax = 0.0;
if (disc > 0.0) { // Real root of disc, so intersection float sdisc = sqrt(disc); tmin=max(0.,-b - sdisc);//DE(origin + max(0.,t0) * direction, min_dist);// tmax=max(0.,-b + sdisc);//max(0.,t0)+t1; hit = true; }
return hit; } This way the value of ray_length is correct and the details change while zooming is even and the fractal doesn't disapear when far away. But one have to change the value of min_dist to 2. for example (in renderPixel function). It doesn't work when min_dist==4. Strange!
|
|
|
Logged
|
|
|
|
itistoday
Forums Freshman
Posts: 15
|
|
« Reply #23 on: August 12, 2013, 02:02:36 AM » |
|
Yay! it works! i've modified the intersect sphere: bool intersectBoundingSphere(vec3 origin, vec3 direction, out float tmin, out float tmax) { bool hit = false;
float b = dot(origin, direction); float c = dot(origin, origin) - bounding*bounding; float disc = b*b - c; // discriminant tmin = tmax = 0.0;
if (disc > 0.0) { // Real root of disc, so intersection float sdisc = sqrt(disc); tmin=max(0.,-b - sdisc);//DE(origin + max(0.,t0) * direction, min_dist);// tmax=max(0.,-b + sdisc);//max(0.,t0)+t1; hit = true; }
return hit; } This way the value of ray_length is correct and the details change while zooming is even and the fractal doesn't disapear when far away. But one have to change the value of min_dist to 2. for example (in renderPixel function). It doesn't work when min_dist==4. Strange! Awesome! Thanks knighty! :-D I've updated the source and have added your changes. I've also fixed the jitteriness problem! The problem was that the camera's matrixWorldInverse and the mesh's matrixWorld were getting out of sync, thus creating an out of sync value for modelViewProjectMatrixInverse. When controls.update is called, it updates the "matrix" value of the camera (but NOT its matrixWorld or matrixWorldInverse values). Then modelViewProjectMatrixInverse was set using those values, and then the renderer.render function was called. In the render function, however, all of the matrixWorld's and matrixWorldInverse were set to the updated values, but our modelViewProjectMatrixInverse was set using the previous values, thus making it out of sync, yet it was multiplied by the updated vertex values. So to fix this we have to update the matrices ourselves before calling render: function render() { controls.update( clock.getDelta() );
// BUG!! in three.js (at least r59). we need to calculate the // matrixWorldInverse here ourselves, otherwise we'll get a // jittery effect. camera.updateMatrixWorld(); camera.matrixWorldInverse.getInverse( camera.matrixWorld );
uniforms.time.value += 0.05; modelViewProjectMatrixInverse.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse).multiply(mesh.matrixWorld); modelViewProjectMatrixInverse.getInverse(modelViewProjectMatrixInverse); uniforms.modelViewProjectMatrixInverse.value = modelViewProjectMatrixInverse; renderer.render( scene, camera ); } Also, I've updated the source code comments to give thanks to all of you for helping me with this! Thanks a ton for your help! There's only really one major problem now (and one "wish I could have"): - You can't fly into the Mandelbulb. If you get too close, the camera will fly off into space for some reason. - It would be nice if we could have the neat phasing effects that the original DE function supported while still having the same fast framerate. Link, as always: http://www.kinostudios.com/mandelbulb.html
|
|
|
Logged
|
|
|
|
itistoday
Forums Freshman
Posts: 15
|
|
« Reply #24 on: August 12, 2013, 02:33:35 AM » |
|
It's a lot of fun to color it too. If you enable the phase and use the original DE function, it can look really neat. I found that right at the end of the color function, before the pixel_color.a = 1.0; line, you can insert random equations and get very neat (and surprising results). Like this one (not safe for epileptics!): pixel_color.g /= cos(pow(sin(phase.x),phase.y)); pixel_color.r *= -ray_length -dist * tan(pow(phase.x, pixel_color.g)); pixel_color.b /= DE(ray, dist)* sin(phase.y) ; pixel_color.a = 1.0; And this one: pixel_color.g /= cos(pow(sin(phase.x),phase.y)); pixel_color.r /= tan(pow(float(i), cos(float(i)))); pixel_color.b /= sin(pow(phase.y, sin(phase.y))); pixel_color.a = 1.0; Which produces a neat swirling rose-like effect: If you find any particularly interesting combinations, let me know! If I had all the time in the world I'd implement adding color presets.
|
|
« Last Edit: August 12, 2013, 02:40:27 AM by itistoday »
|
Logged
|
|
|
|
knighty
Fractal Iambus
Posts: 819
|
|
« Reply #25 on: August 12, 2013, 09:56:31 PM » |
|
I's almost perfect now . Maybe it needs a log window to display shaders errors and warnings. Here is a modification of eiffie's code to make it look like subblue's DE_original. pahse also looks the same: // FROM: http://www.fractalforums.com/index.php?topic=16793.msg64299#msg64299 float DE(vec3 z0, inout float min_dist){//MandelBulb by twinbee vec4 z = vec4(z0,1.0), c = z; float r = length(z.xyz),zr,theta,phi,p=power;//p is the power phi = atan(z.y, z.x) * p;// th = atan(z.y, z.x) + phase.x; ...and here theta = asin(z.z / r) * p;// ph = acos(z.z / r) + phase.y; add phase shifts here min_dist = min(min_dist, r); for (int n = 0; n < MAX_ITERATIONS; n++) { zr = pow(r, p-1.0); z=zr*vec4(r*vec3(sin(theta)*vec2(cos(phi),sin(phi)),cos(theta)),z.w*p)+c; // this version was from the forums r = length(z.xyz); min_dist = min(min_dist, r); if (r > bailout) break; phi = (atan(z.y, z.x) + phase.x) * p;// th = atan(z.y, z.x) + phase.x; ...and here theta = (acos(z.z / r) + phase.y) * p;// ph = acos(z.z / r) + phase.y; add phase shifts here } return 0.5 * log(r) * r / z.w; } (I think it will look better with lower pixel_scale values.) For the interior, infortunately the DE formula doesn't really work inside. It's an open problem. As noticed by visual.bermarte, you can still use the DE (especially those based on scalar derivative like the one above) to dive inside but: - The DE is negative inside so you need to modify the code in order to take this into account. - It's not perfect at all: epsilonScale have to be smaller than one. - It's still not perfect at all.
|
|
|
Logged
|
|
|
|
itistoday
Forums Freshman
Posts: 15
|
|
« Reply #26 on: August 12, 2013, 11:47:08 PM » |
|
I's almost perfect now . Maybe it needs a log window to display shaders errors and warnings. Here is a modification of eiffie's code to make it look like subblue's DE_original. pahse also looks the same: // FROM: http://www.fractalforums.com/index.php?topic=16793.msg64299#msg64299 float DE(vec3 z0, inout float min_dist){//MandelBulb by twinbee vec4 z = vec4(z0,1.0), c = z; float r = length(z.xyz),zr,theta,phi,p=power;//p is the power phi = atan(z.y, z.x) * p;// th = atan(z.y, z.x) + phase.x; ...and here theta = asin(z.z / r) * p;// ph = acos(z.z / r) + phase.y; add phase shifts here min_dist = min(min_dist, r); for (int n = 0; n < MAX_ITERATIONS; n++) { zr = pow(r, p-1.0); z=zr*vec4(r*vec3(sin(theta)*vec2(cos(phi),sin(phi)),cos(theta)),z.w*p)+c; // this version was from the forums r = length(z.xyz); min_dist = min(min_dist, r); if (r > bailout) break; phi = (atan(z.y, z.x) + phase.x) * p;// th = atan(z.y, z.x) + phase.x; ...and here theta = (acos(z.z / r) + phase.y) * p;// ph = acos(z.z / r) + phase.y; add phase shifts here } return 0.5 * log(r) * r / z.w; } (I think it will look better with lower pixel_scale values.) For the interior, infortunately the DE formula doesn't really work inside. It's an open problem. As noticed by visual.bermarte, you can still use the DE (especially those based on scalar derivative like the one above) to dive inside but: - The DE is negative inside so you need to modify the code in order to take this into account. - It's not perfect at all: epsilonScale have to be smaller than one. - It's still not perfect at all. AWESOME knighty! Thanks a bunch! Exactly what I was hoping for. I've updated the code with yours and have also done a lot of cleanup. http://www.kinostudios.com/mandelbulb.html
|
|
|
Logged
|
|
|
|
|