重启图元遇到指定索引值重新绘制和glew通过NULL指定没有cpu数据拷贝到缓存区对象中

1.重绘顶点索引,glPrimitiveRestartIndex在遍历索引缓存绘制中,遇到指定索引值,重新开始绘制同类型的一个新图元,避免开辟多个索引缓存。
2. glew中 glGenBuffers glBindBuffer glBufferData通过NULL指定最近的缓存, glBufferData(GL_ARRAY_BUFFER, 6 * NumPoints * sizeof(GLfloat), NULL, GL_STATIC_DRAW);可以传递一个空指针地址,glBufferData空地址传入是说明cpu没有数据拷贝到GPU中但是申请这么大的空间只是没有初始化值后面可以用glMapBufffer映射返回当前激活的该类GPU缓冲区对象地址并可以填充返回的指针值。glColorPointer或glDrawElements接着空地址传入填充内存块或取得内存块,传递进去的NULL+ offset指针其实是当前激活的缓存区对象的地址偏移(也是说明CPU中没有传入填充的数据,到GPU当前激活缓冲区中指定的偏移取就可以了)。

缓存区对象都是在GPU显存中的,只是加载顶点数据(传递数据)这个步骤提高传递性能, 绘制时候还是要Draw call调用,除非合并了顶点数据和纹理像素数据才可以减少Draw call。

Specifies a pointer to data that will be copied into the data store for initialization, or NULL if no data is to be copied.
If data is NULL, a data store of the specified size is still created, but its contents remain uninitialized and thus undefined.
3.glBufferData usage  决定数据存储的位置和DX一样,STATIC和STREAM的在显卡中只能修改一次,DYNAMIC的在APG缓存中和系统缓存中
    glBufferData(GL_ARRAY_BUFFER, 6 * NumPoints * sizeof(GLfloat), NULL, GL_STATIC_DRAW);

glColorPointer(3, GL_FLOAT, 6 * sizeof(GLfloat), NULL);
glDrawElements(GL_TRIANGLE_STRIP, NumStrips * (NumPointsPerStrip + 1), GL_UNSIGNED_SHORT, NULL);
#include <stdlib.h>
#include <stdio.h>
#define GLEW_STATIC
#include <GL/glew.h>
//#define FREEGLUT_STATIC
#include <GL/freeglut.h>


#define BUFFER_OFFSET(offset) ((const GLubyte *)NULL + (offset))

#pragma comment(lib, "glew32s.lib")


#define XStart -0.8
#define XEnd 0.8
#define YStart -0.8
#define YEnd 0.8
#define NumXPoints 11
#define NumYPoints 11
#define NumPoints (NumXPoints * NumYPoints)
#define NumPointsPerStrip (2 * NumXPoints)
#define NumStrips (NumYPoints - 1)
#define RestartIndex 0xffff
GLfloat color[6][3] = {
    { 1.0, 1.0, 1.0 }, { 1.0, 0.0, 0.0 }, { 1.0, 1.0, 0.0 },
    { 0.0, 1.0, 0.0 }, { 0.0, 1.0, 1.0 }, { 0.0, 0.0, 1.0 }
};


void init() {
    GLuint vbo = 0;
    GLuint ebo = 0;
    GLfloat* vertices = NULL;
    GLushort* indices = NULL;

    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);

    //target:可以是GL_ARRAY_BUFFER()(顶点数据)或GL_ELEMENT_ARRAY_BUFFER(索引数据)
    //size:存储相关数据所需的内存容量
    //data:用于初始化缓冲区对象,可以是一个指向客户区内存的指针,也可以是NULL
    //usage:数据在分配之后如何进行读写,如GL_STREAM_READ,GL_STREAM_DRAW,GL_STREAM_COPY
    glBufferData(GL_ARRAY_BUFFER, 6 * NumPoints * sizeof(GLfloat), NULL, GL_STATIC_DRAW);

    //提供对缓冲区对象包含的整个数据集合的更新
    //access:GL_READ_ONLY,GL_WRITE_ONLY,GL_READ_WRITE
    vertices = (GLfloat*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);

    if (vertices == NULL) {
        exit(EXIT_FAILURE);
    }
    else {
        int i;
        int j;
        GLfloat dx = (GLfloat)(XEnd - XStart) / (NumXPoints - 1);
        GLfloat dy = (GLfloat)(YEnd - YStart) / (NumYPoints - 1);
        GLfloat* tmp = vertices;
        int n = 0;

        // 绘制NumYPoints * NumXPoints个顶点,包含了像素和顶点数据
        for (j = 0; j < NumYPoints; ++j) {
            GLfloat y = (GLfloat)(YStart + j * dy);// y最小为-0.8,最大为0.8
            for (i = 0; i < NumXPoints; ++i) {
                GLfloat x = (GLfloat)(XStart + i * dx);// x最小为-0.8,最大为0.8
                *tmp++ = color[(i + j) % 6][0]; // i,j是0到10
                *tmp++ = color[(i + j) % 6][1];
                *tmp++ = color[(i + j) % 6][2];
                *tmp++ = x;
                *tmp++ = y;
                *tmp++ = 0;
            }
        }
        //表示当前绑定缓冲区对象的更新已经完成,与glMapBuffer()结合使用
        glUnmapBuffer(GL_ARRAY_BUFFER);
        // 顶点数据加载,这里从NULL地址中加载
        glVertexPointer(3, GL_FLOAT, 6 * sizeof(GLfloat), (const GLubyte *)NULL + 3 * sizeof(GLfloat));//BUFFER_OFFSET(3 * sizeof(GLfloat))
        // 颜色数据加载,这里从NULL地址中加载
        glColorPointer(3, GL_FLOAT, 6 * sizeof(GLfloat), NULL);//BUFFER_OFFSET(0)
        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);
        //glInterleavedArrays(GL_C3F_V3F, 0, 0);
    }

    glGenBuffers(1, &ebo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
    // 索引数量,每列顶点有两重索引,比一般索引多了两倍
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, NumStrips * (NumPointsPerStrip + 1) * sizeof(GLushort), NULL, GL_STATIC_DRAW);
    indices = (GLushort*)glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
    if (indices == NULL) {
        exit(EXIT_FAILURE);
    }
    else {
        int i;
        int j;
        GLushort* index = indices;
        // 列数
        for (j = 0; j < NumStrips; ++j) {
            // 底部顶点的索引开始
            GLushort bottomRow = j * NumYPoints;
            // 顶部顶点的索引开始
            GLushort topRow = bottomRow + NumYPoints;
            // 指定列中的两行索引,赋值
            for (i = 0; i < NumXPoints; ++i) {
                *index++ = topRow + i;
                *index++ = bottomRow + i;
            }
            // 每一列的结尾,都赋值一个重绘索引值
            *index++ = RestartIndex;
        }
        // 结束索引数据的填充
        glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
    }
    // 遇到重绘索引值,那么开始重绘相同类型的图元,索引缓存会一直迭代直到没有则绘制结束
    glPrimitiveRestartIndex(RestartIndex);
    glEnable(GL_PRIMITIVE_RESTART);
}


