opengl入门(三)使用shader绘制三角形

13 篇文章 2 订阅

虽然在最开始的文章中可以直接画出一个三角形,但是并不是所有的平台和显卡都可以,为啥能画出来,主要是因为opengl会自带一个fragment shader和一个vertex shader,这就是为什么只设置几个位置就能画出一个三角形。本文将自己写两个shader来完成同样的工作,为了区别,我们用红色来填充三角形。

概念

Vertex Shader

简单的说,vertex shader是管三角形的三个顶点的,这里说一个重要概念,任何二维图形都可以拆分成若干个三角形的,如下图。所以,我们第一步就是要画一个三角形。
在这里插入图片描述

Fragment Shader

简单的说就是,三角形里面应该是什么颜色,或者是图形,或者是某种”材质“。shader的意思叫做着色器,为啥叫着色器,那就是因为,Vetex Shader和Fragment Shader都是运行在显卡中的程序,在我们的程序中,只是一些简单的字符串,我们需要再程序运行时,动态的编译,传输到显卡中,再通知显卡来渲染。

创建vertex buffer

  1. 通过opengl与显卡通讯,只需要传入显卡的array buffer即可,代码如下.
 float positions[6] = {
     -0.5f,-0.5f,
     0.0f,0.5f,
     0.5f,-0.5f
 };

unsigned int buffer;
glGenBuffers(1,&buffer);
glBindBuffer(GL_ARRAY_BUFFER,buffer);
glBufferData(GL_ARRAY_BUFFER,6*sizeof(float),positions,GL_STATIC_DRAW);
  1. 但是在显卡眼里,这只是一堆内存,并不清楚如何使用,因此,还需要告诉显卡,这内存是按照什么方式分布的,这叫做layout,glVertexAttribPointer中第一个参数可以理解成offset偏移量,第二个参数可以理解成step步长。
glEnableVertexAttribArray(0);
glVertexAttribPointer(0,2,GL_FLOAT,GL_FALSE,2*sizeof(float),0);

创建和编译shader的函数

首先,创建一个program,然后在编译一下shader,再把shader链到program上,都是套路型的代码,网上到处都是,照抄就行。


static unsigned int CompileShader(const unsigned int type,const std::string& source)
{
    unsigned int id = glCreateShader(type);
    const char* src = source.c_str();
    glShaderSource(id,1,&src,nullptr);
    glCompileShader(id);

    int result;
    glGetShaderiv(id,GL_COMPILE_STATUS,&result);
    if(result == GL_FALSE){
        int length;
        glGetShaderiv(id,GL_INFO_LOG_LENGTH,&length);
        char* messge = (char * )alloca(length * sizeof(char));
        glGetShaderInfoLog(id,length,&length,messge);
        std::cout << "fild to compile" <<  (type == GL_VERTEX_SHADER?"vertex":"fragment") << std::endl;
        std::cout << messge << std::endl;
    }

    return id;
}

static int CreateShader(const std::string& vertexShader,const std::string& fragmentShader)
{
    unsigned int program = glCreateProgram();
    unsigned int vs = CompileShader(GL_VERTEX_SHADER,vertexShader);
    unsigned int fs = CompileShader(GL_FRAGMENT_SHADER,fragmentShader);

    glAttachShader(program,vs);
    glAttachShader(program,fs);

    glLinkProgram(program);
    glValidateProgram(program);

    glDeleteShader(vs);
    glDeleteShader(fs);
    return program;
}

Vertex Shader

这里attribute 就是从显卡的array buffer中按照layout读出数据,保存到position变量中。然后这里再main函数中,简单的把position赋值给gl_Position,gl_Position代表着vertex在显卡中绘制的位置。

std::string vertexShader = 
"attribute vec4 position;\n"
 "\n"
 "void main()\n"
 "\n"
 "{\n"
 " gl_Position = position;\n"
 "}\n";

Fragment Shader

gl_FragColor代表着显卡绘制时候使用的颜色,这里给了一个vec4数组来表示,四个数字分别代表了,红绿蓝和透明度。

std::string fragmentShader = 
"void main()\n"
"{\n"
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n";

最终调用函数,应用program

运行后,会得到一个红色的三角形,有兴趣的可以改一下fragmentShader,选一个喜欢的颜色。

unsigned int shader = CreateShader(vertexShader,fragmentShader);
glUseProgram(shader);

在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值