shader 着色器

shader 着色器

着色器是运行在GPU上面的小程序,这些小程序为图形渲染的某个特定部份而运行,从基本意义上来说,着色器只一种把输入转换为输出的程序。

着色器的开头声明版本,接着输入和输出变量,uniform和main函数。
一个典型的着色器有下面的结构

#version version_number

in type in_variable_name;
in type in_variable_name;

out type out_variable_name;

uniform type uniform_name;

int main()
{
  // 处理输入并进行一些图形操作
  ...
  // 输出处理过的结果到输出变量
  out_variable_name = weird_stuff_we_processed;
}

顶点着色器的输入变量也叫顶点属性(Vertex Attribute),它由硬件来决定,OpenGL确保至少有16个包含4分量的顶点属性可以用,可以用GL_MAX_VERTEX_ATTRIBS来查询

GLint nrAttributes;
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &nrAttributes);
std::cout << "Maximum nr of vertex attributes supported: " << nrAttributes << std::endl;

数据类型

GLSL中包含C等其它语言大部份的默认的数据类型,如int,float,double,uint,bool.GLSL也有两种容器类型,矩阵(Matrix),向量(Vector

向量
类型说明
vecn包含n个float分量的的默认向量
bvecn包含n个bool分量的向量
ivecn包含n个int分量的向量
uvecn包含n个unsigned int 分量的向量
dvecn包含n个double分量的向量

输入与输出

顶点着色器接收的是一种特殊行式的输入,顶点着色器的输入特殊在,它从顶点数据中直接接收输入。为了定义顶点数据该如何管理,我们使用location这一元数据指定输入变量,这样我们才可以在CPU上配置顶点属性。我们已经在前面的教程看过这个了,layout (location = 0)。顶点着色器需要为它的输入提供一个额外的layout标识,这样我们才能把它链接到顶点数据。
另一个例外是片段着色器,它需要一个vec4颜色输出变量,因为片段着色器需要生成一个最终输出的颜色。如果你在片段着色器没有定义输出颜色,OpenGL会把你的物体渲染为黑色(或白色)。

所以,如果我们打算从一个着色器向另一个着色器发送数据,我们必须在发送方着色器中声明一个输出,在接收方着色器中声明一个类似的输入。当类型和名字都一样的时候,OpenGL就会把两个变量链接到一起,它们之间就能发送数据了(这是在链接程序对象时完成的)。

//
//  main.cpp
//  shaders0
//
//  Created by xufan on 2017/5/16.
//  Copyright © 2017年 xufan. All rights reserved.
//

#include <iostream>
#include <math.h>

#define GLEW_STATIC
#include <GL/glew.h>

#include <GLFW/glfw3.h>

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
void display();

// Shaders


const GLchar *vertexShaderSource = " \n \
    #version 330 core \n \
    layout (location = 0) in vec3 position; // position变量的属性位置值为0 \n \
    layout (location = 1) in vec3 color;    // 颜色变量的属性位置值为1 \n \
\n \
    out vec3 ourColor; // 为片段着色器输出一个颜色输出\n \
\n \
    void main() \n \
    { \n \
        gl_Position = vec4(position, 1.0); // 注意我们如何把一个vec3作为vec4的构造器的参数\n \
        ourColor = color; //将ourColor设置为我们从顶点数据那里得到的输入颜色\n \
    }\n";

const GLchar* fragmentShaderSource = "\n \
    #version 330 core \n \
    in vec3 ourColor; // 从顶点着色器传来的输入变量(名称相同、类型相同)\n \
\n \
    out vec4 color; // 片段着色器输出的变量名可以任意命名,类型必须是vec4\n \
    //uniform vec4 ourColor; //在OpenGL程序代码中设定这个变量\n \
\n \
    void main() \n \
    { \n \
        color = vec4(ourColor, 1.0f); \n \
        //color = ourColor; \n \
    }\n";

int main()
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

    GLFWwindow *window = glfwCreateWindow(800, 600, "learnOpenGL", nullptr, nullptr);
    glfwMakeContextCurrent(window);

    glfwSetKeyCallback(window, key_callback);

    glewExperimental = GL_TRUE;
    glewInit();

    printf("%s\n",vertexShaderSource);
    printf("%s\n",fragmentShaderSource);
    GLint nrAttributes;
    glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &nrAttributes);
    std::cout << "Maximum nr of vertex attributes supported: " << nrAttributes << std::endl;

    int width,height;
    glfwGetFramebufferSize(window, &width, &height);
    glViewport(0, 0, width, height);

    //vertex shader
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);

    //check
    GLint success;
    GLchar infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        std::cout<<"vertex shader compilation failed"<<std::endl;
    }

    //fragmeng shader
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource,NULL);
    glCompileShader(fragmentShader);

    glGetShaderiv(fragmentShader,GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        std::cout<<"fragment shader compilation failed"<<std::endl;
    }

    //create a program
    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);

    //check
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        std::cout<<"shaderPorgram failed"<<std::endl;
    }

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);