void display(void) {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glColor3f(1, 1, 1);
 // 通过NULL指定最近开启的client端缓存,这里是指定最近操作的索引缓存
    glDrawElements(GL_TRIANGLE_STRIP, NumStrips * (NumPointsPerStrip + 1), GL_UNSIGNED_SHORT, NULL);
    glutSwapBuffers();
}
void reshape(int w, int h) {
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, w, 0.0, h);
}
void keyboardfunc(unsigned char key, int x, int y) {
    //std::cout << key << x << y << std::endl;
}
void mouse(int button, int state, int x, int y) {
    switch (button)
    {
    case GLUT_LEFT_BUTTON:
        if (state == GLUT_DOWN) {
            glutIdleFunc(NULL);
        }
        break;
    case GLUT_RIGHT_BUTTON:
        if (state == GLUT_DOWN) {
            glutIdleFunc(NULL);
        }
        break;
    default:
        break;
    }
}
void move(int x, int y) {
    //std::cout << x << y << std::endl;
}


int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowSize(250, 250);

    glutInitWindowPosition(100, 100);
    glutInitContextVersion(3, 1);

    glutCreateWindow("hello");
    GLenum res = glewInit();
    if (GLEW_OK != res)
    {
        /* Problem: glewInit failed, something is seriously wrong. */
        fprintf(stderr, "Error: %s\n", glewGetErrorString(res));
    }
    init();
    glutDisplayFunc(display);
    //glutReshapeFunc(reshape);
    glutMouseFunc(mouse);
    //glutMotionFunc(move);
    //glutKeyboardFunc(keyboardfunc);
    glutMainLoop();

    return 0;
}


要使选的不同种类图元纵向分布,可以按照以下步骤进行操作: 1. 对于每个不同种类的图元,分别遍历选图元,获取该种类图元在 y 轴上的最小和最大。 2. 计算每个种类图元间位置的 y ,即 (最小 + 最大) / 2。 3. 遍历选图元,根据它们的种类,将它们的 y 设置为对应种类图元间位置的 y 减去该图元自身高度的一半。 下面是一个示例代码片段,演示了如何实现选不同种类图元的纵向分布: ```javascript // 假设我们有一个包含选图元的数组 selectedElements const selectedElements = [ { x: 10, y: 20, height: 30, type: 'rect' }, { x: 30, y: 40, height: 40, type: 'circle' }, { x: 50, y: 60, height: 50, type: 'line' }, // ... ]; // 创建一个映射来存储每个种类图元的最小和最大 y const minYMap = {}; const maxYMap = {}; // 遍历选图元,记录每个种类图元的最小和最大 y selectedElements.forEach(element => { const { type, y, height } = element; if (!minYMap[type] || y < minYMap[type]) { minYMap[type] = y; } if (!maxYMap[type] || (y + height) > maxYMap[type]) { maxYMap[type] = y + height; } }); // 遍历选图元,根据种类设置它们的 y 为对应种类图元间位置减去自身高度的一半 selectedElements.forEach(element => { const { type, y, height } = element; const midY = (minYMap[type] + maxYMap[type]) / 2; element.y = midY - (height / 2); }); // 最后根据具体的图元数据进行绘制操作 ``` 请注意,这只是一个示例代码片段,具体实现可能会根据你的需求和具体的图元数据结构有所不同。你需要根据自己的情况进行相应的调整和修改。同时,还需要确保选的不同种类图元在同一垂直方向上没有重叠,以实现纵向分布的效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值