系列六:Shader的使用

 

 

Vertex.h

复制代码
 1 #pragma once
 2 
 3 #include <gl/glew.h>
 4 
 5 //The vertex definition
 6 struct Vertex
 7 {
 8     //This is the position struct, when you store a struct or class
 9     //inside of another struct or class, it is called composition, This is
10     //layed out exactly the same in memory as if we had a float position[2],
11     //but doing it this way makes more sense.
12 
13     struct Position //Position is the type
14     {
15         float x;
16         float y;
17     } position; //position is the same of this particular instance
18 
19     //4 bytes for r g b a color.
20     struct Color
21     {
22         GLubyte r;
23         GLubyte g;
24         GLubyte b;
25         GLubyte a;
26     } color;
27 };
复制代码

 

GLSLProgram.h

复制代码
#pragma once
#include <string>
#include <gl/glew.h>

class GLSLProgram
{
public:
    GLSLProgram();
    ~GLSLProgram();

    void compileShaders(const std::string& vertexSharderFilePath, const std::string& fragmentShaderFilePath);

    void linkShaders();

    void addAttribute(const std::string& attributeName);

    void use();
    void unuse();
private:
    void compileShader(const std::string& filePath, GLuint shaderID);

    GLuint m_progamID;
    GLuint m_vertexShaderID;
    GLuint m_fragmentShaderID;
    int m_numAttributes;
};
复制代码

 

GLSLProgram.cpp

复制代码
#include "GLSLProgram.h"
#include "Error.h"
#include <fstream>
#include <vector>

GLSLProgram::GLSLProgram() :m_progamID(0), m_vertexShaderID(0), m_fragmentShaderID(0), m_numAttributes(0)
{
}


GLSLProgram::~GLSLProgram()
{
}

void GLSLProgram::compileShaders(const std::string& vertexSharderFilePath, const std::string& fragmentShaderFilePath)
{
    // Get a program object.
    // Because addAttribute will use this programID
    m_progamID = glCreateProgram();

    m_vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
    if (0 == m_vertexShaderID)
    {
        faterError("Vertex shader failed to the created!");
    }

    m_fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
    if (0 == m_fragmentShaderID)
    {
        faterError("Fragment shader failed to the created!");
    }

    compileShader(vertexSharderFilePath, m_vertexShaderID);

    compileShader(fragmentShaderFilePath, m_fragmentShaderID); 

}

// Now time to link them together into a program.
void GLSLProgram::linkShaders()
{
    // Attach our shaders to our program
    glAttachShader(m_progamID, m_vertexShaderID);
    glAttachShader(m_progamID, m_fragmentShaderID);

    // Link our program
    glLinkProgram(m_progamID);

    // Note the different functions here: glGetProgram* instead of glGetShader*.
    GLint isLinked(0);
    glGetProgramiv(m_progamID, GL_LINK_STATUS, &isLinked);
    if (GL_FALSE == isLinked)
    {
        GLint maxLength = 0;
        glGetProgramiv(m_progamID, GL_INFO_LOG_LENGTH, &maxLength);

        // The maxLength includes the NULL character
        std::vector<char> infoLog(maxLength);
        glGetProgramInfoLog(m_progamID, maxLength, &maxLength, &infoLog[0]);

        // We don't need the program anymore
        glDeleteProgram(m_progamID);
        // Don't leak shaders either
        glDeleteShader(m_vertexShaderID);
        glDeleteShader(m_fragmentShaderID);

        std::printf("%s\n", &(infoLog[0]));
        faterError("Shaders failed to link");
    }

    // Always detach shaders after a successful link
    glDetachShader(m_progamID, m_vertexShaderID);
    glDetachShader(m_progamID, m_fragmentShaderID);
    // Don't leak shaders either
    glDeleteShader(m_vertexShaderID);
    glDeleteShader(m_fragmentShaderID);
}

void GLSLProgram::addAttribute(const std::string& attributeName)
{
    glBindAttribLocation(m_progamID, m_numAttributes++, attributeName.c_str());
}

void GLSLProgram::use()
{
    glUseProgram(m_progamID);
    for (int i = 0; i < m_numAttributes; ++ i)
    {
        glEnableVertexAttribArray(i);
    }
}

void GLSLProgram::unuse()
{
    glUseProgram(0);
    for (int i = 0; i < m_numAttributes; ++ i)
    {
        glDisableVertexAttribArray(i);
    }
}