//    GLfloat vertices[] = {
//        -0.5f, -0.5f, 0.0f, // Left
//        0.5f, -0.5f, 0.0f, // Right
//        0.0f,  0.5f, 0.0f  // Top
//    };
//    GLfloat vertices[] = {
//        
//
//        
//        // 第一个三角形
//        0.5f, 0.5f, 0.0f,   // 右上角
//        0.5f, -0.5f, 0.0f,  // 右下角
//        -0.5f, 0.5f, 0.0f,  // 左上角
//        // 第二个三角形
//        0.5f, -0.5f, 0.0f,  // 右下角
//        -0.5f, -0.5f, 0.0f, // 左下角
//        -0.5f, 0.5f, 0.0f   // 左上角
//        
//    };

    GLfloat vertices[] = {
        // 位置              // 颜色
        0.5f, -0.5f, 0.0f,  1.0f, 0.0f, 0.0f,   // 右下
        -0.5f, -0.5f, 0.0f,  0.0f, 1.0f, 0.0f,  // 左下
        0.0f,  0.5f, 0.0f,  0.0f, 0.0f, 1.0f    // 顶部

    };

    GLuint VBO; // vertex buffer object,顶点缓冲对象
    GLuint VAO; // vertex array object ,顶点数组对象

    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);

    //绑定
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);

    //复制
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    //设置顶点属性指针,位置属性
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT) * 6, (GLvoid*)(0));
    //启动顶点属性,位置是0
    glEnableVertexAttribArray(0);

    //设置颜色属性,启动
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, (GLvoid *)(3 * sizeof(GLfloat)));
    glEnableVertexAttribArray(1);

    //解绑
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    //线框
    //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    //GL_FILL 填充

    while (!glfwWindowShouldClose(window)) {

        glfwPollEvents();

        display();

        //激活着色器
        glUseProgram(shaderProgram);

//        GLfloat timeValue = glfwGetTime();
//        GLfloat greenValue = (sin(timeValue) / 2) + 0.5;
//        GLint vertextColorLocation = glGetUniformLocation(shaderProgram, "ourColor");
//        glUniform4f(vertextColorLocation, 0.0f, greenValue, 0.0f, 1.0f);
//        
        //绘制这个三角形
        glBindVertexArray(VAO);
        glDrawArrays(GL_TRIANGLES, 0, sizeof(vertices)/ (3 * sizeof(vertices[0])));
        glBindVertexArray(0);

        glfwSwapBuffers(window);
    }

    glDeleteVertexArrays(1,&VAO);
    glDeleteBuffers(1, &VBO);

    glfwTerminate();

    return 0;
}

void display()
{
    //缓冲颜色
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    //清空颜色缓冲
    glClear(GL_COLOR_BUFFER_BIT);
}

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {

        std::cout<<"enter escape";
        glfwSetWindowShouldClose(window, GL_TRUE);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值