在OpenGL中绘制单色2D数组

问题描述 投票:0回答:1

我需要将OpenGL用于特定目的。我有一个尺寸为[SIZE] [SIZE](总是正方形)的一维浮点数组,它表示2D图像。因为我一直在使用第三程序通过将数组输出到文本文件来执行绘图,所以绘图只是这里的一个额外功能,但是我想在程序本身中提供进行绘图的选项。

该数组正在不断地更新,因为它应该表示模拟字段的值,该字段的详细信息是无关紧要的,但是重要的一点是,每个数组的值都将是- 1和1。现在,我想将这个数组绘制为2D图像(实时),在主循环中每N步绘制一次。我尝试使用X11的像素绘制工具(我正在Linux上执行此操作),并通过循环遍历并在SIZE X SIZE窗口上逐像素地绘制阵列来进行绘制,但这非常慢,而且需要花费更多的时间比模拟本身。我一直在研究OpenGL,从我看过的理想解决方案是将数组重新插入为2D纹理,然后将其打印在四边形上。显然,要使用裸露的OpenGL,我将不得不重新调整我的代码以使其与OpenGL绘图的主循环配合使用,这有点不切实际,因此,如果可以在GLFW中完成相同的操作,我会对此感到满意。

要绘制的图像始终是正方形的,并且其方向完全无关紧要,因为它应该是完全各向同性的,所以绘制它是镜像,倒置,转置等都没有关系。

程序的主要骨干遵循下一个方案

#include <iostream>
#include <GLFW/glfw3.h>
using namespace std;


int main(int argc, char** argv)
{
    if (GFX) //GFX is a bool, only draw stuff if it's 1 (its value doesnt change)
    {
        //Initialize GLFW
    }


    float field[2*SIZE][SIZE] = {0}; //This is the array to print (only the first SIZE * SIZE components)

    for (int i = 0; i < totalTime; i++)
    {
        for (int x=0; x < SIZE; x++)
        {
            for (int y=0; y < SIZE; y++)
            {
                //Each position of the array is then updates here
            }
        }
        if (GFX)
        {
            //The drawing should be done here
        }
    }
    return 0;
}

我已经尝试了一些代码片段,并修改了一些我发现的示例,但是还无法使其正常工作,要么他们必须调用中断我自己的模拟循环的glLoop,要么只打印一个像素位于中间。

因此,我的主要问题是如何从field的前SIZE X SIZE个分量中制作出纹理,然后将其绘制在QUAD上。

谢谢!

c++ opengl textures glut
1个回答
0
投票

对于新手来说,最简单的方法是使用不带着色器的旧API。为了完成这项工作,您只需将数据编码为范围为<0.0,-1.0>的1D线性浮点线性数组,就可以在CPU端从<-1,+1>相当快地通过单个for循环完成此操作:

for (i=0;i<size*size;i++) data[i]=0.5*(data[i]+1.0);

我不为您的平台使用GLUT或代码,因此我只坚持渲染:

//---------------------------------------------------------------------------
const int size=512;         // data  resolution
const int size2=size*size;
float data[size2];          // your float size*size data
GLuint txrid=-1;            // GL texture ID
//---------------------------------------------------------------------------
void init() // this must be called once (after GL is initialized)
    {
    int i;
    // generate float data
    Randomize();
    for (i=0;i<size2;i++) data[i]=Random();
    // create texture
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D,txrid);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_MODULATE);
    glDisable(GL_TEXTURE_2D);
    }
//---------------------------------------------------------------------------
void exit() // this must be called once (before GL is unitialized)
    {
    // release texture
    glDeleteTextures(1,&txrid);
    }
//---------------------------------------------------------------------------
void gl_draw()
    {
    glClear(GL_COLOR_BUFFER_BIT);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    // bind texture
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D,txrid);
    // copy your actual data into it
    glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE32F_ARB, size, size, 0, GL_LUMINANCE, GL_FLOAT, data);

    // render single textured QUAD
    glColor3f(1.0,1.0,1.0);
    glBegin(GL_QUADS);
    glTexCoord2f(0.0,0.0); glVertex2f(-1.0,-1.0);
    glTexCoord2f(1.0,0.0); glVertex2f(+1.0,-1.0);
    glTexCoord2f(1.0,1.0); glVertex2f(+1.0,+1.0);
    glTexCoord2f(0.0,1.0); glVertex2f(-1.0,+1.0);
    glEnd();

    // unbind texture (so it does not mess with othre rendering)
    glBindTexture(GL_TEXTURE_2D,0);
    glDisable(GL_TEXTURE_2D);

    glFlush();
    SwapBuffers(hdc);   // ignore this GLUT should make it on its own
    }
//---------------------------------------------------------------------------

这里预览:

preview

为了使这项工作有效,您需要在GLUT创建GL上下文后在应用程序启动时调用init(),并在GLUT关闭GL上下文之前在Apps结束时调用exit()gl_draw()将呈现您的数据,因此必须在GLUT的绘图事件中调用它。

[如果您不想在CPU端将范围转换为<0,1>,则可以将其移至着色器(非常简单的顶点和片段着色器),但是我觉得您是菜鸟,并且着色器实在太多了让您开始。如果您真的想那样走,请参见:

它还介绍了没有GLUT但在Windows上的GL初始化...

现在对上面的程序有一些注释:

  1. 我使用了GL_LUMINANCE32F_ARB纹理格式扩展

    其32位浮点纹理格式没有被钳位,因此您的数据保持不变。如今,它应该出现在gfx硬件上。

  2. size

    在原始GL规范中,纹理大小应为2的幂,因此16,32,64,128,256,512,...如果不是,您需要使用矩形纹理扩展,但是这在gfx HW中已经存在多年了,因此无需更改任何内容。但是在Linux和MAC上,GL的实现可能会出现问题,因此,如果某些操作不起作用,请尝试使用2大小的幂(以防万一)...

  3. GL_CLAMP_TO_EDGE

    这也是扩展(现在是HW固有的,因此您的纹理坐标从01,而不是从0+pixel/21-pixel/2 ...

    ]

但是所有这些都不是GL 1.0的东西,因此您需要在应用程序中添加扩展名(如果还没有GLUT或您使用的任何东西)。所有这些都是令牌/常量,没有函数调用,因此,如果编译器抱怨它应该足以:

#include <gl\glext.h>

[包含gl.h之后或改为直接添加定义:

#define GL_CLAMP_TO_EDGE                  0x812F
#define GL_LUMINANCE32F_ARB               0x8818

btw。您的代码看起来不像GLUT应用程序(但我可能不正确,因为我不使用它),例如:

您的标题建议GLFW3GLUT完全不同(除非它是从GLUT派生的),所以也许您应该编辑标签和OP以匹配您真正拥有/使用的内容。

© www.soinside.com 2019 - 2024. All rights reserved.