void GLSLProgram::compileShader(const std::string& filePath, GLuint shaderID)
{
    std::ifstream vertexFile(filePath);
    if (vertexFile.fail())
    {
        perror(filePath.c_str());
        faterError("Failed to open " + filePath);
    }

    std::string fileContents = "";
    std::string line;

    while (std::getline(vertexFile, line))
    {
        fileContents += line + "\n";
    }

    vertexFile.close();

    const char* contentsPtr = fileContents.c_str();

    glShaderSource(shaderID, 1, &contentsPtr, nullptr);

    glCompileShader(shaderID);

    GLint isCompiled(0);
    glGetShaderiv(shaderID, GL_COMPILE_STATUS, &isCompiled);
    if (GL_FALSE == isCompiled)
    {
        GLint maxLength(0);
        glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &maxLength);

        std::vector<char> infoLog(maxLength);
        glGetShaderInfoLog(shaderID, maxLength, &maxLength, &infoLog[0]);

        glDeleteShader(shaderID);

        std::printf("%s\n", &(infoLog[0]));
        faterError("Shader " + filePath + " failed to compile");
    }
}
复制代码

 

Sprite.cpp

复制代码
#include "Sprite.h"
#include "vertex.h"
#include <cstddef>

Sprite::Sprite() :m_X(0.0f), m_Y(0.0f), m_Width(0.0f), m_Height(0.0f), m_vboID(0)
{
}


Sprite::~Sprite()
{
    if (m_vboID)
    {
        glDeleteBuffers(1, &m_vboID);
    }
}

void Sprite::init(float x, float y, float width, float height)
{
    m_X = x;
    m_Y = y;
    m_Width = width;
    m_Height = height;

    if (0 == m_vboID)
    {
        glGenBuffers(1, &m_vboID);
    }

    //Hard code, vertex num: 6, xy:2
    
    //    v2         v1
    //
    //
    //    v3
    Vertex vertexData[6];
    vertexData[0].position.x = x + width;
    vertexData[0].position.y = y + height;

    vertexData[1].position.x = x;
    vertexData[1].position.y = y + height;

    vertexData[2].position.x = x;
    vertexData[2].position.y = y;

    //Second Triangle
    vertexData[3].position.x = x;
    vertexData[3].position.y = y;

    vertexData[4].position.x = x + width;
    vertexData[4].position.y = y;

    vertexData[5].position.x = x + width;
    vertexData[5].position.y = y + width;

    for (int i = 0; i < 6; ++ i)
    {
        vertexData[i].color.r = 255;
        vertexData[i].color.g = 0;
        vertexData[i].color.b = 255;
        vertexData[i].color.a = 255;
    }
#if 0
    float vertexData[6 * 2];
    //First Triangle
    vertexData[0] = x + width;
    vertexData[1] = y + height;

    vertexData[2] = x;
    vertexData[3] = y + height;

    vertexData[4] = x;
    vertexData[5] = y;
    
    //Second Triangle
    vertexData[6] = x;
    vertexData[7] = y;

    vertexData[8] = x + width;
    vertexData[9] = y;

    vertexData[10] = x + width;
    vertexData[11] = y + width;
#endif

    vertexData[1].color.r = 0;
    vertexData[1].color.g = 0;
    vertexData[1].color.b = 255;
    vertexData[1].color.a = 255;

    vertexData[4].color.r = 0;
    vertexData[4].color.g = 255;
    vertexData[4].color.b = 0;
    vertexData[4].color.a = 255;

    glBindBuffer(GL_ARRAY_BUFFER, m_vboID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void Sprite::draw()
{
    // Bind the buffer object
    glBindBuffer(GL_ARRAY_BUFFER, m_vboID);

    // Tell OpenGL that we want to use the first
    // attribute array. we only need one array right
    // now since we are only using position
    glEnableVertexAttribArray(0);

    // This is the position attribute pointer
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position));
    // This is the color attribute pointer
    glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (void*)offsetof(Vertex, color));


    // Draw the 6 vertices to the screen
    glDrawArrays(GL_TRIANGLES, 0, 6);

    // Disable the vertex attrib array, This is not optional
    glDisableVertexAttribArray(0);

    // Unbind the VBO
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}
复制代码

 

posted @   unicornsir  阅读(393)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示