基于QT的OpenGL开发学习(3.1)--着色器之彩色三角形

OpenGL开发学习之 --着色器之彩色三角形

一、摘要

1.着色器是使用一种叫GLSL的类C语言写成的。GLSL是为图形计算量身定制的,它包含一些针对向量和矩阵操作的有用特性。
2.和其他编程语言一样,GLSL有数据类型可以来指定变量的种类。GLSL中包含C等其它语言大部分的默认基础数据类型:int、float、double、uint和bool。GLSL也有两种容器类型,它们会在这个教程中使用很多,分别是向量(Vector)和矩阵(Matrix)
3.向量在这里插入图片描述
4.虽然着色器是各自独立的小程序,但是它们都是一个整体的一部分,出于这样的原因,我们希望每个着色器都有输入和输出,这样才能进行数据交流和传递。GLSL定义了in和out关键字专门来实现这个目的。每个着色器使用这两个关键字设定输入和输出,只要一个输出变量与下一个着色器阶段的输入匹配,它就会传递下去。但在顶点和片段着色器中会有点不同。

5.顶点着色器应该接收的是一种特殊形式的输入,否则就会效率低下。顶点着色器的输入特殊在,它从顶点数据中直接接收输入。为了定义顶点数据该如何管理,我们使用location这一元数据指定输入变量,这样我们才可以在CPU上配置顶点属性,layout (location = 0)。顶点着色器需要为它的输入提供一个额外的layout标识,这样我们才能把它链接到顶点数据。
6.Uniform是一种从CPU中的应用向GPU中的着色器发送数据的方式,但uniform和顶点属性有些不同。首先,uniform是全局的(Global)。全局意味着uniform变量必须在每个着色器程序对象中都是独一无二的,而且它可以被着色器程序的任意着色器在任意阶段访问。第二,无论你把uniform值设置成什么,uniform会一直保存它们的数据,直到它们被重置或更新。
在这里插入图片描述
7.目录结构
在这里插入图片描述

二、代码

opengl.h

#ifndef OPENGL_H
#define OPENGL_H

#pragma once

#include <QOpenGLWidget>
#include <QDebug>
#include <QOpenGLFunctions_3_3_Core>
#include "shader.h"
#include <QOpenGLWidget>

namespace Ui {
class opengl;
}

class opengl : public QOpenGLWidget
{
public:
    opengl();
    ~opengl();

    GLuint a;
protected:
    virtual void initializeGL();
    virtual void resizeGL(int w, int h);
    virtual void paintGL();
private:
    Shader *ourShader;
    QOpenGLFunctions_3_3_Core *core;
    GLuint VBO, VAO;
};
#endif // OPENGL_H

opengl.cpp

#include "opengl.h"
#include <QtDebug>

opengl::opengl()
{
}

opengl::~opengl()
{
}

/*
 *function:负责初始化
*/
void opengl::initializeGL(){
    //着色器部分
    core = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_3_Core>();
    ourShader = new Shader(":/shader/texshadersource.vert",":/shader/fragmentshadersource.frag");
    //VAO,VBO数据部分
    GLfloat vertices[] = {
        0.5f, -0.5f, 0.0f,  1.0f, 0.0f, 0.0f,  // Bottom Right
        -0.5f, -0.5f, 0.0f,  0.0f, 1.0f, 0.0f,  // Bottom Left
        0.0f,  0.5f, 0.0f,  0.0f, 0.0f, 1.0f   // Top
    };
    core->glGenVertexArrays(1, &VAO);//两个参数,第一个为需要创建的缓存数量。第二个为用于存储单一ID或多个ID的GLuint变量或数组的地址
    core->glGenBuffers(1, &VBO);
    core->glBindVertexArray(VAO);
    core->glBindBuffer(GL_ARRAY_BUFFER, VBO);
    core->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    core->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)0);
    core->glEnableVertexAttribArray(0);
    core->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));
    core->glEnableVertexAttribArray(1);
    core->glBindBuffer(GL_ARRAY_BUFFER, 0);
    core->glBindVertexArray(0);
    core->glClearColor(0.1f, 0.5f, 0.3f, 1.0f);
}

