OpenGL 入门——shaders(着色器)

本文详细介绍了如何使用OpenGL创建和使用着色器程序,包括顶点着色器和片段着色器的编写、编译、链接及错误检查过程。通过实例代码展示了如何设置顶点数据、顶点属性指针,并使用着色器程序绘制三角形。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#pragma once

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

#include <string>
using namespace std;

class Shader
{
public:
	Shader(const GLchar* vertexPath, const GLchar* fragmentPath);

	string vertexString;
	string fragmentString;
	const char* vertexSource;
	const char* fragmentSource;
	unsigned int ID;  //shader Program ID

	void  use();
private:
	void checkCompileErrors(unsigned int proID, string type);

};

#include<iostream>

#include "Shader.h"
#include <fstream>
#include <sstream>

using namespace std;

Shader::Shader(const GLchar* vertexPath,const GLchar* fragmentPath)
{
    ifstream vertexFile;
    ifstream fragmentFile;
    stringstream vertexSStream;
    stringstream fragmengSStream;

    // 打开文件
    vertexFile.open(vertexPath);
    fragmentFile.open(fragmentPath);
    // 保证ifstream对象可以抛出异常:
    vertexFile.exceptions(ifstream::failbit || ifstream::badbit );
    fragmentFile.exceptions(ifstream::failbit || ifstream::badbit);
    try
    {
        if (!vertexFile.is_open() || !fragmentFile.is_open())
        {
            throw exception(" file open failure!");
        }
        // 读取文件的缓冲内容到流中
        vertexSStream << vertexFile.rdbuf();
        fragmengSStream << fragmentFile.rdbuf();

        // 转换流至string
        vertexString = vertexSStream.str();
        fragmentString = fragmengSStream.str();

        //转换string到Char数组
        vertexSource = vertexString.c_str();
        fragmentSource = fragmentString.c_str();

        /*printf(vertexSource);
        printf(fragmentSource);*/

        unsigned int vertex, fragment;
        vertex = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertex, 1, &vertexSource, NULL);
        glCompileShader(vertex);
        checkCompileErrors(vertex, "VERTEX");

        fragment = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fragment, 1, &fragmentSource, NULL);
        glCompileShader(fragment);
        checkCompileErrors(fragment, "FRAGMENT");

        ID = glCreateProgram();
        glAttachShader(ID, vertex);
        glAttachShader(ID, fragment);
        glLinkProgram(ID);
        checkCompileErrors(ID, "PROGRAM");

        glDeleteShader(vertex);
        glDeleteShader(fragment);

    }
    catch (const std::exception& ex)
    {
        printf(ex.what());
    }


}

///使用shaderProgram
void Shader::use()
{
    glUseProgram(ID);
}



///检查编译错误并输出
void Shader::checkCompileErrors(unsigned int proID, string type)
{
    int success;
    char infoLog[512];
    if (type != "PROGRAM")
    {
        glGetShaderiv(proID, GL_COMPILE_STATUS, &success);
        if (!success)
        {
            glGetShaderInfoLog(proID, 512, NULL, infoLog);
            std::cout << "shader complie error\n" << infoLog << std::endl;
        }
    }
    else
    {
        glGetProgramiv(proID, GL_LINK_STATUS, &success);
        if (!success)
        {
            glGetProgramInfoLog(proID, 512, NULL, infoLog);
            std::cout << "program linking error\n" << infoLog << std::endl;
        }

    }

}

 

vertexsource.txt
#version 330 core
layout (location = 6) in vec3 aPos;
layout (location = 7) in vec3 aColor;
out vec4 vertexColor; 
void main()
{
   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
   vertexColor=vec4(aColor.x+0.5, aColor.y, aColor.z, 1.0);
}



fragmentsource.txt

#version 330 core
in vec4 vertexColor; 
//uniform  vec4 ourColor; 
out vec4 FragColor;  
void main()
{
   FragColor = vertexColor;
}

 

#include <iostream>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "Shader.h"
using namespace std;


//齐次坐标系 【-1,1】Normalized Device Coordinates(NDC)
//Vertex input
float 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,
     0.8f, 0.8f, 0.0f,     1.0f, 0, 1.0f
};



unsigned int indices[] = {  // note that we start from 0!
    0, 1, 2,   // first triangle
     2,1, 3    // second triangle
};


void processInput(GLFWwindow* window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}

int main(int argc, char* argv[])
{

    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);

    GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", nullptr, nullptr);
    if (window == nullptr)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return EXIT_FAILURE;
    }
    glfwMakeContextCurrent(window);

    //////==========================
    glewExperimental = GL_TRUE;
    if (glewInit() != GLEW_OK)
    {
        std::cout << "Failed to initialize GLEW" << std::endl;
        return EXIT_FAILURE;
    }

    int width, height;
    glfwGetFramebufferSize(window, &width, &height);
    glViewport(0, 0, width, height);
    //线框模式(Wireframe Mode)
    //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
    ////三角形默认逆时针绘制--背面剔除
    //glEnable(GL_CULL_FACE);
    //glCullFace(GL_BACK);

    Shader* myShader = new Shader("vertexSource.txt","fragmentSource.txt");


    //VAO Vertex Array Object
     // 1. bind Vertex Array Object 绑定顶点数组对象
    unsigned int VAO;
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);

    // vertex buffer objects (VBO)   can store a large number of vertices in the GPU's memory.
    // 2. copy our vertices array in a buffer for OpenGL to use
    unsigned int VBO;
    glGenBuffers(1, &VBO);  //产生一个bufferID 
    glBindBuffer(GL_ARRAY_BUFFER, VBO);  
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);  

    //3.copy our index array in a element buffer for OpenGL to use
    unsigned int EBO;
    glGenBuffers(1, &EBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    // 4. then set our vertex attributes pointers
    // 位置属性
    glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(6);
    // 颜色属性
    glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
    glEnableVertexAttribArray(7);


    while (!glfwWindowShouldClose(window))
    {
        processInput(window);

        glClearColor(0.2, 0.3, 0.3f, 1.0);
        glClear(GL_COLOR_BUFFER_BIT);


        // 4. draw the object
        myShader->use();

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
        glBindVertexArray(VAO);
       // glDrawArrays(GL_TRIANGLES, 0, 6);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        glfwPollEvents();
        glfwSwapBuffers(window);
    }

    glfwTerminate();
    //std::cin.get();

    return 0;
}

 

一般有16个Vertix

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值