ocean所用的蝴蝶纹理

#include <ork/render/FrameBuffer.h>
#include <ork/scenegraph/SceneManager.h>
#include <ork/ui/GlutWindow.h>
#include <pmath.h>
#include <stbi/stb_image.h>
#include <iostream>
#include <fstream>


const int FFT_SIZE = 256;
const int PASSES = 8;
const int N = 256;


int bitReverse(int i, int N)
{
    int j = i;
    int M = N;
    int Sum = 0;
    int W = 1;
    M = M / 2;
    while (M != 0) {
        j = (i & M) > M - 1;
        Sum += j * W;
        W *= 2;
        M = M / 2;
    }
    return Sum;
}
void computeWeight(int N, int k, float &Wr, float &Wi)
{
    Wr = cosl(2.0 * M_PI * k / float(N));
    Wi = sinl(2.0 * M_PI * k / float(N));
}

float *computeButterflyLookupTexture()
{
    float *data = new float[FFT_SIZE * PASSES * 4];

    for (int i = 0; i < PASSES; i++) {
        int nBlocks  = (int) powf(2.0, float(PASSES - 1 - i));
        int nHInputs = (int) powf(2.0, float(i));
        for (int j = 0; j < nBlocks; j++) {
            for (int k = 0; k < nHInputs; k++) {
                int i1, i2, j1, j2;
                if (i == 0) {
                    i1 = j * nHInputs * 2 + k;
                    i2 = j * nHInputs * 2 + nHInputs + k;
                    j1 = bitReverse(i1, FFT_SIZE);
                    j2 = bitReverse(i2, FFT_SIZE);
                } else {
                    i1 = j * nHInputs * 2 + k;
                    i2 = j * nHInputs * 2 + nHInputs + k;
                    j1 = i1;
                    j2 = i2;
                }

                float wr, wi;
                computeWeight(FFT_SIZE, k * nBlocks, wr, wi);

                int offset1 = 4 * (i1 + i * FFT_SIZE);
                data[offset1 + 0] = (j1 + 0.5) / FFT_SIZE;
                data[offset1 + 1] = (j2 + 0.5) / FFT_SIZE;
                data[offset1 + 2] = wr;
                data[offset1 + 3] = wi;

                int offset2 = 4 * (i2 + i * FFT_SIZE);
                data[offset2 + 0] = (j1 + 0.5) / FFT_SIZE;
                data[offset2 + 1] = (j2 + 0.5) / FFT_SIZE;
                data[offset2 + 2] = -wr;
                data[offset2 + 3] = -wi;
            }
        }
    }

    return data;
}
const unsigned char * loadfile(const std::string &file, int &size)
{
    std::ifstream fs(file.c_str(), std::ios::binary);
    fs.seekg(0, std::ios::end);
    size = fs.tellg();
    char * data = new char[size + 1];
    fs.seekg(0);
    fs.read(data, size);
    fs.close();
    data[size] = 0;
    return (unsigned char *)data;
}