void opengl::resizeGL(int w, int h){
    core->glViewport(0, 0, w, h);
}

void opengl::paintGL(){

    core->glClear(GL_COLOR_BUFFER_BIT);
    ourShader->use();
    core->glBindVertexArray(VAO);
    core->glDrawArrays(GL_TRIANGLES, 0, 3);
}

shader.h

#include "opengl.h"
#include <QtDebug>

opengl::opengl()
{
}

opengl::~opengl()
{
}

/*
 *function:负责初始化
*/
void opengl::initializeGL(){
    //着色器部分
    core = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_3_Core>();
    ourShader = new Shader(":/shader/texshadersource.vert",":/shader/fragmentshadersource.frag");
    //VAO,VBO数据部分
    GLfloat vertices[] = {
        0.5f, -0.5f, 0.0f,  1.0f, 0.0f, 0.0f,  // Bottom Right
        -0.5f, -0.5f, 0.0f,  0.0f, 1.0f, 0.0f,  // Bottom Left
        0.0f,  0.5f, 0.0f,  0.0f, 0.0f, 1.0f   // Top
    };
    core->glGenVertexArrays(1, &VAO);//两个参数,第一个为需要创建的缓存数量。第二个为用于存储单一ID或多个ID的GLuint变量或数组的地址
    core->glGenBuffers(1, &VBO);
    core->glBindVertexArray(VAO);
    core->glBindBuffer(GL_ARRAY_BUFFER, VBO);
    core->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    core->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)0);
    core->glEnableVertexAttribArray(0);
    core->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));
    core->glEnableVertexAttribArray(1);
    core->glBindBuffer(GL_ARRAY_BUFFER, 0);
    core->glBindVertexArray(0);
    core->glClearColor(0.1f, 0.5f, 0.3f, 1.0f);
}

void opengl::resizeGL(int w, int h){
    core->glViewport(0, 0, w, h);
}

void opengl::paintGL(){

    core->glClear(GL_COLOR_BUFFER_BIT);
    ourShader->use();
    core->glBindVertexArray(VAO);
    core->glDrawArrays(GL_TRIANGLES, 0, 3);
}

shader.cpp


#include "shader.h"

Shader::Shader(const QString& vertexPath, const QString& fragmentPath){
    QOpenGLShader vertexShader(QOpenGLShader::Vertex);
    bool success = vertexShader.compileSourceFile(vertexPath);
    if(!success){
        qDebug() << "ERROR::SHADER::VERTEX::COMPILATION_FAILED" << endl;
        qDebug() << vertexShader.log() << endl;
    }

    QOpenGLShader fragmentShader(QOpenGLShader::Fragment);
    success  =fragmentShader.compileSourceFile(fragmentPath);
    if(!success){
        qDebug() << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED" << endl;
        qDebug() << fragmentShader.log() << endl;
    }

   shaderProgram.addShader(&vertexShader);
   shaderProgram.addShader(&fragmentShader);
   success = shaderProgram.link();
   if(!success){
        qDebug() << "ERROR::SHADER::PROGRAM::LINKING_FAILED" << endl;
        qDebug() << shaderProgram.log() << endl;
   }
}

Shader::~Shader(){
}

三、重点问题原因以及解决办法

a.可能由于工作电脑没有独显导致(后面换个有显卡的电脑后解决) -> illegal non-ASCII character编码错误
b.shader在第一行没有进行独行回车导致 -> error C0204: version directive must be first statement and may not be repeated
c.shader文件的相对路径地址和绝对路径地址要注意

其中代码学习教程以及遇到问题解决办法所参考文章的链接附在下方:
源码参考:
https://learnopengl-cn.readthedocs.io/zh/latest/01%20Getting%20started/05%20Shaders/
https://blog.csdn.net/z136411501/article/details/79879537
解决问题参考:
https://blog.csdn.net/perfer258/article/details/116697601
https://blog.csdn.net/z136411501/article/details/83306516

四、正常运行后效果图

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值