计算机图形学第三章习题第一題可编程管线实现DDA法和中点画线法,Bresenham画线法

   买了人民邮电苏小红教授主编的计算机图形学实用教程,但是一直懒得看,现在决定利用CSDN博客平台来督促自己。

   上网搜了下,大多数人都是用老式的固定管线,没看到有谁用现代OpenGL,看了算法实现,尝试改成着色器的,自己看教材,教材上的算法写得很清楚了,一步一步实现即可。

   SetPixel函数是windows下的函数,看了其他人博客里面用固定管线实现其实很简单,就是调用glBegin(GL_POINTS);  glVertex2i(x,y)。

改成着色器很简单,代码是我学习learnopengl的时候拿自己建的工程改的。DDA法和中点画线法,Bresenham畫線法

教材里面的算法x的增量是1,但是OpenGL里面标准化设备坐标是一个x、y和z值在-1.0到1.0的一小段空间,所以我把增量改成0.1,还可以更小。

运行结果:第一張圖是pointsize 15.0 ,第二張圖是5.0

分別是中點畫線和Bresenham,中點畫線波浪紋比較明顯。

glPointSize(15.0);

 

glPointSize(5.0);

void bges::CGfxRenderDDADrawLine::startUp()

{

vertexArrayID = 0;

    glGenVertexArrays(1, &vertexArrayID);

    glBindVertexArray(vertexArrayID);

    // Create and compile our GLSL program from the shaders

    Shader shader;

    Shader shader2;

programID = shader.LoadShaders("/home/study/OpenGL/learnopengl/MyProject/shaderFile/SimpleVertexShader.vertexshader","/home/study/OpenGL/learnopengl/MyProject/shaderFile/SimpleFragmentShader.fragmentshader" );

    static GLfloat lineVertex_Buffer_Data[902] = {0.0};

    //{0.00000,1.000000,0.250000,0.500000};

    //this->length = GetLineDDAData(0.0,0.0,0.45,0.41,lineVertex_Buffer_Data);

    static GLfloat lineVertexX[451] = {0.0};

    static GLfloat lineVertexY[451] = {0.0};

    GetLineMLDAData(0.0,0.0,0.45,0.41,lineVertexX,lineVertexY);

    for(int i = 0;i < 451;i++){

        lineVertex_Buffer_Data[ i ] = lineVertexX[ i ];

    }

    for(int i = 451;i < 902;i++){

        lineVertex_Buffer_Data[ i ] = lineVertexY[ i - 451 ];

    }

    vertexbuffer = 0;

    glGenBuffers(1, &vertexbuffer);

    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);

    glBufferData(GL_ARRAY_BUFFER, sizeof(lineVertex_Buffer_Data),

     lineVertex_Buffer_Data, GL_STATIC_DRAW);

    // 1rst attribute buffer : vertices

    glEnableVertexAttribArray(0);

    glVertexAttribPointer(

        0,

        2,

        GL_FLOAT,

        GL_FALSE,

        0,

        (void*)0

    );

    vertexArrayIDBresenham = 0;

    glGenVertexArrays(1, &vertexArrayIDBresenham);

    glBindVertexArray(vertexArrayIDBresenham);

    programIDBresenham = shader2.LoadShaders( "/home/tankweight/study/OpenGL/learnopengl/MyProject/shaderFile/SimpleVertexShader.vertexshader", "/home/tankweight/study/OpenGL/learnopengl/MyProject/shaderFile/SimpleFragmentShader.fragmentshader" );

    static GLfloat lineVertex_Buffer_DataBresenham[1224] = {0.0};

    static GLfloat lineVertexXBresenham[612] = {0.0};

    static GLfloat lineVertexYBresenham[612] = {0.0};

    GetLineBresenhamData(-0.46,-0.2,0.15,0.11,lineVertexXBresenham,lineVertexYBresenham);

    for(int i = 0;i < 612;i++){

        lineVertex_Buffer_DataBresenham[ i ] = lineVertexXBresenham[ i ];

    }

    for(int i = 612;i < 1004;i++){

        lineVertex_Buffer_DataBresenham[ i ] = lineVertexYBresenham[ i - 612 ];

    }

    vertexbufferBresenham = 0;

    glGenBuffers(1, &vertexbufferBresenham);

    glBindBuffer(GL_ARRAY_BUFFER, vertexbufferBresenham);

    glBufferData(GL_ARRAY_BUFFER, sizeof(lineVertex_Buffer_DataBresenham),

     lineVertex_Buffer_DataBresenham, GL_STATIC_DRAW);

    // 1rst attribute buffer : vertices

    glEnableVertexAttribArray(0);

    glVertexAttribPointer(

        0,

        2,

        GL_FLOAT,

        GL_FALSE,

        0,

        (void*)0

    );

    glPointSize(5.0);

}

DDA数值微分画线算法:

