简体   繁体   中英

openGL reverse image texturing logic

I'm about to project image into cylindrical panorama. But first I need to get the pixel (or color from pixel) I'm going to draw, then then do some Math in shaders with polar coordinates to get new position of pixel and then finally draw pixel.

Using this way I'll be able to change shape of image from polygon shape to whatever I want.

But I cannot find anything about this method (get pixel first, then do the Math and get new position for pixel).
Is there something like this, please?

OpenGL historically doesn't work that way around; it forward renders — from geometry to pixels — rather than backwards — from pixel to geometry.

The most natural way to achieve what you want to do is to calculate texture coordinates based on geometry, then render as usual. For a cylindrical mapping:

  • establish a mapping from cylindrical coordinates to texture coordinates;
  • with your actual geometry, imagine it placed within the cylinder, then from each vertex proceed along the normal until you intersect the cylinder. Use that location to determine the texture coordinate for the original vertex.

The latter is most easily and conveniently done within your geometry shader; it's a simple ray intersection test, with attributes therefore being only vertex location and vertex normal, and texture location being a varying that is calculated purely from the location and normal.

Extemporaneously, something like:

// get intersection as if ray hits the circular region of the cylinder,
// i.e. where |(position + n*normal).xy| = 1
float planarLengthOfPosition = length(position.xy);
float planarLengthOfNormal = length(normal.xy);
float planarDistanceToPerimeter = 1.0 - planarLengthOfNormal;
vec3 circularIntersection = position + 
                            (planarDistanceToPerimeter/planarLengthOfNormal)*normal;

// get intersection as if ray hits the bottom or top of the cylinder,
// i.e. where |(position + n*normal).z| = 1
float linearLengthOfPosition = abs(position.z);
float linearLengthOfNormal = abs(normal.z);
float linearDistanceToEdge = 1.0 - linearLengthOfPosition;
vec3 endIntersection = position +
                       (linearDistanceToEdge/linearLengthOfNormal)*normal;

// pick whichever of those was lesser
vec3 cylindricalIntersection = mix(circularIntersection,
                                   endIntersection,
                                   step(linearDistanceToEdge, 
                                        planarDistanceToPerimeter));

// ... do something to map cylindrical intersection to texture coordinates ...
textureCoordinateVarying = 
    coordinateFromCylindricalPosition(cylindricalIntersection);

With a common implementation of coordinateFromCylindricalPosition possibly being simply return vec2(atan(cylindricalIntersection.y, cylindricalIntersection.x) / 6.28318530717959, cylindricalIntersection.z * 0.5); .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM