Skip to main content
GameDev.net gamedev.net
🔒 Locked

Fluid Dynamics via GPU Woes

Started by kiplingw Feb 8, 2010 at 8:17 PM 4 replies 1.1k views
Original Post
kiplingw
kiplingw
I have a 2D array allocated as a 1D array (pGridLocations). This array represents the points on a flat 2D grid. Each point is a pair of GLuints (e.g. bottom left is (0,0), top right is point (width,height)). They are all integral values. I want to pass this array of pairs to my shader where I do some fancy calculations and write out the results to a texture (bound via FBO) of the same width / height as the grid dimensions. Each texel (I use only single channel) contains a Z-displacement value of the wave at that position on surface. I am finding though that getting my pairs into the shader is very difficult and I've gone through a lot of documentation and cannot seem to get it to work. Whether the glDrawArrays is called or not, the buffer seems to contain the same junk. Here is where I initialize the pairs:

    // Initialize grid location pairs...

        // Calculate required storage space for all location pairs...
        GLuint const Storage = m_Width * m_Height * sizeof(GLuint) * 2;

        // Allocate...
        GLuint *pGridLocations = (GLuint *) malloc(Storage);

        // Initialize vertex ordinals across the grid...
        for(GLuint CurrentY = 0; CurrentY < m_Height; ++CurrentY)
            for(GLuint CurrentX = 0; CurrentX < m_Width; ++CurrentX)
            {
                // Calculate current location...
                GLuint *pCurrentLocation =
                    pGridLocations + (2 * ((CurrentY * m_Width) + CurrentX));

                // Store grid index...
                pCurrentLocation[0] = CurrentX;
                pCurrentLocation[1] = CurrentY;
            }

        // Initialize vertex buffer object with vertex pairs...

            // Allocate...
            glGenBuffers(1, &m_VBO_GridLocations);

            // Select...
            glBindBuffer(GL_ARRAY_BUFFER, m_VBO_GridLocations);

            // Commit grid indices to card...
            glBufferData(GL_ARRAY_BUFFER, Storage, pGridLocations, GL_STATIC_DRAW);

            // Associate data with generic vertex attribute...
            glVertexAttribIPointer(m_GVA_GridLocations, 2, GL_UNSIGNED_INT, 0, BufferOffset(0));
Here is where I try to pass the data to the shader:

    // Redirect rendering through our framebuffer object...
    glBindFramebuffer(GL_FRAMEBUFFER, m_FrameBufferObject);

        // Check for OpenGL errors...
        PrintOpenGLErrors();

    // Make sure data written to texture replaces and doesn't just modulate...
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

    // Send grid location data to program...

        // Install program...
        glUseProgram(m_PO_EvaluateWaves);

        // Select the Z map texture...
        glBindTexture(GL_TEXTURE_2D, m_ZMaps_TextureID[0]);

        // Enable required vertex arrays...
        glEnableVertexAttribArray(m_GVA_GridLocations);

        // Select the grid indices...
        glBindBuffer(GL_ARRAY_BUFFER, m_VBO_GridLocations);

        // Commit data to shader...
        glDrawArrays(GL_POINTS, 0, m_Width * m_Height);

        // Disable required vertex arrays...
        glDisableVertexAttribArray(m_GVA_GridLocations);
My vertex shader tries to receive the pairs as

in uvec2 GridLocation;
And it just passes a zero or some other test value on to the fragment shader which then writes it to the logical buffer GL_COLOR_ATTACHMENT0, but nothing happens. I've been stumped on this for days and any help would be much appreciated. Kip
kiplingw
kiplingw
So I tried using GLfloat instead of GLint, to no avail. Nothing different was observed.

I tried someone else's advice and commented out the glDrawArrays() call and replaced it with this...

glBegin(GL_QUADS);    glVertex2i(-m_Width / 2, -m_Height / 2);    glVertex2i(m_Width / 2, -m_Height / 2);    glVertex2i(m_Width / 2, m_Height / 2);    glVertex2i(-m_Width / 2, m_Height / 2);glEnd();


When I read back from the framebuffer, it's the same junk still. I can verify that because whatever I write to the framebuffer before with glClearColor() / glClear() is all I get back. Very frustrating, but thanks so far for your help.

Kip
klee1
klee1
If you have a new nvidia card on your computer, you might be able to use CUDA or OpenCL as a way to do your processing on the GPU. However as neither CUDA or OpenCL are that widely supported as of yet, you might be limiting your game to the select few who have the graphics cards.

OpenCL is _supposed_ to be able to be run on multiple targets eventually.
kiplingw
kiplingw
Thanks man. I would have considered it, but right now I don't have time to learn another API. Moreover, like you say, it's an additional dependency whose support for the end users is still sketchy. What I am trying to do really shouldn't be so hard, but for some crazy reason it is. I guess I just don't know what I am doing and it is hard to find accurate documentation and tutorials that doesn't have deprecated APIs.

Kip
kiplingw
kiplingw
I updated the vertex and fragment shaders to the following, but still no luck.

Vertex shader:
// We want at least GLSL 1.50...#version 150// Input variables...    // Grid location...    in uvec2            GridLocation;// Variables for the fragment shader, none of which need be interpolated...    // Grid location...    flat out uvec2      Location;// Entry point...void main(){    Location = GridLocation;}


Fragment shader:
// We want at least GLSL 1.50...#version 150// Input variables...    // Grid location...    flat in uvec2   Location;// Output variables...    // Z-displacement...    out float       StoredZ_0;// Entry point...void main(){    float temp = min(float(Location.x), 0.5);    temp = max(temp, 0.5);    StoredZ_0 = temp;}


Still same junk in the framebuffer's colour attachment.

Kip

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.