int bges::CGfxRenderDDADrawLine::GetLineDDAData(float x1,float y1,float x2,float y2, GLfloat vertex_buffer_data[])

{

    float length = 0.0;

    int k = 0;

    float x = x1;

float y = y1;

    float dx = abs(x2 - x1);

    float dy = abs(y2 - y1);

    float m = (float)(dy / dx);

length = dx - dy >= 0.0000001f ? dx : dy;

int yinit = length / 0.001;

    printf("yinit = %d,length = %f\n",yinit,length);

    vertex_buffer_data[ k ] = x;

    vertex_buffer_data[ k + yinit ] = y;

    //printf("%f,%f,%f\n",m,x,y);

    //vertex_buffer_data[ k + 2 ] = 0.0f;

    k = 1;

    for(int i = 1;i < yinit;i++){

        if(dx - dy > 0.0 && x1 - x2 < 0.0){

            x += 0.001;

            y += m;

            vertex_buffer_data[ k ] = x;

     vertex_buffer_data[ k + yinit ] = y;

     //vertex_buffer_data[ k + 2 ] = 0.0f;

            printf("%f,%f\n",x,y);

            k++;

        }

    }

    return length / 0.01;

}

 

渲染

void bges::CGfxRenderDDADrawLine::Render(double currentTime)

{

glClear( GL_COLOR_BUFFER_BIT );

    // Use our shader

    glUseProgram(programID);

    glBindVertexArray(vertexArrayID);

    glDrawArrays(GL_POINTS, 0, 451);

    //glDisableVertexAttribArray(0);

 

    glUseProgram(programIDBresenham);

    glBindVertexArray(vertexArrayIDBresenham);

    glDrawArrays(GL_POINTS, 0, 200);

    // Swap buffers

    glfwSwapBuffers(window);

    glfwPollEvents();

}

顶点着色器

#version 330 core

// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;

void main(){

    gl_Position.xyz = vertexPosition_modelspace;
    gl_Position.w = 1.0;

}

片元着色器

#version 330 core

// Ouput data
out vec3 color;

void main()
{

    // Output color = red
    color = vec3(1,0,0);

}

中点画线法:

void bges::CGfxRenderDDADrawLine::GetLineMLDAData(float x1,float y1,float x2,float y2, GLfloat lineVertexX[],GLfloat lineVertexY[])

{

    float a = y1 - y2;

    float b = x2 - x1;

    float d = 2 * a + b;

    float deta1 = 2 * a;

    float deta2 = 2 * (a + b);

    float x = x1,y = y1;

    lineVertexX[ 0 ] = x;

    lineVertexY[ 0 ] = y;

    int i = 1;

    for(;;)

    {

        if(x - x2 < 0.000001){

            if(d - 0.0000001 < 0){

                x = x + 0.001;

                y = y + 0.001;

                d = d + deta2;

            }

            else {

                x = x + 0.001;

                d = d + deta1;

            }

            lineVertexX[ i ] = x;

            lineVertexY[ i ] = y;

            //printf("%f,%f\n",x,y);

            i++;

        }

        else{

            return;

        }

    }

}

Bresenham畫線算法

void bges::CGfxRenderDDADrawLine::GetLineBresenhamData(float x1,float y1,float x2,float y2, GLfloat lineVertexX[],GLfloat lineVertexY[])

{

    float dx = x2 - x1;

    float dy = y2 - y1;

    float x = x1;

    float y = y1;

    lineVertexX[ 0 ] = x;

    lineVertexY[ 0 ] = y;

    float m = abs(float(dy / dx));

    bool xx_yy = m - 1.0 < 0.0000001 ? true : false;

    float S1 = dx - 0.0000001 > 0.0 ? 0.001 : -0.001;

    float S2 = dy - 0.0000001 > 0.0 ? 0.001 : -0.001;

    float e_InitValue = m - 1.0 > 0.0000001 ? 2 * abs(dx) - 2 * (dy) : 2 * abs(dy) - 2 * (dx);

    float e_current = e_InitValue;

    int i = 1;

    for(;;)

    {

        if((x2 - x) > 0.0000001){

            if(e_current - 0.0000001 < 0.0){

                if(false == xx_yy){

                    y += S2;

                    e_current += 2 * abs(dx);

                }

                else{

                    x += S1;

                    e_current += 2 * abs(dy);

                }

            }

            else{

                if(false == xx_yy){

                    x += S1;

                    y += S2;

                    e_current += (2 * abs(dx) - 2 * abs(dy));

                }

                else{

                    y += S2;

                    x += S1;

                    e_current += (2 * abs(dy) - 2 * abs(dx));

                }

            }

         lineVertexX[ i ] = x;

            lineVertexY[ i ] = y;

            i++;

            //printf("1 i = %d\n",i);

        }

        else{

            //printf("2 i = %d\n",i);

            return;

        }

    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值