struct P3_UV
{
    float _x, _y, _z;
    float _u, _v;
    P3_UV()
    {

    }
    P3_UV(float x, float y, float z, float u, float v)
        :_x(x),_y(y),_z(z),_u(u),_v(v)
    {

    }

};
class TestWindow : public ork::GlutWindow
{
public:
    TestWindow()
        :ork::GlutWindow(ork::Window::Parameters().name("ProlandTerrain").size(1024, 800))
        ,_dist(2.0)
    {
        _mesh = new ork::Mesh<P3_UV, unsigned int>(ork::TRIANGLES, ork::GPU_STATIC);
        _mesh->addAttributeType(0, 3, ork::A32F, false);
        _mesh->addAttributeType(1, 2, ork::A32F, true);

        _mesh->addVertex(P3_UV(-1, -1, 0, 0, 1));
        _mesh->addVertex(P3_UV(1, -1, 0, 1, 1));
        _mesh->addVertex(P3_UV(1, 1, 0, 1, 0));
        _mesh->addVertex(P3_UV(-1, 1, 0, 0, 0));

        _mesh->addIndice(0);
        _mesh->addIndice(1);
        _mesh->addIndice(2);
        _mesh->addIndice(0);
        _mesh->addIndice(2);
        _mesh->addIndice(3);
        int w;
        int h;
        int channels;
        int size;
        /*const unsigned char * data = loadfile("D:/1.jpg", size);
        const unsigned char * logo = stbi_load_from_memory(data, size, &w, &h, &channels, 0);*/

        float *data = computeButterflyLookupTexture();
        ork::ptr<ork::Texture2D> butterfly = new ork::Texture2D(FFT_SIZE, PASSES, ork::RGBA16F, ork::RGBA, ork::ORK_FLOAT,
            ork::Texture::Parameters().min(ork::NEAREST).mag(ork::NEAREST).wrapS(ork::CLAMP_TO_EDGE).wrapT(ork::CLAMP_TO_EDGE),
            ork::Buffer::Parameters(), ork::CPUBuffer(data));
        ork::ptr<ork::Module> meshModule = new ork::Module(330, "\
                                                                uniform mat4 localToScreen; \n\
                                                                layout(location = 0) in vec3 vertex; \n\
                                                                layout(location = 1) in vec2 uv; \n\
                                                                out vec2 fuv; \n\
                                                                void main() { \n\
                                                                fuv = uv; \n\
                                                                gl_Position = localToScreen * vec4(vertex, 1.0); \n\
                                                                } \n\
                                                                ", "\
                                                                uniform sampler2D sampler; \n\
                                                                layout(location = 0) out vec4 data; \n\
                                                                in vec2 fuv; \n\
                                                                void main() { \n\
                                                                data = vec4(texture(sampler, fuv).rgb, 1); \n\
                                                                } \n\
                                                                ");
        _meshProgram = new ork::Program(meshModule);
        _localToScreen = _meshProgram->getUniformMatrix4f("localToScreen");
        _meshProgram->getUniformSampler("sampler")->set(butterfly);
        _frameBuffer = ork::FrameBuffer::getDefault();
        _frameBuffer->setClearColor(ork::vec4f(0.0, 0.0, 1.0, 1.0));
        _frameBuffer->setDepthTest(true, ork::LESS);

        
    }

    virtual void redisplay(double t, double dt)
    {
        _frameBuffer->clear(true, false, true);
        static float i = 0.0;
        ork::mat4f cameraToWorld = ork::mat4f::rotatey(i);
        //i += 0.01;
        cameraToWorld = cameraToWorld * ork::mat4f::translate(ork::vec3f(0.0, 0.0, _dist));
        ork::mat4f worldToCamera = cameraToWorld.inverse();
        ork::vec4<int> vp = _frameBuffer->getViewport();
        float width = float(vp.z);
        float height = float(vp.w);
        ork::mat4f cameraToScreen = ork::mat4f::perspectiveProjection(degrees(45.0), width/height, 0.1, 100000.0);
        _localToScreen->setMatrix(cameraToScreen * worldToCamera);
        _frameBuffer->draw(_meshProgram, *_mesh);
        ork::GlutWindow::redisplay(t, dt);
    }

    virtual void reshape(int x, int y)
    {
        _frameBuffer->setViewport(ork::vec4i(0, 0, x, y));
        ork::GlutWindow::reshape(x, y);
        idle(false);
    }
public:
    static ork::static_ptr<ork::Window>            _app;
    ork::ptr<ork::FrameBuffer>                     _frameBuffer;
    ork::ptr<ork::Mesh<P3_UV, unsigned int> >      _mesh;
    ork::ptr<ork::Program>                         _meshProgram;
    ork::ptr<ork::UniformMatrix4f>                 _localToScreen;
    float                                          _dist;
};

ork::static_ptr<ork::Window> TestWindow::_app;

int main()
{
    atexit(ork::Object::exit);
    TestWindow::_app = new TestWindow;
    TestWindow::_app->start();
    return EXIT_SUCCESS;
}

posted @ 2014-02-25 15:19  20118281131  阅读(379)  评论(0编辑  收藏  举报