简体   繁体   中英

How do I get a calculation result from a shader?

I load a 3D-model from a file and need to see it all on my screen. All vertices should be on the screen within the main window. Then I rotate and zoom the model and at some point I would like to fit the model to the window again. So, I have written the function OptimiseView (see below) which multiplies the view matrix by each vertex position and then calculates minimum and maximum coordinates of the screen plane.

The above multiplication takes a lot of time. My shader does the same multiplication but I can't manage to store minimum and maximum coordinates in the shader (GPU) and return these values back to the program (CPU) after processing the last vertex.

Is this possible at all? How do CAD-systems implement this Fit View (Optimise View) feature? How does a space mouse (eg 3Dconnexion) work in this relation?

I am currently using C++ and OpenGL.

void OptimiseView(glm::mat4& view, glm::mat4* proj, int trianglesNumber, float* positions)
{
    if ((rotAngleX != 0) || (rotAngleY != 0) || (mouseScroll != 0))
    {
        float minX, maxX, minY, maxY, minZ, maxZ;
        float centreX, centreY;
        float largestDimension;

        int triangleCount{ 0 };

        glm::vec4 vertexPosition;

        if (trianglesNumber < 1)
        {
            minX = maxX = minY = maxY = minZ = maxZ = 0;
        }
        else
        {
            vertexPosition = view * glm::vec4(
                positions[0],
                positions[1],
                positions[2],
                1.0f);

            minX = maxX = vertexPosition.x;
            minY = maxY = vertexPosition.y;
            minZ = maxZ = vertexPosition.z;
        }

        while (triangleCount < trianglesNumber)
        {
            for (int initialPosition : {0, 3, 9})
            {
                vertexPosition = view * glm::vec4(
                    positions[triangleCount * 9 * 2 + initialPosition],
                    positions[triangleCount * 9 * 2 + initialPosition + 1],
                    positions[triangleCount * 9 * 2 + initialPosition + 2],
                    1.0f);

                if (vertexPosition.x < minX) minX = vertexPosition.x;
                if (vertexPosition.x > maxX) maxX = vertexPosition.x;

                if (vertexPosition.y < minY) minY = vertexPosition.y;
                if (vertexPosition.y > maxY) maxY = vertexPosition.y;

                if (vertexPosition.z < minZ) minZ = vertexPosition.z;
                if (vertexPosition.z > maxZ) maxZ = vertexPosition.z;
            }
            triangleCount++;
        }

        centreX = minX + (maxX - minX) / 2.0f;
        centreY = minY + (maxY - minY) / 2.0f;
        largestDimension = ((maxX - minX) >= (maxY - minY)) ? (maxX - minX) : (maxY - minY);

        minX = centreX - largestDimension / 2.0f;
        maxX = centreX + largestDimension / 2.0f;

        minY = centreY - largestDimension / 2.0f;
        maxY = centreY + largestDimension / 2.0f;

        *proj = glm::ortho(minX, maxX, minY, maxY, -minZ, -maxZ);
    }
}

I have also tried to use global variables in the shader but they seem to store values during processing a single vertex only.

I know the Fit View feature already works in different CAD-systems and am just wondering what approach would be the best.

Thanks.

After more deep research, I found the OpenGL thing which is called 'Transform Feedback'. The best practical manual and the answer to my question is here .

More information is here .

It will also be useful to read the book of Sam Buss ' 3D Computer Graphics: A mathematical approach with OpenGL .' It contains a lot of examples on using different OpenGL functions.

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